]> Pileus Git - ~andy/gtk/blob - docs/gtk_tut.sgml
- Complete the ProgressBar API - Fix the CList example code
[~andy/gtk] / docs / 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 21st, 1999
15 <abstract>
16 This is a tutorial on how to use GTK (the GIMP Toolkit) through its C
17 interface.
18 </abstract>
19
20 <!-- Table of contents -->
21 <!-- Older versions of this tutorial did not have a table of contents,
22      but the tutorial is now so large that having one is very useful. -->
23 <toc>
24  
25
26 <!-- ***************************************************************** -->
27 <sect>Introduction
28 <!-- ***************************************************************** -->
29 <p>
30 GTK (GIMP Toolkit) is a library for creating graphical user
31 interfaces. It is licensed using the LGPL license, so you can develop
32 open software, free software, or even commercial non-free software
33 using GTK without having to spend anything for licenses or royalties.
34
35 It's called the GIMP toolkit because it was originally written for
36 developing the General Image Manipulation Program (GIMP), but GTK has
37 now been used in a large number of software projects, including the
38 GNU Network Object Model Environment (GNOME) project. GTK is built on
39 top of GDK (GIMP Drawing Kit) which is basically a wrapper around the
40 low-level functions for accessing the underlying windowing functions
41 (Xlib in the case of X windows). The primary authors of GTK are:
42
43 <itemize>
44 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
45                            name="petm@xcf.berkeley.edu"></tt>
46 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
47                            name="spencer@xcf.berkeley.edu"></tt>
48 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
49                            name="jmacd@xcf.berkeley.edu"></tt>
50 </itemize>
51
52 GTK is essentially an object oriented application programmers
53 interface (API). Although written completely in C, it is implemented
54 using the idea of classes and callback functions (pointers to
55 functions).
56
57 There is also a third component called glib which contains a few
58 replacements for some standard calls, as well as some additional
59 functions for handling linked lists etc. The replacement functions are
60 used to increase GTK's portability, as some of the functions
61 implemented here are not available or are nonstandard on other unixes
62 such as g_strerror(). Some also contain enhancements to the libc
63 versions, such as g_malloc that has enhanced debugging utilities.
64
65 This tutorial describes the C interface to GTK. There are GTK
66 bindings for many other languages including C++, Guile, Perl, Python,
67 TOM, Ada95, Objective C, Free Pascal, and Eiffel. If you intend to
68 use another language's bindings to GTK, look at that binding's
69 documentation first. In some cases that documentation may describe
70 some important conventions (which you should know first) and then
71 refer you back to this tutorial. There are also some cross-platform
72 APIs (such as wxWindows and V) which use GTK as one of their target
73 platforms; again, consult their documentation first.
74
75 If you're developing your GTK application in C++, a few extra notes
76 are in order. There's a C++ binding to GTK called GTK--, which
77 provides a more C++-like interface to GTK; you should probably look
78 into this instead. If you don't like that approach for whatever
79 reason, there are two alternatives for using GTK. First, you can use
80 only the C subset of C++ when interfacing with GTK and then use the C
81 interface as described in this tutorial. Second, you can use GTK and
82 C++ together by declaring all callbacks as static functions in C++
83 classes, and again calling GTK using its C interface. If you choose
84 this last approach, you can include as the callback's data value a
85 pointer to the object to be manipulated (the so-called "this" value).
86 Selecting between these options is simply a matter of preference,
87 since in all three approaches you get C++ and GTK. None of these
88 approaches requires the use of a specialized preprocessor, so no
89 matter what you choose you can use standard C++ with GTK.
90
91 This tutorial is an attempt to document as much as possible of GTK,
92 but it is by no means complete. This tutorial assumes a good
93 understanding of C, and how to create C programs. It would be a great
94 benefit for the reader to have previous X programming experience, but
95 it shouldn't be necessary. If you are learning GTK as your first
96 widget set, please comment on how you found this tutorial, and what
97 you had trouble with. Note that there is also a C++ API for GTK
98 (GTK--) in the works, so if you prefer to use C++, you should look
99 into this instead. There are also Objective C, ADA, Guile and other
100 language bindings available, but I don't follow these.
101
102 This document is a 'work in progress'. Please look for updates on
103 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
104 name="http://www.gtk.org/">.
105
106 I would very much like to hear of any problems you have learning GTK
107 from this document, and would appreciate input as to how it may be
108 improved. Please see the section on <ref id="sec_Contributing"
109 name="Contributing"> for further information.
110
111 <!-- ***************************************************************** -->
112 <sect>Getting Started
113 <!-- ***************************************************************** -->
114
115 <p>
116 The first thing to do of course, is download the GTK source and
117 install it. You can always get the latest version from ftp.gtk.org in
118 /pub/gtk. You can also view other sources of GTK information on
119 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
120 name="http://www.gtk.org/">. GTK uses GNU autoconf for configuration.
121 Once untar'd, type ./configure --help to see a list of options.
122
123 Th GTK source distribution also contains the complete source to all of
124 the examples used in this tutorial, along with Makefiles to aid
125 compilation.
126
127 To begin our introduction to GTK, we'll start with the simplest
128 program possible. This program will create a 200x200 pixel window and
129 has no way of exiting except to be killed using the shell.
130
131 <tscreen><verb>
132 /* example-start base base.c */
133
134 #include <gtk/gtk.h>
135
136 int main( int   argc,
137           char *argv[] )
138 {
139     GtkWidget *window;
140     
141     gtk_init (&amp;argc, &amp;argv);
142     
143     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
144     gtk_widget_show  (window);
145     
146     gtk_main ();
147     
148     return(0);
149 }
150 /* example-end */
151 </verb></tscreen>
152
153 You can compile the above program with gcc using:
154 <tscreen><verb>
155 gcc base.c -o base `gtk-config --cflags --libs`
156 </verb></tscreen>
157
158 The meaning of the unusual compilation options is explained below.
159
160 All programs will of course include gtk/gtk.h which declares the
161 variables, functions, structures etc. that will be used in your GTK
162 application.
163
164 The next line:
165
166 <tscreen><verb>
167 gtk_init (&amp;argc, &amp;argv);
168 </verb></tscreen>
169
170 calls the function gtk_init(gint *argc, gchar ***argv) which will be
171 called in all GTK applications. This sets up a few things for us such
172 as the default visual and color map and then proceeds to call
173 gdk_init(gint *argc, gchar ***argv). This function initializes the
174 library for use, sets up default signal handlers, and checks the
175 arguments passed to your application on the command line, looking for
176 one of the following:
177
178 <itemize>
179 <item> <tt/--gtk-module/
180 <item> <tt/--g-fatal-warnings/
181 <item> <tt/--gtk-debug/
182 <item> <tt/--gtk-no-debug/
183 <item> <tt/--gdk-debug/
184 <item> <tt/--gdk-no-debug/
185 <item> <tt/--display/
186 <item> <tt/--sync/
187 <item> <tt/--no-xshm/
188 <item> <tt/--name/
189 <item> <tt/--class/
190 </itemize>
191
192 It removes these from the argument list, leaving anything it does not
193 recognize for your application to parse or ignore. This creates a set
194 of standard arguments accepted by all GTK applications.
195
196 The next two lines of code create and display a window.
197
198 <tscreen><verb>
199   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
200   gtk_widget_show (window);
201 </verb></tscreen>
202
203 The GTK_WINDOW_TOPLEVEL argument specifies that we want the window to
204 undergo window manager decoration and placement. Rather than create a
205 window of 0x0 size, a window without children is set to 200x200 by
206 default so you can still manipulate it.
207
208 The gtk_widget_show() function lets GTK know that we are done setting
209 the attributes of this widget, and that it can display it.
210
211 The last line enters the GTK main processing loop.
212
213 <tscreen><verb>
214   gtk_main ();
215 </verb></tscreen>
216
217 gtk_main() is another call you will see in every GTK application.
218 When control reaches this point, GTK will sleep waiting for X events
219 (such as button or key presses), timeouts, or file IO notifications to
220 occur. In our simple example however, events are ignored.
221
222 <!-- ----------------------------------------------------------------- -->
223 <sect1>Hello World in GTK
224 <p>
225 Now for a program with a widget (a button).  It's the classic
226 hello world a la GTK.
227
228 <tscreen><verb>
229 /* example-start helloworld helloworld.c */
230
231 #include <gtk/gtk.h>
232
233 /* This is a callback function. The data arguments are ignored
234  * in this example. More on callbacks below. */
235 void hello( GtkWidget *widget,
236             gpointer   data )
237 {
238     g_print ("Hello World\n");
239 }
240
241 gint delete_event( GtkWidget *widget,
242                    GdkEvent  *event,
243                    gpointer   data )
244 {
245     /* If you return FALSE in the "delete_event" signal handler,
246      * GTK will emit the "destroy" signal. Returning TRUE means
247      * you don't want the window to be destroyed.
248      * This is useful for popping up 'are you sure you want to quit?'
249      * type dialogs. */
250
251     g_print ("delete event occurred\n");
252
253     /* Change TRUE to FALSE and the main window will be destroyed with
254      * a "delete_event". */
255
256     return(TRUE);
257 }
258
259 /* Another callback */
260 void destroy( GtkWidget *widget,
261               gpointer   data )
262 {
263     gtk_main_quit();
264 }
265
266 int main( int   argc,
267           char *argv[] )
268 {
269     /* GtkWidget is the storage type for widgets */
270     GtkWidget *window;
271     GtkWidget *button;
272     
273     /* This is called in all GTK applications. Arguments are parsed
274      * from the command line and are returned to the application. */
275     gtk_init(&amp;argc, &amp;argv);
276     
277     /* create a new window */
278     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
279     
280     /* When the window is given the "delete_event" signal (this is given
281      * by the window manager, usually by the 'close' option, or on the
282      * titlebar), we ask it to call the delete_event () function
283      * as defined above. The data passed to the callback
284      * function is NULL and is ignored in the callback function. */
285     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
286                         GTK_SIGNAL_FUNC (delete_event), NULL);
287     
288     /* Here we connect the "destroy" event to a signal handler.  
289      * This event occurs when we call gtk_widget_destroy() on the window,
290      * or if we return 'FALSE' in the "delete_event" callback. */
291     gtk_signal_connect (GTK_OBJECT (window), "destroy",
292                         GTK_SIGNAL_FUNC (destroy), NULL);
293     
294     /* Sets the border width of the window. */
295     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
296     
297     /* Creates a new button with the label "Hello World". */
298     button = gtk_button_new_with_label ("Hello World");
299     
300     /* When the button receives the "clicked" signal, it will call the
301      * function hello() passing it NULL as its argument.  The hello()
302      * function is defined above. */
303     gtk_signal_connect (GTK_OBJECT (button), "clicked",
304                         GTK_SIGNAL_FUNC (hello), NULL);
305     
306     /* This will cause the window to be destroyed by calling
307      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
308      * signal could come from here, or the window manager. */
309     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
310                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
311                                GTK_OBJECT (window));
312     
313     /* This packs the button into the window (a gtk container). */
314     gtk_container_add (GTK_CONTAINER (window), button);
315     
316     /* The final step is to display this newly created widget. */
317     gtk_widget_show (button);
318     
319     /* and the window */
320     gtk_widget_show (window);
321     
322     /* All GTK applications must have a gtk_main(). Control ends here
323      * and waits for an event to occur (like a key press or
324      * mouse event). */
325     gtk_main ();
326     
327     return(0);
328 }
329 /* example-end */
330 </verb></tscreen>
331
332 <!-- ----------------------------------------------------------------- -->
333 <sect1>Compiling Hello World
334 <p>
335 To compile use:
336
337 <tscreen><verb>
338 gcc -Wall -g helloworld.c -o helloworld `gtk-config --cflags` \
339     `gtk-config --libs`
340 </verb></tscreen>
341
342 This uses the program <tt>gtk-config</>, which comes with gtk. This
343 program 'knows' what compiler switches are needed to compile programs
344 that use gtk. <tt>gtk-config --cflags</> will output a list of include
345 directories for the compiler to look in, and <tt>gtk-config --libs</>
346 will output the list of libraries for the compiler to link with and
347 the directories to find them in. In the aboce example they could have
348 been combined into a single instance, such as
349 `gtk-config --cflags --libs`.
350
351 Note that the type of single quote used in the compile command above
352 is significant.
353
354 The libraries that are usually linked in are:
355 <itemize>
356 <item>The GTK library (-lgtk), the widget library, based on top of GDK.
357 <item>The GDK library (-lgdk), the Xlib wrapper.
358 <item>The gmodule library (-lgmodule), which is used to load run time
359 extensions.
360 <item>The glib library (-lglib), containing miscellaneous functions, only
361 g_print() is used in this particular example. GTK is built on top
362 of glib so you will always require this library. See the section on 
363 <ref id="sec_glib" name="glib"> for details.
364 <item>The Xlib library (-lX11) which is used by GDK.
365 <item>The Xext library (-lXext). This contains code for shared memory
366 pixmaps and other X extensions.
367 <item>The math library (-lm). This is used by GTK for various purposes.
368 </itemize>
369
370 <!-- ----------------------------------------------------------------- -->
371 <sect1>Theory of Signals and Callbacks
372 <p>
373 Before we look in detail at <em>helloworld</em>, we'll discuss signals
374 and callbacks. GTK is an event driven toolkit, which means it will
375 sleep in gtk_main until an event occurs and control is passed to the
376 appropriate function.
377
378 This passing of control is done using the idea of "signals". When an
379 event occurs, such as the press of a mouse button, the appropriate
380 signal will be "emitted" by the widget that was pressed.  This is how
381 GTK does most of its useful work. There are a set of signals that all
382 widgets inherit, such as "destroy", and there are signals that are
383 widget specific, such as "toggled" on a toggle button.
384
385 To make a button perform an action, we set up a signal handler to
386 catch these signals and call the appropriate function. This is done by
387 using a function such as:
388
389 <tscreen><verb>
390 gint gtk_signal_connect( GtkObject     *object,
391                          gchar         *name,
392                          GtkSignalFunc  func,
393                          gpointer       func_data );
394 </verb></tscreen>
395
396 Where the first argument is the widget which will be emitting the
397 signal, and the second, the name of the signal you wish to catch. The
398 third is the function you wish to be called when it is caught, and the
399 fourth, the data you wish to have passed to this function.
400
401 The function specified in the third argument is called a "callback
402 function", and should generally be of the form:
403
404 <tscreen><verb>
405 void callback_func( GtkWidget *widget,
406                     gpointer   callback_data );
407 </verb></tscreen>
408
409 Where the first argument will be a pointer to the widget that emitted
410 the signal, and the second, a pointer to the data given as the last
411 argument to the gtk_signal_connect() function as shown above.
412
413 Note that the above form for a signal callback function declaration is
414 only a general guide, as some widget specific signals generate
415 different calling parameters. For example, the GtkCList "select_row"
416 signal provides both row and column parameters.
417
418 Another call used in the <em>helloworld</em> example, is:
419
420 <tscreen><verb>
421 gint gtk_signal_connect_object( GtkObject     *object,
422                                 gchar         *name,
423                                 GtkSignalFunc  func,
424                                 GtkObject     *slot_object );
425 </verb></tscreen>
426
427 gtk_signal_connect_object() is the same as gtk_signal_connect() except
428 that the callback function only uses one argument, a pointer to a GTK
429 object. So when using this function to connect signals, the callback
430 should be of the form:
431
432 <tscreen><verb>
433 void callback_func( GtkObject *object );
434 </verb></tscreen>
435
436 Where the object is usually a widget. We usually don't setup callbacks
437 for gtk_signal_connect_object however. They are usually used to call a
438 GTK function that accepts a single widget or object as an argument, as
439 is the case in our <em>helloworld</em> example.
440
441 The purpose of having two functions to connect signals is simply to
442 allow the callbacks to have a different number of arguments. Many
443 functions in the GTK library accept only a single GtkWidget pointer as
444 an argument, so you want to use the gtk_signal_connect_object() for
445 these, whereas for your functions, you may need to have additional
446 data supplied to the callbacks.
447
448 <!-- ----------------------------------------------------------------- -->
449 <sect1>Events
450 <p>
451 In addition to the signal mechanism described above, there are a set
452 of <em>events</em> that reflect the X event mechanism. Callbacks may
453 also be attached to these events. These events are:
454
455 <itemize>
456 <item> event
457 <item> button_press_event
458 <item> button_release_event
459 <item> motion_notify_event
460 <item> delete_event
461 <item> destroy_event
462 <item> expose_event
463 <item> key_press_event
464 <item> key_release_event
465 <item> enter_notify_event
466 <item> leave_notify_event
467 <item> configure_event
468 <item> focus_in_event
469 <item> focus_out_event
470 <item> map_event
471 <item> unmap_event
472 <item> property_notify_event
473 <item> selection_clear_event
474 <item> selection_request_event
475 <item> selection_notify_event
476 <item> proximity_in_event
477 <item> proximity_out_event
478 <item> drag_begin_event
479 <item> drag_request_event
480 <item> drag_end_event
481 <item> drop_enter_event
482 <item> drop_leave_event
483 <item> drop_data_available_event
484 <item> other_event
485 </itemize>
486
487 In order to connect a callback function to one of these events, you
488 use the function gtk_signal_connect, as described above, using one of
489 the above event names as the <tt/name/ parameter. The callback
490 function for events has a slightly different form than that for
491 signals:
492
493 <tscreen><verb>
494 void callback_func( GtkWidget *widget,
495                     GdkEvent  *event,
496                     gpointer   callback_data );
497 </verb></tscreen>
498
499 GdkEvent is a C <tt/union/ structure whose type will depend upon which
500 of the above events has occurred. In order for us to tell which event
501 has been issued each of the possible alternatives has a <tt/type/
502 parameter which reflects the event being issued. The other components
503 of the event structure will depend upon the type of the
504 event. Possible values for the type are:
505
506 <tscreen><verb>
507   GDK_NOTHING
508   GDK_DELETE
509   GDK_DESTROY
510   GDK_EXPOSE
511   GDK_MOTION_NOTIFY
512   GDK_BUTTON_PRESS
513   GDK_2BUTTON_PRESS
514   GDK_3BUTTON_PRESS
515   GDK_BUTTON_RELEASE
516   GDK_KEY_PRESS
517   GDK_KEY_RELEASE
518   GDK_ENTER_NOTIFY
519   GDK_LEAVE_NOTIFY
520   GDK_FOCUS_CHANGE
521   GDK_CONFIGURE
522   GDK_MAP
523   GDK_UNMAP
524   GDK_PROPERTY_NOTIFY
525   GDK_SELECTION_CLEAR
526   GDK_SELECTION_REQUEST
527   GDK_SELECTION_NOTIFY
528   GDK_PROXIMITY_IN
529   GDK_PROXIMITY_OUT
530   GDK_DRAG_BEGIN
531   GDK_DRAG_REQUEST
532   GDK_DROP_ENTER
533   GDK_DROP_LEAVE
534   GDK_DROP_DATA_AVAIL
535   GDK_CLIENT_EVENT
536   GDK_VISIBILITY_NOTIFY
537   GDK_NO_EXPOSE
538   GDK_OTHER_EVENT       /* Deprecated, use filters instead */
539 </verb></tscreen>
540
541 So, to connect a callback function to one of these events we would use
542 something like:
543
544 <tscreen><verb>
545 gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
546                     GTK_SIGNAL_FUNC(button_press_callback), 
547                         NULL);
548 </verb></tscreen>
549
550 This assumes that <tt/button/ is a GtkButton widget. Now, when the
551 mouse is over the button and a mouse button is pressed, the function
552 <tt/button_press_callback/ will be called. This function may be
553 declared as:
554
555 <tscreen><verb>
556 static gint button_press_event (GtkWidget      *widget, 
557                                 GdkEventButton *event,
558                                 gpointer        data);
559 </verb></tscreen>
560
561 Note that we can declare the second argument as type
562 <tt/GdkEventButton/ as we know what type of event will occur for this
563 function to be called.
564
565 The value returned from this function indicates whether the event
566 should be propagated further by the GTK event handling
567 mechanism. Returning TRUE indicates that the event has been handled,
568 and that it should not propagate further. Returning FALSE continues
569 the normal event handling.  See the section on
570 <ref id="sec_Adv_Events_and_Signals"
571 name="Advanced Event and Signal Handling"> for more details on this
572 propagation process.
573
574 For details on the GdkEvent data types, see the appendix entitled
575 <ref id="sec_GDK_Event_Types" name="GDK Event Types">.
576
577 <!-- ----------------------------------------------------------------- -->
578 <sect1>Stepping Through Hello World
579 <p>
580 Now that we know the theory behind this, lets clarify by walking through 
581 the example <em>helloworld</em> program.
582
583 Here is the callback function that will be called when the button is
584 "clicked". We ignore both the widget and the data in this example, but
585 it is not hard to do things with them. The next example will use the
586 data argument to tell us which button was pressed.
587
588 <tscreen><verb>
589 void hello( GtkWidget *widget,
590             gpointer   data )
591 {
592     g_print ("Hello World\n");
593 }
594 </verb></tscreen>
595
596 The next callback is a bit special. The "delete_event" occurs when the
597 window manager sends this event to the application. We have a choice
598 here as to what to do about these events. We can ignore them, make
599 some sort of response, or simply quit the application.
600
601 The value you return in this callback lets GTK know what action to
602 take.  By returning TRUE, we let it know that we don't want to have
603 the "destroy" signal emitted, keeping our application running. By
604 returning FALSE, we ask that "destroy" is emitted, which in turn will
605 call our "destroy" signal handler.
606
607 <tscreen><verb>
608 gint delete_event( GtkWidget *widget,
609                    GdkEvent  *event,
610                    gpointer   data )
611 {
612     g_print ("delete event occurred\n");
613
614     return (TRUE); 
615 }
616 </verb></tscreen>
617
618 Here is another callback function which causes the program to quit by
619 calling gtk_main_quit(). This function tells GTK that it is to exit
620 from gtk_main when control is returned to it.
621
622 <tscreen><verb>
623 void destroy( GtkWidget *widget,
624               gpointer   data )
625 {
626     gtk_main_quit ();
627 }
628 </verb></tscreen>
629
630 I assume you know about the main() function... yes, as with other
631 applications, all GTK applications will also have one of these.
632
633 <tscreen><verb>
634 int main( int   argc,
635           char *argv[] )
636 {
637 </verb></tscreen>
638
639 This next part, declares a pointer to a structure of type
640 GtkWidget. These are used below to create a window and a button.
641
642 <tscreen><verb>
643     GtkWidget *window;
644     GtkWidget *button;
645 </verb></tscreen>
646
647 Here is our gtk_init again. As before, this initializes the toolkit,
648 and parses the arguments found on the command line. Any argument it
649 recognizes from the command line, it removes from the list, and
650 modifies argc and argv to make it look like they never existed,
651 allowing your application to parse the remaining arguments.
652
653 <tscreen><verb>
654     gtk_init (&amp;argc, &amp;argv);
655 </verb></tscreen>
656
657 Create a new window. This is fairly straight forward. Memory is
658 allocated for the GtkWidget *window structure so it now points to a
659 valid structure. It sets up a new window, but it is not displayed
660 until we call gtk_widget_show(window) near the end of our program.
661
662 <tscreen><verb>
663     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
664 </verb></tscreen>
665
666 Here is an example of connecting a signal handler to an object, in
667 this case, the window. Here, the "destroy" signal is caught. This is
668 emitted when we use the window manager to kill the window (and we
669 return FALSE in the "delete_event" handler), or when we use the
670 gtk_widget_destroy() call passing in the window widget as the object
671 to destroy. By setting this up, we handle both cases with a single
672 call. Here, it just calls the destroy() function defined above with a
673 NULL argument, which quits GTK for us.
674
675 The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform type
676 casting and checking for us, as well as aid the readability of the
677 code.
678
679 <tscreen><verb>
680     gtk_signal_connect (GTK_OBJECT (window), "destroy",
681                         GTK_SIGNAL_FUNC (destroy), NULL);
682 </verb></tscreen>
683
684 This next function is used to set an attribute of a container object.
685 This just sets the window so it has a blank area along the inside of
686 it 10 pixels wide where no widgets will go. There are other similar
687 functions which we will look at in the section on
688 <ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
689
690 And again, GTK_CONTAINER is a macro to perform type casting.
691
692 <tscreen><verb>
693     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
694 </verb></tscreen>
695
696 This call creates a new button. It allocates space for a new GtkWidget
697 structure in memory, initializes it, and makes the button pointer
698 point to it. It will have the label "Hello World" on it when
699 displayed.
700
701 <tscreen><verb>
702     button = gtk_button_new_with_label ("Hello World");
703 </verb></tscreen>
704
705 Here, we take this button, and make it do something useful. We attach
706 a signal handler to it so when it emits the "clicked" signal, our
707 hello() function is called. The data is ignored, so we simply pass in
708 NULL to the hello() callback function. Obviously, the "clicked" signal
709 is emitted when we click the button with our mouse pointer.
710
711 <tscreen><verb>
712     gtk_signal_connect (GTK_OBJECT (button), "clicked",
713                         GTK_SIGNAL_FUNC (hello), NULL);
714 </verb></tscreen>
715
716 We are also going to use this button to exit our program. This will
717 illustrate how the "destroy" signal may come from either the window
718 manager, or our program. When the button is "clicked", same as above,
719 it calls the first hello() callback function, and then this one in the
720 order they are set up. You may have as many callback functions as you
721 need, and all will be executed in the order you connected
722 them. Because the gtk_widget_destroy() function accepts only a
723 GtkWidget *widget as an argument, we use the
724 gtk_signal_connect_object() function here instead of straight
725 gtk_signal_connect().
726
727 <tscreen><verb>
728     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
729                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
730                                GTK_OBJECT (window));
731 </verb></tscreen>
732
733 This is a packing call, which will be explained in depth later on. But
734 it is fairly easy to understand. It simply tells GTK that the button
735 is to be placed in the window where it will be displayed. Note that a
736 GTK container can only contain one widget. There are other widgets,
737 that are described later, which are designed to layout multiple
738 widgets in various ways.
739  
740 <tscreen><verb>
741     gtk_container_add (GTK_CONTAINER (window), button);
742 </verb></tscreen>
743
744 Now we have everything set up the way we want it to be. With all the
745 signal handlers in place, and the button placed in the window where it
746 should be, we ask GTK to "show" the widgets on the screen. The window
747 widget is shown last so the whole window will pop up at once rather
748 than seeing the window pop up, and then the button form inside of
749 it. Although with such a simple example, you'd never notice.
750
751 <tscreen><verb>
752     gtk_widget_show (button);
753
754     gtk_widget_show (window);
755 </verb></tscreen>
756
757 And of course, we call gtk_main() which waits for events to come from
758 the X server and will call on the widgets to emit signals when these
759 events come.
760
761 <tscreen><verb>
762     gtk_main ();
763 </verb></tscreen>
764
765 And the final return. Control returns here after gtk_quit() is called.
766
767 <tscreen><verb>
768     return 0;
769 </verb></tscreen>
770
771 Now, when we click the mouse button on a GTK button, the widget emits
772 a "clicked" signal. In order for us to use this information, our
773 program sets up a signal handler to catch that signal, which
774 dispatches the function of our choice. In our example, when the button
775 we created is "clicked", the hello() function is called with a NULL
776 argument, and then the next handler for this signal is called. This
777 calls the gtk_widget_destroy() function, passing it the window widget
778 as its argument, destroying the window widget. This causes the window
779 to emit the "destroy" signal, which is caught, and calls our destroy()
780 callback function, which simply exits GTK.
781
782 Another course of events, is to use the window manager to kill the
783 window. This will cause the "delete_event" to be emitted. This will
784 call our "delete_event" handler. If we return TRUE here, the window
785 will be left as is and nothing will happen. Returning FALSE will cause
786 GTK to emit the "destroy" signal which of course, calls the "destroy"
787 callback, exiting GTK.
788
789 Note that these signals are not the same as the Unix system signals,
790 and are not implemented using them, although the terminology is almost
791 identical.
792
793 <!-- ***************************************************************** -->
794 <sect>Moving On
795 <!-- ***************************************************************** -->
796
797 <!-- ----------------------------------------------------------------- -->
798 <sect1>Data Types
799 <p>
800 There are a few things you probably noticed in the previous examples
801 that need explaining. The gint, gchar etc. that you see are typedefs
802 to int and char respectively. This is done to get around that nasty
803 dependency on the size of simple data 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 straight forward and intuitive. They are
808 all defined in glib/glib.h (which gets included from gtk.h).
809
810 You'll also notice the ability to use GtkWidget when the function
811 calls for a GtkObject. GTK is an object oriented design, and a widget
812 is an object.
813
814 <!-- ----------------------------------------------------------------- -->
815 <sect1>More on Signal Handlers
816 <p>
817 Lets take another look at the gtk_signal_connect declaration.
818
819 <tscreen><verb>
820 gint gtk_signal_connect( GtkObject *object,
821                          gchar *name,
822                          GtkSignalFunc func,
823                          gpointer func_data );
824 </verb></tscreen>
825
826 Notice the gint return value? This is a tag that identifies your
827 callback function. As stated above, you may have as many callbacks per
828 signal and per object as you need, and each will be executed in turn,
829 in the order they were attached.
830
831 This tag allows you to remove this callback from the list by using:
832
833 <tscreen><verb>
834 void gtk_signal_disconnect( GtkObject *object,
835                             gint id );
836 </verb></tscreen>
837
838 So, by passing in the widget you wish to remove the handler from, and
839 the tag returned by one of the signal_connect functions, you can
840 disconnect a signal handler.
841
842 Another function to remove all the signal handers from an object is:
843
844 <tscreen><verb>
845 void gtk_signal_handlers_destroy( GtkObject *object );
846 </verb></tscreen>
847
848 This call is fairly self explanatory. It simply removes all the
849 current signal handlers from the object passed in as the first
850 argument.
851
852 <!-- ----------------------------------------------------------------- -->
853 <sect1>An Upgraded Hello World
854 <p>
855 Let's take a look at a slightly improved <em>helloworld</em> with
856 better examples of callbacks. This will also introduce us to our next
857 topic, packing widgets.
858
859 <tscreen><verb>
860 /* example-start helloworld2 helloworld2.c */
861
862 #include <gtk/gtk.h>
863
864 /* Our new improved callback.  The data passed to this function
865  * is printed to stdout. */
866 void callback( GtkWidget *widget,
867                gpointer   data )
868 {
869     g_print ("Hello again - %s was pressed\n", (char *) data);
870 }
871
872 /* another callback */
873 void delete_event( GtkWidget *widget,
874                    GdkEvent  *event,
875                    gpointer   data )
876 {
877     gtk_main_quit ();
878 }
879
880 int main( int   argc,
881           char *argv[] )
882 {
883     /* GtkWidget is the storage type for widgets */
884     GtkWidget *window;
885     GtkWidget *button;
886     GtkWidget *box1;
887
888     /* This is called in all GTK applications. Arguments are parsed
889      * from the command line and are returned to the application. */
890     gtk_init (&amp;argc, &amp;argv);
891
892     /* Create a new window */
893     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
894
895     /* This is a new call, this just sets the title of our
896      * new window to "Hello Buttons!" */
897     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
898
899     /* Here we just set a handler for delete_event that immediately
900      * exits GTK. */
901     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
902                         GTK_SIGNAL_FUNC (delete_event), NULL);
903
904     /* Sets the border width of the window. */
905     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
906
907     /* We create a box to pack widgets into.  This is described in detail
908      * in the "packing" section. The box is not really visible, it
909      * is just used as a tool to arrange widgets. */
910     box1 = gtk_hbox_new(FALSE, 0);
911
912     /* Put the box into the main window. */
913     gtk_container_add (GTK_CONTAINER (window), box1);
914
915     /* Creates a new button with the label "Button 1". */
916     button = gtk_button_new_with_label ("Button 1");
917
918     /* Now when the button is clicked, we call the "callback" function
919      * with a pointer to "button 1" as its argument */
920     gtk_signal_connect (GTK_OBJECT (button), "clicked",
921                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
922
923     /* Instead of gtk_container_add, we pack this button into the invisible
924      * box, which has been packed into the window. */
925     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
926
927     /* Always remember this step, this tells GTK that our preparation for
928      * this button is complete, and it can now be displayed. */
929     gtk_widget_show(button);
930
931     /* Do these same steps again to create a second button */
932     button = gtk_button_new_with_label ("Button 2");
933
934     /* Call the same callback function with a different argument,
935      * passing a pointer to "button 2" instead. */
936     gtk_signal_connect (GTK_OBJECT (button), "clicked",
937                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
938
939     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
940
941     /* The order in which we show the buttons is not really important, but I
942      * recommend showing the window last, so it all pops up at once. */
943     gtk_widget_show(button);
944
945     gtk_widget_show(box1);
946
947     gtk_widget_show (window);
948
949     /* Rest in gtk_main and wait for the fun to begin! */
950     gtk_main ();
951
952     return(0);
953 }
954 /* example-end */
955 </verb></tscreen>
956
957 Compile this program using the same linking arguments as our first
958 example.  You'll notice this time there is no easy way to exit the
959 program, you have to use your window manager or command line to kill
960 it. A good exercise for the reader would be to insert a third "Quit"
961 button that will exit the program. You may also wish to play with the
962 options to gtk_box_pack_start() while reading the next section.  Try
963 resizing the window, and observe the behavior.
964
965 Just as a side note, there is another useful define for
966 gtk_window_new() - GTK_WINDOW_DIALOG. This interacts with the window
967 manager a little differently and should be used for transient windows.
968
969 <!-- ***************************************************************** -->
970 <sect>Packing Widgets
971 <!-- ***************************************************************** -->
972 <p>
973 When creating an application, you'll want to put more than one widget
974 inside a window. Our first <em>helloworld</em> example only used one
975 widget so we could simply use a gtk_container_add call to "pack" the
976 widget into the window. But when you want to put more than one widget
977 into a window, how do you control where that widget is positioned?
978 This is where packing comes in.
979
980 <!-- ----------------------------------------------------------------- -->
981 <sect1>Theory of Packing Boxes
982 <p>
983 Most packing is done by creating boxes as in the example above. These
984 are invisible widget containers that we can pack our widgets into
985 which come in two forms, a horizontal box, and a vertical box. When
986 packing widgets into a horizontal box, the objects are inserted
987 horizontally from left to right or right to left depending on the call
988 used. In a vertical box, widgets are packed from top to bottom or vice
989 versa. You may use any combination of boxes inside or beside other
990 boxes to create the desired effect.
991
992 To create a new horizontal box, we use a call to gtk_hbox_new(), and
993 for vertical boxes, gtk_vbox_new().The gtk_box_pack_start() and
994 gtk_box_pack_end() functions are used to place objects inside of these
995 containers. The gtk_box_pack_start() function will start at the top
996 and work its way down in a vbox, and pack left to right in an hbox.
997 gtk_box_pack_end() will do the opposite, packing from bottom to top in
998 a vbox, and right to left in an hbox. Using these functions allow us
999 to right justify or left justify our widgets and may be mixed in any
1000 way to achieve the desired effect. We will use gtk_box_pack_start() in
1001 most of our examples. An object may be another container or a
1002 widget. In fact, many widgets are actually containers themselves,
1003 including the button, but we usually only use a label inside a button.
1004
1005 By using these calls, GTK knows where you want to place your widgets
1006 so it can do automatic resizing and other nifty things. There's also a
1007 number of options as to how your widgets should be packed. As you can
1008 imagine, this method gives us a quite a bit of flexibility when
1009 placing and creating widgets.
1010
1011 <!-- ----------------------------------------------------------------- -->
1012 <sect1>Details of Boxes
1013 <p>
1014 Because of this flexibility, packing boxes in GTK can be confusing at
1015 first. There are a lot of options, and it's not immediately obvious how
1016 they all fit together. In the end however, there are basically five
1017 different styles.
1018
1019 <? <CENTER> >
1020 <?
1021 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
1022 HEIGHT="235" ALT="Box Packing Example Image">
1023 >
1024 <? </CENTER> >
1025
1026 Each line contains one horizontal box (hbox) with several buttons. The
1027 call to gtk_box_pack is shorthand for the call to pack each of the
1028 buttons into the hbox. Each of the buttons is packed into the hbox the
1029 same way (i.e. same arguments to the gtk_box_pack_start() function).
1030
1031 This is the declaration of the gtk_box_pack_start function.
1032
1033 <tscreen><verb>
1034 void gtk_box_pack_start( GtkBox    *box,
1035                          GtkWidget *child,
1036                          gint       expand,
1037                          gint       fill,
1038                          gint       padding );
1039 </verb></tscreen>
1040
1041 The first argument is the box you are packing the object into, the
1042 second is the object. The objects will all be buttons for now, so
1043 we'll be packing buttons into boxes.
1044
1045 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1046 controls whether the widgets are laid out in the box to fill in all
1047 the extra space in the box so the box is expanded to fill the area
1048 alloted to it (TRUE).  Or the box is shrunk to just fit the widgets
1049 (FALSE). Setting expand to FALSE will allow you to do right and left
1050 justification of your widgets.  Otherwise, they will all expand to fit
1051 into the box, and the same effect could be achieved by using only one
1052 of gtk_box_pack_start or gtk_box_pack_end.
1053
1054 The fill argument to the gtk_box_pack functions control whether the
1055 extra space is allocated to the objects themselves (TRUE), or as extra
1056 padding in the box around these objects (FALSE). It only has an effect
1057 if the expand argument is also TRUE.
1058
1059 When creating a new box, the function looks like this:
1060
1061 <tscreen><verb>
1062 GtkWidget *gtk_hbox_new (gint homogeneous,
1063                          gint spacing);
1064 </verb></tscreen>
1065
1066 The homogeneous argument to gtk_hbox_new (and the same for
1067 gtk_vbox_new) controls whether each object in the box has the same
1068 size (i.e. the same width in an hbox, or the same height in a
1069 vbox). If it is set, the expand argument to the gtk_box_pack routines
1070 is always turned on.
1071
1072 What's the difference between spacing (set when the box is created)
1073 and padding (set when elements are packed)? Spacing is added between
1074 objects, and padding is added on either side of an object. The
1075 following figure should make it clearer:
1076
1077 <? <CENTER> >
1078 <?
1079 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1080 HEIGHT="213" VSPACE="15" HSPACE="10"
1081 ALT="Box Packing Example Image">
1082 >
1083 <? </CENTER> >
1084
1085 Here is the code used to create the above images. I've commented it
1086 fairly heavily so hopefully you won't have any problems following
1087 it. Compile it yourself and play with it.
1088
1089 <!-- ----------------------------------------------------------------- -->
1090 <sect1>Packing Demonstration Program
1091 <p>
1092 <tscreen><verb>
1093 /* example-start packbox packbox.c */
1094
1095 #include <stdio.h>
1096 #include "gtk/gtk.h"
1097
1098 void delete_event( GtkWidget *widget,
1099                    GdkEvent  *event,
1100                    gpointer   data )
1101 {
1102     gtk_main_quit ();
1103 }
1104
1105 /* Make a new hbox filled with button-labels. Arguments for the 
1106  * variables we're interested are passed in to this function. 
1107  * We do not show the box, but do show everything inside. */
1108 GtkWidget *make_box( gint homogeneous,
1109                      gint spacing,
1110                      gint expand,
1111                      gint fill,
1112                      gint padding ) 
1113 {
1114     GtkWidget *box;
1115     GtkWidget *button;
1116     char padstr[80];
1117     
1118     /* Create a new hbox with the appropriate homogeneous
1119      * and spacing settings */
1120     box = gtk_hbox_new (homogeneous, spacing);
1121     
1122     /* Create a series of buttons with the appropriate settings */
1123     button = gtk_button_new_with_label ("gtk_box_pack");
1124     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1125     gtk_widget_show (button);
1126     
1127     button = gtk_button_new_with_label ("(box,");
1128     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1129     gtk_widget_show (button);
1130     
1131     button = gtk_button_new_with_label ("button,");
1132     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1133     gtk_widget_show (button);
1134     
1135     /* Create a button with the label depending on the value of
1136      * expand. */
1137     if (expand == TRUE)
1138             button = gtk_button_new_with_label ("TRUE,");
1139     else
1140             button = gtk_button_new_with_label ("FALSE,");
1141     
1142     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1143     gtk_widget_show (button);
1144     
1145     /* This is the same as the button creation for "expand"
1146      * above, but uses the shorthand form. */
1147     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1148     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1149     gtk_widget_show (button);
1150     
1151     sprintf (padstr, "%d);", padding);
1152     
1153     button = gtk_button_new_with_label (padstr);
1154     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1155     gtk_widget_show (button);
1156     
1157     return box;
1158 }
1159
1160 int main( int   argc,
1161           char *argv[]) 
1162 {
1163     GtkWidget *window;
1164     GtkWidget *button;
1165     GtkWidget *box1;
1166     GtkWidget *box2;
1167     GtkWidget *separator;
1168     GtkWidget *label;
1169     GtkWidget *quitbox;
1170     int which;
1171     
1172     /* Our init, don't forget this! :) */
1173     gtk_init (&amp;argc, &amp;argv);
1174     
1175     if (argc != 2) {
1176         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1177         /* This just does cleanup in GTK and exits with an exit status of 1. */
1178         gtk_exit (1);
1179     }
1180     
1181     which = atoi (argv[1]);
1182
1183     /* Create our window */
1184     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1185
1186     /* You should always remember to connect the destroy signal to the
1187      * main window. This is very important for proper intuitive
1188      * behavior */
1189     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1190                         GTK_SIGNAL_FUNC (delete_event), NULL);
1191     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1192     
1193     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1194      * This allows us to stack the horizontal boxes filled with buttons one
1195      * on top of the other in this vbox. */
1196     box1 = gtk_vbox_new (FALSE, 0);
1197     
1198     /* which example to show. These correspond to the pictures above. */
1199     switch (which) {
1200     case 1:
1201         /* create a new label. */
1202         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1203         
1204         /* Align the label to the left side.  We'll discuss this function and 
1205          * others in the section on Widget Attributes. */
1206         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1207
1208         /* Pack the label into the vertical box (vbox box1).  Remember that 
1209          * widgets added to a vbox will be packed one on top of the other in
1210          * order. */
1211         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1212         
1213         /* Show the label */
1214         gtk_widget_show (label);
1215         
1216         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1217          * expand = FALSE, fill = FALSE, padding = 0 */
1218         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1219         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1220         gtk_widget_show (box2);
1221
1222         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1223          * expand = FALSE, fill = FALSE, padding = 0 */
1224         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1225         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1226         gtk_widget_show (box2);
1227         
1228         /* Args are: homogeneous, spacing, expand, fill, padding */
1229         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1230         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1231         gtk_widget_show (box2);
1232         
1233         /* Creates a separator, we'll learn more about these later, 
1234          * but they are quite simple. */
1235         separator = gtk_hseparator_new ();
1236         
1237         /* Cack the separator into the vbox. Remember each of these
1238          * widgets are being packed into a vbox, so they'll be stacked
1239          * vertically. */
1240         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1241         gtk_widget_show (separator);
1242         
1243         /* Create another new label, and show it. */
1244         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1245         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1246         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1247         gtk_widget_show (label);
1248         
1249         /* Args are: homogeneous, spacing, expand, fill, padding */
1250         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1251         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1252         gtk_widget_show (box2);
1253         
1254         /* Args are: homogeneous, spacing, expand, fill, padding */
1255         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1256         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1257         gtk_widget_show (box2);
1258         
1259         /* Another new separator. */
1260         separator = gtk_hseparator_new ();
1261         /* The last 3 arguments to gtk_box_pack_start are:
1262          * expand, fill, padding. */
1263         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1264         gtk_widget_show (separator);
1265         
1266         break;
1267
1268     case 2:
1269
1270         /* Create a new label, remember box1 is a vbox as created 
1271          * near the beginning of main() */
1272         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1273         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1274         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1275         gtk_widget_show (label);
1276         
1277         /* Args are: homogeneous, spacing, expand, fill, padding */
1278         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1279         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1280         gtk_widget_show (box2);
1281         
1282         /* Args are: homogeneous, spacing, expand, fill, padding */
1283         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1284         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1285         gtk_widget_show (box2);
1286         
1287         separator = gtk_hseparator_new ();
1288         /* The last 3 arguments to gtk_box_pack_start are:
1289          * expand, fill, padding. */
1290         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1291         gtk_widget_show (separator);
1292         
1293         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1294         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1295         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1296         gtk_widget_show (label);
1297         
1298         /* Args are: homogeneous, spacing, expand, fill, padding */
1299         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1300         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1301         gtk_widget_show (box2);
1302         
1303         /* Args are: homogeneous, spacing, expand, fill, padding */
1304         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1305         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1306         gtk_widget_show (box2);
1307         
1308         separator = gtk_hseparator_new ();
1309         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1310         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1311         gtk_widget_show (separator);
1312         break;
1313     
1314     case 3:
1315
1316         /* This demonstrates the ability to use gtk_box_pack_end() to
1317          * right justify widgets. First, we create a new box as before. */
1318         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1319
1320         /* Create the label that will be put at the end. */
1321         label = gtk_label_new ("end");
1322         /* Pack it using gtk_box_pack_end(), so it is put on the right
1323          * side of the hbox created in the make_box() call. */
1324         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1325         /* Show the label. */
1326         gtk_widget_show (label);
1327         
1328         /* Pack box2 into box1 (the vbox remember ? :) */
1329         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1330         gtk_widget_show (box2);
1331         
1332         /* A separator for the bottom. */
1333         separator = gtk_hseparator_new ();
1334         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1335          * high. This is so the hbox we created will also be 400 pixels wide,
1336          * and the "end" label will be separated from the other labels in the
1337          * hbox. Otherwise, all the widgets in the hbox would be packed as
1338          * close together as possible. */
1339         gtk_widget_set_usize (separator, 400, 5);
1340         /* pack the separator into the vbox (box1) created near the start 
1341          * of main() */
1342         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1343         gtk_widget_show (separator);    
1344     }
1345     
1346     /* Create another new hbox.. remember we can use as many as we need! */
1347     quitbox = gtk_hbox_new (FALSE, 0);
1348     
1349     /* Our quit button. */
1350     button = gtk_button_new_with_label ("Quit");
1351     
1352     /* Setup the signal to destroy the window. Remember that this will send
1353      * the "destroy" signal to the window which will be caught by our signal
1354      * handler as defined above. */
1355     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1356                                GTK_SIGNAL_FUNC (gtk_main_quit),
1357                                GTK_OBJECT (window));
1358     /* Pack the button into the quitbox.
1359      * The last 3 arguments to gtk_box_pack_start are:
1360      * expand, fill, padding. */
1361     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1362     /* pack the quitbox into the vbox (box1) */
1363     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1364     
1365     /* Pack the vbox (box1) which now contains all our widgets, into the
1366      * main window. */
1367     gtk_container_add (GTK_CONTAINER (window), box1);
1368     
1369     /* And show everything left */
1370     gtk_widget_show (button);
1371     gtk_widget_show (quitbox);
1372     
1373     gtk_widget_show (box1);
1374     /* Showing the window last so everything pops up at once. */
1375     gtk_widget_show (window);
1376     
1377     /* And of course, our main function. */
1378     gtk_main ();
1379
1380     /* Control returns here when gtk_main_quit() is called, but not when 
1381      * gtk_exit is used. */
1382     
1383     return(0);
1384 }
1385 /* example-end */
1386 </verb></tscreen>
1387
1388 <!-- ----------------------------------------------------------------- -->
1389 <sect1>Packing Using Tables
1390 <p>
1391 Let's take a look at another way of packing - Tables. These can be
1392 extremely useful in certain situations.
1393
1394 Using tables, we create a grid that we can place widgets in. The
1395 widgets may take up as many spaces as we specify.
1396
1397 The first thing to look at of course, is the gtk_table_new function:
1398
1399 <tscreen><verb>
1400 GtkWidget *gtk_table_new( gint rows,
1401                           gint columns,
1402                           gint homogeneous );
1403 </verb></tscreen>
1404
1405 The first argument is the number of rows to make in the table, while
1406 the second, obviously, is the number of columns.
1407
1408 The homogeneous argument has to do with how the table's boxes are
1409 sized. If homogeneous is TRUE, the table boxes are resized to the size
1410 of the largest widget in the table. If homogeneous is FALSE, the size
1411 of a table boxes is dictated by the tallest widget in its same row,
1412 and the widest widget in its column.
1413
1414 The rows and columns are laid out from 0 to n, where n was the number
1415 specified in the call to gtk_table_new. So, if you specify rows = 2
1416 and columns = 2, the layout would look something like this:
1417
1418 <tscreen><verb>
1419  0          1          2
1420 0+----------+----------+
1421  |          |          |
1422 1+----------+----------+
1423  |          |          |
1424 2+----------+----------+
1425 </verb></tscreen>
1426
1427 Note that the coordinate system starts in the upper left hand corner.
1428 To place a widget into a box, use the following function:
1429
1430 <tscreen><verb>
1431 void gtk_table_attach( GtkTable  *table,
1432                        GtkWidget *child,
1433                        gint       left_attach,
1434                        gint       right_attach,
1435                        gint       top_attach,
1436                        gint       bottom_attach,
1437                        gint       xoptions,
1438                        gint       yoptions,
1439                        gint       xpadding,
1440                        gint       ypadding );
1441 </verb></tscreen>                                      
1442
1443 Where the first argument ("table") is the table you've created and the
1444 second ("child") the widget you wish to place in the table.
1445
1446 The left and right attach arguments specify where to place the widget,
1447 and how many boxes to use. If you want a button in the lower right
1448 table entry of our 2x2 table, and want it to fill that entry ONLY,
1449 left_attach would be = 1, right_attach = 2, top_attach = 1,
1450 bottom_attach = 2.
1451
1452 Now, if you wanted a widget to take up the whole top row of our 2x2
1453 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1454 bottom_attach = 1.
1455
1456 The xoptions and yoptions are used to specify packing options and may
1457 be bitwise OR'ed together to allow multiple options.
1458
1459 These options are:
1460 <itemize>
1461 <item>GTK_FILL - If the table box is larger than the widget, and
1462 GTK_FILL is specified, the widget will expand to use all the room
1463 available.
1464
1465 <item>GTK_SHRINK - If the table widget was allocated less space then
1466 was requested (usually by the user resizing the window), then the
1467 widgets would normally just be pushed off the bottom of the window and
1468 disappear. If GTK_SHRINK is specified, the widgets will shrink with
1469 the table.
1470
1471 <item>GTK_EXPAND - This will cause the table to expand to use up any
1472 remaining space in the window.
1473 </itemize>
1474
1475 Padding is just like in boxes, creating a clear area around the widget
1476 specified in pixels.
1477
1478 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1479
1480 <tscreen><verb>
1481 void gtk_table_attach_defaults( GtkTable  *table,
1482                                 GtkWidget *widget,
1483                                 gint       left_attach,
1484                                 gint       right_attach,
1485                                 gint       top_attach,
1486                                 gint       bottom_attach );
1487 </verb></tscreen>
1488
1489 The X and Y options default to GTK_FILL | GTK_EXPAND, and X and Y
1490 padding are set to 0. The rest of the arguments are identical to the
1491 previous function.
1492
1493 We also have gtk_table_set_row_spacing() and
1494 gtk_table_set_col_spacing().  This places spacing between the rows at
1495 the specified row or column.
1496
1497 <tscreen><verb>
1498 void gtk_table_set_row_spacing( GtkTable *table,
1499                                 gint      row,
1500                                 gint      spacing );
1501 </verb></tscreen>
1502
1503 and
1504
1505 <tscreen><verb>
1506 void gtk_table_set_col_spacing ( GtkTable *table,
1507                                  gint      column,
1508                                  gint      spacing );
1509 </verb></tscreen>
1510
1511 Note that for columns, the space goes to the right of the column, and
1512 for rows, the space goes below the row.
1513
1514 You can also set a consistent spacing of all rows and/or columns with:
1515
1516 <tscreen><verb>
1517 void gtk_table_set_row_spacings( GtkTable *table,
1518                                  gint      spacing );
1519 </verb></tscreen>
1520
1521 And,
1522
1523 <tscreen><verb>
1524 void gtk_table_set_col_spacings( GtkTable *table,
1525                                  gint      spacing );
1526 </verb></tscreen>
1527
1528 Note that with these calls, the last row and last column do not get
1529 any spacing.
1530
1531 <!-- ----------------------------------------------------------------- -->
1532 <sect1>Table Packing Example
1533 <p>
1534 Here we make a window with three buttons in a 2x2 table.
1535 The first two buttons will be placed in the upper row.
1536 A third, quit button, is placed in the lower row, spanning both columns.
1537 Which means it should look something like this:
1538
1539 <? <CENTER> >
1540 <?
1541 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1542 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1543 >
1544 <? </CENTER> >
1545
1546 Here's the source code:
1547
1548 <tscreen><verb>
1549 /* example-start table table.c */
1550
1551 #include <gtk/gtk.h>
1552
1553 /* Our callback.
1554  * The data passed to this function is printed to stdout */
1555 void callback( GtkWidget *widget,
1556                gpointer   data )
1557 {
1558     g_print ("Hello again - %s was pressed\n", (char *) data);
1559 }
1560
1561 /* This callback quits the program */
1562 void delete_event( GtkWidget *widget,
1563                    GdkEvent  *event,
1564                    gpointer   data )
1565 {
1566     gtk_main_quit ();
1567 }
1568
1569 int main( int   argc,
1570           char *argv[] )
1571 {
1572     GtkWidget *window;
1573     GtkWidget *button;
1574     GtkWidget *table;
1575
1576     gtk_init (&amp;argc, &amp;argv);
1577
1578     /* Create a new window */
1579     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1580
1581     /* Set the window title */
1582     gtk_window_set_title (GTK_WINDOW (window), "Table");
1583
1584     /* Set a handler for delete_event that immediately
1585      * exits GTK. */
1586     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1587                         GTK_SIGNAL_FUNC (delete_event), NULL);
1588
1589     /* Sets the border width of the window. */
1590     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1591
1592     /* Create a 2x2 table */
1593     table = gtk_table_new (2, 2, TRUE);
1594
1595     /* Put the table in the main window */
1596     gtk_container_add (GTK_CONTAINER (window), table);
1597
1598     /* Create first button */
1599     button = gtk_button_new_with_label ("button 1");
1600
1601     /* When the button is clicked, we call the "callback" function
1602      * with a pointer to "button 1" as its argument */
1603     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1604               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1605
1606
1607     /* Insert button 1 into the upper left quadrant of the table */
1608     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1609
1610     gtk_widget_show (button);
1611
1612     /* Create second button */
1613
1614     button = gtk_button_new_with_label ("button 2");
1615
1616     /* When the button is clicked, we call the "callback" function
1617      * with a pointer to "button 2" as its argument */
1618     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1619               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1620     /* Insert button 2 into the upper right quadrant of the table */
1621     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1622
1623     gtk_widget_show (button);
1624
1625     /* Create "Quit" button */
1626     button = gtk_button_new_with_label ("Quit");
1627
1628     /* When the button is clicked, we call the "delete_event" function
1629      * and the program exits */
1630     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1631                         GTK_SIGNAL_FUNC (delete_event), NULL);
1632
1633     /* Insert the quit button into the both 
1634      * lower quadrants of the table */
1635     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1636
1637     gtk_widget_show (button);
1638
1639     gtk_widget_show (table);
1640     gtk_widget_show (window);
1641
1642     gtk_main ();
1643
1644     return 0;
1645 }
1646 /* example-end */
1647 </verb></tscreen>
1648
1649 <!-- ***************************************************************** -->
1650 <sect>Widget Overview
1651 <!-- ***************************************************************** -->
1652 <p>
1653 The general steps to creating a widget in GTK are:
1654 <enum>
1655 <item> gtk_*_new - one of various functions to create a new widget.
1656 These are all detailed in this section.
1657
1658 <item> Connect all signals and events we wish to use to the
1659 appropriate handlers.
1660
1661 <item> Set the attributes of the widget.
1662
1663 <item> Pack the widget into a container using the appropriate call
1664 such as gtk_container_add() or gtk_box_pack_start().
1665
1666 <item> gtk_widget_show() the widget.
1667 </enum>
1668
1669 gtk_widget_show() lets GTK know that we are done setting the
1670 attributes of the widget, and it is ready to be displayed. You may
1671 also use gtk_widget_hide to make it disappear again. The order in
1672 which you show the widgets is not important, but I suggest showing the
1673 window last so the whole window pops up at once rather than seeing the
1674 individual widgets come up on the screen as they're formed. The
1675 children of a widget (a window is a widget too) will not be displayed
1676 until the window itself is shown using the gtk_widget_show() function.
1677
1678 <!-- ----------------------------------------------------------------- -->
1679 <sect1> Casting
1680 <p>
1681 You'll notice as you go on, that GTK uses a type casting system. This
1682 is always done using macros that both test the ability to cast the
1683 given item, and perform the cast. Some common ones you will see are:
1684
1685 <itemize>
1686 <item> GTK_WIDGET(widget)
1687 <item> GTK_OBJECT(object)
1688 <item> GTK_SIGNAL_FUNC(function)
1689 <item> GTK_CONTAINER(container)
1690 <item> GTK_WINDOW(window)
1691 <item> GTK_BOX(box)
1692 </itemize>
1693
1694 These are all used to cast arguments in functions. You'll see them in the
1695 examples, and can usually tell when to use them simply by looking at the
1696 function's declaration.
1697
1698 As you can see below in the class hierarchy, all GtkWidgets are
1699 derived from the GtkObject base class. This means you can use a widget
1700 in any place the function asks for an object - simply use the
1701 GTK_OBJECT() macro.
1702
1703 For example:
1704
1705 <tscreen><verb>
1706 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1707                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1708 </verb></tscreen> 
1709
1710 This casts the button into an object, and provides a cast for the
1711 function pointer to the callback.
1712
1713 Many widgets are also containers. If you look in the class hierarchy
1714 below, you'll notice that many widgets derive from the GtkContainer
1715 class. Any one of these widgets may be used with the GTK_CONTAINER
1716 macro to pass them to functions that ask for containers.
1717
1718 Unfortunately, these macros are not extensively covered in the
1719 tutorial, but I recommend taking a look through the GTK header
1720 files. It can be very educational. In fact, it's not difficult to
1721 learn how a widget works just by looking at the function declarations.
1722
1723 <!-- ----------------------------------------------------------------- -->
1724 <sect1>Widget Hierarchy
1725 <p>
1726 For your reference, here is the class hierarchy tree used to implement widgets.
1727
1728 <tscreen><verb>
1729  GtkObject
1730   +GtkWidget
1731   | +GtkMisc
1732   | | +GtkLabel
1733   | | | +GtkAccelLabel
1734   | | | `GtkTipsQuery
1735   | | +GtkArrow
1736   | | +GtkImage
1737   | | `GtkPixmap
1738   | +GtkContainer
1739   | | +GtkBin
1740   | | | +GtkAlignment
1741   | | | +GtkFrame
1742   | | | | `GtkAspectFrame
1743   | | | +GtkButton
1744   | | | | +GtkToggleButton
1745   | | | | | `GtkCheckButton
1746   | | | | |   `GtkRadioButton
1747   | | | | `GtkOptionMenu
1748   | | | +GtkItem
1749   | | | | +GtkMenuItem
1750   | | | | | +GtkCheckMenuItem
1751   | | | | | | `GtkRadioMenuItem
1752   | | | | | `GtkTearoffMenuItem
1753   | | | | +GtkListItem
1754   | | | | `GtkTreeItem
1755   | | | +GtkWindow
1756   | | | | +GtkColorSelectionDialog
1757   | | | | +GtkDialog
1758   | | | | | `GtkInputDialog
1759   | | | | +GtkDrawWindow
1760   | | | | +GtkFileSelection
1761   | | | | +GtkFontSelectionDialog
1762   | | | | `GtkPlug
1763   | | | +GtkEventBox
1764   | | | +GtkHandleBox
1765   | | | +GtkScrolledWindow
1766   | | | `GtkViewport
1767   | | +GtkBox
1768   | | | +GtkButtonBox
1769   | | | | +GtkHButtonBox
1770   | | | | `GtkVButtonBox
1771   | | | +GtkVBox
1772   | | | | +GtkColorSelection
1773   | | | | `GtkGammaCurve
1774   | | | `GtkHBox
1775   | | |   +GtkCombo
1776   | | |   `GtkStatusbar
1777   | | +GtkCList
1778   | | | `GtkCTree
1779   | | +GtkFixed
1780   | | +GtkNotebook
1781   | | | `GtkFontSelection
1782   | | +GtkPaned
1783   | | | +GtkHPaned
1784   | | | `GtkVPaned
1785   | | +GtkLayout
1786   | | +GtkList
1787   | | +GtkMenuShell
1788   | | | +GtkMenuBar
1789   | | | `GtkMenu
1790   | | +GtkPacker
1791   | | +GtkSocket
1792   | | +GtkTable
1793   | | +GtkToolbar
1794   | | `GtkTree
1795   | +GtkCalendar
1796   | +GtkDrawingArea
1797   | | `GtkCurve
1798   | +GtkEditable
1799   | | +GtkEntry
1800   | | | `GtkSpinButton
1801   | | `GtkText
1802   | +GtkRuler
1803   | | +GtkHRuler
1804   | | `GtkVRuler
1805   | +GtkRange
1806   | | +GtkScale
1807   | | | +GtkHScale
1808   | | | `GtkVScale
1809   | | `GtkScrollbar
1810   | |   +GtkHScrollbar
1811   | |   `GtkVScrollbar
1812   | +GtkSeparator
1813   | | +GtkHSeparator
1814   | | `GtkVSeparator
1815   | +GtkPreview
1816   | `GtkProgress
1817   |   `GtkProgressBar
1818   +GtkData
1819   | +GtkAdjustment
1820   | `GtkTooltips
1821   `GtkItemFactory
1822 </verb></tscreen>
1823
1824 <!-- ----------------------------------------------------------------- -->
1825 <sect1>Widgets Without Windows
1826 <p>
1827 The following widgets do not have an associated window. If you want to
1828 capture events, you'll have to use the GtkEventBox. See the section on
1829 the <ref id="sec_EventBox" name="EventBox"> widget.
1830
1831 <tscreen><verb>
1832 GtkAlignment
1833 GtkArrow
1834 GtkBin
1835 GtkBox
1836 GtkImage
1837 GtkItem
1838 GtkLabel
1839 GtkPixmap
1840 GtkScrolledWindow
1841 GtkSeparator
1842 GtkTable
1843 GtkAspectFrame
1844 GtkFrame
1845 GtkVBox
1846 GtkHBox
1847 GtkVSeparator
1848 GtkHSeparator
1849 </verb></tscreen>
1850
1851 We'll further our exploration of GTK by examining each widget in turn,
1852 creating a few simple functions to display them. Another good source
1853 is the testgtk.c program that comes with GTK. It can be found in
1854 gtk/testgtk.c.
1855
1856 <!-- ***************************************************************** -->
1857 <sect>The Button Widget
1858 <!-- ***************************************************************** -->
1859
1860 <!-- ----------------------------------------------------------------- -->
1861 <sect1>Normal Buttons
1862 <p>
1863 We've almost seen all there is to see of the button widget. It's
1864 pretty simple. There are however two ways to create a button. You can
1865 use the gtk_button_new_with_label() to create a button with a label,
1866 or use gtk_button_new() to create a blank button. It's then up to you
1867 to pack a label or pixmap into this new button. To do this, create a
1868 new box, and then pack your objects into this box using the usual
1869 gtk_box_pack_start, and then use gtk_container_add to pack the box
1870 into the button.
1871
1872 Here's an example of using gtk_button_new to create a button with a
1873 picture and a label in it. I've broken up the code to create a box
1874 from the rest so you can use it in your programs. There are further
1875 examples of using pixmaps later in the tutorial.
1876
1877 <tscreen><verb>
1878 /* example-start buttons buttons.c */
1879
1880 #include <gtk/gtk.h>
1881
1882 /* Create a new hbox with an image and a label packed into it
1883  * and return the box. */
1884
1885 GtkWidget *xpm_label_box( GtkWidget *parent,
1886                           gchar     *xpm_filename,
1887                           gchar     *label_text )
1888 {
1889     GtkWidget *box1;
1890     GtkWidget *label;
1891     GtkWidget *pixmapwid;
1892     GdkPixmap *pixmap;
1893     GdkBitmap *mask;
1894     GtkStyle *style;
1895
1896     /* Create box for xpm and label */
1897     box1 = gtk_hbox_new (FALSE, 0);
1898     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1899
1900     /* Get the style of the button to get the
1901      * background color. */
1902     style = gtk_widget_get_style(parent);
1903
1904     /* Now on to the xpm stuff */
1905     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1906                                          &amp;style->bg[GTK_STATE_NORMAL],
1907                                          xpm_filename);
1908     pixmapwid = gtk_pixmap_new (pixmap, mask);
1909
1910     /* Create a label for the button */
1911     label = gtk_label_new (label_text);
1912
1913     /* Pack the pixmap and label into the box */
1914     gtk_box_pack_start (GTK_BOX (box1),
1915                         pixmapwid, FALSE, FALSE, 3);
1916
1917     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1918
1919     gtk_widget_show(pixmapwid);
1920     gtk_widget_show(label);
1921
1922     return(box1);
1923 }
1924
1925 /* Our usual callback function */
1926 void callback( GtkWidget *widget,
1927                gpointer   data )
1928 {
1929     g_print ("Hello again - %s was pressed\n", (char *) data);
1930 }
1931
1932
1933 int main( int   argc,
1934           char *argv[] )
1935 {
1936     /* GtkWidget is the storage type for widgets */
1937     GtkWidget *window;
1938     GtkWidget *button;
1939     GtkWidget *box1;
1940
1941     gtk_init (&amp;argc, &amp;argv);
1942
1943     /* Create a new window */
1944     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1945
1946     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1947
1948     /* It's a good idea to do this for all windows. */
1949     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1950                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1951
1952     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1953                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1954
1955
1956     /* Sets the border width of the window. */
1957     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1958     gtk_widget_realize(window);
1959
1960     /* Create a new button */
1961     button = gtk_button_new ();
1962
1963     /* Connect the "clicked" signal of the button to our callback */
1964     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1965                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1966
1967     /* This calls our box creating function */
1968     box1 = xpm_label_box(window, "info.xpm", "cool button");
1969
1970     /* Pack and show all our widgets */
1971     gtk_widget_show(box1);
1972
1973     gtk_container_add (GTK_CONTAINER (button), box1);
1974
1975     gtk_widget_show(button);
1976
1977     gtk_container_add (GTK_CONTAINER (window), button);
1978
1979     gtk_widget_show (window);
1980
1981     /* Rest in gtk_main and wait for the fun to begin! */
1982     gtk_main ();
1983
1984     return(0);
1985 }
1986 /* example-end */
1987 </verb></tscreen>
1988
1989 The xpm_label_box function could be used to pack xpm's and labels into
1990 any widget that can be a container.
1991
1992 The Button widget has the following signals:
1993
1994 <itemize>
1995 <item> pressed
1996 <item> released
1997 <item> clicked
1998 <item> enter
1999 <item> leave
2000 </itemize>
2001
2002 <!-- ----------------------------------------------------------------- -->
2003 <sect1> Toggle Buttons
2004 <p>
2005 Toggle buttons are derived from normal buttons and are very similar,
2006 except they will always be in one of two states, alternated by a
2007 click. They may be depressed, and when you click again, they will pop
2008 back up. Click again, and they will pop back down.
2009
2010 Toggle buttons are the basis for check buttons and radio buttons, as
2011 such, many of the calls used for toggle buttons are inherited by radio
2012 and check buttons. I will point these out when we come to them.
2013
2014 Creating a new toggle button:
2015
2016 <tscreen><verb>
2017 GtkWidget *gtk_toggle_button_new( void );
2018
2019 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
2020 </verb></tscreen>
2021
2022 As you can imagine, these work identically to the normal button widget
2023 calls. The first creates a blank toggle button, and the second, a
2024 button with a label widget already packed into it.
2025
2026 To retrieve the state of the toggle widget, including radio and check
2027 buttons, we use a GTK macro as shown in our example below. This tests
2028 the state of the toggle in a callback. The signal of interest emitted
2029 to us by toggle buttons (the toggle button, check button, and radio
2030 button widgets), is the "toggled" signal. To check the state of these
2031 buttons, set up a signal handler to catch the toggled signal, and use
2032 the macro to determine its state. The callback will look something
2033 like:
2034
2035 <tscreen><verb>
2036 void toggle_button_callback (GtkWidget *widget, gpointer data)
2037 {
2038     if (GTK_TOGGLE_BUTTON (widget)->active) 
2039     {
2040         /* If control reaches here, the toggle button is down */
2041     
2042     } else {
2043     
2044         /* If control reaches here, the toggle button is up */
2045     }
2046 }
2047 </verb></tscreen>
2048
2049 <tscreen><verb>
2050 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2051                                   gint             state );
2052 </verb></tscreen>
2053
2054 The above call can be used to set the state of the toggle button, and
2055 its children the radio and check buttons. Passing in your created
2056 button as the first argument, and a TRUE or FALSE for the second state
2057 argument to specify whether it should be down (depressed) or up
2058 (released). Default is up, or FALSE.
2059
2060 Note that when you use the gtk_toggle_button_set_active() function, and
2061 the state is actually changed, it causes the "clicked" signal to be
2062 emitted from the button.
2063
2064 <tscreen><verb>
2065 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2066 </verb></tscreen>
2067
2068 This simply toggles the button, and emits the "toggled" signal.
2069
2070 <!-- ----------------------------------------------------------------- -->
2071 <sect1> Check Buttons
2072 <p>
2073 Check buttons inherent many properties and functions from the the
2074 toggle buttons above, but look a little different. Rather than being
2075 buttons with text inside them, they are small squares with the text to
2076 the right of them. These are often used for toggling options on and
2077 off in applications.
2078
2079 The two creation functions are similar to those of the normal button.
2080
2081 <tscreen><verb>
2082 GtkWidget *gtk_check_button_new( void );
2083
2084 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2085 </verb></tscreen>
2086
2087 The new_with_label function creates a check button with a label beside
2088 it.
2089
2090 Checking the state of the check button is identical to that of the
2091 toggle button.
2092
2093 <!-- ----------------------------------------------------------------- -->
2094 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2095 <p>
2096 Radio buttons are similar to check buttons except they are grouped so
2097 that only one may be selected/depressed at a time. This is good for
2098 places in your application where you need to select from a short list
2099 of options.
2100
2101 Creating a new radio button is done with one of these calls:
2102
2103 <tscreen><verb>
2104 GtkWidget *gtk_radio_button_new( GSList *group );
2105
2106 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2107                                             gchar  *label );
2108 </verb></tscreen>
2109
2110 You'll notice the extra argument to these calls. They require a group
2111 to perform their duty properly. The first call to
2112 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2113 should pass NULL as the first argument. Then create a group using:
2114
2115 <tscreen><verb>
2116 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2117 </verb></tscreen>
2118
2119 The important thing to remember is that gtk_radio_button_group must be
2120 called for each new button added to the group, with the previous
2121 button passed in as an argument. The result is then passed into the
2122 call to gtk_radio_button_new or gtk_radio_button_new_with_label. This
2123 allows a chain of buttons to be established. The example below should
2124 make this clear.
2125
2126 You can shorten this slightly by using the following syntax, which
2127 removes the need for a variable to hold the list of buttons. This form
2128 is used in the example to create the third button:
2129
2130 <tscreen><verb>
2131      button2 = gtk_radio_button_new_with_label(
2132                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2133                  "button2");
2134 </verb></tscreen>
2135
2136 It is also a good idea to explicitly set which button should be the
2137 default depressed button with:
2138
2139 <tscreen><verb>
2140 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2141                                   gint             state );
2142 </verb></tscreen>
2143
2144 This is described in the section on toggle buttons, and works in
2145 exactly the same way.
2146
2147 The following example creates a radio button group with three buttons.
2148
2149 <tscreen><verb>
2150 /* example-start radiobuttons radiobuttons.c */
2151
2152 #include <gtk/gtk.h>
2153 #include <glib.h>
2154
2155 void close_application( GtkWidget *widget,
2156                         GdkEvent  *event,
2157                         gpointer   data )
2158 {
2159   gtk_main_quit();
2160 }
2161
2162 int main( int   argc,
2163           char *argv[] )
2164 {
2165     GtkWidget *window = NULL;
2166     GtkWidget *box1;
2167     GtkWidget *box2;
2168     GtkWidget *button;
2169     GtkWidget *separator;
2170     GSList *group;
2171   
2172     gtk_init(&amp;argc,&amp;argv);    
2173       
2174     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2175   
2176     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2177                         GTK_SIGNAL_FUNC(close_application),
2178                         NULL);
2179
2180     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2181     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2182
2183     box1 = gtk_vbox_new (FALSE, 0);
2184     gtk_container_add (GTK_CONTAINER (window), box1);
2185     gtk_widget_show (box1);
2186
2187     box2 = gtk_vbox_new (FALSE, 10);
2188     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2189     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2190     gtk_widget_show (box2);
2191
2192     button = gtk_radio_button_new_with_label (NULL, "button1");
2193     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2194     gtk_widget_show (button);
2195
2196     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2197     button = gtk_radio_button_new_with_label(group, "button2");
2198     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2199     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2200     gtk_widget_show (button);
2201
2202     button = gtk_radio_button_new_with_label(
2203                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2204                  "button3");
2205     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2206     gtk_widget_show (button);
2207
2208     separator = gtk_hseparator_new ();
2209     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2210     gtk_widget_show (separator);
2211
2212     box2 = gtk_vbox_new (FALSE, 10);
2213     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2214     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2215     gtk_widget_show (box2);
2216
2217     button = gtk_button_new_with_label ("close");
2218     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2219                                GTK_SIGNAL_FUNC(close_application),
2220                                GTK_OBJECT (window));
2221     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2222     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2223     gtk_widget_grab_default (button);
2224     gtk_widget_show (button);
2225     gtk_widget_show (window);
2226      
2227     gtk_main();
2228
2229     return(0);
2230 }
2231 /* example-end */
2232 </verb></tscreen>
2233
2234 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2235
2236 <!-- ***************************************************************** -->
2237 <sect> Adjustments <label id="sec_Adjustment">
2238 <!-- ***************************************************************** -->
2239 <p>
2240 GTK+ has various widgets that can be visually adjusted by the user
2241 using the mouse or the keyboard, such as the range widgets, described
2242 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2243 section. There are also a few widgets that display some adjustable
2244 portion of a larger area of data, such as the text widget and the
2245 viewport widget.
2246
2247 Obviously, an application needs to be able to react to changes the
2248 user makes in range widgets. One way to do this would be to have each
2249 widget emit its own type of signal when its adjustment changes, and
2250 either pass the new value to the signal handler, or require it to look
2251 inside the widget's data structure in order to ascertain the value.
2252 But you may also want to connect the adjustments of several widgets
2253 together, so that adjusting one adjusts the others. The most obvious
2254 example of this is connecting a scrollbar to a panning viewport or a
2255 scrolling text area. If each widget has its own way of setting or
2256 getting the adjustment value, then the programmer may have to write
2257 their own signal handlers to translate between the output of one
2258 widget's signal and the "input" of another's adjustment setting
2259 function.
2260
2261 GTK+ solves this problem using the GtkAdjustment object, which is a
2262 way for widgets to store and pass adjustment information in an
2263 abstract and flexible form. The most obvious use of GtkAdjustment is
2264 to store the configuration parameters and values of range widgets,
2265 such as scrollbars and scale controls. However, since GtkAdjustments
2266 are derived from GtkObject, they have some special powers beyond those
2267 of normal data structures. Most importantly, they can emit signals,
2268 just like widgets, and these signals can be used not only to allow
2269 your program to react to user input on adjustable widgets, but also to
2270 propagate adjustment values transparently between adjustable widgets.
2271
2272 <sect1> Creating an Adjustment
2273 <p>
2274 You create an adjustment using:
2275
2276 <tscreen><verb>
2277 GtkObject *gtk_adjustment_new( gfloat value,
2278                                gfloat lower,
2279                                gfloat upper,
2280                                gfloat step_increment,
2281                                gfloat page_increment,
2282                                gfloat page_size );
2283 </verb></tscreen>
2284
2285 The <tt/value/ argument is the initial value you want to give to the
2286 adjustment, usually corresponding to the topmost or leftmost position
2287 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2288 value which the adjustment can hold. The <tt/step_increment/ argument
2289 specifies the "smaller" of the two increments by which the user can
2290 change the value, while the <tt/page_increment/ is the "larger" one.
2291 The <tt/page_size/ argument usually corresponds somehow to the visible
2292 area of a panning widget. The <tt/upper/ argument is used to represent
2293 the bottom most or right most coordinate in a panning widget's
2294 child. Therefore it is <em/not/ always the largest number that
2295 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2296 usually non-zero.
2297
2298 <!-- ----------------------------------------------------------------- -->
2299 <sect1> Using Adjustments the Easy Way
2300 <p>
2301 The adjustable widgets can be roughly divided into those which use and
2302 require specific units for these values and those which treat them as
2303 arbitrary numbers. The group which treats the values as arbitrary
2304 numbers includes the range widgets (scrollbars and scales, the
2305 progress bar widget, and the spin button widget). These widgets are
2306 all the widgets which are typically "adjusted" directly by the user
2307 with the mouse or keyboard. They will treat the <tt/lower/ and
2308 <tt/upper/ values of an adjustment as a range within which the user
2309 can manipulate the adjustment's <tt/value/. By default, they will only
2310 modify the <tt/value/ of an adjustment.
2311
2312 The other group includes the text widget, the viewport widget, the
2313 compound list widget, and the scrolled window widget. All of these
2314 widgets use pixel values for their adjustments. These are also all
2315 widgets which are typically "adjusted" indirectly using scrollbars.
2316 While all widgets which use adjustments can either create their own
2317 adjustments or use ones you supply, you'll generally want to let this
2318 particular category of widgets create its own adjustments. Usually,
2319 they will eventually override all the values except the <tt/value/
2320 itself in whatever adjustments you give them, but the results are, in
2321 general, undefined (meaning, you'll have to read the source code to
2322 find out, and it may be different from widget to widget).
2323
2324 Now, you're probably thinking, since text widgets and viewports insist
2325 on setting everything except the <tt/value/ of their adjustments,
2326 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2327 you <em/share/ an adjustment object between a scrollbar and a text
2328 widget, manipulating the scrollbar will automagically adjust the text
2329 widget?  Of course it will! Just like this:
2330
2331 <tscreen><verb>
2332   /* creates its own adjustments */
2333   text = gtk_text_new (NULL, NULL);
2334   /* uses the newly-created adjustment for the scrollbar as well */
2335   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2336 </verb></tscreen>
2337
2338 </sect1>
2339 <!-- ----------------------------------------------------------------- -->
2340 <sect1> Adjustment Internals
2341 <p>
2342 Ok, you say, that's nice, but what if I want to create my own handlers
2343 to respond when the user adjusts a range widget or a spin button, and
2344 how do I get at the value of the adjustment in these handlers?  To
2345 answer these questions and more, let's start by taking a look at
2346 <tt>struct _GtkAdjustment</tt> itself:
2347
2348 <tscreen><verb>
2349 struct _GtkAdjustment
2350 {
2351   GtkData data;
2352   
2353   gfloat lower;
2354   gfloat upper;
2355   gfloat value;
2356   gfloat step_increment;
2357   gfloat page_increment;
2358   gfloat page_size;
2359 };     
2360 </verb></tscreen>
2361
2362 The first thing you should know is that there aren't any handy-dandy
2363 macros or accessor functions for getting the <tt/value/ out of a
2364 GtkAdjustment, so you'll have to (horror of horrors) do it like a
2365 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2366 (Object)</tt> macro does run-time type checking (as do all the GTK+
2367 type-casting macros, actually).
2368
2369 Since, when you set the <tt/value/ of an adjustment, you generally
2370 want the change to be reflected by every widget that uses this
2371 adjustment, GTK+ provides this convenience function to do this:
2372
2373 <tscreen><verb>
2374 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2375                                gfloat         value );
2376 </verb></tscreen>
2377
2378 As mentioned earlier, GtkAdjustment is a subclass of GtkObject just
2379 like all the various widgets, and thus it is able to emit signals.
2380 This is, of course, why updates happen automagically when you share an
2381 adjustment object between a scrollbar and another adjustable widget;
2382 all adjustable widgets connect signal handlers to their adjustment's
2383 <tt/value_changed/ signal, as can your program. Here's the definition
2384 of this signal in <tt/struct _GtkAdjustmentClass/:
2385
2386 <tscreen><verb>
2387   void (* value_changed) (GtkAdjustment *adjustment);
2388 </verb></tscreen>
2389
2390 The various widgets that use the GtkAdjustment object will emit this
2391 signal on an adjustment whenever they change its value. This happens
2392 both when user input causes the slider to move on a range widget, as
2393 well as when the program explicitly changes the value with
2394 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2395 widget, and you want to change the rotation of a picture whenever its
2396 value changes, you would create a callback like this:
2397
2398 <tscreen><verb>
2399 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2400 {
2401   set_picture_rotation (picture, adj->value);
2402 ...
2403 </verb></tscreen>
2404
2405 and connect it to the scale widget's adjustment like this:
2406
2407 <tscreen><verb>
2408 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2409                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2410 </verb></tscreen>
2411
2412 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2413 fields of its adjustment, such as when a user adds more text to a text
2414 widget?  In this case, it emits the <tt/changed/ signal, which looks
2415 like this:
2416
2417 <tscreen><verb>
2418   void (* changed)       (GtkAdjustment *adjustment);
2419 </verb></tscreen>
2420
2421 Range widgets typically connect a handler to this signal, which
2422 changes their appearance to reflect the change - for example, the size
2423 of the slider in a scrollbar will grow or shrink in inverse proportion
2424 to the difference between the <tt/lower/ and <tt/upper/ values of its
2425 adjustment.
2426
2427 You probably won't ever need to attach a handler to this signal,
2428 unless you're writing a new type of range widget.  However, if you
2429 change any of the values in a GtkAdjustment directly, you should emit
2430 this signal on it to reconfigure whatever widgets are using it, like
2431 this:
2432
2433 <tscreen><verb>
2434 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2435 </verb></tscreen>
2436
2437 Now go forth and adjust!
2438 </sect1>
2439 </sect>
2440
2441 <!-- ***************************************************************** -->
2442 <sect> Range Widgets<label id="sec_Range_Widgets">
2443 <!-- ***************************************************************** -->
2444
2445 <p>
2446 The category of range widgets includes the ubiquitous scrollbar widget
2447 and the less common "scale" widget. Though these two types of widgets
2448 are generally used for different purposes, they are quite similar in
2449 function and implementation. All range widgets share a set of common
2450 graphic elements, each of which has its own X window and receives
2451 events. They all contain a "trough" and a "slider" (what is sometimes
2452 called a "thumbwheel" in other GUI environments). Dragging the slider
2453 with the pointer moves it back and forth within the trough, while
2454 clicking in the trough advances the slider towards the location of the
2455 click, either completely, or by a designated amount, depending on
2456 which mouse button is used.
2457
2458 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2459 all range widgets are associated with an adjustment object, from which
2460 they calculate the length of the slider and its position within the
2461 trough. When the user manipulates the slider, the range widget will
2462 change the value of the adjustment.
2463
2464 <!-- ----------------------------------------------------------------- -->
2465 <sect1> Scrollbar Widgets
2466 <p>
2467 These are your standard, run-of-the-mill scrollbars. These should be
2468 used only for scrolling some other widget, such as a list, a text box,
2469 or a viewport (and it's generally easier to use the scrolled window
2470 widget in most cases).  For other purposes, you should use scale
2471 widgets, as they are friendlier and more featureful.
2472
2473 There are separate types for horizontal and vertical scrollbars.
2474 There really isn't much to say about these. You create them with the
2475 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2476 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2477
2478 <tscreen><verb>
2479 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2480
2481 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2482 </verb></tscreen>
2483
2484 and that's about it (if you don't believe me, look in the header
2485 files!).  The <tt/adjustment/ argument can either be a pointer to an
2486 existing GtkAdjustment, or NULL, in which case one will be created for
2487 you. Specifying NULL might actually be useful in this case, if you
2488 wish to pass the newly-created adjustment to the constructor function
2489 of some other widget which will configure it for you, such as a text
2490 widget.
2491 </sect1>
2492
2493 <!-- ----------------------------------------------------------------- -->
2494 <sect1> Scale Widgets
2495 <p>
2496 Scale widgets are used to allow the user to visually select and
2497 manipulate a value within a specific range. You might want to use a
2498 scale widget, for example, to adjust the magnification level on a
2499 zoomed preview of a picture, or to control the brightness of a colour,
2500 or to specify the number of minutes of inactivity before a screensaver
2501 takes over the screen.
2502
2503 <!-- ----------------------------------------------------------------- -->
2504 <sect2>Creating a Scale Widget
2505 <p>
2506 As with scrollbars, there are separate widget types for horizontal and
2507 vertical scale widgets. (Most programmers seem to favour horizontal
2508 scale widgets). Since they work essentially the same way, there's no
2509 need to treat them separately here. The following functions, defined
2510 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2511 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2512 widgets, respectively:
2513
2514 <tscreen>
2515 <verb>
2516 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2517
2518 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2519 </verb>
2520 </tscreen>
2521
2522 The <tt/adjustment/ argument can either be an adjustment which has
2523 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2524 which case, an anonymous GtkAdjustment is created with all of its
2525 values set to <tt/0.0/ (which isn't very useful in this case). In
2526 order to avoid confusing yourself, you probably want to create your
2527 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2528 value actually corresponds to the highest value the user can select.
2529 (If you're <em/already/ thoroughly confused, read the section on <ref
2530 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2531 what exactly adjustments do and how to create and manipulate them).
2532
2533 <!-- ----------------------------------------------------------------- -->
2534 <sect2> Functions and Signals (well, functions, at least)
2535 <p>
2536 Scale widgets can display their current value as a number beside the
2537 trough. The default behaviour is to show the value, but you can change
2538 this with this function:
2539
2540 <tscreen><verb>
2541 void gtk_scale_set_draw_value( GtkScale *scale,
2542                                gint      draw_value );
2543 </verb></tscreen>
2544
2545 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2546 <tt/FALSE/, with predictable consequences for either one.
2547
2548 The value displayed by a scale widget is rounded to one decimal point
2549 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2550 change this with:
2551
2552 <tscreen>
2553 <verb>
2554 void gtk_scale_set_digits( GtkScale *scale,
2555                             gint     digits );
2556 </verb>
2557 </tscreen>
2558
2559 where <tt/digits/ is the number of decimal places you want. You can
2560 set <tt/digits/ to anything you like, but no more than 13 decimal
2561 places will actually be drawn on screen.
2562
2563 Finally, the value can be drawn in different positions
2564 relative to the trough:
2565
2566 <tscreen>
2567 <verb>
2568 void gtk_scale_set_value_pos( GtkScale        *scale,
2569                               GtkPositionType  pos );
2570 </verb>
2571 </tscreen>
2572
2573 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2574 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2575 following values:
2576
2577 <itemize>
2578 <item> GTK_POS_LEFT
2579 <item> GTK_POS_RIGHT
2580 <item> GTK_POS_TOP
2581 <item> GTK_POS_BOTTOM
2582 </itemize>
2583
2584 If you position the value on the "side" of the trough (e.g. on the top
2585 or bottom of a horizontal scale widget), then it will follow the
2586 slider up and down the trough.
2587
2588 All the preceding functions are defined in
2589 <tt>&lt;gtk/gtkscale.h&gt;</tt>.
2590 </sect2>
2591 </sect1>
2592
2593 <!-- ----------------------------------------------------------------- -->
2594 <sect1> Common Functions <label id="sec_Range_Functions">
2595 <p>
2596 The GtkRange widget class is fairly complicated internally, but, like
2597 all the "base class" widgets, most of its complexity is only
2598 interesting if you want to hack on it. Also, almost all of the
2599 functions and signals it defines are only really used in writing
2600 derived widgets. There are, however, a few useful functions that are
2601 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2602 widgets.
2603
2604 <!-- ----------------------------------------------------------------- -->
2605 <sect2> Setting the Update Policy
2606 <p>
2607 The "update policy" of a range widget defines at what points during
2608 user interaction it will change the <tt/value/ field of its
2609 GtkAdjustment and emit the "value_changed" signal on this
2610 GtkAdjustment. The update policies, defined in
2611 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2612 are:
2613
2614 <itemize>
2615 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2616 "value_changed" signal is emitted continuously, i.e. whenever the
2617 slider is moved by even the tiniest amount.
2618 </item>
2619 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2620 only emitted once the slider has stopped moving and the user has
2621 released the mouse button.
2622 </item>
2623 <item>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emitted
2624 when the user releases the mouse button, or if the slider stops moving
2625 for a short period of time.
2626 </item>
2627 </itemize>
2628
2629 The update policy of a range widget can be set by casting it using the
2630 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2631
2632 <tscreen><verb>
2633 void gtk_range_set_update_policy( GtkRange      *range,
2634                                   GtkUpdateType  policy) ;
2635 </verb></tscreen>
2636
2637 <!-- ----------------------------------------------------------------- -->
2638 <sect2>Getting and Setting Adjustments
2639 <p>
2640 Getting and setting the adjustment for a range widget "on the fly" is
2641 done, predictably, with:
2642
2643 <tscreen><verb>
2644 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2645
2646 void gtk_range_set_adjustment( GtkRange      *range,
2647                                GtkAdjustment *adjustment );
2648 </verb></tscreen>
2649
2650 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2651 which <tt/range/ is connected.
2652
2653 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2654 the adjustment that <tt/range/ is already using, regardless of whether
2655 you changed any of its fields or not. If you pass it a new
2656 GtkAdjustment, it will unreference the old one if it exists (possibly
2657 destroying it), connect the appropriate signals to the new one, and
2658 call the private function <tt/gtk_range_adjustment_changed()/, which
2659 will (or at least, is supposed to...) recalculate the size and/or
2660 position of the slider and redraw if necessary. As mentioned in the
2661 section on adjustments, if you wish to reuse the same GtkAdjustment,
2662 when you modify its values directly, you should emit the "changed"
2663 signal on it, like this:
2664
2665 <tscreen><verb>
2666 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2667 </verb></tscreen>
2668 </sect2>
2669 </sect1>
2670
2671 <!-- ----------------------------------------------------------------- -->
2672 <sect1> Key and Mouse bindings
2673 <p>
2674 All of the GTK+ range widgets react to mouse clicks in more or less
2675 the same way. Clicking button-1 in the trough will cause its
2676 adjustment's <tt/page_increment/ to be added or subtracted from its
2677 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2678 button-2 in the trough will jump the slider to the point at which the
2679 button was clicked. Clicking any button on a scrollbar's arrows will
2680 cause its adjustment's value to change <tt/step_increment/ at a time.
2681
2682 It may take a little while to get used to, but by default, scrollbars
2683 as well as scale widgets can take the keyboard focus in GTK+. If you
2684 think your users will find this too confusing, you can always disable
2685 this by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:
2686
2687 <tscreen><verb>
2688 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2689 </verb></tscreen>
2690
2691 The key bindings (which are, of course, only active when the widget
2692 has focus) are slightly different between horizontal and vertical
2693 range widgets, for obvious reasons. They are also not quite the same
2694 for scale widgets as they are for scrollbars, for somewhat less
2695 obvious reasons (possibly to avoid confusion between the keys for
2696 horizontal and vertical scrollbars in scrolled windows, where both
2697 operate on the same area).
2698
2699 <sect2> Vertical Range Widgets
2700 <p>
2701 All vertical range widgets can be operated with the up and down arrow
2702 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2703 arrows move the slider up and down by <tt/step_increment/, while
2704 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2705
2706 The user can also move the slider all the way to one end or the other
2707 of the trough using the keyboard. With the GtkVScale widget, this is
2708 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2709 GtkVScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2710 and <tt>Control-Page Down</tt>.
2711
2712 <!-- ----------------------------------------------------------------- -->
2713 <sect2> Horizontal Range Widgets
2714 <p>
2715 The left and right arrow keys work as you might expect in these
2716 widgets, moving the slider back and forth by <tt/step_increment/. The
2717 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2718 For the GtkHScale widget, moving the slider by <tt/page_increment/ is
2719 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2720 while for GtkHScrollbar, it's done with <tt>Control-Home</tt> and
2721 <tt>Control-End</tt>.
2722 </sect2>
2723 </sect1>
2724
2725 <!-- ----------------------------------------------------------------- -->
2726 <sect1> Example<label id="sec_Range_Example">
2727 <p>
2728 This example is a somewhat modified version of the "range controls"
2729 test from <tt/testgtk.c/. It basically puts up a window with three
2730 range widgets all connected to the same adjustment, and a couple of
2731 controls for adjusting some of the parameters mentioned above and in
2732 the seciton on adjustments, so you can see how they affect the way
2733 these widgets work for the user.
2734
2735 <tscreen><verb>
2736 /* example-start rangewidgets rangewidgets.c */
2737
2738 #include <gtk/gtk.h>
2739
2740 GtkWidget *hscale, *vscale;
2741
2742 void cb_pos_menu_select( GtkWidget       *item,
2743                          GtkPositionType  pos )
2744 {
2745     /* Set the value position on both scale widgets */
2746     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2747     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2748 }
2749
2750 void cb_update_menu_select( GtkWidget     *item,
2751                             GtkUpdateType  policy )
2752 {
2753     /* Set the update policy for both scale widgets */
2754     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2755     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2756 }
2757
2758 void cb_digits_scale( GtkAdjustment *adj )
2759 {
2760     /* Set the number of decimal places to which adj->value is rounded */
2761     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2762     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2763 }
2764
2765 void cb_page_size( GtkAdjustment *get,
2766                    GtkAdjustment *set )
2767 {
2768     /* Set the page size and page increment size of the sample
2769      * adjustment to the value specified by the "Page Size" scale */
2770     set->page_size = get->value;
2771     set->page_increment = get->value;
2772     /* Now emit the "changed" signal to reconfigure all the widgets that
2773      * are attached to this adjustment */
2774     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2775 }
2776
2777 void cb_draw_value( GtkToggleButton *button )
2778 {
2779     /* Turn the value display on the scale widgets off or on depending
2780      *  on the state of the checkbutton */
2781     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2782     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2783 }
2784
2785 /* Convenience functions */
2786
2787 GtkWidget *make_menu_item( gchar         *name,
2788                            GtkSignalFunc  callback,
2789                            gpointer       data )
2790 {
2791     GtkWidget *item;
2792   
2793     item = gtk_menu_item_new_with_label (name);
2794     gtk_signal_connect (GTK_OBJECT (item), "activate",
2795                         callback, data);
2796     gtk_widget_show (item);
2797
2798     return(item);
2799 }
2800
2801 void scale_set_default_values( GtkScale *scale )
2802 {
2803     gtk_range_set_update_policy (GTK_RANGE (scale),
2804                                  GTK_UPDATE_CONTINUOUS);
2805     gtk_scale_set_digits (scale, 1);
2806     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2807     gtk_scale_set_draw_value (scale, TRUE);
2808 }
2809
2810 /* makes the sample window */
2811
2812 void create_range_controls( void )
2813 {
2814     GtkWidget *window;
2815     GtkWidget *box1, *box2, *box3;
2816     GtkWidget *button;
2817     GtkWidget *scrollbar;
2818     GtkWidget *separator;
2819     GtkWidget *opt, *menu, *item;
2820     GtkWidget *label;
2821     GtkWidget *scale;
2822     GtkObject *adj1, *adj2;
2823
2824     /* Standard window-creating stuff */
2825     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2826     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2827                         GTK_SIGNAL_FUNC(gtk_main_quit),
2828                         NULL);
2829     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2830
2831     box1 = gtk_vbox_new (FALSE, 0);
2832     gtk_container_add (GTK_CONTAINER (window), box1);
2833     gtk_widget_show (box1);
2834
2835     box2 = gtk_hbox_new (FALSE, 10);
2836     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2837     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2838     gtk_widget_show (box2);
2839
2840     /* calue, lower, upper, step_increment, page_increment, page_size */
2841     /* Note that the page_size value only makes a difference for
2842      * scrollbar widgets, and the highest value you'll get is actually
2843      * (upper - page_size). */
2844     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2845   
2846     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2847     scale_set_default_values (GTK_SCALE (vscale));
2848     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2849     gtk_widget_show (vscale);
2850
2851     box3 = gtk_vbox_new (FALSE, 10);
2852     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2853     gtk_widget_show (box3);
2854
2855     /* Reuse the same adjustment */
2856     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2857     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2858     scale_set_default_values (GTK_SCALE (hscale));
2859     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2860     gtk_widget_show (hscale);
2861
2862     /* Reuse the same adjustment again */
2863     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2864     /* Notice how this causes the scales to always be updated
2865      * continuously when the scrollbar is moved */
2866     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2867                                  GTK_UPDATE_CONTINUOUS);
2868     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2869     gtk_widget_show (scrollbar);
2870
2871     box2 = gtk_hbox_new (FALSE, 10);
2872     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2873     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2874     gtk_widget_show (box2);
2875
2876     /* A checkbutton to control whether the value is displayed or not */
2877     button = gtk_check_button_new_with_label("Display value on scale widgets");
2878     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2879     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2880                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2881     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2882     gtk_widget_show (button);
2883   
2884     box2 = gtk_hbox_new (FALSE, 10);
2885     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2886
2887     /* An option menu to change the position of the value */
2888     label = gtk_label_new ("Scale Value Position:");
2889     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2890     gtk_widget_show (label);
2891   
2892     opt = gtk_option_menu_new();
2893     menu = gtk_menu_new();
2894
2895     item = make_menu_item ("Top",
2896                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2897                            GINT_TO_POINTER (GTK_POS_TOP));
2898     gtk_menu_append (GTK_MENU (menu), item);
2899   
2900     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2901                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2902     gtk_menu_append (GTK_MENU (menu), item);
2903   
2904     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2905                            GINT_TO_POINTER (GTK_POS_LEFT));
2906     gtk_menu_append (GTK_MENU (menu), item);
2907   
2908     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2909                             GINT_TO_POINTER (GTK_POS_RIGHT));
2910     gtk_menu_append (GTK_MENU (menu), item);
2911   
2912     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2913     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2914     gtk_widget_show (opt);
2915
2916     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2917     gtk_widget_show (box2);
2918
2919     box2 = gtk_hbox_new (FALSE, 10);
2920     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2921
2922     /* Yet another option menu, this time for the update policy of the
2923      * scale widgets */
2924     label = gtk_label_new ("Scale Update Policy:");
2925     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2926     gtk_widget_show (label);
2927   
2928     opt = gtk_option_menu_new();
2929     menu = gtk_menu_new();
2930   
2931     item = make_menu_item ("Continuous",
2932                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2933                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2934     gtk_menu_append (GTK_MENU (menu), item);
2935   
2936     item = make_menu_item ("Discontinuous",
2937                             GTK_SIGNAL_FUNC (cb_update_menu_select),
2938                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2939     gtk_menu_append (GTK_MENU (menu), item);
2940   
2941     item = make_menu_item ("Delayed",
2942                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2943                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2944     gtk_menu_append (GTK_MENU (menu), item);
2945   
2946     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2947     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2948     gtk_widget_show (opt);
2949   
2950     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2951     gtk_widget_show (box2);
2952
2953     box2 = gtk_hbox_new (FALSE, 10);
2954     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2955   
2956     /* A GtkHScale widget for adjusting the number of digits on the
2957      * sample scales. */
2958     label = gtk_label_new ("Scale Digits:");
2959     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2960     gtk_widget_show (label);
2961
2962     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
2963     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2964                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
2965     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2966     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2967     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2968     gtk_widget_show (scale);
2969
2970     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2971     gtk_widget_show (box2);
2972   
2973     box2 = gtk_hbox_new (FALSE, 10);
2974     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2975   
2976     /* And, one last GtkHScale widget for adjusting the page size of the
2977      * scrollbar. */
2978     label = gtk_label_new ("Scrollbar Page Size:");
2979     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2980     gtk_widget_show (label);
2981
2982     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
2983     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2984                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
2985     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2986     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2987     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2988     gtk_widget_show (scale);
2989
2990     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2991     gtk_widget_show (box2);
2992
2993     separator = gtk_hseparator_new ();
2994     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2995     gtk_widget_show (separator);
2996
2997     box2 = gtk_vbox_new (FALSE, 10);
2998     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2999     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3000     gtk_widget_show (box2);
3001
3002     button = gtk_button_new_with_label ("Quit");
3003     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3004                                GTK_SIGNAL_FUNC(gtk_main_quit),
3005                                NULL);
3006     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3007     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3008     gtk_widget_grab_default (button);
3009     gtk_widget_show (button);
3010
3011     gtk_widget_show (window);
3012 }
3013
3014 int main( int   argc,
3015           char *argv[] )
3016 {
3017     gtk_init(&amp;argc, &amp;argv);
3018
3019     create_range_controls();
3020
3021     gtk_main();
3022
3023     return(0);
3024 }
3025
3026 /* example-end */
3027 </verb></tscreen>
3028 </sect1>
3029 </sect>
3030
3031 <!-- ***************************************************************** -->
3032 <sect> Miscellaneous Widgets
3033 <!-- ***************************************************************** -->
3034
3035 <!-- ----------------------------------------------------------------- -->
3036 <sect1> Labels
3037 <p>
3038 Labels are used a lot in GTK, and are relatively simple. Labels emit
3039 no signals as they do not have an associated X window. If you need to
3040 catch signals, or do clipping, use the <ref id="sec_EventBox"
3041 name="EventBox"> widget.
3042
3043 To create a new label, use:
3044
3045 <tscreen><verb>
3046 GtkWidget *gtk_label_new( char *str );
3047 </verb></tscreen>
3048
3049 Where the sole argument is the string you wish the label to display.
3050
3051 To change the label's text after creation, use the function:
3052
3053 <tscreen><verb>
3054 void gtk_label_set_text( GtkLabel *label,
3055                          char     *str );
3056 </verb></tscreen>
3057
3058 Where the first argument is the label you created previously (cast
3059 using the GTK_LABEL() macro), and the second is the new string.
3060
3061 The space needed for the new string will be automatically adjusted if
3062 needed. You can produce multi-line labels by putting line breaks in
3063 the label string.
3064
3065 To retrieve the current string, use:
3066
3067 <tscreen><verb>
3068 void gtk_label_get( GtkLabel  *label,
3069                     char     **str );
3070 </verb></tscreen>
3071
3072 Where the first argument is the label you've created, and the second,
3073 the return for the string. Do not free the return string, as it is
3074 used internally by GTK.
3075
3076 The label text can be justified using:
3077
3078 <tscreen><verb>
3079 void gtk_label_set_justify( GtkLabel         *label,
3080                             GtkJustification  jtype );
3081 </verb></tscreen>
3082
3083 Values for <tt/jtype/ are:
3084 <itemize>
3085 <item> GTK_JUSTIFY_LEFT
3086 <item> GTK_JUSTIFY_RIGHT
3087 <item> GTK_JUSTIFY_CENTER (the default)
3088 <item> GTK_JUSTIFY_FILL
3089 </itemize>
3090
3091 The label widget is also capable of line wrapping the text
3092 automatically. This can be activated using:
3093
3094 <tscreen><verb>
3095 void gtk_label_set_line_wrap (GtkLabel *label,
3096                               gboolean  wrap);
3097 </verb></tscreen>
3098
3099 The <//wrap/ argument takes a TRUE or FALSE value.
3100
3101 If you want your label underlined, then you can set a pattern on the
3102 label:
3103
3104 <tscreen><verb>
3105 void       gtk_label_set_pattern   (GtkLabel          *label,
3106                                     const gchar       *pattern);
3107 </verb></tscreen>
3108
3109 The pattern argument indicates how the underlining should look. It
3110 consists of a string of underscore and space characters. An underscore
3111 indicates that the corresponding character in the label should be
3112 underlined. For example, the string <verb/"__     __"/ would underline the
3113 first two characters and eigth and ninth characters.
3114
3115 Below is a short example to illustrate these functions. This example
3116 makes use of the Frame widget to better demonstrate the label
3117 styles. You can ignore this for now as the <ref id="sec_Frames"
3118 name="Frame"> widget is explained later on.
3119
3120 <tscreen><verb>
3121 /* example-start label label.c */
3122
3123 #include <gtk/gtk.h>
3124
3125 int main( int   argc,
3126           char *argv[] )
3127 {
3128   static GtkWidget *window = NULL;
3129   GtkWidget *hbox;
3130   GtkWidget *vbox;
3131   GtkWidget *frame;
3132   GtkWidget *label;
3133
3134   /* Initialise GTK */
3135   gtk_init(&amp;argc, &amp;argv);
3136
3137   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3138   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3139                       GTK_SIGNAL_FUNC(gtk_main_quit),
3140                       NULL);
3141
3142   gtk_window_set_title (GTK_WINDOW (window), "Label");
3143   vbox = gtk_vbox_new (FALSE, 5);
3144   hbox = gtk_hbox_new (FALSE, 5);
3145   gtk_container_add (GTK_CONTAINER (window), hbox);
3146   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3147   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3148   
3149   frame = gtk_frame_new ("Normal Label");
3150   label = gtk_label_new ("This is a Normal label");
3151   gtk_container_add (GTK_CONTAINER (frame), label);
3152   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3153   
3154   frame = gtk_frame_new ("Multi-line Label");
3155   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3156                          "Third line");
3157   gtk_container_add (GTK_CONTAINER (frame), label);
3158   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3159   
3160   frame = gtk_frame_new ("Left Justified Label");
3161   label = gtk_label_new ("This is a Left-Justified\n" \
3162                          "Multi-line label.\nThird      line");
3163   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3164   gtk_container_add (GTK_CONTAINER (frame), label);
3165   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3166   
3167   frame = gtk_frame_new ("Right Justified Label");
3168   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3169                          "Fourth line, (j/k)");
3170   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3171   gtk_container_add (GTK_CONTAINER (frame), label);
3172   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3173
3174   vbox = gtk_vbox_new (FALSE, 5);
3175   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3176   frame = gtk_frame_new ("Line wrapped label");
3177   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3178                          "should not be taking up the entire             " /* big space to test spacing */\
3179                          "width allocated to it, but automatically " \
3180                          "wraps the words to fit.  " \
3181                          "The time has come, for all good men, to come to " \
3182                          "the aid of their party.  " \
3183                          "The sixth sheik's six sheep's sick.\n" \
3184                          "     It supports multiple paragraphs correctly, " \
3185                          "and  correctly   adds "\
3186                          "many          extra  spaces. ");
3187   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3188   gtk_container_add (GTK_CONTAINER (frame), label);
3189   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3190   
3191   frame = gtk_frame_new ("Filled, wrapped label");
3192   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3193                          "It should be taking "\
3194                          "up the entire              width allocated to it.  " \
3195                          "Here is a seneance to prove "\
3196                          "my point.  Here is another sentence. "\
3197                          "Here comes the sun, do de do de do.\n"\
3198                          "    This is a new paragraph.\n"\
3199                          "    This is another newer, longer, better " \
3200                          "paragraph.  It is coming to an end, "\
3201                          "unfortunately.");
3202   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3203   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3204   gtk_container_add (GTK_CONTAINER (frame), label);
3205   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3206   
3207   frame = gtk_frame_new ("Underlined label");
3208   label = gtk_label_new ("This label is underlined!\n"
3209                          "This one is underlined in quite a funky fashion");
3210   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3211   gtk_label_set_pattern (GTK_LABEL (label),
3212                          "_________________________ _ _________ _ ______     __ _______ ___");
3213   gtk_container_add (GTK_CONTAINER (frame), label);
3214   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3215   
3216   gtk_widget_show_all (window);
3217
3218   gtk_main ();
3219   
3220   return(0);
3221 }
3222 /* example-end */
3223 </verb></tscreen>
3224
3225 <!-- ----------------------------------------------------------------- -->
3226 <sect1> Arrows
3227 <p>
3228 The Arrow widget draws an arrowhead, facing in a number of possible
3229 directions and having a number of possible styles. It can be very
3230 useful when placed on a button in many applications.
3231
3232 There are only two functions for manipulating an Arrow widget:
3233
3234 <tscreen><verb>
3235 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3236                           GtkShadowType  shadow_type );
3237
3238 void gtk_arrow_set( GtkArrow      *arrow,
3239                     GtkArrowType   arrow_type,
3240                     GtkShadowType  shadow_type );
3241 </verb></tscreen>
3242
3243 The first creates a new arrow widget with the indicated type and
3244 appearance. The second allows these values to be altered
3245 retrospectively. The <tt/arrow_type/ argument may take one of the
3246 following values:
3247
3248 <itemize>
3249 <item> GTK_ARROW_UP
3250 <item> GTK_ARROW_DOWN
3251 <item> GTK_ARROW_LEFT
3252 <item> GTK_ARROW_RIGHT
3253 </itemize>
3254
3255 These values obviously indicate the direction in which the arrow will
3256 point. The <tt/shadow_type/ argument may take one of these values:
3257
3258 <itemize>
3259 <item> GTK_SHADOW_IN
3260 <item> GTK_SHADOW_OUT (the default)
3261 <item> GTK_SHADOW_ETCHED_IN
3262 <item> GTK_SHADOW_ETCHED_OUT
3263 </itemize>
3264
3265 Here's a brief example to illustrate their use.
3266
3267 <tscreen><verb>
3268 /* example-start arrow arrow.c */
3269
3270 #include <gtk/gtk.h>
3271
3272 /* Create an Arrow widget with the specified parameters
3273  * and pack it into a button */
3274 GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3275                                 GtkShadowType shadow_type )
3276 {
3277   GtkWidget *button;
3278   GtkWidget *arrow;
3279
3280   button = gtk_button_new();
3281   arrow = gtk_arrow_new (arrow_type, shadow_type);
3282
3283   gtk_container_add (GTK_CONTAINER (button), arrow);
3284   
3285   gtk_widget_show(button);
3286   gtk_widget_show(arrow);
3287
3288   return(button);
3289 }
3290
3291 int main( int   argc,
3292           char *argv[] )
3293 {
3294   /* GtkWidget is the storage type for widgets */
3295   GtkWidget *window;
3296   GtkWidget *button;
3297   GtkWidget *box;
3298
3299   /* Initialize the toolkit */
3300   gtk_init (&amp;argc, &amp;argv);
3301
3302   /* Create a new window */
3303   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3304
3305   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3306
3307   /* It's a good idea to do this for all windows. */
3308   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3309                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3310
3311   /* Sets the border width of the window. */
3312   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3313
3314   /* Create a box to hold the arrows/buttons */
3315   box = gtk_hbox_new (FALSE, 0);
3316   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3317   gtk_container_add (GTK_CONTAINER (window), box);
3318
3319   /* Pack and show all our widgets */
3320   gtk_widget_show(box);
3321
3322   button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN);
3323   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3324
3325   button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3326   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3327   
3328   button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3329   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3330   
3331   button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3332   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3333   
3334   gtk_widget_show (window);
3335   
3336   /* Rest in gtk_main and wait for the fun to begin! */
3337   gtk_main ();
3338   
3339   return(0);
3340 }
3341 /* example-end */
3342 </verb></tscreen>
3343
3344 <!-- ----------------------------------------------------------------- -->
3345 <sect1>The Tooltips Widget
3346 <p>
3347 These are the little text strings that pop up when you leave your
3348 pointer over a button or other widget for a few seconds. They are easy
3349 to use, so I will just explain them without giving an example. If you
3350 want to see some code, take a look at the testgtk.c program
3351 distributed with GTK.
3352
3353 Widgets that do not receieve events (widgets that do not have their
3354 own window) will not work with tooltips.
3355
3356 The first call you will use creates a new tooltip. You only need to do
3357 this once for a set of tooltips as the <tt/GtkTooltip/ object this
3358 function returns can be used to create multiple tooltips.
3359
3360 <tscreen><verb>
3361 GtkTooltips *gtk_tooltips_new( void );
3362 </verb></tscreen>
3363
3364 Once you have created a new tooltip, and the widget you wish to use it
3365 on, simply use this call to set it:
3366
3367 <tscreen><verb>
3368 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3369                            GtkWidget   *widget,
3370                            const gchar *tip_text,
3371                            const gchar *tip_private );
3372 </verb></tscreen>
3373
3374 The first argument is the tooltip you've already created, followed by
3375 the widget you wish to have this tooltip pop up for, and the text you
3376 wish it to say. The last argument is a text string that can be used as
3377 an identifier when using GtkTipsQuery to implement context sensitive
3378 help. For now, you can set it to NULL.
3379
3380 <!-- TODO: sort out what how to do the context sensitive help -->
3381
3382 Here's a short example:
3383
3384 <tscreen><verb>
3385 GtkTooltips *tooltips;
3386 GtkWidget *button;
3387 .
3388 .
3389 .
3390 tooltips = gtk_tooltips_new ();
3391 button = gtk_button_new_with_label ("button 1");
3392 .
3393 .
3394 .
3395 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3396 </verb></tscreen>
3397
3398 There are other calls that can be used with tooltips. I will just list
3399 them with a brief description of what they do.
3400
3401 <tscreen><verb>
3402 void gtk_tooltips_enable( GtkTooltips *tooltips );
3403 </verb></tscreen>
3404
3405 Enable a disabled set of tooltips.
3406
3407 <tscreen><verb>
3408 void gtk_tooltips_disable( GtkTooltips *tooltips );
3409 </verb></tscreen>
3410
3411 Disable an enabled set of tooltips.
3412
3413 <tscreen><verb>
3414 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3415                              gint         delay );
3416
3417 </verb></tscreen>
3418
3419 Sets how many milliseconds you have to hold your pointer over the
3420 widget before the tooltip will pop up. The default is 500
3421 milliseconds (half a second).
3422
3423 <tscreen><verb>
3424 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3425                               GdkColor    *background,
3426                               GdkColor    *foreground );
3427 </verb></tscreen>
3428
3429 Set the foreground and background color of the tooltips.
3430
3431 And that's all the functions associated with tooltips. More than
3432 you'll ever want to know :-)
3433
3434 <!-- ----------------------------------------------------------------- -->
3435 <sect1> Progress Bars <label id="sec_ProgressBar">
3436 <p>
3437 Progress bars are used to show the status of an operation. They are
3438 pretty easy to use, as you will see with the code below. But first
3439 lets start out with the calls to create a new progress bar.
3440
3441 There are two ways to create a progress bar, one simple that takes
3442 no arguments, and one that takes a GtkAdjustment object as an
3443 argument. If the former is used, the progress bar creates its own
3444 adjustment object.
3445
3446 <tscreen><verb>
3447 GtkWidget *gtk_progress_bar_new( void );
3448
3449 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3450 </verb></tscreen>
3451
3452 The second method has the advantage that we can use the adjustment
3453 object to specify our own range parameters for the progress bar.
3454
3455 The adjustment of a progress object can be changed dynamically using:
3456
3457 <tscreen><verb>
3458 void gtk_progress_set_adjustment( GtkProgress   *progress,
3459                                   GtkAdjustment *adjustment );
3460 </verb></tscreen>
3461
3462 Now that the progress bar has been created we can use it.
3463
3464 <tscreen><verb>
3465 void gtk_progress_bar_update( GtkProgressBar *pbar,
3466                               gfloat          percentage );
3467 </verb></tscreen>
3468
3469 The first argument is the progress bar you wish to operate on, and the
3470 second argument is the amount 'completed', meaning the amount the
3471 progress bar has been filled from 0-100%. This is passed to the
3472 function as a real number ranging from 0 to 1.
3473
3474 GTK v1.2 has added new functionality to the progress bar that enables
3475 it to display its value in different ways, and to inform the user of
3476 its current value and its range.
3477
3478 A progress bar may be set to one of a number of orientations using the
3479 function
3480
3481 <tscreen><verb>
3482 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3483                                        GtkProgressBarOrientation orientation );
3484 </verb></tscreen>
3485
3486 Where the <tt/orientation/ argument may take one of the following
3487 values to indicate the direction in which the progress bar moves:
3488
3489 <itemize>
3490 <item> GTK_PROGRESS_LEFT_TO_RIGHT
3491 <item> GTK_PROGRESS_RIGHT_TO_LEFT
3492 <item> GTK_PROGRESS_BOTTOM_TO_TOP
3493 <item> GTK_PROGRESS_TOP_TO_BOTTOM
3494 </itemize>
3495
3496 When used as a measure of how far a process has progressed, the
3497 GtkProgressBar can be set to display its value in either a continuous
3498 or discrete mode. In continuous mode, the progress bar is updated for
3499 each value. In discrete mode, the progress bar is updated in a number
3500 of discrete blocks. The number of blocks is also configurable.
3501
3502 The style of a progress bar can be set using the following function.
3503
3504 <tscreen><verb>
3505 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3506                                      GtkProgressBarStyle  style );
3507 </verb></tscreen>
3508
3509 The <tt/style/ parameter can take one of two values:
3510
3511 <itemize>
3512 <item>GTK_PROGRESS_CONTINUOUS
3513 <item>GTK_PROGRESS_DISCRETE
3514 </itemize>
3515
3516 The number of discrete blocks can be set by calling
3517
3518 <tscreen><verb>
3519 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3520                                            guint           blocks );
3521 </verb></tscreen>
3522
3523 As well as indicating the amount of progress that has occured, the
3524 progress bar may be set to just indicate that there is some
3525 activity. This can be useful in situations where progress cannot be
3526 measured against a value range. Activity mode is not effected by the
3527 bar style that is described above, and overrides it.This mode is
3528 selected by the following function.
3529
3530 <tscreen><verb>
3531 void gtk_progress_set_activity_mode( GtkProgress *progress,
3532                                      guint        activity_mode );
3533 </verb></tscreen>
3534
3535 The step size of the activity indicator, and the number of blocks are
3536 set using the following functions.
3537
3538 <tscreen><verb>
3539 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3540                                          guint           step );
3541
3542 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3543                                            guint           blocks );
3544 </verb></tscreen>
3545
3546 When in continuous mode, the progress bar can also display a
3547 configurable text string within its trough, using the following
3548 function.
3549
3550 <tscreen><verb>
3551 void gtk_progress_set_format_string( GtkProgress *progress,
3552                                      gchar       *format);
3553 </verb></tscreen>
3554
3555 The <tt/format/ argument is similiar to one that would be used in a C
3556 <tt/printf/ statement. The following directives may be used within the
3557 format string:
3558
3559 <itemize>
3560 <item> %p - percentage
3561 <item> %v - value
3562 <item> %l - lower range value
3563 <item> %u - upper range value
3564 </itemize>
3565
3566 The displaying of this text string can be toggled using:
3567
3568 <tscreen><verb>
3569 void gtk_progress_set_show_text( GtkProgress *progress,
3570                                  gint         show_text );
3571 </verb></tscreen>
3572
3573 The <tt/show_text/ argument is a boolean TRUE/FALSE value. The
3574 appearance of the text can be modified further using:
3575
3576 <tscreen><verb>
3577 void gtk_progress_set_text_alignment( GtkProgress   *progress,
3578                                       gfloat         x_align,
3579                                       gfloat         y_align );
3580 </verb></tscreen>
3581
3582 The <tt/x_align/ and <tt/y_align/ arguments take a value between 0.0
3583 and 1.0. Their value indicates the position of the text string within
3584 the trough. Values of 0.0 for both would place the string in the top
3585 left hand corner; values of 0.5 (the default) centres the text, and
3586 values of 1.0 places the text in the lower right hand corner.
3587
3588 The current text setting of a progress object can be retrieved using
3589 the current or a specified adjustment value using the following two
3590 functions. The character string returned by these functions should be
3591 freed by the application (using the g_free() function). These
3592 functions return the formatted string that would be displayed within
3593 the trough.
3594
3595 <tscreen><verb>
3596 gchar *gtk_progress_get_current_text( GtkProgress   *progress );
3597
3598 gchar *gtk_progress_get_text_from_value( GtkProgress *progress,
3599                                          gfloat       value );
3600 </verb></tscreen>
3601
3602 There is yet another way to change the range and value of a progress
3603 object using the following function:
3604
3605 <tscreen><verb>
3606 void gtk_progress_configure( GtkProgress  *progress,
3607                              gfloat        value,
3608                              gfloat        min,
3609                              gfloat        max );
3610 </verb></tscreen>
3611
3612 This function provides quite a simple interface to the range and value
3613 of a progress object.
3614
3615 The remaining functions can be used to get and set the current value
3616 of a progess object in various types and formats:
3617
3618 <tscreen><verb>
3619 void gtk_progress_set_percentage( GtkProgress *progress,
3620                                   gfloat       percentage );
3621
3622 void gtk_progress_set_value( GtkProgress *progress,
3623                              gfloat       value );
3624
3625 gfloat gtk_progress_get_value( GtkProgress *progress );
3626
3627 gfloat gtk_progress_get_current_percentage( GtkProgress *progress );
3628
3629 gfloat gtk_progress_get_percentage_from_value( GtkProgress *progress,
3630                                                gfloat       value );
3631 </verb></tscreen>
3632
3633 These functions are pretty self explanatory. The last function uses
3634 the the adjustment of the specified progess object to compute the
3635 percentage value of the given range value.
3636
3637 Progress Bars are usually used with timeouts or other such functions
3638 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3639 Functions">) to give the illusion of multitasking. All will employ the
3640 gtk_progress_bar_update function in the same manner.
3641
3642 Here is an example of the progress bar, updated using timeouts. This
3643 code also shows you how to reset the Progress Bar.
3644
3645 <tscreen><verb>
3646 /* example-start progressbar progressbar.c */
3647
3648 #include <gtk/gtk.h>
3649
3650 typedef struct _ProgressData {
3651     GtkWidget *window;
3652     GtkWidget *pbar;
3653     int timer;
3654 } ProgressData;
3655
3656 /* Update the value of the progress bar so that we get
3657  * some movement */
3658 gint progress_timeout( gpointer data )
3659 {
3660     gfloat new_val;
3661     GtkAdjustment *adj;
3662
3663     /* Calculate the value of the progress bar using the
3664      * value range set in the adjustment object */
3665
3666     new_val = gtk_progress_get_value( GTK_PROGRESS(data) ) + 1;
3667
3668     adj = GTK_PROGRESS (data)->adjustment;
3669     if (new_val > adj->upper)
3670       new_val = adj->lower;
3671
3672     /* Set the new value */
3673     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3674
3675     /* As this is a timeout function, return TRUE so that it
3676      * continues to get called */
3677     return(TRUE);
3678
3679
3680 /* Callback that toggles the text display within the progress
3681  * bar trough */
3682 void toggle_show_text( GtkWidget    *widget,
3683                        ProgressData *pdata )
3684 {
3685     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3686                                 GTK_TOGGLE_BUTTON (widget)->active);
3687 }
3688
3689 /* Callback that toggles the activity mode of the progress
3690  * bar */
3691 void toggle_activity_mode( GtkWidget    *widget,
3692                            ProgressData *pdata )
3693 {
3694     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3695                                     GTK_TOGGLE_BUTTON (widget)->active);
3696 }
3697
3698 /* Callback that toggles the continuous mode of the progress
3699  * bar */
3700 void set_continuous_mode( GtkWidget    *widget,
3701                           ProgressData *pdata )
3702 {
3703     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3704                                     GTK_PROGRESS_CONTINUOUS);
3705 }
3706
3707 /* Callback that toggles the discrete mode of the progress
3708  * bar */
3709 void set_discrete_mode( GtkWidget    *widget,
3710                         ProgressData *pdata )
3711 {
3712     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3713                                     GTK_PROGRESS_DISCRETE);
3714 }
3715  
3716 /* Clean up allocated memory and remove the timer */
3717 void destroy_progress( GtkWidget     *widget,
3718                        ProgressData *pdata)
3719 {
3720     gtk_timeout_remove (pdata->timer);
3721     pdata->timer = 0;
3722     pdata->window = NULL;
3723     g_free(pdata);
3724     gtk_main_quit();
3725 }
3726
3727 int main( int   argc,
3728           char *argv[])
3729 {
3730     ProgressData *pdata;
3731     GtkWidget *align;
3732     GtkWidget *separator;
3733     GtkWidget *table;
3734     GtkAdjustment *adj;
3735     GtkWidget *button;
3736     GtkWidget *check;
3737     GtkWidget *vbox;
3738
3739     gtk_init (&amp;argc, &amp;argv);
3740
3741     /* Allocate memory for the data that is passwd to the callbacks */
3742     pdata = g_malloc( sizeof(ProgressData) );
3743   
3744     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3745     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3746
3747     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3748                         GTK_SIGNAL_FUNC (destroy_progress),
3749                         pdata);
3750     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3751     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3752
3753     vbox = gtk_vbox_new (FALSE, 5);
3754     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3755     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3756     gtk_widget_show(vbox);
3757   
3758     /* Create a centering alignment object */
3759     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3760     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3761     gtk_widget_show(align);
3762
3763     /* Create a GtkAdjusment object to hold the range of the
3764      * progress bar */
3765     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3766
3767     /* Create the GtkProgressBar using the adjustment */
3768     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3769
3770     /* Set the format of the string that can be displayed in the
3771      * trough of the progress bar:
3772      * %p - percentage
3773      * %v - value
3774      * %l - lower range value
3775      * %u - upper range value */
3776     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3777                                     "%v from [%l-%u] (=%p%%)");
3778     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3779     gtk_widget_show(pdata->pbar);
3780
3781     /* Add a timer callback to update the value of the progress bar */
3782     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3783
3784     separator = gtk_hseparator_new ();
3785     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3786     gtk_widget_show(separator);
3787
3788     /* rows, columns, homogeneous */
3789     table = gtk_table_new (2, 3, FALSE);
3790     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3791     gtk_widget_show(table);
3792
3793     /* Add a check button to select displaying of the trough text */
3794     check = gtk_check_button_new_with_label ("Show text");
3795     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3796                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3797                       5, 5);
3798     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3799                         GTK_SIGNAL_FUNC (toggle_show_text),
3800                         pdata);
3801     gtk_widget_show(check);
3802
3803     /* Add a check button to toggle activity mode */
3804     check = gtk_check_button_new_with_label ("Activity mode");
3805     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3806                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3807                       5, 5);
3808     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3809                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3810                         pdata);
3811     gtk_widget_show(check);
3812
3813     separator = gtk_vseparator_new ();
3814     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3815                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3816                       5, 5);
3817     gtk_widget_show(separator);
3818
3819     /* Add a radio button to select continuous display mode */
3820     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3821     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3822                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3823                       5, 5);
3824     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3825                         GTK_SIGNAL_FUNC (set_continuous_mode),
3826                         pdata);
3827     gtk_widget_show (button);
3828
3829     /* Add a radio button to select discrete display mode */
3830     button = gtk_radio_button_new_with_label(
3831                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3832                "Discrete");
3833     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3834                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3835                       5, 5);
3836     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3837                         GTK_SIGNAL_FUNC (set_discrete_mode),
3838                         pdata);
3839     gtk_widget_show (button);
3840
3841     separator = gtk_hseparator_new ();
3842     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3843     gtk_widget_show(separator);
3844
3845     /* Add a button to exit the program */
3846     button = gtk_button_new_with_label ("close");
3847     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3848                                (GtkSignalFunc) gtk_widget_destroy,
3849                                GTK_OBJECT (pdata->window));
3850     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3851
3852     /* This makes it so the button is the default. */
3853     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3854
3855     /* This grabs this button to be the default button. Simply hitting
3856      * the "Enter" key will cause this button to activate. */
3857     gtk_widget_grab_default (button);
3858     gtk_widget_show(button);
3859
3860     gtk_widget_show (pdata->window);
3861
3862     gtk_main ();
3863     
3864     return(0);
3865 }
3866 /* example-end */
3867 </verb></tscreen>
3868
3869 <!-- ----------------------------------------------------------------- -->
3870 <sect1> Dialogs
3871 <p>
3872 The Dialog widget is very simple, and is actually just a window with a
3873 few things pre-packed into it for you. The structure for a Dialog is:
3874
3875 <tscreen><verb>
3876 struct GtkDialog
3877 {
3878       GtkWindow window;
3879     
3880       GtkWidget *vbox;
3881       GtkWidget *action_area;
3882 };
3883 </verb></tscreen>
3884
3885 So you see, it simply creates a window, and then packs a vbox into the
3886 top, then a separator, and then an hbox for the "action_area".
3887
3888 The Dialog widget can be used for pop-up messages to the user, and
3889 other similar tasks. It is really basic, and there is only one
3890 function for the dialog box, which is:
3891
3892 <tscreen><verb>
3893 GtkWidget *gtk_dialog_new( void );
3894 </verb></tscreen>
3895
3896 So to create a new dialog box, use,
3897
3898 <tscreen><verb>
3899     GtkWidget *window;
3900     window = gtk_dialog_new ();
3901 </verb></tscreen>
3902
3903 This will create the dialog box, and it is now up to you to use it.
3904 you could pack a button in the action_area by doing something like this:
3905
3906 <tscreen><verb>
3907     button = ...
3908     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3909                         button, TRUE, TRUE, 0);
3910     gtk_widget_show (button);
3911 </verb></tscreen>
3912
3913 And you could add to the vbox area by packing, for instance, a label 
3914 in it, try something like this:
3915
3916 <tscreen><verb>
3917     label = gtk_label_new ("Dialogs are groovy");
3918     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3919                         label, TRUE, TRUE, 0);
3920     gtk_widget_show (label);
3921 </verb></tscreen>
3922
3923 As an example in using the dialog box, you could put two buttons in
3924 the action_area, a Cancel button and an Ok button, and a label in the
3925 vbox area, asking the user a question or giving an error etc. Then
3926 you could attach a different signal to each of the buttons and perform
3927 the operation the user selects.
3928
3929 If the simple functionality provided by the default vertical and
3930 horizontal boxes in the two areas does't give you enough control for
3931 your application, then you can simply pack another layout widget into
3932 the boxes provided. For example, you could pack a table into the
3933 vertical box.
3934
3935 <!-- ----------------------------------------------------------------- -->
3936 <sect1> Pixmaps <label id="sec_Pixmaps">
3937 <p>
3938 Pixmaps are data structures that contain pictures. These pictures can
3939 be used in various places, but most visibly as icons on the X-Windows
3940 desktop, or as cursors.
3941
3942 A pixmap which only has 2 colors is called a bitmap, and there are a
3943 few additional routines for handling this common special case.
3944
3945 To understand pixmaps, it would help to understand how X-windows
3946 works. Under X-windows, applications do not need to be running on the
3947 same computer that is interacting with the user. Instead, the various
3948 applications, called "clients", all communicate with a program which
3949 displays the graphics and handles the keyboard and mouse. This
3950 program which interacts directly with the user is called a "display
3951 server" or "X server." Since the communication might take place over
3952 a network, it's important to keep some information with the X server.
3953 Pixmaps, for example, are stored in the memory of the X server. This
3954 means that once pixmap values are set, they don't need to keep getting
3955 transmitted over the network; instead a command is sent to "display
3956 pixmap number XYZ here." Even if you aren't using X-windows with GTK
3957 currently, using constructs such as Pixmaps will make your programs
3958 work acceptably under X-windows.
3959
3960 To use pixmaps in GTK, we must first build a GdkPixmap structure using
3961 routines from the GDK layer. Pixmaps can either be created from
3962 in-memory data, or from data read from a file. We'll go through each
3963 of the calls to create a pixmap.
3964
3965 <tscreen><verb>
3966 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
3967                                         gchar     *data,
3968                                         gint       width,
3969                                         gint       height );
3970 </verb></tscreen>
3971
3972 This routine is used to create a single-plane pixmap (2 colors) from
3973 data in memory. Each bit of the data represents whether that pixel is
3974 off or on. Width and height are in pixels. The GdkWindow pointer is
3975 to the current window, since a pixmap resources are meaningful only in
3976 the context of the screen where it is to be displayed.
3977
3978 <tscreen><verb>
3979 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
3980                                         gchar     *data,
3981                                         gint       width,
3982                                         gint       height,
3983                                         gint       depth,
3984                                         GdkColor  *fg,
3985                                         GdkColor  *bg );
3986 </verb></tscreen>
3987
3988 This is used to create a pixmap of the given depth (number of colors) from
3989 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
3990 background color to use.
3991
3992 <tscreen><verb>
3993 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
3994                                        GdkBitmap  **mask,
3995                                        GdkColor    *transparent_color,
3996                                        const gchar *filename );
3997 </verb></tscreen>
3998
3999 XPM format is a readable pixmap representation for the X Window
4000 System. It is widely used and many different utilities are available
4001 for creating image files in this format. The file specified by
4002 filename must contain an image in that format and it is loaded into
4003 the pixmap structure. The mask specifies which bits of the pixmap are
4004 opaque. All other bits are colored using the color specified by
4005 transparent_color. An example using this follows below.
4006
4007 <tscreen><verb>
4008 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
4009                                          GdkBitmap **mask,
4010                                          GdkColor   *transparent_color,
4011                                          gchar     **data );
4012 </verb></tscreen>
4013
4014 Small images can be incorporated into a program as data in the XPM
4015 format. A pixmap is created using this data, instead of reading it
4016 from a file. An example of such data is
4017
4018 <tscreen><verb>
4019 /* XPM */
4020 static const char * xpm_data[] = {
4021 "16 16 3 1",
4022 "       c None",
4023 ".      c #000000000000",
4024 "X      c #FFFFFFFFFFFF",
4025 "                ",
4026 "   ......       ",
4027 "   .XXX.X.      ",
4028 "   .XXX.XX.     ",
4029 "   .XXX.XXX.    ",
4030 "   .XXX.....    ",
4031 "   .XXXXXXX.    ",
4032 "   .XXXXXXX.    ",
4033 "   .XXXXXXX.    ",
4034 "   .XXXXXXX.    ",
4035 "   .XXXXXXX.    ",
4036 "   .XXXXXXX.    ",
4037 "   .XXXXXXX.    ",
4038 "   .........    ",
4039 "                ",
4040 "                "};
4041 </verb></tscreen>
4042
4043 When we're done using a pixmap and not likely to reuse it again soon,
4044 it is a good idea to release the resource using
4045 gdk_pixmap_unref(). Pixmaps should be considered a precious resource.
4046
4047 Once we've created a pixmap, we can display it as a GTK widget. We
4048 must create a GTK pixmap widget to contain the GDK pixmap. This is
4049 done using
4050
4051 <tscreen><verb>
4052 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
4053                            GdkBitmap *mask );
4054 </verb></tscreen>
4055
4056 The other pixmap widget calls are
4057
4058 <tscreen><verb>
4059 guint gtk_pixmap_get_type( void );
4060
4061 void  gtk_pixmap_set( GtkPixmap  *pixmap,
4062                       GdkPixmap  *val,
4063                       GdkBitmap  *mask );
4064
4065 void  gtk_pixmap_get( GtkPixmap  *pixmap,
4066                       GdkPixmap **val,
4067                       GdkBitmap **mask);
4068 </verb></tscreen>
4069
4070 gtk_pixmap_set is used to change the pixmap that the widget is currently
4071 managing. Val is the pixmap created using GDK.
4072
4073 The following is an example of using a pixmap in a button.
4074
4075 <tscreen><verb>
4076 /* example-start pixmap pixmap.c */
4077
4078 #include <gtk/gtk.h>
4079
4080
4081 /* XPM data of Open-File icon */
4082 static const char * xpm_data[] = {
4083 "16 16 3 1",
4084 "       c None",
4085 ".      c #000000000000",
4086 "X      c #FFFFFFFFFFFF",
4087 "                ",
4088 "   ......       ",
4089 "   .XXX.X.      ",
4090 "   .XXX.XX.     ",
4091 "   .XXX.XXX.    ",
4092 "   .XXX.....    ",
4093 "   .XXXXXXX.    ",
4094 "   .XXXXXXX.    ",
4095 "   .XXXXXXX.    ",
4096 "   .XXXXXXX.    ",
4097 "   .XXXXXXX.    ",
4098 "   .XXXXXXX.    ",
4099 "   .XXXXXXX.    ",
4100 "   .........    ",
4101 "                ",
4102 "                "};
4103
4104
4105 /* when invoked (via signal delete_event), terminates the application.
4106  */
4107 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4108     gtk_main_quit();
4109 }
4110
4111
4112 /* is invoked when the button is clicked.  It just prints a message.
4113  */
4114 void button_clicked( GtkWidget *widget, gpointer data ) {
4115     printf( "button clicked\n" );
4116 }
4117
4118 int main( int argc, char *argv[] )
4119 {
4120     /* GtkWidget is the storage type for widgets */
4121     GtkWidget *window, *pixmapwid, *button;
4122     GdkPixmap *pixmap;
4123     GdkBitmap *mask;
4124     GtkStyle *style;
4125     
4126     /* create the main window, and attach delete_event signal to terminating
4127        the application */
4128     gtk_init( &amp;argc, &amp;argv );
4129     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4130     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
4131                         GTK_SIGNAL_FUNC (close_application), NULL );
4132     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
4133     gtk_widget_show( window );
4134
4135     /* now for the pixmap from gdk */
4136     style = gtk_widget_get_style( window );
4137     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
4138                                            &amp;style->bg[GTK_STATE_NORMAL],
4139                                            (gchar **)xpm_data );
4140
4141     /* a pixmap widget to contain the pixmap */
4142     pixmapwid = gtk_pixmap_new( pixmap, mask );
4143     gtk_widget_show( pixmapwid );
4144
4145     /* a button to contain the pixmap widget */
4146     button = gtk_button_new();
4147     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
4148     gtk_container_add( GTK_CONTAINER(window), button );
4149     gtk_widget_show( button );
4150
4151     gtk_signal_connect( GTK_OBJECT(button), "clicked",
4152                         GTK_SIGNAL_FUNC(button_clicked), NULL );
4153
4154     /* show the window */
4155     gtk_main ();
4156           
4157     return 0;
4158 }
4159 /* example-end */
4160 </verb></tscreen>
4161
4162 To load a file from an XPM data file called icon0.xpm in the current
4163 directory, we would have created the pixmap thus
4164
4165 <tscreen><verb>
4166     /* load a pixmap from a file */
4167     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
4168                                          &amp;style->bg[GTK_STATE_NORMAL],
4169                                          "./icon0.xpm" );
4170     pixmapwid = gtk_pixmap_new( pixmap, mask );
4171     gtk_widget_show( pixmapwid );
4172     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
4173 </verb></tscreen>
4174
4175 A disadvantage of using pixmaps is that the displayed object is always
4176 rectangular, regardless of the image. We would like to create desktops
4177 and applications with icons that have more natural shapes. For
4178 example, for a game interface, we would like to have round buttons to
4179 push. The way to do this is using shaped windows.
4180
4181 A shaped window is simply a pixmap where the background pixels are
4182 transparent. This way, when the background image is multi-colored, we
4183 don't overwrite it with a rectangular, non-matching border around our
4184 icon. The following example displays a full wheelbarrow image on the
4185 desktop.
4186
4187 <tscreen><verb>
4188 /* example-start wheelbarrow wheelbarrow.c */
4189
4190 #include <gtk/gtk.h>
4191
4192 /* XPM */
4193 static char * WheelbarrowFull_xpm[] = {
4194 "48 48 64 1",
4195 "       c None",
4196 ".      c #DF7DCF3CC71B",
4197 "X      c #965875D669A6",
4198 "o      c #71C671C671C6",
4199 "O      c #A699A289A699",
4200 "+      c #965892489658",
4201 "@      c #8E38410330C2",
4202 "#      c #D75C7DF769A6",
4203 "$      c #F7DECF3CC71B",
4204 "%      c #96588A288E38",
4205 "&amp;      c #A69992489E79",
4206 "*      c #8E3886178E38",
4207 "=      c #104008200820",
4208 "-      c #596510401040",
4209 ";      c #C71B30C230C2",
4210 ":      c #C71B9A699658",
4211 ">      c #618561856185",
4212 ",      c #20811C712081",
4213 "<      c #104000000000",
4214 "1      c #861720812081",
4215 "2      c #DF7D4D344103",
4216 "3      c #79E769A671C6",
4217 "4      c #861782078617",
4218 "5      c #41033CF34103",
4219 "6      c #000000000000",
4220 "7      c #49241C711040",
4221 "8      c #492445144924",
4222 "9      c #082008200820",
4223 "0      c #69A618611861",
4224 "q      c #B6DA71C65144",
4225 "w      c #410330C238E3",
4226 "e      c #CF3CBAEAB6DA",
4227 "r      c #71C6451430C2",
4228 "t      c #EFBEDB6CD75C",
4229 "y      c #28A208200820",
4230 "u      c #186110401040",
4231 "i      c #596528A21861",
4232 "p      c #71C661855965",
4233 "a      c #A69996589658",
4234 "s      c #30C228A230C2",
4235 "d      c #BEFBA289AEBA",
4236 "f      c #596545145144",
4237 "g      c #30C230C230C2",
4238 "h      c #8E3882078617",
4239 "j      c #208118612081",
4240 "k      c #38E30C300820",
4241 "l      c #30C2208128A2",
4242 "z      c #38E328A238E3",
4243 "x      c #514438E34924",
4244 "c      c #618555555965",
4245 "v      c #30C2208130C2",
4246 "b      c #38E328A230C2",
4247 "n      c #28A228A228A2",
4248 "m      c #41032CB228A2",
4249 "M      c #104010401040",
4250 "N      c #492438E34103",
4251 "B      c #28A2208128A2",
4252 "V      c #A699596538E3",
4253 "C      c #30C21C711040",
4254 "Z      c #30C218611040",
4255 "A      c #965865955965",
4256 "S      c #618534D32081",
4257 "D      c #38E31C711040",
4258 "F      c #082000000820",
4259 "                                                ",
4260 "          .XoO                                  ",
4261 "         +@#$%o&amp;                                ",
4262 "         *=-;#::o+                              ",
4263 "           >,<12#:34                            ",
4264 "             45671#:X3                          ",
4265 "               +89<02qwo                        ",
4266 "e*                >,67;ro                       ",
4267 "ty>                 459@>+&amp;&amp;                    ",
4268 "$2u+                  ><ipas8*                  ",
4269 "%$;=*                *3:.Xa.dfg>                ",
4270 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
4271 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
4272 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
4273 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
4274 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
4275 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
4276 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
4277 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
4278 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
4279 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
4280 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
4281 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
4282 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
4283 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
4284 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
4285 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
4286 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
4287 "              p;<69BvwwsszslllbBlllllllu<5+     ",
4288 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
4289 "               c1-699Blvlllllu7k96MMMg4         ",
4290 "               *10y8n6FjvllllB<166668           ",
4291 "                S-kg+>666<M<996-y6n<8*          ",
4292 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
4293 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
4294 "                 N-k-<>     >=01-kuu666>        ",
4295 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
4296 "                 Ou0<>       o66y<ulw<66&amp;       ",
4297 "                  *kk5       >66By7=xu664       ",
4298 "                   <<M4      466lj<Mxu66o       ",
4299 "                   *>>       +66uv,zN666*       ",
4300 "                              566,xxj669        ",
4301 "                              4666FF666>        ",
4302 "                               >966666M         ",
4303 "                                oM6668+         ",
4304 "                                  *4            ",
4305 "                                                ",
4306 "                                                "};
4307
4308
4309 /* When invoked (via signal delete_event), terminates the application */
4310 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4311     gtk_main_quit();
4312 }
4313
4314 int main (int argc, char *argv[])
4315 {
4316     /* GtkWidget is the storage type for widgets */
4317     GtkWidget *window, *pixmap, *fixed;
4318     GdkPixmap *gdk_pixmap;
4319     GdkBitmap *mask;
4320     GtkStyle *style;
4321     GdkGC *gc;
4322     
4323     /* Create the main window, and attach delete_event signal to terminate
4324      * the application.  Note that the main window will not have a titlebar
4325      * since we're making it a popup. */
4326     gtk_init (&amp;argc, &amp;argv);
4327     window = gtk_window_new( GTK_WINDOW_POPUP );
4328     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4329                         GTK_SIGNAL_FUNC (close_application), NULL);
4330     gtk_widget_show (window);
4331
4332     /* Now for the pixmap and the pixmap widget */
4333     style = gtk_widget_get_default_style();
4334     gc = style->black_gc;
4335     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
4336                                              &amp;style->bg[GTK_STATE_NORMAL],
4337                                              WheelbarrowFull_xpm );
4338     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
4339     gtk_widget_show( pixmap );
4340
4341     /* To display the pixmap, we use a fixed widget to place the pixmap */
4342     fixed = gtk_fixed_new();
4343     gtk_widget_set_usize( fixed, 200, 200 );
4344     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
4345     gtk_container_add( GTK_CONTAINER(window), fixed );
4346     gtk_widget_show( fixed );
4347
4348     /* This masks out everything except for the image itself */
4349     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
4350     
4351     /* show the window */
4352     gtk_widget_set_uposition( window, 20, 400 );
4353     gtk_widget_show( window );
4354     gtk_main ();
4355           
4356     return(0);
4357 }
4358 /* example-end */
4359 </verb></tscreen>
4360
4361 To make the wheelbarrow image sensitive, we could attach the button
4362 press event signal to make it do something. The following few lines
4363 would make the picture sensitive to a mouse button being pressed which
4364 makes the application terminate.
4365
4366 <tscreen><verb>
4367     gtk_widget_set_events( window,
4368                           gtk_widget_get_events( window ) |
4369                           GDK_BUTTON_PRESS_MASK );
4370
4371    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
4372                        GTK_SIGNAL_FUNC(close_application), NULL );
4373 </verb></tscreen>
4374
4375 <!-- ----------------------------------------------------------------- -->
4376 <sect1>Rulers
4377 <p>
4378 Ruler widgets are used to indicate the location of the mouse pointer
4379 in a given window. A window can have a vertical ruler spanning across
4380 the width and a horizontal ruler spanning down the height. A small
4381 triangular indicator on the ruler shows the exact location of the
4382 pointer relative to the ruler.
4383
4384 A ruler must first be created. Horizontal and vertical rulers are
4385 created using
4386
4387 <tscreen><verb>
4388 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4389
4390 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4391 </verb></tscreen>
4392
4393 Once a ruler is created, we can define the unit of measurement. Units
4394 of measure for rulers can be GTK_PIXELS, GTK_INCHES or
4395 GTK_CENTIMETERS. This is set using
4396
4397 <tscreen><verb>
4398 void gtk_ruler_set_metric( GtkRuler      *ruler,
4399                            GtkMetricType  metric );
4400 </verb></tscreen>
4401
4402 The default measure is GTK_PIXELS.
4403
4404 <tscreen><verb>
4405     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4406 </verb></tscreen>
4407
4408 Other important characteristics of a ruler are how to mark the units
4409 of scale and where the position indicator is initially placed. These
4410 are set for a ruler using
4411
4412 <tscreen><verb>
4413 void gtk_ruler_set_range( GtkRuler *ruler,
4414                           gfloat    lower,
4415                           gfloat    upper,
4416                           gfloat    position,
4417                           gfloat    max_size );
4418 </verb></tscreen>
4419
4420 The lower and upper arguments define the extent of the ruler, and
4421 max_size is the largest possible number that will be displayed.
4422 Position defines the initial position of the pointer indicator within
4423 the ruler.
4424
4425 A vertical ruler can span an 800 pixel wide window thus
4426
4427 <tscreen><verb>
4428     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4429 </verb></tscreen>
4430
4431 The markings displayed on the ruler will be from 0 to 800, with a
4432 number for every 100 pixels. If instead we wanted the ruler to range
4433 from 7 to 16, we would code
4434
4435 <tscreen><verb>
4436     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4437 </verb></tscreen>
4438
4439 The indicator on the ruler is a small triangular mark that indicates
4440 the position of the pointer relative to the ruler. If the ruler is
4441 used to follow the mouse pointer, the motion_notify_event signal
4442 should be connected to the motion_notify_event method of the ruler.
4443 To follow all mouse movements within a window area, we would use
4444
4445 <tscreen><verb>
4446 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4447
4448     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4449            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4450            GTK_OBJECT(ruler) );
4451 </verb></tscreen>
4452
4453 The following example creates a drawing area with a horizontal ruler
4454 above it and a vertical ruler to the left of it. The size of the
4455 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4456 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4457 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4458 Placement of the drawing area and the rulers is done using a table.
4459
4460 <tscreen><verb>
4461 /* example-start rulers rulers.c */
4462
4463 #include <gtk/gtk.h>
4464
4465 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4466
4467 #define XSIZE  600
4468 #define YSIZE  400
4469
4470 /* This routine gets control when the close button is clicked */
4471 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4472     gtk_main_quit();
4473 }
4474
4475 /* The main routine */
4476 int main( int argc, char *argv[] ) {
4477     GtkWidget *window, *table, *area, *hrule, *vrule;
4478
4479     /* Initialize GTK and create the main window */
4480     gtk_init( &amp;argc, &amp;argv );
4481
4482     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4483     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4484             GTK_SIGNAL_FUNC( close_application ), NULL);
4485     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4486
4487     /* Create a table for placing the ruler and the drawing area */
4488     table = gtk_table_new( 3, 2, FALSE );
4489     gtk_container_add( GTK_CONTAINER(window), table );
4490
4491     area = gtk_drawing_area_new();
4492     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4493     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4494                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4495     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK |
4496                                  GDK_POINTER_MOTION_HINT_MASK );
4497
4498     /* The horizontal ruler goes on top. As the mouse moves across the
4499      * drawing area, a motion_notify_event is passed to the
4500      * appropriate event handler for the ruler. */
4501     hrule = gtk_hruler_new();
4502     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4503     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4504     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4505                                (GtkSignalFunc)EVENT_METHOD(hrule,
4506                                                         motion_notify_event),
4507                                GTK_OBJECT(hrule) );
4508     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4509     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4510                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4511     
4512     /* The vertical ruler goes on the left. As the mouse moves across
4513      * the drawing area, a motion_notify_event is passed to the
4514      * appropriate event handler for the ruler. */
4515     vrule = gtk_vruler_new();
4516     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4517     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4518     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4519                                (GtkSignalFunc)
4520                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->
4521                                                          motion_notify_event,
4522                                GTK_OBJECT(vrule) );
4523     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4524                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4525
4526     /* Now show everything */
4527     gtk_widget_show( area );
4528     gtk_widget_show( hrule );
4529     gtk_widget_show( vrule );
4530     gtk_widget_show( table );
4531     gtk_widget_show( window );
4532     gtk_main();
4533
4534     return(0);
4535 }
4536 /* example-end */
4537 </verb></tscreen>
4538
4539 <!-- ----------------------------------------------------------------- -->
4540 <sect1>Statusbars
4541 <p>
4542 Statusbars are simple widgets used to display a text message. They
4543 keep a stack of the messages pushed onto them, so that popping the
4544 current message will re-display the previous text message.
4545
4546 In order to allow different parts of an application to use the same
4547 statusbar to display messages, the statusbar widget issues Context
4548 Identifiers which are used to identify different 'users'. The message
4549 on top of the stack is the one displayed, no matter what context it is
4550 in. Messages are stacked in last-in-first-out order, not context
4551 identifier order.
4552
4553 A statusbar is created with a call to:
4554
4555 <tscreen><verb>
4556 GtkWidget *gtk_statusbar_new( void );
4557 </verb></tscreen>
4558
4559 A new Context Identifier is requested using a call to the following 
4560 function with a short textual description of the context:
4561
4562 <tscreen><verb>
4563 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4564                                     const gchar  *context_description );
4565 </verb></tscreen>
4566
4567 There are three functions that can operate on statusbars:
4568
4569 <tscreen><verb>
4570 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4571                           guint         context_id,
4572                           gchar        *text );
4573
4574 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4575                         guint         context_id );
4576
4577 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4578                            guint         context_id,
4579                            guint         message_id ); 
4580 </verb></tscreen>
4581
4582 The first, gtk_statusbar_push, is used to add a new message to the
4583 statusbar.  It returns a Message Identifier, which can be passed later
4584 to the function gtk_statusbar_remove to remove the message with the
4585 given Message and Context Identifiers from the statusbar's stack.
4586
4587 The function gtk_statusbar_pop removes the message highest in the
4588 stack with the given Context Identifier.
4589
4590 The following example creates a statusbar and two buttons, one for
4591 pushing items onto the statusbar, and one for popping the last item
4592 back off.
4593
4594 <tscreen><verb>
4595 /* example-start statusbar statusbar.c */
4596
4597 #include <gtk/gtk.h>
4598 #include <glib.h>
4599
4600 GtkWidget *status_bar;
4601
4602 void push_item (GtkWidget *widget, gpointer data)
4603 {
4604   static int count = 1;
4605   char buff[20];
4606
4607   g_snprintf(buff, 20, "Item %d", count++);
4608   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4609
4610   return;
4611 }
4612
4613 void pop_item (GtkWidget *widget, gpointer data)
4614 {
4615   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4616   return;
4617 }
4618
4619 int main (int argc, char *argv[])
4620 {
4621
4622     GtkWidget *window;
4623     GtkWidget *vbox;
4624     GtkWidget *button;
4625
4626     gint context_id;
4627
4628     gtk_init (&amp;argc, &amp;argv);
4629
4630     /* create a new window */
4631     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4632     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4633     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4634     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4635                        (GtkSignalFunc) gtk_exit, NULL);
4636  
4637     vbox = gtk_vbox_new(FALSE, 1);
4638     gtk_container_add(GTK_CONTAINER(window), vbox);
4639     gtk_widget_show(vbox);
4640           
4641     status_bar = gtk_statusbar_new();      
4642     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4643     gtk_widget_show (status_bar);
4644
4645     context_id = gtk_statusbar_get_context_id(
4646                           GTK_STATUSBAR(status_bar), "Statusbar example");
4647
4648     button = gtk_button_new_with_label("push item");
4649     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4650         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4651     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4652     gtk_widget_show(button);              
4653
4654     button = gtk_button_new_with_label("pop last item");
4655     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4656         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4657     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4658     gtk_widget_show(button);              
4659
4660     /* always display the window as the last step so it all splashes on
4661      * the screen at once. */
4662     gtk_widget_show(window);
4663
4664     gtk_main ();
4665
4666     return 0;
4667 }
4668 /* example-end */
4669 </verb></tscreen>
4670
4671 <!-- ----------------------------------------------------------------- -->
4672 <sect1>Text Entries
4673 <p>
4674 The Entry widget allows text to be typed and displayed in a single line
4675 text box. The text may be set with function calls that allow new text
4676 to replace, prepend or append the current contents of the Entry widget.
4677
4678 There are two functions for creating Entry widgets:
4679
4680 <tscreen><verb>
4681 GtkWidget *gtk_entry_new( void );
4682
4683 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4684 </verb></tscreen>
4685
4686 The first just creates a new Entry widget, whilst the second creates a
4687 new Entry and sets a limit on the length of the text within the Entry.
4688
4689 There are several functions for altering the text which is currently
4690 within the Entry widget.
4691
4692 <tscreen><verb>
4693 void gtk_entry_set_text( GtkEntry    *entry,
4694                          const gchar *text );
4695
4696 void gtk_entry_append_text( GtkEntry    *entry,
4697                             const gchar *text );
4698
4699 void gtk_entry_prepend_text( GtkEntry    *entry,
4700                              const gchar *text );
4701 </verb></tscreen>
4702
4703 The function gtk_entry_set_text sets the contents of the Entry widget,
4704 replacing the current contents. The functions gtk_entry_append_text
4705 and gtk_entry_prepend_text allow the current contents to be appended
4706 and prepended to.
4707
4708 The next function allows the current insertion point to be set.
4709
4710 <tscreen><verb>
4711 void gtk_entry_set_position( GtkEntry *entry,
4712                              gint      position );
4713 </verb></tscreen>
4714
4715 The contents of the Entry can be retrieved by using a call to the
4716 following function. This is useful in the callback functions described below.
4717
4718 <tscreen><verb>
4719 gchar *gtk_entry_get_text( GtkEntry *entry );
4720 </verb></tscreen>
4721
4722 The value returned by this function is used internally, and must not
4723 be freed using either free() or g_free()
4724
4725 If we don't want the contents of the Entry to be changed by someone typing
4726 into it, we can change its editable state.
4727
4728 <tscreen><verb>
4729 void gtk_entry_set_editable( GtkEntry *entry,
4730                              gboolean  editable );
4731 </verb></tscreen>
4732
4733 The function above allows us to toggle the editable state of the
4734 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4735 argument.
4736
4737 If we are using the Entry where we don't want the text entered to be
4738 visible, for example when a password is being entered, we can use the
4739 following function, which also takes a boolean flag.
4740
4741 <tscreen><verb>
4742 void gtk_entry_set_visibility( GtkEntry *entry,
4743                                gboolean  visible );
4744 </verb></tscreen>
4745
4746 A region of the text may be set as selected by using the following
4747 function. This would most often be used after setting some default
4748 text in an Entry, making it easy for the user to remove it.
4749
4750 <tscreen><verb>
4751 void gtk_entry_select_region( GtkEntry *entry,
4752                               gint      start,
4753                               gint      end );
4754 </verb></tscreen>
4755
4756 If we want to catch when the user has entered text, we can connect to
4757 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4758 user hits the enter key within the Entry widget. Changed is raised
4759 when the text changes at all, e.g. for every character entered or
4760 removed.
4761
4762 The following code is an example of using an Entry widget.
4763
4764 <tscreen><verb>
4765 /* example-start entry entry.c */
4766
4767 #include <gtk/gtk.h>
4768
4769 void enter_callback(GtkWidget *widget, GtkWidget *entry)
4770 {
4771   gchar *entry_text;
4772   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4773   printf("Entry contents: %s\n", entry_text);
4774 }
4775
4776 void entry_toggle_editable (GtkWidget *checkbutton,
4777                                    GtkWidget *entry)
4778 {
4779   gtk_entry_set_editable(GTK_ENTRY(entry),
4780                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4781 }
4782
4783 void entry_toggle_visibility (GtkWidget *checkbutton,
4784                                    GtkWidget *entry)
4785 {
4786   gtk_entry_set_visibility(GTK_ENTRY(entry),
4787                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4788 }
4789
4790 int main (int argc, char *argv[])
4791 {
4792
4793     GtkWidget *window;
4794     GtkWidget *vbox, *hbox;
4795     GtkWidget *entry;
4796     GtkWidget *button;
4797     GtkWidget *check;
4798
4799     gtk_init (&amp;argc, &amp;argv);
4800
4801     /* create a new window */
4802     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4803     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4804     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4805     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4806                        (GtkSignalFunc) gtk_exit, NULL);
4807
4808     vbox = gtk_vbox_new (FALSE, 0);
4809     gtk_container_add (GTK_CONTAINER (window), vbox);
4810     gtk_widget_show (vbox);
4811
4812     entry = gtk_entry_new_with_max_length (50);
4813     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4814                        GTK_SIGNAL_FUNC(enter_callback),
4815                        entry);
4816     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4817     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4818     gtk_entry_select_region (GTK_ENTRY (entry),
4819                              0, GTK_ENTRY(entry)->text_length);
4820     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4821     gtk_widget_show (entry);
4822
4823     hbox = gtk_hbox_new (FALSE, 0);
4824     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4825     gtk_widget_show (hbox);
4826                                   
4827     check = gtk_check_button_new_with_label("Editable");
4828     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4829     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4830                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4831     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4832     gtk_widget_show (check);
4833     
4834     check = gtk_check_button_new_with_label("Visible");
4835     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4836     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4837                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4838     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4839     gtk_widget_show (check);
4840                                    
4841     button = gtk_button_new_with_label ("Close");
4842     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4843                                GTK_SIGNAL_FUNC(gtk_exit),
4844                                GTK_OBJECT (window));
4845     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4846     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4847     gtk_widget_grab_default (button);
4848     gtk_widget_show (button);
4849     
4850     gtk_widget_show(window);
4851
4852     gtk_main();
4853     return(0);
4854 }
4855 /* example-end */
4856 </verb></tscreen>
4857
4858 <!-- ----------------------------------------------------------------- -->
4859 <sect1>Spin Buttons
4860 <p>
4861 The Spin Button widget is generally used to allow the user to select a
4862 value from a range of numeric values. It consists of a text
4863 entry box with up and down arrow buttons attached to the
4864 side. Selecting one of the buttons causes the value to 'spin' up and
4865 down the range of possible values. The entry box may also be edited
4866 directly to enter a specific value.
4867
4868 The Spin Button allows the value to have zero or a number of decimal
4869 places and to be incremented/decremented in configurable steps. The
4870 action of holding down one of the buttons optionally result in an
4871 acceleration of change in the value according to how long it is
4872 depressed.
4873
4874 The Spin Button uses an <ref id="sec_Adjustment" name="Adjustment">
4875 object to hold information about the range of values that the spin
4876 button can take. This makes for a powerful Spin Button widget.
4877
4878 Recall that an adjustment widget is created with the following
4879 function, which illustrates the information that it holds:
4880
4881 <tscreen><verb>
4882 GtkObject *gtk_adjustment_new( gfloat value,
4883                                gfloat lower,
4884                                gfloat upper,
4885                                gfloat step_increment,
4886                                gfloat page_increment,
4887                                gfloat page_size );
4888 </verb></tscreen>
4889
4890 These attributes of an Adjustment are used by the Spin Button in the
4891 following way:
4892
4893 <itemize>
4894 <item> <tt/value/: initial value for the Spin Button
4895 <item> <tt/lower/: lower range value
4896 <item> <tt/upper/: upper range value
4897 <item> <tt/step_increment/: value to increment/decrement when pressing
4898 mouse button 1 on a button
4899 <item> <tt/page_increment/: value to increment/decrement when pressing
4900 mouse button 2 on a button
4901 <item> <tt/page_size/: unused
4902 </itemize>
4903
4904 Additionally, mouse button 3 can be used to jump directly to the
4905 <tt/upper/ or <tt/lower/ values when used to select one of the
4906 buttons. Lets look at how to create a Spin Button:
4907
4908 <tscreen><verb>
4909 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4910                                 gfloat         climb_rate,
4911                                 guint          digits );
4912 </verb></tscreen>
4913
4914 The <tt/climb_rate/ argument take a value between 0.0 and 1.0 and
4915 indicates the amount of acceleration that the Spin Button has. The
4916 <tt/digits/ argument specifies the number of decimal places to which
4917 the value will be displayed.
4918
4919 A Spin Button can be reconfigured after creation using the following
4920 function:
4921
4922 <tscreen><verb>
4923 void gtk_spin_button_configure( GtkSpinButton *spin_button,
4924                                 GtkAdjustment *adjustment,
4925                                 gfloat         climb_rate,
4926                                 guint          digits );
4927 </verb></tscreen>
4928
4929 The <tt/spin_button/ argument specifies the Spin Button widget that is
4930 to be reconfigured. The other arguments are as specified above.
4931
4932 The adjustment can be set and retrieved independantly using the
4933 following two functions:
4934
4935 <tscreen><verb>
4936 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
4937                                      GtkAdjustment  *adjustment );
4938
4939 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
4940 </verb></tscreen>
4941
4942 The number of decimal places can also be altered using:
4943
4944 <tscreen><verb>
4945 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
4946                                  guint          digits) ;
4947 </verb></tscreen>
4948
4949 The value that a Spin Button is currently displaying can be changed
4950 using the following function:
4951
4952 <tscreen><verb>
4953 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
4954                                 gfloat         value );
4955 </verb></tscreen>
4956
4957 The current value of a Spin Button can be retrieved as either a
4958 floating point or integer value with the following functions:
4959
4960 <tscreen><verb>
4961 gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *spin_button );
4962
4963 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
4964 </verb></tscreen>
4965
4966 If you want to alter the value of a Spin Value relative to its current
4967 value, then the following function can be used:
4968
4969 <tscreen><verb>
4970 void gtk_spin_button_spin( GtkSpinButton *spin_button,
4971                            GtkSpinType    direction,
4972                            gfloat         increment );
4973 </verb></tscreen>
4974
4975 The <tt/direction/ parameter can take one of the following values:
4976
4977 <itemize>
4978 <item> GTK_SPIN_STEP_FORWARD
4979 <item> GTK_SPIN_STEP_BACKWARD
4980 <item> GTK_SPIN_PAGE_FORWARD
4981 <item> GTK_SPIN_PAGE_BACKWARD
4982 <item> GTK_SPIN_HOME
4983 <item> GTK_SPIN_END
4984 <item> GTK_SPIN_USER_DEFINED
4985 </itemize>
4986
4987 This function packs in quite a bit of functionality, which I will
4988 attempt to clearly explain. Many of these settings use values from the
4989 Adjustment object that is associated with a Spin Button.
4990
4991 GTK_SPIN_STEP_FORWARD and GTK_SPIN_STEP_BACKWARD change the value of
4992 the Spin Button by the amount specified by <tt/increment/, unless
4993 <tt/increment/ is equal to 0, in which case the value is changed by
4994 the value of <tt/step_increment/ in theAdjustment.
4995
4996 GTK_SPIN_PAGE_FORWARD and GTK_SPIN_PAGE_BACKWARD simply alter the value of
4997 the Spin Button by <tt/increment/.
4998
4999 GTK_SPIN_HOME sets the value of the Spin Button to the bottom of the
5000 Adjustments range.
5001
5002 GTK_SPIN_END sets the value of the Spin Button to the top of the
5003 Adjustments range.
5004
5005 GTK_SPIN_USER_DEFINED simply alters the value of the Spin Button by
5006 the specified amount.
5007
5008 We move away from functions for setting and retreving the range attributes
5009 of the Spin Button now, and move onto functions that effect the
5010 appearance and behaviour of the Spin Button widget itself.
5011
5012 The first of these functions is used to constrain the text box of the
5013 Spin Button such that it may only contain a numric value. This
5014 prevents a user from typing anything other than numeric values into
5015 the text box of a Spin Button:
5016
5017 <tscreen><verb>
5018 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
5019                                   gboolean       numeric );
5020 </verb></tscreen>
5021
5022 You can set whether a Spin Button will wrap around between the upper
5023 and lower range values with the following function:
5024
5025 <tscreen><verb>
5026 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
5027                                gboolean       wrap );
5028 </verb></tscreen>
5029
5030 You can set a Spin Button to round the value to the nearest
5031 <tt/step_increment/, which is set within the Adjustment object used
5032 with the Spin Button. This is accomplished with the following
5033 function:
5034
5035 <tscreen><verb>
5036 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
5037                                         gboolean        snap_to_ticks );
5038 </verb></tscreen>
5039
5040 The update policy of a Spin Button can be changed with the following
5041 function:
5042
5043 <tscreen><verb>
5044 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
5045                                     GtkSpinButtonUpdatePolicy policy );
5046 </verb></tscreen>
5047
5048 <!-- TODO: find out what this does - TRG -->
5049
5050 The possible values of <tt/policy/ are either GTK_UPDATE_ALWAYS or
5051 GTK_UPDATE_IF_VALID.
5052
5053 These policies affect the behavior of a Spin Button when parsing
5054 inserted text and syncing it's value with the values of the
5055 Adjustment.
5056
5057 In the case of GTK_UPDATE_IF_VALID the Spin Button only value gets
5058 changed if the text input is a numeric value that
5059 is within the range specified by the Adjustment. Otherwise
5060 the text is reset to the current value.
5061
5062 In case of GTK_UPDATE_ALWAYS we ignore errors while converting text
5063 into a numeric value.
5064
5065 The appearance of the buttons used in a Spin Button can be changed
5066 using the following function:
5067
5068 <tscreen><verb>
5069 void gtk_spin_button_set_shadow_type( GtkSpinButton *spin_button,
5070                                       GtkShadowType  shadow_type );
5071 </verb></tscreen>
5072
5073 As usual, the <tt/shadow_type/ can be one of:
5074
5075 <itemize>
5076 <item> GTK_SHADOW_IN
5077 <item> GTK_SHADOW_OUT
5078 <item> GTK_SHADOW_ETCHED_IN
5079 <item> GTK_SHADOW_ETCHED_OUT
5080 </itemize>
5081
5082 Finally, you can explicitly request that a Spin Button update itself:
5083
5084 <tscreen><verb>
5085 void gtk_spin_button_update( GtkSpinButton  *spin_button );
5086 </verb></tscreen>
5087
5088 It's example time again.
5089
5090 <tscreen><verb>
5091 /* example-start spinbutton spinbutton.c */
5092
5093 #include <gtk/gtk.h>
5094
5095 static GtkWidget *spinner1;
5096
5097 void toggle_snap( GtkWidget     *widget,
5098                   GtkSpinButton *spin )
5099 {
5100   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5101 }
5102
5103 void toggle_numeric( GtkWidget *widget,
5104                      GtkSpinButton *spin )
5105 {
5106   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5107 }
5108
5109 void change_digits( GtkWidget *widget,
5110                     GtkSpinButton *spin )
5111 {
5112   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5113                               gtk_spin_button_get_value_as_int (spin));
5114 }
5115
5116 void get_value( GtkWidget *widget,
5117                 gpointer data )
5118 {
5119   gchar buf[32];
5120   GtkLabel *label;
5121   GtkSpinButton *spin;
5122
5123   spin = GTK_SPIN_BUTTON (spinner1);
5124   label = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget)));
5125   if (GPOINTER_TO_INT (data) == 1)
5126     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5127   else
5128     sprintf (buf, "%0.*f", spin->digits,
5129              gtk_spin_button_get_value_as_float (spin));
5130   gtk_label_set_text (label, buf);
5131 }
5132
5133
5134 int main( int   argc,
5135           char *argv[] )
5136 {
5137   GtkWidget *window;
5138   GtkWidget *frame;
5139   GtkWidget *hbox;
5140   GtkWidget *main_vbox;
5141   GtkWidget *vbox;
5142   GtkWidget *vbox2;
5143   GtkWidget *spinner2;
5144   GtkWidget *spinner;
5145   GtkWidget *button;
5146   GtkWidget *label;
5147   GtkWidget *val_label;
5148   GtkAdjustment *adj;
5149
5150   /* Initialise GTK */
5151   gtk_init(&amp;argc, &amp;argv);
5152
5153   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5154
5155   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5156                       GTK_SIGNAL_FUNC (gtk_main_quit),
5157                       NULL);
5158
5159   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5160
5161   main_vbox = gtk_vbox_new (FALSE, 5);
5162   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5163   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5164   
5165   frame = gtk_frame_new ("Not accelerated");
5166   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5167   
5168   vbox = gtk_vbox_new (FALSE, 0);
5169   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5170   gtk_container_add (GTK_CONTAINER (frame), vbox);
5171   
5172   /* Day, month, year spinners */
5173   
5174   hbox = gtk_hbox_new (FALSE, 0);
5175   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5176   
5177   vbox2 = gtk_vbox_new (FALSE, 0);
5178   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5179   
5180   label = gtk_label_new ("Day :");
5181   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5182   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5183   
5184   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5185                                               5.0, 0.0);
5186   spinner = gtk_spin_button_new (adj, 0, 0);
5187   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5188   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5189                                    GTK_SHADOW_OUT);
5190   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5191   
5192   vbox2 = gtk_vbox_new (FALSE, 0);
5193   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5194   
5195   label = gtk_label_new ("Month :");
5196   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5197   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5198   
5199   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5200                                               5.0, 0.0);
5201   spinner = gtk_spin_button_new (adj, 0, 0);
5202   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5203   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5204                                    GTK_SHADOW_ETCHED_IN);
5205   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5206   
5207   vbox2 = gtk_vbox_new (FALSE, 0);
5208   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5209   
5210   label = gtk_label_new ("Year :");
5211   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5212   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5213   
5214   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5215                                               1.0, 100.0, 0.0);
5216   spinner = gtk_spin_button_new (adj, 0, 0);
5217   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5218   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5219                                    GTK_SHADOW_IN);
5220   gtk_widget_set_usize (spinner, 55, 0);
5221   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5222   
5223   frame = gtk_frame_new ("Accelerated");
5224   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5225   
5226   vbox = gtk_vbox_new (FALSE, 0);
5227   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5228   gtk_container_add (GTK_CONTAINER (frame), vbox);
5229   
5230   hbox = gtk_hbox_new (FALSE, 0);
5231   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5232   
5233   vbox2 = gtk_vbox_new (FALSE, 0);
5234   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5235   
5236   label = gtk_label_new ("Value :");
5237   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5238   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5239   
5240   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5241                                               0.5, 100.0, 0.0);
5242   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5243   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5244   gtk_widget_set_usize (spinner1, 100, 0);
5245   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5246   
5247   vbox2 = gtk_vbox_new (FALSE, 0);
5248   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5249   
5250   label = gtk_label_new ("Digits :");
5251   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5252   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5253   
5254   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5255   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5256   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5257   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
5258                       GTK_SIGNAL_FUNC (change_digits),
5259                       (gpointer) spinner2);
5260   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5261   
5262   hbox = gtk_hbox_new (FALSE, 0);
5263   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5264   
5265   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5266   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5267                       GTK_SIGNAL_FUNC (toggle_snap),
5268                       spinner1);
5269   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5270   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5271   
5272   button = gtk_check_button_new_with_label ("Numeric only input mode");
5273   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5274                       GTK_SIGNAL_FUNC (toggle_numeric),
5275                       spinner1);
5276   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5277   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5278   
5279   val_label = gtk_label_new ("");
5280   
5281   hbox = gtk_hbox_new (FALSE, 0);
5282   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5283   button = gtk_button_new_with_label ("Value as Int");
5284   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5285   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5286                       GTK_SIGNAL_FUNC (get_value),
5287                       GINT_TO_POINTER (1));
5288   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5289   
5290   button = gtk_button_new_with_label ("Value as Float");
5291   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5292   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5293                       GTK_SIGNAL_FUNC (get_value),
5294                       GINT_TO_POINTER (2));
5295   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5296   
5297   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5298   gtk_label_set_text (GTK_LABEL (val_label), "0");
5299   
5300   hbox = gtk_hbox_new (FALSE, 0);
5301   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5302   
5303   button = gtk_button_new_with_label ("Close");
5304   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5305                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
5306                              GTK_OBJECT (window));
5307   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5308
5309   gtk_widget_show_all (window);
5310
5311   /* Enter the event loop */
5312   gtk_main ();
5313     
5314   return(0);
5315 }
5316 /* example-end */
5317 </verb></tscreen>
5318
5319 <!-- ----------------------------------------------------------------- -->
5320 <sect1>Combo Box
5321 <p>
5322 The combo box is another fairly simple widget that is really just a
5323 collection of other widgets. From the users point of view, the widget
5324 consists of a text entry box and a pull down menu from which the user
5325 can select one of a set of predefined entries. Alternatively, the user
5326 can type a different option directly into the text box.
5327
5328 The following extract from the structure that defines a Combo Box
5329 identifies several of the components:
5330
5331 <tscreen><verb>
5332 struct _GtkCombo { 
5333         GtkHBox hbox; 
5334         GtkWidget *entry; 
5335         GtkWidget *button;
5336         GtkWidget *popup; 
5337         GtkWidget *popwin; 
5338         GtkWidget *list;
5339         ...  };
5340 </verb></tscreen>
5341
5342 As you can see, the Combo Box has two principle parts that you really
5343 care about: an entry and a list.
5344
5345 First off, to create a combo box, use:
5346
5347 <tscreen><verb>
5348 GtkWidget *gtk_combo_new( void );
5349 </verb></tscreen>
5350
5351 Now, if you want to set the string in the entry section of the combo
5352 box, this is done by manipulating the <tt/entry/ widget directly:
5353
5354 <tscreen><verb>
5355     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "My String.");
5356 </verb></tscreen>
5357
5358 To set the values in the popdown list, one uses the function:
5359
5360 <tscreen><verb>
5361 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5362                                     GList    *strings );
5363 </verb></tscreen>
5364
5365 Before you can do this, you have to assemble a GList of the strings
5366 that you want. GList is a linked list implementation that is part of
5367 <ref id="sec_glib" name="glib">, a library supporing GTK. For the
5368 moment, the quick and dirty explanation is that you need to set up a
5369 GList pointer, set it equal to NULL, then append strings to it with
5370
5371 <tscreen><verb>
5372 GList *g_list_append( GList *glist, 
5373                       gpointer data );
5374 </verb></tscreen>
5375
5376 It is important that you set the initial GList pointer to NULL. The
5377 value returned from the g_list_append function must be used as the new
5378 pointer to the GList.
5379
5380 Here's a typical code segment for creating a set of options:
5381
5382 <tscreen><verb>
5383     GList *glist=NULL;
5384
5385     glist = g_list_append(glist, "String 1");
5386     glist = g_list_append(glist, "String 2");
5387     glist = g_list_append(glist, "String 3"); 
5388     glist = g_list_append(glist, "String 4");
5389
5390     gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ;
5391 </verb></tscreen>
5392
5393 At this point you have a working combo box that has been set up.
5394 There are a few aspects of its behavior that you can change. These
5395 are accomplished with the functions: 
5396
5397 <tscreen><verb>
5398 void gtk_combo_set_use_arrows( GtkCombo *combo,
5399                                gint      val );
5400
5401 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5402                                       gint      val );
5403
5404 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5405                                    gint      val );
5406 </verb></tscreen>
5407
5408 <tt/gtk_combo_set_use_arrows()/ lets the user change the value in the
5409 entry using the up/down arrow keys. This doesn't bring up the list, but
5410 rather replaces the current text in the entry with the next list entry
5411 (up or down, as your key choice indicates). It does this by searching
5412 in the list for the item corresponding to the current value in the
5413 entry and selecting the previous/next item accordingly. Usually in an
5414 entry the arrow keys are used to change focus (you can do that anyway
5415 using TAB). Note that when the current item is the last of the list
5416 and you press arrow-down it changes the focus (the same applies with
5417 the first item and arrow-up).
5418
5419 If the current value in the entry is not in the list, then the
5420 function of <tt/gtk_combo_set_use_arrows()/ is disabled.
5421
5422 <tt/gtk_combo_set_use_arrows_always()/ similarly allows the use the
5423 the up/down arrow keys to cycle through the choices in the dropdown
5424 list, except that it wraps around the values in the list, completely
5425 disabling the use of the up and down arrow keys for changing focus.
5426
5427 <tt/gtk_combo_set_case_sensitive()/ toggles whether or not GTK
5428 searches for entries in a case sensitive manner. This is used when
5429 the Combo widget is asked to find a value from the list using the
5430 current entry in the text box. This completion can be performed in
5431 eother a case sensitive or insensitive manner, depending upon the use
5432 of this function. The Combo widget can also simply complete the
5433 current entry if the user presses the key combination MOD-1 and
5434 'Tab'. MOD-1 is often mapped to the 'Alt' key. Note, however that some
5435 Window managers also use this key combination, which will override
5436 it's use within GTK.
5437
5438 Now that we have a combo box, tailored to look and act how we want it,
5439 all that remains is being able to get data from the combo box. This is
5440 relatively straight forward. The majority of the time, all you are
5441 going to care about getting data from is the entry. The entry is
5442 accessed simply by GTK_ENTRY(GTK_COMBO(combo)->entry). The two
5443 principle things that you are going to want to do with it are attach
5444 to the activate signal, which indicates that the user has pressed the
5445 Return or Enter key,and read the text. The first is accomplished
5446 using something like:
5447
5448 <tscreen><verb>
5449     gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate",
5450                        GTK_SIGNAL_FUNC (my_callback_function), my_data);
5451 </verb></tscreen>
5452
5453 Getting the text at any arbitrary time is accomplished by simply using
5454 the entry function:
5455
5456 <tscreen><verb>
5457 gchar *gtk_entry_get_text(GtkEntry *entry);
5458 </verb></tscreen>
5459
5460 Such as:
5461
5462 <tscreen><verb>
5463     char *string;
5464
5465     string = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
5466 </verb></tscreen>
5467
5468 That's about all there is to it. There is a function
5469
5470 <tscreen><verb>
5471 void gtk_combo_disable_activate(GtkCombo *combo);
5472 </verb></tscreen>
5473
5474 that will disable the activate signal on the entry widget in the combo
5475 box. Personally, I can't think of why you'd want to use it, but it
5476 does exist.
5477
5478 <!-- There are also a function to set the string on a particular item, void
5479 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5480 *item_value), but this requires that you have a pointer to the
5481 appropriate GtkItem.  Frankly, I have no idea how to do that.
5482 -->
5483
5484 <!-- ----------------------------------------------------------------- -->
5485 <sect1> Color Selection
5486 <p>
5487 The color selection widget is, not surprisingly, a widget for
5488 interactive selection of colors. This composite widget lets the user
5489 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5490 Saturation, Value) triples.  This is done either by adjusting single
5491 values with sliders or entries, or by picking the desired color from a
5492 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5493 can also be set.
5494
5495 The color selection widget currently emits only one signal,
5496 "color_changed", which is emitted whenever the current color in the
5497 widget changes, either when the user changes it or if it's set
5498 explicitly through gtk_color_selection_set_color().
5499
5500 Lets have a look at what the color selection widget has to offer
5501 us. The widget comes in two flavours: gtk_color_selection and
5502 gtk_color_selection_dialog.
5503
5504 <tscreen><verb>
5505 GtkWidget *gtk_color_selection_new( void );
5506 </verb></tscreen>
5507         
5508 You'll probably not be using this constructor directly. It creates an
5509 orphan GtkColorSelection widget which you'll have to parent
5510 yourself. The GtkColorSelection widget inherits from the GtkVBox
5511 widget.
5512
5513 <tscreen><verb> 
5514 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5515 </verb></tscreen>
5516
5517 This is the most common color selection constructor. It creates a
5518 GtkColorSelectionDialog, which inherits from a GtkDialog. It consists
5519 of a GtkFrame containing a GtkColorSelection widget, a GtkHSeparator
5520 and a GtkHBox with three buttons, "Ok", "Cancel" and "Help". You can
5521 reach these buttons by accessing the "ok_button", "cancel_button" and
5522 "help_button" widgets in the GtkColorSelectionDialog structure,
5523 (i.e. GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
5524
5525 <tscreen><verb>
5526 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
5527                                             GtkUpdateType      policy );
5528 </verb></tscreen>
5529
5530 This function sets the update policy. The default policy is
5531 GTK_UPDATE_CONTINUOUS which means that the current color is updated
5532 continuously when the user drags the sliders or presses the mouse and
5533 drags in the hue-saturation wheel or value bar. If you experience
5534 performance problems, you may want to set the policy to
5535 GTK_UPDATE_DISCONTINUOUS or GTK_UPDATE_DELAYED.
5536
5537 <tscreen><verb>
5538 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
5539                                       gint               use_opacity );
5540 </verb></tscreen>
5541
5542 The color selection widget supports adjusting the opacity of a color
5543 (also known as the alpha channel). This is disabled by
5544 default. Calling this function with use_opacity set to TRUE enables
5545 opacity. Likewise, use_opacity set to FALSE will disable opacity.
5546
5547 <tscreen><verb>
5548 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
5549                                     gdouble           *color );
5550 </verb></tscreen>
5551
5552 You can set the current color explicitly by calling this function with
5553 a pointer to an array of colors (gdouble). The length of the array
5554 depends on whether opacity is enabled or not. Position 0 contains the
5555 red component, 1 is green, 2 is blue and opacity is at position 3
5556 (only if opacity is enabled, see
5557 gtk_color_selection_set_opacity()). All values are between 0.0 and
5558 1.0.
5559
5560 <tscreen><verb>
5561 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
5562                                     gdouble           *color );
5563 </verb></tscreen>
5564
5565 When you need to query the current color, typically when you've
5566 received a "color_changed" signal, you use this function. Color is a
5567 pointer to the array of colors to fill in. See the
5568 gtk_color_selection_set_color() function for the description of this
5569 array.
5570
5571 <!-- Need to do a whole section on DnD - TRG
5572 Drag and drop
5573 -------------
5574
5575 The color sample areas (right under the hue-saturation wheel) supports
5576 drag and drop. The type of drag and drop is "application/x-color". The
5577 message data consists of an array of 4 (or 5 if opacity is enabled)
5578 gdouble values, where the value at position 0 is 0.0 (opacity on) or
5579 1.0 (opacity off) followed by the red, green and blue values at
5580 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
5581 is passed in the value at position 4.
5582 -->
5583
5584 Here's a simple example demonstrating the use of the
5585 GtkColorSelectionDialog. The program displays a window containing a
5586 drawing area. Clicking on it opens a color selection dialog, and
5587 changing the color in the color selection dialog changes the
5588 background color.
5589
5590 <tscreen><verb>
5591 /* example-start colorsel colorsel.c */
5592
5593 #include <glib.h>
5594 #include <gdk/gdk.h>
5595 #include <gtk/gtk.h>
5596
5597 GtkWidget *colorseldlg = NULL;
5598 GtkWidget *drawingarea = NULL;
5599
5600 /* Color changed handler */
5601
5602 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
5603 {
5604   gdouble color[3];
5605   GdkColor gdk_color;
5606   GdkColormap *colormap;
5607
5608   /* Get drawingarea colormap */
5609
5610   colormap = gdk_window_get_colormap (drawingarea->window);
5611
5612   /* Get current color */
5613
5614   gtk_color_selection_get_color (colorsel,color);
5615
5616   /* Fit to a unsigned 16 bit integer (0..65535) and
5617    * insert into the GdkColor structure */
5618
5619   gdk_color.red = (guint16)(color[0]*65535.0);
5620   gdk_color.green = (guint16)(color[1]*65535.0);
5621   gdk_color.blue = (guint16)(color[2]*65535.0);
5622
5623   /* Allocate color */
5624
5625   gdk_color_alloc (colormap, &amp;gdk_color);
5626
5627   /* Set window background color */
5628
5629   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
5630
5631   /* Clear window */
5632
5633   gdk_window_clear (drawingarea->window);
5634 }
5635
5636 /* Drawingarea event handler */
5637
5638 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
5639 {
5640   gint handled = FALSE;
5641   GtkWidget *colorsel;
5642
5643   /* Check if we've received a button pressed event */
5644
5645   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
5646     {
5647       /* Yes, we have an event and there's no colorseldlg yet! */
5648
5649       handled = TRUE;
5650
5651       /* Create color selection dialog */
5652
5653       colorseldlg = gtk_color_selection_dialog_new("Select background color");
5654
5655       /* Get the GtkColorSelection widget */
5656
5657       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
5658
5659       /* Connect to the "color_changed" signal, set the client-data
5660        * to the colorsel widget */
5661
5662       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
5663         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
5664
5665       /* Show the dialog */
5666
5667       gtk_widget_show(colorseldlg);
5668     }
5669
5670   return handled;
5671 }
5672
5673 /* Close down and exit handler */
5674
5675 void destroy_window (GtkWidget *widget, gpointer client_data)
5676 {
5677   gtk_main_quit ();
5678 }
5679
5680 /* Main */
5681
5682 gint main (gint argc, gchar *argv[])
5683 {
5684   GtkWidget *window;
5685
5686   /* Initialize the toolkit, remove gtk-related commandline stuff */
5687
5688   gtk_init (&amp;argc,&amp;argv);
5689
5690   /* Create toplevel window, set title and policies */
5691
5692   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5693   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
5694   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
5695
5696   /* Attach to the "delete" and "destroy" events so we can exit */
5697
5698   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
5699     (GtkSignalFunc)destroy_window, (gpointer)window);
5700
5701   gtk_signal_connect (GTK_OBJECT(window), "destroy",
5702     (GtkSignalFunc)destroy_window, (gpointer)window);
5703   
5704   /* Create drawingarea, set size and catch button events */
5705
5706   drawingarea = gtk_drawing_area_new ();
5707
5708   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
5709
5710   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
5711
5712   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
5713     (GtkSignalFunc)area_event, (gpointer)drawingarea);
5714   
5715   /* Add drawingarea to window, then show them both */
5716
5717   gtk_container_add (GTK_CONTAINER(window), drawingarea);
5718
5719   gtk_widget_show (drawingarea);
5720   gtk_widget_show (window);
5721   
5722   /* Enter the gtk main loop (this never returns) */
5723
5724   gtk_main ();
5725
5726   /* Satisfy grumpy compilers */
5727
5728   return(0);
5729 }
5730 /* example-end */
5731 </verb></tscreen>
5732
5733 <!-- ----------------------------------------------------------------- -->
5734 <sect1> File Selections
5735 <p>
5736 The file selection widget is a quick and simple way to display a File
5737 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
5738 great way to cut down on programming time.
5739
5740 To create a new file selection box use:
5741
5742 <tscreen><verb>
5743 GtkWidget *gtk_file_selection_new( gchar *title );
5744 </verb></tscreen>
5745
5746 To set the filename, for example to bring up a specific directory, or
5747 give a default filename, use this function:
5748
5749 <tscreen><verb>
5750 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
5751                                       gchar            *filename );
5752 </verb></tscreen>
5753
5754 To grab the text that the user has entered or clicked on, use this 
5755 function:
5756
5757 <tscreen><verb>
5758 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
5759 </verb></tscreen>
5760
5761 There are also pointers to the widgets contained within the file 
5762 selection widget. These are:
5763
5764 <itemize>
5765 <item>dir_list
5766 <item>file_list
5767 <item>selection_entry
5768 <item>selection_text
5769 <item>main_vbox
5770 <item>ok_button
5771 <item>cancel_button
5772 <item>help_button
5773 </itemize>
5774
5775 Most likely you will want to use the ok_button, cancel_button, and
5776 help_button pointers in signaling their use.
5777
5778 Included here is an example stolen from testgtk.c, modified to run on
5779 its own. As you will see, there is nothing much to creating a file
5780 selection widget. While in this example the Help button appears on the
5781 screen, it does nothing as there is not a signal attached to it.
5782
5783 <tscreen><verb>
5784 /* example-start filesel filesel.c */
5785
5786 #include <gtk/gtk.h>
5787
5788 /* Get the selected filename and print it to the console */
5789 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
5790 {
5791     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
5792 }
5793
5794 void destroy (GtkWidget *widget, gpointer data)
5795 {
5796     gtk_main_quit ();
5797 }
5798
5799 int main (int argc, char *argv[])
5800 {
5801     GtkWidget *filew;
5802     
5803     gtk_init (&amp;argc, &amp;argv);
5804     
5805     /* Create a new file selection widget */
5806     filew = gtk_file_selection_new ("File selection");
5807     
5808     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
5809                         (GtkSignalFunc) destroy, &amp;filew);
5810     /* Connect the ok_button to file_ok_sel function */
5811     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
5812                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
5813     
5814     /* Connect the cancel_button to destroy the widget */
5815     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
5816                                             (filew)->cancel_button),
5817                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
5818                                GTK_OBJECT (filew));
5819     
5820     /* Lets set the filename, as if this were a save dialog, and we are giving
5821      a default filename */
5822     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
5823                                      "penguin.png");
5824     
5825     gtk_widget_show(filew);
5826     gtk_main ();
5827     return 0;
5828 }
5829 /* example-end */
5830 </verb></tscreen>
5831
5832 <!-- ***************************************************************** -->
5833 <sect> Container Widgets
5834 <!-- ***************************************************************** -->
5835
5836 <!-- ----------------------------------------------------------------- -->   
5837 <sect1>The EventBox <label id="sec_EventBox">
5838 <p> 
5839 Some GTK widgets don't have associated X windows, so they just draw on
5840 their parents. Because of this, they cannot receive events and if they
5841 are incorrectly sized, they don't clip so you can get messy
5842 overwriting etc. If you require more from these widgets, the EventBox
5843 is for you.
5844
5845 At first glance, the EventBox widget might appear to be totally
5846 useless. It draws nothing on the screen and responds to no
5847 events. However, it does serve a function - it provides an X window
5848 for its child widget. This is important as many GTK widgets do not
5849 have an associated X window. Not having an X window saves memory and
5850 improves performance, but also has some drawbacks. A widget without an
5851 X window cannot receive events, and does not perform any clipping on
5852 its contents. Although the name <em/EventBox/ emphasizes the
5853 event-handling function, the widget can also be used for clipping.
5854 (and more, see the example below).
5855
5856 To create a new EventBox widget, use:
5857
5858 <tscreen><verb>
5859 GtkWidget *gtk_event_box_new( void );
5860 </verb></tscreen>
5861
5862 A child widget can then be added to this EventBox:
5863
5864 <tscreen><verb>
5865     gtk_container_add( GTK_CONTAINER(event_box), child_widget );
5866 </verb></tscreen>
5867
5868 The following example demonstrates both uses of an EventBox - a label
5869 is created that is clipped to a small box, and set up so that a
5870 mouse-click on the label causes the program to exit. Resizing the
5871 window reveals varying amounts of the label.
5872
5873 <tscreen><verb>
5874 /* example-start eventbox eventbox.c */
5875
5876 #include <gtk/gtk.h>
5877
5878 int 
5879 main (int argc, char *argv[])
5880 {
5881     GtkWidget *window;
5882     GtkWidget *event_box;
5883     GtkWidget *label;
5884     
5885     gtk_init (&amp;argc, &amp;argv);
5886     
5887     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5888     
5889     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
5890     
5891     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5892                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5893     
5894     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5895     
5896     /* Create an EventBox and add it to our toplevel window */
5897     
5898     event_box = gtk_event_box_new ();
5899     gtk_container_add (GTK_CONTAINER(window), event_box);
5900     gtk_widget_show (event_box);
5901     
5902     /* Create a long label */
5903     
5904     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
5905     gtk_container_add (GTK_CONTAINER (event_box), label);
5906     gtk_widget_show (label);
5907     
5908     /* Clip it short. */
5909     gtk_widget_set_usize (label, 110, 20);
5910     
5911     /* And bind an action to it */
5912     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
5913     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
5914                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5915     
5916     /* Yet one more thing you need an X window for ... */
5917     
5918     gtk_widget_realize (event_box);
5919     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
5920     
5921     gtk_widget_show (window);
5922     
5923     gtk_main ();
5924     
5925     return(0);
5926 }
5927 /* example-end */
5928 </verb></tscreen>
5929
5930 <!-- ----------------------------------------------------------------- -->   
5931 <sect1>The Alignment widget <label id="sec_Alignment">
5932 <p>
5933 The alignment widget allows you to place a widget within its window at
5934 a position and size relative to the size of the Alignment widget
5935 itself. For example, it can be very useful for centering a widget
5936 within the window.
5937
5938 There are only two functions associated with the Alignment widget:
5939
5940 <tscreen><verb>
5941 GtkWidget* gtk_alignment_new( gfloat xalign,
5942                               gfloat yalign,
5943                               gfloat xscale,
5944                               gfloat yscale );
5945
5946 void gtk_alignment_set( GtkAlignment *alignment,
5947                         gfloat        xalign,
5948                         gfloat        yalign,
5949                         gfloat        xscale,
5950                         gfloat        yscale );
5951 </verb></tscreen>
5952
5953 The first function creates a new Alignment widget with the specified
5954 parameters. The second function allows the alignment paramters of an
5955 exisiting Alignment widget to be altered.
5956
5957 All four alignment parameters are floating point numbers which can
5958 range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
5959 affect the position of the widget placed within the Alignment
5960 widget. The <tt/xscale/ and <tt/yscale/ arguments effect the amount of
5961 space allocated to the widget.
5962
5963 A child widget can be added to this Alignment widget using:
5964
5965 <tscreen><verb>
5966     gtk_container_add( GTK_CONTAINER(alignment), child_widget );
5967 </verb></tscreen>
5968
5969 For an example of using an Alignment widget, refer to the example for
5970 the <ref id="sec_ProgressBar" name="Progress Bar"> widget.
5971
5972 <!-- ----------------------------------------------------------------- -->
5973 <sect1> Fixed Container
5974 <p>
5975 The Fixed container allows you to place widgets at a fixed position
5976 within it's window, relative to it's upper left hand corner. The
5977 position of the widgets can be changed dynamically.
5978
5979 There are only three functions associated with the fixed widget:
5980
5981 <tscreen><verb>
5982 GtkWidget* gtk_fixed_new( void );
5983
5984 void gtk_fixed_put( GtkFixed  *fixed,
5985                     GtkWidget *widget,
5986                     gint16     x,
5987                     gint16     y );
5988
5989 void gtk_fixed_move( GtkFixed  *fixed,
5990                      GtkWidget *widget,
5991                      gint16     x,
5992                      gint16     y );
5993 </verb></tscreen>
5994
5995 The function <tt/gtk_fixed_new/ allows you to create a new Fixed
5996 container.
5997
5998 <tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
5999 the position specified by <tt/x/ and <tt/y/.
6000
6001 <tt/gtk_fixed_move/ allows the specified widget to be moved to a new
6002 position.
6003
6004 The following example illustrates how to use the Fixed Container.
6005
6006 <tscreen><verb>
6007 /* example-start fixed fixed.c */
6008
6009 #include <gtk/gtk.h>
6010
6011 /* I'm going to be lazy and use some global variables to
6012  * store the position of the widget within the fixed
6013  * container */
6014 gint x=50;
6015 gint y=50;
6016
6017 /* This callback function moves the button to a new position
6018  * in the Fixed container. */
6019 void move_button( GtkWidget *widget,
6020                   GtkWidget *fixed )
6021 {
6022   x = (x+30)%300;
6023   y = (y+50)%300;
6024   gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); 
6025 }
6026
6027 int main( int   argc,
6028           char *argv[] )
6029 {
6030   /* GtkWidget is the storage type for widgets */
6031   GtkWidget *window;
6032   GtkWidget *fixed;
6033   GtkWidget *button;
6034   gint i;
6035
6036   /* Initialise GTK */
6037   gtk_init(&amp;argc, &amp;argv);
6038     
6039   /* Create a new window */
6040   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6041   gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
6042
6043   /* Here we connect the "destroy" event to a signal handler */ 
6044   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6045                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6046  
6047   /* Sets the border width of the window. */
6048   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6049
6050   /* Create a Fixed Container */
6051   fixed = gtk_fixed_new();
6052   gtk_container_add(GTK_CONTAINER(window), fixed);
6053   gtk_widget_show(fixed);
6054   
6055   for (i = 1 ; i <= 3 ; i++) {
6056     /* Creates a new button with the label "Press me" */
6057     button = gtk_button_new_with_label ("Press me");
6058   
6059     /* When the button receives the "clicked" signal, it will call the
6060      * function move_button() passing it the Fixed Containter as its
6061      * argument. */
6062     gtk_signal_connect (GTK_OBJECT (button), "clicked",
6063                         GTK_SIGNAL_FUNC (move_button), fixed);
6064   
6065     /* This packs the button into the fixed containers window. */
6066     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
6067   
6068     /* The final step is to display this newly created widget. */
6069     gtk_widget_show (button);
6070   }
6071
6072   /* Display the window */
6073   gtk_widget_show (window);
6074     
6075   /* Enter the event loop */
6076   gtk_main ();
6077     
6078   return(0);
6079 }
6080 /* example-end */
6081 </verb></tscreen>
6082
6083 <!-- ----------------------------------------------------------------- -->
6084 <sect1> Layout Container
6085 <p>
6086 The Layout container is similar to the Fixed container except that it
6087 implements an infinite (where infinity is less than 2^32) scrolling
6088 area. Xwindows has a limitation where windows can be at most 32767
6089 pixels wide or tall. The Layout container gets around this limitation
6090 by doing some exotic stuff using window and bit gravities, so that you
6091 can have smooth scrolling even when you have many child widgets in
6092 your scrolling area.
6093
6094 A Layout container is created using:
6095
6096 <tscreen><verb>
6097 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6098                            GtkAdjustment *vadjustment );
6099 </verb></tscreen>
6100
6101 As you can see, you can optionally specify the Adjustment objects that
6102 the Layout widget will use for it's scrolling.
6103
6104 You can add and move widgets in the Layout container using the
6105 following two functions:
6106
6107 <tscreen><verb>
6108 void gtk_layout_put( GtkLayout *layout,
6109                      GtkWidget *widget,
6110                      gint       x,
6111                      gint       y );
6112
6113 void gtk_layout_move( GtkLayout *layout,
6114                       GtkWidget *widget,
6115                       gint       x,
6116                       gint       y );
6117 </verb></tscreen>
6118
6119 The size of the Layout container can be set using the next function:
6120
6121 <tscreen><verb>
6122 void gtk_layout_set_size( GtkLayout *layout,
6123                           guint      width,
6124                           guint      height );
6125 </verb></tscreen>
6126
6127 Layout containers are one of the very few widgets in the GTK widget
6128 set that actively repaint themselves on screen as they are changed
6129 using the above functions (the vast majority of widgets queue
6130 requests which are then processed when control returns to the
6131 <tt/gtk_main()/ function).
6132
6133 When you want to make a large number of changes to a Layout container,
6134 you can use the following two functions to disable and re-enable this
6135 repainting functionality:
6136
6137 <tscreen><verb>
6138 void gtk_layout_freeze( GtkLayout *layout );
6139
6140 void gtk_layout_thaw( GtkLayout *layout );
6141 </verb></tscreen>
6142
6143 The final four functions for use with Layout widgets are for
6144 manipulating the horizontal and vertical adjustment widgets:
6145
6146 <tscreen><verb>
6147 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6148
6149 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6150
6151 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6152                                  GtkAdjustment *adjustment );
6153
6154 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6155                                  GtkAdjustment *adjustment);
6156 </verb></tscreen>
6157
6158 <!-- ----------------------------------------------------------------- -->
6159 <sect1> Frames <label id="sec_Frames">
6160 <p>
6161 Frames can be used to enclose one or a group of widgets with a box
6162 which can optionally be labelled. The position of the label and the
6163 style of the box can be altered to suit.
6164
6165 A Frame can be created with the following function:
6166
6167 <tscreen><verb>
6168 GtkWidget *gtk_frame_new( const gchar *label );
6169 </verb></tscreen>
6170
6171 The label is by default placed in the upper left hand corner of the
6172 frame. A value of NULL for the <tt/label/ argument will result in no
6173 label being displayed. The text of the label can be changed using the
6174 next function.
6175
6176 <tscreen><verb>
6177 void gtk_frame_set_label( GtkFrame    *frame,
6178                           const gchar *label );
6179 </verb></tscreen>
6180
6181 The position of the label can be changed using this function:
6182
6183 <tscreen><verb>
6184 void gtk_frame_set_label_align( GtkFrame *frame,
6185                                 gfloat    xalign,
6186                                 gfloat    yalign );
6187 </verb></tscreen>
6188
6189 <tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
6190 indicates the position of the label along the top horizontal of the
6191 frame. <tt/yalign/ is not currently used. The default value of xalign
6192 is 0.0 which places the label at the left hand end of the frame.
6193
6194 The next function alters the style of the box that is used to outline
6195 the frame.
6196
6197 <tscreen><verb>
6198 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6199                                 GtkShadowType  type);
6200 </verb></tscreen>
6201
6202 The <tt/type/ argument can take one of the following values:
6203 <itemize>
6204 <item> GTK_SHADOW_NONE
6205 <item> GTK_SHADOW_IN
6206 <item> GTK_SHADOW_OUT
6207 <item> GTK_SHADOW_ETCHED_IN (the default)
6208 <item> GTK_SHADOW_ETCHED_OUT
6209 </itemize>
6210
6211 The following code example illustrates the use of the Frame widget.
6212
6213 <tscreen><verb>
6214 /* example-start frame frame.c */
6215
6216 #include <gtk/gtk.h>
6217
6218 int main( int   argc,
6219           char *argv[] )
6220 {
6221   /* GtkWidget is the storage type for widgets */
6222   GtkWidget *window;
6223   GtkWidget *frame;
6224   GtkWidget *button;
6225   gint i;
6226
6227   /* Initialise GTK */
6228   gtk_init(&amp;argc, &amp;argv);
6229     
6230   /* Create a new window */
6231   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6232   gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
6233
6234   /* Here we connect the "destroy" event to a signal handler */ 
6235   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6236                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6237
6238   gtk_widget_set_usize(window, 300, 300);
6239   /* Sets the border width of the window. */
6240   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6241
6242   /* Create a Frame */
6243   frame = gtk_frame_new(NULL);
6244   gtk_container_add(GTK_CONTAINER(window), frame);
6245
6246   /* Set the frames label */
6247   gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
6248
6249   /* Align the label at the right of the frame */
6250   gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
6251
6252   /* Set the style of the frame */
6253   gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
6254
6255   gtk_widget_show(frame);
6256   
6257   /* Display the window */
6258   gtk_widget_show (window);
6259     
6260   /* Enter the event loop */
6261   gtk_main ();
6262     
6263   return(0);
6264 }
6265 /* example-end */
6266
6267 </verb></tscreen>
6268
6269 <!-- ----------------------------------------------------------------- -->   
6270 <sect1> Aspect Frames
6271 <p>
6272 The aspect frame widget is like a frame widget, except that it also
6273 enforces the aspect ratio (that is, the ratio of the width to the
6274 height) of the child widget to have a certain value, adding extra
6275 space if necessary. This is useful, for instance, if you want to
6276 preview a larger image. The size of the preview should vary when the
6277 user resizes the window, but the aspect ratio needs to always match
6278 the original image.
6279   
6280 To create a new aspect frame use:
6281    
6282 <tscreen><verb>
6283 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6284                                  gfloat       xalign,
6285                                  gfloat       yalign,
6286                                  gfloat       ratio,
6287                                  gint         obey_child);
6288 </verb></tscreen>
6289    
6290 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
6291 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
6292 widget will match the aspect ratio of the ideal size it requests.
6293 Otherwise, it is given by <tt/ratio/.
6294    
6295 To change the options of an existing aspect frame, you can use:
6296    
6297 <tscreen><verb>
6298 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6299                            gfloat          xalign,
6300                            gfloat          yalign,
6301                            gfloat          ratio,
6302                            gint            obey_child);
6303 </verb></tscreen>
6304    
6305 As an example, the following program uses an AspectFrame to present a
6306 drawing area whose aspect ratio will always be 2:1, no matter how the
6307 user resizes the top-level window.
6308    
6309 <tscreen><verb>
6310 /* example-start aspectframe aspectframe.c */
6311
6312 #include <gtk/gtk.h>
6313    
6314 int
6315 main (int argc, char *argv[])
6316 {
6317     GtkWidget *window;
6318     GtkWidget *aspect_frame;
6319     GtkWidget *drawing_area;
6320     gtk_init (&amp;argc, &amp;argv);
6321    
6322     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6323     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
6324     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6325                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6326     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6327    
6328     /* Create an aspect_frame and add it to our toplevel window */
6329    
6330     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
6331                                          0.5, /* center x */
6332                                          0.5, /* center y */
6333                                          2, /* xsize/ysize = 2 */
6334                                          FALSE /* ignore child's aspect */);
6335    
6336     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
6337     gtk_widget_show (aspect_frame);
6338    
6339     /* Now add a child widget to the aspect frame */
6340    
6341     drawing_area = gtk_drawing_area_new ();
6342    
6343     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6344      * window since we are forcing a 2x1 aspect ratio */
6345     gtk_widget_set_usize (drawing_area, 200, 200);
6346     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
6347     gtk_widget_show (drawing_area);
6348    
6349     gtk_widget_show (window);
6350     gtk_main ();
6351     return 0;
6352 }
6353 /* example-end */
6354 </verb></tscreen>
6355
6356 <!-- ----------------------------------------------------------------- -->   
6357 <sect1> Paned Window Widgets
6358 <p>
6359 The paned window widgets are useful when you want to divide an area
6360 into two parts, with the relative size of the two parts controlled by
6361 the user. A groove is drawn between the two portions with a handle
6362 that the user can drag to change the ratio. The division can either be
6363 horizontal (HPaned) or vertical (VPaned).
6364    
6365 To create a new paned window, call one of:
6366    
6367 <tscreen><verb>
6368 GtkWidget *gtk_hpaned_new (void);
6369
6370 GtkWidget *gtk_vpaned_new (void);
6371 </verb></tscreen>
6372
6373 After creating the paned window widget, you need to add child widgets
6374 to its two halves. To do this, use the functions:
6375    
6376 <tscreen><verb>
6377 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6378
6379 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6380 </verb></tscreen>
6381    
6382 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
6383 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
6384 right or bottom half of the paned window.
6385
6386 A paned widget can be changed visually using the following two
6387 functions.
6388
6389 <tscreen><verb>
6390 void gtk_paned_set_handle_size( GtkPaned *paned,
6391                                 guint16   size);
6392
6393 void gtk_paned_set_gutter_size( GtkPaned *paned,
6394                                 guint16   size);
6395 </verb></tscreen>
6396
6397 The first of these sets the size of the handle and the second sets the
6398 size of the gutter that is between the two parts of the paned window.
6399
6400 As an example, we will create part of the user interface of an
6401 imaginary email program. A window is divided into two portions
6402 vertically, with the top portion being a list of email messages and
6403 the bottom portion the text of the email message. Most of the program
6404 is pretty straightforward. A couple of points to note: text can't be
6405 added to a Text widget until it is realized. This could be done by
6406 calling <tt/gtk_widget_realize()/, but as a demonstration of an
6407 alternate technique, we connect a handler to the "realize" signal to
6408 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
6409 of the items in the table containing the text window and its
6410 scrollbars, so that when the bottom portion is made smaller, the
6411 correct portions shrink instead of being pushed off the bottom of the
6412 window.
6413
6414 <tscreen><verb>
6415 /* example-start paned paned.c */
6416
6417 #include <gtk/gtk.h>
6418    
6419 /* Create the list of "messages" */
6420 GtkWidget *
6421 create_list (void)
6422 {
6423
6424     GtkWidget *scrolled_window;
6425     GtkWidget *list;
6426     GtkWidget *list_item;
6427    
6428     int i;
6429     char buffer[16];
6430    
6431     /* Create a new scrolled window, with scrollbars only if needed */
6432     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6433     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6434                                     GTK_POLICY_AUTOMATIC, 
6435                                     GTK_POLICY_AUTOMATIC);
6436    
6437     /* Create a new list and put it in the scrolled window */
6438     list = gtk_list_new ();
6439     gtk_scrolled_window_add_with_viewport (
6440                GTK_SCROLLED_WINDOW (scrolled_window), list);
6441     gtk_widget_show (list);
6442    
6443     /* Add some messages to the window */
6444     for (i=0; i<10; i++) {
6445
6446         sprintf(buffer,"Message #%d",i);
6447         list_item = gtk_list_item_new_with_label (buffer);
6448         gtk_container_add (GTK_CONTAINER(list), list_item);
6449         gtk_widget_show (list_item);
6450
6451     }
6452    
6453     return scrolled_window;
6454 }
6455    
6456 /* Add some text to our text widget - this is a callback that is invoked
6457 when our window is realized. We could also force our window to be
6458 realized with gtk_widget_realize, but it would have to be part of
6459 a hierarchy first */
6460
6461 void
6462 realize_text (GtkWidget *text, gpointer data)
6463 {
6464     gtk_text_freeze (GTK_TEXT (text));
6465     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
6466     "From: pathfinder@nasa.gov\n"
6467     "To: mom@nasa.gov\n"
6468     "Subject: Made it!\n"
6469     "\n"
6470     "We just got in this morning. The weather has been\n"
6471     "great - clear but cold, and there are lots of fun sights.\n"
6472     "Sojourner says hi. See you soon.\n"
6473     " -Path\n", -1);
6474    
6475     gtk_text_thaw (GTK_TEXT (text));
6476 }
6477    
6478 /* Create a scrolled text area that displays a "message" */
6479 GtkWidget *
6480 create_text (void)
6481 {
6482     GtkWidget *table;
6483     GtkWidget *text;
6484     GtkWidget *hscrollbar;
6485     GtkWidget *vscrollbar;
6486    
6487     /* Create a table to hold the text widget and scrollbars */
6488     table = gtk_table_new (2, 2, FALSE);
6489    
6490     /* Put a text widget in the upper left hand corner. Note the use of
6491      * GTK_SHRINK in the y direction */
6492     text = gtk_text_new (NULL, NULL);
6493     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
6494                       GTK_FILL | GTK_EXPAND,
6495                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
6496     gtk_widget_show (text);
6497    
6498     /* Put a HScrollbar in the lower left hand corner */
6499     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
6500     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
6501                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6502     gtk_widget_show (hscrollbar);
6503    
6504     /* And a VScrollbar in the upper right */
6505     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
6506     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
6507                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
6508     gtk_widget_show (vscrollbar);
6509    
6510     /* Add a handler to put a message in the text widget when it is realized */
6511     gtk_signal_connect (GTK_OBJECT (text), "realize",
6512                         GTK_SIGNAL_FUNC (realize_text), NULL);
6513    
6514     return table;
6515 }
6516    
6517 int
6518 main (int argc, char *argv[])
6519 {
6520     GtkWidget *window;
6521     GtkWidget *vpaned;
6522     GtkWidget *list;
6523     GtkWidget *text;
6524
6525     gtk_init (&amp;argc, &amp;argv);
6526    
6527     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6528     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
6529     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6530                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6531     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6532     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
6533
6534     /* create a vpaned widget and add it to our toplevel window */
6535    
6536     vpaned = gtk_vpaned_new ();
6537     gtk_container_add (GTK_CONTAINER(window), vpaned);
6538     gtk_paned_set_handle_size (GTK_PANED(vpaned),
6539                                10);
6540     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
6541                                15);                       
6542     gtk_widget_show (vpaned);
6543    
6544     /* Now create the contents of the two halves of the window */
6545    
6546     list = create_list ();
6547     gtk_paned_add1 (GTK_PANED(vpaned), list);
6548     gtk_widget_show (list);
6549    
6550     text = create_text ();
6551     gtk_paned_add2 (GTK_PANED(vpaned), text);
6552     gtk_widget_show (text);
6553     gtk_widget_show (window);
6554     gtk_main ();
6555     return 0;
6556 }
6557 /* example-end */
6558 </verb></tscreen>
6559
6560 <!-- ----------------------------------------------------------------- -->
6561 <sect1>Viewports <label id="sec_Viewports">
6562 <p>
6563 It is unlikely that you will ever need to use the Viewport widget
6564 directly. You are much more likely to use the
6565 <ref id="sec_ScrolledWindows" name="Scrolled Windows"> widget which
6566 itself uses the Viewport.
6567
6568 A viewport widget allows you to place a larger widget within it such
6569 that you can view a part of it at a time. It uses
6570 <ref id="sec_Adjustment" name="Adjustments"> to define the area that
6571 is currently in view.
6572
6573 A Viewport is created with the function
6574
6575 <tscreen><verb>
6576 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
6577                              GtkAdjustment *vadjustment );
6578 </verb></tscreen>
6579
6580 As you can see you can specify the horizontal and vertical Adjustments
6581 that the widget is to use when you create the widget. It will create
6582 it's own if you pass NULL as the value of the arguments.
6583
6584 You can get and set the adjustments after the widget has been created
6585 using the following four functions:
6586
6587 <tscreen><verb>
6588 GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
6589
6590 GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
6591
6592 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
6593                                    GtkAdjustment *adjustment );
6594
6595 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
6596                                    GtkAdjustment *adjustment );
6597 </verb></tscreen>
6598
6599 The only other viewport function is used to alter its appearance:
6600
6601 <tscreen><verb>
6602 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
6603                                    GtkShadowType  type );
6604 </verb></tscreen>
6605
6606 Possible values for the <tt/type/ parameter are:
6607 <itemize>
6608 <item> GTK_SHADOW_NONE,
6609 <item> GTK_SHADOW_IN,
6610 <item> GTK_SHADOW_OUT,
6611 <item> GTK_SHADOW_ETCHED_IN,
6612 <item> GTK_SHADOW_ETCHED_OUT
6613 </itemize>
6614
6615 <!-- ----------------------------------------------------------------- -->
6616 <sect1>Scrolled Windows <label id="sec_ScrolledWindows">
6617 <p>
6618 Scrolled windows are used to create a scrollable area inside a real
6619 window.  You may insert any type of widget into a scrolled window, and
6620 it will be accessible regardless of the size by using the scrollbars.
6621
6622 The following function is used to create a new scrolled window.
6623
6624 <tscreen><verb>
6625 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
6626                                     GtkAdjustment *vadjustment );
6627 </verb></tscreen>
6628
6629 Where the first argument is the adjustment for the horizontal
6630 direction, and the second, the adjustment for the vertical direction.
6631 These are almost always set to NULL.
6632
6633 <tscreen><verb>
6634 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
6635                                      GtkPolicyType      hscrollbar_policy,
6636                                      GtkPolicyType      vscrollbar_policy );
6637 </verb></tscreen>
6638
6639 This sets the policy to be used with respect to the scrollbars.
6640 The first argument is the scrolled window you wish to change. The second
6641 sets the policy for the horizontal scrollbar, and the third the policy for 
6642 the vertical scrollbar.
6643
6644 The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
6645 GTK_POLICY_AUTOMATIC will automatically decide whether you need
6646 scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6647 there.
6648
6649 You can then place your object into the scrolled window using the
6650 following function.
6651
6652 <tscreen><verb>
6653 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
6654                                             GtkWidget         *child);
6655 </verb></tscreen>
6656
6657 Here is a simple example that packs 100 toggle buttons into a scrolled
6658 window.  I've only commented on the parts that may be new to you.
6659
6660 <tscreen><verb>
6661 /* example-start scrolledwin scrolledwin.c */
6662
6663 #include <gtk/gtk.h>
6664
6665 void destroy(GtkWidget *widget, gpointer data)
6666 {
6667     gtk_main_quit();
6668 }
6669
6670 int main (int argc, char *argv[])
6671 {
6672     static GtkWidget *window;
6673     GtkWidget *scrolled_window;
6674     GtkWidget *table;
6675     GtkWidget *button;
6676     char buffer[32];
6677     int i, j;
6678     
6679     gtk_init (&amp;argc, &amp;argv);
6680     
6681     /* Create a new dialog window for the scrolled window to be
6682      * packed into. A dialog is just like a normal window except it has a 
6683      * vbox and a horizontal separator packed into it. It's just a shortcut
6684      * for creating dialogs */
6685     window = gtk_dialog_new ();
6686     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6687                         (GtkSignalFunc) destroy, NULL);
6688     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
6689     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6690     gtk_widget_set_usize(window, 300, 300);
6691     
6692     /* create a new scrolled window. */
6693     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6694     
6695     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
6696     
6697     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
6698      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
6699      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6700      * there.  The first one is the horizontal scrollbar, the second, 
6701      * the vertical. */
6702     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6703                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
6704     /* The dialog window is created with a vbox packed into it. */                                                              
6705     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
6706                         TRUE, TRUE, 0);
6707     gtk_widget_show (scrolled_window);
6708     
6709     /* create a table of 10 by 10 squares. */
6710     table = gtk_table_new (10, 10, FALSE);
6711     
6712     /* set the spacing to 10 on x and 10 on y */
6713     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
6714     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
6715     
6716     /* pack the table into the scrolled window */
6717     gtk_scrolled_window_add_with_viewport (
6718                    GTK_SCROLLED_WINDOW (scrolled_window), table);
6719     gtk_widget_show (table);
6720     
6721     /* this simply creates a grid of toggle buttons on the table
6722      * to demonstrate the scrolled window. */
6723     for (i = 0; i < 10; i++)
6724        for (j = 0; j < 10; j++) {
6725           sprintf (buffer, "button (%d,%d)\n", i, j);
6726           button = gtk_toggle_button_new_with_label (buffer);
6727           gtk_table_attach_defaults (GTK_TABLE (table), button,
6728                                      i, i+1, j, j+1);
6729           gtk_widget_show (button);
6730        }
6731     
6732     /* Add a "close" button to the bottom of the dialog */
6733     button = gtk_button_new_with_label ("close");
6734     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6735                                (GtkSignalFunc) gtk_widget_destroy,
6736                                GTK_OBJECT (window));
6737     
6738     /* this makes it so the button is the default. */
6739     
6740     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6741     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
6742     
6743     /* This grabs this button to be the default button. Simply hitting
6744      * the "Enter" key will cause this button to activate. */
6745     gtk_widget_grab_default (button);
6746     gtk_widget_show (button);
6747     
6748     gtk_widget_show (window);
6749     
6750     gtk_main();
6751     
6752     return(0);
6753 }
6754 /* example-end */
6755 </verb></tscreen>
6756
6757 Try playing with resizing the window. You'll notice how the scrollbars
6758 react. You may also wish to use the gtk_widget_set_usize() call to set
6759 the default size of the window or other widgets.
6760
6761 <!-- ----------------------------------------------------------------- -->   
6762 <sect1>Button Boxes
6763 <p>
6764 Button Boxes are a convenient way to quickly layout a group of
6765 buttons. They come in both horizontal and vertical flavours. You
6766 create a new Button Box with one of the following calls, which create
6767 a horizontal or vertical box, respectively:
6768
6769 <tscreen><verb>
6770 GtkWidget *gtk_hbutton_box_new( void );
6771
6772 GtkWidget *gtk_vbutton_box_new( void );
6773 </verb></tscreen>
6774
6775 The only attributes pertaining to button boxes effect how the buttons
6776 are layed out. You can change the spacing between the buttons with:
6777
6778 <tscreen><verb>
6779 void gtk_hbutton_box_set_spacing_default( gint spacing );
6780
6781 void gtk_vbutton_box_set_spacing_default( gint spacing );
6782 </verb></tscreen>
6783
6784 Similarly, the current spacing values can be queried using:
6785
6786 <tscreen><verb>
6787 gint gtk_hbutton_box_get_spacing_default( void );
6788
6789 gint gtk_vbutton_box_get_spacing_default( void );
6790 </verb></tscreen>
6791
6792 The second attribute that we can access effects the layour of the
6793 buttons within the box. It is set using one of:
6794
6795 <tscreen><verb>
6796 void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6797
6798 void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6799 </verb></tscreen>
6800
6801 The <tt/layout/ argument can take one of the following values:
6802
6803 <itemize>
6804 <item> GTK_BUTTONBOX_DEFAULT_STYLE
6805 <item> GTK_BUTTONBOX_SPREAD
6806 <item> GTK_BUTTONBOX_EDGE
6807 <item> GTK_BUTTONBOX_START
6808 <item> GTK_BUTTONBOX_END
6809 </itemize>
6810
6811 The current layout setting can be retrieved using:
6812
6813 <tscreen><verb>
6814 GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
6815
6816 GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
6817 </verb></tscreen>
6818
6819 Buttons are added to a Button Box using the usual function:
6820
6821 <tscreen><verb>
6822     gtk_container_add( GTK_CONTAINER(button_box), child_widget );
6823 </verb></tscreen>
6824
6825 Here's an example that illustrates all the different layout settings
6826 for Button Boxes.
6827
6828 <tscreen><verb>
6829 /* example-start buttonbox buttonbox.c */
6830
6831 #include <gtk/gtk.h>
6832
6833 /* Create a Button Box with the specified parameters */
6834 GtkWidget *create_bbox (gint  horizontal,
6835                         char* title,
6836                         gint  spacing,
6837                         gint  child_w,
6838                         gint  child_h,
6839                         gint  layout)
6840 {
6841   GtkWidget *frame;
6842   GtkWidget *bbox;
6843   GtkWidget *button;
6844
6845   frame = gtk_frame_new (title);
6846
6847   if (horizontal)
6848     bbox = gtk_hbutton_box_new ();
6849   else
6850     bbox = gtk_vbutton_box_new ();
6851
6852   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
6853   gtk_container_add (GTK_CONTAINER (frame), bbox);
6854
6855   /* Set the appearance of the Button Box */
6856   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
6857   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
6858   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
6859
6860   button = gtk_button_new_with_label ("OK");
6861   gtk_container_add (GTK_CONTAINER (bbox), button);
6862
6863   button = gtk_button_new_with_label ("Cancel");
6864   gtk_container_add (GTK_CONTAINER (bbox), button);
6865
6866   button = gtk_button_new_with_label ("Help");
6867   gtk_container_add (GTK_CONTAINER (bbox), button);
6868
6869   return(frame);
6870 }
6871
6872 int main( int   argc,
6873           char *argv[] )
6874 {
6875   static GtkWidget* window = NULL;
6876   GtkWidget *main_vbox;
6877   GtkWidget *vbox;
6878   GtkWidget *hbox;
6879   GtkWidget *frame_horz;
6880   GtkWidget *frame_vert;
6881
6882   /* Initialize GTK */
6883   gtk_init( &amp;argc, &amp;argv );
6884
6885   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6886   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
6887
6888   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6889                       GTK_SIGNAL_FUNC(gtk_main_quit),
6890                       NULL);
6891
6892   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6893
6894   main_vbox = gtk_vbox_new (FALSE, 0);
6895   gtk_container_add (GTK_CONTAINER (window), main_vbox);
6896
6897   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
6898   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
6899
6900   vbox = gtk_vbox_new (FALSE, 0);
6901   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6902   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
6903
6904   gtk_box_pack_start (GTK_BOX (vbox),
6905            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
6906                       TRUE, TRUE, 0);
6907
6908   gtk_box_pack_start (GTK_BOX (vbox),
6909            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6910                       TRUE, TRUE, 5);
6911
6912   gtk_box_pack_start (GTK_BOX (vbox),
6913            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6914                       TRUE, TRUE, 5);
6915
6916   gtk_box_pack_start (GTK_BOX (vbox),
6917            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
6918                       TRUE, TRUE, 5);
6919
6920   frame_vert = gtk_frame_new ("Vertical Button Boxes");
6921   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
6922
6923   hbox = gtk_hbox_new (FALSE, 0);
6924   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6925   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
6926
6927   gtk_box_pack_start (GTK_BOX (hbox),
6928            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
6929                       TRUE, TRUE, 0);
6930
6931   gtk_box_pack_start (GTK_BOX (hbox),
6932            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6933                       TRUE, TRUE, 5);
6934
6935   gtk_box_pack_start (GTK_BOX (hbox),
6936            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6937                       TRUE, TRUE, 5);
6938
6939   gtk_box_pack_start (GTK_BOX (hbox),
6940            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
6941                       TRUE, TRUE, 5);
6942
6943   gtk_widget_show_all (window);
6944
6945   /* Enter the event loop */
6946   gtk_main ();
6947     
6948   return(0);
6949 }
6950 /* example-end */
6951 </verb></tscreen>
6952
6953 <!-- ----------------------------------------------------------------- -->   
6954 <sect1>Toolbar
6955 <p>
6956 Toolbars are usually used to group some number of widgets in order to
6957 simplify customization of their look and layout. Typically a toolbar
6958 consists of buttons with icons, labels and tooltips, but any other
6959 widget can also be put inside a toolbar. Finally, items can be
6960 arranged horizontally or vertically and buttons can be displayed with
6961 icons, labels or both.
6962
6963 Creating a toolbar is (as one may already suspect) done with the
6964 following function:
6965
6966 <tscreen><verb>
6967 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
6968                             GtkToolbarStyle  style );
6969 </verb></tscreen>
6970
6971 where orientation may be one of:
6972
6973 <tscreen><verb>
6974   GTK_ORIENTATION_HORIZONTAL    
6975   GTK_ORIENTATION_VERTICAL
6976 </verb></tscreen>
6977
6978 and style one of:
6979
6980 <tscreen><verb>
6981   GTK_TOOLBAR_TEXT
6982   GTK_TOOLBAR_ICONS
6983   GTK_TOOLBAR_BOTH
6984 </verb></tscreen>
6985
6986 The style applies to all the buttons created with the `item' functions
6987 (not to buttons inserted into toolbar as separate widgets).
6988
6989 After creating a toolbar one can append, prepend and insert items
6990 (that means simple buttons) into the toolbar. To describe an item we
6991 need a label text, a tooltip text, a private tooltip text, an icon for
6992 the button and a callback function for it. For example, to append or
6993 prepend an item you may use the following functions:
6994
6995 <tscreen><verb>
6996 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
6997                                     const char    *text,
6998                                     const char    *tooltip_text,
6999                                     const char    *tooltip_private_text,
7000                                     GtkWidget     *icon,
7001                                     GtkSignalFunc  callback,
7002                                     gpointer       user_data );
7003
7004 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
7005                                      const char    *text,
7006                                      const char    *tooltip_text,
7007                                      const char    *tooltip_private_text,
7008                                      GtkWidget     *icon,
7009                                      GtkSignalFunc  callback,
7010                                      gpointer       user_data );
7011 </verb></tscreen>
7012
7013 If you want to use gtk_toolbar_insert_item, the only additional
7014 parameter which must be specified is the position in which the item
7015 should be inserted, thus:
7016
7017 <tscreen><verb>
7018 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
7019                                     const char    *text,
7020                                     const char    *tooltip_text,
7021                                     const char    *tooltip_private_text,
7022                                     GtkWidget     *icon,
7023                                     GtkSignalFunc  callback,
7024                                     gpointer       user_data,
7025                                     gint           position );
7026 </verb></tscreen>
7027
7028 To simplify adding spaces between toolbar items, you may use the
7029 following functions:
7030
7031 <tscreen><verb>
7032 void gtk_toolbar_append_space( GtkToolbar *toolbar );
7033
7034 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
7035
7036 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
7037                                gint        position );
7038  
7039 </verb></tscreen>
7040
7041 While the size of the added space can be set globally for a
7042 whole toolbar with the function:
7043
7044 <tscreen><verb>
7045 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
7046                                  gint        space_size) ;
7047 </verb></tscreen>
7048
7049 If it's required, the orientation of a toolbar and its style can be
7050 changed `on the fly' using the following functions:
7051
7052 <tscreen><verb>
7053 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
7054                                   GtkOrientation  orientation );
7055
7056 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
7057                             GtkToolbarStyle  style );
7058
7059 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
7060                                gint        enable );
7061 </verb></tscreen>
7062
7063 Where <tt/orientation/ is one of GTK_ORIENTATION_HORIZONTAL or
7064 GTK_ORIENTATION_VERTICAL. The <tt/style/ is used to set appearance of
7065 the toolbar items by using one of GTK_TOOLBAR_ICONS, GTK_TOOLBAR_TEXT
7066 or GTK_TOOLBAR_BOTH.
7067
7068 To show some other things that can be done with a toolbar, let's take
7069 the following program (we'll interrupt the listing with some
7070 additional explanations):
7071
7072 <tscreen><verb>
7073 #include <gtk/gtk.h>
7074
7075 #include "gtk.xpm"
7076
7077 /* This function is connected to the Close button or
7078  * closing the window from the WM */
7079 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
7080 {
7081   gtk_main_quit ();
7082 }
7083 </verb></tscreen>
7084
7085 The above beginning seems for sure familiar to you if it's not your first
7086 GTK program. There is one additional thing though, we include a nice XPM
7087 picture to serve as an icon for all of the buttons.
7088
7089 <tscreen><verb>
7090 GtkWidget* close_button; /* This button will emit signal to close
7091                           * application */
7092 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7093 GtkWidget* text_button,
7094          * icon_button,
7095          * both_button; /* radio buttons for toolbar style */
7096 GtkWidget* entry; /* a text entry to show packing any widget into
7097                    * toolbar */
7098 </verb></tscreen>
7099
7100 In fact not all of the above widgets are needed here, but to make things
7101 clearer I put them all together.
7102
7103 <tscreen><verb>
7104 /* that's easy... when one of the buttons is toggled, we just
7105  * check which one is active and set the style of the toolbar
7106  * accordingly
7107  * ATTENTION: our toolbar is passed as data to callback ! */
7108 void radio_event (GtkWidget *widget, gpointer data)
7109 {
7110   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7111     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
7112   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7113     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
7114   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7115     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
7116 }
7117
7118 /* even easier, just check given toggle button and enable/disable 
7119  * tooltips */
7120 void toggle_event (GtkWidget *widget, gpointer data)
7121 {
7122   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
7123                             GTK_TOGGLE_BUTTON (widget)->active );
7124 }
7125 </verb></tscreen>
7126
7127 The above are just two callback functions that will be called when
7128 one of the buttons on a toolbar is pressed. You should already be
7129 familiar with things like this if you've already used toggle buttons (and
7130 radio buttons).
7131
7132 <tscreen><verb>
7133 int main (int argc, char *argv[])
7134 {
7135   /* Here is our main window (a dialog) and a handle for the handlebox */
7136   GtkWidget* dialog;
7137   GtkWidget* handlebox;
7138
7139   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7140      the buttons) and an icon widget to put this icon in (but 
7141      we'll create a separate widget for each button) */
7142   GtkWidget * toolbar;
7143   GdkPixmap * icon;
7144   GdkBitmap * mask;
7145   GtkWidget * iconw;
7146
7147   /* this is called in all GTK application. */
7148   gtk_init (&amp;argc, &amp;argv);
7149   
7150   /* create a new window with a given title, and nice size */
7151   dialog = gtk_dialog_new ();
7152   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
7153   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
7154   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
7155
7156   /* typically we quit if someone tries to close us */
7157   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
7158                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
7159
7160   /* we need to realize the window because we use pixmaps for 
7161    * items on the toolbar in the context of it */
7162   gtk_widget_realize ( dialog );
7163
7164   /* to make it nice we'll put the toolbar into the handle box, 
7165    * so that it can be detached from the main window */
7166   handlebox = gtk_handle_box_new ();
7167   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
7168                        handlebox, FALSE, FALSE, 5 );
7169 </verb></tscreen>
7170
7171 The above should be similar to any other GTK application. Just
7172 initialization of GTK, creating the window etc.. There is only one
7173 thing that probably needs some explanation: a handle box. A handle box
7174 is just another box that can be used to pack widgets in to. The
7175 difference between it and typical boxes is that it can be detached
7176 from a parent window (or, in fact, the handle box remains in the
7177 parent, but it is reduced to a very small rectangle, while all of its
7178 contents are reparented to a new freely floating window). It is
7179 usually nice to have a detachable toolbar, so these two widgets occur
7180 together quite often.
7181
7182 <tscreen><verb>
7183   /* toolbar will be horizontal, with both icons and text, and
7184    * with 5pxl spaces between items and finally, 
7185    * we'll also put it into our handlebox */
7186   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
7187                               GTK_TOOLBAR_BOTH );
7188   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
7189   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
7190   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
7191
7192   /* now we create icon with mask: we'll reuse it to create
7193    * icon widgets for toolbar items */
7194   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
7195       &amp;dialog->style->white, gtk_xpm );
7196 </verb></tscreen>
7197
7198 Well, what we do above is just a straight-forward initialization of
7199 the toolbar widget and creation of a GDK pixmap with its mask. If you
7200 want to know something more about using pixmaps, refer to GDK
7201 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
7202 earlier in this tutorial.
7203
7204 <tscreen><verb>
7205   /* our first item is <close> button */
7206   iconw = gtk_pixmap_new ( icon, mask ); /* icon widget */
7207   close_button = 
7208     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), /* our toolbar */
7209                               "Close",               /* button label */
7210                               "Closes this app",     /* this button's tooltip */
7211                               "Private",             /* tooltip private info */
7212                               iconw,                 /* icon widget */
7213                               GTK_SIGNAL_FUNC (delete_event), /* a signal */
7214                                NULL );
7215   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); /* space after item */
7216 </verb></tscreen>
7217
7218 In the above code you see the simplest case: adding a button to
7219 toolbar.  Just before appending a new item, we have to construct a
7220 pixmap widget to serve as an icon for this item; this step will have
7221 to be repeated for each new item. Just after the item we also add a
7222 space, so the following items will not touch each other. As you see
7223 gtk_toolbar_append_item returns a pointer to our newly created button
7224 widget, so that we can work with it in the normal way.
7225
7226 <tscreen><verb>
7227   /* now, let's make our radio buttons group... */
7228   iconw = gtk_pixmap_new ( icon, mask );
7229   icon_button = gtk_toolbar_append_element(
7230                     GTK_TOOLBAR(toolbar),
7231                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7232                     NULL,                          /* pointer to widget */
7233                     "Icon",                        /* label */
7234                     "Only icons in toolbar",       /* tooltip */
7235                     "Private",                     /* tooltip private string */
7236                     iconw,                         /* icon */
7237                     GTK_SIGNAL_FUNC (radio_event), /* signal */
7238                     toolbar);                      /* data for signal */
7239   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7240 </verb></tscreen>
7241
7242 Here we begin creating a radio buttons group. To do this we use
7243 gtk_toolbar_append_element.  In fact, using this function one can also
7244 add simple items or even spaces (type = GTK_TOOLBAR_CHILD_SPACE or
7245 GTK_TOOLBAR_CHILD_BUTTON). In the above case we start creating a radio
7246 group. In creating other radio buttons for this group a pointer to the
7247 previous button in the group is required, so that a list of buttons
7248 can be easily constructed (see the section on <ref
7249 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
7250 tutorial).
7251
7252 <tscreen><verb>
7253   /* following radio buttons refer to previous ones */
7254   iconw = gtk_pixmap_new ( icon, mask );
7255   text_button = 
7256     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7257                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7258                                icon_button,
7259                                "Text",
7260                                "Only texts in toolbar",
7261                                "Private",
7262                                iconw,
7263                                GTK_SIGNAL_FUNC (radio_event),
7264                                toolbar);
7265   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7266                                           
7267   iconw = gtk_pixmap_new ( icon, mask );
7268   both_button = 
7269     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7270                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7271                                text_button,
7272                                "Both",
7273                                "Icons and text in toolbar",
7274                                "Private",
7275                                iconw,
7276                                GTK_SIGNAL_FUNC (radio_event),
7277                                toolbar);
7278   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7279   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
7280 </verb></tscreen>
7281
7282 In the end we have set the state of one of the buttons manually (otherwise
7283 they all stay in active state, preventing us from switching between them).
7284
7285 <tscreen><verb>
7286   /* here we have just a simple toggle button */
7287   iconw = gtk_pixmap_new ( icon, mask );
7288   tooltips_button = 
7289     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7290                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7291                                NULL,
7292                                "Tooltips",
7293                                "Toolbar with or without tips",
7294                                "Private",
7295                                iconw,
7296                                GTK_SIGNAL_FUNC (toggle_event),
7297                                toolbar);
7298   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7299   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
7300 </verb></tscreen>
7301
7302 A toggle button can be created in the obvious way (if one knows how to create
7303 radio buttons already).
7304
7305 <tscreen><verb>
7306   /* to pack a widget into toolbar, we only have to 
7307    * create it and append it with an appropriate tooltip */
7308   entry = gtk_entry_new ();
7309   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
7310                              entry, 
7311                              "This is just an entry", 
7312                              "Private" );
7313
7314   /* well, it isn't created within thetoolbar, so we must still show it */
7315   gtk_widget_show ( entry );
7316 </verb></tscreen>
7317
7318 As you see, adding any kind of widget to a toolbar is simple. The
7319 one thing you have to remember is that this widget must be shown manually
7320 (contrary to other items which will be shown together with the toolbar).
7321
7322 <tscreen><verb>
7323   /* that's it ! let's show everything. */
7324   gtk_widget_show ( toolbar );
7325   gtk_widget_show (handlebox);
7326   gtk_widget_show ( dialog );
7327
7328   /* rest in gtk_main and wait for the fun to begin! */
7329   gtk_main ();
7330   
7331   return 0;
7332 }
7333 </verb></tscreen>
7334
7335 So, here we are at the end of toolbar tutorial. Of course, to appreciate
7336 it in full you need also this nice XPM icon, so here it is:
7337
7338 <tscreen><verb>
7339 /* XPM */
7340 static char * gtk_xpm[] = {
7341 "32 39 5 1",
7342 ".      c none",
7343 "+      c black",
7344 "@      c #3070E0",
7345 "#      c #F05050",
7346 "$      c #35E035",
7347 "................+...............",
7348 "..............+++++.............",
7349 "............+++++@@++...........",
7350 "..........+++++@@@@@@++.........",
7351 "........++++@@@@@@@@@@++........",
7352 "......++++@@++++++++@@@++.......",
7353 ".....+++@@@+++++++++++@@@++.....",
7354 "...+++@@@@+++@@@@@@++++@@@@+....",
7355 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7356 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7357 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7358 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7359 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7360 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7361 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7362 ".+######++++@@@@@@@++@$$$$$$$$+.",
7363 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7364 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7365 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7366 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7367 ".+####+++++++#++$$@+@$$++$$$$+..",
7368 ".++####++++++#++$$@+@$++@$$$$+..",
7369 ".+#####+++++##++$$++@+++$$$$$+..",
7370 ".++####+++##+#++$$+++++@$$$$$+..",
7371 ".++####+++####++$$++++++@$$$@+..",
7372 ".+#####++#####++$$+++@++++@$@+..",
7373 ".+#####++#####++$$++@$$@+++$@@..",
7374 ".++####++#####++$$++$$$$$+@$@++.",
7375 ".++####++#####++$$++$$$$$$$$+++.",
7376 ".+++####+#####++$$++$$$$$$$@+++.",
7377 "..+++#########+@$$+@$$$$$$+++...",
7378 "...+++########+@$$$$$$$$@+++....",
7379 ".....+++######+@$$$$$$$+++......",
7380 "......+++#####+@$$$$$@++........",
7381 ".......+++####+@$$$$+++.........",
7382 ".........++###+$$$@++...........",
7383 "..........++##+$@+++............",
7384 "...........+++++++..............",
7385 ".............++++..............."};
7386 </verb></tscreen>
7387
7388 <!-- ----------------------------------------------------------------- -->
7389 <sect1> Notebooks
7390 <p>
7391 The NoteBook Widget is a collection of 'pages' that overlap each
7392 other, each page contains different information. This widget has
7393 become more common lately in GUI programming, and it is a good way to
7394 show blocks of similar information that warrant separation in their
7395 display.
7396
7397 The first function call you will need to know, as you can probably
7398 guess by now, is used to create a new notebook widget.
7399
7400 <tscreen><verb>
7401 GtkWidget *gtk_notebook_new( void );
7402 </verb></tscreen>
7403
7404 Once the notebook has been created, there are a number of functions
7405 that operate on the notebook widget. Let's look at them individually.
7406
7407 The first one we will look at is how to position the page indicators.
7408 These page indicators or 'tabs' as they are referred to, can be
7409 positioned in four ways: top, bottom, left, or right.
7410
7411 <tscreen><verb>
7412 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7413                                GtkPositionType  pos );
7414 </verb></tscreen>
7415
7416 GtkPostionType will be one of the following, which are pretty self
7417 explanatory:
7418 <itemize>
7419 <item> GTK_POS_LEFT
7420 <item> GTK_POS_RIGHT
7421 <item> GTK_POS_TOP
7422 <item> GTK_POS_BOTTOM
7423 </itemize>
7424
7425 GTK_POS_TOP is the default.
7426
7427 Next we will look at how to add pages to the notebook. There are three
7428 ways to add pages to the NoteBook. Let's look at the first two
7429 together as they are quite similar.
7430
7431 <tscreen><verb>
7432 void gtk_notebook_append_page( GtkNotebook *notebook,
7433                                GtkWidget   *child,
7434                                GtkWidget   *tab_label );
7435
7436 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7437                                 GtkWidget   *child,
7438                                 GtkWidget   *tab_label );
7439 </verb></tscreen>
7440
7441 These functions add pages to the notebook by inserting them from the
7442 back of the notebook (append), or the front of the notebook (prepend).
7443 <tt/child/ is the widget that is placed within the notebook page, and
7444 <tt/tab_label/ is the label for the page being added. The <tt/child/
7445 widget must be created separately, and is typically a set of options
7446 setout witin one of the other container widgets, such as a table.
7447
7448 The final function for adding a page to the notebook contains all of
7449 the properties of the previous two, but it allows you to specify what
7450 position you want the page to be in the notebook.
7451
7452 <tscreen><verb>
7453 void gtk_notebook_insert_page( GtkNotebook *notebook,
7454                                GtkWidget   *child,
7455                                GtkWidget   *tab_label,
7456                                gint         position );
7457 </verb></tscreen>
7458
7459 The parameters are the same as _append_ and _prepend_ except it
7460 contains an extra parameter, <tt/position/.  This parameter is used to
7461 specify what place this page will be inserted into.
7462
7463 Now that we know how to add a page, lets see how we can remove a page
7464 from the notebook.
7465
7466 <tscreen><verb>
7467 void gtk_notebook_remove_page( GtkNotebook *notebook,
7468                                gint         page_num );
7469 </verb></tscreen>
7470
7471 This function takes the page specified by <tt/page_num/ and removes it
7472 from the widget pointed to by <tt/notebook/.
7473
7474 To find out what the current page is in a notebook use the function:
7475
7476 <tscreen><verb>
7477 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7478 </verb></tscreen>
7479
7480 These next two functions are simple calls to move the notebook page
7481 forward or backward. Simply provide the respective function call with
7482 the notebook widget you wish to operate on. Note: when the NoteBook is
7483 currently on the last page, and gtk_notebook_next_page is called, the
7484 notebook will wrap back to the first page. Likewise, if the NoteBook
7485 is on the first page, and gtk_notebook_prev_page is called, the
7486 notebook will wrap to the last page.
7487
7488 <tscreen><verb>
7489 void gtk_notebook_next_page( GtkNoteBook *notebook );
7490
7491 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7492 </verb></tscreen>
7493
7494 This next function sets the 'active' page. If you wish the notebook to
7495 be opened to page 5 for example, you would use this function.  Without
7496 using this function, the notebook defaults to the first page.
7497
7498 <tscreen><verb>
7499 void gtk_notebook_set_page( GtkNotebook *notebook,
7500                             gint         page_num );
7501 </verb></tscreen>
7502
7503 The next two functions add or remove the notebook page tabs and the
7504 notebook border respectively.
7505
7506 <tscreen><verb>
7507 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7508                                  gboolean     show_tabs);
7509
7510 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7511                                    gboolean     show_border );
7512 </verb></tscreen>
7513
7514 The next function is useful when the you have a large number of pages,
7515 and the tabs don't fit on the page. It allows the tabs to be scrolled
7516 through using two arrow buttons.
7517
7518 <tscreen><verb>
7519 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7520                                   gboolean     scrollable );
7521 </verb></tscreen>
7522
7523 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
7524 TRUE or FALSE.
7525
7526 Now lets look at an example, it is expanded from the testgtk.c code
7527 that comes with the GTK distribution. This small program creates a
7528 window with a notebook and six buttons. The notebook contains 11
7529 pages, added in three different ways, appended, inserted, and
7530 prepended. The buttons allow you rotate the tab positions, add/remove
7531 the tabs and border, remove a page, change pages in both a forward and
7532 backward manner, and exit the program.
7533
7534 <tscreen><verb>
7535 /* example-start notebook notebook.c */
7536
7537 #include <gtk/gtk.h>
7538
7539 /* This function rotates the position of the tabs */
7540 void rotate_book (GtkButton *button, GtkNotebook *notebook)
7541 {
7542     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
7543 }
7544
7545 /* Add/Remove the page tabs and the borders */
7546 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
7547 {
7548     gint tval = FALSE;
7549     gint bval = FALSE;
7550     if (notebook->show_tabs == 0)
7551             tval = TRUE; 
7552     if (notebook->show_border == 0)
7553             bval = TRUE;
7554     
7555     gtk_notebook_set_show_tabs (notebook, tval);
7556     gtk_notebook_set_show_border (notebook, bval);
7557 }
7558
7559 /* Remove a page from the notebook */
7560 void remove_book (GtkButton *button, GtkNotebook *notebook)
7561 {
7562     gint page;
7563     
7564     page = gtk_notebook_get_current_page(notebook);
7565     gtk_notebook_remove_page (notebook, page);
7566     /* Need to refresh the widget -- 
7567      This forces the widget to redraw itself. */
7568     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
7569 }
7570
7571 void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
7572 {
7573     gtk_main_quit ();
7574 }
7575
7576 int main (int argc, char *argv[])
7577 {
7578     GtkWidget *window;
7579     GtkWidget *button;
7580     GtkWidget *table;
7581     GtkWidget *notebook;
7582     GtkWidget *frame;
7583     GtkWidget *label;
7584     GtkWidget *checkbutton;
7585     int i;
7586     char bufferf[32];
7587     char bufferl[32];
7588     
7589     gtk_init (&amp;argc, &amp;argv);
7590     
7591     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7592     
7593     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
7594                         GTK_SIGNAL_FUNC (delete), NULL);
7595     
7596     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7597
7598     table = gtk_table_new(3,6,FALSE);
7599     gtk_container_add (GTK_CONTAINER (window), table);
7600     
7601     /* Create a new notebook, place the position of the tabs */
7602     notebook = gtk_notebook_new ();
7603     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
7604     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
7605     gtk_widget_show(notebook);
7606     
7607     /* Lets append a bunch of pages to the notebook */
7608     for (i=0; i < 5; i++) {
7609         sprintf(bufferf, "Append Frame %d", i+1);
7610         sprintf(bufferl, "Page %d", i+1);
7611         
7612         frame = gtk_frame_new (bufferf);
7613         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7614         gtk_widget_set_usize (frame, 100, 75);
7615         gtk_widget_show (frame);
7616         
7617         label = gtk_label_new (bufferf);
7618         gtk_container_add (GTK_CONTAINER (frame), label);
7619         gtk_widget_show (label);
7620         
7621         label = gtk_label_new (bufferl);
7622         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
7623     }
7624       
7625     /* Now lets add a page to a specific spot */
7626     checkbutton = gtk_check_button_new_with_label ("Check me please!");
7627     gtk_widget_set_usize(checkbutton, 100, 75);
7628     gtk_widget_show (checkbutton);
7629    
7630     label = gtk_label_new ("Add page");
7631     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
7632     
7633     /* Now finally lets prepend pages to the notebook */
7634     for (i=0; i < 5; i++) {
7635         sprintf(bufferf, "Prepend Frame %d", i+1);
7636         sprintf(bufferl, "PPage %d", i+1);
7637         
7638         frame = gtk_frame_new (bufferf);
7639         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7640         gtk_widget_set_usize (frame, 100, 75);
7641         gtk_widget_show (frame);
7642         
7643         label = gtk_label_new (bufferf);
7644         gtk_container_add (GTK_CONTAINER (frame), label);
7645         gtk_widget_show (label);
7646         
7647         label = gtk_label_new (bufferl);
7648         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
7649     }
7650     
7651     /* Set what page to start at (page 4) */
7652     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
7653
7654     /* Create a bunch of buttons */
7655     button = gtk_button_new_with_label ("close");
7656     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7657                                GTK_SIGNAL_FUNC (delete), NULL);
7658     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
7659     gtk_widget_show(button);
7660     
7661     button = gtk_button_new_with_label ("next page");
7662     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7663                                (GtkSignalFunc) gtk_notebook_next_page,
7664                                GTK_OBJECT (notebook));
7665     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
7666     gtk_widget_show(button);
7667     
7668     button = gtk_button_new_with_label ("prev page");
7669     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7670                                (GtkSignalFunc) gtk_notebook_prev_page,
7671                                GTK_OBJECT (notebook));
7672     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
7673     gtk_widget_show(button);
7674     
7675     button = gtk_button_new_with_label ("tab position");
7676     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7677                         (GtkSignalFunc) rotate_book,
7678                         GTK_OBJECT(notebook));
7679     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
7680     gtk_widget_show(button);
7681     
7682     button = gtk_button_new_with_label ("tabs/border on/off");
7683     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7684                         (GtkSignalFunc) tabsborder_book,
7685                         GTK_OBJECT (notebook));
7686     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
7687     gtk_widget_show(button);
7688     
7689     button = gtk_button_new_with_label ("remove page");
7690     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7691                         (GtkSignalFunc) remove_book,
7692                         GTK_OBJECT(notebook));
7693     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
7694     gtk_widget_show(button);
7695     
7696     gtk_widget_show(table);
7697     gtk_widget_show(window);
7698     
7699     gtk_main ();
7700     
7701     return(0);
7702 }
7703 /* example-end */
7704 </verb></tscreen>
7705
7706 Hopefully this helps you on your way with creating notebooks for your
7707 GTK applications.
7708
7709 <!-- ***************************************************************** -->
7710 <sect>CList Widget
7711 <!-- ***************************************************************** -->
7712
7713 <!-- ----------------------------------------------------------------- -->
7714 <p>
7715 The GtkCList widget has replaced the GtkList widget (which is still
7716 available).
7717
7718 The GtkCList widget is a multi-column list widget that is capable of
7719 handling literally thousands of rows of information. Each column can
7720 optionally have a title, which itself is optionally active, allowing
7721 us to bind a function to its selection.
7722
7723 <!-- ----------------------------------------------------------------- -->
7724 <sect1>Creating a GtkCList widget
7725 <p>
7726 Creating a GtkCList is quite straightforward, once you have learned
7727 about widgets in general. It provides the almost standard two ways,
7728 that is the hard way, and the easy way. But before we create it, there
7729 is one thing we should figure out beforehand: how many columns should
7730 it have?
7731
7732 Not all columns have to be visible and can be used to store data that
7733 is related to a certain cell in the list.
7734
7735 <tscreen><verb>
7736 GtkWidget *gtk_clist_new ( gint columns );
7737
7738 GtkWidget *gtk_clist_new_with_titles( gint   columns,
7739                                       gchar *titles[] );
7740 </verb></tscreen>
7741
7742 The first form is very straight forward, the second might require some
7743 explanation. Each column can have a title associated with it, and this
7744 title can be a label or a button that reacts when we click on it. If
7745 we use the second form, we must provide pointers to the title texts,
7746 and the number of pointers should equal the number of columns
7747 specified. Of course we can always use the first form, and manually
7748 add titles later.
7749
7750 Note: the GtkCList widget does not have its own scrollbars and should
7751 be placed within a GtkScrolledWindow widget if your require this
7752 functionality. This is a change from the GTK 1.0 implementation.
7753
7754 <!-- ----------------------------------------------------------------- -->
7755 <sect1>Modes of operation
7756 <p>
7757 There are several attributes that can be used to alter the behaviour of
7758 a GtkCList. First there is
7759
7760 <tscreen><verb>
7761 void gtk_clist_set_selection_mode( GtkCList         *clist,
7762                                    GtkSelectionMode  mode );
7763 </verb></tscreen>
7764
7765 which, as the name implies, sets the selection mode of the
7766 GtkCList. The first argument is the GtkCList widget, and the second
7767 specifies the cell selection mode (they are defined in gtkenums.h). At
7768 the time of this writing, the following modes are available to us:
7769
7770 <itemize>
7771 <item> GTK_SELECTION_SINGLE - The selection is either NULL or contains
7772 a GList pointer for a single selected item.
7773
7774 <item> GTK_SELECTION_BROWSE - The selection is NULL if the list
7775 contains no widgets or insensitive ones only, otherwise it contains a
7776 GList pointer for one GList structure, and therefore exactly one list
7777 item.
7778
7779 <item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list items
7780 are selected or a GList pointer for the first selected item. That in
7781 turn points to a GList structure for the second selected item and so
7782 on. This is currently the <bf>default</bf> for the GtkCList widget.
7783
7784 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
7785 </itemize>
7786
7787 Others might be added in later revisions of GTK.
7788
7789 We can also define what the border of the GtkCList widget should look
7790 like. It is done through
7791
7792 <tscreen><verb>
7793 void gtk_clist_set_shadow_type( GtkCList      *clist,
7794                                 GtkShadowType  border );
7795 </verb></tscreen>
7796
7797 And the possible values for the second argument are
7798
7799 <itemize>
7800 <item> GTK_SHADOW_NONE
7801
7802 <item> GTK_SHADOW_IN
7803
7804 <item> GTK_SHADOW_OUT
7805
7806 <item> GTK_SHADOW_ETCHED_IN
7807
7808 <item> GTK_SHADOW_ETCHED_OUT
7809 </itemize>
7810
7811 <!-- ----------------------------------------------------------------- -->
7812 <sect1>Working with titles
7813 <p>
7814 When you create a GtkCList widget, you will also get a set of title
7815 buttons automatically. They live in the top of the CList window, and
7816 can act either as normal buttons that respond to being pressed, or
7817 they can be passive, in which case they are nothing more than a
7818 title. There are four different calls that aid us in setting the
7819 status of the title buttons.
7820
7821 <tscreen><verb>
7822 void gtk_clist_column_title_active( GtkCList *clist,
7823                                      gint     column );
7824
7825 void gtk_clist_column_title_passive( GtkCList *clist,
7826                                      gint      column );
7827
7828 void gtk_clist_column_titles_active( GtkCList *clist );
7829
7830 void gtk_clist_column_titles_passive( GtkCList *clist );
7831 </verb></tscreen>
7832
7833 An active title is one which acts as a normal button, a passive one is
7834 just a label. The first two calls above will activate/deactivate the
7835 title button above the specific column, while the last two calls
7836 activate/deactivate all title buttons in the supplied clist widget.
7837
7838 But of course there are those cases when we don't want them at all,
7839 and so they can be hidden and shown at will using the following two
7840 calls.
7841
7842 <tscreen><verb>
7843 void gtk_clist_column_titles_show( GtkCList *clist );
7844
7845 void gtk_clist_column_titles_hide( GtkCList *clist );
7846 </verb></tscreen>
7847
7848 For titles to be really useful we need a mechanism to set and change
7849 them, and this is done using
7850
7851 <tscreen><verb>
7852 void gtk_clist_set_column_title( GtkCList *clist,
7853                                  gint      column,
7854                                  gchar    *title );
7855 </verb></tscreen>
7856
7857 Note that only the title of one column can be set at a time, so if all
7858 the titles are known from the beginning, then I really suggest using
7859 gtk_clist_new_with_titles (as described above) to set them. Saves you
7860 coding time, and makes your program smaller. There are some cases
7861 where getting the job done the manual way is better, and that's when
7862 not all titles will be text. GtkCList provides us with title buttons
7863 that can in fact incorporate whole widgets, for example a pixmap. It's
7864 all done through
7865
7866 <tscreen><verb>
7867 void gtk_clist_set_column_widget( GtkCList  *clist,
7868                                   gint       column,
7869                                   GtkWidget *widget );
7870 </verb></tscreen>
7871
7872 which should require no special explanation.
7873
7874 <!-- ----------------------------------------------------------------- -->
7875 <sect1>Manipulating the list itself
7876 <p>
7877 It is possible to change the justification for a column, and it is
7878 done through
7879
7880 <tscreen><verb>
7881 void gtk_clist_set_column_justification( GtkCList         *clist,
7882                                          gint              column,
7883                                          GtkJustification  justification );
7884 </verb></tscreen>
7885
7886 The GtkJustification type can take the following values:
7887
7888 <itemize>
7889 <item>GTK_JUSTIFY_LEFT - The text in the column will begin from the
7890 left edge.
7891
7892 <item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the
7893 right edge.
7894
7895 <item>GTK_JUSTIFY_CENTER - The text is placed in the center of the
7896 column.
7897
7898 <item>GTK_JUSTIFY_FILL - The text will use up all available space in
7899 the column. It is normally done by inserting extra blank spaces
7900 between words (or between individual letters if it's a single
7901 word). Much in the same way as any ordinary WYSIWYG text editor.
7902 </itemize>
7903
7904 The next function is a very important one, and should be standard in
7905 the setup of all GtkCList widgets. When the list is created, the width
7906 of the various columns are chosen to match their titles, and since
7907 this is seldom the right width we have to set it using
7908
7909 <tscreen><verb>
7910 void gtk_clist_set_column_width( GtkCList *clist,
7911                                  gint      column,
7912                                  gint      width );
7913 </verb></tscreen>
7914
7915 Note that the width is given in pixels and not letters. The same goes
7916 for the height of the cells in the columns, but as the default value
7917 is the height of the current font this isn't as critical to the
7918 application. Still, it is done through
7919
7920 <tscreen><verb>
7921 void gtk_clist_set_row_height( GtkCList *clist,
7922                                gint      height );
7923 </verb></tscreen>
7924
7925 Again, note that the height is given in pixels.
7926
7927 We can also move the list around without user interaction, however, it
7928 does require that we know what we are looking for. Or in other words,
7929 we need the row and column of the item we want to scroll to.
7930
7931 <tscreen><verb>
7932 void gtk_clist_moveto( GtkCList *clist,
7933                        gint      row,
7934                        gint      column,
7935                        gfloat    row_align,
7936                        gfloat    col_align );
7937 </verb></tscreen>
7938
7939 The gfloat row_align is pretty important to understand. It's a value
7940 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
7941 the row appears at the top, while if the value of row_align is 1.0,
7942 the row will appear at the bottom instead. All other values between
7943 0.0 and 1.0 are also valid and will place the row between the top and
7944 the bottom. The last argument, gfloat col_align works in the same way,
7945 though 0.0 marks left and 1.0 marks right instead.
7946
7947 Depending on the application's needs, we don't have to scroll to an
7948 item that is already visible to us. So how do we know if it is
7949 visible? As usual, there is a function to find that out as well.
7950
7951 <tscreen><verb>
7952 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
7953                                         gint      row );
7954 </verb></tscreen>
7955
7956 The return value is is one of the following:
7957
7958 <itemize>
7959 <item>GTK_VISIBILITY_NONE
7960
7961 <item>GTK_VISIBILITY_PARTIAL
7962
7963 <item>GTK_VISIBILITY_FULL
7964 </itemize>
7965
7966 Note that it will only tell us if a row is visible. Currently there is
7967 no way to determine this for a column. We can get partial information
7968 though, because if the return is GTK_VISIBILITY_PARTIAL, then some of
7969 it is hidden, but we don't know if it is the row that is being cut by
7970 the lower edge of the listbox, or if the row has columns that are
7971 outside.
7972
7973 We can also change both the foreground and background colors of a
7974 particular row. This is useful for marking the row selected by the
7975 user, and the two functions that is used to do it are
7976
7977 <tscreen><verb>
7978 void gtk_clist_set_foreground( GtkCList *clist,
7979                                gint      row,
7980                                GdkColor *color );
7981
7982 void gtk_clist_set_background( GtkCList *clist,
7983                                gint      row,
7984                                GdkColor *color );
7985 </verb></tscreen>
7986
7987 Please note that the colors must have been previously allocated.
7988
7989 <!-- ----------------------------------------------------------------- -->
7990 <sect1>Adding rows to the list
7991 <p>
7992 We can add rows in three ways. They can be prepended or appended to
7993 the list using
7994
7995 <tscreen><verb>
7996 gint gtk_clist_prepend( GtkCList *clist,
7997                         gchar    *text[] );
7998
7999 gint gtk_clist_append( GtkCList *clist,
8000                        gchar    *text[] );
8001 </verb></tscreen>
8002
8003 The return value of these two functions indicate the index of the row
8004 that was just added. We can insert a row at a given place using
8005
8006 <tscreen><verb>
8007 void gtk_clist_insert( GtkCList *clist,
8008                        gint      row,
8009                        gchar    *text[] );
8010 </verb></tscreen>
8011
8012 In these calls we have to provide a collection of pointers that are
8013 the texts we want to put in the columns. The number of pointers should
8014 equal the number of columns in the list. If the text[] argument is
8015 NULL, then there will be no text in the columns of the row. This is
8016 useful, for example, if we want to add pixmaps instead (something that
8017 has to be done manually).
8018
8019 Also, please note that the numbering of both rows and columns start at 0.
8020
8021 To remove an individual row we use
8022
8023 <tscreen><verb>
8024 void gtk_clist_remove( GtkCList *clist,
8025                        gint      row );
8026 </verb></tscreen>
8027
8028 There is also a call that removes all rows in the list. This is a lot
8029 faster than calling gtk_clist_remove once for each row, which is the
8030 only alternative.
8031
8032 <tscreen><verb>
8033 void gtk_clist_clear( GtkCList *clist );
8034 </verb></tscreen>
8035
8036 There are also two convenience functions that should be used when a
8037 lot of changes have to be made to the list. This is to prevent the
8038 list flickering while being repeatedly updated, which may be highly
8039 annoying to the user. So instead it is a good idea to freeze the list,
8040 do the updates to it, and finally thaw it which causes the list to be
8041 updated on the screen.
8042
8043 <tscreen><verb>
8044 void gtk_clist_freeze( GtkCList * clist );
8045
8046 void gtk_clist_thaw( GtkCList * clist );
8047 </verb></tscreen>
8048
8049 <!-- ----------------------------------------------------------------- -->
8050 <sect1>Setting text and pixmaps in the cells
8051 <p>
8052 A cell can contain a pixmap, text or both. To set them the following
8053 functions are used.
8054
8055 <tscreen><verb>
8056 void gtk_clist_set_text( GtkCList *clist,
8057                          gint      row,
8058                          gint      column,
8059                          gchar    *text );
8060
8061 void gtk_clist_set_pixmap( GtkCList  *clist,
8062                            gint       row,
8063                            gint       column,
8064                            GdkPixmap *pixmap,
8065                            GdkBitmap *mask );
8066
8067 void gtk_clist_set_pixtext( GtkCList  *clist,
8068                             gint       row,
8069                             gint       column,
8070                             gchar     *text,
8071                             guint8     spacing,
8072                             GdkPixmap *pixmap,
8073                             GdkBitmap *mask );
8074 </verb></tscreen>
8075
8076 It's quite straightforward. All the calls have the GtkCList as the
8077 first argument, followed by the row and column of the cell, followed
8078 by the data to be set. The <tt/spacing/ argument in
8079 gtk_clist_set_pixtext is the number of pixels between the pixmap and
8080 the beginning of the text.
8081
8082 To read back the data, we instead use
8083
8084 <tscreen><verb>
8085 gint gtk_clist_get_text( GtkCList  *clist,
8086                          gint       row,
8087                          gint       column,
8088                          gchar    **text );
8089
8090 gint gtk_clist_get_pixmap( GtkCList   *clist,
8091                            gint        row,
8092                            gint        column,
8093                            GdkPixmap **pixmap,
8094                            GdkBitmap **mask );
8095
8096 gint gtk_clist_get_pixtext( GtkCList   *clist,
8097                             gint        row,
8098                             gint        column,
8099                             gchar     **text,
8100                             guint8     *spacing,
8101                             GdkPixmap **pixmap,
8102                             GdkBitmap **mask );
8103 </verb></tscreen>
8104
8105 It isn't necessary to read it all back in case you aren't
8106 interested. Any of the pointers that are meant for return values (all
8107 except the clist) can be NULL. So if we want to read back only the
8108 text from a cell that is of type pixtext, then we would do the
8109 following, assuming that clist, row and column already exist:
8110
8111 <tscreen><verb>
8112 gchar *mytext;
8113
8114 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
8115 </verb></tscreen>
8116
8117 There is one more call that is related to what's inside a cell in the
8118 clist, and that's
8119
8120 <tscreen><verb>
8121 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
8122                                      gint      row,
8123                                      gint      column );
8124 </verb></tscreen>
8125
8126 which returns the type of data in a cell. The return value is one of
8127
8128 <itemize>
8129 <item>GTK_CELL_EMPTY
8130
8131 <item>GTK_CELL_TEXT
8132
8133 <item>GTK_CELL_PIXMAP
8134
8135 <item>GTK_CELL_PIXTEXT
8136
8137 <item>GTK_CELL_WIDGET
8138 </itemize>
8139
8140 There is also a function that will let us set the indentation, both
8141 vertical and horizontal, of a cell. The indentation value is of type
8142 gint, given in pixels, and can be both positive and negative.
8143
8144 <tscreen><verb>
8145 void gtk_clist_set_shift( GtkCList *clist,
8146                           gint      row,
8147                           gint      column,
8148                           gint      vertical,
8149                           gint      horizontal );
8150 </verb></tscreen>
8151
8152 <!-- ----------------------------------------------------------------- -->
8153 <sect1>Storing data pointers
8154 <p>
8155 With a GtkCList it is possible to set a data pointer for a row. This
8156 pointer will not be visible for the user, but is merely a convenience
8157 for the programmer to associate a row with a pointer to some
8158 additional data.
8159
8160 The functions should be fairly self-explanatory by now
8161
8162 <tscreen><verb>
8163 void gtk_clist_set_row_data( GtkCList *clist,
8164                              gint      row,
8165                              gpointer  data );
8166
8167 void gtk_clist_set_row_data_full( GtkCList         *clist,
8168                                   gint              row,
8169                                   gpointer          data,
8170                                   GtkDestroyNotify  destroy );
8171
8172 gpointer gtk_clist_get_row_data( GtkCList *clist,
8173                                  gint      row );
8174
8175 gint gtk_clist_find_row_from_data( GtkCList *clist,
8176                                    gpointer  data );
8177 </verb></tscreen>
8178
8179 <!-- ----------------------------------------------------------------- -->
8180 <sect1>Working with selections
8181 <p>
8182 There are also functions available that let us force the (un)selection
8183 of a row. These are
8184
8185 <tscreen><verb>
8186 void gtk_clist_select_row( GtkCList *clist,
8187                            gint      row,
8188                            gint      column );
8189
8190 void gtk_clist_unselect_row( GtkCList *clist,
8191                              gint      row,
8192                              gint      column );
8193 </verb></tscreen>
8194
8195 And also a function that will take x and y coordinates (for example,
8196 read from the mousepointer), and map that onto the list, returning the
8197 corresponding row and column.
8198
8199 <tscreen><verb>
8200 gint gtk_clist_get_selection_info( GtkCList *clist,
8201                                    gint      x,
8202                                    gint      y,
8203                                    gint     *row,
8204                                    gint     *column );
8205 </verb></tscreen>
8206
8207 When we detect something of interest, it might be movement of the
8208 pointer, a click somewhere in the list, we can read the pointer
8209 coordinates and find out where in the list the pointer is. Cumbersome?
8210 Luckily, there is a simpler way...
8211
8212 <!-- ----------------------------------------------------------------- -->
8213 <sect1>The signals that bring it together
8214 <p>
8215 As with all other widgets, there are a few signals that can be used. The
8216 GtkCList widget is derived from the GtkContainer widget, and so has all the
8217 same signals, but also the adds following:
8218
8219 <itemize>
8220 <item>select_row - This signal will send the following information, in
8221 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
8222
8223 <item>unselect_row - When the user unselects a row, this signal is
8224 activated. It sends the same information as select_row
8225
8226 <item>click_column - Send GtkCList *clist, gint column
8227 </itemize>
8228
8229 So if we want to connect a callback to select_row, the callback
8230 function would be declared like this
8231
8232 <tscreen><verb>
8233 void select_row_callback(GtkWidget *widget,
8234                          gint row,
8235                          gint column,
8236                          GdkEventButton *event,
8237                          gpointer data);
8238 </verb></tscreen>
8239
8240 The callback is connected as usual with
8241
8242 <tscreen><verb>
8243 gtk_signal_connect(GTK_OBJECT( clist),
8244                    "select_row"
8245                    GTK_SIGNAL_FUNC(select_row_callback),
8246                    NULL);
8247 </verb></tscreen>
8248
8249 <!-- ----------------------------------------------------------------- -->
8250 <sect1>A GtkCList example
8251 <p>
8252
8253 <tscreen><verb>
8254 /* example-start clist clist.c */
8255
8256 #include <gtk/gtk.h>
8257
8258 /* User clicked the "Add List" button. */
8259 void button_add_clicked( gpointer data )
8260 {
8261     int indx;
8262  
8263     /* Something silly to add to the list. 4 rows of 2 columns each */
8264     gchar *drink[4][2] = { { "Milk",    "3 Oz" },
8265                            { "Water",   "6 l" },
8266                            { "Carrots", "2" },
8267                            { "Snakes",  "55" } };
8268
8269     /* Here we do the actual adding of the text. It's done once for
8270      * each row.
8271      */
8272     for ( indx=0 ; indx < 4 ; indx++ )
8273         gtk_clist_append( (GtkCList *) data, drink[indx]);
8274
8275     return;
8276 }
8277
8278 /* User clicked the "Clear List" button. */
8279 void button_clear_clicked( gpointer data )
8280 {
8281     /* Clear the list using gtk_clist_clear. This is much faster than
8282      * calling gtk_clist_remove once for each row.
8283      */
8284     gtk_clist_clear( (GtkCList *) data);
8285
8286     return;
8287 }
8288
8289 /* The user clicked the "Hide/Show titles" button. */
8290 void button_hide_show_clicked( gpointer data )
8291 {
8292     /* Just a flag to remember the status. 0 = currently visible */
8293     static short int flag = 0;
8294
8295     if (flag == 0)
8296     {
8297         /* Hide the titles and set the flag to 1 */
8298         gtk_clist_column_titles_hide((GtkCList *) data);
8299         flag++;
8300     }
8301     else
8302     {
8303         /* Show the titles and reset flag to 0 */
8304         gtk_clist_column_titles_show((GtkCList *) data);
8305         flag--;
8306     }
8307
8308     return;
8309 }
8310
8311 /* If we come here, then the user has selected a row in the list. */
8312 void selection_made( GtkWidget      *clist,
8313                      gint            row,
8314                      gint            column,
8315                      GdkEventButton *event,
8316                      gpointer        data )
8317 {
8318     gchar *text;
8319
8320     /* Get the text that is stored in the selected row and column
8321      * which was clicked in. We will receive it as a pointer in the
8322      * argument text.
8323      */
8324     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
8325
8326     /* Just prints some information about the selected row */
8327     g_print("You selected row %d. More specifically you clicked in "
8328             "column %d, and the text in this cell is %s\n\n",
8329             row, column, text);
8330
8331     return;
8332 }
8333
8334 int main( int    argc,
8335           gchar *argv[] )
8336 {                                  
8337     GtkWidget *window;
8338     GtkWidget *vbox, *hbox;
8339     GtkWidget *clist;
8340     GtkWidget *button_add, *button_clear, *button_hide_show;    
8341     gchar *titles[2] = { "Ingredients", "Amount" };
8342
8343     gtk_init(&amp;argc, &amp;argv);
8344     
8345     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
8346     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
8347
8348     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
8349     gtk_signal_connect(GTK_OBJECT(window),
8350                        "destroy",
8351                        GTK_SIGNAL_FUNC(gtk_main_quit),
8352                        NULL);
8353     
8354     vbox=gtk_vbox_new(FALSE, 5);
8355     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
8356     gtk_container_add(GTK_CONTAINER(window), vbox);
8357     gtk_widget_show(vbox);
8358     
8359     /* Create the GtkCList. For this example we use 2 columns */
8360     clist = gtk_clist_new_with_titles( 2, titles);
8361
8362     /* When a selection is made, we want to know about it. The callback
8363      * used is selection_made, and its code can be found further down */
8364     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
8365                        GTK_SIGNAL_FUNC(selection_made),
8366                        NULL);
8367
8368     /* It isn't necessary to shadow the border, but it looks nice :) */
8369     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
8370
8371     /* What however is important, is that we set the column widths as
8372      * they will never be right otherwise. Note that the columns are
8373      * numbered from 0 and up (to 1 in this case).
8374      */
8375     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
8376
8377     /* Add the GtkCList widget to the vertical box and show it. */
8378     gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
8379     gtk_widget_show(clist);
8380
8381     /* Create the buttons and add them to the window. See the button
8382      * tutorial for more examples and comments on this.
8383      */
8384     hbox = gtk_hbox_new(FALSE, 0);
8385     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
8386     gtk_widget_show(hbox);
8387
8388     button_add = gtk_button_new_with_label("Add List");
8389     button_clear = gtk_button_new_with_label("Clear List");
8390     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
8391
8392     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
8393     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
8394     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
8395
8396     /* Connect our callbacks to the three buttons */
8397     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
8398                               GTK_SIGNAL_FUNC(button_add_clicked),
8399                               (gpointer) clist);
8400     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
8401                               GTK_SIGNAL_FUNC(button_clear_clicked),
8402                               (gpointer) clist);
8403     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
8404                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
8405                               (gpointer) clist);
8406
8407     gtk_widget_show(button_add);
8408     gtk_widget_show(button_clear);
8409     gtk_widget_show(button_hide_show);
8410
8411     /* The interface is completely set up so we show the window and
8412      * enter the gtk_main loop.
8413      */
8414     gtk_widget_show(window);
8415     gtk_main();
8416     
8417     return(0);
8418 }
8419 /* example-end */
8420 </verb></tscreen>
8421                     
8422 <!-- ***************************************************************** -->
8423 <sect> Tree Widget <label id="sec_Tree_Widgets">
8424 <!-- ***************************************************************** -->
8425 <p>
8426 The purpose of tree widgets is to display hierarchically-organized
8427 data. The GtkTree widget itself is a vertical container for widgets of
8428 type GtkTreeItem. GtkTree itself is not terribly different from
8429 GtkList - both are derived directly from GtkContainer, and the
8430 GtkContainer methods work in the same way on GtkTree widgets as on
8431 GtkList widgets. The difference is that GtkTree widgets can be nested
8432 within other GtkTree widgets. We'll see how to do this shortly.
8433
8434 The GtkTree widget has its own window, and defaults to a white
8435 background, as does GtkList. Also, most of the GtkTree methods work in
8436 the same way as the corresponding GtkList ones. However, GtkTree is
8437 not derived from GtkList, so you cannot use them interchangeably.
8438
8439 <sect1> Creating a Tree
8440 <p>
8441 A GtkTree is created in the usual way, using:
8442
8443 <tscreen><verb>
8444 GtkWidget *gtk_tree_new( void );
8445 </verb></tscreen>
8446
8447 Like the GtkList widget, a GtkTree will simply keep growing as more
8448 items are added to it, as well as when subtrees are expanded.  For
8449 this reason, they are almost always packed into a
8450 GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
8451 scrolled window to ensure that it is big enough to see the tree's
8452 items, as the default size for GtkScrolledWindow is quite small.
8453
8454 Now that you have a tree, you'll probably want to add some items to
8455 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
8456 explains the gory details of GtkTreeItem. For now, it'll suffice to
8457 create one, using:
8458
8459 <tscreen><verb>
8460 GtkWidget *gtk_tree_item_new_with_label( gchar *label );
8461 </verb></tscreen>
8462
8463 You can then add it to the tree using one of the following (see
8464 <ref id="sec_GtkTree_Functions" name="Functions and Macros">
8465 below for more options):
8466
8467 <tscreen><verb>
8468 void gtk_tree_append( GtkTree    *tree,
8469                        GtkWidget *tree_item );
8470
8471 void gtk_tree_prepend( GtkTree   *tree,
8472                        GtkWidget *tree_item );
8473 </verb></tscreen>
8474
8475 Note that you must add items to a GtkTree one at a time - there is no
8476 equivalent to gtk_list_*_items().
8477
8478 <!-- ----------------------------------------------------------------- -->
8479 <sect1> Adding a Subtree
8480 <p>
8481 A subtree is created like any other GtkTree widget. A subtree is added
8482 to another tree beneath a tree item, using:
8483
8484 <tscreen><verb>
8485 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8486                                 GtkWidget   *subtree );
8487 </verb></tscreen>
8488
8489 You do not need to call gtk_widget_show() on a subtree before or after
8490 adding it to a GtkTreeItem. However, you <em>must</em> have added the
8491 GtkTreeItem in question to a parent tree before calling
8492 gtk_tree_item_set_subtree(). This is because, technically, the parent
8493 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
8494 rather the GtkTree which holds that GtkTreeItem.
8495
8496 When you add a subtree to a GtkTreeItem, a plus or minus sign appears
8497 beside it, which the user can click on to "expand" or "collapse" it,
8498 meaning, to show or hide its subtree. GtkTreeItems are collapsed by
8499 default. Note that when you collapse a GtkTreeItem, any selected
8500 items in its subtree remain selected, which may not be what the user
8501 expects.
8502
8503 <!-- ----------------------------------------------------------------- -->
8504 <sect1> Handling the Selection List
8505 <p>
8506 As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
8507 it is possible to control the behaviour of the tree (somewhat) by
8508 setting the selection type using:
8509
8510 <tscreen><verb>
8511 void gtk_tree_set_selection_mode( GtkTree          *tree,
8512                                   GtkSelectionMode  mode );
8513 </verb></tscreen>
8514
8515 The semantics associated with the various selection modes are
8516 described in the section on the GtkList widget. As with the GtkList
8517 widget, the "select_child", "unselect_child" (not really - see <ref
8518 id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
8519 and "selection_changed" signals are emitted when list items are
8520 selected or unselected. However, in order to take advantage of these
8521 signals, you need to know <em>which</em> GtkTree widget they will be
8522 emitted by, and where to find the list of selected items.
8523
8524 This is a source of potential confusion. The best way to explain this
8525 is that though all GtkTree widgets are created equal, some are more
8526 equal than others. All GtkTree widgets have their own X window, and
8527 can therefore receive events such as mouse clicks (if their
8528 GtkTreeItems or their children don't catch them first!). However, to
8529 make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
8530 behave in a sane manner, the list of selected items is specific to the
8531 topmost GtkTree widget in a hierarchy, known as the "root tree".
8532
8533 Thus, accessing the <tt>selection</tt>field directly in an arbitrary
8534 GtkTree widget is not a good idea unless you <em>know</em> it's the
8535 root tree.  Instead, use the GTK_TREE_SELECTION (Tree) macro, which
8536 gives the root tree's selection list as a GList pointer. Of course,
8537 this list can include items that are not in the subtree in question if 
8538 the selection type is GTK_SELECTION_MULTIPLE.
8539
8540 Finally, the "select_child" (and "unselect_child", in theory) signals
8541 are emitted by all trees, but the "selection_changed" signal is only
8542 emitted by the root tree. Consequently, if you want to handle the
8543 "select_child" signal for a tree and all its subtrees, you will have
8544 to call gtk_signal_connect() for every subtree.
8545
8546 <sect1> Tree Widget Internals
8547 <p>
8548 The GtkTree's struct definition looks like this:
8549
8550 <tscreen><verb>
8551 struct _GtkTree
8552 {
8553   GtkContainer container;
8554
8555   GList *children;
8556   
8557   GtkTree* root_tree; /* owner of selection list */
8558   GtkWidget* tree_owner;
8559   GList *selection;
8560   guint level;
8561   guint indent_value;
8562   guint current_indent;
8563   guint selection_mode : 2;
8564   guint view_mode : 1;
8565   guint view_line : 1;
8566 };
8567 </verb></tscreen>
8568
8569 The perils associated with accessing the <tt>selection</tt> field
8570 directly have already been mentioned. The other important fields of
8571 the struct can also be accessed with handy macros or class functions.
8572 GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
8573 whether a tree is the root tree in a GtkTree hierarchy, while
8574 GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
8575 GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
8576 to use one of the gtk_widget_*() functions on it).
8577
8578 Instead of directly accessing the children field of a GtkTree widget,
8579 it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
8580 to the gtk_container_children() function. This creates a duplicate of
8581 the original list, so it's advisable to free it up using g_list_free()
8582 after you're done with it, or to iterate on it destructively, like
8583 this:
8584
8585 <tscreen><verb>
8586     children = gtk_container_children (GTK_CONTAINER (tree));
8587     while (children) {
8588       do_something_nice (GTK_TREE_ITEM (children->data));
8589       children = g_list_remove_link (children, children);
8590 }
8591 </verb></tscreen>
8592
8593 The <tt>tree_owner</tt> field is defined only in subtrees, where it
8594 points to the GtkTreeItem widget which holds the tree in question.
8595 The <tt>level</tt> field indicates how deeply nested a particular tree
8596 is; root trees have level 0, and each successive level of subtrees has
8597 a level one greater than the parent level. This field is set only
8598 after a GtkTree widget is actually mapped (i.e. drawn on the screen).
8599
8600 <sect2> Signals<label id="sec_GtkTree_Signals">
8601 <p>
8602 <tscreen><verb>
8603 void selection_changed( GtkTree *tree );
8604 </verb></tscreen>
8605
8606 This signal will be emitted whenever the <tt>selection</tt> field of a
8607 GtkTree has changed. This happens when a child of the GtkTree is
8608 selected or deselected.
8609
8610 <tscreen><verb>
8611 void select_child( GtkTree   *tree,
8612                    GtkWidget *child );
8613 </verb></tscreen>
8614
8615 This signal is emitted when a child of the GtkTree is about to get
8616 selected. This happens on calls to gtk_tree_select_item(),
8617 gtk_tree_select_child(), on <em>all</em> button presses and calls to
8618 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
8619 indirectly triggered on other occasions where children get added to or
8620 removed from the GtkTree.
8621
8622 <tscreen><verb>
8623 void unselect_child (GtkTree   *tree,
8624                      GtkWidget *child);
8625 </verb></tscreen>
8626
8627 This signal is emitted when a child of the GtkTree is about to get
8628 deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
8629 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
8630 other occasions, but <em>not</em> when a button press deselects a
8631 child, nor on emission of the "toggle" signal by gtk_item_toggle().
8632
8633 <sect2> Functions and Macros<label id="sec_GtkTree_Functions">
8634 <p>
8635 <tscreen><verb>
8636 guint gtk_tree_get_type( void );
8637 </verb></tscreen>
8638
8639 Returns the `GtkTree' type identifier.
8640
8641 <tscreen><verb>
8642 GtkWidget* gtk_tree_new( void );
8643 </verb></tscreen>
8644
8645 Create a new GtkTree object. The new widget is returned as a pointer
8646 to a GtkWidget object. NULL is returned on failure.
8647
8648 <tscreen><verb>
8649 void gtk_tree_append( GtkTree   *tree,
8650                       GtkWidget *tree_item );
8651 </verb></tscreen>
8652
8653 Append a tree item to a GtkTree.
8654
8655 <tscreen><verb>
8656 void gtk_tree_prepend( GtkTree   *tree,
8657                        GtkWidget *tree_item );
8658 </verb></tscreen>
8659
8660 Prepend a tree item to a GtkTree.
8661
8662 <tscreen><verb>
8663 void gtk_tree_insert( GtkTree   *tree,
8664                       GtkWidget *tree_item,
8665                       gint       position );
8666 </verb></tscreen>
8667
8668 Insert a tree item into a GtkTree at the position in the list
8669 specified by <tt>position.</tt>
8670
8671 <tscreen><verb>
8672 void gtk_tree_remove_items( GtkTree *tree,
8673                             GList   *items );
8674 </verb></tscreen>
8675
8676 Remove a list of items (in the form of a GList *) from a GtkTree.
8677 Note that removing an item from a tree dereferences (and thus usually)
8678 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
8679 subtrees in that subtree.  If you want to remove only one item, you
8680 can use gtk_container_remove().
8681
8682 <tscreen><verb>
8683 void gtk_tree_clear_items( GtkTree *tree,
8684                            gint     start,
8685                            gint     end );
8686 </verb></tscreen>
8687
8688 Remove the items from position <tt>start</tt> to position <tt>end</tt>
8689 from a GtkTree.  The same warning about dereferencing applies here, as
8690 gtk_tree_clear_items() simply constructs a list and passes it to
8691 gtk_tree_remove_items().
8692
8693 <tscreen><verb>
8694 void gtk_tree_select_item( GtkTree *tree,
8695                            gint     item );
8696 </verb></tscreen>
8697
8698 Emits the "select_item" signal for the child at position
8699 <tt>item</tt>, thus selecting the child (unless you unselect it in a
8700 signal handler).
8701
8702 <tscreen><verb>
8703 void gtk_tree_unselect_item( GtkTree *tree,
8704                              gint     item );
8705 </verb></tscreen>
8706
8707 Emits the "unselect_item" signal for the child at position
8708 <tt>item</tt>, thus unselecting the child.
8709
8710 <tscreen><verb>
8711 void gtk_tree_select_child( GtkTree   *tree,
8712                             GtkWidget *tree_item );
8713 </verb></tscreen>
8714
8715 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
8716 selecting it.
8717
8718 <tscreen><verb>
8719 void gtk_tree_unselect_child( GtkTree   *tree,
8720                               GtkWidget *tree_item );
8721 </verb></tscreen>
8722
8723 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
8724 thus unselecting it.
8725
8726 <tscreen><verb>
8727 gint gtk_tree_child_position( GtkTree   *tree,
8728                               GtkWidget *child );
8729 </verb></tscreen>
8730
8731 Returns the position in the tree of <tt>child</tt>, unless
8732 <tt>child</tt> is not in the tree, in which case it returns -1.
8733
8734 <tscreen><verb>
8735 void gtk_tree_set_selection_mode( GtkTree          *tree,
8736                                   GtkSelectionMode  mode );
8737 </verb></tscreen>
8738
8739 Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
8740 default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
8741 GTK_SELECTION_EXTENDED. This is only defined for root trees, which
8742 makes sense, since the root tree "owns" the selection. Setting it for
8743 subtrees has no effect at all; the value is simply ignored.
8744
8745 <tscreen><verb>
8746 void gtk_tree_set_view_mode( GtkTree         *tree,
8747                              GtkTreeViewMode  mode ); 
8748 </verb></tscreen>
8749
8750 Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
8751 default) or GTK_TREE_VIEW_ITEM.  The view mode propagates from a tree
8752 to its subtrees, and can't be set exclusively to a subtree (this is
8753 not exactly true - see the example code comments).
8754
8755 The term "view mode" is rather ambiguous - basically, it controls the
8756 way the highlight is drawn when one of a tree's children is selected.
8757 If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
8758 highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
8759 (i.e. usually the label) is highlighted.
8760
8761 <tscreen><verb>
8762 void gtk_tree_set_view_lines( GtkTree *tree,
8763                               guint    flag );
8764 </verb></tscreen>
8765
8766 Controls whether connecting lines between tree items are drawn.
8767 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
8768 which case they aren't.
8769
8770 <tscreen><verb>
8771 GtkTree *GTK_TREE (gpointer obj);
8772 </verb></tscreen>
8773
8774 Cast a generic pointer to `GtkTree *'.
8775
8776 <tscreen><verb>
8777 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
8778 </verb></tscreen>
8779
8780 Cast a generic pointer to `GtkTreeClass*'.
8781
8782 <tscreen><verb>
8783 gint GTK_IS_TREE (gpointer obj);
8784 </verb></tscreen>
8785
8786 Determine if a generic pointer refers to a `GtkTree' object.
8787
8788 <tscreen><verb>
8789 gint GTK_IS_ROOT_TREE (gpointer obj)
8790 </verb></tscreen>
8791
8792 Determine if a generic pointer refers to a `GtkTree' object
8793 <em>and</em> is a root tree. Though this will accept any pointer, the
8794 results of passing it a pointer that does not refer to a GtkTree are
8795 undefined and possibly harmful.
8796
8797 <tscreen><verb>
8798 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
8799 </verb></tscreen>
8800
8801 Return the root tree of a pointer to a `GtkTree' object. The above
8802 warning applies.
8803
8804 <tscreen><verb>
8805 GList *GTK_TREE_SELECTION( gpointer obj)
8806 </verb></tscreen>
8807
8808 Return the selection list of the root tree of a `GtkTree' object. The
8809 above warning applies here, too.
8810
8811 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
8812 <p>
8813 The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
8814 which in turn is derived from GtkBin.  Therefore, the item itself is a
8815 generic container holding exactly one child widget, which can be of
8816 any type.  The GtkTreeItem widget has a number of extra fields, but
8817 the only one we need be concerned with is the <tt>subtree</tt> field.
8818
8819 The definition for the GtkTreeItem struct looks like this:
8820
8821 <tscreen><verb>
8822 struct _GtkTreeItem
8823 {
8824   GtkItem item;
8825
8826   GtkWidget *subtree;
8827   GtkWidget *pixmaps_box;
8828   GtkWidget *plus_pix_widget, *minus_pix_widget;
8829
8830   GList *pixmaps;               /* pixmap node for this items color depth */
8831
8832   guint expanded : 1;
8833 };
8834 </verb></tscreen>
8835
8836 The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
8837 on the plus/minus symbol which controls expansion and collapsing.  The
8838 <tt>pixmaps</tt> field points to an internal data structure.  Since
8839 you can always obtain the subtree of a GtkTreeItem in a (relatively)
8840 type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
8841 probably advisable never to touch the insides of a GtkTreeItem unless
8842 you <em>really</em> know what you're doing.
8843
8844 Since it is directly derived from a GtkItem it can be treated as such
8845 by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
8846 label, so the convenience function gtk_list_item_new_with_label() is
8847 provided. The same effect can be achieved using code like the
8848 following, which is actually copied verbatim from
8849 gtk_tree_item_new_with_label():
8850
8851 <tscreen><verb>
8852 tree_item = gtk_tree_item_new ();
8853 label_widget = gtk_label_new (label);
8854 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
8855
8856 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
8857 gtk_widget_show (label_widget);
8858 </verb></tscreen>
8859
8860 As one is not forced to add a GtkLabel to a GtkTreeItem, you could
8861 also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
8862 app will likely be quite unpopular in this case) to the GtkTreeItem.
8863
8864 If you remove all the items from a subtree, it will be destroyed and
8865 unparented, unless you reference it beforehand, and the GtkTreeItem
8866 which owns it will be collapsed.  So, if you want it to stick around,
8867 do something like the following:
8868
8869 <tscreen><verb>
8870 gtk_widget_ref (tree);
8871 owner = GTK_TREE(tree)->tree_owner;
8872 gtk_container_remove (GTK_CONTAINER(tree), item);
8873 if (tree->parent == NULL){
8874   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
8875   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
8876 }
8877 else
8878   gtk_widget_unref (tree);
8879 </verb></tscreen>
8880
8881 Finally, drag-n-drop <em>does</em> work with GtkTreeItems.  You just
8882 have to make sure that the GtkTreeItem you want to make into a drag
8883 item or a drop site has not only been added to a GtkTree, but that
8884 each successive parent widget has a parent itself, all the way back to
8885 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
8886 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
8887
8888 <sect2> Signals
8889 <p>
8890 GtkTreeItem inherits the "select", "deselect", and "toggle" signals
8891 from GtkItem.  In addition, it adds two signals of its own, "expand"
8892 and "collapse".
8893
8894 <tscreen><verb>
8895 void select( GtkItem *tree_item );
8896 </verb></tscreen>
8897
8898 This signal is emitted when an item is about to be selected, either
8899 after it has been clicked on by the user, or when the program calls
8900 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
8901
8902 <tscreen><verb>
8903 void deselect( GtkItem *tree_item );
8904 </verb></tscreen>
8905
8906 This signal is emitted when an item is about to be unselected, either
8907 after it has been clicked on by the user, or when the program calls
8908 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
8909 GtkTreeItems, it is also emitted by gtk_tree_unselect_child(), and
8910 sometimes gtk_tree_select_child().
8911
8912 <tscreen><verb>
8913 void toggle( GtkItem *tree_item );
8914 </verb></tscreen>
8915
8916 This signal is emitted when the program calls gtk_item_toggle().  The
8917 effect it has when emitted on a GtkTreeItem is to call
8918 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
8919 item's parent tree, if the item has a parent tree.  If it doesn't,
8920 then the highlight is reversed on the item.
8921
8922 <tscreen><verb>
8923 void expand( GtkTreeItem *tree_item );
8924 </verb></tscreen>
8925
8926 This signal is emitted when the tree item's subtree is about to be
8927 expanded, that is, when the user clicks on the plus sign next to the
8928 item, or when the program calls gtk_tree_item_expand().
8929
8930 <tscreen><verb>
8931 void collapse( GtkTreeItem *tree_item );
8932 </verb></tscreen>
8933
8934 This signal is emitted when the tree item's subtree is about to be
8935 collapsed, that is, when the user clicks on the minus sign next to the
8936 item, or when the program calls gtk_tree_item_collapse().
8937
8938 <sect2> Functions and Macros
8939 <p>
8940 <tscreen><verb>
8941 guint gtk_tree_item_get_type( void );
8942 </verb></tscreen>
8943
8944 Returns the `GtkTreeItem' type identifier.
8945
8946 <tscreen><verb>
8947 GtkWidget* gtk_tree_item_new( void );
8948 </verb></tscreen>
8949
8950 Create a new GtkTreeItem object. The new widget is returned as a
8951 pointer to a GtkWidget object. NULL is returned on failure.
8952
8953 <tscreen><verb>
8954 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
8955 </verb></tscreen>
8956
8957 Create a new GtkTreeItem object, having a single GtkLabel as the sole
8958 child. The new widget is returned as a pointer to a GtkWidget
8959 object. NULL is returned on failure.
8960
8961 <tscreen><verb>
8962 void gtk_tree_item_select( GtkTreeItem *tree_item );
8963 </verb></tscreen>
8964
8965 This function is basically a wrapper around a call to gtk_item_select
8966 (GTK_ITEM (tree_item)) which will emit the select signal.
8967
8968 <tscreen><verb>
8969 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
8970 </verb></tscreen>
8971
8972 This function is basically a wrapper around a call to
8973 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
8974 signal.
8975
8976 <tscreen><verb>
8977 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8978                                 GtkWidget   *subtree );
8979 </verb></tscreen>
8980
8981 This function adds subtree to tree_item, showing it if tree_item is
8982 expanded, or hiding it if tree_item is collapsed. Again, remember that
8983 the tree_item must have already been added to a tree for this to work.
8984
8985 <tscreen><verb>
8986 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
8987 </verb></tscreen>
8988
8989 This removes all of tree_item's subtree's children (thus unreferencing
8990 and destroying it, any of its children's subtrees, and so on...), then
8991 removes the subtree itself, and hides the plus/minus sign.
8992
8993 <tscreen><verb>
8994 void gtk_tree_item_expand( GtkTreeItem *tree_item );
8995 </verb></tscreen>
8996
8997 This emits the "expand" signal on tree_item, which expands it.
8998
8999 <tscreen><verb>
9000 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
9001 </verb></tscreen>
9002
9003 This emits the "collapse" signal on tree_item, which collapses it.
9004
9005 <tscreen><verb>
9006 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
9007 </verb></tscreen>
9008
9009 Cast a generic pointer to `GtkTreeItem*'.
9010
9011 <tscreen><verb>
9012 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
9013 </verb></tscreen>
9014
9015 Cast a generic pointer to `GtkTreeItemClass'.
9016
9017 <tscreen><verb>
9018 gint GTK_IS_TREE_ITEM (gpointer obj)
9019 </verb></tscreen>
9020
9021 Determine if a generic pointer refers to a `GtkTreeItem' object.
9022  
9023 <tscreen><verb>
9024 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
9025 </verb></tscreen>
9026
9027 Returns a tree item's subtree (obj should point to a `GtkTreeItem'
9028 object).
9029
9030 <sect1> Tree Example
9031 <p>
9032 This is somewhat like the tree example in testgtk.c, but a lot less
9033 complete (although much better commented).  It puts up a window with a
9034 tree, and connects all the signals for the relevant objects, so you
9035 can see when they are emitted.
9036
9037 <tscreen><verb>
9038 /* example-start tree tree.c */
9039
9040 #include <gtk/gtk.h>
9041
9042 /* for all the GtkItem:: and GtkTreeItem:: signals */
9043 static void cb_itemsignal (GtkWidget *item, gchar *signame)
9044 {
9045   gchar *name;
9046   GtkLabel *label;
9047
9048   /* It's a GtkBin, so it has one child, which we know to be a
9049      label, so get that */
9050   label = GTK_LABEL (GTK_BIN (item)->child);
9051   /* Get the text of the label */
9052   gtk_label_get (label, &amp;name);
9053   /* Get the level of the tree which the item is in */
9054   g_print ("%s called for item %s->%p, level %d\n", signame, name,
9055            item, GTK_TREE (item->parent)->level);
9056 }
9057
9058 /* Note that this is never called */
9059 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
9060                                GtkWidget *subtree)
9061 {
9062   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
9063            root_tree, subtree, child);
9064 }
9065
9066 /* Note that this is called every time the user clicks on an item,
9067    whether it is already selected or not. */
9068 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
9069                              GtkWidget *subtree)
9070 {
9071   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
9072            root_tree, subtree, child);
9073 }
9074
9075 static void cb_selection_changed (GtkWidget *tree)
9076 {
9077   GList *i;
9078   
9079   g_print ("selection_change called for tree %p\n", tree);
9080   g_print ("selected objects are:\n");
9081
9082   i = GTK_TREE_SELECTION(tree);
9083   while (i){
9084     gchar *name;
9085     GtkLabel *label;
9086     GtkWidget *item;
9087
9088     /* Get a GtkWidget pointer from the list node */
9089     item = GTK_WIDGET (i->data);
9090     label = GTK_LABEL (GTK_BIN (item)->child);
9091     gtk_label_get (label, &amp;name);
9092     g_print ("\t%s on level %d\n", name, GTK_TREE
9093              (item->parent)->level);
9094     i = i->next;
9095   }
9096 }
9097
9098 int main (int argc, char *argv[])
9099 {
9100   GtkWidget *window, *scrolled_win, *tree;
9101   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
9102                                "Maurice"};
9103   gint i;
9104
9105   gtk_init (&amp;argc, &amp;argv);
9106
9107   /* a generic toplevel window */
9108   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9109   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
9110                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
9111   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
9112
9113   /* A generic scrolled window */
9114   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9115   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9116                                   GTK_POLICY_AUTOMATIC,
9117                                   GTK_POLICY_AUTOMATIC);
9118   gtk_widget_set_usize (scrolled_win, 150, 200);
9119   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
9120   gtk_widget_show (scrolled_win);
9121   
9122   /* Create the root tree */
9123   tree = gtk_tree_new();
9124   g_print ("root tree is %p\n", tree);
9125   /* connect all GtkTree:: signals */
9126   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
9127                       GTK_SIGNAL_FUNC(cb_select_child), tree);
9128   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
9129                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
9130   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
9131                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
9132   /* Add it to the scrolled window */
9133   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
9134                                          tree);
9135   /* Set the selection mode */
9136   gtk_tree_set_selection_mode (GTK_TREE(tree),
9137                                GTK_SELECTION_MULTIPLE);
9138   /* Show it */
9139   gtk_widget_show (tree);
9140
9141   for (i = 0; i < 5; i++){
9142     GtkWidget *subtree, *item;
9143     gint j;
9144
9145     /* Create a tree item */
9146     item = gtk_tree_item_new_with_label (itemnames[i]);
9147     /* Connect all GtkItem:: and GtkTreeItem:: signals */
9148     gtk_signal_connect (GTK_OBJECT(item), "select",
9149                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9150     gtk_signal_connect (GTK_OBJECT(item), "deselect",
9151                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9152     gtk_signal_connect (GTK_OBJECT(item), "toggle",
9153                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9154     gtk_signal_connect (GTK_OBJECT(item), "expand",
9155                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9156     gtk_signal_connect (GTK_OBJECT(item), "collapse",
9157                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9158     /* Add it to the parent tree */
9159     gtk_tree_append (GTK_TREE(tree), item);
9160     /* Show it - this can be done at any time */
9161     gtk_widget_show (item);
9162     /* Create this item's subtree */
9163     subtree = gtk_tree_new();
9164     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
9165              subtree);
9166
9167     /* This is still necessary if you want these signals to be called
9168        for the subtree's children.  Note that selection_change will be 
9169        signalled for the root tree regardless. */
9170     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
9171                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
9172     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
9173                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
9174     /* This has absolutely no effect, because it is completely ignored 
9175        in subtrees */
9176     gtk_tree_set_selection_mode (GTK_TREE(subtree),
9177                                  GTK_SELECTION_SINGLE);
9178     /* Neither does this, but for a rather different reason - the
9179        view_mode and view_line values of a tree are propagated to
9180        subtrees when they are mapped.  So, setting it later on would
9181        actually have a (somewhat unpredictable) effect */
9182     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
9183     /* Set this item's subtree - note that you cannot do this until
9184        AFTER the item has been added to its parent tree! */
9185     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
9186
9187     for (j = 0; j < 5; j++){
9188       GtkWidget *subitem;
9189
9190       /* Create a subtree item, in much the same way */
9191       subitem = gtk_tree_item_new_with_label (itemnames[j]);
9192       /* Connect all GtkItem:: and GtkTreeItem:: signals */
9193       gtk_signal_connect (GTK_OBJECT(subitem), "select",
9194                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9195       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
9196                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9197       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
9198                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9199       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
9200                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9201       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
9202                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9203       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
9204       /* Add it to its parent tree */
9205       gtk_tree_append (GTK_TREE(subtree), subitem);
9206       /* Show it */
9207       gtk_widget_show (subitem);
9208     }
9209   }
9210
9211   /* Show the window and loop endlessly */
9212   gtk_widget_show (window);
9213   gtk_main();
9214   return 0;
9215 }
9216 /* example-end */
9217 </verb></tscreen>
9218
9219 <!-- ***************************************************************** -->
9220 <sect>Menu Widget
9221 <!-- ***************************************************************** -->
9222 <p>
9223 There are two ways to create menus, there's the easy way, and there's
9224 the hard way. Both have their uses, but you can usually use the
9225 itemfactory (the easy way). The "hard" way is to create all the menus
9226 using the calls directly. The easy way is to use the gtk_item_factory
9227 calls. This is much simpler, but there are advantages and
9228 disadvantages to each approach.
9229
9230 The itemfactory is much easier to use, and to add new menus to,
9231 although writing a few wrapper functions to create menus using the
9232 manual method could go a long way towards usability. With the
9233 itemfactory, it is not possible to add images or the character '/' to
9234 the menus.
9235
9236 <!-- ----------------------------------------------------------------- -->
9237 <sect1>Manual Menu Creation
9238 <p>
9239 In the true tradition of teaching, we'll show you the hard way
9240 first. <tt>:)</>
9241
9242 There are three widgets that go into making a menubar and submenus:
9243 <itemize>
9244 <item>a menu item, which is what the user wants to select, e.g. 'Save'
9245 <item>a menu, which acts as a container for the menu items, and
9246 <item>a menubar, which is a container for each of the individual
9247 menus.
9248 </itemize>
9249
9250 This is slightly complicated by the fact that menu item widgets are
9251 used for two different things. They are both the widgets that are
9252 packed into the menu, and the widget that is packed into the menubar,
9253 which, when selected, activates the menu.
9254
9255 Let's look at the functions that are used to create menus and
9256 menubars.  This first function is used to create a new menubar.
9257
9258 <tscreen>
9259 <verb>
9260 GtkWidget *gtk_menu_bar_new( void );
9261 </verb>
9262 </tscreen>
9263
9264 This rather self explanatory function creates a new menubar. You use
9265 gtk_container_add to pack this into a window, or the box_pack
9266 functions to pack it into a box - the same as buttons.
9267
9268 <tscreen><verb>
9269 GtkWidget *gtk_menu_new( void );
9270 </verb></tscreen>
9271
9272 This function returns a pointer to a new menu, it is never actually
9273 shown (with gtk_widget_show), it is just a container for the menu
9274 items. Hopefully this will become more clear when you look at the
9275 example below.
9276
9277 The next two calls are used to create menu items that are packed into
9278 the menu (and menubar).
9279
9280 <tscreen><verb>
9281 GtkWidget *gtk_menu_item_new( void );
9282 </verb></tscreen>
9283
9284 and
9285
9286 <tscreen><verb>
9287 GtkWidget *gtk_menu_item_new_with_label( const char *label );
9288 </verb></tscreen>
9289
9290 These calls are used to create the menu items that are to be
9291 displayed.  Remember to differentiate between a "menu" as created with
9292 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
9293 functions. The menu item will be an actual button with an associated
9294 action, whereas a menu will be a container holding menu items.
9295
9296 The gtk_menu_new_with_label and gtk_menu_new functions are just as
9297 you'd expect after reading about the buttons. One creates a new menu
9298 item with a label already packed into it, and the other just creates a
9299 blank menu item.
9300
9301 Once you've created a menu item you have to put it into a menu. This
9302 is done using the function gtk_menu_append. In order to capture when
9303 the item is selected by the user, we need to connect to the
9304 <tt/activate/ signal in the usual way. So, if we wanted to create a
9305 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/ and
9306 <tt/Quit/ the code would look something like:
9307
9308 <tscreen><verb>
9309     file_menu = gtk_menu_new ();    /* Don't need to show menus */
9310
9311     /* Create the menu items */
9312     open_item = gtk_menu_item_new_with_label ("Open");
9313     save_item = gtk_menu_item_new_with_label ("Save");
9314     quit_item = gtk_menu_item_new_with_label ("Quit");
9315
9316     /* Add them to the menu */
9317     gtk_menu_append (GTK_MENU (file_menu), open_item);
9318     gtk_menu_append (GTK_MENU (file_menu), save_item);
9319     gtk_menu_append (GTK_MENU (file_menu), quit_item);
9320
9321     /* Attach the callback functions to the activate signal */
9322     gtk_signal_connect_object (GTK_OBJECT (open_items), "activate",
9323                                GTK_SIGNAL_FUNC (menuitem_response),
9324                                (gpointer) "file.open");
9325     gtk_signal_connect_object (GTK_OBJECT (save_items), "activate",
9326                                GTK_SIGNAL_FUNC (menuitem_response),
9327                                (gpointer) "file.save");
9328
9329     /* We can attach the Quit menu item to our exit function */
9330     gtk_signal_connect_object (GTK_OBJECT (quit_items), "activate",
9331                                GTK_SIGNAL_FUNC (destroy),
9332                                (gpointer) "file.quit");
9333
9334     /* We do need to show menu items */
9335     gtk_widget_show (open_item);
9336     gtk_widget_show (save_item);
9337     gtk_widget_show (quit_item);
9338 </verb></tscreen>
9339
9340 At this point we have our menu. Now we need to create a menubar and a
9341 menu item for the <tt/File/ entry, to which we add our menu. The code
9342 looks like this:
9343
9344 <tscreen><verb>
9345     menu_bar = gtk_menu_bar_new ();
9346     gtk_container_add (GTK_CONTAINER (window), menu_bar);
9347     gtk_widget_show (menu_bar);
9348
9349     file_item = gtk_menu_item_new_with_label ("File");
9350     gtk_widget_show (file_item);
9351 </verb></tscreen>
9352
9353 Now we need to associate the menu with <tt/file_item/. This is done
9354 with the function
9355
9356 <tscreen>
9357 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
9358                                 GtkWidget   *submenu );
9359 </tscreen>
9360
9361 So, our example would continue with
9362
9363 <tscreen><verb>
9364     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
9365 </verb></tscreen>
9366
9367 All that is left to do is to add the menu to the menubar, which is
9368 accomplished using the function
9369
9370 <tscreen>
9371 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
9372                           GtkWidget  *menu_item );
9373 </tscreen>
9374
9375 which in our case looks like this:
9376
9377 <tscreen><verb>
9378     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
9379 </verb></tscreen>
9380
9381 If we wanted the menu right justified on the menubar, such as help
9382 menus often are, we can use the following function (again on
9383 <tt/file_item/ in the current example) before attaching it to the
9384 menubar.
9385
9386 <tscreen><verb>
9387 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
9388 </verb></tscreen>
9389
9390 Here is a summary of the steps needed to create a menu bar with menus
9391 attached:
9392
9393 <itemize>
9394 <item> Create a new menu using gtk_menu_new()
9395 <item> Use multiple calls to gtk_menu_item_new() for each item you
9396 wish to have on your menu. And use gtk_menu_append() to put each of
9397 these new items on to the menu.
9398 <item> Create a menu item using gtk_menu_item_new(). This will be the
9399 root of the menu, the text appearing here will be on the menubar
9400 itself.
9401 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
9402 menu item (the one created in the above step).
9403 <item> Create a new menubar using gtk_menu_bar_new. This step only
9404 needs to be done once when creating a series of menus on one menu bar.
9405 <item> Use gtk_menu_bar_append() to put the root menu onto the menubar.
9406 </itemize>
9407
9408 Creating a popup menu is nearly the same. The difference is that the
9409 menu is not posted `automatically' by a menubar, but explicitly by
9410 calling the function gtk_menu_popup() from a button-press event, for
9411 example.  Take these steps:
9412
9413 <itemize>
9414 <item>Create an event handling function. It needs to have the
9415 prototype
9416 <tscreen>
9417 static gint handler (GtkWidget *widget,
9418                      GdkEvent  *event);
9419 </tscreen>
9420 and it will use the event to find out where to pop up the menu.
9421 <item>In the event handler, if the event is a mouse button press,
9422 treat <tt>event</tt> as a button event (which it is) and use it as
9423 shown in the sample code to pass information to gtk_menu_popup().
9424 <item>Bind that event handler to a widget with
9425 <tscreen>
9426     gtk_signal_connect_object (GTK_OBJECT (widget), "event",
9427                                GTK_SIGNAL_FUNC (handler),
9428                                GTK_OBJECT (menu));
9429 </tscreen>
9430 where <tt>widget</tt> is the widget you are binding to,
9431 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
9432 created with gtk_menu_new(). This can be a menu which is also posted
9433 by a menu bar, as shown in the sample code.
9434 </itemize>
9435
9436 <!-- ----------------------------------------------------------------- -->
9437 <sect1>Manual Menu Example
9438 <p>
9439 That should about do it. Let's take a look at an example to help clarify.
9440
9441 <tscreen><verb>
9442 /* example-start menu menu.c */
9443
9444 #include <gtk/gtk.h>
9445
9446 static gint button_press (GtkWidget *, GdkEvent *);
9447 static void menuitem_response (gchar *);
9448
9449 int main( int   argc,
9450           char *argv[] )
9451 {
9452
9453     GtkWidget *window;
9454     GtkWidget *menu;
9455     GtkWidget *menu_bar;
9456     GtkWidget *root_menu;
9457     GtkWidget *menu_items;
9458     GtkWidget *vbox;
9459     GtkWidget *button;
9460     char buf[128];
9461     int i;
9462
9463     gtk_init (&amp;argc, &amp;argv);
9464
9465     /* create a new window */
9466     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9467     gtk_widget_set_usize (GTK_WIDGET (window), 200, 100);
9468     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
9469     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
9470                         (GtkSignalFunc) gtk_main_quit, NULL);
9471
9472     /* Init the menu-widget, and remember -- never
9473      * gtk_show_widget() the menu widget!! 
9474      * This is the menu that holds the menu items, the one that
9475      * will pop up when you click on the "Root Menu" in the app */
9476     menu = gtk_menu_new ();
9477
9478     /* Next we make a little loop that makes three menu-entries for "test-menu".
9479      * Notice the call to gtk_menu_append.  Here we are adding a list of
9480      * menu items to our menu.  Normally, we'd also catch the "clicked"
9481      * signal on each of the menu items and setup a callback for it,
9482      * but it's omitted here to save space. */
9483
9484     for (i = 0; i < 3; i++)
9485         {
9486             /* Copy the names to the buf. */
9487             sprintf (buf, "Test-undermenu - %d", i);
9488
9489             /* Create a new menu-item with a name... */
9490             menu_items = gtk_menu_item_new_with_label (buf);
9491
9492             /* ...and add it to the menu. */
9493             gtk_menu_append (GTK_MENU (menu), menu_items);
9494
9495             /* Do something interesting when the menuitem is selected */
9496             gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate",
9497                 GTK_SIGNAL_FUNC (menuitem_response), (gpointer) g_strdup (buf));
9498
9499             /* Show the widget */
9500             gtk_widget_show (menu_items);
9501         }
9502
9503     /* This is the root menu, and will be the label
9504      * displayed on the menu bar.  There won't be a signal handler attached,
9505      * as it only pops up the rest of the menu when pressed. */
9506     root_menu = gtk_menu_item_new_with_label ("Root Menu");
9507
9508     gtk_widget_show (root_menu);
9509
9510     /* Now we specify that we want our newly created "menu" to be the menu
9511      * for the "root menu" */
9512     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
9513
9514     /* A vbox to put a menu and a button in: */
9515     vbox = gtk_vbox_new (FALSE, 0);
9516     gtk_container_add (GTK_CONTAINER (window), vbox);
9517     gtk_widget_show (vbox);
9518
9519     /* Create a menu-bar to hold the menus and add it to our main window */
9520     menu_bar = gtk_menu_bar_new ();
9521     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
9522     gtk_widget_show (menu_bar);
9523
9524     /* Create a button to which to attach menu as a popup */
9525     button = gtk_button_new_with_label ("press me");
9526     gtk_signal_connect_object (GTK_OBJECT (button), "event",
9527         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT (menu));
9528     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
9529     gtk_widget_show (button);
9530
9531     /* And finally we append the menu-item to the menu-bar -- this is the
9532      * "root" menu-item I have been raving about =) */
9533     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), root_menu);
9534
9535     /* always display the window as the last step so it all splashes on
9536      * the screen at once. */
9537     gtk_widget_show (window);
9538
9539     gtk_main ();
9540
9541     return(0);
9542 }
9543
9544 /* Respond to a button-press by posting a menu passed in as widget.
9545  *
9546  * Note that the "widget" argument is the menu being posted, NOT
9547  * the button that was pressed.
9548  */
9549
9550 static gint button_press (GtkWidget *widget, GdkEvent *event)
9551 {
9552
9553     if (event->type == GDK_BUTTON_PRESS) {
9554         GdkEventButton *bevent = (GdkEventButton *) event; 
9555         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
9556                         bevent->button, bevent->time);
9557         /* Tell calling code that we have handled this event; the buck
9558          * stops here. */
9559         return TRUE;
9560     }
9561
9562     /* Tell calling code that we have not handled this event; pass it on. */
9563     return FALSE;
9564 }
9565
9566
9567 /* Print a string when a menu item is selected */
9568
9569 static void menuitem_response (gchar *string)
9570 {
9571     printf ("%s\n", string);
9572 }
9573 /* example-end */
9574 </verb></tscreen>
9575
9576 You may also set a menu item to be insensitive and, using an accelerator
9577 table, bind keys to menu functions.
9578
9579 <!-- ----------------------------------------------------------------- -->
9580 <sect1>Using GtkItemFactory
9581 <p>
9582 Now that we've shown you the hard way, here's how you do it using the
9583 gtk_item_factory calls.
9584
9585 <!-- ----------------------------------------------------------------- -->
9586 <sect1>Item Factory Example
9587 <p>
9588 Here is an example using the GTK item factory.
9589
9590 <tscreen><verb>
9591 /* example-start menu itemfactory.c */
9592
9593 #include <gtk/gtk.h>
9594 #include <strings.h>
9595
9596 /* Obligatory basic callback */
9597 static void print_hello( GtkWidget *w,
9598                          gpointer   data )
9599 {
9600   g_message ("Hello, World!\n");
9601 }
9602
9603 /* This is the GtkItemFactoryEntry structure used to generate new menus.
9604    Item 1: The menu path. The letter after the underscore indicates an
9605            accelerator key once the menu is open.
9606    Item 2: The accelerator key for the entry
9607    Item 3: The callback function.
9608    Item 4: The callback action.  This changes the parameters with
9609            which the function is called.  The default is 0.
9610    Item 5: The item type, used to define what kind of an item it is.
9611            Here are the possible values:
9612
9613            NULL               -> "<Item>"
9614            ""                 -> "<Item>"
9615            "<Title>"          -> create a title item
9616            "<Item>"           -> create a simple item
9617            "<CheckItem>"      -> create a check item
9618            "<ToggleItem>"     -> create a toggle item
9619            "<RadioItem>"      -> create a radio item
9620            <path>             -> path of a radio item to link against
9621            "<Separator>"      -> create a separator
9622            "<Branch>"         -> create an item to hold sub items (optional)
9623            "<LastBranch>"     -> create a right justified branch 
9624 */
9625
9626 static GtkItemFactoryEntry menu_items[] = {
9627   { "/_File",         NULL,         NULL, 0, "<Branch>" },
9628   { "/File/_New",     "<control>N", print_hello, 0, NULL },
9629   { "/File/_Open",    "<control>O", print_hello, 0, NULL },
9630   { "/File/_Save",    "<control>S", print_hello, 0, NULL },
9631   { "/File/Save _As", NULL,         NULL, 0, NULL },
9632   { "/File/sep1",     NULL,         NULL, 0, "<Separator>" },
9633   { "/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL },
9634   { "/_Options",      NULL,         NULL, 0, "<Branch>" },
9635   { "/Options/Test",  NULL,         NULL, 0, NULL },
9636   { "/_Help",         NULL,         NULL, 0, "<LastBranch>" },
9637   { "/_Help/About",   NULL,         NULL, 0, NULL },
9638 };
9639
9640
9641 void get_main_menu( GtkWidget  *window,
9642                     GtkWidget **menubar )
9643 {
9644   GtkItemFactory *item_factory;
9645   GtkAccelGroup *accel_group;
9646   gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
9647
9648   accel_group = gtk_accel_group_new ();
9649
9650   /* This function initializes the item factory.
9651      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
9652               or GTK_TYPE_OPTION_MENU.
9653      Param 2: The path of the menu.
9654      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
9655               the accelerator table while generating menus.
9656   */
9657
9658   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
9659                                        accel_group);
9660
9661   /* This function generates the menu items. Pass the item factory,
9662      the number of items in the array, the array itself, and any
9663      callback data for the the menu items. */
9664   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9665
9666   /* Attach the new accelerator group to the window. */
9667   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
9668
9669   if (menubar)
9670     /* Finally, return the actual menu bar created by the item factory. */ 
9671     *menubar = gtk_item_factory_get_widget (item_factory, "<main>");
9672 }
9673
9674 int main( int argc,
9675           char *argv[] )
9676 {
9677   GtkWidget *window;
9678   GtkWidget *main_vbox;
9679   GtkWidget *menubar;
9680   
9681   gtk_init (&amp;argc, &amp;argv);
9682   
9683   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9684   gtk_signal_connect (GTK_OBJECT (window), "destroy", 
9685                       GTK_SIGNAL_FUNC (gtk_main_quit), 
9686                       "WM destroy");
9687   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
9688   gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
9689   
9690   main_vbox = gtk_vbox_new (FALSE, 1);
9691   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
9692   gtk_container_add (GTK_CONTAINER (window), main_vbox);
9693   gtk_widget_show (main_vbox);
9694   
9695   get_main_menu (window, &amp;menubar);
9696   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
9697   gtk_widget_show (menubar);
9698   
9699   gtk_widget_show (window);
9700   gtk_main ();
9701   
9702   return(0);
9703 }
9704 /* example-end */
9705 </verb></tscreen>
9706
9707
9708 For now, there's only this example. An explanation and lots 'o' comments
9709 will follow later.
9710
9711 <!-- ***************************************************************** -->
9712 <sect> Text Widget
9713 <!-- ***************************************************************** -->
9714 <p>
9715 The Text widget allows multiple lines of text to be displayed and
9716 edited.  It supports both multi-colored and multi-font text, allowing
9717 them to be mixed in any way we wish. It also has a wide set of key
9718 based text editing commands, which are compatible with Emacs.
9719
9720 The text widget supports full cut-and-paste facilities, including the
9721 use of double- and triple-click to select a word and a whole line,
9722 respectively.
9723
9724 <!-- ----------------------------------------------------------------- -->
9725 <sect1>Creating and Configuring a Text box
9726 <p>
9727 There is only one function for creating a new Text widget.
9728
9729 <tscreen><verb>
9730 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
9731                          GtkAdjustment *vadj );
9732 </verb></tscreen>
9733
9734 The arguments allow us to give the Text widget pointers to Adjustments
9735 that can be used to track the viewing position of the widget. Passing
9736 NULL values to either or both of these arguments will cause the
9737 gtk_text_new function to create its own.
9738
9739 <tscreen><verb>
9740 void gtk_text_set_adjustments( GtkText       *text,
9741                                GtkAdjustment *hadj,
9742                                GtkAdjustment *vadj );
9743 </verb></tscreen>
9744
9745 The above function allows the horizontal and vertical adjustments of a
9746 text widget to be changed at any time.
9747
9748 The text widget will not automatically create its own scrollbars when
9749 the amount of text to be displayed is too long for the display
9750 window. We therefore have to create and add them to the display layout
9751 ourselves.
9752
9753 <tscreen><verb>
9754   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
9755   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
9756   gtk_widget_show (vscrollbar);
9757 </verb></tscreen>
9758
9759 The above code snippet creates a new vertical scrollbar, and attaches
9760 it to the vertical adjustment of the text widget, <tt/text/. It then
9761 packs it into a box in the normal way.
9762
9763 Note, currently the GtkText widget does not support horizontal
9764 scrollbars.
9765
9766 There are two main ways in which a Text widget can be used: to allow
9767 the user to edit a body of text, or to allow us to display multiple
9768 lines of text to the user. In order for us to switch between these
9769 modes of operation, the text widget has the following function:
9770
9771 <tscreen><verb>
9772 void gtk_text_set_editable( GtkText *text,
9773                             gint     editable );
9774 </verb></tscreen>
9775
9776 The <tt/editable/ argument is a TRUE or FALSE value that specifies
9777 whether the user is permitted to edit the contents of the Text
9778 widget. When the text widget is editable, it will display a cursor at
9779 the current insertion point.
9780
9781 You are not, however, restricted to just using the text widget in
9782 these two modes. You can toggle the editable state of the text widget
9783 at any time, and can insert text at any time.
9784
9785 The text widget wraps lines of text that are too long to fit onto a
9786 single line of the display window. Its default behaviour is to break
9787 words across line breaks. This can be changed using the next function:
9788
9789 <tscreen><verb>
9790 void gtk_text_set_word_wrap( GtkText *text,
9791                              gint     word_wrap );
9792 </verb></tscreen>
9793
9794 Using this function allows us to specify that the text widget should
9795 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
9796 TRUE or FALSE value.
9797
9798 <!-- ----------------------------------------------------------------- -->
9799 <sect1>Text Manipulation
9800 <P>
9801 The current insertion point of a Text widget can be set using
9802 <tscreen><verb>
9803 void gtk_text_set_point( GtkText *text,
9804                          guint    index );
9805 </verb></tscreen>
9806
9807 where <tt/index/ is the position to set the insertion point.
9808
9809 Analogous to this is the function for getting the current insertion
9810 point:
9811
9812 <tscreen><verb>
9813 guint gtk_text_get_point( GtkText *text );
9814 </verb></tscreen>
9815
9816 A function that is useful in combination with the above two functions
9817 is
9818
9819 <tscreen><verb>
9820 guint gtk_text_get_length( GtkText *text );
9821 </verb></tscreen>
9822
9823 which returns the current length of the Text widget. The length is the
9824 number of characters that are within the text block of the widget,
9825 including characters such as carriage-return, which marks the end of
9826 lines.
9827
9828 In order to insert text at the current insertion point of a Text
9829 widget, the function gtk_text_insert is used, which also allows us to
9830 specify background and foreground colors and a font for the text.
9831
9832 <tscreen><verb>
9833 void gtk_text_insert( GtkText    *text,
9834                       GdkFont    *font,
9835                       GdkColor   *fore,
9836                       GdkColor   *back,
9837                       const char *chars,
9838                       gint        length );
9839 </verb></tscreen>
9840
9841 Passing a value of <tt/NULL/ in as the value for the foreground color,
9842 background colour or font will result in the values set within the
9843 widget style to be used. Using a value of <tt/-1/ for the length
9844 parameter will result in the whole of the text string given being
9845 inserted.
9846
9847 The text widget is one of the few within GTK that redraws itself
9848 dynamically, outside of the gtk_main function. This means that all
9849 changes to the contents of the text widget take effect
9850 immediately. This may be undesirable when performing multiple changes
9851 to the text widget. In order to allow us to perform multiple updates
9852 to the text widget without it continuously redrawing, we can freeze
9853 the widget, which temporarily stops it from automatically redrawing
9854 itself every time it is changed. We can then thaw the widget after our
9855 updates are complete.
9856
9857 The following two functions perform this freeze and thaw action:
9858
9859 <tscreen><verb>
9860 void gtk_text_freeze( GtkText *text );
9861
9862 void gtk_text_thaw( GtkText *text );         
9863 </verb></tscreen>
9864
9865 Text is deleted from the text widget relative to the current insertion
9866 point by the following two functions. The return value is a TRUE or
9867 FALSE indicator of whether the operation was successful.
9868
9869 <tscreen><verb>
9870 gint gtk_text_backward_delete( GtkText *text,
9871                                guint    nchars );
9872
9873 gint gtk_text_forward_delete ( GtkText *text,
9874                                guint    nchars );
9875 </verb></tscreen>
9876
9877 If you want to retrieve the contents of the text widget, then the
9878 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
9879 character at position <tt/index/ within the text widget <tt/t/.
9880
9881 To retrieve larger blocks of text, we can use the function
9882
9883 <tscreen><verb>
9884 gchar *gtk_editable_get_chars( GtkEditable *editable,
9885                                gint         start_pos,
9886                                gint         end_pos );   
9887 </verb></tscreen>
9888
9889 This is a function of the parent class of the text widget. A value of
9890 -1 as <tt/end_pos/ signifies the end of the text. The index of the
9891 text starts at 0.
9892
9893 The function allocates a new chunk of memory for the text block, so
9894 don't forget to free it with a call to g_free when you have finished
9895 with it.
9896  
9897 <!-- ----------------------------------------------------------------- -->
9898 <sect1>Keyboard Shortcuts
9899 <p>
9900 The text widget has a number of pre-installed keyboard shortcuts for
9901 common editing, motion and selection functions. These are accessed
9902 using Control and Alt key combinations.
9903
9904 In addition to these, holding down the Control key whilst using cursor
9905 key movement will move the cursor by words rather than
9906 characters. Holding down Shift whilst using cursor movement will
9907 extend the selection.
9908
9909 <sect2>Motion Shortcuts
9910 <p>
9911 <itemize>
9912 <item> Ctrl-A   Beginning of line
9913 <item> Ctrl-E   End of line
9914 <item> Ctrl-N   Next Line
9915 <item> Ctrl-P   Previous Line
9916 <item> Ctrl-B   Backward one character
9917 <item> Ctrl-F   Forward one character
9918 <item> Alt-B    Backward one word
9919 <item> Alt-F    Forward one word
9920 </itemize>
9921
9922 <sect2>Editing Shortcuts
9923 <p>
9924 <itemize>
9925 <item> Ctrl-H   Delete Backward Character (Backspace)
9926 <item> Ctrl-D   Delete Forward Character (Delete)
9927 <item> Ctrl-W   Delete Backward Word
9928 <item> Alt-D    Delete Forward Word
9929 <item> Ctrl-K   Delete to end of line
9930 <item> Ctrl-U   Delete line
9931 </itemize>
9932
9933 <sect2>Selection Shortcuts
9934 <p>
9935 <itemize>
9936 <item> Ctrl-X   Cut to clipboard
9937 <item> Ctrl-C   Copy to clipboard
9938 <item> Ctrl-V   Paste from clipboard
9939 </itemize>
9940
9941 <!-- ----------------------------------------------------------------- -->
9942 <sect1>A GtkText Example
9943 <p>
9944 <tscreen><verb>
9945 /* example-start text text.c */
9946
9947 /* text.c */
9948
9949 #include <stdio.h>
9950 #include <gtk/gtk.h>
9951
9952 void text_toggle_editable (GtkWidget *checkbutton,
9953                            GtkWidget *text)
9954 {
9955   gtk_text_set_editable(GTK_TEXT(text),
9956                         GTK_TOGGLE_BUTTON(checkbutton)->active);
9957 }
9958
9959 void text_toggle_word_wrap (GtkWidget *checkbutton,
9960                             GtkWidget *text)
9961 {
9962   gtk_text_set_word_wrap(GTK_TEXT(text),
9963                          GTK_TOGGLE_BUTTON(checkbutton)->active);
9964 }
9965
9966 void close_application( GtkWidget *widget, gpointer data )
9967 {
9968        gtk_main_quit();
9969 }
9970
9971 int main (int argc, char *argv[])
9972 {
9973   GtkWidget *window;
9974   GtkWidget *box1;
9975   GtkWidget *box2;
9976   GtkWidget *hbox;
9977   GtkWidget *button;
9978   GtkWidget *check;
9979   GtkWidget *separator;
9980   GtkWidget *table;
9981   GtkWidget *vscrollbar;
9982   GtkWidget *text;
9983   GdkColormap *cmap;
9984   GdkColor colour;
9985   GdkFont *fixed_font;
9986
9987   FILE *infile;
9988
9989   gtk_init (&amp;argc, &amp;argv);
9990  
9991   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9992   gtk_widget_set_usize (window, 600, 500);
9993   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
9994   gtk_signal_connect (GTK_OBJECT (window), "destroy",
9995                       GTK_SIGNAL_FUNC(close_application),
9996                       NULL);
9997   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
9998   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9999   
10000   
10001   box1 = gtk_vbox_new (FALSE, 0);
10002   gtk_container_add (GTK_CONTAINER (window), box1);
10003   gtk_widget_show (box1);
10004   
10005   
10006   box2 = gtk_vbox_new (FALSE, 10);
10007   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10008   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
10009   gtk_widget_show (box2);
10010   
10011   
10012   table = gtk_table_new (2, 2, FALSE);
10013   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
10014   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
10015   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
10016   gtk_widget_show (table);
10017   
10018   /* Create the GtkText widget */
10019   text = gtk_text_new (NULL, NULL);
10020   gtk_text_set_editable (GTK_TEXT (text), TRUE);
10021   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
10022                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
10023                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10024   gtk_widget_show (text);
10025
10026   /* Add a vertical scrollbar to the GtkText widget */
10027   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
10028   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
10029                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10030   gtk_widget_show (vscrollbar);
10031
10032   /* Get the system colour map and allocate the colour red */
10033   cmap = gdk_colormap_get_system();
10034   colour.red = 0xffff;
10035   colour.green = 0;
10036   colour.blue = 0;
10037   if (!gdk_color_alloc(cmap, &amp;colour)) {
10038     g_error("couldn't allocate colour");
10039   }
10040
10041   /* Load a fixed font */
10042   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
10043
10044   /* Realizing a widget creates a window for it,
10045    * ready for us to insert some text */
10046   gtk_widget_realize (text);
10047
10048   /* Freeze the text widget, ready for multiple updates */
10049   gtk_text_freeze (GTK_TEXT (text));
10050   
10051   /* Insert some coloured text */
10052   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10053                    "Supports ", -1);
10054   gtk_text_insert (GTK_TEXT (text), NULL, &amp;colour, NULL,
10055                    "colored ", -1);
10056   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10057                    "text and different ", -1);
10058   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
10059                    "fonts\n\n", -1);
10060   
10061   /* Load the file text.c into the text window */
10062
10063   infile = fopen("text.c", "r");
10064   
10065   if (infile) {
10066     char buffer[1024];
10067     int nchars;
10068     
10069     while (1)
10070       {
10071         nchars = fread(buffer, 1, 1024, infile);
10072         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
10073                          NULL, buffer, nchars);
10074         
10075         if (nchars < 1024)
10076           break;
10077       }
10078     
10079     fclose (infile);
10080   }
10081
10082   /* Thaw the text widget, allowing the updates to become visible */  
10083   gtk_text_thaw (GTK_TEXT (text));
10084   
10085   hbox = gtk_hbutton_box_new ();
10086   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
10087   gtk_widget_show (hbox);
10088
10089   check = gtk_check_button_new_with_label("Editable");
10090   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
10091   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10092                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
10093   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
10094   gtk_widget_show (check);
10095   check = gtk_check_button_new_with_label("Wrap Words");
10096   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
10097   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10098                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
10099   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
10100   gtk_widget_show (check);
10101
10102   separator = gtk_hseparator_new ();
10103   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10104   gtk_widget_show (separator);
10105
10106   box2 = gtk_vbox_new (FALSE, 10);
10107   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10108   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10109   gtk_widget_show (box2);
10110   
10111   button = gtk_button_new_with_label ("close");
10112   gtk_signal_connect (GTK_OBJECT (button), "clicked",
10113                       GTK_SIGNAL_FUNC(close_application),
10114                       NULL);
10115   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10116   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10117   gtk_widget_grab_default (button);
10118   gtk_widget_show (button);
10119
10120   gtk_widget_show (window);
10121
10122   gtk_main ();
10123   
10124   return(0);       
10125 }
10126 /* example-end */
10127 </verb></tscreen>
10128
10129
10130 <!-- ***************************************************************** -->
10131 <sect> Undocumented Widgets
10132 <!-- ***************************************************************** -->
10133 <p>
10134 These all require authors! :) Please consider contributing to our
10135 tutorial.
10136
10137 If you must use one of these widgets that are undocumented, I strongly
10138 suggest you take a look at their respective header files in the GTK
10139 distribution. GTK's function names are very descriptive. Once you
10140 have an understanding of how things work, it's not difficult to figure
10141 out how to use a widget simply by looking at its function
10142 declarations. This, along with a few examples from others' code, and
10143 it should be no problem.
10144
10145 When you do come to understand all the functions of a new undocumented
10146 widget, please consider writing a tutorial on it so others may benefit
10147 from your time.
10148
10149 <!-- ----------------------------------------------------------------- -->
10150 <sect1> Calendar
10151 <p>
10152 <!-- ----------------------------------------------------------------- -->
10153 <sect1> CTree
10154 <p>
10155 <!-- ----------------------------------------------------------------- -->
10156 <sect1> Curves
10157 <p>
10158 <!-- ----------------------------------------------------------------- -->
10159 <sect1> Drawing Area
10160 <p>
10161 <!-- ----------------------------------------------------------------- -->
10162 <sect1> Font Selection Dialog
10163 <p>
10164 <!-- ----------------------------------------------------------------- -->
10165 <sect1> Gamma Curve
10166 <p>
10167 <!-- ----------------------------------------------------------------- -->
10168 <sect1> Image
10169 <p>
10170 <!-- ----------------------------------------------------------------- -->
10171 <sect1> Packer
10172 <p>
10173 <!-- ----------------------------------------------------------------- -->
10174 <sect1> Plugs and Sockets
10175 <p>
10176 <!-- ----------------------------------------------------------------- -->
10177 <sect1> Preview
10178 <p>
10179
10180 <!--
10181
10182 (This may need to be rewritten to follow the style of the rest of the tutorial)
10183
10184 <tscreen><verb>
10185
10186 Previews serve a number of purposes in GIMP/GTK. The most important one is
10187 this. High quality images may take up to tens of megabytes of memory - easy!
10188 Any operation on an image that big is bound to take a long time. If it takes
10189 you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after
10190 you make an error) to choose the desired modification, it make take you
10191 literally hours to make the right one - if you don't run out of memory
10192 first. People who have spent hours in color darkrooms know the feeling.
10193 Previews to the rescue!
10194
10195 But the annoyance of the delay is not the only issue. Oftentimes it is
10196 helpful to compare the Before and After versions side-by-side or at least
10197 back-to-back. If you're working with big images and 10 second delays,
10198 obtaining the Before and After impressions is, to say the least, difficult.
10199 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
10200 out for most people, while back-to-back is more like back-to-1001, 1002,
10201 ..., 1010-back! Previews to the rescue!
10202
10203 But there's more. Previews allow for side-by-side pre-previews. In other
10204 words, you write a plug-in (e.g. the filterpack simulation) which would have
10205 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
10206 An approach like this acts as a sort of a preview palette and is very
10207 effective for subtle changes. Let's go previews!
10208
10209 There's more. For certain plug-ins real-time image-specific human
10210 intervention maybe necessary. In the SuperNova plug-in, for example, the
10211 user is asked to enter the coordinates of the center of the future
10212 supernova. The easiest way to do this, really, is to present the user with a
10213 preview and ask him to interactively select the spot. Let's go previews!
10214
10215 Finally, a couple of misc uses. One can use previews even when not working
10216 with big images. For example, they are useful when rendering complicated
10217 patterns. (Just check out the venerable Diffraction plug-in + many other
10218 ones!) As another example, take a look at the colormap rotation plug-in
10219 (work in progress). You can also use previews for little logos inside you
10220 plug-ins and even for an image of yourself, The Author. Let's go previews!
10221
10222 When Not to Use Previews
10223
10224 Don't use previews for graphs, drawing etc. GDK is much faster for that. Use
10225 previews only for rendered images!
10226
10227 Let's go previews!
10228
10229 You can stick a preview into just about anything. In a vbox, an hbox, a
10230 table, a button, etc. But they look their best in tight frames around them.
10231 Previews by themselves do not have borders and look flat without them. (Of
10232 course, if the flat look is what you want...) Tight frames provide the
10233 necessary borders.
10234
10235                                [Image][Image]
10236
10237 Previews in many ways are like any other widgets in GTK (whatever that
10238 means) except they possess an additional feature: they need to be filled with
10239 some sort of an image! First, we will deal exclusively with the GTK aspect
10240 of previews and then we'll discuss how to fill them.
10241
10242 GtkWidget *preview!
10243
10244 Without any ado:
10245
10246                               /* Create a preview widget,
10247                               set its size, an show it */
10248 GtkWidget *preview;
10249 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
10250                               /*Other option:
10251                               GTK_PREVIEW_GRAYSCALE);*/
10252 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
10253 gtk_widget_show(preview);
10254 my_preview_rendering_function(preview);
10255
10256 Oh yeah, like I said, previews look good inside frames, so how about:
10257
10258 GtkWidget *create_a_preview(int        Width,
10259                             int        Height,
10260                             int        Colorfulness)
10261 {
10262   GtkWidget *preview;
10263   GtkWidget *frame;
10264   
10265   frame = gtk_frame_new(NULL);
10266   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
10267   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
10268   gtk_widget_show(frame);
10269
10270   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
10271                                        :GTK_PREVIEW_GRAYSCALE);
10272   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
10273   gtk_container_add(GTK_CONTAINER(frame),preview);
10274   gtk_widget_show(preview);
10275
10276   my_preview_rendering_function(preview);
10277   return frame;
10278 }
10279
10280 That's my basic preview. This routine returns the "parent" frame so you can
10281 place it somewhere else in your interface. Of course, you can pass the
10282 parent frame to this routine as a parameter. In many situations, however,
10283 the contents of the preview are changed continually by your application. In
10284 this case you may want to pass a pointer to the preview to a
10285 "create_a_preview()" and thus have control of it later.
10286
10287 One more important note that may one day save you a lot of time. Sometimes
10288 it is desirable to label you preview. For example, you may label the preview
10289 containing the original image as "Original" and the one containing the
10290 modified image as "Less Original". It might occur to you to pack the
10291 preview along with the appropriate label into a vbox. The unexpected caveat
10292 is that if the label is wider than the preview (which may happen for a
10293 variety of reasons unforseeable to you, from the dynamic decision on the
10294 size of the preview to the size of the font) the frame expands and no longer
10295 fits tightly over the preview. The same problem can probably arise in other
10296 situations as well.
10297
10298                                    [Image]
10299
10300 The solution is to place the preview and the label into a 2x1 table and by
10301 attaching them with the following parameters (this is one possible variations
10302 of course. The key is no GTK_FILL in the second attachment):
10303
10304 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
10305                  0,
10306                  GTK_EXPAND|GTK_FILL,
10307                  0,0);
10308 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
10309                  GTK_EXPAND,
10310                  GTK_EXPAND,
10311                  0,0);
10312
10313
10314 And here's the result:
10315
10316                                    [Image]
10317
10318 Misc
10319
10320 Making a preview clickable is achieved most easily by placing it in a
10321 button. It also adds a nice border around the preview and you may not even
10322 need to place it in a frame. See the Filter Pack Simulation plug-in for an
10323 example.
10324
10325 This is pretty much it as far as GTK is concerned.
10326
10327 Filling In a Preview
10328
10329 In order to familiarize ourselves with the basics of filling in previews,
10330 let's create the following pattern (contrived by trial and error):
10331
10332                                    [Image]
10333
10334 void
10335 my_preview_rendering_function(GtkWidget     *preview)
10336 {
10337 #define SIZE 100
10338 #define HALF (SIZE/2)
10339
10340   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
10341   gint i, j;                             /* Coordinates    */
10342   double r, alpha, x, y;
10343
10344   if (preview==NULL) return; /* I usually add this when I want */
10345                              /* to avoid silly crashes. You    */
10346                              /* should probably make sure that */
10347                              /* everything has been nicely     */
10348                              /* initialized!                   */
10349   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
10350                                          /* glib.h contains ABS(x).   */
10351         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
10352         row[i*3+1] = 128;                /* Define Green              */
10353         row[i*3+2] = 224;                /* Define Blue               */
10354       }                                  /* "+0" is for alignment!    */
10355       else {
10356         row[i*3+0] = r*255;
10357         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
10358         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
10359       }
10360     }
10361     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
10362     /* Insert "row" into "preview" starting at the point with  */
10363     /* coordinates (0,j) first column, j_th row extending SIZE */
10364     /* pixels to the right */
10365   }
10366
10367   free(row); /* save some space */
10368   gtk_widget_draw(preview,NULL); /* what does this do? */
10369   gdk_flush(); /* or this? */
10370 }
10371
10372 Non-GIMP users can have probably seen enough to do a lot of things already.
10373 For the GIMP users I have a few pointers to add.
10374
10375 Image Preview
10376
10377 It is probably wise to keep a reduced version of the image around with just
10378 enough pixels to fill the preview. This is done by selecting every n'th
10379 pixel where n is the ratio of the size of the image to the size of the
10380 preview. All further operations (including filling in the previews) are then
10381 performed on the reduced number of pixels only. The following is my
10382 implementation of reducing the image. (Keep in mind that I've had only basic
10383 C!)
10384
10385 (UNTESTED CODE ALERT!!!)
10386
10387 typedef struct {
10388   gint      width;
10389   gint      height;
10390   gint      bbp;
10391   guchar    *rgb;
10392   guchar    *mask;
10393 } ReducedImage;
10394
10395 enum {
10396   SELECTION_ONLY,
10397   SELECTION_IN_CONTEXT,
10398   ENTIRE_IMAGE
10399 };
10400
10401 ReducedImage *Reduce_The_Image(GDrawable *drawable,
10402                                GDrawable *mask,
10403                                gint LongerSize,
10404                                gint Selection)
10405 {
10406   /* This function reduced the image down to the the selected preview size */
10407   /* The preview size is determine by LongerSize, i.e. the greater of the  */
10408   /* two dimensions. Works for RGB images only!                            */
10409   gint RH, RW;          /* Reduced height and reduced width                */
10410   gint width, height;   /* Width and Height of the area being reduced      */
10411   gint bytes=drawable->bpp;
10412   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
10413
10414   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
10415   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
10416   GPixelRgn srcPR, srcMask;
10417   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
10418                              /* image.                                     */
10419
10420   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
10421   width  = x2-x1;
10422   height = y2-y1;
10423   /* If there's a SELECTION, we got its bounds!)
10424
10425   if (width != drawable->width &amp;&amp; height != drawable->height)
10426     NoSelectionMade=FALSE;
10427   /* Become aware of whether the user has made an active selection   */
10428   /* This will become important later, when creating a reduced mask. */
10429
10430   /* If we want to preview the entire image, overrule the above!  */
10431   /* Of course, if no selection has been made, this does nothing! */
10432   if (Selection==ENTIRE_IMAGE) {
10433     x1=0;
10434     x2=drawable->width;
10435     y1=0;
10436     y2=drawable->height;
10437   }
10438
10439   /* If we want to preview a selection with some surrounding area we */
10440   /* have to expand it a little bit. Consider it a bit of a riddle. */
10441   if (Selection==SELECTION_IN_CONTEXT) {
10442     x1=MAX(0,                x1-width/2.0);
10443     x2=MIN(drawable->width,  x2+width/2.0);
10444     y1=MAX(0,                y1-height/2.0);
10445     y2=MIN(drawable->height, y2+height/2.0);
10446   }
10447
10448   /* How we can determine the width and the height of the area being */
10449   /* reduced.                                                        */
10450   width  = x2-x1;
10451   height = y2-y1;
10452
10453   /* The lines below determine which dimension is to be the longer   */
10454   /* side. The idea borrowed from the supernova plug-in. I suspect I */
10455   /* could've thought of it myself, but the truth must be told.      */
10456   /* Plagiarism stinks!                                               */
10457   if (width>height) {
10458     RW=LongerSize;
10459     RH=(float) height * (float) LongerSize/ (float) width;
10460   }
10461   else {
10462     RH=LongerSize;
10463     RW=(float)width * (float) LongerSize/ (float) height;
10464   }
10465
10466   /* The entire image is stretched into a string! */
10467   tempRGB   = (guchar *) malloc(RW*RH*bytes);
10468   tempmask  = (guchar *) malloc(RW*RH);
10469
10470   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height,
10471                        FALSE, FALSE);
10472   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height,
10473                        FALSE, FALSE);
10474
10475   /* Grab enough to save a row of image and a row of mask. */
10476   src_row       = (guchar *) malloc (width*bytes);
10477   src_mask_row  = (guchar *) malloc (width);
10478
10479   for (i=0; i < RH; i++) {
10480     whichrow=(float)i*(float)height/(float)RH;
10481     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
10482     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
10483
10484     for (j=0; j < RW; j++) {
10485       whichcol=(float)j*(float)width/(float)RW;
10486
10487       /* No selection made = each point is completely selected! */
10488       if (NoSelectionMade)
10489         tempmask[i*RW+j]=255;
10490       else
10491         tempmask[i*RW+j]=src_mask_row[whichcol];
10492
10493       /* Add the row to the one long string which now contains the image! */
10494       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
10495       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
10496       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
10497
10498       /* Hold on to the alpha as well */
10499       if (bytes==4)
10500         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
10501     }
10502   }
10503   temp->bpp=bytes;
10504   temp->width=RW;
10505   temp->height=RH;
10506   temp->rgb=tempRGB;
10507   temp->mask=tempmask;
10508   return temp;
10509 }
10510
10511 The following is a preview function which used the same ReducedImage type!
10512 Note that it uses fakes transparency (if one is present by means of
10513 fake_transparency which is defined as follows:
10514
10515 gint fake_transparency(gint i, gint j)
10516 {
10517   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
10518     return 64;
10519   else
10520     return 196;
10521 }
10522
10523 Now here's the preview function:
10524
10525 void
10526 my_preview_render_function(GtkWidget     *preview,
10527                            gint          changewhat,
10528                            gint          changewhich)
10529 {
10530   gint Inten, bytes=drawable->bpp;
10531   gint i, j, k;
10532   float partial;
10533   gint RW=reduced->width;
10534   gint RH=reduced->height;
10535   guchar *row=malloc(bytes*RW);;
10536
10537
10538   for (i=0; i < RH; i++) {
10539     for (j=0; j < RW; j++) {
10540
10541       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
10542       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
10543       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
10544
10545       if (bytes==4)
10546         for (k=0; k<3; k++) {
10547           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
10548           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
10549         }
10550     }
10551     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
10552   }
10553
10554   free(a);
10555   gtk_widget_draw(preview,NULL);
10556   gdk_flush();
10557 }
10558
10559 Applicable Routines
10560
10561 guint           gtk_preview_get_type           (void);
10562 /* No idea */
10563 void            gtk_preview_uninit             (void);
10564 /* No idea */
10565 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
10566 /* Described above */
10567 void            gtk_preview_size               (GtkPreview      *preview,
10568                                                 gint             width,
10569                                                 gint             height);
10570 /* Allows you to resize an existing preview.    */
10571 /* Apparently there's a bug in GTK which makes  */
10572 /* this process messy. A way to clean up a mess */
10573 /* is to manually resize the window containing  */
10574 /* the preview after resizing the preview.      */
10575
10576 void            gtk_preview_put                (GtkPreview      *preview,
10577                                                 GdkWindow       *window,
10578                                                 GdkGC           *gc,
10579                                                 gint             srcx,
10580                                                 gint             srcy,
10581                                                 gint             destx,
10582                                                 gint             desty,
10583                                                 gint             width,
10584                                                 gint             height);
10585 /* No idea */
10586
10587 void            gtk_preview_put_row            (GtkPreview      *preview,
10588                                                 guchar          *src,
10589                                                 guchar          *dest,
10590                                                 gint             x,
10591                                                 gint             y,
10592                                                 gint             w);
10593 /* No idea */
10594
10595 void            gtk_preview_draw_row           (GtkPreview      *preview,
10596                                                 guchar          *data,
10597                                                 gint             x,
10598                                                 gint             y,
10599                                                 gint             w);
10600 /* Described in the text */
10601
10602 void            gtk_preview_set_expand         (GtkPreview      *preview,
10603                                                 gint             expand);
10604 /* No idea */
10605
10606 /* No clue for any of the below but    */
10607 /* should be standard for most widgets */
10608 void            gtk_preview_set_gamma          (double           gamma);
10609 void            gtk_preview_set_color_cube     (guint            nred_shades,
10610                                                 guint            ngreen_shades,
10611                                                 guint            nblue_shades,
10612                                                 guint            ngray_shades);
10613 void            gtk_preview_set_install_cmap   (gint             install_cmap);
10614 void            gtk_preview_set_reserved       (gint             nreserved);
10615 GdkVisual*      gtk_preview_get_visual         (void);
10616 GdkColormap*    gtk_preview_get_cmap           (void);
10617 GtkPreviewInfo* gtk_preview_get_info           (void);
10618
10619 That's all, folks!
10620
10621 </verb></tscreen>
10622
10623 -->
10624
10625 <!-- ***************************************************************** -->
10626 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
10627 <!-- ***************************************************************** -->
10628 <p>
10629 This describes the functions used to operate on widgets.  These can be
10630 used to set style, padding, size etc.
10631
10632 (Maybe I should make a whole section on accelerators.)
10633
10634 <tscreen><verb>
10635 void gtk_widget_install_accelerator( GtkWidget           *widget,
10636                                      GtkAcceleratorTable *table,
10637                                      gchar               *signal_name,
10638                                      gchar                key,
10639                                      guint8               modifiers );
10640
10641 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
10642                                      GtkAcceleratorTable *table,
10643                                      gchar               *signal_name);
10644
10645 void gtk_widget_activate( GtkWidget *widget );
10646
10647 void gtk_widget_set_name( GtkWidget *widget,
10648                           gchar     *name );
10649
10650 gchar *gtk_widget_get_name( GtkWidget *widget );
10651
10652 void gtk_widget_set_sensitive( GtkWidget *widget,
10653                                gint       sensitive );
10654
10655 void gtk_widget_set_style( GtkWidget *widget,
10656                            GtkStyle  *style );
10657                                            
10658 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
10659
10660 GtkStyle *gtk_widget_get_default_style( void );
10661
10662 void gtk_widget_set_uposition( GtkWidget *widget,
10663                                gint       x,
10664                                gint       y );
10665
10666 void gtk_widget_set_usize( GtkWidget *widget,
10667                            gint       width,
10668                            gint       height );
10669
10670 void gtk_widget_grab_focus( GtkWidget *widget );
10671
10672 void gtk_widget_show( GtkWidget *widget );
10673
10674 void gtk_widget_hide( GtkWidget *widget );
10675 </verb></tscreen>
10676
10677 <!-- ***************************************************************** -->
10678 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
10679 <!-- ***************************************************************** -->
10680
10681 <!-- ----------------------------------------------------------------- -->
10682 <sect1>Timeouts
10683 <p>
10684 You may be wondering how you make GTK do useful work when in gtk_main.
10685 Well, you have several options. Using the following functions you can
10686 create a timeout function that will be called every "interval"
10687 milliseconds.
10688
10689 <tscreen><verb>
10690 gint gtk_timeout_add( guint32     interval,
10691                       GtkFunction function,
10692                       gpointer    data );
10693 </verb></tscreen>
10694
10695 The first argument is the number of milliseconds between calls to your
10696 function. The second argument is the function you wish to have called,
10697 and the third, the data passed to this callback function. The return
10698 value is an integer "tag" which may be used to stop the timeout by
10699 calling:
10700
10701 <tscreen><verb>
10702 void gtk_timeout_remove( gint tag );
10703 </verb></tscreen>
10704
10705 You may also stop the timeout function by returning zero or FALSE from
10706 your callback function. Obviously this means if you want your function
10707 to continue to be called, it should return a non-zero value,
10708 i.e. TRUE.
10709
10710 The declaration of your callback should look something like this:
10711
10712 <tscreen><verb>
10713 gint timeout_callback( gpointer data );
10714 </verb></tscreen>
10715
10716 <!-- ----------------------------------------------------------------- -->
10717 <sect1>Monitoring IO
10718 <p>
10719 A nifty feature of GDK (the library that underlies GTK), is the
10720 ability to have it check for data on a file descriptor for you (as
10721 returned by open(2) or socket(2)). This is especially useful for
10722 networking applications. The function:
10723
10724 <tscreen><verb>
10725 gint gdk_input_add( gint              source,
10726                     GdkInputCondition condition,
10727                     GdkInputFunction  function,
10728                     gpointer          data );
10729 </verb></tscreen>
10730
10731 Where the first argument is the file descriptor you wish to have
10732 watched, and the second specifies what you want GDK to look for. This
10733 may be one of:
10734
10735 <itemize>
10736 <item>GDK_INPUT_READ - Call your function when there is data ready for
10737 reading on your file descriptor.
10738
10739 <item>GDK_INPUT_WRITE - Call your function when the file descriptor is
10740 ready for writing.
10741 </itemize>
10742
10743 As I'm sure you've figured out already, the third argument is the
10744 function you wish to have called when the above conditions are
10745 satisfied, and the fourth is the data to pass to this function.
10746
10747 The return value is a tag that may be used to stop GDK from monitoring
10748 this file descriptor using the following function.
10749
10750 <tscreen><verb>
10751 void gdk_input_remove( gint tag );
10752 </verb></tscreen>
10753
10754 The callback function should be declared as:
10755
10756 <tscreen><verb>
10757 void input_callback( gpointer          data,
10758                      gint              source, 
10759                      GdkInputCondition condition );
10760 </verb></tscreen>
10761
10762 Where <tt/source/ and <tt/condition/ are as specified above.
10763
10764 <!-- ----------------------------------------------------------------- -->
10765 <sect1>Idle Functions
10766 <p>
10767 <!-- TODO: Need to check on idle priorities - TRG -->
10768 What if you have a function you want called when nothing else is
10769 happening ?
10770
10771 <tscreen><verb>
10772 gint gtk_idle_add( GtkFunction function,
10773                    gpointer    data );
10774 </verb></tscreen>
10775
10776 This causes GTK to call the specified function whenever nothing else
10777 is happening.
10778
10779 <tscreen><verb>
10780 void gtk_idle_remove( gint tag );
10781 </verb></tscreen>
10782
10783 I won't explain the meaning of the arguments as they follow very much
10784 like the ones above. The function pointed to by the first argument to
10785 gtk_idle_add will be called whenever the opportunity arises. As with
10786 the others, returning FALSE will stop the idle function from being
10787 called.
10788
10789 <!-- ***************************************************************** -->
10790 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
10791 <!-- ***************************************************************** -->
10792
10793 <!-- ----------------------------------------------------------------- -->
10794 <sect1>Signal Functions
10795
10796 <!-- ----------------------------------------------------------------- -->
10797 <sect2>Connecting and Disconnecting Signal Handlers
10798 <p>
10799
10800 <tscreen><verb>
10801 guint gtk_signal_connect( GtkObject     *object,
10802                           const gchar   *name,
10803                           GtkSignalFunc  func,
10804                           gpointer       func_data );
10805
10806 guint gtk_signal_connect_after( GtkObject     *object,
10807                                 const gchar   *name,
10808                                 GtkSignalFunc  func,
10809                                 gpointer       func_data );
10810
10811 guint gtk_signal_connect_object( GtkObject     *object,
10812                                  const gchar   *name,
10813                                  GtkSignalFunc  func,
10814                                  GtkObject     *slot_object );
10815
10816 guint gtk_signal_connect_object_after( GtkObject     *object,
10817                                        const gchar   *name,
10818                                        GtkSignalFunc  func,
10819                                        GtkObject     *slot_object );
10820
10821 guint gtk_signal_connect_full( GtkObject          *object,
10822                                const gchar        *name,
10823                                GtkSignalFunc       func,
10824                                GtkCallbackMarshal  marshal,
10825                                gpointer            data,
10826                                GtkDestroyNotify    destroy_func,
10827                                gint                object_signal,
10828                                gint                after );
10829
10830 guint gtk_signal_connect_interp( GtkObject          *object,
10831                                  const gchar        *name,
10832                                  GtkCallbackMarshal  func,
10833                                  gpointer            data,
10834                                  GtkDestroyNotify    destroy_func,
10835                                  gint                after );
10836
10837 void gtk_signal_connect_object_while_alive( GtkObject     *object,
10838                                             const gchar   *signal,
10839                                             GtkSignalFunc  func,
10840                                             GtkObject     *alive_object );
10841
10842 void gtk_signal_connect_while_alive( GtkObject     *object,
10843                                      const gchar   *signal,
10844                                      GtkSignalFunc  func,
10845                                      gpointer       func_data,
10846                                      GtkObject     *alive_object );
10847
10848 void gtk_signal_disconnect( GtkObject *object,
10849                             guint      handler_id );
10850
10851 void gtk_signal_disconnect_by_func( GtkObject     *object,
10852                                     GtkSignalFunc  func,
10853                                     gpointer       data );
10854 </verb></tscreen>
10855
10856 <!-- ----------------------------------------------------------------- -->
10857 <sect2>Blocking and Unblocking Signal Handlers
10858 <p>
10859 <tscreen><verb>
10860 void gtk_signal_handler_block( GtkObject *object,
10861                                guint      handler_id);
10862
10863 void gtk_signal_handler_block_by_func( GtkObject     *object,
10864                                        GtkSignalFunc  func,
10865                                        gpointer       data );
10866
10867 void gtk_signal_handler_block_by_data( GtkObject *object,
10868                                        gpointer   data );
10869
10870 void gtk_signal_handler_unblock( GtkObject *object,
10871                                  guint      handler_id );
10872
10873 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
10874                                          GtkSignalFunc  func,
10875                                          gpointer       data );
10876
10877 void gtk_signal_handler_unblock_by_data( GtkObject *object,
10878                                          gpointer   data );
10879 </verb></tscreen>
10880
10881 <!-- ----------------------------------------------------------------- -->
10882 <sect2>Emitting and Stopping Signals
10883 <p>
10884 <tscreen><verb>
10885 void gtk_signal_emit( GtkObject *object,
10886                       guint      signal_id,
10887                       ... );
10888
10889 void gtk_signal_emit_by_name( GtkObject   *object,
10890                               const gchar *name,
10891                               ... );
10892
10893 void gtk_signal_emitv( GtkObject *object,
10894                        guint      signal_id,
10895                        GtkArg    *params );
10896
10897 void gtk_signal_emitv_by_name( GtkObject   *object,
10898                                const gchar *name,
10899                                GtkArg      *params );
10900
10901 guint gtk_signal_n_emissions( GtkObject *object,
10902                               guint      signal_id );
10903
10904 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
10905                                       const gchar *name );
10906
10907 void gtk_signal_emit_stop( GtkObject *object,
10908                            guint      signal_id );
10909
10910 void gtk_signal_emit_stop_by_name( GtkObject   *object,
10911                                    const gchar *name );
10912 </verb></tscreen>
10913
10914 <!-- ----------------------------------------------------------------- -->
10915 <sect1>Signal Emission and Propagation
10916 <p>
10917 Signal emission is the process wherby GTK runs all handlers for a
10918 specific object and signal.
10919
10920 First, note that the return value from a signal emission is the return
10921 value of the <em>last</em> handler executed. Since event signals are
10922 all of type GTK_RUN_LAST, this will be the default (GTK supplied)
10923 default handler, unless you connect with gtk_signal_connect_after().
10924
10925 The way an event (say GTK_BUTTON_PRESS) is handled, is:
10926 <itemize>
10927 <item>Start with the widget where the event occured.
10928
10929 <item>Emit the generic "event" signal. If that signal handler returns
10930 a value of TRUE, stop all processing.
10931
10932 <item>Otherwise, emit a specific, "button_press_event" signal. If that
10933 returns TRUE, stop all processing.
10934
10935 <item>Otherwise, go to the widget's parent, and repeat the above steps.
10936
10937 <item>Contimue until some signal handler returns TRUE, or until the
10938 top-level widget is reached.
10939 </itemize>
10940
10941 Some consequences of the above are:
10942 <itemize>
10943 <item>Your handler's return value will have no effect if there is a
10944 default handler, unless you connect with gtk_signal_connect_after().
10945
10946 <item>To prevent the default handler from being run, you need to
10947 connect with gtk_signal_connect() and use
10948 gtk_signal_emit_stop_by_name() - the return value only affects whether
10949 the signal is propagated, not the current emission.
10950 </itemize>
10951
10952 <!-- ***************************************************************** -->
10953 <sect>Managing Selections
10954 <!-- ***************************************************************** -->
10955
10956 <!-- ----------------------------------------------------------------- -->
10957 <sect1> Overview
10958 <p>
10959 One type of interprocess communication supported by GTK is
10960 <em>selections</em>. A selection identifies a chunk of data, for
10961 instance, a portion of text, selected by the user in some fashion, for
10962 instance, by dragging with the mouse. Only one application on a
10963 display, (the <em>owner</em>) can own a particular selection at one
10964 time, so when a selection is claimed by one application, the previous
10965 owner must indicate to the user that selection has been
10966 relinquished. Other applications can request the contents of a
10967 selection in different forms, called <em>targets</em>. There can be
10968 any number of selections, but most X applications only handle one, the
10969 <em>primary selection</em>.
10970
10971 In most cases, it isn't necessary for a GTK application to deal with
10972 selections itself. The standard widgets, such as the Entry widget,
10973 already have the capability to claim the selection when appropriate
10974 (e.g., when the user drags over text), and to retrieve the contents of
10975 the selection owned by another widget, or another application (e.g.,
10976 when the user clicks the second mouse button). However, there may be
10977 cases in which you want to give other widgets the ability to supply
10978 the selection, or you wish to retrieve targets not supported by
10979 default.
10980
10981 A fundamental concept needed to understand selection handling is that
10982 of the <em>atom</em>. An atom is an integer that uniquely identifies a
10983 string (on a certain display). Certain atoms are predefined by the X
10984 server, and in some cases there are constants in <tt>gtk.h</tt>
10985 corresponding to these atoms. For instance the constant
10986 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
10987 In other cases, you should use the functions
10988 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
10989 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
10990 selections and targets are identified by atoms.
10991
10992 <!-- ----------------------------------------------------------------- -->
10993 <sect1> Retrieving the selection
10994 <p>
10995 Retrieving the selection is an asynchronous process. To start the
10996 process, you call:
10997
10998 <tscreen><verb>
10999 gint gtk_selection_convert( GtkWidget *widget, 
11000                             GdkAtom    selection, 
11001                             GdkAtom    target,
11002                             guint32    time );
11003 </verb</tscreen>
11004
11005 This <em>converts</em> the selection into the form specified by
11006 <tt/target/. If at all possible, the time field should be the time
11007 from the event that triggered the selection. This helps make sure that
11008 events occur in the order that the user requested them. However, if it
11009 is not available (for instance, if the conversion was triggered by a
11010 "clicked" signal), then you can use the constant
11011 <tt>GDK_CURRENT_TIME</tt>.
11012
11013 When the selection owner responds to the request, a
11014 "selection_received" signal is sent to your application. The handler
11015 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
11016 structure, which is defined as:
11017
11018 <tscreen><verb>
11019 struct _GtkSelectionData
11020 {
11021   GdkAtom selection;
11022   GdkAtom target;
11023   GdkAtom type;
11024   gint    format;
11025   guchar *data;
11026   gint    length;
11027 };
11028 </verb></tscreen>
11029
11030 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
11031 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
11032 identifies the type of data returned by the selection owner. Some
11033 possible values are "STRING", a string of latin-1 characters, "ATOM",
11034 a series of atoms, "INTEGER", an integer, etc. Most targets can only
11035 return one type. <tt/format/ gives the length of the units (for
11036 instance characters) in bits. Usually, you don't care about this when
11037 receiving data. <tt>data</tt> is a pointer to the returned data, and
11038 <tt>length</tt> gives the length of the returned data, in bytes. If
11039 <tt>length</tt> is negative, then an error occurred and the selection
11040 could not be retrieved. This might happen if no application owned the
11041 selection, or if you requested a target that the application didn't
11042 support. The buffer is actually guaranteed to be one byte longer than
11043 <tt>length</tt>; the extra byte will always be zero, so it isn't
11044 necessary to make a copy of strings just to null terminate them.
11045
11046 In the following example, we retrieve the special target "TARGETS",
11047 which is a list of all targets into which the selection can be
11048 converted.
11049
11050 <tscreen><verb>
11051 /* example-start selection gettargets.c */
11052
11053 #include <gtk/gtk.h>
11054
11055 void selection_received (GtkWidget *widget, 
11056                          GtkSelectionData *selection_data, 
11057                          gpointer data);
11058
11059 /* Signal handler invoked when user clicks on the "Get Targets" button */
11060 void
11061 get_targets (GtkWidget *widget, gpointer data)
11062 {
11063   static GdkAtom targets_atom = GDK_NONE;
11064
11065   /* Get the atom corresponding to the string "TARGETS" */
11066   if (targets_atom == GDK_NONE)
11067     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
11068
11069   /* And request the "TARGETS" target for the primary selection */
11070   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
11071                          GDK_CURRENT_TIME);
11072 }
11073
11074 /* Signal handler called when the selections owner returns the data */
11075 void
11076 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
11077                     gpointer data)
11078 {
11079   GdkAtom *atoms;
11080   GList *item_list;
11081   int i;
11082
11083   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
11084   if (selection_data->length < 0)
11085     {
11086       g_print ("Selection retrieval failed\n");
11087       return;
11088     }
11089   /* Make sure we got the data in the expected form */
11090   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
11091     {
11092       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
11093       return;
11094     }
11095   
11096   /* Print out the atoms we received */
11097   atoms = (GdkAtom *)selection_data->data;
11098
11099   item_list = NULL;
11100   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
11101     {
11102       char *name;
11103       name = gdk_atom_name (atoms[i]);
11104       if (name != NULL)
11105         g_print ("%s\n",name);
11106       else
11107         g_print ("(bad atom)\n");
11108     }
11109
11110   return;
11111 }
11112
11113 int 
11114 main (int argc, char *argv[])
11115 {
11116   GtkWidget *window;
11117   GtkWidget *button;
11118   
11119   gtk_init (&amp;argc, &amp;argv);
11120
11121   /* Create the toplevel window */
11122
11123   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11124   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11125   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11126
11127   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11128                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11129
11130   /* Create a button the user can click to get targets */
11131
11132   button = gtk_button_new_with_label ("Get Targets");
11133   gtk_container_add (GTK_CONTAINER (window), button);
11134
11135   gtk_signal_connect (GTK_OBJECT(button), "clicked",
11136                       GTK_SIGNAL_FUNC (get_targets), NULL);
11137   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
11138                       GTK_SIGNAL_FUNC (selection_received), NULL);
11139
11140   gtk_widget_show (button);
11141   gtk_widget_show (window);
11142   
11143   gtk_main ();
11144   
11145   return 0;
11146 }
11147 /* example-end */
11148 </verb></tscreen>
11149
11150 <!-- ----------------------------------------------------------------- -->
11151 <sect1> Supplying the selection 
11152 <p>
11153 Supplying the selection is a bit more complicated. You must register 
11154 handlers that will be called when your selection is requested. For
11155 each selection/target pair you will handle, you make a call to:
11156
11157 <tscreen><verb>
11158 void gtk_selection_add_handler( GtkWidget            *widget, 
11159                                 GdkAtom               selection,
11160                                 GdkAtom               target,
11161                                 GtkSelectionFunction  function,
11162                                 GtkRemoveFunction     remove_func,
11163                                 gpointer              data );
11164 </verb></tscreen>
11165
11166 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
11167 this handler will manage.  <tt/remove_func/, if not
11168 NULL, will be called when the signal handler is removed. This is
11169 useful, for instance, for interpreted languages which need to
11170 keep track of a reference count for <tt/data/.
11171
11172 The callback function has the signature:
11173
11174 <tscreen><verb>
11175 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
11176                                       GtkSelectionData *selection_data,
11177                                       gpointer          data );
11178
11179 </verb></tscreen>
11180
11181 The GtkSelectionData is the same as above, but this time, we're
11182 responsible for filling in the fields <tt/type/, <tt/format/,
11183 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
11184 important here - the X server uses it to figure out whether the data
11185 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
11186 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
11187 function:
11188
11189 <tscreen><verb>
11190 void gtk_selection_data_set( GtkSelectionData *selection_data,
11191                              GdkAtom           type,
11192                              gint              format,
11193                              guchar           *data,
11194                              gint              length );
11195 </verb></tscreen>
11196
11197 This function takes care of properly making a copy of the data so that
11198 you don't have to worry about keeping it around. (You should not fill
11199 in the fields of the GtkSelectionData structure by hand.)
11200
11201 When prompted by the user, you claim ownership of the selection by
11202 calling:
11203
11204 <tscreen><verb>
11205 gint gtk_selection_owner_set( GtkWidget *widget,
11206                               GdkAtom    selection,
11207                               guint32    time );
11208 </verb></tscreen>
11209
11210 If another application claims ownership of the selection, you will
11211 receive a "selection_clear_event".
11212
11213 As an example of supplying the selection, the following program adds
11214 selection functionality to a toggle button. When the toggle button is
11215 depressed, the program claims the primary selection. The only target
11216 supported (aside from certain targets like "TARGETS" supplied by GTK
11217 itself), is the "STRING" target. When this target is requested, a
11218 string representation of the time is returned.
11219
11220 <tscreen><verb>
11221 /* example-start selection setselection.c */
11222
11223 #include <gtk/gtk.h>
11224 #include <time.h>
11225
11226 /* Callback when the user toggles the selection */
11227 void
11228 selection_toggled (GtkWidget *widget, gint *have_selection)
11229 {
11230   if (GTK_TOGGLE_BUTTON(widget)->active)
11231     {
11232       *have_selection = gtk_selection_owner_set (widget,
11233                                                  GDK_SELECTION_PRIMARY,
11234                                                  GDK_CURRENT_TIME);
11235       /* if claiming the selection failed, we return the button to
11236          the out state */
11237       if (!*have_selection)
11238         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11239     }
11240   else
11241     {
11242       if (*have_selection)
11243         {
11244           /* Before clearing the selection by setting the owner to NULL,
11245              we check if we are the actual owner */
11246           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
11247             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
11248                                      GDK_CURRENT_TIME);
11249           *have_selection = FALSE;
11250         }
11251     }
11252 }
11253
11254 /* Called when another application claims the selection */
11255 gint
11256 selection_clear (GtkWidget *widget, GdkEventSelection *event,
11257                  gint *have_selection)
11258 {
11259   *have_selection = FALSE;
11260   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11261
11262   return TRUE;
11263 }
11264
11265 /* Supplies the current time as the selection. */
11266 void
11267 selection_handle (GtkWidget *widget, 
11268                   GtkSelectionData *selection_data,
11269                   gpointer data)
11270 {
11271   gchar *timestr;
11272   time_t current_time;
11273
11274   current_time = time (NULL);
11275   timestr = asctime (localtime(&amp;current_time)); 
11276   /* When we return a single string, it should not be null terminated.
11277      That will be done for us */
11278
11279   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
11280                           8, timestr, strlen(timestr));
11281 }
11282
11283 int
11284 main (int argc, char *argv[])
11285 {
11286   GtkWidget *window;
11287
11288   GtkWidget *selection_button;
11289
11290   static int have_selection = FALSE;
11291   
11292   gtk_init (&amp;argc, &amp;argv);
11293
11294   /* Create the toplevel window */
11295
11296   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11297   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11298   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11299
11300   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11301                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11302
11303   /* Create a toggle button to act as the selection */
11304
11305   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
11306   gtk_container_add (GTK_CONTAINER (window), selection_button);
11307   gtk_widget_show (selection_button);
11308
11309   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
11310                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
11311   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
11312                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
11313
11314   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
11315                              GDK_SELECTION_TYPE_STRING,
11316                              selection_handle, NULL);
11317
11318   gtk_widget_show (selection_button);
11319   gtk_widget_show (window);
11320   
11321   gtk_main ();
11322   
11323   return 0;
11324 }
11325 /* example-end */
11326 </verb></tscreen>
11327
11328
11329 <!-- ***************************************************************** -->
11330 <sect>glib<label id="sec_glib">
11331 <!-- ***************************************************************** -->
11332 <p>
11333 glib is a lower-level library that provides many useful definitions
11334 and functions available for use when creating GDK and GTK
11335 applications. These include definitions for basic types and their
11336 limits, standard macros, type conversions, byte order, memory
11337 allocation, warnings and assertions, message logging, timers, string
11338 utilities, hook functions, a lexical scanner, dynamic loading of
11339 modules, and automatic string completion. A number of data structures
11340 (and their related operations) are also defined, including memory
11341 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
11342 (which can grow dynamically), string chunks (groups of strings),
11343 arrays (which can grow in size as elements are added), balanced binary
11344 trees, N-ary trees, quarks (a two-way association of a string and a
11345 unique integer identifier), keyed data lists (lists of data elements
11346 accessible by a string or integer id), relations and tuples (tables of
11347 data which can be indexed on any number of fields), and caches.
11348
11349 A summary of some of glib's capabilities follows; not every function,
11350 data structure, or operation is covered here.  For more complete
11351 information about the glib routines, see the glib documentation. One
11352 source of glib documentation is http://www.gtk.org/ <htmlurl
11353 url="http://www.gtk.org/" name="http://www.gtk.org/">.
11354
11355 If you are using a language other than C, you should consult your
11356 language's binding documentation. In some cases your language may
11357 have equivalent functionality built-in, while in other cases it may
11358 not.
11359
11360 <!-- ----------------------------------------------------------------- -->
11361 <sect1>Definitions
11362 <p>
11363 Definitions for the extremes of many of the standard types are:
11364
11365 <tscreen><verb>
11366 G_MINFLOAT
11367 G_MAXFLOAT
11368 G_MINDOUBLE
11369 G_MAXDOUBLE
11370 G_MINSHORT
11371 G_MAXSHORT
11372 G_MININT
11373 G_MAXINT
11374 G_MINLONG
11375 G_MAXLONG
11376 </verb></tscreen>
11377
11378 Also, the following typedefs. The ones left unspecified are dynamically set
11379 depending on the architecture. Remember to avoid counting on the size of a
11380 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
11381 bytes, but 4 on Intel 80x86 family CPUs.
11382
11383 <tscreen><verb>
11384 char   gchar;
11385 short  gshort;
11386 long   glong;
11387 int    gint;
11388 char   gboolean;
11389
11390 unsigned char   guchar;
11391 unsigned short  gushort;
11392 unsigned long   gulong;
11393 unsigned int    guint;
11394
11395 float   gfloat;
11396 double  gdouble;
11397 long double gldouble;
11398
11399 void* gpointer;
11400
11401 gint8
11402 guint8
11403 gint16
11404 guint16
11405 gint32
11406 guint32
11407 </verb></tscreen>
11408
11409 <!-- ----------------------------------------------------------------- -->
11410 <sect1>Doubly Linked Lists
11411 <p>
11412 The following functions are used to create, manage, and destroy
11413 standard doubly linked lists. Each element in the list contains a
11414 piece of data, together with pointers which link to the previous and
11415 next elements in the list. This enables easy movement in either
11416 direction through the list. The data item is of type "gpointer",
11417 which means the data can be a pointer to your real data or (through
11418 casting) a numeric value (but do not assume that int and gpointer have
11419 the same size!). These routines internally allocate list elements in
11420 blocks, which is more efficient than allocating elements individually.
11421
11422 There is no function to specifically create a list. Instead, simply
11423 create a variable of type GList* and set its value to NULL; NULL is
11424 considered to be the empty list.
11425
11426 To add elements to a list, use the g_list_append(), g_list_prepend(),
11427 g_list_insert(), or g_list_insert_sorted() routines. In all cases
11428 they accept a pointer to the beginning of the list, and return the
11429 (possibly changed) pointer to the beginning of the list. Thus, for
11430 all of the operations that add or remove elements, be sure to save the
11431 returned value!
11432
11433 <tscreen><verb>
11434 GList *g_list_append( GList    *list,
11435                       gpointer  data );
11436 </verb></tscreen>
11437
11438 This adds a new element (with value <tt/data/) onto the end of the
11439 list.
11440   
11441 <tscreen><verb>    
11442 GList *g_list_prepend( GList    *list,
11443                        gpointer  data );
11444 </verb></tscreen>
11445
11446 This adds a new element (with value <tt/data/) to the beginning of the
11447 list.
11448
11449 <tscreen><verb>         
11450 GList *g_list_insert( GList    *list,
11451                       gpointer  data,
11452                       gint      position );
11453
11454 </verb></tscreen>
11455
11456 This inserts a new element (with value data) into the list at the
11457 given position. If position is 0, this is just like g_list_prepend();
11458 if position is less than 0, this is just like g_list_append().
11459
11460 <tscreen><verb>
11461 GList *g_list_remove( GList    *list,
11462                       gpointer  data );
11463 </verb></tscreen>
11464
11465 This removes the element in the list with the value <tt/data/;
11466 if the element isn't there, the list is unchanged.
11467
11468 <tscreen><verb>
11469 void g_list_free( GList *list );
11470 </verb></tscreen>
11471
11472 This frees all of the memory used by a GList. If the list elements
11473 refer to dynamically-allocated memory, then they should be freed
11474 first.
11475
11476 There are many other glib functions that support doubly linked lists;
11477 see the glib documentation for more information.  Here are a few of
11478 the more useful functions' signatures:
11479
11480 <tscreen><verb>            
11481 GList *g_list_remove_link( GList *list,
11482                            GList *link );
11483
11484 GList *g_list_reverse( GList *list );
11485
11486 GList *g_list_nth( GList *list,
11487                    gint   n );
11488                            
11489 GList *g_list_find( GList    *list,
11490                     gpointer  data );
11491
11492 GList *g_list_last( GList *list );
11493
11494 GList *g_list_first( GList *list );
11495
11496 gint g_list_length( GList *list );
11497
11498 void g_list_foreach( GList    *list,
11499                      GFunc     func,
11500                      gpointer  user_data );
11501 </verb></tscreen>                                             
11502
11503 <!-- ----------------------------------------------------------------- -->
11504 <sect1>Singly Linked Lists
11505 <p>
11506 Many of the above functions for singly linked lists are identical to the
11507 above. Here is a list of some of their operations:
11508
11509 <tscreen><verb>
11510 GSList *g_slist_append( GSList   *list,
11511                         gpointer  data );
11512                 
11513 GSList *g_slist_prepend( GSList   *list,
11514                          gpointer  data );
11515                              
11516 GSList *g_slist_insert( GSList   *list,
11517                         gpointer  data,
11518                         gint      position );
11519                              
11520 GSList *g_slist_remove( GSList   *list,
11521                         gpointer  data );
11522                              
11523 GSList *g_slist_remove_link( GSList *list,
11524                              GSList *link );
11525                              
11526 GSList *g_slist_reverse( GSList *list );
11527
11528 GSList *g_slist_nth( GSList *list,
11529                      gint    n );
11530                              
11531 GSList *g_slist_find( GSList   *list,
11532                       gpointer  data );
11533                              
11534 GSList *g_slist_last( GSList *list );
11535
11536 gint g_slist_length( GSList *list );
11537
11538 void g_slist_foreach( GSList   *list,
11539                       GFunc     func,
11540                       gpointer  user_data );
11541         
11542 </verb></tscreen>
11543
11544 <!-- ----------------------------------------------------------------- -->
11545 <sect1>Memory Management
11546 <p>
11547 <tscreen><verb>
11548 gpointer g_malloc( gulong size );
11549 </verb></tscreen>
11550
11551 This is a replacement for malloc(). You do not need to check the return
11552 value as it is done for you in this function. If the memory allocation
11553 fails for whatever reasons, your applications will be terminated.
11554
11555 <tscreen><verb>
11556 gpointer g_malloc0( gulong size );
11557 </verb></tscreen>
11558
11559 Same as above, but zeroes the memory before returning a pointer to it.
11560
11561 <tscreen><verb>
11562 gpointer g_realloc( gpointer mem,
11563                     gulong   size );
11564 </verb></tscreen>
11565
11566 Relocates "size" bytes of memory starting at "mem".  Obviously, the
11567 memory should have been previously allocated.
11568
11569 <tscreen><verb>
11570 void g_free( gpointer mem );
11571 </verb></tscreen>
11572
11573 Frees memory. Easy one. If <tt/mem/ is NULL it simply returns.
11574
11575 <tscreen><verb>
11576 void g_mem_profile( void );
11577 </verb></tscreen>
11578
11579 Dumps a profile of used memory, but requires that you add #define
11580 MEM_PROFILE to the top of glib/gmem.c and re-make and make install.
11581
11582 <tscreen><verb>
11583 void g_mem_check( gpointer mem );
11584 </verb></tscreen>
11585
11586 Checks that a memory location is valid.  Requires you add #define
11587 MEM_CHECK to the top of gmem.c and re-make and make install.
11588
11589 <!-- ----------------------------------------------------------------- -->
11590 <sect1>Timers
11591 <p>
11592 Timer functions can be used to time operations (e.g. to see how much
11593 time has elapsed). First, you create a new timer with g_timer_new().
11594 You can then use g_timer_start() to start timing an operation,
11595 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
11596 determine the elapsed time.
11597
11598 <tscreen><verb>
11599 GTimer *g_timer_new( void );
11600
11601 void g_timer_destroy( GTimer *timer );
11602
11603 void g_timer_start( GTimer  *timer );
11604
11605 void g_timer_stop( GTimer  *timer );
11606
11607 void g_timer_reset( GTimer  *timer );
11608
11609 gdouble g_timer_elapsed( GTimer *timer,
11610                          gulong *microseconds );
11611 </verb></tscreen>                        
11612
11613 <!-- ----------------------------------------------------------------- -->
11614 <sect1>String Handling
11615 <p>
11616 glib defines a new type called a GString, which is similar to a
11617 standard C string but one that grows automatically. Its string data
11618 is null-terminated. What this gives you is protection from buffer
11619 overflow programming errors within your program. This is a very
11620 important feature, and hence I recommend that you make use of
11621 GStrings. GString itself has a simple public definition:
11622
11623 <tscreen><verb>
11624 struct GString 
11625 {
11626   gchar *str; /* Points to the string's current \0-terminated value. */
11627   gint len; /* Current length */
11628 };
11629 </verb></tscreen>
11630
11631 As you might expect, there are a number of operations you can do with
11632 a GString.
11633
11634 <tscreen><verb>
11635 GString *g_string_new( gchar *init );
11636 </verb></tscreen>
11637
11638 This constructs a GString, copying the string value of <tt/init/
11639 into the GString and returning a pointer to it. NULL may be given as
11640 the argument for an initially empty GString.
11641  
11642 <tscreen><verb>
11643
11644 void g_string_free( GString *string,
11645                     gint     free_segment );
11646 </verb></tscreen>
11647
11648 This frees the memory for the given GString. If <tt/free_segment/ is
11649 TRUE, then this also frees its character data.
11650
11651 <tscreen><verb>
11652                              
11653 GString *g_string_assign( GString     *lval,
11654                           const gchar *rval );
11655 </verb></tscreen>
11656
11657 This copies the characters from rval into lval, destroying the
11658 previous contents of lval. Note that lval will be lengthened as
11659 necessary to hold the string's contents, unlike the standard strcpy()
11660 function.
11661
11662 The rest of these functions should be relatively obvious (the _c
11663 versions accept a character instead of a string):
11664
11665 <tscreen><verb>              
11666 GString *g_string_truncate( GString *string,
11667                             gint     len );
11668                              
11669 GString *g_string_append( GString *string,
11670                           gchar   *val );
11671                             
11672 GString *g_string_append_c( GString *string,
11673                             gchar    c );
11674         
11675 GString *g_string_prepend( GString *string,
11676                            gchar   *val );
11677                              
11678 GString *g_string_prepend_c( GString *string,
11679                              gchar    c );
11680         
11681 void g_string_sprintf( GString *string,
11682                        gchar   *fmt,
11683                        ...);
11684         
11685 void g_string_sprintfa ( GString *string,
11686                          gchar   *fmt,
11687                          ... );
11688 </verb></tscreen>                                                         
11689
11690 <!-- ----------------------------------------------------------------- -->
11691 <sect1>Utility and Error Functions
11692 <p>
11693 <tscreen><verb>
11694 gchar *g_strdup( const gchar *str );
11695 </verb></tscreen>
11696
11697 Replacement strdup function.  Copies the original strings contents to
11698 newly allocated memory, and returns a pointer to it.
11699
11700 <tscreen><verb>
11701 gchar *g_strerror( gint errnum );
11702 </verb></tscreen>
11703
11704 I recommend using this for all error messages.  It's much nicer, and more
11705 portable than perror() or others.  The output is usually of the form:
11706
11707 <tscreen><verb>
11708 program name:function that failed:file or further description:strerror
11709 </verb></tscreen>
11710
11711 Here's an example of one such call used in our hello_world program:
11712
11713 <tscreen><verb>
11714 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
11715 </verb></tscreen>
11716
11717 <tscreen><verb>
11718 void g_error( gchar *format, ... );
11719 </verb></tscreen>
11720
11721 Prints an error message. The format is just like printf, but it
11722 prepends "** ERROR **: " to your message, and exits the program.  
11723 Use only for fatal errors.
11724
11725 <tscreen><verb>
11726 void g_warning( gchar *format, ... );
11727 </verb></tscreen>
11728
11729 Same as above, but prepends "** WARNING **: ", and does not exit the
11730 program.
11731
11732 <tscreen><verb>
11733 void g_message( gchar *format, ... );
11734 </verb></tscreen>
11735
11736 Prints "message: " prepended to the string you pass in.
11737
11738 <tscreen><verb>
11739 void g_print( gchar *format, ... );
11740 </verb></tscreen>
11741
11742 Replacement for printf().
11743
11744 And our last function:
11745
11746 <tscreen><verb>
11747 gchar *g_strsignal( gint signum );
11748 </verb></tscreen>
11749
11750 Prints out the name of the Unix system signal given the signal number.
11751 Useful in generic signal handling functions.
11752
11753 All of the above are more or less just stolen from glib.h.  If anyone cares
11754 to document any function, just send me an email!
11755
11756 <!-- ***************************************************************** -->
11757 <sect>GTK's rc Files
11758 <!-- ***************************************************************** -->
11759 <p>
11760 GTK has its own way of dealing with application defaults, by using rc
11761 files. These can be used to set the colors of just about any widget, and
11762 can also be used to tile pixmaps onto the background of some widgets.  
11763
11764 <!-- ----------------------------------------------------------------- -->
11765 <sect1>Functions For rc Files 
11766 <p>
11767 When your application starts, you should include a call to:
11768
11769 <tscreen><verb>
11770 void gtk_rc_parse( char *filename );
11771 </verb></tscreen>
11772
11773 Passing in the filename of your rc file. This will cause GTK to parse
11774 this file, and use the style settings for the widget types defined
11775 there.
11776
11777 If you wish to have a special set of widgets that can take on a
11778 different style from others, or any other logical division of widgets,
11779 use a call to:
11780
11781 <tscreen><verb>
11782 void gtk_widget_set_name( GtkWidget *widget,
11783                           gchar     *name );
11784 </verb></tscreen>
11785
11786 Passing your newly created widget as the first argument, and the name
11787 you wish to give it as the second. This will allow you to change the
11788 attributes of this widget by name through the rc file.
11789
11790 If we use a call something like this:
11791
11792 <tscreen><verb>
11793 button = gtk_button_new_with_label ("Special Button");
11794 gtk_widget_set_name (button, "special button");
11795 </verb></tscreen>
11796
11797 Then this button is given the name "special button" and may be addressed by
11798 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
11799
11800 The example rc file below, sets the properties of the main window, and lets
11801 all children of that main window inherit the style described by the "main
11802 button" style.  The code used in the application is:
11803
11804 <tscreen><verb>
11805 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11806 gtk_widget_set_name (window, "main window");
11807 </verb></tscreen>
11808
11809 And then the style is defined in the rc file using:
11810
11811 <tscreen><verb>
11812 widget "main window.*GtkButton*" style "main_button"
11813 </verb></tscreen>
11814
11815 Which sets all the GtkButton widgets in the "main window" to the
11816 "main_buttons" style as defined in the rc file.
11817
11818 As you can see, this is a fairly powerful and flexible system.  Use your
11819 imagination as to how best to take advantage of this.
11820
11821 <!-- ----------------------------------------------------------------- -->
11822 <sect1>GTK's rc File Format
11823 <p>
11824 The format of the GTK file is illustrated in the example below. This is
11825 the testgtkrc file from the GTK distribution, but I've added a
11826 few comments and things. You may wish to include this explanation
11827 your application to allow the user to fine tune his application.
11828
11829 There are several directives to change the attributes of a widget.
11830
11831 <itemize>
11832 <item>fg - Sets the foreground color of a widget.
11833 <item>bg - Sets the background color of a widget.
11834 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
11835 <item>font - Sets the font to be used with the given widget.
11836 </itemize>
11837
11838 In addition to this, there are several states a widget can be in, and you
11839 can set different colors, pixmaps and fonts for each state. These states are:
11840
11841 <itemize>
11842 <item>NORMAL - The normal state of a widget, without the mouse over top of
11843 it, and not being pressed etc.
11844 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
11845 using this state will be in effect.
11846 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
11847 the attributes assigned by this tag will be in effect.
11848 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
11849 activated, it will take these attributes.
11850 <item>SELECTED - When an object is selected, it takes these attributes.
11851 </itemize>
11852
11853 When using the "fg" and "bg" keywords to set the colors of widgets, the
11854 format is:
11855
11856 <tscreen><verb>
11857 fg[<STATE>] = { Red, Green, Blue }
11858 </verb></tscreen>
11859
11860 Where STATE is one of the above states (PRELIGHT, ACTIVE etc), and the Red,
11861 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
11862 white. They must be in float form, or they will register as 0, so a straight 
11863 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
11864 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
11865
11866 bg_pixmap is very similar to the above, except the colors are replaced by a
11867 filename.
11868
11869 pixmap_path is a list of paths separated by ":"'s.  These paths will be
11870 searched for any pixmap you specify.
11871
11872 The font directive is simply:
11873 <tscreen><verb>
11874 font = "<font name>"
11875 </verb></tscreen>
11876
11877 Where the only hard part is figuring out the font string. Using xfontsel or
11878 similar utility should help.
11879
11880 The "widget_class" sets the style of a class of widgets. These classes are
11881 listed in the widget overview on the class hierarchy.
11882
11883 The "widget" directive sets a specifically named set of widgets to a
11884 given style, overriding any style set for the given widget class.
11885 These widgets are registered inside the application using the
11886 gtk_widget_set_name() call. This allows you to specify the attributes of a
11887 widget on a per widget basis, rather than setting the attributes of an
11888 entire widget class. I urge you to document any of these special widgets so
11889 users may customize them.
11890
11891 When the keyword <tt>parent</> is used as an attribute, the widget will take on
11892 the attributes of its parent in the application.
11893
11894 When defining a style, you may assign the attributes of a previously defined
11895 style to this new one.
11896
11897 <tscreen><verb>
11898 style "main_button" = "button"
11899 {
11900   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11901   bg[PRELIGHT] = { 0.75, 0, 0 }
11902 }
11903 </verb></tscreen>
11904
11905 This example takes the "button" style, and creates a new "main_button" style
11906 simply by changing the font and prelight background color of the "button"
11907 style.
11908
11909 Of course, many of these attributes don't apply to all widgets. It's a
11910 simple matter of common sense really. Anything that could apply, should.
11911
11912 <!-- ----------------------------------------------------------------- -->
11913 <sect1>Example rc file
11914 <p>
11915
11916 <tscreen><verb>
11917 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
11918 #
11919 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
11920 #
11921 # style <name> [= <name>]
11922 # {
11923 #   <option>
11924 # }
11925 #
11926 # widget <widget_set> style <style_name>
11927 # widget_class <widget_class_set> style <style_name>
11928
11929
11930 # Here is a list of all the possible states.  Note that some do not apply to
11931 # certain widgets.
11932 #
11933 # NORMAL - The normal state of a widget, without the mouse over top of
11934 # it, and not being pressed etc.
11935 #
11936 # PRELIGHT - When the mouse is over top of the widget, colors defined
11937 # using this state will be in effect.
11938 #
11939 # ACTIVE - When the widget is pressed or clicked it will be active, and
11940 # the attributes assigned by this tag will be in effect.
11941 #
11942 # INSENSITIVE - When a widget is set insensitive, and cannot be
11943 # activated, it will take these attributes.
11944 #
11945 # SELECTED - When an object is selected, it takes these attributes.
11946 #
11947 # Given these states, we can set the attributes of the widgets in each of
11948 # these states using the following directives.
11949 #
11950 # fg - Sets the foreground color of a widget.
11951 # fg - Sets the background color of a widget.
11952 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
11953 # font - Sets the font to be used with the given widget.
11954 #
11955
11956 # This sets a style called "button".  The name is not really important, as
11957 # it is assigned to the actual widgets at the bottom of the file.
11958
11959 style "window"
11960 {
11961   #This sets the padding around the window to the pixmap specified.
11962   #bg_pixmap[<STATE>] = "<pixmap filename>"
11963   bg_pixmap[NORMAL] = "warning.xpm"
11964 }
11965
11966 style "scale"
11967 {
11968   #Sets the foreground color (font color) to red when in the "NORMAL"
11969   #state.
11970   
11971   fg[NORMAL] = { 1.0, 0, 0 }
11972   
11973   #Sets the background pixmap of this widget to that of its parent.
11974   bg_pixmap[NORMAL] = "<parent>"
11975 }
11976
11977 style "button"
11978 {
11979   # This shows all the possible states for a button.  The only one that
11980   # doesn't apply is the SELECTED state.
11981   
11982   fg[PRELIGHT] = { 0, 1.0, 1.0 }
11983   bg[PRELIGHT] = { 0, 0, 1.0 }
11984   bg[ACTIVE] = { 1.0, 0, 0 }
11985   fg[ACTIVE] = { 0, 1.0, 0 }
11986   bg[NORMAL] = { 1.0, 1.0, 0 }
11987   fg[NORMAL] = { .99, 0, .99 }
11988   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
11989   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
11990 }
11991
11992 # In this example, we inherit the attributes of the "button" style and then
11993 # override the font and background color when prelit to create a new
11994 # "main_button" style.
11995
11996 style "main_button" = "button"
11997 {
11998   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11999   bg[PRELIGHT] = { 0.75, 0, 0 }
12000 }
12001
12002 style "toggle_button" = "button"
12003 {
12004   fg[NORMAL] = { 1.0, 0, 0 }
12005   fg[ACTIVE] = { 1.0, 0, 0 }
12006   
12007   # This sets the background pixmap of the toggle_button to that of its
12008   # parent widget (as defined in the application).
12009   bg_pixmap[NORMAL] = "<parent>"
12010 }
12011
12012 style "text"
12013 {
12014   bg_pixmap[NORMAL] = "marble.xpm"
12015   fg[NORMAL] = { 1.0, 1.0, 1.0 }
12016 }
12017
12018 style "ruler"
12019 {
12020   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
12021 }
12022
12023 # pixmap_path "~/.pixmaps"
12024
12025 # These set the widget types to use the styles defined above.
12026 # The widget types are listed in the class hierarchy, but could probably be
12027 # just listed in this document for the users reference.
12028
12029 widget_class "GtkWindow" style "window"
12030 widget_class "GtkDialog" style "window"
12031 widget_class "GtkFileSelection" style "window"
12032 widget_class "*Gtk*Scale" style "scale"
12033 widget_class "*GtkCheckButton*" style "toggle_button"
12034 widget_class "*GtkRadioButton*" style "toggle_button"
12035 widget_class "*GtkButton*" style "button"
12036 widget_class "*Ruler" style "ruler"
12037 widget_class "*GtkText" style "text"
12038
12039 # This sets all the buttons that are children of the "main window" to
12040 # the main_button style.  These must be documented to be taken advantage of.
12041 widget "main window.*GtkButton*" style "main_button"
12042 </verb></tscreen>
12043
12044 <!-- ***************************************************************** -->
12045 <sect>Writing Your Own Widgets 
12046 <!-- ***************************************************************** -->
12047
12048 <!-- ----------------------------------------------------------------- -->
12049 <sect1> Overview
12050 <p>
12051 Although the GTK distribution comes with many types of widgets that
12052 should cover most basic needs, there may come a time when you need to
12053 create your own new widget type. Since GTK uses widget inheritance
12054 extensively, and there is already a widget that is close to what you want,
12055 it is often possible to make a useful new widget type in
12056 just a few lines of code. But before starting work on a new widget, check
12057 around first to make sure that someone has not already written
12058 it. This will prevent duplication of effort and keep the number of
12059 GTK widgets out there to a minimum, which will help keep both the code
12060 and the interface of different applications consistent. As a flip side
12061 to this, once you finish your widget, announce it to the world so
12062 other people can benefit. The best place to do this is probably the
12063 <tt>gtk-list</tt>.
12064
12065 Complete sources for the example widgets are available at the place you 
12066 got this tutorial, or from:
12067
12068 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12069 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12070
12071
12072 <!-- ----------------------------------------------------------------- -->
12073 <sect1> The Anatomy Of A Widget
12074 <p>
12075 In order to create a new widget, it is important to have an
12076 understanding of how GTK objects work. This section is just meant as a
12077 brief overview. See the reference documentation for the details. 
12078
12079 GTK widgets are implemented in an object oriented fashion. However,
12080 they are implemented in standard C. This greatly improves portability
12081 and stability over using current generation C++ compilers; however,
12082 it does mean that the widget writer has to pay attention to some of
12083 the implementation details. The information common to all instances of
12084 one class of widgets (e.g., to all Button widgets) is stored in the 
12085 <em>class structure</em>. There is only one copy of this in
12086 which is stored information about the class's signals
12087 (which act like virtual functions in C). To support inheritance, the
12088 first field in the class structure must be a copy of the parent's
12089 class structure. The declaration of the class structure of GtkButtton
12090 looks like:
12091
12092 <tscreen><verb>
12093 struct _GtkButtonClass
12094 {
12095   GtkContainerClass parent_class;
12096
12097   void (* pressed)  (GtkButton *button);
12098   void (* released) (GtkButton *button);
12099   void (* clicked)  (GtkButton *button);
12100   void (* enter)    (GtkButton *button);
12101   void (* leave)    (GtkButton *button);
12102 };
12103 </verb></tscreen>
12104
12105 When a button is treated as a container (for instance, when it is
12106 resized), its class structure can be cast to GtkContainerClass, and
12107 the relevant fields used to handle the signals.
12108
12109 There is also a structure for each widget that is created on a
12110 per-instance basis. This structure has fields to store information that
12111 is different for each instance of the widget. We'll call this
12112 structure the <em>object structure</em>. For the Button class, it looks
12113 like:
12114
12115 <tscreen><verb>
12116 struct _GtkButton
12117 {
12118   GtkContainer container;
12119
12120   GtkWidget *child;
12121
12122   guint in_button : 1;
12123   guint button_down : 1;
12124 };
12125 </verb></tscreen>
12126
12127 Note that, similar to the class structure, the first field is the
12128 object structure of the parent class, so that this structure can be
12129 cast to the parent class's object structure as needed.
12130
12131 <!-- ----------------------------------------------------------------- -->
12132 <sect1> Creating a Composite widget
12133
12134 <!-- ----------------------------------------------------------------- -->
12135 <sect2> Introduction
12136 <p>
12137 One type of widget that you may be interested in creating is a
12138 widget that is merely an aggregate of other GTK widgets. This type of
12139 widget does nothing that couldn't be done without creating new
12140 widgets, but provides a convenient way of packaging user interface
12141 elements for reuse. The FileSelection and ColorSelection widgets in
12142 the standard distribution are examples of this type of widget.
12143
12144 The example widget that we'll create in this section is the Tictactoe
12145 widget, a 3x3 array of toggle buttons which triggers a signal when all
12146 three buttons in a row, column, or on one of the diagonals are
12147 depressed. 
12148
12149 <!-- ----------------------------------------------------------------- -->
12150 <sect2> Choosing a parent class
12151 <p>
12152 The parent class for a composite widget is typically the container
12153 class that holds all of the elements of the composite widget. For
12154 example, the parent class of the FileSelection widget is the
12155 Dialog class. Since our buttons will be arranged in a table, it
12156 might seem natural to make our parent class the GtkTable
12157 class. Unfortunately, this turns out not to work. The creation of a
12158 widget is divided among two functions - a <tt/WIDGETNAME_new()/
12159 function that the user calls, and a <tt/WIDGETNAME_init()/ function
12160 which does the basic work of initializing the widget which is
12161 independent of the arguments passed to the <tt/_new()/
12162 function. Descendent widgets only call the <tt/_init/ function of
12163 their parent widget. But this division of labor doesn't work well for
12164 tables, which when created, need to know the number of rows and
12165 columns in the table. Unless we want to duplicate most of the
12166 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
12167 best avoid deriving it from GtkTable. For that reason, we derive it
12168 from GtkVBox instead, and stick our table inside the VBox.
12169
12170 <!-- ----------------------------------------------------------------- -->
12171 <sect2> The header file
12172 <p>
12173 Each widget class has a header file which declares the object and
12174 class structures for that widget, along with public functions. 
12175 A couple of features are worth pointing out. To prevent duplicate
12176 definitions, we wrap the entire header file in:
12177
12178 <tscreen><verb>
12179 #ifndef __TICTACTOE_H__
12180 #define __TICTACTOE_H__
12181 .
12182 .
12183 .
12184 #endif /* __TICTACTOE_H__ */
12185 </verb></tscreen>
12186
12187 And to keep C++ programs that include the header file happy, in:
12188
12189 <tscreen><verb>
12190 #ifdef __cplusplus
12191 extern "C" {
12192 #endif /* __cplusplus */
12193 .
12194 .
12195 .
12196 #ifdef __cplusplus
12197 }
12198 #endif /* __cplusplus */
12199 </verb></tscreen>
12200
12201 Along with the functions and structures, we declare three standard
12202 macros in our header file, <tt/TICTACTOE(obj)/,
12203 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
12204 pointer into a pointer to the object or class structure, and check
12205 if an object is a Tictactoe widget respectively.
12206
12207 Here is the complete header file:
12208
12209 <tscreen><verb>
12210 /* tictactoe.h */
12211
12212 #ifndef __TICTACTOE_H__
12213 #define __TICTACTOE_H__
12214
12215 #include <gdk/gdk.h>
12216 #include <gtk/gtkvbox.h>
12217
12218 #ifdef __cplusplus
12219 extern "C" {
12220 #endif /* __cplusplus */
12221
12222 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
12223 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
12224 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
12225
12226
12227 typedef struct _Tictactoe       Tictactoe;
12228 typedef struct _TictactoeClass  TictactoeClass;
12229
12230 struct _Tictactoe
12231 {
12232   GtkVBox vbox;
12233   
12234   GtkWidget *buttons[3][3];
12235 };
12236
12237 struct _TictactoeClass
12238 {
12239   GtkVBoxClass parent_class;
12240
12241   void (* tictactoe) (Tictactoe *ttt);
12242 };
12243
12244 guint          tictactoe_get_type        (void);
12245 GtkWidget*     tictactoe_new             (void);
12246 void           tictactoe_clear           (Tictactoe *ttt);
12247
12248 #ifdef __cplusplus
12249 }
12250 #endif /* __cplusplus */
12251
12252 #endif /* __TICTACTOE_H__ */
12253
12254 </verb></tscreen>
12255
12256 <!-- ----------------------------------------------------------------- -->
12257 <sect2> The <tt/_get_type()/ function.
12258 <p>
12259 We now continue on to the implementation of our widget. A core
12260 function for every widget is the function
12261 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
12262 GTK about the widget class, and gets an ID that uniquely identifies
12263 the widget class. Upon subsequent calls, it just returns the ID.
12264
12265 <tscreen><verb>
12266 guint
12267 tictactoe_get_type ()
12268 {
12269   static guint ttt_type = 0;
12270
12271   if (!ttt_type)
12272     {
12273       GtkTypeInfo ttt_info =
12274       {
12275         "Tictactoe",
12276         sizeof (Tictactoe),
12277         sizeof (TictactoeClass),
12278         (GtkClassInitFunc) tictactoe_class_init,
12279         (GtkObjectInitFunc) tictactoe_init,
12280         (GtkArgSetFunc) NULL,
12281         (GtkArgGetFunc) NULL
12282       };
12283
12284       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
12285     }
12286
12287   return ttt_type;
12288 }
12289 </verb></tscreen>
12290
12291 The GtkTypeInfo structure has the following definition:
12292
12293 <tscreen><verb>
12294 struct _GtkTypeInfo
12295 {
12296   gchar *type_name;
12297   guint object_size;
12298   guint class_size;
12299   GtkClassInitFunc class_init_func;
12300   GtkObjectInitFunc object_init_func;
12301   GtkArgSetFunc arg_set_func;
12302   GtkArgGetFunc arg_get_func;
12303 };
12304 </verb></tscreen>
12305
12306 The fields of this structure are pretty self-explanatory. We'll ignore
12307 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
12308 but as yet largely
12309 unimplemented, role in allowing widget options to be conveniently set
12310 from interpreted languages. Once GTK has a correctly filled in copy of
12311 this structure, it knows how to create objects of a particular widget
12312 type. 
12313
12314 <!-- ----------------------------------------------------------------- -->
12315 <sect2> The <tt/_class_init()/ function
12316 <p>
12317 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
12318 the widget's class structure, and sets up any signals for the
12319 class. For our Tictactoe widget it looks like:
12320
12321 <tscreen><verb>
12322
12323 enum {
12324   TICTACTOE_SIGNAL,
12325   LAST_SIGNAL
12326 };
12327
12328 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
12329
12330 static void
12331 tictactoe_class_init (TictactoeClass *class)
12332 {
12333   GtkObjectClass *object_class;
12334
12335   object_class = (GtkObjectClass*) class;
12336   
12337   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
12338                                          GTK_RUN_FIRST,
12339                                          object_class->type,
12340                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
12341                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
12342
12343
12344   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
12345
12346   class->tictactoe = NULL;
12347 }
12348 </verb></tscreen>
12349
12350 Our widget has just one signal, the <tt/tictactoe/ signal that is
12351 invoked when a row, column, or diagonal is completely filled in. Not
12352 every composite widget needs signals, so if you are reading this for
12353 the first time, you may want to skip to the next section now, as
12354 things are going to get a bit complicated.
12355
12356 The function:
12357
12358 <tscreen><verb>
12359 gint gtk_signal_new( const gchar         *name,
12360                      GtkSignalRunType     run_type,
12361                      GtkType              object_type,
12362                      gint                 function_offset,
12363                      GtkSignalMarshaller  marshaller,
12364                      GtkType              return_val,
12365                      guint                nparams,
12366                      ...);
12367 </verb></tscreen>
12368
12369 Creates a new signal. The parameters are:
12370
12371 <itemize>
12372 <item> <tt/name/: The name of the signal.
12373 <item> <tt/run_type/: Whether the default handler runs before or after
12374 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
12375 although there are other possibilities.
12376 <item> <tt/object_type/: The ID of the object that this signal applies
12377 to. (It will also apply to that objects descendents)
12378 <item> <tt/function_offset/: The offset within the class structure of
12379 a pointer to the default handler.
12380 <item> <tt/marshaller/: A function that is used to invoke the signal
12381 handler. For signal handlers that have no arguments other than the
12382 object that emitted the signal and user data, we can use the
12383 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
12384 <item> <tt/return_val/: The type of the return val.
12385 <item> <tt/nparams/: The number of parameters of the signal handler
12386 (other than the two default ones mentioned above)
12387 <item> <tt/.../: The types of the parameters.
12388 </itemize>
12389
12390 When specifying types, the <tt/GtkType/ enumeration is used:
12391
12392 <tscreen><verb>
12393 typedef enum
12394 {
12395   GTK_TYPE_INVALID,
12396   GTK_TYPE_NONE,
12397   GTK_TYPE_CHAR,
12398   GTK_TYPE_BOOL,
12399   GTK_TYPE_INT,
12400   GTK_TYPE_UINT,
12401   GTK_TYPE_LONG,
12402   GTK_TYPE_ULONG,
12403   GTK_TYPE_FLOAT,
12404   GTK_TYPE_DOUBLE,
12405   GTK_TYPE_STRING,
12406   GTK_TYPE_ENUM,
12407   GTK_TYPE_FLAGS,
12408   GTK_TYPE_BOXED,
12409   GTK_TYPE_FOREIGN,
12410   GTK_TYPE_CALLBACK,
12411   GTK_TYPE_ARGS,
12412
12413   GTK_TYPE_POINTER,
12414
12415   /* it'd be great if the next two could be removed eventually */
12416   GTK_TYPE_SIGNAL,
12417   GTK_TYPE_C_CALLBACK,
12418
12419   GTK_TYPE_OBJECT
12420
12421 } GtkFundamentalType;
12422 </verb></tscreen>
12423
12424 <tt/gtk_signal_new()/ returns a unique integer identifier for the
12425 signal, that we store in the <tt/tictactoe_signals/ array, which we
12426 index using an enumeration. (Conventionally, the enumeration elements
12427 are the signal name, uppercased, but here there would be a conflict
12428 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
12429 instead.
12430
12431 After creating our signals, we need to tell GTK to associate our
12432 signals with the Tictactoe class. We do that by calling
12433 <tt/gtk_object_class_add_signals()/. We then set the pointer which
12434 points to the default handler for the `tictactoe' signal to NULL,
12435 indicating that there is no default action.
12436
12437 <!-- ----------------------------------------------------------------- -->
12438 <sect2> The <tt/_init()/ function.
12439 <p>
12440 Each widget class also needs a function to initialize the object
12441 structure. Usually, this function has the fairly limited role of
12442 setting the fields of the structure to default values. For composite
12443 widgets, however, this function also creates the component widgets.
12444
12445 <tscreen><verb>
12446 static void
12447 tictactoe_init (Tictactoe *ttt)
12448 {
12449   GtkWidget *table;
12450   gint i,j;
12451   
12452   table = gtk_table_new (3, 3, TRUE);
12453   gtk_container_add (GTK_CONTAINER(ttt), table);
12454   gtk_widget_show (table);
12455
12456   for (i=0;i<3; i++)
12457     for (j=0;j<3; j++)
12458       {
12459         ttt->buttons[i][j] = gtk_toggle_button_new ();
12460         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
12461                                    i, i+1, j, j+1);
12462         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
12463                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
12464         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
12465         gtk_widget_show (ttt->buttons[i][j]);
12466       }
12467 }
12468 </verb></tscreen>
12469
12470 <!-- ----------------------------------------------------------------- -->
12471 <sect2> And the rest...
12472 <p>
12473 There is one more function that every widget (except for base widget
12474 types like GtkBin that cannot be instantiated) needs to have - the
12475 function that the user calls to create an object of that type. This is
12476 conventionally called <tt/WIDGETNAME_new()/. In some
12477 widgets, though not for the Tictactoe widgets, this function takes
12478 arguments, and does some setup based on the arguments. The other two
12479 functions are specific to the Tictactoe widget. 
12480
12481 <tt/tictactoe_clear()/ is a public function that resets all the
12482 buttons in the widget to the up position. Note the use of
12483 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
12484 button toggles from being triggered unnecessarily.
12485
12486 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
12487 user clicks on a button. It checks to see if there are any winning
12488 combinations that involve the toggled button, and if so, emits
12489 the "tictactoe" signal.
12490
12491 <tscreen><verb>  
12492 GtkWidget*
12493 tictactoe_new ()
12494 {
12495   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
12496 }
12497
12498 void           
12499 tictactoe_clear (Tictactoe *ttt)
12500 {
12501   int i,j;
12502
12503   for (i=0;i<3;i++)
12504     for (j=0;j<3;j++)
12505       {
12506         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12507         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
12508                                      FALSE);
12509         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12510       }
12511 }
12512
12513 static void
12514 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
12515 {
12516   int i,k;
12517
12518   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12519                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12520                              { 0, 1, 2 }, { 0, 1, 2 } };
12521   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12522                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12523                              { 0, 1, 2 }, { 2, 1, 0 } };
12524
12525   int success, found;
12526
12527   for (k=0; k<8; k++)
12528     {
12529       success = TRUE;
12530       found = FALSE;
12531
12532       for (i=0;i<3;i++)
12533         {
12534           success = success &amp;&amp; 
12535             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
12536           found = found ||
12537             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
12538         }
12539       
12540       if (success &amp;&amp; found)
12541         {
12542           gtk_signal_emit (GTK_OBJECT (ttt), 
12543                            tictactoe_signals[TICTACTOE_SIGNAL]);
12544           break;
12545         }
12546     }
12547 }
12548 </verb></tscreen>
12549
12550 And finally, an example program using our Tictactoe widget:
12551
12552 <tscreen><verb>
12553 #include <gtk/gtk.h>
12554 #include "tictactoe.h"
12555
12556 /* Invoked when a row, column or diagonal is completed */
12557 void
12558 win (GtkWidget *widget, gpointer data)
12559 {
12560   g_print ("Yay!\n");
12561   tictactoe_clear (TICTACTOE (widget));
12562 }
12563
12564 int 
12565 main (int argc, char *argv[])
12566 {
12567   GtkWidget *window;
12568   GtkWidget *ttt;
12569   
12570   gtk_init (&amp;argc, &amp;argv);
12571
12572   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12573   
12574   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
12575   
12576   gtk_signal_connect (GTK_OBJECT (window), "destroy",
12577                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
12578   
12579   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12580
12581   /* Create a new Tictactoe widget */
12582   ttt = tictactoe_new ();
12583   gtk_container_add (GTK_CONTAINER (window), ttt);
12584   gtk_widget_show (ttt);
12585
12586   /* And attach to its "tictactoe" signal */
12587   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
12588                       GTK_SIGNAL_FUNC (win), NULL);
12589
12590   gtk_widget_show (window);
12591   
12592   gtk_main ();
12593   
12594   return 0;
12595 }
12596
12597 </verb></tscreen>
12598
12599 <!-- ----------------------------------------------------------------- -->
12600 <sect1> Creating a widget from scratch.
12601
12602 <!-- ----------------------------------------------------------------- -->
12603 <sect2> Introduction
12604 <p>
12605 In this section, we'll learn more about how widgets display themselves
12606 on the screen and interact with events. As an example of this, we'll
12607 create an analog dial widget with a pointer that the user can drag to
12608 set the value.
12609
12610 <!-- ----------------------------------------------------------------- -->
12611 <sect2> Displaying a widget on the screen
12612 <p>
12613 There are several steps that are involved in displaying on the screen.
12614 After the widget is created with a call to <tt/WIDGETNAME_new()/,
12615 several more functions are needed:
12616
12617 <itemize>
12618 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
12619 window for the widget if it has one.
12620 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
12621 <tt/gtk_widget_show()/. It is responsible for making sure the widget
12622 is actually drawn on the screen (<em/mapped/). For a container class,
12623 it must also make calls to <tt/map()/> functions of any child widgets.
12624 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
12625 is called for the widget or one of its ancestors. It makes the actual
12626 calls to the drawing functions to draw the widget on the screen. For
12627 container widgets, this function must make calls to
12628 <tt/gtk_widget_draw()/ for its child widgets.
12629 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
12630 widget. It makes the necessary calls to the drawing functions to draw
12631 the exposed portion on the screen. For container widgets, this
12632 function must generate expose events for its child widgets which don't
12633 have their own windows. (If they have their own windows, then X will
12634 generate the necessary expose events)
12635 </itemize>
12636
12637 You might notice that the last two functions are quite similar - each
12638 is responsible for drawing the widget on the screen. In fact many
12639 types of widgets don't really care about the difference between the
12640 two. The default <tt/draw()/ function in the widget class simply
12641 generates a synthetic expose event for the redrawn area. However, some
12642 types of widgets can save work by distinguishing between the two
12643 functions. For instance, if a widget has multiple X windows, then
12644 since expose events identify the exposed window, it can redraw only
12645 the affected window, which is not possible for calls to <tt/draw()/.
12646
12647 Container widgets, even if they don't care about the difference for
12648 themselves, can't simply use the default <tt/draw()/ function because
12649 their child widgets might care about the difference. However,
12650 it would be wasteful to duplicate the drawing code between the two
12651 functions. The convention is that such widgets have a function called
12652 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
12653 widget, that is then called by the <tt/draw()/ and <tt/expose()/
12654 functions.
12655
12656 In our example approach, since the dial widget is not a container
12657 widget, and only has a single window, we can take the simplest
12658 approach and use the default <tt/draw()/ function and only implement
12659 an <tt/expose()/ function.
12660
12661 <!-- ----------------------------------------------------------------- -->
12662 <sect2> The origins of the Dial Widget
12663 <p>
12664 Just as all land animals are just variants on the first amphibian that
12665 crawled up out of the mud, Gtk widgets tend to start off as variants
12666 of some other, previously written widget.  Thus, although this section
12667 is entitled `Creating a Widget from Scratch', the Dial widget really
12668 began with the source code for the Range widget. This was picked as a
12669 starting point because it would be nice if our Dial had the same
12670 interface as the Scale widgets which are just specialized descendents
12671 of the Range widget. So, though the source code is presented below in
12672 finished form, it should not be implied that it was written, <em>deus
12673 ex machina</em> in this fashion. Also, if you aren't yet familiar with
12674 how scale widgets work from the application writer's point of view, it
12675 would be a good idea to look them over before continuing.
12676
12677 <!-- ----------------------------------------------------------------- -->
12678 <sect2> The Basics
12679 <p>
12680 Quite a bit of our widget should look pretty familiar from the
12681 Tictactoe widget. First, we have a header file:
12682
12683 <tscreen><verb>
12684 /* GTK - The GIMP Toolkit
12685  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
12686  *
12687  * This library is free software; you can redistribute it and/or
12688  * modify it under the terms of the GNU Library General Public
12689  * License as published by the Free Software Foundation; either
12690  * version 2 of the License, or (at your option) any later version.
12691  *
12692  * This library is distributed in the hope that it will be useful,
12693  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12694  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12695  * Library General Public License for more details.
12696  *
12697  * You should have received a copy of the GNU Library General Public
12698  * License along with this library; if not, write to the Free
12699  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12700  */
12701
12702 #ifndef __GTK_DIAL_H__
12703 #define __GTK_DIAL_H__
12704
12705 #include <gdk/gdk.h>
12706 #include <gtk/gtkadjustment.h>
12707 #include <gtk/gtkwidget.h>
12708
12709
12710 #ifdef __cplusplus
12711 extern "C" {
12712 #endif /* __cplusplus */
12713
12714
12715 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
12716 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
12717 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
12718
12719
12720 typedef struct _GtkDial        GtkDial;
12721 typedef struct _GtkDialClass   GtkDialClass;
12722
12723 struct _GtkDial
12724 {
12725   GtkWidget widget;
12726
12727   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
12728   guint policy : 2;
12729
12730   /* Button currently pressed or 0 if none */
12731   guint8 button;
12732
12733   /* Dimensions of dial components */
12734   gint radius;
12735   gint pointer_width;
12736
12737   /* ID of update timer, or 0 if none */
12738   guint32 timer;
12739
12740   /* Current angle */
12741   gfloat angle;
12742
12743   /* Old values from adjustment stored so we know when something changes */
12744   gfloat old_value;
12745   gfloat old_lower;
12746   gfloat old_upper;
12747
12748   /* The adjustment object that stores the data for this dial */
12749   GtkAdjustment *adjustment;
12750 };
12751
12752 struct _GtkDialClass
12753 {
12754   GtkWidgetClass parent_class;
12755 };
12756
12757
12758 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
12759 guint          gtk_dial_get_type               (void);
12760 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
12761 void           gtk_dial_set_update_policy      (GtkDial      *dial,
12762                                                 GtkUpdateType  policy);
12763
12764 void           gtk_dial_set_adjustment         (GtkDial      *dial,
12765                                                 GtkAdjustment *adjustment);
12766 #ifdef __cplusplus
12767 }
12768 #endif /* __cplusplus */
12769
12770
12771 #endif /* __GTK_DIAL_H__ */
12772 </verb></tscreen>
12773
12774 Since there is quite a bit more going on in this widget, than the last
12775 one, we have more fields in the data structure, but otherwise things
12776 are pretty similar.
12777
12778 Next, after including header files, and declaring a few constants,
12779 we have some functions to provide information about the widget
12780 and initialize it:
12781
12782 <tscreen><verb>
12783 #include <math.h>
12784 #include <stdio.h>
12785 #include <gtk/gtkmain.h>
12786 #include <gtk/gtksignal.h>
12787
12788 #include "gtkdial.h"
12789
12790 #define SCROLL_DELAY_LENGTH  300
12791 #define DIAL_DEFAULT_SIZE 100
12792
12793 /* Forward declarations */
12794
12795 [ omitted to save space ]
12796
12797 /* Local data */
12798
12799 static GtkWidgetClass *parent_class = NULL;
12800
12801 guint
12802 gtk_dial_get_type ()
12803 {
12804   static guint dial_type = 0;
12805
12806   if (!dial_type)
12807     {
12808       GtkTypeInfo dial_info =
12809       {
12810         "GtkDial",
12811         sizeof (GtkDial),
12812         sizeof (GtkDialClass),
12813         (GtkClassInitFunc) gtk_dial_class_init,
12814         (GtkObjectInitFunc) gtk_dial_init,
12815         (GtkArgSetFunc) NULL,
12816         (GtkArgGetFunc) NULL,
12817       };
12818
12819       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
12820     }
12821
12822   return dial_type;
12823 }
12824
12825 static void
12826 gtk_dial_class_init (GtkDialClass *class)
12827 {
12828   GtkObjectClass *object_class;
12829   GtkWidgetClass *widget_class;
12830
12831   object_class = (GtkObjectClass*) class;
12832   widget_class = (GtkWidgetClass*) class;
12833
12834   parent_class = gtk_type_class (gtk_widget_get_type ());
12835
12836   object_class->destroy = gtk_dial_destroy;
12837
12838   widget_class->realize = gtk_dial_realize;
12839   widget_class->expose_event = gtk_dial_expose;
12840   widget_class->size_request = gtk_dial_size_request;
12841   widget_class->size_allocate = gtk_dial_size_allocate;
12842   widget_class->button_press_event = gtk_dial_button_press;
12843   widget_class->button_release_event = gtk_dial_button_release;
12844   widget_class->motion_notify_event = gtk_dial_motion_notify;
12845 }
12846
12847 static void
12848 gtk_dial_init (GtkDial *dial)
12849 {
12850   dial->button = 0;
12851   dial->policy = GTK_UPDATE_CONTINUOUS;
12852   dial->timer = 0;
12853   dial->radius = 0;
12854   dial->pointer_width = 0;
12855   dial->angle = 0.0;
12856   dial->old_value = 0.0;
12857   dial->old_lower = 0.0;
12858   dial->old_upper = 0.0;
12859   dial->adjustment = NULL;
12860 }
12861
12862 GtkWidget*
12863 gtk_dial_new (GtkAdjustment *adjustment)
12864 {
12865   GtkDial *dial;
12866
12867   dial = gtk_type_new (gtk_dial_get_type ());
12868
12869   if (!adjustment)
12870     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
12871
12872   gtk_dial_set_adjustment (dial, adjustment);
12873
12874   return GTK_WIDGET (dial);
12875 }
12876
12877 static void
12878 gtk_dial_destroy (GtkObject *object)
12879 {
12880   GtkDial *dial;
12881
12882   g_return_if_fail (object != NULL);
12883   g_return_if_fail (GTK_IS_DIAL (object));
12884
12885   dial = GTK_DIAL (object);
12886
12887   if (dial->adjustment)
12888     gtk_object_unref (GTK_OBJECT (dial->adjustment));
12889
12890   if (GTK_OBJECT_CLASS (parent_class)->destroy)
12891     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
12892 }
12893 </verb></tscreen>
12894
12895 Note that this <tt/init()/ function does less than for the Tictactoe
12896 widget, since this is not a composite widget, and the <tt/new()/
12897 function does more, since it now has an argument. Also, note that when
12898 we store a pointer to the Adjustment object, we increment its
12899 reference count, (and correspondingly decrement when we no longer use
12900 it) so that GTK can keep track of when it can be safely destroyed.
12901
12902 <p>
12903 Also, there are a few function to manipulate the widget's options:
12904
12905 <tscreen><verb>
12906 GtkAdjustment*
12907 gtk_dial_get_adjustment (GtkDial *dial)
12908 {
12909   g_return_val_if_fail (dial != NULL, NULL);
12910   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
12911
12912   return dial->adjustment;
12913 }
12914
12915 void
12916 gtk_dial_set_update_policy (GtkDial      *dial,
12917                              GtkUpdateType  policy)
12918 {
12919   g_return_if_fail (dial != NULL);
12920   g_return_if_fail (GTK_IS_DIAL (dial));
12921
12922   dial->policy = policy;
12923 }
12924
12925 void
12926 gtk_dial_set_adjustment (GtkDial      *dial,
12927                           GtkAdjustment *adjustment)
12928 {
12929   g_return_if_fail (dial != NULL);
12930   g_return_if_fail (GTK_IS_DIAL (dial));
12931
12932   if (dial->adjustment)
12933     {
12934       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
12935       gtk_object_unref (GTK_OBJECT (dial->adjustment));
12936     }
12937
12938   dial->adjustment = adjustment;
12939   gtk_object_ref (GTK_OBJECT (dial->adjustment));
12940
12941   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
12942                       (GtkSignalFunc) gtk_dial_adjustment_changed,
12943                       (gpointer) dial);
12944   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
12945                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
12946                       (gpointer) dial);
12947
12948   dial->old_value = adjustment->value;
12949   dial->old_lower = adjustment->lower;
12950   dial->old_upper = adjustment->upper;
12951
12952   gtk_dial_update (dial);
12953 }
12954 </verb></tscreen>
12955
12956 <sect2> <tt/gtk_dial_realize()/
12957
12958 <p>
12959 Now we come to some new types of functions. First, we have a function
12960 that does the work of creating the X window. Notice that a mask is
12961 passed to the function <tt/gdk_window_new()/ which specifies which fields of
12962 the GdkWindowAttr structure actually have data in them (the remaining
12963 fields will be given default values). Also worth noting is the way the
12964 event mask of the widget is created. We call
12965 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
12966 has specified for this widget (with <tt/gtk_widget_set_events()/, and
12967 add the events that we are interested in ourselves.
12968
12969 <p>
12970 After creating the window, we set its style and background, and put a
12971 pointer to the widget in the user data field of the GdkWindow. This
12972 last step allows GTK to dispatch events for this window to the correct
12973 widget.
12974
12975 <tscreen><verb>
12976 static void
12977 gtk_dial_realize (GtkWidget *widget)
12978 {
12979   GtkDial *dial;
12980   GdkWindowAttr attributes;
12981   gint attributes_mask;
12982
12983   g_return_if_fail (widget != NULL);
12984   g_return_if_fail (GTK_IS_DIAL (widget));
12985
12986   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
12987   dial = GTK_DIAL (widget);
12988
12989   attributes.x = widget->allocation.x;
12990   attributes.y = widget->allocation.y;
12991   attributes.width = widget->allocation.width;
12992   attributes.height = widget->allocation.height;
12993   attributes.wclass = GDK_INPUT_OUTPUT;
12994   attributes.window_type = GDK_WINDOW_CHILD;
12995   attributes.event_mask = gtk_widget_get_events (widget) | 
12996     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
12997     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
12998     GDK_POINTER_MOTION_HINT_MASK;
12999   attributes.visual = gtk_widget_get_visual (widget);
13000   attributes.colormap = gtk_widget_get_colormap (widget);
13001
13002   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
13003   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
13004
13005   widget->style = gtk_style_attach (widget->style, widget->window);
13006
13007   gdk_window_set_user_data (widget->window, widget);
13008
13009   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
13010 }
13011 </verb></tscreen>
13012
13013 <sect2> Size negotiation
13014
13015 <p>
13016 Before the first time that the window containing a widget is
13017 displayed, and whenever the layout of the window changes, GTK asks
13018 each child widget for its desired size. This request is handled by the
13019 function, <tt/gtk_dial_size_request()/. Since our widget isn't a
13020 container widget, and has no real constraints on its size, we just
13021 return a reasonable default value.
13022
13023 <tscreen><verb>
13024 static void 
13025 gtk_dial_size_request (GtkWidget      *widget,
13026                        GtkRequisition *requisition)
13027 {
13028   requisition->width = DIAL_DEFAULT_SIZE;
13029   requisition->height = DIAL_DEFAULT_SIZE;
13030 }
13031 </verb></tscreen>
13032
13033 <p>
13034 After all the widgets have requested an ideal size, the layout of the
13035 window is computed and each child widget is notified of its actual
13036 size. Usually, this will at least as large as the requested size, but
13037 if for instance, the user has resized the window, it may occasionally
13038 be smaller than the requested size. The size notification is handled
13039 by the function <tt/gtk_dial_size_allocate()/. Notice that as well as
13040 computing the sizes of some component pieces for future use, this
13041 routine also does the grunt work of moving the widgets X window into
13042 the new position and size.
13043
13044 <tscreen><verb>
13045 static void
13046 gtk_dial_size_allocate (GtkWidget     *widget,
13047                         GtkAllocation *allocation)
13048 {
13049   GtkDial *dial;
13050
13051   g_return_if_fail (widget != NULL);
13052   g_return_if_fail (GTK_IS_DIAL (widget));
13053   g_return_if_fail (allocation != NULL);
13054
13055   widget->allocation = *allocation;
13056   if (GTK_WIDGET_REALIZED (widget))
13057     {
13058       dial = GTK_DIAL (widget);
13059
13060       gdk_window_move_resize (widget->window,
13061                               allocation->x, allocation->y,
13062                               allocation->width, allocation->height);
13063
13064       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
13065       dial->pointer_width = dial->radius / 5;
13066     }
13067 }
13068 </verb></tscreen>.
13069
13070 <!-- ----------------------------------------------------------------- -->
13071 <sect2> <tt/gtk_dial_expose()/
13072
13073 <p>
13074 As mentioned above, all the drawing of this widget is done in the
13075 handler for expose events. There's not much to remark on here except
13076 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
13077 three dimensional shading according to the colors stored in the
13078 widget's style.
13079
13080 <tscreen><verb>
13081 static gint
13082 gtk_dial_expose (GtkWidget      *widget,
13083                  GdkEventExpose *event)
13084 {
13085   GtkDial *dial;
13086   GdkPoint points[3];
13087   gdouble s,c;
13088   gdouble theta;
13089   gint xc, yc;
13090   gint tick_length;
13091   gint i;
13092
13093   g_return_val_if_fail (widget != NULL, FALSE);
13094   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13095   g_return_val_if_fail (event != NULL, FALSE);
13096
13097   if (event->count > 0)
13098     return FALSE;
13099   
13100   dial = GTK_DIAL (widget);
13101
13102   gdk_window_clear_area (widget->window,
13103                          0, 0,
13104                          widget->allocation.width,
13105                          widget->allocation.height);
13106
13107   xc = widget->allocation.width/2;
13108   yc = widget->allocation.height/2;
13109
13110   /* Draw ticks */
13111
13112   for (i=0; i<25; i++)
13113     {
13114       theta = (i*M_PI/18. - M_PI/6.);
13115       s = sin(theta);
13116       c = cos(theta);
13117
13118       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
13119       
13120       gdk_draw_line (widget->window,
13121                      widget->style->fg_gc[widget->state],
13122                      xc + c*(dial->radius - tick_length),
13123                      yc - s*(dial->radius - tick_length),
13124                      xc + c*dial->radius,
13125                      yc - s*dial->radius);
13126     }
13127
13128   /* Draw pointer */
13129
13130   s = sin(dial->angle);
13131   c = cos(dial->angle);
13132
13133
13134   points[0].x = xc + s*dial->pointer_width/2;
13135   points[0].y = yc + c*dial->pointer_width/2;
13136   points[1].x = xc + c*dial->radius;
13137   points[1].y = yc - s*dial->radius;
13138   points[2].x = xc - s*dial->pointer_width/2;
13139   points[2].y = yc - c*dial->pointer_width/2;
13140
13141   gtk_draw_polygon (widget->style,
13142                     widget->window,
13143                     GTK_STATE_NORMAL,
13144                     GTK_SHADOW_OUT,
13145                     points, 3,
13146                     TRUE);
13147   
13148   return FALSE;
13149 }
13150 </verb></tscreen>
13151
13152 <!-- ----------------------------------------------------------------- -->
13153 <sect2> Event handling
13154 <p>
13155 The rest of the widget's code handles various types of events, and
13156 isn't too different from what would be found in many GTK
13157 applications. Two types of events can occur - either the user can
13158 click on the widget with the mouse and drag to move the pointer, or
13159 the value of the Adjustment object can change due to some external
13160 circumstance. 
13161
13162 When the user clicks on the widget, we check to see if the click was
13163 appropriately near the pointer, and if so, store then button that the
13164 user clicked with in the <tt/button/ field of the widget
13165 structure, and grab all mouse events with a call to
13166 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
13167 value of the control to be recomputed (by the function
13168 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
13169 set, "value_changed" events are either generated instantly
13170 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
13171 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
13172 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
13173
13174 <tscreen><verb>
13175 static gint
13176 gtk_dial_button_press (GtkWidget      *widget,
13177                        GdkEventButton *event)
13178 {
13179   GtkDial *dial;
13180   gint dx, dy;
13181   double s, c;
13182   double d_parallel;
13183   double d_perpendicular;
13184
13185   g_return_val_if_fail (widget != NULL, FALSE);
13186   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13187   g_return_val_if_fail (event != NULL, FALSE);
13188
13189   dial = GTK_DIAL (widget);
13190
13191   /* Determine if button press was within pointer region - we 
13192      do this by computing the parallel and perpendicular distance of
13193      the point where the mouse was pressed from the line passing through
13194      the pointer */
13195   
13196   dx = event->x - widget->allocation.width / 2;
13197   dy = widget->allocation.height / 2 - event->y;
13198   
13199   s = sin(dial->angle);
13200   c = cos(dial->angle);
13201   
13202   d_parallel = s*dy + c*dx;
13203   d_perpendicular = fabs(s*dx - c*dy);
13204   
13205   if (!dial->button &&
13206       (d_perpendicular < dial->pointer_width/2) &&
13207       (d_parallel > - dial->pointer_width))
13208     {
13209       gtk_grab_add (widget);
13210
13211       dial->button = event->button;
13212
13213       gtk_dial_update_mouse (dial, event->x, event->y);
13214     }
13215
13216   return FALSE;
13217 }
13218
13219 static gint
13220 gtk_dial_button_release (GtkWidget      *widget,
13221                           GdkEventButton *event)
13222 {
13223   GtkDial *dial;
13224
13225   g_return_val_if_fail (widget != NULL, FALSE);
13226   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13227   g_return_val_if_fail (event != NULL, FALSE);
13228
13229   dial = GTK_DIAL (widget);
13230
13231   if (dial->button == event->button)
13232     {
13233       gtk_grab_remove (widget);
13234
13235       dial->button = 0;
13236
13237       if (dial->policy == GTK_UPDATE_DELAYED)
13238         gtk_timeout_remove (dial->timer);
13239       
13240       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
13241           (dial->old_value != dial->adjustment->value))
13242         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13243     }
13244
13245   return FALSE;
13246 }
13247
13248 static gint
13249 gtk_dial_motion_notify (GtkWidget      *widget,
13250                          GdkEventMotion *event)
13251 {
13252   GtkDial *dial;
13253   GdkModifierType mods;
13254   gint x, y, mask;
13255
13256   g_return_val_if_fail (widget != NULL, FALSE);
13257   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13258   g_return_val_if_fail (event != NULL, FALSE);
13259
13260   dial = GTK_DIAL (widget);
13261
13262   if (dial->button != 0)
13263     {
13264       x = event->x;
13265       y = event->y;
13266
13267       if (event->is_hint || (event->window != widget->window))
13268         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
13269
13270       switch (dial->button)
13271         {
13272         case 1:
13273           mask = GDK_BUTTON1_MASK;
13274           break;
13275         case 2:
13276           mask = GDK_BUTTON2_MASK;
13277           break;
13278         case 3:
13279           mask = GDK_BUTTON3_MASK;
13280           break;
13281         default:
13282           mask = 0;
13283           break;
13284         }
13285
13286       if (mods & mask)
13287         gtk_dial_update_mouse (dial, x,y);
13288     }
13289
13290   return FALSE;
13291 }
13292
13293 static gint
13294 gtk_dial_timer (GtkDial *dial)
13295 {
13296   g_return_val_if_fail (dial != NULL, FALSE);
13297   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
13298
13299   if (dial->policy == GTK_UPDATE_DELAYED)
13300     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13301
13302   return FALSE;
13303 }
13304
13305 static void
13306 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
13307 {
13308   gint xc, yc;
13309   gfloat old_value;
13310
13311   g_return_if_fail (dial != NULL);
13312   g_return_if_fail (GTK_IS_DIAL (dial));
13313
13314   xc = GTK_WIDGET(dial)->allocation.width / 2;
13315   yc = GTK_WIDGET(dial)->allocation.height / 2;
13316
13317   old_value = dial->adjustment->value;
13318   dial->angle = atan2(yc-y, x-xc);
13319
13320   if (dial->angle < -M_PI/2.)
13321     dial->angle += 2*M_PI;
13322
13323   if (dial->angle < -M_PI/6)
13324     dial->angle = -M_PI/6;
13325
13326   if (dial->angle > 7.*M_PI/6.)
13327     dial->angle = 7.*M_PI/6.;
13328
13329   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
13330     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
13331
13332   if (dial->adjustment->value != old_value)
13333     {
13334       if (dial->policy == GTK_UPDATE_CONTINUOUS)
13335         {
13336           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13337         }
13338       else
13339         {
13340           gtk_widget_draw (GTK_WIDGET(dial), NULL);
13341
13342           if (dial->policy == GTK_UPDATE_DELAYED)
13343             {
13344               if (dial->timer)
13345                 gtk_timeout_remove (dial->timer);
13346
13347               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
13348                                              (GtkFunction) gtk_dial_timer,
13349                                              (gpointer) dial);
13350             }
13351         }
13352     }
13353 }
13354 </verb></tscreen>
13355
13356 Changes to the Adjustment by external means are communicated to our
13357 widget by the `changed' and `value_changed' signals. The handlers
13358 for these functions call <tt/gtk_dial_update()/ to validate the
13359 arguments, compute the new pointer angle, and redraw the widget (by
13360 calling <tt/gtk_widget_draw()/).
13361
13362 <tscreen><verb>
13363 static void
13364 gtk_dial_update (GtkDial *dial)
13365 {
13366   gfloat new_value;
13367   
13368   g_return_if_fail (dial != NULL);
13369   g_return_if_fail (GTK_IS_DIAL (dial));
13370
13371   new_value = dial->adjustment->value;
13372   
13373   if (new_value < dial->adjustment->lower)
13374     new_value = dial->adjustment->lower;
13375
13376   if (new_value > dial->adjustment->upper)
13377     new_value = dial->adjustment->upper;
13378
13379   if (new_value != dial->adjustment->value)
13380     {
13381       dial->adjustment->value = new_value;
13382       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13383     }
13384
13385   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
13386     (dial->adjustment->upper - dial->adjustment->lower);
13387
13388   gtk_widget_draw (GTK_WIDGET(dial), NULL);
13389 }
13390
13391 static void
13392 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
13393                               gpointer       data)
13394 {
13395   GtkDial *dial;
13396
13397   g_return_if_fail (adjustment != NULL);
13398   g_return_if_fail (data != NULL);
13399
13400   dial = GTK_DIAL (data);
13401
13402   if ((dial->old_value != adjustment->value) ||
13403       (dial->old_lower != adjustment->lower) ||
13404       (dial->old_upper != adjustment->upper))
13405     {
13406       gtk_dial_update (dial);
13407
13408       dial->old_value = adjustment->value;
13409       dial->old_lower = adjustment->lower;
13410       dial->old_upper = adjustment->upper;
13411     }
13412 }
13413
13414 static void
13415 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
13416                                     gpointer       data)
13417 {
13418   GtkDial *dial;
13419
13420   g_return_if_fail (adjustment != NULL);
13421   g_return_if_fail (data != NULL);
13422
13423   dial = GTK_DIAL (data);
13424
13425   if (dial->old_value != adjustment->value)
13426     {
13427       gtk_dial_update (dial);
13428
13429       dial->old_value = adjustment->value;
13430     }
13431 }
13432 </verb></tscreen>
13433
13434 <!-- ----------------------------------------------------------------- -->
13435 <sect2> Possible Enhancements
13436 <p>
13437 The Dial widget as we've described it so far runs about 670 lines of
13438 code. Although that might sound like a fair bit, we've really
13439 accomplished quite a bit with that much code, especially since much of
13440 that length is headers and boilerplate. However, there are quite a few
13441 more enhancements that could be made to this widget:
13442
13443 <itemize>
13444 <item> If you try this widget out, you'll find that there is some
13445 flashing as the pointer is dragged around. This is because the entire
13446 widget is erased every time the pointer is moved before being
13447 redrawn. Often, the best way to handle this problem is to draw to an
13448 offscreen pixmap, then copy the final results onto the screen in one
13449 step. (The ProgressBar widget draws itself in this fashion.)
13450
13451 <item> The user should be able to use the up and down arrow keys to
13452 increase and decrease the value.
13453
13454 <item> It would be nice if the widget had buttons to increase and
13455 decrease the value in small or large steps. Although it would be
13456 possible to use embedded Button widgets for this, we would also like
13457 the buttons to auto-repeat when held down, as the arrows on a
13458 scrollbar do. Most of the code to implement this type of behavior can
13459 be found in the GtkRange widget.
13460
13461 <item> The Dial widget could be made into a container widget with a
13462 single child widget positioned at the bottom between the buttons
13463 mentioned above. The user could then add their choice of a label or
13464 entry widget to display the current value of the dial.
13465
13466 </itemize>
13467
13468 <!-- ----------------------------------------------------------------- -->
13469 <sect1> Learning More
13470
13471 <p>
13472 Only a small part of the many details involved in creating widgets
13473 could be described above. If you want to write your own widgets, the
13474 best source of examples is the GTK source itself. Ask yourself some
13475 questions about the widget you want to write: is it a Container
13476 widget? does it have its own window? is it a modification of an
13477 existing widget? Then find a similar widget, and start making changes.
13478 Good luck!
13479
13480 <!-- ***************************************************************** -->
13481 <sect>Scribble, A Simple Example Drawing Program
13482 <!-- ***************************************************************** -->
13483
13484 <!-- ----------------------------------------------------------------- -->
13485 <sect1> Overview
13486 <p>
13487 In this section, we will build a simple drawing program. In the
13488 process, we will examine how to handle mouse events, how to draw in a
13489 window, and how to do drawing better by using a backing pixmap. After
13490 creating the simple drawing program, we will extend it by adding
13491 support for XInput devices, such as drawing tablets. GTK provides
13492 support routines which makes getting extended information, such as
13493 pressure and tilt, from such devices quite easy.
13494
13495 <!-- ----------------------------------------------------------------- -->
13496 <sect1> Event Handling
13497 <p>
13498 The GTK signals we have already discussed are for high-level actions,
13499 such as a menu item being selected. However, sometimes it is useful to
13500 learn about lower-level occurrences, such as the mouse being moved, or
13501 a key being pressed. There are also GTK signals corresponding to these
13502 low-level <em>events</em>. The handlers for these signals have an
13503 extra parameter which is a pointer to a structure containing
13504 information about the event. For instance, motion events handlers are
13505 passed a pointer to a GdkEventMotion structure which looks (in part)
13506 like:
13507
13508 <tscreen><verb>
13509 struct _GdkEventMotion
13510 {
13511   GdkEventType type;
13512   GdkWindow *window;
13513   guint32 time;
13514   gdouble x;
13515   gdouble y;
13516   ...
13517   guint state;
13518   ...
13519 };
13520 </verb></tscreen>
13521
13522 <tt/type/ will be set to the event type, in this case
13523 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
13524 occurred. <tt/x/ and <tt/y/ give the coordinates of the event,
13525 and <tt/state/ specifies the modifier state when the event
13526 occurred (that is, it specifies which modifier keys and mouse buttons
13527 were pressed.) It is the bitwise OR of some of the following:
13528
13529 <tscreen><verb>
13530 GDK_SHIFT_MASK  
13531 GDK_LOCK_MASK   
13532 GDK_CONTROL_MASK
13533 GDK_MOD1_MASK   
13534 GDK_MOD2_MASK   
13535 GDK_MOD3_MASK   
13536 GDK_MOD4_MASK   
13537 GDK_MOD5_MASK   
13538 GDK_BUTTON1_MASK
13539 GDK_BUTTON2_MASK
13540 GDK_BUTTON3_MASK
13541 GDK_BUTTON4_MASK
13542 GDK_BUTTON5_MASK
13543 </verb></tscreen>
13544
13545 As for other signals, to determine what happens when an event occurs
13546 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
13547 know which events we want to be notified about. To do this, we call
13548 the function:
13549
13550 <tscreen><verb>
13551 void gtk_widget_set_events (GtkWidget *widget,
13552                             gint      events);
13553 </verb></tscreen>
13554
13555 The second field specifies the events we are interested in. It
13556 is the bitwise OR of constants that specify different types
13557 of events. For future reference the event types are:
13558
13559 <tscreen><verb>
13560 GDK_EXPOSURE_MASK
13561 GDK_POINTER_MOTION_MASK
13562 GDK_POINTER_MOTION_HINT_MASK
13563 GDK_BUTTON_MOTION_MASK     
13564 GDK_BUTTON1_MOTION_MASK    
13565 GDK_BUTTON2_MOTION_MASK    
13566 GDK_BUTTON3_MOTION_MASK    
13567 GDK_BUTTON_PRESS_MASK      
13568 GDK_BUTTON_RELEASE_MASK    
13569 GDK_KEY_PRESS_MASK         
13570 GDK_KEY_RELEASE_MASK       
13571 GDK_ENTER_NOTIFY_MASK      
13572 GDK_LEAVE_NOTIFY_MASK      
13573 GDK_FOCUS_CHANGE_MASK      
13574 GDK_STRUCTURE_MASK         
13575 GDK_PROPERTY_CHANGE_MASK   
13576 GDK_PROXIMITY_IN_MASK      
13577 GDK_PROXIMITY_OUT_MASK     
13578 </verb></tscreen>
13579
13580 There are a few subtle points that have to be observed when calling
13581 <tt/gtk_widget_set_events()/. First, it must be called before the X window
13582 for a GTK widget is created. In practical terms, this means you
13583 should call it immediately after creating the widget. Second, the
13584 widget must have an associated X window. For efficiency, many widget
13585 types do not have their own window, but draw in their parent's window.
13586 These widgets are:
13587
13588 <tscreen><verb>
13589 GtkAlignment
13590 GtkArrow
13591 GtkBin
13592 GtkBox
13593 GtkImage
13594 GtkItem
13595 GtkLabel
13596 GtkPixmap
13597 GtkScrolledWindow
13598 GtkSeparator
13599 GtkTable
13600 GtkAspectFrame
13601 GtkFrame
13602 GtkVBox
13603 GtkHBox
13604 GtkVSeparator
13605 GtkHSeparator
13606 </verb></tscreen>
13607
13608 To capture events for these widgets, you need to use an EventBox
13609 widget. See the section on the <ref id="sec_EventBox"
13610 name="EventBox"> widget for details.
13611
13612 For our drawing program, we want to know when the mouse button is
13613 pressed and when the mouse is moved, so we specify
13614 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
13615 want to know when we need to redraw our window, so we specify
13616 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
13617 Configure event when our window size changes, we don't have to specify
13618 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
13619 automatically specified for all windows.
13620
13621 It turns out, however, that there is a problem with just specifying
13622 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
13623 motion event to the event queue every time the user moves the mouse.
13624 Imagine that it takes us 0.1 seconds to handle a motion event, but the
13625 X server queues a new motion event every 0.05 seconds. We will soon
13626 get way behind the users drawing. If the user draws for 5 seconds,
13627 it will take us another 5 seconds to catch up after they release 
13628 the mouse button! What we would like is to only get one motion
13629 event for each event we process. The way to do this is to 
13630 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
13631
13632 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
13633 us a motion event the first time the pointer moves after entering
13634 our window, or after a button press or release event. Subsequent 
13635 motion events will be suppressed until we explicitly ask for
13636 the position of the pointer using the function:
13637
13638 <tscreen><verb>
13639 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
13640                                           gint            *x,
13641                                           gint            *y,
13642                                           GdkModifierType *mask);
13643 </verb></tscreen>
13644
13645 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
13646 has a simpler interface, but turns out not to be very useful, since
13647 it only retrieves the position of the mouse, not whether the buttons
13648 are pressed.)
13649
13650 The code to set the events for our window then looks like:
13651
13652 <tscreen><verb>
13653   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
13654                       (GtkSignalFunc) expose_event, NULL);
13655   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
13656                       (GtkSignalFunc) configure_event, NULL);
13657   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
13658                       (GtkSignalFunc) motion_notify_event, NULL);
13659   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
13660                       (GtkSignalFunc) button_press_event, NULL);
13661
13662   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
13663                          | GDK_LEAVE_NOTIFY_MASK
13664                          | GDK_BUTTON_PRESS_MASK
13665                          | GDK_POINTER_MOTION_MASK
13666                          | GDK_POINTER_MOTION_HINT_MASK);
13667 </verb></tscreen>
13668
13669 We'll save the "expose_event" and "configure_event" handlers for
13670 later. The "motion_notify_event" and "button_press_event" handlers
13671 pretty simple:
13672
13673 <tscreen><verb>
13674 static gint
13675 button_press_event (GtkWidget *widget, GdkEventButton *event)
13676 {
13677   if (event->button == 1 &amp;&amp; pixmap != NULL)
13678       draw_brush (widget, event->x, event->y);
13679
13680   return TRUE;
13681 }
13682
13683 static gint
13684 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13685 {
13686   int x, y;
13687   GdkModifierType state;
13688
13689   if (event->is_hint)
13690     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
13691   else
13692     {
13693       x = event->x;
13694       y = event->y;
13695       state = event->state;
13696     }
13697     
13698   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13699     draw_brush (widget, x, y);
13700   
13701   return TRUE;
13702 }
13703 </verb></tscreen>
13704
13705 <!-- ----------------------------------------------------------------- -->
13706 <sect1> The DrawingArea Widget, And Drawing
13707 <p>
13708 We know turn to the process of drawing on the screen. The 
13709 widget we use for this is the DrawingArea widget. A drawing area
13710 widget is essentially an X window and nothing more. It is a blank
13711 canvas in which we can draw whatever we like. A drawing area
13712 is created using the call:
13713
13714 <tscreen><verb>
13715 GtkWidget* gtk_drawing_area_new        (void);
13716 </verb></tscreen>
13717
13718 A default size for the widget can be specified by calling:
13719
13720 <tscreen><verb>
13721 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
13722                                         gint                 width,
13723                                         gint                 height);
13724 </verb></tscreen>
13725
13726 This default size can be overridden, as is true for all widgets,
13727 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
13728 be overridden if the user manually resizes the the window containing
13729 the drawing area.
13730
13731 It should be noted that when we create a DrawingArea widget, we are,
13732 <em>completely</em> responsible for drawing the contents. If our
13733 window is obscured then uncovered, we get an exposure event and must
13734 redraw what was previously hidden.
13735
13736 Having to remember everything that was drawn on the screen so we
13737 can properly redraw it can, to say the least, be a nuisance. In
13738 addition, it can be visually distracting if portions of the
13739 window are cleared, then redrawn step by step. The solution to
13740 this problem is to use an offscreen <em>backing pixmap</em>.
13741 Instead of drawing directly to the screen, we draw to an image
13742 stored in server memory but not displayed, then when the image
13743 changes or new portions of the image are displayed, we copy the
13744 relevant portions onto the screen.
13745
13746 To create an offscreen pixmap, we call the function:
13747
13748 <tscreen><verb>
13749 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
13750                                          gint        width,
13751                                          gint        height,
13752                                          gint        depth);
13753 </verb></tscreen>
13754
13755 The <tt>window</tt> parameter specifies a GDK window that this pixmap
13756 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
13757 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
13758 depth</em>, that is the number of bits per pixel, for the new window.
13759 If the depth is specified as <tt>-1</tt>, it will match the depth
13760 of <tt>window</tt>.
13761
13762 We create the pixmap in our "configure_event" handler. This event
13763 is generated whenever the window changes size, including when it
13764 is originally created.
13765
13766 <tscreen><verb>
13767 /* Backing pixmap for drawing area */
13768 static GdkPixmap *pixmap = NULL;
13769
13770 /* Create a new backing pixmap of the appropriate size */
13771 static gint
13772 configure_event (GtkWidget *widget, GdkEventConfigure *event)
13773 {
13774   if (pixmap)
13775     gdk_pixmap_unref(pixmap);
13776
13777   pixmap = gdk_pixmap_new(widget->window,
13778                           widget->allocation.width,
13779                           widget->allocation.height,
13780                           -1);
13781   gdk_draw_rectangle (pixmap,
13782                       widget->style->white_gc,
13783                       TRUE,
13784                       0, 0,
13785                       widget->allocation.width,
13786                       widget->allocation.height);
13787
13788   return TRUE;
13789 }
13790 </verb></tscreen>
13791
13792 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
13793 initially to white. We'll say more about that in a moment.
13794
13795 Our exposure event handler then simply copies the relevant portion
13796 of the pixmap onto the screen (we determine the area we need
13797 to redraw by using the event->area field of the exposure event):
13798
13799 <tscreen><verb>
13800 /* Redraw the screen from the backing pixmap */
13801 static gint
13802 expose_event (GtkWidget *widget, GdkEventExpose *event)
13803 {
13804   gdk_draw_pixmap(widget->window,
13805                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
13806                   pixmap,
13807                   event->area.x, event->area.y,
13808                   event->area.x, event->area.y,
13809                   event->area.width, event->area.height);
13810
13811   return FALSE;
13812 }
13813 </verb></tscreen>
13814
13815 We've now seen how to keep the screen up to date with our pixmap, but
13816 how do we actually draw interesting stuff on our pixmap?  There are a
13817 large number of calls in GTK's GDK library for drawing on
13818 <em>drawables</em>. A drawable is simply something that can be drawn
13819 upon. It can be a window, a pixmap, or a bitmap (a black and white
13820 image).  We've already seen two such calls above,
13821 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
13822 complete list is:
13823
13824 <tscreen><verb>
13825 gdk_draw_line ()
13826 gdk_draw_rectangle ()
13827 gdk_draw_arc ()
13828 gdk_draw_polygon ()
13829 gdk_draw_string ()
13830 gdk_draw_text ()
13831 gdk_draw_pixmap ()
13832 gdk_draw_bitmap ()
13833 gdk_draw_image ()
13834 gdk_draw_points ()
13835 gdk_draw_segments ()
13836 </verb></tscreen>
13837
13838 See the reference documentation or the header file
13839 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
13840 These functions all share the same first two arguments. The first
13841 argument is the drawable to draw upon, the second argument is a
13842 <em>graphics context</em> (GC). 
13843
13844 A graphics context encapsulates information about things such as
13845 foreground and background color and line width. GDK has a full set of
13846 functions for creating and modifying graphics contexts, but to keep
13847 things simple we'll just use predefined graphics contexts. Each widget
13848 has an associated style. (Which can be modified in a gtkrc file, see
13849 the section GTK's rc file.) This, among other things, stores a number
13850 of graphics contexts. Some examples of accessing these graphics
13851 contexts are:
13852
13853 <tscreen><verb>
13854 widget->style->white_gc
13855 widget->style->black_gc
13856 widget->style->fg_gc[GTK_STATE_NORMAL]
13857 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
13858 </verb></tscreen>
13859
13860 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
13861 <tt>light_gc</tt> are indexed by a parameter of type
13862 <tt>GtkStateType</tt> which can take on the values:
13863
13864 <tscreen><verb>
13865 GTK_STATE_NORMAL,
13866 GTK_STATE_ACTIVE,
13867 GTK_STATE_PRELIGHT,
13868 GTK_STATE_SELECTED,
13869 GTK_STATE_INSENSITIVE
13870 </verb></tscreen>
13871
13872 For instance, the for <tt/GTK_STATE_SELECTED/ the default foreground
13873 color is white and the default background color, dark blue.
13874
13875 Our function <tt>draw_brush()</tt>, which does the actual drawing
13876 on the screen, is then:
13877
13878 <tscreen><verb>
13879 /* Draw a rectangle on the screen */
13880 static void
13881 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
13882 {
13883   GdkRectangle update_rect;
13884
13885   update_rect.x = x - 5;
13886   update_rect.y = y - 5;
13887   update_rect.width = 10;
13888   update_rect.height = 10;
13889   gdk_draw_rectangle (pixmap,
13890                       widget->style->black_gc,
13891                       TRUE,
13892                       update_rect.x, update_rect.y,
13893                       update_rect.width, update_rect.height);
13894   gtk_widget_draw (widget, &amp;update_rect);
13895 }
13896 </verb></tscreen>
13897
13898 After we draw the rectangle representing the brush onto the pixmap,
13899 we call the function:
13900
13901 <tscreen><verb>
13902 void       gtk_widget_draw                (GtkWidget           *widget,
13903                                            GdkRectangle        *area);
13904 </verb></tscreen>
13905
13906 which notifies X that the area given by the <tt>area</tt> parameter
13907 needs to be updated. X will eventually generate an expose event
13908 (possibly combining the areas passed in several calls to
13909 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
13910 to copy the relevant portions to the screen.
13911
13912 We have now covered the entire drawing program except for a few
13913 mundane details like creating the main window. The complete
13914 source code is available from the location from which you got
13915 this tutorial, or from:
13916
13917 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13918 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13919
13920
13921 <!-- ----------------------------------------------------------------- -->
13922 <sect1> Adding XInput support
13923 <p>
13924 It is now possible to buy quite inexpensive input devices such 
13925 as drawing tablets, which allow drawing with a much greater
13926 ease of artistic expression than does a mouse. The simplest way
13927 to use such devices is simply as a replacement for the mouse,
13928 but that misses out many of the advantages of these devices,
13929 such as:
13930
13931 <itemize>
13932 <item> Pressure sensitivity
13933 <item> Tilt reporting
13934 <item> Sub-pixel positioning
13935 <item> Multiple inputs (for example, a stylus with a point and eraser)
13936 </itemize>
13937
13938 For information about the XInput extension, see the <htmlurl
13939 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13940 name="XInput-HOWTO">.
13941
13942 If we examine the full definition of, for example, the GdkEventMotion
13943 structure, we see that it has fields to support extended device
13944 information.
13945
13946 <tscreen><verb>
13947 struct _GdkEventMotion
13948 {
13949   GdkEventType type;
13950   GdkWindow *window;
13951   guint32 time;
13952   gdouble x;
13953   gdouble y;
13954   gdouble pressure;
13955   gdouble xtilt;
13956   gdouble ytilt;
13957   guint state;
13958   gint16 is_hint;
13959   GdkInputSource source;
13960   guint32 deviceid;
13961 };
13962 </verb></tscreen>
13963
13964 <tt/pressure/ gives the pressure as a floating point number between
13965 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
13966 -1 and 1, corresponding to the degree of tilt in each direction.
13967 <tt/source/ and <tt/deviceid/ specify the device for which the
13968 event occurred in two different ways. <tt/source/ gives some simple
13969 information about the type of device. It can take the enumeration
13970 values.
13971
13972 <tscreen><verb>
13973 GDK_SOURCE_MOUSE
13974 GDK_SOURCE_PEN
13975 GDK_SOURCE_ERASER
13976 GDK_SOURCE_CURSOR
13977 </verb></tscreen>
13978
13979 <tt/deviceid/ specifies a unique numeric ID for the device. This can
13980 be used to find out further information about the device using the
13981 <tt/gdk_input_list_devices()/ call (see below). The special value
13982 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
13983 the mouse.)
13984
13985 <sect2> Enabling extended device information
13986 <p>
13987 To let GTK know about our interest in the extended device information,
13988 we merely have to add a single line to our program:
13989
13990 <tscreen><verb>
13991 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
13992 </verb></tscreen>
13993
13994 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
13995 we are interested in extension events, but only if we don't have
13996 to draw our own cursor. See the section <ref
13997 id="sec_Further_Sophistications" name="Further Sophistications"> below
13998 for more information about drawing the cursor. We could also 
13999 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
14000 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
14001 back to the default condition.
14002
14003 This is not completely the end of the story however. By default,
14004 no extension devices are enabled. We need a mechanism to allow
14005 users to enable and configure their extension devices. GTK provides
14006 the InputDialog widget to automate this process. The following
14007 procedure manages an InputDialog widget. It creates the dialog if
14008 it isn't present, and raises it to the top otherwise.
14009
14010 <tscreen><verb>
14011 void
14012 input_dialog_destroy (GtkWidget *w, gpointer data)
14013 {
14014   *((GtkWidget **)data) = NULL;
14015 }
14016
14017 void
14018 create_input_dialog ()
14019 {
14020   static GtkWidget *inputd = NULL;
14021
14022   if (!inputd)
14023     {
14024       inputd = gtk_input_dialog_new();
14025
14026       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
14027                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
14028       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
14029                                  "clicked",
14030                                  (GtkSignalFunc)gtk_widget_hide,
14031                                  GTK_OBJECT(inputd));
14032       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
14033
14034       gtk_widget_show (inputd);
14035     }
14036   else
14037     {
14038       if (!GTK_WIDGET_MAPPED(inputd))
14039         gtk_widget_show(inputd);
14040       else
14041         gdk_window_raise(inputd->window);
14042     }
14043 }
14044 </verb></tscreen>
14045
14046 (You might want to take note of the way we handle this dialog.  By
14047 connecting to the "destroy" signal, we make sure that we don't keep a
14048 pointer to dialog around after it is destroyed - that could lead to a
14049 segfault.)
14050
14051 The InputDialog has two buttons "Close" and "Save", which by default
14052 have no actions assigned to them. In the above function we make
14053 "Close" hide the dialog, hide the "Save" button, since we don't
14054 implement saving of XInput options in this program.
14055
14056 <sect2> Using extended device information
14057 <p>
14058 Once we've enabled the device, we can just use the extended 
14059 device information in the extra fields of the event structures.
14060 In fact, it is always safe to use this information since these
14061 fields will have reasonable default values even when extended
14062 events are not enabled.
14063
14064 Once change we do have to make is to call
14065 <tt/gdk_input_window_get_pointer()/ instead of
14066 <tt/gdk_window_get_pointer/. This is necessary because
14067 <tt/gdk_window_get_pointer/ doesn't return the extended device
14068 information.
14069
14070 <tscreen><verb>
14071 void gdk_input_window_get_pointer( GdkWindow       *window,
14072                                    guint32         deviceid,
14073                                    gdouble         *x,
14074                                    gdouble         *y,
14075                                    gdouble         *pressure,
14076                                    gdouble         *xtilt,
14077                                    gdouble         *ytilt,
14078                                    GdkModifierType *mask);
14079 </verb></tscreen>
14080
14081 When calling this function, we need to specify the device ID as
14082 well as the window. Usually, we'll get the device ID from the
14083 <tt/deviceid/ field of an event structure. Again, this function
14084 will return reasonable values when extension events are not
14085 enabled. (In this case, <tt/event->deviceid/ will have the value
14086 <tt/GDK_CORE_POINTER/).
14087
14088 So the basic structure of our button-press and motion event handlers,
14089 doesn't change much - we just need to add code to deal with the
14090 extended information.
14091
14092 <tscreen><verb>
14093 static gint
14094 button_press_event (GtkWidget *widget, GdkEventButton *event)
14095 {
14096   print_button_press (event->deviceid);
14097   
14098   if (event->button == 1 &amp;&amp; pixmap != NULL)
14099     draw_brush (widget, event->source, event->x, event->y, event->pressure);
14100
14101   return TRUE;
14102 }
14103
14104 static gint
14105 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14106 {
14107   gdouble x, y;
14108   gdouble pressure;
14109   GdkModifierType state;
14110
14111   if (event->is_hint)
14112     gdk_input_window_get_pointer (event->window, event->deviceid,
14113                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
14114   else
14115     {
14116       x = event->x;
14117       y = event->y;
14118       pressure = event->pressure;
14119       state = event->state;
14120     }
14121     
14122   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14123     draw_brush (widget, event->source, x, y, pressure);
14124   
14125   return TRUE;
14126 }
14127 </verb></tscreen>
14128
14129 We also need to do something with the new information. Our new
14130 <tt/draw_brush()/ function draws with a different color for
14131 each <tt/event->source/ and changes the brush size depending
14132 on the pressure.
14133
14134 <tscreen><verb>
14135 /* Draw a rectangle on the screen, size depending on pressure,
14136    and color on the type of device */
14137 static void
14138 draw_brush (GtkWidget *widget, GdkInputSource source,
14139             gdouble x, gdouble y, gdouble pressure)
14140 {
14141   GdkGC *gc;
14142   GdkRectangle update_rect;
14143
14144   switch (source)
14145     {
14146     case GDK_SOURCE_MOUSE:
14147       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
14148       break;
14149     case GDK_SOURCE_PEN:
14150       gc = widget->style->black_gc;
14151       break;
14152     case GDK_SOURCE_ERASER:
14153       gc = widget->style->white_gc;
14154       break;
14155     default:
14156       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
14157     }
14158
14159   update_rect.x = x - 10 * pressure;
14160   update_rect.y = y - 10 * pressure;
14161   update_rect.width = 20 * pressure;
14162   update_rect.height = 20 * pressure;
14163   gdk_draw_rectangle (pixmap, gc, TRUE,
14164                       update_rect.x, update_rect.y,
14165                       update_rect.width, update_rect.height);
14166   gtk_widget_draw (widget, &amp;update_rect);
14167 }
14168 </verb></tscreen>
14169
14170 <sect2> Finding out more about a device
14171 <p>
14172 As an example of how to find out more about a device, our program
14173 will print the name of the device that generates each button
14174 press. To find out the name of a device, we call the function:
14175
14176 <tscreen><verb>
14177 GList *gdk_input_list_devices               (void);
14178 </verb></tscreen>
14179
14180 which returns a GList (a linked list type from the glib library)
14181 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
14182 as:
14183
14184 <tscreen><verb>
14185 struct _GdkDeviceInfo
14186 {
14187   guint32 deviceid;
14188   gchar *name;
14189   GdkInputSource source;
14190   GdkInputMode mode;
14191   gint has_cursor;
14192   gint num_axes;
14193   GdkAxisUse *axes;
14194   gint num_keys;
14195   GdkDeviceKey *keys;
14196 };
14197 </verb></tscreen>
14198
14199 Most of these fields are configuration information that you
14200 can ignore unless you are implemented XInput configuration
14201 saving. The we are interested in here is <tt/name/ which is
14202 simply the name that X assigns to the device. The other field
14203 that isn't configuration information is <tt/has_cursor/. If
14204 <tt/has_cursor/ is false, then we we need to draw our own
14205 cursor. But since we've specified <tt/GDK_EXTENSION_EVENTS_CURSOR/,
14206 we don't have to worry about this.
14207
14208 Our <tt/print_button_press()/ function simply iterates through
14209 the returned list until it finds a match, then prints out
14210 the name of the device.
14211
14212 <tscreen><verb>
14213 static void
14214 print_button_press (guint32 deviceid)
14215 {
14216   GList *tmp_list;
14217
14218   /* gdk_input_list_devices returns an internal list, so we shouldn't
14219      free it afterwards */
14220   tmp_list = gdk_input_list_devices();
14221
14222   while (tmp_list)
14223     {
14224       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
14225
14226       if (info->deviceid == deviceid)
14227         {
14228           printf("Button press on device '%s'\n", info->name);
14229           return;
14230         }
14231
14232       tmp_list = tmp_list->next;
14233     }
14234 }
14235 </verb></tscreen>
14236
14237 That completes the changes to `XInputize' our program. As with
14238 the first version, the complete source is available at the location
14239 from which you got this tutorial, or from:
14240
14241 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
14242 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
14243
14244
14245 <sect2> Further sophistications <label id="sec_Further_Sophistications">
14246 <p>
14247 Although our program now supports XInput quite well, it lacks some
14248 features we would want in a full-featured application. First, the user
14249 probably doesn't want to have to configure their device each time they
14250 run the program, so we should allow them to save the device
14251 configuration. This is done by iterating through the return of
14252 <tt/gdk_input_list_devices()/ and writing out the configuration to a
14253 file.
14254
14255 To restore the state next time the program is run, GDK provides
14256 functions to change device configuration:
14257
14258 <tscreen><verb>
14259 gdk_input_set_extension_events()
14260 gdk_input_set_source()
14261 gdk_input_set_mode()
14262 gdk_input_set_axes()
14263 gdk_input_set_key()
14264 </verb></tscreen>
14265
14266 (The list returned from <tt/gdk_input_list_devices()/ should not be
14267 modified directly.) An example of doing this can be found in the
14268 drawing program gsumi. (Available from <htmlurl
14269 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
14270 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
14271 would be nice to have a standard way of doing this for all
14272 applications. This probably belongs at a slightly higher level than
14273 GTK, perhaps in the GNOME library.
14274
14275 Another major omission that we have mentioned above is the lack of
14276 cursor drawing. Platforms other than XFree86 currently do not allow
14277 simultaneously using a device as both the core pointer and directly by
14278 an application. See the <url
14279 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14280 name="XInput-HOWTO"> for more information about this. This means that
14281 applications that want to support the widest audience need to draw
14282 their own cursor.
14283
14284 An application that draws its own cursor needs to do two things:
14285 determine if the current device needs a cursor drawn or not, and
14286 determine if the current device is in proximity. (If the current
14287 device is a drawing tablet, it's a nice touch to make the cursor 
14288 disappear when the stylus is lifted from the tablet. When the
14289 device is touching the stylus, that is called "in proximity.")
14290 The first is done by searching the device list, as we did
14291 to find out the device name. The second is achieved by selecting
14292 "proximity_out" events. An example of drawing one's own cursor is
14293 found in the 'testinput' program found in the GTK distribution.
14294
14295 <!-- ***************************************************************** -->
14296 <sect>Tips For Writing GTK Applications
14297 <!-- ***************************************************************** -->
14298 <p>
14299 This section is simply a gathering of wisdom, general style guidelines
14300 and hints to creating good GTK applications. Currently this section
14301 is very short, but hopefully it will get longer in future editions of
14302 this tutorial.
14303
14304 Use GNU autoconf and automake! They are your friends :) Automake
14305 examines C files, determines how they depend on each other, and
14306 generates a Makefile so the files can be compiled in the correct
14307 order. Autoconf permits automatic configuration of software
14308 installation, handling a large number of system quirks to increase
14309 portability. I am planning to make a quick intro on them here.
14310
14311 When writing C code, use only C comments (beginning with "/*" and
14312 ending with "*/"), and don't use C++-style comments ("//").  Although
14313 many C compilers understand C++ comments, others don't, and the ANSI C
14314 standard does not require that C++-style comments be processed as
14315 comments.
14316
14317 <!-- ***************************************************************** -->
14318 <sect>Contributing <label id="sec_Contributing">
14319 <!-- ***************************************************************** -->
14320 <p>
14321 This document, like so much other great software out there, was
14322 created for free by volunteers.  If you are at all knowledgeable about
14323 any aspect of GTK that does not already have documentation, please
14324 consider contributing to this document.
14325
14326 If you do decide to contribute, please mail your text to Tony Gale,
14327 <tt><htmlurl url="mailto:gale@gtk.org"
14328 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
14329 document is free, and any addition by you provide must also be
14330 free. That is, people may use any portion of your examples in their
14331 programs, and copies of this document may be distributed at will etc.
14332
14333 Thank you.
14334
14335 <!-- ***************************************************************** -->
14336 <sect>Credits
14337 <!-- ***************************************************************** -->
14338 <p>
14339 I would like to thank the following for their contributions to this text.
14340
14341 <itemize>
14342 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
14343 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
14344
14345 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
14346 name="raph@acm.org"></tt>
14347 for hello world ala GTK, widget packing, and general all around wisdom.
14348 He's also generously donated a home for this tutorial.
14349
14350 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
14351 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
14352 and the ability to make it :)
14353
14354 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
14355 name="werner.koch@guug.de"></tt> for converting the original plain text to
14356 SGML, and the widget class hierarchy.
14357
14358 <item>Mark Crichton <tt><htmlurl
14359 url="mailto:crichton@expert.cc.purdue.edu"
14360 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
14361 and the table packing tutorial.
14362
14363 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
14364 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
14365 patch to the distro).  He's also responsible for the selections code
14366 and tutorial, as well as the sections on writing your own GTK widgets,
14367 and the example application. Thanks a lot Owen for all you help!
14368
14369 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
14370 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
14371 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
14372 lot Mark!  You've been a great help.
14373
14374 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
14375 name="timj@psynet.net"></tt> for his great job on the Lists
14376 Widget. His excellent work on automatically extracting the widget tree
14377 and signal information from GTK. Thanks Tim :)
14378
14379 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
14380 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
14381 tutorial.
14382
14383 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
14384 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
14385
14386 <item>David Huggins-Daines <tt><htmlurl
14387 url="mailto:bn711@freenet.carleton.ca"
14388 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
14389 Widget sections.
14390
14391 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
14392 name="mars@lysator.liu.se"></tt> for the GtkCList section.
14393
14394 <item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org"
14395 name="dwheeler@ida.org"></tt> for portions of the text on glib
14396 and various tutorial fixups and improvements.
14397 The glib text was in turn based on material developed by Damon Chaplin
14398 <tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt>
14399 </itemize>
14400
14401 And to all of you who commented and helped refine this document.
14402
14403 Thanks.
14404
14405 <!-- ***************************************************************** -->
14406 <sect> Tutorial Copyright and Permissions Notice
14407 <!-- ***************************************************************** -->
14408
14409 <p>
14410 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
14411
14412 Copyright (C) 1998-1999 Tony Gale.
14413
14414 Permission is granted to make and distribute verbatim copies of this 
14415 manual provided the copyright notice and this permission notice are 
14416 preserved on all copies.
14417
14418 Permission is granted to copy and distribute modified versions of 
14419 this document under the conditions for verbatim copying, provided that 
14420 this copyright notice is included exactly as in the original,
14421 and that the entire resulting derived work is distributed under 
14422 the terms of a permission notice identical to this one.
14423 <P>Permission is granted to copy and distribute translations of this 
14424 document into another language, under the above conditions for modified 
14425 versions.
14426
14427 If you are intending to incorporate this document into a published 
14428 work, please contact the maintainer, and we will make an effort 
14429 to ensure that you have the most up to date information available.
14430
14431 There is no guarantee that this document lives up to its intended
14432 purpose.  This is simply provided as a free resource.  As such,
14433 the authors and maintainers of the information provided within can
14434 not make any guarantee that the information is even accurate.
14435
14436 <!-- ***************************************************************** -->
14437 <appendix>
14438 <!-- ***************************************************************** -->
14439
14440 <!-- ***************************************************************** -->
14441 <sect> GTK Signals <label id="sec_GTK_Signals">
14442 <!-- ***************************************************************** -->
14443 <p>
14444 As GTK is an object oriented widget set, it has a hierarchy of
14445 inheritance. This inheritance mechanism applies for
14446 signals. Therefore, you should refer to the widget hierarchy tree when
14447 using the signals listed in this section.
14448
14449 <!-- ----------------------------------------------------------------- -->
14450 <sect1>GtkObject
14451 <!-- ----------------------------------------------------------------- -->
14452 <p>
14453 <tscreen><verb>
14454 void GtkObject::destroy (GtkObject *,
14455                          gpointer);
14456 </verb></tscreen>
14457
14458 <!-- ----------------------------------------------------------------- -->
14459 <sect1>GtkWidget
14460 <!-- ----------------------------------------------------------------- -->
14461 <p>
14462 <tscreen><verb>
14463
14464 void GtkWidget::show    (GtkWidget *,
14465                          gpointer);
14466 void GtkWidget::hide    (GtkWidget *,
14467                          gpointer);
14468 void GtkWidget::map     (GtkWidget *,
14469                          gpointer);
14470 void GtkWidget::unmap   (GtkWidget *,
14471                          gpointer);
14472 void GtkWidget::realize (GtkWidget *,
14473                          gpointer);
14474 void GtkWidget::unrealize       (GtkWidget *,
14475                                  gpointer);
14476 void GtkWidget::draw    (GtkWidget *,
14477                          ggpointer,
14478                          gpointer);
14479 void GtkWidget::draw-focus      (GtkWidget *,
14480                                  gpointer);
14481 void GtkWidget::draw-default    (GtkWidget *,
14482                                  gpointer);
14483 void GtkWidget::size-request    (GtkWidget *,
14484                                  ggpointer,
14485                                  gpointer);
14486 void GtkWidget::size-allocate   (GtkWidget *,
14487                                  ggpointer,
14488                                  gpointer);
14489 void GtkWidget::state-changed   (GtkWidget *,
14490                                  GtkStateType,
14491                                  gpointer);
14492 void GtkWidget::parent-set      (GtkWidget *,
14493                                  GtkObject *,
14494                                  gpointer);
14495 void GtkWidget::style-set       (GtkWidget *,
14496                                  GtkStyle *,
14497                                  gpointer);
14498 void GtkWidget::add-accelerator (GtkWidget *,
14499                                  gguint,
14500                                  GtkAccelGroup *,
14501                                  gguint,
14502                                  GdkModifierType,
14503                                  GtkAccelFlags,
14504                                  gpointer);
14505 void GtkWidget::remove-accelerator      (GtkWidget *,
14506                                          GtkAccelGroup *,
14507                                          gguint,
14508                                          GdkModifierType,
14509                                          gpointer);
14510 gboolean GtkWidget::event       (GtkWidget *,
14511                                  GdkEvent *,
14512                                  gpointer);
14513 gboolean GtkWidget::button-press-event  (GtkWidget *,
14514                                          GdkEvent *,
14515                                          gpointer);
14516 gboolean GtkWidget::button-release-event        (GtkWidget *,
14517                                                  GdkEvent *,
14518                                                  gpointer);
14519 gboolean GtkWidget::motion-notify-event (GtkWidget *,
14520                                          GdkEvent *,
14521                                          gpointer);
14522 gboolean GtkWidget::delete-event        (GtkWidget *,
14523                                          GdkEvent *,
14524                                          gpointer);
14525 gboolean GtkWidget::destroy-event       (GtkWidget *,
14526                                          GdkEvent *,
14527                                          gpointer);
14528 gboolean GtkWidget::expose-event        (GtkWidget *,
14529                                          GdkEvent *,
14530                                          gpointer);
14531 gboolean GtkWidget::key-press-event     (GtkWidget *,
14532                                          GdkEvent *,
14533                                          gpointer);
14534 gboolean GtkWidget::key-release-event   (GtkWidget *,
14535                                          GdkEvent *,
14536                                          gpointer);
14537 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
14538                                          GdkEvent *,
14539                                          gpointer);
14540 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
14541                                          GdkEvent *,
14542                                          gpointer);
14543 gboolean GtkWidget::configure-event     (GtkWidget *,
14544                                          GdkEvent *,
14545                                          gpointer);
14546 gboolean GtkWidget::focus-in-event      (GtkWidget *,
14547                                          GdkEvent *,
14548                                          gpointer);
14549 gboolean GtkWidget::focus-out-event     (GtkWidget *,
14550                                          GdkEvent *,
14551                                          gpointer);
14552 gboolean GtkWidget::map-event   (GtkWidget *,
14553                                  GdkEvent *,
14554                                  gpointer);
14555 gboolean GtkWidget::unmap-event (GtkWidget *,
14556                                  GdkEvent *,
14557                                  gpointer);
14558 gboolean GtkWidget::property-notify-event       (GtkWidget *,
14559                                                  GdkEvent *,
14560                                                  gpointer);
14561 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
14562                                                  GdkEvent *,
14563                                                  gpointer);
14564 gboolean GtkWidget::selection-request-event     (GtkWidget *,
14565                                                  GdkEvent *,
14566                                                  gpointer);
14567 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
14568                                                  GdkEvent *,
14569                                                  gpointer);
14570 void GtkWidget::selection-get   (GtkWidget *,
14571                                  GtkSelectionData *,
14572                                  gguint,
14573                                  gpointer);
14574 void GtkWidget::selection-received      (GtkWidget *,
14575                                          GtkSelectionData *,
14576                                          gguint,
14577                                          gpointer);
14578 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
14579                                          GdkEvent *,
14580                                          gpointer);
14581 gboolean GtkWidget::proximity-out-event (GtkWidget *,
14582                                          GdkEvent *,
14583                                          gpointer);
14584 void GtkWidget::drag-begin      (GtkWidget *,
14585                                  GdkDragContext *,
14586                                  gpointer);
14587 void GtkWidget::drag-end        (GtkWidget *,
14588                                  GdkDragContext *,
14589                                  gpointer);
14590 void GtkWidget::drag-data-delete        (GtkWidget *,
14591                                          GdkDragContext *,
14592                                          gpointer);
14593 void GtkWidget::drag-leave      (GtkWidget *,
14594                                  GdkDragContext *,
14595                                  gguint,
14596                                  gpointer);
14597 gboolean GtkWidget::drag-motion (GtkWidget *,
14598                                  GdkDragContext *,
14599                                  ggint,
14600                                  ggint,
14601                                  gguint,
14602                                  gpointer);
14603 gboolean GtkWidget::drag-drop   (GtkWidget *,
14604                                  GdkDragContext *,
14605                                  ggint,
14606                                  ggint,
14607                                  gguint,
14608                                  gpointer);
14609 void GtkWidget::drag-data-get   (GtkWidget *,
14610                                  GdkDragContext *,
14611                                  GtkSelectionData *,
14612                                  gguint,
14613                                  gguint,
14614                                  gpointer);
14615 void GtkWidget::drag-data-received      (GtkWidget *,
14616                                          GdkDragContext *,
14617                                          ggint,
14618                                          ggint,
14619                                          GtkSelectionData *,
14620                                          gguint,
14621                                          gguint,
14622                                          gpointer);
14623 gboolean GtkWidget::client-event        (GtkWidget *,
14624                                          GdkEvent *,
14625                                          gpointer);
14626 gboolean GtkWidget::no-expose-event     (GtkWidget *,
14627                                          GdkEvent *,
14628                                          gpointer);
14629 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
14630                                                  GdkEvent *,
14631                                                  gpointer);
14632 void GtkWidget::debug-msg       (GtkWidget *,
14633                                  GtkString *,
14634                                  gpointer);
14635 </verb></tscreen>
14636
14637 <!-- ----------------------------------------------------------------- -->
14638 <sect1>GtkData
14639 <!-- ----------------------------------------------------------------- -->
14640 <p>
14641 <tscreen><verb>
14642 void GtkData::disconnect        (GtkData *,
14643                                  gpointer);
14644 </verb></tscreen>
14645
14646 <!-- ----------------------------------------------------------------- -->
14647 <sect1>GtkContainer
14648 <!-- ----------------------------------------------------------------- -->
14649 <p>
14650 <tscreen><verb>
14651 void GtkContainer::add  (GtkContainer *,
14652                          GtkWidget *,
14653                          gpointer);
14654 void GtkContainer::remove       (GtkContainer *,
14655                                  GtkWidget *,
14656                                  gpointer);
14657 void GtkContainer::check-resize (GtkContainer *,
14658                                  gpointer);
14659 GtkDirectionType GtkContainer::focus    (GtkContainer *,
14660                                          GtkDirectionType,
14661                                          gpointer);
14662 void GtkContainer::set-focus-child      (GtkContainer *,
14663                                          GtkWidget *,
14664                                          gpointer);
14665 </verb></tscreen>
14666
14667 <!-- ----------------------------------------------------------------- -->
14668 <sect1>GtkCalendar
14669 <!-- ----------------------------------------------------------------- -->
14670 <p>
14671 <tscreen><verb>
14672 void GtkCalendar::month-changed (GtkCalendar *,
14673                                  gpointer);
14674 void GtkCalendar::day-selected  (GtkCalendar *,
14675                                  gpointer);
14676 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
14677                                                  gpointer);
14678 void GtkCalendar::prev-month    (GtkCalendar *,
14679                                  gpointer);
14680 void GtkCalendar::next-month    (GtkCalendar *,
14681                                  gpointer);
14682 void GtkCalendar::prev-year     (GtkCalendar *,
14683                                  gpointer);
14684 void GtkCalendar::next-year     (GtkCalendar *,
14685                                  gpointer);
14686 </verb></tscreen>
14687
14688 <!-- ----------------------------------------------------------------- -->
14689 <sect1>GtkEditable
14690 <!-- ----------------------------------------------------------------- -->
14691 <p>
14692 <tscreen><verb>
14693 void GtkEditable::changed       (GtkEditable *,
14694                                  gpointer);
14695 void GtkEditable::insert-text   (GtkEditable *,
14696                                  GtkString *,
14697                                  ggint,
14698                                  ggpointer,
14699                                  gpointer);
14700 void GtkEditable::delete-text   (GtkEditable *,
14701                                  ggint,
14702                                  ggint,
14703                                  gpointer);
14704 void GtkEditable::activate      (GtkEditable *,
14705                                  gpointer);
14706 void GtkEditable::set-editable  (GtkEditable *,
14707                                  gboolean,
14708                                  gpointer);
14709 void GtkEditable::move-cursor   (GtkEditable *,
14710                                  ggint,
14711                                  ggint,
14712                                  gpointer);
14713 void GtkEditable::move-word     (GtkEditable *,
14714                                  ggint,
14715                                  gpointer);
14716 void GtkEditable::move-page     (GtkEditable *,
14717                                  ggint,
14718                                  ggint,
14719                                  gpointer);
14720 void GtkEditable::move-to-row   (GtkEditable *,
14721                                  ggint,
14722                                  gpointer);
14723 void GtkEditable::move-to-column        (GtkEditable *,
14724                                          ggint,
14725                                          gpointer);
14726 void GtkEditable::kill-char     (GtkEditable *,
14727                                  ggint,
14728                                  gpointer);
14729 void GtkEditable::kill-word     (GtkEditable *,
14730                                  ggint,
14731                                  gpointer);
14732 void GtkEditable::kill-line     (GtkEditable *,
14733                                  ggint,
14734                                  gpointer);
14735 void GtkEditable::cut-clipboard (GtkEditable *,
14736                                  gpointer);
14737 void GtkEditable::copy-clipboard        (GtkEditable *,
14738                                          gpointer);
14739 void GtkEditable::paste-clipboard       (GtkEditable *,
14740                                          gpointer);
14741 </verb></tscreen>
14742
14743 <!-- ----------------------------------------------------------------- -->
14744 <sect1>GtkTipsQuery
14745 <!-- ----------------------------------------------------------------- -->
14746 <p>
14747 <tscreen><verb>
14748 void GtkTipsQuery::start-query  (GtkTipsQuery *,
14749                                  gpointer);
14750 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
14751                                  gpointer);
14752 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
14753                                          GtkWidget *,
14754                                          GtkString *,
14755                                          GtkString *,
14756                                          gpointer);
14757 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
14758                                          GtkWidget *,
14759                                          GtkString *,
14760                                          GtkString *,
14761                                          GdkEvent *,
14762                                          gpointer);
14763 </verb></tscreen>
14764
14765 <!-- ----------------------------------------------------------------- -->
14766 <sect1>GtkCList
14767 <!-- ----------------------------------------------------------------- -->
14768 <p>
14769 <tscreen><verb>
14770 void GtkCList::select-row       (GtkCList *,
14771                                  ggint,
14772                                  ggint,
14773                                  GdkEvent *,
14774                                  gpointer);
14775 void GtkCList::unselect-row     (GtkCList *,
14776                                  ggint,
14777                                  ggint,
14778                                  GdkEvent *,
14779                                  gpointer);
14780 void GtkCList::row-move (GtkCList *,
14781                          ggint,
14782                          ggint,
14783                          gpointer);
14784 void GtkCList::click-column     (GtkCList *,
14785                                  ggint,
14786                                  gpointer);
14787 void GtkCList::resize-column    (GtkCList *,
14788                                  ggint,
14789                                  ggint,
14790                                  gpointer);
14791 void GtkCList::toggle-focus-row (GtkCList *,
14792                                  gpointer);
14793 void GtkCList::select-all       (GtkCList *,
14794                                  gpointer);
14795 void GtkCList::unselect-all     (GtkCList *,
14796                                  gpointer);
14797 void GtkCList::undo-selection   (GtkCList *,
14798                                  gpointer);
14799 void GtkCList::start-selection  (GtkCList *,
14800                                  gpointer);
14801 void GtkCList::end-selection    (GtkCList *,
14802                                  gpointer);
14803 void GtkCList::toggle-add-mode  (GtkCList *,
14804                                  gpointer);
14805 void GtkCList::extend-selection (GtkCList *,
14806                                  GtkScrollType,
14807                                  ggfloat,
14808                                  gboolean,
14809                                  gpointer);
14810 void GtkCList::scroll-vertical  (GtkCList *,
14811                                  GtkScrollType,
14812                                  ggfloat,
14813                                  gpointer);
14814 void GtkCList::scroll-horizontal        (GtkCList *,
14815                                          GtkScrollType,
14816                                          ggfloat,
14817                                          gpointer);
14818 void GtkCList::abort-column-resize      (GtkCList *,
14819                                          gpointer);
14820 </verb></tscreen>
14821
14822 <!-- ----------------------------------------------------------------- -->
14823 <sect1>GtkNotebook
14824 <!-- ----------------------------------------------------------------- -->
14825 <p>
14826 <tscreen><verb>
14827 void GtkNotebook::switch-page   (GtkNotebook *,
14828                                  ggpointer,
14829                                  gguint,
14830                                  gpointer);
14831
14832 </verb></tscreen>
14833
14834 <!-- ----------------------------------------------------------------- -->
14835 <sect1>GtkList
14836 <!-- ----------------------------------------------------------------- -->
14837 <p>
14838 <tscreen><verb>
14839 void GtkList::selection-changed (GtkList *,
14840                                  gpointer);
14841 void GtkList::select-child      (GtkList *,
14842                                  GtkWidget *,
14843                                  gpointer);
14844 void GtkList::unselect-child    (GtkList *,
14845                                  GtkWidget *,
14846                                  gpointer);
14847 </verb></tscreen>
14848
14849 <!-- ----------------------------------------------------------------- -->
14850 <sect1>GtkMenuShell
14851 <!-- ----------------------------------------------------------------- -->
14852 <p>
14853 <tscreen><verb>
14854 void GtkMenuShell::deactivate   (GtkMenuShell *,
14855                                  gpointer);
14856 void GtkMenuShell::selection-done       (GtkMenuShell *,
14857                                          gpointer);
14858 void GtkMenuShell::move-current (GtkMenuShell *,
14859                                  GtkMenuDirectionType,
14860                                  gpointer);
14861 void GtkMenuShell::activate-current     (GtkMenuShell *,
14862                                          gboolean,
14863                                          gpointer);
14864 void GtkMenuShell::cancel       (GtkMenuShell *,
14865                                  gpointer);
14866 </verb></tscreen>
14867
14868 <!-- ----------------------------------------------------------------- -->
14869 <sect1>GtkToolbar
14870 <!-- ----------------------------------------------------------------- -->
14871 <p>
14872 <tscreen><verb>
14873 void GtkToolbar::orientation-changed    (GtkToolbar *,
14874                                          ggint,
14875                                          gpointer);
14876 void GtkToolbar::style-changed  (GtkToolbar *,
14877                                  ggint,
14878                                  gpointer);
14879 </verb></tscreen>
14880
14881 <!-- ----------------------------------------------------------------- -->
14882 <sect1>GtkTree
14883 <!-- ----------------------------------------------------------------- -->
14884 <p>
14885 <tscreen><verb>
14886 void GtkTree::selection-changed (GtkTree *,
14887                                  gpointer);
14888 void GtkTree::select-child      (GtkTree *,
14889                                  GtkWidget *,
14890                                  gpointer);
14891 void GtkTree::unselect-child    (GtkTree *,
14892                                  GtkWidget *,
14893                                  gpointer);
14894 </verb></tscreen>
14895
14896 <!-- ----------------------------------------------------------------- -->
14897 <sect1>GtkButton
14898 <!-- ----------------------------------------------------------------- -->
14899 <p>
14900 <tscreen><verb>
14901 void GtkButton::pressed (GtkButton *,
14902                          gpointer);
14903 void GtkButton::released        (GtkButton *,
14904                                  gpointer);
14905 void GtkButton::clicked (GtkButton *,
14906                          gpointer);
14907 void GtkButton::enter   (GtkButton *,
14908                          gpointer);
14909 void GtkButton::leave   (GtkButton *,
14910                          gpointer);
14911 </verb></tscreen>
14912
14913 <!-- ----------------------------------------------------------------- -->
14914 <sect1>GtkItem
14915 <!-- ----------------------------------------------------------------- -->
14916 <p>
14917 <tscreen><verb>
14918 void GtkItem::select    (GtkItem *,
14919                          gpointer);
14920 void GtkItem::deselect  (GtkItem *,
14921                          gpointer);
14922 void GtkItem::toggle    (GtkItem *,
14923                          gpointer);
14924 </verb></tscreen>
14925
14926 <!-- ----------------------------------------------------------------- -->
14927 <sect1>GtkWindow
14928 <!-- ----------------------------------------------------------------- -->
14929 <p>
14930 <tscreen><verb>
14931 void GtkWindow::set-focus       (GtkWindow *,
14932                                  ggpointer,
14933                                  gpointer);
14934 </verb></tscreen>
14935
14936 <!-- ----------------------------------------------------------------- -->
14937 <sect1>GtkHandleBox
14938 <!-- ----------------------------------------------------------------- -->
14939 <p>
14940 <tscreen><verb>
14941 void GtkHandleBox::child-attached       (GtkHandleBox *,
14942                                          GtkWidget *,
14943                                          gpointer);
14944 void GtkHandleBox::child-detached       (GtkHandleBox *,
14945                                          GtkWidget *,
14946                                          gpointer);
14947 </verb></tscreen>
14948
14949 <!-- ----------------------------------------------------------------- -->
14950 <sect1>GtkToggleButton
14951 <!-- ----------------------------------------------------------------- -->
14952 <p>
14953 <tscreen><verb>
14954 void GtkToggleButton::toggled   (GtkToggleButton *,
14955                                  gpointer);
14956
14957 </verb></tscreen>
14958
14959 <!-- ----------------------------------------------------------------- -->
14960 <sect1>GtkMenuItem
14961 <!-- ----------------------------------------------------------------- -->
14962 <p>
14963 <tscreen><verb>
14964 void GtkMenuItem::activate      (GtkMenuItem *,
14965                                  gpointer);
14966 void GtkMenuItem::activate-item (GtkMenuItem *,
14967                                  gpointer);
14968 </verb></tscreen>
14969
14970 <!-- ----------------------------------------------------------------- -->
14971 <sect1>GtkListItem
14972 <!-- ----------------------------------------------------------------- -->
14973 <p>
14974 <tscreen><verb>
14975 void GtkListItem::toggle-focus-row      (GtkListItem *,
14976                                          gpointer);
14977 void GtkListItem::select-all    (GtkListItem *,
14978                                  gpointer);
14979 void GtkListItem::unselect-all  (GtkListItem *,
14980                                  gpointer);
14981 void GtkListItem::undo-selection        (GtkListItem *,
14982                                          gpointer);
14983 void GtkListItem::start-selection       (GtkListItem *,
14984                                          gpointer);
14985 void GtkListItem::end-selection (GtkListItem *,
14986                                  gpointer);
14987 void GtkListItem::toggle-add-mode       (GtkListItem *,
14988                                          gpointer);
14989 void GtkListItem::extend-selection      (GtkListItem *,
14990                                          GtkEnum,
14991                                          ggfloat,
14992                                          gboolean,
14993                                          gpointer);
14994 void GtkListItem::scroll-vertical       (GtkListItem *,
14995                                          GtkEnum,
14996                                          ggfloat,
14997                                          gpointer);
14998 void GtkListItem::scroll-horizontal     (GtkListItem *,
14999                                          GtkEnum,
15000                                          ggfloat,
15001                                          gpointer);
15002 </verb></tscreen>
15003
15004 <!-- ----------------------------------------------------------------- -->
15005 <sect1>GtkTreeItem
15006 <!-- ----------------------------------------------------------------- -->
15007 <p>
15008 <tscreen><verb>
15009 void GtkTreeItem::collapse      (GtkTreeItem *,
15010                                  gpointer);
15011 void GtkTreeItem::expand        (GtkTreeItem *,
15012                                  gpointer);
15013 </verb></tscreen>
15014
15015 <!-- ----------------------------------------------------------------- -->
15016 <sect1>GtkCheckMenuItem
15017 <!-- ----------------------------------------------------------------- -->
15018 <p>
15019 <tscreen><verb>
15020 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
15021                                  gpointer);
15022 </verb></tscreen>
15023
15024 <!-- ----------------------------------------------------------------- -->
15025 <sect1>GtkInputDialog
15026 <!-- ----------------------------------------------------------------- -->
15027 <p>
15028 <tscreen><verb>
15029 void GtkInputDialog::enable-device      (GtkInputDialog *,
15030                                          ggint,
15031                                          gpointer);
15032 void GtkInputDialog::disable-device     (GtkInputDialog *,
15033                                          ggint,
15034                                          gpointer);
15035 </verb></tscreen>
15036
15037 <!-- ----------------------------------------------------------------- -->
15038 <sect1>GtkColorSelection
15039 <!-- ----------------------------------------------------------------- -->
15040 <p>
15041 <tscreen><verb>
15042 void GtkColorSelection::color-changed   (GtkColorSelection *,
15043                                          gpointer);
15044 </verb></tscreen>
15045
15046 <!-- ----------------------------------------------------------------- -->
15047 <sect1>GtkStatusBar
15048 <!-- ----------------------------------------------------------------- -->
15049 <p>
15050 <tscreen><verb>
15051 void GtkStatusbar::text-pushed  (GtkStatusbar *,
15052                                  gguint,
15053                                  GtkString *,
15054                                  gpointer);
15055 void GtkStatusbar::text-popped  (GtkStatusbar *,
15056                                  gguint,
15057                                  GtkString *,
15058                                  gpointer);
15059 </verb></tscreen>
15060
15061 <!-- ----------------------------------------------------------------- -->
15062 <sect1>GtkCTree
15063 <!-- ----------------------------------------------------------------- -->
15064 <p>
15065 <tscreen><verb>
15066 void GtkCTree::tree-select-row  (GtkCTree *,
15067                                  GtkCTreeNode *,
15068                                  ggint,
15069                                  gpointer);
15070 void GtkCTree::tree-unselect-row        (GtkCTree *,
15071                                          GtkCTreeNode *,
15072                                          ggint,
15073                                          gpointer);
15074 void GtkCTree::tree-expand      (GtkCTree *,
15075                                  GtkCTreeNode *,
15076                                  gpointer);
15077 void GtkCTree::tree-collapse    (GtkCTree *,
15078                                  ggpointer,
15079                                  gpointer);
15080 void GtkCTree::tree-move        (GtkCTree *,
15081                                  GtkCTreeNode *,
15082                                  GtkCTreeNode *,
15083                                  GtkCTreeNode *,
15084                                  gpointer);
15085 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
15086                                                  GtkCTreeExpansionType,
15087                                                  gpointer);
15088 </verb></tscreen>
15089
15090 <!-- ----------------------------------------------------------------- -->
15091 <sect1>GtkCurve
15092 <!-- ----------------------------------------------------------------- -->
15093 <p>
15094 <tscreen><verb>
15095 void GtkCurve::curve-type-changed       (GtkCurve *,
15096                                          gpointer);
15097 </verb></tscreen>
15098
15099 <!-- ----------------------------------------------------------------- -->
15100 <sect1>GtkAdjustment
15101 <!-- ----------------------------------------------------------------- -->
15102 <p>
15103 <tscreen><verb>
15104 void GtkAdjustment::changed     (GtkAdjustment *,
15105                                  gpointer);
15106 void GtkAdjustment::value-changed       (GtkAdjustment *,
15107                                          gpointer);
15108 </verb></tscreen>
15109
15110 <!-- ***************************************************************** -->
15111 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
15112 <!-- ***************************************************************** -->
15113 <p>
15114 The follwing data types are passed into event handlers by GTK+. For
15115 each data type listed, the signals that use this data type are listed.
15116
15117 <itemize>
15118 <item>  GdkEvent
15119           <itemize>
15120           <item>drag_end_event
15121           </itemize>
15122
15123 <item>  GdkEventType
15124
15125 <item>  GdkEventAny
15126           <itemize>
15127           <item>delete_event
15128           <item>destroy_event
15129           <item>map_event
15130           <item>unmap_event
15131           <item>no_expose_event
15132           </itemize>
15133
15134 <item>  GdkEventExpose
15135           <itemize>
15136           <item>expose_event
15137           </itemize>
15138
15139 <item>  GdkEventNoExpose
15140
15141 <item>  GdkEventVisibility
15142
15143 <item>  GdkEventMotion
15144           <itemize>
15145           <item>motion_notify_event
15146           </itemize>
15147
15148 <item>  GdkEventButton
15149           <itemize>
15150           <item>button_press_event
15151           <item>button_release_event
15152           </itemize>
15153
15154 <item>  GdkEventKey
15155           <itemize>
15156           <item>key_press_event
15157           <item>key_release_event
15158           </itemize>
15159
15160 <item>  GdkEventCrossing
15161           <itemize>
15162           <item>enter_notify_event
15163           <item>leave_notify_event
15164           </itemize>
15165
15166 <item>  GdkEventFocus
15167           <itemize>
15168           <item>focus_in_event
15169           <item>focus_out_event
15170           </itemize>
15171
15172 <item>  GdkEventConfigure
15173           <itemize>
15174           <item>configure_event
15175           </itemize>
15176
15177 <item>  GdkEventProperty
15178           <itemize>
15179           <item>property_notify_event
15180           </itemize>
15181
15182 <item>  GdkEventSelection
15183           <itemize>
15184           <item>selection_clear_event
15185           <item>selection_request_event
15186           <item>selection_notify_event
15187           </itemize>
15188
15189 <item>  GdkEventProximity
15190           <itemize>
15191           <item>proximity_in_event
15192           <item>proximity_out_event
15193           </itemize>
15194
15195 <item>  GdkEventDragBegin
15196           <itemize>
15197           <item>drag_begin_event
15198           </itemize>
15199
15200 <item>  GdkEventDragRequest
15201           <itemize>
15202           <item>drag_request_event
15203           </itemize>
15204
15205 <item>  GdkEventDropEnter
15206           <itemize>
15207           <item>drop_enter_event
15208           </itemize>
15209
15210 <item>  GdkEventDropLeave
15211           <itemize>
15212           <item>drop_leave_event
15213           </itemize>
15214
15215 <item>  GdkEventDropDataAvailable
15216           <itemize>
15217           <item>drop_data_available_event
15218           </itemize>
15219
15220 <item>  GdkEventClient
15221           <itemize>
15222           <item>client_event
15223           </itemize>
15224
15225 <item>  GdkEventOther
15226           <itemize>
15227           <item>other_event
15228           </itemize>
15229 </itemize>
15230
15231 The data type <tt/GdkEventType/ is a special data type that is used by
15232 all the other data types as an indicator of the data type being passed
15233 to the signal handler. As you will see below, each of the event data
15234 structures has a member of this type. It is defined as an enumeration
15235 type as follows:
15236
15237 <tscreen><verb>
15238 typedef enum
15239 {
15240   GDK_NOTHING           = -1,
15241   GDK_DELETE            = 0,
15242   GDK_DESTROY           = 1,
15243   GDK_EXPOSE            = 2,
15244   GDK_MOTION_NOTIFY     = 3,
15245   GDK_BUTTON_PRESS      = 4,
15246   GDK_2BUTTON_PRESS     = 5,
15247   GDK_3BUTTON_PRESS     = 6,
15248   GDK_BUTTON_RELEASE    = 7,
15249   GDK_KEY_PRESS         = 8,
15250   GDK_KEY_RELEASE       = 9,
15251   GDK_ENTER_NOTIFY      = 10,
15252   GDK_LEAVE_NOTIFY      = 11,
15253   GDK_FOCUS_CHANGE      = 12,
15254   GDK_CONFIGURE         = 13,
15255   GDK_MAP               = 14,
15256   GDK_UNMAP             = 15,
15257   GDK_PROPERTY_NOTIFY   = 16,
15258   GDK_SELECTION_CLEAR   = 17,
15259   GDK_SELECTION_REQUEST = 18,
15260   GDK_SELECTION_NOTIFY  = 19,
15261   GDK_PROXIMITY_IN      = 20,
15262   GDK_PROXIMITY_OUT     = 21,
15263   GDK_DRAG_BEGIN        = 22,
15264   GDK_DRAG_REQUEST      = 23,
15265   GDK_DROP_ENTER        = 24,
15266   GDK_DROP_LEAVE        = 25,
15267   GDK_DROP_DATA_AVAIL   = 26,
15268   GDK_CLIENT_EVENT      = 27,
15269   GDK_VISIBILITY_NOTIFY = 28,
15270   GDK_NO_EXPOSE         = 29,
15271   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
15272 } GdkEventType;
15273 </verb></tscreen>
15274
15275 The other event type that is different from the others is
15276 <tt/GdkEvent/ itself. This is a union of all the other
15277 data types, which allows it to be cast to a specific
15278 event data type within a signal handler.
15279
15280 <!-- Just a big list for now, needs expanding upon - TRG -->
15281 So, the event data types are defined as follows:
15282
15283 <tscreen><verb>
15284 struct _GdkEventAny
15285 {
15286   GdkEventType type;
15287   GdkWindow *window;
15288   gint8 send_event;
15289 };
15290
15291 struct _GdkEventExpose
15292 {
15293   GdkEventType type;
15294   GdkWindow *window;
15295   gint8 send_event;
15296   GdkRectangle area;
15297   gint count; /* If non-zero, how many more events follow. */
15298 };
15299
15300 struct _GdkEventNoExpose
15301 {
15302   GdkEventType type;
15303   GdkWindow *window;
15304   gint8 send_event;
15305   /* XXX: does anyone need the X major_code or minor_code fields? */
15306 };
15307
15308 struct _GdkEventVisibility
15309 {
15310   GdkEventType type;
15311   GdkWindow *window;
15312   gint8 send_event;
15313   GdkVisibilityState state;
15314 };
15315
15316 struct _GdkEventMotion
15317 {
15318   GdkEventType type;
15319   GdkWindow *window;
15320   gint8 send_event;
15321   guint32 time;
15322   gdouble x;
15323   gdouble y;
15324   gdouble pressure;
15325   gdouble xtilt;
15326   gdouble ytilt;
15327   guint state;
15328   gint16 is_hint;
15329   GdkInputSource source;
15330   guint32 deviceid;
15331   gdouble x_root, y_root;
15332 };
15333
15334 struct _GdkEventButton
15335 {
15336   GdkEventType type;
15337   GdkWindow *window;
15338   gint8 send_event;
15339   guint32 time;
15340   gdouble x;
15341   gdouble y;
15342   gdouble pressure;
15343   gdouble xtilt;
15344   gdouble ytilt;
15345   guint state;
15346   guint button;
15347   GdkInputSource source;
15348   guint32 deviceid;
15349   gdouble x_root, y_root;
15350 };
15351
15352 struct _GdkEventKey
15353 {
15354   GdkEventType type;
15355   GdkWindow *window;
15356   gint8 send_event;
15357   guint32 time;
15358   guint state;
15359   guint keyval;
15360   gint length;
15361   gchar *string;
15362 };
15363
15364 struct _GdkEventCrossing
15365 {
15366   GdkEventType type;
15367   GdkWindow *window;
15368   gint8 send_event;
15369   GdkWindow *subwindow;
15370   GdkNotifyType detail;
15371 };
15372
15373 struct _GdkEventFocus
15374 {
15375   GdkEventType type;
15376   GdkWindow *window;
15377   gint8 send_event;
15378   gint16 in;
15379 };
15380
15381 struct _GdkEventConfigure
15382 {
15383   GdkEventType type;
15384   GdkWindow *window;
15385   gint8 send_event;
15386   gint16 x, y;
15387   gint16 width;
15388   gint16 height;
15389 };
15390
15391 struct _GdkEventProperty
15392 {
15393   GdkEventType type;
15394   GdkWindow *window;
15395   gint8 send_event;
15396   GdkAtom atom;
15397   guint32 time;
15398   guint state;
15399 };
15400
15401 struct _GdkEventSelection
15402 {
15403   GdkEventType type;
15404   GdkWindow *window;
15405   gint8 send_event;
15406   GdkAtom selection;
15407   GdkAtom target;
15408   GdkAtom property;
15409   guint32 requestor;
15410   guint32 time;
15411 };
15412
15413 /* This event type will be used pretty rarely. It only is important
15414    for XInput aware programs that are drawing their own cursor */
15415
15416 struct _GdkEventProximity
15417 {
15418   GdkEventType type;
15419   GdkWindow *window;
15420   gint8 send_event;
15421   guint32 time;
15422   GdkInputSource source;
15423   guint32 deviceid;
15424 };
15425
15426 struct _GdkEventDragRequest
15427 {
15428   GdkEventType type;
15429   GdkWindow *window;
15430   gint8 send_event;
15431   guint32 requestor;
15432   union {
15433     struct {
15434       guint protocol_version:4;
15435       guint sendreply:1;
15436       guint willaccept:1;
15437       guint delete_data:1; /* Do *not* delete if link is sent, only
15438                               if data is sent */
15439       guint senddata:1;
15440       guint reserved:22;
15441     } flags;
15442     glong allflags;
15443   } u;
15444   guint8 isdrop; /* This gdk event can be generated by a couple of
15445                     X events - this lets the app know whether the
15446                     drop really occurred or we just set the data */
15447
15448   GdkPoint drop_coords;
15449   gchar *data_type;
15450   guint32 timestamp;
15451 };
15452
15453 struct _GdkEventDragBegin
15454 {
15455   GdkEventType type;
15456   GdkWindow *window;
15457   gint8 send_event;
15458   union {
15459     struct {
15460       guint protocol_version:4;
15461       guint reserved:28;
15462     } flags;
15463     glong allflags;
15464   } u;
15465 };
15466
15467 struct _GdkEventDropEnter
15468 {
15469   GdkEventType type;
15470   GdkWindow *window;
15471   gint8 send_event;
15472   guint32 requestor;
15473   union {
15474     struct {
15475       guint protocol_version:4;
15476       guint sendreply:1;
15477       guint extended_typelist:1;
15478       guint reserved:26;
15479     } flags;
15480     glong allflags;
15481   } u;
15482 };
15483
15484 struct _GdkEventDropLeave
15485 {
15486   GdkEventType type;
15487   GdkWindow *window;
15488   gint8 send_event;
15489   guint32 requestor;
15490   union {
15491     struct {
15492       guint protocol_version:4;
15493       guint reserved:28;
15494     } flags;
15495     glong allflags;
15496   } u;
15497 };
15498
15499 struct _GdkEventDropDataAvailable
15500 {
15501   GdkEventType type;
15502   GdkWindow *window;
15503   gint8 send_event;
15504   guint32 requestor;
15505   union {
15506     struct {
15507       guint protocol_version:4;
15508       guint isdrop:1;
15509       guint reserved:25;
15510     } flags;
15511     glong allflags;
15512   } u;
15513   gchar *data_type; /* MIME type */
15514   gulong data_numbytes;
15515   gpointer data;
15516   guint32 timestamp;
15517   GdkPoint coords;
15518 };
15519
15520 struct _GdkEventClient
15521 {
15522   GdkEventType type;
15523   GdkWindow *window;
15524   gint8 send_event;
15525   GdkAtom message_type;
15526   gushort data_format;
15527   union {
15528     char b[20];
15529     short s[10];
15530     long l[5];
15531   } data;
15532 };
15533
15534 struct _GdkEventOther
15535 {
15536   GdkEventType type;
15537   GdkWindow *window;
15538   gint8 send_event;
15539   GdkXEvent *xevent;
15540 };
15541 </verb></tscreen>
15542
15543 <!-- ***************************************************************** -->
15544 <sect> Code Examples
15545 <!-- ***************************************************************** -->
15546 <p>
15547 Below are the code examples that are used in the above text
15548 which are not included in complete form elsewhere.
15549
15550 <!-- ----------------------------------------------------------------- -->
15551 <sect1>Tictactoe
15552 <!-- ----------------------------------------------------------------- -->
15553 <sect2>tictactoe.h
15554 <p>
15555 <tscreen><verb>
15556 /* example-start tictactoe tictactoe.h */
15557
15558 /* GTK - The GIMP Toolkit
15559  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15560  *
15561  * This library is free software; you can redistribute it and/or
15562  * modify it under the terms of the GNU Library General Public
15563  * License as published by the Free Software Foundation; either
15564  * version 2 of the License, or (at your option) any later version.
15565  *
15566  * This library is distributed in the hope that it will be useful,
15567  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15568  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15569  * Library General Public License for more details.
15570  *
15571  * You should have received a copy of the GNU Library General Public
15572  * License along with this library; if not, write to the
15573  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15574  * Boston, MA 02111-1307, USA.
15575  */
15576 #ifndef __TICTACTOE_H__
15577 #define __TICTACTOE_H__
15578
15579
15580 #include <gdk/gdk.h>
15581 #include <gtk/gtkvbox.h>
15582
15583
15584 #ifdef __cplusplus
15585 extern "C" {
15586 #endif /* __cplusplus */
15587
15588 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
15589 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
15590 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
15591
15592
15593 typedef struct _Tictactoe       Tictactoe;
15594 typedef struct _TictactoeClass  TictactoeClass;
15595
15596 struct _Tictactoe
15597 {
15598   GtkVBox vbox;
15599   
15600   GtkWidget *buttons[3][3];
15601 };
15602
15603 struct _TictactoeClass
15604 {
15605   GtkVBoxClass parent_class;
15606
15607   void (* tictactoe) (Tictactoe *ttt);
15608 };
15609
15610 guint          tictactoe_get_type        (void);
15611 GtkWidget*     tictactoe_new             (void);
15612 void           tictactoe_clear           (Tictactoe *ttt);
15613
15614 #ifdef __cplusplus
15615 }
15616 #endif /* __cplusplus */
15617
15618 #endif /* __TICTACTOE_H__ */
15619
15620 /* example-end */
15621 </verb></tscreen>
15622
15623 <!-- ----------------------------------------------------------------- -->
15624 <sect2>tictactoe.c
15625 <p>
15626 <tscreen><verb>
15627 /* example-start tictactoe tictactoe.c */
15628
15629 /* GTK - The GIMP Toolkit
15630  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15631  *
15632  * This library is free software; you can redistribute it and/or
15633  * modify it under the terms of the GNU Library General Public
15634  * License as published by the Free Software Foundation; either
15635  * version 2 of the License, or (at your option) any later version.
15636  *
15637  * This library is distributed in the hope that it will be useful,
15638  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15639  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15640  * Library General Public License for more details.
15641  *
15642  * You should have received a copy of the GNU Library General Public
15643  * License along with this library; if not, write to the
15644  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15645  * Boston, MA 02111-1307, USA.
15646  */
15647 #include "gtk/gtksignal.h"
15648 #include "gtk/gtktable.h"
15649 #include "gtk/gtktogglebutton.h"
15650 #include "tictactoe.h"
15651
15652 enum {
15653   TICTACTOE_SIGNAL,
15654   LAST_SIGNAL
15655 };
15656
15657 static void tictactoe_class_init          (TictactoeClass *klass);
15658 static void tictactoe_init                (Tictactoe      *ttt);
15659 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
15660
15661 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
15662
15663 guint
15664 tictactoe_get_type ()
15665 {
15666   static guint ttt_type = 0;
15667
15668   if (!ttt_type)
15669     {
15670       GtkTypeInfo ttt_info =
15671       {
15672         "Tictactoe",
15673         sizeof (Tictactoe),
15674         sizeof (TictactoeClass),
15675         (GtkClassInitFunc) tictactoe_class_init,
15676         (GtkObjectInitFunc) tictactoe_init,
15677         (GtkArgSetFunc) NULL,
15678         (GtkArgGetFunc) NULL
15679       };
15680
15681       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
15682     }
15683
15684   return ttt_type;
15685 }
15686
15687 static void
15688 tictactoe_class_init (TictactoeClass *class)
15689 {
15690   GtkObjectClass *object_class;
15691
15692   object_class = (GtkObjectClass*) class;
15693   
15694   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
15695                                          GTK_RUN_FIRST,
15696                                          object_class->type,
15697                                          GTK_SIGNAL_OFFSET (TictactoeClass,
15698                                                             tictactoe),
15699                                          gtk_signal_default_marshaller,
15700                                          GTK_TYPE_NONE, 0);
15701
15702
15703   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
15704
15705   class->tictactoe = NULL;
15706 }
15707
15708 static void
15709 tictactoe_init (Tictactoe *ttt)
15710 {
15711   GtkWidget *table;
15712   gint i,j;
15713   
15714   table = gtk_table_new (3, 3, TRUE);
15715   gtk_container_add (GTK_CONTAINER(ttt), table);
15716   gtk_widget_show (table);
15717
15718   for (i=0;i<3; i++)
15719     for (j=0;j<3; j++)
15720       {
15721         ttt->buttons[i][j] = gtk_toggle_button_new ();
15722         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
15723                                    i, i+1, j, j+1);
15724         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
15725                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
15726         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
15727         gtk_widget_show (ttt->buttons[i][j]);
15728       }
15729 }
15730
15731 GtkWidget*
15732 tictactoe_new ()
15733 {
15734   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
15735 }
15736
15737 void           
15738 tictactoe_clear (Tictactoe *ttt)
15739 {
15740   int i,j;
15741
15742   for (i=0;i<3;i++)
15743     for (j=0;j<3;j++)
15744       {
15745         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15746         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
15747                                      FALSE);
15748         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15749       }
15750 }
15751
15752 static void
15753 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
15754 {
15755   int i,k;
15756
15757   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15758                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15759                              { 0, 1, 2 }, { 0, 1, 2 } };
15760   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15761                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15762                              { 0, 1, 2 }, { 2, 1, 0 } };
15763
15764   int success, found;
15765
15766   for (k=0; k<8; k++)
15767     {
15768       success = TRUE;
15769       found = FALSE;
15770
15771       for (i=0;i<3;i++)
15772         {
15773           success = success &amp;&amp; 
15774             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
15775           found = found ||
15776             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
15777         }
15778       
15779       if (success &amp;&amp; found)
15780         {
15781           gtk_signal_emit (GTK_OBJECT (ttt), 
15782                            tictactoe_signals[TICTACTOE_SIGNAL]);
15783           break;
15784         }
15785     }
15786 }
15787
15788 /* example-end */
15789 </verb></tscreen>
15790
15791 <!-- ----------------------------------------------------------------- -->
15792 <sect2>ttt_test.c
15793 <p>
15794 <tscreen><verb>
15795 /* example-start tictactoe ttt_test.c */
15796
15797 #include <gtk/gtk.h>
15798 #include "tictactoe.h"
15799
15800 void
15801 win (GtkWidget *widget, gpointer data)
15802 {
15803   g_print ("Yay!\n");
15804   tictactoe_clear (TICTACTOE (widget));
15805 }
15806
15807 int 
15808 main (int argc, char *argv[])
15809 {
15810   GtkWidget *window;
15811   GtkWidget *ttt;
15812   
15813   gtk_init (&amp;argc, &amp;argv);
15814
15815   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15816   
15817   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
15818   
15819   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15820                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
15821   
15822   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15823
15824   ttt = tictactoe_new ();
15825   
15826   gtk_container_add (GTK_CONTAINER (window), ttt);
15827   gtk_widget_show (ttt);
15828
15829   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
15830                       GTK_SIGNAL_FUNC (win), NULL);
15831
15832   gtk_widget_show (window);
15833   
15834   gtk_main ();
15835   
15836   return 0;
15837 }
15838
15839 /* example-end */
15840 </verb></tscreen>
15841
15842 <!-- ----------------------------------------------------------------- -->
15843 <sect1> GtkDial
15844
15845 <!-- ----------------------------------------------------------------- -->
15846 <sect2> gtkdial.h
15847 <p>
15848 <tscreen><verb>
15849 /* example-start gtkdial gtkdial.h */
15850
15851 /* GTK - The GIMP Toolkit
15852  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15853  *
15854  * This library is free software; you can redistribute it and/or
15855  * modify it under the terms of the GNU Library General Public
15856  * License as published by the Free Software Foundation; either
15857  * version 2 of the License, or (at your option) any later version.
15858  *
15859  * This library is distributed in the hope that it will be useful,
15860  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15861  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15862  * Library General Public License for more details.
15863  *
15864  * You should have received a copy of the GNU Library General Public
15865  * License along with this library; if not, write to the
15866  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15867  * Boston, MA 02111-1307, USA.
15868  */
15869 #ifndef __GTK_DIAL_H__
15870 #define __GTK_DIAL_H__
15871
15872
15873 #include <gdk/gdk.h>
15874 #include <gtk/gtkadjustment.h>
15875 #include <gtk/gtkwidget.h>
15876
15877
15878 #ifdef __cplusplus
15879 extern "C" {
15880 #endif /* __cplusplus */
15881
15882
15883 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
15884 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
15885 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
15886
15887
15888 typedef struct _GtkDial        GtkDial;
15889 typedef struct _GtkDialClass   GtkDialClass;
15890
15891 struct _GtkDial
15892 {
15893   GtkWidget widget;
15894
15895   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
15896   guint policy : 2;
15897
15898   /* Button currently pressed or 0 if none */
15899   guint8 button;
15900
15901   /* Dimensions of dial components */
15902   gint radius;
15903   gint pointer_width;
15904
15905   /* ID of update timer, or 0 if none */
15906   guint32 timer;
15907
15908   /* Current angle */
15909   gfloat angle;
15910
15911   /* Old values from adjustment stored so we know when something changes */
15912   gfloat old_value;
15913   gfloat old_lower;
15914   gfloat old_upper;
15915
15916   /* The adjustment object that stores the data for this dial */
15917   GtkAdjustment *adjustment;
15918 };
15919
15920 struct _GtkDialClass
15921 {
15922   GtkWidgetClass parent_class;
15923 };
15924
15925
15926 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
15927 guint          gtk_dial_get_type               (void);
15928 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
15929 void           gtk_dial_set_update_policy      (GtkDial      *dial,
15930                                                 GtkUpdateType  policy);
15931
15932 void           gtk_dial_set_adjustment         (GtkDial      *dial,
15933                                                 GtkAdjustment *adjustment);
15934 #ifdef __cplusplus
15935 }
15936 #endif /* __cplusplus */
15937
15938
15939 #endif /* __GTK_DIAL_H__ */
15940 /* example-end */
15941 </verb></tscreen>
15942
15943 <!-- ----------------------------------------------------------------- -->
15944 <sect2> gtkdial.c
15945 <p>
15946 <tscreen><verb>
15947 /* example-start gtkdial gtkdial.c */
15948
15949 /* GTK - The GIMP Toolkit
15950  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15951  *
15952  * This library is free software; you can redistribute it and/or
15953  * modify it under the terms of the GNU Library General Public
15954  * License as published by the Free Software Foundation; either
15955  * version 2 of the License, or (at your option) any later version.
15956  *
15957  * This library is distributed in the hope that it will be useful,
15958  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15959  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15960  * Library General Public License for more details.
15961  *
15962  * You should have received a copy of the GNU Library General Public
15963  * License along with this library; if not, write to the
15964  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15965  * Boston, MA 02111-1307, USA.
15966  */
15967 #include <math.h>
15968 #include <stdio.h>
15969 #include <gtk/gtkmain.h>
15970 #include <gtk/gtksignal.h>
15971
15972 #include "gtkdial.h"
15973
15974 #define SCROLL_DELAY_LENGTH  300
15975 #define DIAL_DEFAULT_SIZE 100
15976
15977 /* Forward declarations */
15978
15979 static void gtk_dial_class_init               (GtkDialClass    *klass);
15980 static void gtk_dial_init                     (GtkDial         *dial);
15981 static void gtk_dial_destroy                  (GtkObject        *object);
15982 static void gtk_dial_realize                  (GtkWidget        *widget);
15983 static void gtk_dial_size_request             (GtkWidget      *widget,
15984                                                GtkRequisition *requisition);
15985 static void gtk_dial_size_allocate            (GtkWidget     *widget,
15986                                                GtkAllocation *allocation);
15987 static gint gtk_dial_expose                   (GtkWidget        *widget,
15988                                                 GdkEventExpose   *event);
15989 static gint gtk_dial_button_press             (GtkWidget        *widget,
15990                                                 GdkEventButton   *event);
15991 static gint gtk_dial_button_release           (GtkWidget        *widget,
15992                                                 GdkEventButton   *event);
15993 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
15994                                                 GdkEventMotion   *event);
15995 static gint gtk_dial_timer                    (GtkDial         *dial);
15996
15997 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
15998 static void gtk_dial_update                   (GtkDial *dial);
15999 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
16000                                                 gpointer          data);
16001 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
16002                                                 gpointer          data);
16003
16004 /* Local data */
16005
16006 static GtkWidgetClass *parent_class = NULL;
16007
16008 guint
16009 gtk_dial_get_type ()
16010 {
16011   static guint dial_type = 0;
16012
16013   if (!dial_type)
16014     {
16015       GtkTypeInfo dial_info =
16016       {
16017         "GtkDial",
16018         sizeof (GtkDial),
16019         sizeof (GtkDialClass),
16020         (GtkClassInitFunc) gtk_dial_class_init,
16021         (GtkObjectInitFunc) gtk_dial_init,
16022         (GtkArgSetFunc) NULL,
16023         (GtkArgGetFunc) NULL,
16024       };
16025
16026       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
16027     }
16028
16029   return dial_type;
16030 }
16031
16032 static void
16033 gtk_dial_class_init (GtkDialClass *class)
16034 {
16035   GtkObjectClass *object_class;
16036   GtkWidgetClass *widget_class;
16037
16038   object_class = (GtkObjectClass*) class;
16039   widget_class = (GtkWidgetClass*) class;
16040
16041   parent_class = gtk_type_class (gtk_widget_get_type ());
16042
16043   object_class->destroy = gtk_dial_destroy;
16044
16045   widget_class->realize = gtk_dial_realize;
16046   widget_class->expose_event = gtk_dial_expose;
16047   widget_class->size_request = gtk_dial_size_request;
16048   widget_class->size_allocate = gtk_dial_size_allocate;
16049   widget_class->button_press_event = gtk_dial_button_press;
16050   widget_class->button_release_event = gtk_dial_button_release;
16051   widget_class->motion_notify_event = gtk_dial_motion_notify;
16052 }
16053
16054 static void
16055 gtk_dial_init (GtkDial *dial)
16056 {
16057   dial->button = 0;
16058   dial->policy = GTK_UPDATE_CONTINUOUS;
16059   dial->timer = 0;
16060   dial->radius = 0;
16061   dial->pointer_width = 0;
16062   dial->angle = 0.0;
16063   dial->old_value = 0.0;
16064   dial->old_lower = 0.0;
16065   dial->old_upper = 0.0;
16066   dial->adjustment = NULL;
16067 }
16068
16069 GtkWidget*
16070 gtk_dial_new (GtkAdjustment *adjustment)
16071 {
16072   GtkDial *dial;
16073
16074   dial = gtk_type_new (gtk_dial_get_type ());
16075
16076   if (!adjustment)
16077     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0,
16078                                                       0.0, 0.0, 0.0);
16079
16080   gtk_dial_set_adjustment (dial, adjustment);
16081
16082   return GTK_WIDGET (dial);
16083 }
16084
16085 static void
16086 gtk_dial_destroy (GtkObject *object)
16087 {
16088   GtkDial *dial;
16089
16090   g_return_if_fail (object != NULL);
16091   g_return_if_fail (GTK_IS_DIAL (object));
16092
16093   dial = GTK_DIAL (object);
16094
16095   if (dial->adjustment)
16096     gtk_object_unref (GTK_OBJECT (dial->adjustment));
16097
16098   if (GTK_OBJECT_CLASS (parent_class)->destroy)
16099     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
16100 }
16101
16102 GtkAdjustment*
16103 gtk_dial_get_adjustment (GtkDial *dial)
16104 {
16105   g_return_val_if_fail (dial != NULL, NULL);
16106   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
16107
16108   return dial->adjustment;
16109 }
16110
16111 void
16112 gtk_dial_set_update_policy (GtkDial      *dial,
16113                              GtkUpdateType  policy)
16114 {
16115   g_return_if_fail (dial != NULL);
16116   g_return_if_fail (GTK_IS_DIAL (dial));
16117
16118   dial->policy = policy;
16119 }
16120
16121 void
16122 gtk_dial_set_adjustment (GtkDial      *dial,
16123                           GtkAdjustment *adjustment)
16124 {
16125   g_return_if_fail (dial != NULL);
16126   g_return_if_fail (GTK_IS_DIAL (dial));
16127
16128   if (dial->adjustment)
16129     {
16130       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment),
16131                                      (gpointer) dial);
16132       gtk_object_unref (GTK_OBJECT (dial->adjustment));
16133     }
16134
16135   dial->adjustment = adjustment;
16136   gtk_object_ref (GTK_OBJECT (dial->adjustment));
16137
16138   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
16139                       (GtkSignalFunc) gtk_dial_adjustment_changed,
16140                       (gpointer) dial);
16141   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
16142                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
16143                       (gpointer) dial);
16144
16145   dial->old_value = adjustment->value;
16146   dial->old_lower = adjustment->lower;
16147   dial->old_upper = adjustment->upper;
16148
16149   gtk_dial_update (dial);
16150 }
16151
16152 static void
16153 gtk_dial_realize (GtkWidget *widget)
16154 {
16155   GtkDial *dial;
16156   GdkWindowAttr attributes;
16157   gint attributes_mask;
16158
16159   g_return_if_fail (widget != NULL);
16160   g_return_if_fail (GTK_IS_DIAL (widget));
16161
16162   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
16163   dial = GTK_DIAL (widget);
16164
16165   attributes.x = widget->allocation.x;
16166   attributes.y = widget->allocation.y;
16167   attributes.width = widget->allocation.width;
16168   attributes.height = widget->allocation.height;
16169   attributes.wclass = GDK_INPUT_OUTPUT;
16170   attributes.window_type = GDK_WINDOW_CHILD;
16171   attributes.event_mask = gtk_widget_get_events (widget) | 
16172     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
16173     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
16174     GDK_POINTER_MOTION_HINT_MASK;
16175   attributes.visual = gtk_widget_get_visual (widget);
16176   attributes.colormap = gtk_widget_get_colormap (widget);
16177
16178   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
16179   widget->window = gdk_window_new (widget->parent->window,
16180                                    &amp;attributes,
16181                                    attributes_mask);
16182
16183   widget->style = gtk_style_attach (widget->style, widget->window);
16184
16185   gdk_window_set_user_data (widget->window, widget);
16186
16187   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
16188 }
16189
16190 static void 
16191 gtk_dial_size_request (GtkWidget      *widget,
16192                        GtkRequisition *requisition)
16193 {
16194   requisition->width = DIAL_DEFAULT_SIZE;
16195   requisition->height = DIAL_DEFAULT_SIZE;
16196 }
16197
16198 static void
16199 gtk_dial_size_allocate (GtkWidget     *widget,
16200                         GtkAllocation *allocation)
16201 {
16202   GtkDial *dial;
16203
16204   g_return_if_fail (widget != NULL);
16205   g_return_if_fail (GTK_IS_DIAL (widget));
16206   g_return_if_fail (allocation != NULL);
16207
16208   widget->allocation = *allocation;
16209   dial = GTK_DIAL (widget);
16210
16211   if (GTK_WIDGET_REALIZED (widget))
16212     {
16213
16214       gdk_window_move_resize (widget->window,
16215                               allocation->x, allocation->y,
16216                               allocation->width, allocation->height);
16217
16218     }
16219   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
16220   dial->pointer_width = dial->radius / 5;
16221 }
16222
16223 static gint
16224 gtk_dial_expose (GtkWidget      *widget,
16225                  GdkEventExpose *event)
16226 {
16227   GtkDial *dial;
16228   GdkPoint points[3];
16229   gdouble s,c;
16230   gdouble theta;
16231   gint xc, yc;
16232   gint tick_length;
16233   gint i;
16234
16235   g_return_val_if_fail (widget != NULL, FALSE);
16236   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16237   g_return_val_if_fail (event != NULL, FALSE);
16238
16239   if (event->count > 0)
16240     return FALSE;
16241   
16242   dial = GTK_DIAL (widget);
16243
16244   gdk_window_clear_area (widget->window,
16245                          0, 0,
16246                          widget->allocation.width,
16247                          widget->allocation.height);
16248
16249   xc = widget->allocation.width/2;
16250   yc = widget->allocation.height/2;
16251
16252   /* Draw ticks */
16253
16254   for (i=0; i<25; i++)
16255     {
16256       theta = (i*M_PI/18. - M_PI/6.);
16257       s = sin(theta);
16258       c = cos(theta);
16259
16260       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
16261       
16262       gdk_draw_line (widget->window,
16263                      widget->style->fg_gc[widget->state],
16264                      xc + c*(dial->radius - tick_length),
16265                      yc - s*(dial->radius - tick_length),
16266                      xc + c*dial->radius,
16267                      yc - s*dial->radius);
16268     }
16269
16270   /* Draw pointer */
16271
16272   s = sin(dial->angle);
16273   c = cos(dial->angle);
16274
16275
16276   points[0].x = xc + s*dial->pointer_width/2;
16277   points[0].y = yc + c*dial->pointer_width/2;
16278   points[1].x = xc + c*dial->radius;
16279   points[1].y = yc - s*dial->radius;
16280   points[2].x = xc - s*dial->pointer_width/2;
16281   points[2].y = yc - c*dial->pointer_width/2;
16282
16283   gtk_draw_polygon (widget->style,
16284                     widget->window,
16285                     GTK_STATE_NORMAL,
16286                     GTK_SHADOW_OUT,
16287                     points, 3,
16288                     TRUE);
16289   
16290   return FALSE;
16291 }
16292
16293 static gint
16294 gtk_dial_button_press (GtkWidget      *widget,
16295                        GdkEventButton *event)
16296 {
16297   GtkDial *dial;
16298   gint dx, dy;
16299   double s, c;
16300   double d_parallel;
16301   double d_perpendicular;
16302
16303   g_return_val_if_fail (widget != NULL, FALSE);
16304   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16305   g_return_val_if_fail (event != NULL, FALSE);
16306
16307   dial = GTK_DIAL (widget);
16308
16309   /* Determine if button press was within pointer region - we 
16310      do this by computing the parallel and perpendicular distance of
16311      the point where the mouse was pressed from the line passing through
16312      the pointer */
16313   
16314   dx = event->x - widget->allocation.width / 2;
16315   dy = widget->allocation.height / 2 - event->y;
16316   
16317   s = sin(dial->angle);
16318   c = cos(dial->angle);
16319   
16320   d_parallel = s*dy + c*dx;
16321   d_perpendicular = fabs(s*dx - c*dy);
16322   
16323   if (!dial->button &amp;&amp;
16324       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
16325       (d_parallel > - dial->pointer_width))
16326     {
16327       gtk_grab_add (widget);
16328
16329       dial->button = event->button;
16330
16331       gtk_dial_update_mouse (dial, event->x, event->y);
16332     }
16333
16334   return FALSE;
16335 }
16336
16337 static gint
16338 gtk_dial_button_release (GtkWidget      *widget,
16339                           GdkEventButton *event)
16340 {
16341   GtkDial *dial;
16342
16343   g_return_val_if_fail (widget != NULL, FALSE);
16344   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16345   g_return_val_if_fail (event != NULL, FALSE);
16346
16347   dial = GTK_DIAL (widget);
16348
16349   if (dial->button == event->button)
16350     {
16351       gtk_grab_remove (widget);
16352
16353       dial->button = 0;
16354
16355       if (dial->policy == GTK_UPDATE_DELAYED)
16356         gtk_timeout_remove (dial->timer);
16357       
16358       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
16359           (dial->old_value != dial->adjustment->value))
16360         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16361                                  "value_changed");
16362     }
16363
16364   return FALSE;
16365 }
16366
16367 static gint
16368 gtk_dial_motion_notify (GtkWidget      *widget,
16369                          GdkEventMotion *event)
16370 {
16371   GtkDial *dial;
16372   GdkModifierType mods;
16373   gint x, y, mask;
16374
16375   g_return_val_if_fail (widget != NULL, FALSE);
16376   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16377   g_return_val_if_fail (event != NULL, FALSE);
16378
16379   dial = GTK_DIAL (widget);
16380
16381   if (dial->button != 0)
16382     {
16383       x = event->x;
16384       y = event->y;
16385
16386       if (event->is_hint || (event->window != widget->window))
16387         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
16388
16389       switch (dial->button)
16390         {
16391         case 1:
16392           mask = GDK_BUTTON1_MASK;
16393           break;
16394         case 2:
16395           mask = GDK_BUTTON2_MASK;
16396           break;
16397         case 3:
16398           mask = GDK_BUTTON3_MASK;
16399           break;
16400         default:
16401           mask = 0;
16402           break;
16403         }
16404
16405       if (mods &amp; mask)
16406         gtk_dial_update_mouse (dial, x,y);
16407     }
16408
16409   return FALSE;
16410 }
16411
16412 static gint
16413 gtk_dial_timer (GtkDial *dial)
16414 {
16415   g_return_val_if_fail (dial != NULL, FALSE);
16416   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
16417
16418   if (dial->policy == GTK_UPDATE_DELAYED)
16419     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16420                              "value_changed");
16421
16422   return FALSE;
16423 }
16424
16425 static void
16426 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
16427 {
16428   gint xc, yc;
16429   gfloat old_value;
16430
16431   g_return_if_fail (dial != NULL);
16432   g_return_if_fail (GTK_IS_DIAL (dial));
16433
16434   xc = GTK_WIDGET(dial)->allocation.width / 2;
16435   yc = GTK_WIDGET(dial)->allocation.height / 2;
16436
16437   old_value = dial->adjustment->value;
16438   dial->angle = atan2(yc-y, x-xc);
16439
16440   if (dial->angle < -M_PI/2.)
16441     dial->angle += 2*M_PI;
16442
16443   if (dial->angle < -M_PI/6)
16444     dial->angle = -M_PI/6;
16445
16446   if (dial->angle > 7.*M_PI/6.)
16447     dial->angle = 7.*M_PI/6.;
16448
16449   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
16450     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
16451
16452   if (dial->adjustment->value != old_value)
16453     {
16454       if (dial->policy == GTK_UPDATE_CONTINUOUS)
16455         {
16456           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16457                                    "value_changed");
16458         }
16459       else
16460         {
16461           gtk_widget_draw (GTK_WIDGET(dial), NULL);
16462
16463           if (dial->policy == GTK_UPDATE_DELAYED)
16464             {
16465               if (dial->timer)
16466                 gtk_timeout_remove (dial->timer);
16467
16468               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
16469                                              (GtkFunction) gtk_dial_timer,
16470                                              (gpointer) dial);
16471             }
16472         }
16473     }
16474 }
16475
16476 static void
16477 gtk_dial_update (GtkDial *dial)
16478 {
16479   gfloat new_value;
16480   
16481   g_return_if_fail (dial != NULL);
16482   g_return_if_fail (GTK_IS_DIAL (dial));
16483
16484   new_value = dial->adjustment->value;
16485   
16486   if (new_value < dial->adjustment->lower)
16487     new_value = dial->adjustment->lower;
16488
16489   if (new_value > dial->adjustment->upper)
16490     new_value = dial->adjustment->upper;
16491
16492   if (new_value != dial->adjustment->value)
16493     {
16494       dial->adjustment->value = new_value;
16495       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16496     }
16497
16498   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 
16499                               4.*M_PI/3. /
16500     (dial->adjustment->upper - dial->adjustment->lower);
16501
16502   gtk_widget_draw (GTK_WIDGET(dial), NULL);
16503 }
16504
16505 static void
16506 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
16507                               gpointer       data)
16508 {
16509   GtkDial *dial;
16510
16511   g_return_if_fail (adjustment != NULL);
16512   g_return_if_fail (data != NULL);
16513
16514   dial = GTK_DIAL (data);
16515
16516   if ((dial->old_value != adjustment->value) ||
16517       (dial->old_lower != adjustment->lower) ||
16518       (dial->old_upper != adjustment->upper))
16519     {
16520       gtk_dial_update (dial);
16521
16522       dial->old_value = adjustment->value;
16523       dial->old_lower = adjustment->lower;
16524       dial->old_upper = adjustment->upper;
16525     }
16526 }
16527
16528 static void
16529 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
16530                                     gpointer       data)
16531 {
16532   GtkDial *dial;
16533
16534   g_return_if_fail (adjustment != NULL);
16535   g_return_if_fail (data != NULL);
16536
16537   dial = GTK_DIAL (data);
16538
16539   if (dial->old_value != adjustment->value)
16540     {
16541       gtk_dial_update (dial);
16542
16543       dial->old_value = adjustment->value;
16544     }
16545 }
16546 /* example-end */
16547 </verb></tscreen>
16548
16549 <!-- ----------------------------------------------------------------- -->
16550 <sect1> Scribble
16551 <p>
16552 <tscreen><verb>
16553 /* example-start scribble-simple scribble-simple.c */
16554
16555 /* GTK - The GIMP Toolkit
16556  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16557  *
16558  * This library is free software; you can redistribute it and/or
16559  * modify it under the terms of the GNU Library General Public
16560  * License as published by the Free Software Foundation; either
16561  * version 2 of the License, or (at your option) any later version.
16562  *
16563  * This library is distributed in the hope that it will be useful,
16564  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16565  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16566  * Library General Public License for more details.
16567  *
16568  * You should have received a copy of the GNU Library General Public
16569  * License along with this library; if not, write to the
16570  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16571  * Boston, MA 02111-1307, USA.
16572  */
16573
16574 #include <gtk/gtk.h>
16575
16576 /* Backing pixmap for drawing area */
16577 static GdkPixmap *pixmap = NULL;
16578
16579 /* Create a new backing pixmap of the appropriate size */
16580 static gint
16581 configure_event (GtkWidget *widget, GdkEventConfigure *event)
16582 {
16583   if (pixmap)
16584     gdk_pixmap_unref(pixmap);
16585
16586   pixmap = gdk_pixmap_new(widget->window,
16587                           widget->allocation.width,
16588                           widget->allocation.height,
16589                           -1);
16590   gdk_draw_rectangle (pixmap,
16591                       widget->style->white_gc,
16592                       TRUE,
16593                       0, 0,
16594                       widget->allocation.width,
16595                       widget->allocation.height);
16596
16597   return TRUE;
16598 }
16599
16600 /* Redraw the screen from the backing pixmap */
16601 static gint
16602 expose_event (GtkWidget *widget, GdkEventExpose *event)
16603 {
16604   gdk_draw_pixmap(widget->window,
16605                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
16606                   pixmap,
16607                   event->area.x, event->area.y,
16608                   event->area.x, event->area.y,
16609                   event->area.width, event->area.height);
16610
16611   return FALSE;
16612 }
16613
16614 /* Draw a rectangle on the screen */
16615 static void
16616 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
16617 {
16618   GdkRectangle update_rect;
16619
16620   update_rect.x = x - 5;
16621   update_rect.y = y - 5;
16622   update_rect.width = 10;
16623   update_rect.height = 10;
16624   gdk_draw_rectangle (pixmap,
16625                       widget->style->black_gc,
16626                       TRUE,
16627                       update_rect.x, update_rect.y,
16628                       update_rect.width, update_rect.height);
16629   gtk_widget_draw (widget, &amp;update_rect);
16630 }
16631
16632 static gint
16633 button_press_event (GtkWidget *widget, GdkEventButton *event)
16634 {
16635   if (event->button == 1 &amp;&amp; pixmap != NULL)
16636     draw_brush (widget, event->x, event->y);
16637
16638   return TRUE;
16639 }
16640
16641 static gint
16642 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
16643 {
16644   int x, y;
16645   GdkModifierType state;
16646
16647   if (event->is_hint)
16648     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
16649   else
16650     {
16651       x = event->x;
16652       y = event->y;
16653       state = event->state;
16654     }
16655     
16656   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
16657     draw_brush (widget, x, y);
16658   
16659   return TRUE;
16660 }
16661
16662 void
16663 quit ()
16664 {
16665   gtk_exit (0);
16666 }
16667
16668 int
16669 main (int argc, char *argv[])
16670 {
16671   GtkWidget *window;
16672   GtkWidget *drawing_area;
16673   GtkWidget *vbox;
16674
16675   GtkWidget *button;
16676
16677   gtk_init (&amp;argc, &amp;argv);
16678
16679   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16680   gtk_widget_set_name (window, "Test Input");
16681
16682   vbox = gtk_vbox_new (FALSE, 0);
16683   gtk_container_add (GTK_CONTAINER (window), vbox);
16684   gtk_widget_show (vbox);
16685
16686   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16687                       GTK_SIGNAL_FUNC (quit), NULL);
16688
16689   /* Create the drawing area */
16690
16691   drawing_area = gtk_drawing_area_new ();
16692   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
16693   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16694
16695   gtk_widget_show (drawing_area);
16696
16697   /* Signals used to handle backing pixmap */
16698
16699   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
16700                       (GtkSignalFunc) expose_event, NULL);
16701   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
16702                       (GtkSignalFunc) configure_event, NULL);
16703
16704   /* Event signals */
16705
16706   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
16707                       (GtkSignalFunc) motion_notify_event, NULL);
16708   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
16709                       (GtkSignalFunc) button_press_event, NULL);
16710
16711   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16712                          | GDK_LEAVE_NOTIFY_MASK
16713                          | GDK_BUTTON_PRESS_MASK
16714                          | GDK_POINTER_MOTION_MASK
16715                          | GDK_POINTER_MOTION_HINT_MASK);
16716
16717   /* .. And a quit button */
16718   button = gtk_button_new_with_label ("Quit");
16719   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16720
16721   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
16722                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
16723                              GTK_OBJECT (window));
16724   gtk_widget_show (button);
16725
16726   gtk_widget_show (window);
16727
16728   gtk_main ();
16729
16730   return 0;
16731 }
16732 /* example-end */
16733 </verb></tscreen>
16734
16735 <!-- ***************************************************************** -->
16736 <sect> List Widget
16737 <!-- ***************************************************************** -->
16738 <p>
16739 NOTE: The GtkList widget has been superseded by the GtkCList
16740 widget. It is detailed here just for completeness.
16741
16742 The GtkList widget is designed to act as a vertical container for
16743 widgets that should be of the type GtkListItem.
16744
16745 A GtkList widget has its own window to receive events and its own
16746 background color which is usually white. As it is directly derived
16747 from a GtkContainer it can be treated as such by using the
16748 GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
16749 this. One should already be familiar with the usage of a GList and
16750 its related functions g_list_*() to be able to use the GtkList widget
16751 to it full extent.
16752
16753 There is one field inside the structure definition of the GtkList
16754 widget that will be of greater interest to us, this is:
16755
16756 <tscreen><verb>
16757 struct _GtkList
16758 {
16759   ...
16760   GList *selection;
16761   guint selection_mode;
16762   ...
16763 }; 
16764 </verb></tscreen>
16765
16766 The selection field of a GtkList points to a linked list of all items
16767 that are currently selected, or NULL if the selection is empty.  So to
16768 learn about the current selection we read the GTK_LIST()->selection
16769 field, but do not modify it since the internal fields are maintained
16770 by the gtk_list_*() functions.
16771
16772 The selection_mode of the GtkList determines the selection facilities
16773 of a GtkList and therefore the contents of the GTK_LIST()->selection
16774 field. The selection_mode may be one of the following:
16775
16776 <itemize>
16777 <item> GTK_SELECTION_SINGLE - The selection is either NULL
16778                         or contains a GList pointer
16779                         for a single selected item.
16780
16781 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list
16782                         contains no widgets or insensitive
16783                         ones only, otherwise it contains
16784                         a GList pointer for one GList
16785                         structure, and therefore exactly
16786                         one list item.
16787
16788 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list
16789                         items are selected or a GList pointer
16790                         for the first selected item. That
16791                         in turn points to a GList structure
16792                         for the second selected item and so
16793                         on.
16794
16795 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
16796 </itemize>
16797
16798 The default is GTK_SELECTION_MULTIPLE.
16799
16800 <!-- ----------------------------------------------------------------- -->
16801 <sect1> Signals
16802 <p>
16803 <tscreen><verb>
16804 void selection_changed( GtkList *list );
16805 </verb></tscreen>
16806
16807 This signal will be invoked whenever the selection field of a GtkList
16808 has changed. This happens when a child of the GtkList got selected or
16809 deselected.
16810
16811 <tscreen><verb>
16812 void select_child( GtkList   *list,
16813                    GtkWidget *child);
16814 </verb></tscreen>
16815
16816 This signal is invoked when a child of the GtkList is about to get
16817 selected. This happens mainly on calls to gtk_list_select_item(),
16818 gtk_list_select_child(), button presses and sometimes indirectly
16819 triggered on some else occasions where children get added to or
16820 removed from the GtkList.
16821
16822 <tscreen><verb>
16823 void unselect_child( GtkList   *list,
16824                      GtkWidget *child );
16825 </verb></tscreen>
16826
16827 This signal is invoked when a child of the GtkList is about to get
16828 deselected. This happens mainly on calls to gtk_list_unselect_item(),
16829 gtk_list_unselect_child(), button presses and sometimes indirectly
16830 triggered on some else occasions where children get added to or
16831 removed from the GtkList.
16832
16833 <!-- ----------------------------------------------------------------- -->
16834 <sect1> Functions
16835 <p>
16836 <tscreen><verb>
16837 guint gtk_list_get_type( void );
16838 </verb></tscreen>
16839
16840 Returns the `GtkList' type identifier.
16841
16842 <tscreen><verb>
16843 GtkWidget *gtk_list_new( void );
16844 </verb></tscreen>
16845
16846 Create a new GtkList object. The new widget is returned as a pointer
16847 to a GtkWidget object. NULL is returned on failure.
16848
16849 <tscreen><verb>
16850 void gtk_list_insert_items( GtkList *list,
16851                             GList   *items,
16852                             gint     position );
16853 </verb></tscreen>
16854
16855 Insert list items into the list, starting at <tt/position/.
16856 <tt/items/ is a doubly linked list where each nodes data pointer is
16857 expected to point to a newly created GtkListItem.  The GList nodes of
16858 <tt/items/ are taken over by the list.
16859
16860 <tscreen><verb>
16861 void gtk_list_append_items( GtkList *list,
16862                             GList   *items);
16863 </verb></tscreen>
16864
16865 Insert list items just like gtk_list_insert_items() at the end of the
16866 list. The GList nodes of <tt/items/ are taken over by the list.
16867
16868 <tscreen><verb>
16869 void gtk_list_prepend_items( GtkList *list,
16870                              GList   *items);
16871 </verb></tscreen>
16872
16873 Insert list items just like gtk_list_insert_items() at the very
16874 beginning of the list. The GList nodes of <tt/items/ are taken over by
16875 the list.
16876
16877 <tscreen><verb>
16878 void gtk_list_remove_items( GtkList *list,
16879                             GList   *items);
16880 </verb></tscreen>
16881
16882 Remove list items from the list. <tt/items/ is a doubly linked list
16883 where each nodes data pointer is expected to point to a direct child
16884 of list. It is the callers responsibility to make a call to
16885 g_list_free(items) afterwards. Also the caller has to destroy the list
16886 items himself.
16887
16888 <tscreen><verb>
16889 void gtk_list_clear_items( GtkList *list,
16890                            gint start,
16891                            gint end );
16892 </verb></tscreen>
16893
16894 Remove and destroy list items from the list. A widget is affected if
16895 its current position within the list is in the range specified by
16896 <tt/start/ and <tt/end/.
16897
16898 <tscreen><verb>
16899 void gtk_list_select_item( GtkList *list,
16900                            gint     item );
16901 </verb></tscreen>
16902
16903 Invoke the select_child signal for a list item specified through its
16904 current position within the list.
16905
16906 <tscreen><verb>
16907 void gtk_list_unselect_item( GtkList *list,
16908                              gint     item);
16909 </verb></tscreen>
16910
16911 Invoke the unselect_child signal for a list item specified through its
16912 current position within the list.
16913
16914 <tscreen><verb>
16915 void gtk_list_select_child( GtkList *list,
16916                             GtkWidget *child);
16917 </verb></tscreen>
16918
16919 Invoke the select_child signal for the specified child.
16920
16921 <tscreen><verb>
16922 void gtk_list_unselect_child( GtkList   *list,
16923                               GtkWidget *child);
16924 </verb></tscreen>
16925
16926 Invoke the unselect_child signal for the specified child.
16927
16928 <tscreen><verb>
16929 gint gtk_list_child_position( GtkList *list,
16930                               GtkWidget *child);
16931 </verb></tscreen>
16932
16933 Return the position of <tt/child/ within the list. "-1" is returned on
16934 failure.
16935
16936 <tscreen><verb>
16937 void gtk_list_set_selection_mode( GtkList         *list,
16938                                   GtkSelectionMode mode );
16939 </verb></tscreen>
16940
16941 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
16942 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
16943 GTK_SELECTION_EXTENDED.
16944
16945 <tscreen><verb>
16946 GtkList *GTK_LIST( gpointer obj );
16947 </verb></tscreen>
16948
16949 Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
16950 more info.
16951
16952 <tscreen><verb>
16953 GtkListClass *GTK_LIST_CLASS( gpointer class);
16954 </verb></tscreen>
16955
16956 Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
16957 for more info.
16958
16959 <tscreen><verb>
16960 gint GTK_IS_LIST( gpointer obj);
16961 </verb></tscreen>
16962
16963 Determine if a generic pointer refers to a `GtkList' object. *Note
16964 Standard Macros::, for more info.
16965
16966 <!-- ----------------------------------------------------------------- -->
16967 <sect1> Example
16968 <p>
16969 Following is an example program that will print out the changes of the
16970 selection of a GtkList, and lets you "arrest" list items into a prison
16971 by selecting them with the rightmost mouse button.
16972
16973 <tscreen><verb>
16974 /* example-start list list.c */
16975
16976 /* Include the gtk+ header files
16977  * Include stdio.h, we need that for the printf() function
16978  */
16979 #include        <gtk/gtk.h>
16980 #include        <stdio.h>
16981
16982 /* This is our data identification string to store
16983  * data in list items
16984  */
16985 const gchar *list_item_data_key="list_item_data";
16986
16987
16988 /* prototypes for signal handler that we are going to connect
16989  * to the GtkList widget
16990  */
16991 static void  sigh_print_selection( GtkWidget *gtklist,
16992                                    gpointer   func_data);
16993
16994 static void  sigh_button_event( GtkWidget      *gtklist,
16995                                 GdkEventButton *event,
16996                                 GtkWidget      *frame );
16997
16998
16999 /* Main function to set up the user interface */
17000
17001 gint main (int    argc,
17002            gchar *argv[])
17003 {                                  
17004     GtkWidget *separator;
17005     GtkWidget *window;
17006     GtkWidget *vbox;
17007     GtkWidget *scrolled_window;
17008     GtkWidget *frame;
17009     GtkWidget *gtklist;
17010     GtkWidget *button;
17011     GtkWidget *list_item;
17012     GList *dlist;
17013     guint i;
17014     gchar buffer[64];
17015     
17016     
17017     /* Initialize gtk+ (and subsequently gdk) */
17018
17019     gtk_init(&amp;argc, &amp;argv);
17020     
17021     
17022     /* Create a window to put all the widgets in
17023      * connect gtk_main_quit() to the "destroy" event of
17024      * the window to handle window manager close-window-events
17025      */
17026     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
17027     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
17028     gtk_signal_connect(GTK_OBJECT(window),
17029                        "destroy",
17030                        GTK_SIGNAL_FUNC(gtk_main_quit),
17031                        NULL);
17032     
17033     
17034     /* Inside the window we need a box to arrange the widgets
17035      * vertically */
17036     vbox=gtk_vbox_new(FALSE, 5);
17037     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
17038     gtk_container_add(GTK_CONTAINER(window), vbox);
17039     gtk_widget_show(vbox);
17040     
17041     /* This is the scrolled window to put the GtkList widget inside */
17042     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
17043     gtk_widget_set_usize(scrolled_window, 250, 150);
17044     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
17045     gtk_widget_show(scrolled_window);
17046     
17047     /* Create the GtkList widget.
17048      * Connect the sigh_print_selection() signal handler
17049      * function to the "selection_changed" signal of the GtkList
17050      * to print out the selected items each time the selection
17051      * has changed */
17052     gtklist=gtk_list_new();
17053     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
17054                                            gtklist);
17055     gtk_widget_show(gtklist);
17056     gtk_signal_connect(GTK_OBJECT(gtklist),
17057                        "selection_changed",
17058                        GTK_SIGNAL_FUNC(sigh_print_selection),
17059                        NULL);
17060     
17061     /* We create a "Prison" to put a list item in ;) */
17062     frame=gtk_frame_new("Prison");
17063     gtk_widget_set_usize(frame, 200, 50);
17064     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
17065     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
17066     gtk_container_add(GTK_CONTAINER(vbox), frame);
17067     gtk_widget_show(frame);
17068     
17069     /* Connect the sigh_button_event() signal handler to the GtkList
17070      * which will handle the "arresting" of list items
17071      */
17072     gtk_signal_connect(GTK_OBJECT(gtklist),
17073                        "button_release_event",
17074                        GTK_SIGNAL_FUNC(sigh_button_event),
17075                        frame);
17076     
17077     /* Create a separator */
17078     separator=gtk_hseparator_new();
17079     gtk_container_add(GTK_CONTAINER(vbox), separator);
17080     gtk_widget_show(separator);
17081     
17082     /* Finally create a button and connect its "clicked" signal
17083      * to the destruction of the window */
17084     button=gtk_button_new_with_label("Close");
17085     gtk_container_add(GTK_CONTAINER(vbox), button);
17086     gtk_widget_show(button);
17087     gtk_signal_connect_object(GTK_OBJECT(button),
17088                               "clicked",
17089                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
17090                               GTK_OBJECT(window));
17091     
17092     
17093     /* Now we create 5 list items, each having its own
17094      * label and add them to the GtkList using gtk_container_add()
17095      * Also we query the text string from the label and
17096      * associate it with the list_item_data_key for each list item
17097      */
17098     for (i=0; i<5; i++) {
17099         GtkWidget       *label;
17100         gchar           *string;
17101         
17102         sprintf(buffer, "ListItemContainer with Label #%d", i);
17103         label=gtk_label_new(buffer);
17104         list_item=gtk_list_item_new();
17105         gtk_container_add(GTK_CONTAINER(list_item), label);
17106         gtk_widget_show(label);
17107         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
17108         gtk_widget_show(list_item);
17109         gtk_label_get(GTK_LABEL(label), &amp;string);
17110         gtk_object_set_data(GTK_OBJECT(list_item),
17111                             list_item_data_key,
17112                             string);
17113     }
17114     /* Here, we are creating another 5 labels, this time
17115      * we use gtk_list_item_new_with_label() for the creation
17116      * we can't query the text string from the label because
17117      * we don't have the labels pointer and therefore
17118      * we just associate the list_item_data_key of each
17119      * list item with the same text string.
17120      * For adding of the list items we put them all into a doubly
17121      * linked list (GList), and then add them by a single call to
17122      * gtk_list_append_items().
17123      * Because we use g_list_prepend() to put the items into the
17124      * doubly linked list, their order will be descending (instead
17125      * of ascending when using g_list_append())
17126      */
17127     dlist=NULL;
17128     for (; i<10; i++) {
17129         sprintf(buffer, "List Item with Label %d", i);
17130         list_item=gtk_list_item_new_with_label(buffer);
17131         dlist=g_list_prepend(dlist, list_item);
17132         gtk_widget_show(list_item);
17133         gtk_object_set_data(GTK_OBJECT(list_item),
17134                             list_item_data_key,
17135                             "ListItem with integrated Label");
17136     }
17137     gtk_list_append_items(GTK_LIST(gtklist), dlist);
17138     
17139     /* Finally we want to see the window, don't we? ;) */
17140     gtk_widget_show(window);
17141     
17142     /* Fire up the main event loop of gtk */
17143     gtk_main();
17144     
17145     /* We get here after gtk_main_quit() has been called which
17146      * happens if the main window gets destroyed
17147      */
17148     return(0);
17149 }
17150
17151 /* This is the signal handler that got connected to button
17152  * press/release events of the GtkList
17153  */
17154 void sigh_button_event( GtkWidget      *gtklist,
17155                         GdkEventButton *event,
17156                         GtkWidget      *frame )
17157 {
17158     /* We only do something if the third (rightmost mouse button
17159      * was released
17160      */
17161     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
17162         event->button==3) {
17163         GList           *dlist, *free_list;
17164         GtkWidget       *new_prisoner;
17165         
17166         /* Fetch the currently selected list item which
17167          * will be our next prisoner ;)
17168          */
17169         dlist=GTK_LIST(gtklist)->selection;
17170         if (dlist)
17171                 new_prisoner=GTK_WIDGET(dlist->data);
17172         else
17173                 new_prisoner=NULL;
17174         
17175         /* Look for already imprisoned list items, we
17176          * will put them back into the list.
17177          * Remember to free the doubly linked list that
17178          * gtk_container_children() returns
17179          */
17180         dlist=gtk_container_children(GTK_CONTAINER(frame));
17181         free_list=dlist;
17182         while (dlist) {
17183             GtkWidget       *list_item;
17184             
17185             list_item=dlist->data;
17186             
17187             gtk_widget_reparent(list_item, gtklist);
17188             
17189             dlist=dlist->next;
17190         }
17191         g_list_free(free_list);
17192         
17193         /* If we have a new prisoner, remove him from the
17194          * GtkList and put him into the frame "Prison".
17195          * We need to unselect the item first.
17196          */
17197         if (new_prisoner) {
17198             GList   static_dlist;
17199             
17200             static_dlist.data=new_prisoner;
17201             static_dlist.next=NULL;
17202             static_dlist.prev=NULL;
17203             
17204             gtk_list_unselect_child(GTK_LIST(gtklist),
17205                                     new_prisoner);
17206             gtk_widget_reparent(new_prisoner, frame);
17207         }
17208     }
17209 }
17210
17211 /* This is the signal handler that gets called if GtkList
17212  * emits the "selection_changed" signal
17213  */
17214 void sigh_print_selection( GtkWidget *gtklist,
17215                            gpointer   func_data)
17216 {
17217     GList   *dlist;
17218     
17219     /* Fetch the doubly linked list of selected items
17220      * of the GtkList, remember to treat this as read-only!
17221      */
17222     dlist=GTK_LIST(gtklist)->selection;
17223     
17224     /* If there are no selected items there is nothing more
17225      * to do than just telling the user so
17226      */
17227     if (!dlist) {
17228         g_print("Selection cleared\n");
17229         return;
17230     }
17231     /* Ok, we got a selection and so we print it
17232      */
17233     g_print("The selection is a ");
17234     
17235     /* Get the list item from the doubly linked list
17236      * and then query the data associated with list_item_data_key.
17237      * We then just print it */
17238     while (dlist) {
17239         GtkObject       *list_item;
17240         gchar           *item_data_string;
17241         
17242         list_item=GTK_OBJECT(dlist->data);
17243         item_data_string=gtk_object_get_data(list_item,
17244                                              list_item_data_key);
17245         g_print("%s ", item_data_string);
17246         
17247         dlist=dlist->next;
17248     }
17249     g_print("\n");
17250 }
17251 /* example-end */
17252 </verb></tscreen>
17253
17254 <!-- ----------------------------------------------------------------- -->
17255 <sect1> List Item Widget
17256 <p>
17257 The GtkListItem widget is designed to act as a container holding up to
17258 one child, providing functions for selection/deselection just like the
17259 GtkList widget requires them for its children.
17260
17261 A GtkListItem has its own window to receive events and has its own
17262 background color which is usually white.
17263
17264 As it is directly derived from a GtkItem it can be treated as such by
17265 using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
17266 this. Usually a GtkListItem just holds a label to identify e.g. a
17267 filename within a GtkList -- therefore the convenience function
17268 gtk_list_item_new_with_label() is provided. The same effect can be
17269 achieved by creating a GtkLabel on its own, setting its alignment to
17270 xalign=0 and yalign=0.5 with a subsequent container addition to the
17271 GtkListItem.
17272
17273 As one is not forced to add a GtkLabel to a GtkListItem, you could
17274 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
17275
17276 <!-- ----------------------------------------------------------------- -->
17277 <sect1> Signals
17278 <p>
17279 A GtkListItem does not create new signals on its own, but inherits
17280 the signals of a GtkItem. *Note GtkItem::, for more info.
17281
17282 <!-- ----------------------------------------------------------------- -->
17283 <sect1> Functions
17284 <p>
17285 <tscreen><verb>
17286 guint gtk_list_item_get_type( void );
17287 </verb></tscreen>
17288
17289 Returns the `GtkListItem' type identifier.
17290
17291 <tscreen><verb>
17292 GtkWidget *gtk_list_item_new( void );
17293 </verb></tscreen>
17294
17295 Create a new GtkListItem object. The new widget is returned as a
17296 pointer to a GtkWidget object. NULL is returned on failure.
17297
17298 <tscreen><verb>
17299 GtkWidget *gtk_list_item_new_with_label( gchar *label );
17300 </verb></tscreen>
17301
17302 Create a new GtkListItem object, having a single GtkLabel as the sole
17303 child. The new widget is returned as a pointer to a GtkWidget
17304 object. NULL is returned on failure.
17305
17306 <tscreen><verb>
17307 void gtk_list_item_select( GtkListItem *list_item );
17308 </verb></tscreen>
17309
17310 This function is basically a wrapper around a call to gtk_item_select
17311 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
17312 GtkItem::, for more info.
17313
17314 <tscreen><verb>
17315 void gtk_list_item_deselect( GtkListItem *list_item );
17316 </verb></tscreen>
17317
17318 This function is basically a wrapper around a call to
17319 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
17320 signal.  *Note GtkItem::, for more info.
17321
17322 <tscreen><verb>
17323 GtkListItem *GTK_LIST_ITEM( gpointer obj );
17324 </verb></tscreen>
17325
17326 Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
17327 more info.
17328
17329 <tscreen><verb>
17330 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
17331 </verb></tscreen>
17332
17333 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
17334 for more info.
17335
17336 <tscreen><verb>
17337 gint GTK_IS_LIST_ITEM( gpointer obj );
17338 </verb></tscreen>
17339
17340 Determine if a generic pointer refers to a `GtkListItem' object.
17341 *Note Standard Macros::, for more info.
17342  
17343 <!-- ----------------------------------------------------------------- -->
17344 <sect1> Example
17345 <p>
17346 Please see the GtkList example on this, which covers the usage of a
17347 GtkListItem as well.
17348
17349
17350 </article>