]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
- Complete documentation of Label widget API - New sections for the
[~andy/gtk] / docs / tutorial / gtk_tut.sgml
1 <!doctype linuxdoc system>
2
3 <!-- This is the tutorial marked up in SGML
4      (just to show how to write a comment)
5 -->
6
7 <article>
8 <title>GTK v1.1 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>January 31th, 1999
15
16 <!-- ***************************************************************** -->
17 <sect>Introduction
18 <!-- ***************************************************************** -->
19 <p>
20 GTK (GIMP Toolkit) was originally developed as a toolkit for the GIMP
21 (General Image Manipulation Program).  GTK is built on top of GDK
22 (GIMP Drawing Kit) which is basically a wrapper around the Xlib
23 functions.  It's called the GIMP toolkit because it was originally
24 written for developing the GIMP, but has now been used in several free
25 software projects.  The authors are:
26 <itemize>
27 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
28                            name="petm@xcf.berkeley.edu"></tt>
29 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
30                            name="spencer@xcf.berkeley.edu"></tt>
31 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
32                            name="jmacd@xcf.berkeley.edu"></tt>
33 </itemize>
34
35 GTK is essentially an object oriented application programmers
36 interface (API). Although written completely in C, it is implemented
37 using the idea of classes and callback functions (pointers to
38 functions).
39
40 There is also a third component called glib which contains a few
41 replacements for some standard calls, as well as some additional
42 functions for handling linked lists etc. The replacement functions are
43 used to increase GTK's portability, as some of the functions
44 implemented here are not available or are nonstandard on other unixes
45 such as g_strerror(). Some also contain enhancements to the libc
46 versions, such as g_malloc that has enhanced debugging utilities.
47
48 This tutorial is an attempt to document as much as possible of GTK, it
49 is by no means complete. This tutorial assumes a good understanding of
50 C, and how to create C programs. It would be a great benefit for the
51 reader to have previous X programming experience, but it shouldn't be
52 necessary. If you are learning GTK as your first widget set, please
53 comment on how you found this tutorial, and what you had trouble
54 with. Note that there is also a C++ API for GTK (GTK--) in the works,
55 so if you prefer to use C++, you should look into this
56 instead. There are also Objective C, ADA, Guile and other language
57 bindings available, but I don't follow these.
58
59 This document is a 'work in progress'. Please look for updates on 
60 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
61 name="http://www.gtk.org/">.
62
63 I would very much like to hear of any problems you have learning GTK
64 from this document, and would appreciate input as to how it may be
65 improved. Please see the section on <ref id="sec_Contributing"
66 name="Contributing"> for further information.
67
68 <!-- ***************************************************************** -->
69 <sect>Getting Started
70 <!-- ***************************************************************** -->
71
72 <p>
73 The first thing to do of course, is download the GTK source and
74 install it. You can always get the latest version from ftp.gtk.org in
75 /pub/gtk. You can also view other sources of GTK information on
76 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
77 name="http://www.gtk.org/">. GTK uses GNU autoconf for configuration.
78 Once untar'd, type ./configure --help to see a list of options.
79
80 Th GTK source distribution also contains the complete source to all of
81 the examples used in this tutorial, along with Makefiles to aid
82 compilation.
83
84 To begin our introduction to GTK, we'll start with the simplest
85 program possible. This program will create a 200x200 pixel window and
86 has no way of exiting except to be killed using the shell.
87
88 <tscreen><verb>
89 /* example-start base base.c */
90
91 #include <gtk/gtk.h>
92
93 int main( int   argc,
94           char *argv[] )
95 {
96     GtkWidget *window;
97     
98     gtk_init (&amp;argc, &amp;argv);
99     
100     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
101     gtk_widget_show  (window);
102     
103     gtk_main ();
104     
105     return(0);
106 }
107 /* example-end */
108 </verb></tscreen>
109
110 You can compile the above program with gcc using:
111 <tscreen><verb>
112 gcc base.c -o base `gtk-config --cflags --libs`
113 </verb></tscreen>
114
115 The meaning of the unusual compilation options is explained below.
116
117 All programs will of course include gtk/gtk.h which declares the
118 variables, functions, structures etc. that will be used in your GTK
119 application.
120
121 The next line:
122
123 <tscreen><verb>
124 gtk_init (&amp;argc, &amp;argv);
125 </verb></tscreen>
126
127 calls the function gtk_init(gint *argc, gchar ***argv) which will be
128 called in all GTK applications. This sets up a few things for us such
129 as the default visual and color map and then proceeds to call
130 gdk_init(gint *argc, gchar ***argv). This function initializes the
131 library for use, sets up default signal handlers, and checks the
132 arguments passed to your application on the command line, looking for
133 one of the following:
134
135 <itemize>
136 <item> <tt/--gtk-module/
137 <item> <tt/--g-fatal-warnings/
138 <item> <tt/--gtk-debug/
139 <item> <tt/--gtk-no-debug/
140 <item> <tt/--gdk-debug/
141 <item> <tt/--gdk-no-debug/
142 <item> <tt/--display/
143 <item> <tt/--sync/
144 <item> <tt/--no-xshm/
145 <item> <tt/--name/
146 <item> <tt/--class/
147 </itemize>
148
149 It removes these from the argument list, leaving anything it does not
150 recognize for your application to parse or ignore. This creates a set
151 of standard arguments accepted by all GTK applications.
152
153 The next two lines of code create and display a window.
154
155 <tscreen><verb>
156   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
157   gtk_widget_show (window);
158 </verb></tscreen>
159
160 The GTK_WINDOW_TOPLEVEL argument specifies that we want the window to
161 undergo window manager decoration and placement. Rather than create a
162 window of 0x0 size, a window without children is set to 200x200 by
163 default so you can still manipulate it.
164
165 The gtk_widget_show() function lets GTK know that we are done setting
166 the attributes of this widget, and that it can display it.
167
168 The last line enters the GTK main processing loop.
169
170 <tscreen><verb>
171   gtk_main ();
172 </verb></tscreen>
173
174 gtk_main() is another call you will see in every GTK application.
175 When control reaches this point, GTK will sleep waiting for X events
176 (such as button or key presses), timeouts, or file IO notifications to
177 occur. In our simple example however, events are ignored.
178
179 <!-- ----------------------------------------------------------------- -->
180 <sect1>Hello World in GTK
181 <p>
182 Now for a program with a widget (a button).  It's the classic
183 hello world a la GTK.
184
185 <tscreen><verb>
186 /* example-start helloworld helloworld.c */
187
188 #include <gtk/gtk.h>
189
190 /* This is a callback function. The data arguments are ignored
191  * in this example. More on callbacks below. */
192 void hello( GtkWidget *widget,
193             gpointer   data )
194 {
195     g_print ("Hello World\n");
196 }
197
198 gint delete_event( GtkWidget *widget,
199                    GdkEvent  *event,
200                    gpointer   data )
201 {
202     /* If you return FALSE in the "delete_event" signal handler,
203      * GTK will emit the "destroy" signal. Returning TRUE means
204      * you don't want the window to be destroyed.
205      * This is useful for popping up 'are you sure you want to quit?'
206      * type dialogs. */
207
208     g_print ("delete event occurred\n");
209
210     /* Change TRUE to FALSE and the main window will be destroyed with
211      * a "delete_event". */
212
213     return(TRUE);
214 }
215
216 /* Another callback */
217 void destroy( GtkWidget *widget,
218               gpointer   data )
219 {
220     gtk_main_quit();
221 }
222
223 int main( int   argc,
224           char *argv[] )
225 {
226     /* GtkWidget is the storage type for widgets */
227     GtkWidget *window;
228     GtkWidget *button;
229     
230     /* This is called in all GTK applications. Arguments are parsed
231      * from the command line and are returned to the application. */
232     gtk_init(&amp;argc, &amp;argv);
233     
234     /* create a new window */
235     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
236     
237     /* When the window is given the "delete_event" signal (this is given
238      * by the window manager, usually by the 'close' option, or on the
239      * titlebar), we ask it to call the delete_event () function
240      * as defined above. The data passed to the callback
241      * function is NULL and is ignored in the callback function. */
242     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
243                         GTK_SIGNAL_FUNC (delete_event), NULL);
244     
245     /* Here we connect the "destroy" event to a signal handler.  
246      * This event occurs when we call gtk_widget_destroy() on the window,
247      * or if we return 'FALSE' in the "delete_event" callback. */
248     gtk_signal_connect (GTK_OBJECT (window), "destroy",
249                         GTK_SIGNAL_FUNC (destroy), NULL);
250     
251     /* Sets the border width of the window. */
252     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
253     
254     /* Creates a new button with the label "Hello World". */
255     button = gtk_button_new_with_label ("Hello World");
256     
257     /* When the button receives the "clicked" signal, it will call the
258      * function hello() passing it NULL as its argument.  The hello()
259      * function is defined above. */
260     gtk_signal_connect (GTK_OBJECT (button), "clicked",
261                         GTK_SIGNAL_FUNC (hello), NULL);
262     
263     /* This will cause the window to be destroyed by calling
264      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
265      * signal could come from here, or the window manager. */
266     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
267                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
268                                GTK_OBJECT (window));
269     
270     /* This packs the button into the window (a gtk container). */
271     gtk_container_add (GTK_CONTAINER (window), button);
272     
273     /* The final step is to display this newly created widget. */
274     gtk_widget_show (button);
275     
276     /* and the window */
277     gtk_widget_show (window);
278     
279     /* All GTK applications must have a gtk_main(). Control ends here
280      * and waits for an event to occur (like a key press or
281      * mouse event). */
282     gtk_main ();
283     
284     return(0);
285 }
286 /* example-end */
287 </verb></tscreen>
288
289 <!-- ----------------------------------------------------------------- -->
290 <sect1>Compiling Hello World
291 <p>
292 To compile use:
293
294 <tscreen><verb>
295 gcc -Wall -g helloworld.c -o helloworld `gtk-config --cflags` \
296     `gtk-config --libs`
297 </verb></tscreen>
298
299 This uses the program <tt>gtk-config</>, which comes with gtk. This
300 program 'knows' what compiler switches are needed to compile programs
301 that use gtk. <tt>gtk-config --cflags</> will output a list of include
302 directories for the compiler to look in, and <tt>gtk-config --libs</>
303 will output the list of libraries for the compiler to link with and
304 the directories to find them in. In the aboce example they could have
305 been combined into a single instance, such as
306 `gtk-config --cflags --libs`.
307
308 Note that the type of single quote used in the compile command above
309 is significant.
310
311 The libraries that are usually linked in are:
312 <itemize>
313 <item>The GTK library (-lgtk), the widget library, based on top of GDK.
314 <item>The GDK library (-lgdk), the Xlib wrapper.
315 <item>The gmodule library (-lgmodule), which is used to load run time
316 extensions.
317 <item>The glib library (-lglib), containing miscellaneous functions, only
318 g_print() is used in this particular example. GTK is built on top
319 of glib so you will always require this library. See the section on 
320 <ref id="sec_glib" name="glib"> for details.
321 <item>The Xlib library (-lX11) which is used by GDK.
322 <item>The Xext library (-lXext). This contains code for shared memory
323 pixmaps and other X extensions.
324 <item>The math library (-lm). This is used by GTK for various purposes.
325 </itemize>
326
327 <!-- ----------------------------------------------------------------- -->
328 <sect1>Theory of Signals and Callbacks
329 <p>
330 Before we look in detail at <em>helloworld</em>, we'll discuss signals
331 and callbacks. GTK is an event driven toolkit, which means it will
332 sleep in gtk_main until an event occurs and control is passed to the
333 appropriate function.
334
335 This passing of control is done using the idea of "signals". When an
336 event occurs, such as the press of a mouse button, the appropriate
337 signal will be "emitted" by the widget that was pressed.  This is how
338 GTK does most of its useful work. There are a set of signals that all
339 widgets inherit, such as "destroy", and there are signals that are
340 widget specific, such as "toggled" on a toggle button.
341
342 To make a button perform an action, we set up a signal handler to
343 catch these signals and call the appropriate function. This is done by
344 using a function such as:
345
346 <tscreen><verb>
347 gint gtk_signal_connect( GtkObject     *object,
348                          gchar         *name,
349                          GtkSignalFunc  func,
350                          gpointer       func_data );
351 </verb></tscreen>
352
353 Where the first argument is the widget which will be emitting the
354 signal, and the second, the name of the signal you wish to catch. The
355 third is the function you wish to be called when it is caught, and the
356 fourth, the data you wish to have passed to this function.
357
358 The function specified in the third argument is called a "callback
359 function", and should generally be of the form:
360
361 <tscreen><verb>
362 void callback_func( GtkWidget *widget,
363                     gpointer   callback_data );
364 </verb></tscreen>
365
366 Where the first argument will be a pointer to the widget that emitted
367 the signal, and the second, a pointer to the data given as the last
368 argument to the gtk_signal_connect() function as shown above.
369
370 Note that the above form for a signal callback function declaration is
371 only a general guide, as some widget specific signals generate
372 different calling parameters. For example, the GtkCList "select_row"
373 signal provides both row and column parameters.
374
375 Another call used in the <em>helloworld</em> example, is:
376
377 <tscreen><verb>
378 gint gtk_signal_connect_object( GtkObject     *object,
379                                 gchar         *name,
380                                 GtkSignalFunc  func,
381                                 GtkObject     *slot_object );
382 </verb></tscreen>
383
384 gtk_signal_connect_object() is the same as gtk_signal_connect() except
385 that the callback function only uses one argument, a pointer to a GTK
386 object. So when using this function to connect signals, the callback
387 should be of the form:
388
389 <tscreen><verb>
390 void callback_func( GtkObject *object );
391 </verb></tscreen>
392
393 Where the object is usually a widget. We usually don't setup callbacks
394 for gtk_signal_connect_object however. They are usually used to call a
395 GTK function that accepts a single widget or object as an argument, as
396 is the case in our <em>helloworld</em> example.
397
398 The purpose of having two functions to connect signals is simply to
399 allow the callbacks to have a different number of arguments. Many
400 functions in the GTK library accept only a single GtkWidget pointer as
401 an argument, so you want to use the gtk_signal_connect_object() for
402 these, whereas for your functions, you may need to have additional
403 data supplied to the callbacks.
404
405 <!-- ----------------------------------------------------------------- -->
406 <sect1>Events
407 <p>
408 In addition to the signal mechanism described above, there are a set
409 of <em>events</em> that reflect the X event mechanism. Callbacks may
410 also be attached to these events. These events are:
411
412 <itemize>
413 <item> event
414 <item> button_press_event
415 <item> button_release_event
416 <item> motion_notify_event
417 <item> delete_event
418 <item> destroy_event
419 <item> expose_event
420 <item> key_press_event
421 <item> key_release_event
422 <item> enter_notify_event
423 <item> leave_notify_event
424 <item> configure_event
425 <item> focus_in_event
426 <item> focus_out_event
427 <item> map_event
428 <item> unmap_event
429 <item> property_notify_event
430 <item> selection_clear_event
431 <item> selection_request_event
432 <item> selection_notify_event
433 <item> proximity_in_event
434 <item> proximity_out_event
435 <item> drag_begin_event
436 <item> drag_request_event
437 <item> drag_end_event
438 <item> drop_enter_event
439 <item> drop_leave_event
440 <item> drop_data_available_event
441 <item> other_event
442 </itemize>
443
444 In order to connect a callback function to one of these events, you
445 use the function gtk_signal_connect, as described above, using one of
446 the above event names as the <tt/name/ parameter. The callback
447 function for events has a slightly different form than that for
448 signals:
449
450 <tscreen><verb>
451 void callback_func( GtkWidget *widget,
452                     GdkEvent  *event,
453                     gpointer   callback_data );
454 </verb></tscreen>
455
456 GdkEvent is a C <tt/union/ structure whose type will depend upon which
457 of the above events has occurred. In order for us to tell which event
458 has been issued each of the possible alternatives has a <tt/type/
459 parameter which reflects the event being issued. The other components
460 of the event structure will depend upon the type of the
461 event. Possible values for the type are:
462
463 <tscreen><verb>
464   GDK_NOTHING
465   GDK_DELETE
466   GDK_DESTROY
467   GDK_EXPOSE
468   GDK_MOTION_NOTIFY
469   GDK_BUTTON_PRESS
470   GDK_2BUTTON_PRESS
471   GDK_3BUTTON_PRESS
472   GDK_BUTTON_RELEASE
473   GDK_KEY_PRESS
474   GDK_KEY_RELEASE
475   GDK_ENTER_NOTIFY
476   GDK_LEAVE_NOTIFY
477   GDK_FOCUS_CHANGE
478   GDK_CONFIGURE
479   GDK_MAP
480   GDK_UNMAP
481   GDK_PROPERTY_NOTIFY
482   GDK_SELECTION_CLEAR
483   GDK_SELECTION_REQUEST
484   GDK_SELECTION_NOTIFY
485   GDK_PROXIMITY_IN
486   GDK_PROXIMITY_OUT
487   GDK_DRAG_BEGIN
488   GDK_DRAG_REQUEST
489   GDK_DROP_ENTER
490   GDK_DROP_LEAVE
491   GDK_DROP_DATA_AVAIL
492   GDK_CLIENT_EVENT
493   GDK_VISIBILITY_NOTIFY
494   GDK_NO_EXPOSE
495   GDK_OTHER_EVENT       /* Deprecated, use filters instead */
496 </verb></tscreen>
497
498 So, to connect a callback function to one of these events we would use
499 something like:
500
501 <tscreen><verb>
502 gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
503                     GTK_SIGNAL_FUNC(button_press_callback), 
504                         NULL);
505 </verb></tscreen>
506
507 This assumes that <tt/button/ is a GtkButton widget. Now, when the
508 mouse is over the button and a mouse button is pressed, the function
509 <tt/button_press_callback/ will be called. This function may be
510 declared as:
511
512 <tscreen><verb>
513 static gint button_press_event (GtkWidget      *widget, 
514                                 GdkEventButton *event,
515                                 gpointer        data);
516 </verb></tscreen>
517
518 Note that we can declare the second argument as type
519 <tt/GdkEventButton/ as we know what type of event will occur for this
520 function to be called.
521
522 The value returned from this function indicates whether the event
523 should be propagated further by the GTK event handling
524 mechanism. Returning TRUE indicates that the event has been handled,
525 and that it should not propagate further. Returning FALSE continues
526 the normal event handling.  See the section on
527 <ref id="sec_Adv_Events_and_Signals"
528 name="Advanced Event and Signal Handling"> for more details on this
529 propagation process.
530
531 For details on the GdkEvent data types, see the appendix entitled
532 <ref id="sec_GDK_Event_Types" name="GDK Event Types">.
533
534 <!-- ----------------------------------------------------------------- -->
535 <sect1>Stepping Through Hello World
536 <p>
537 Now that we know the theory behind this, lets clarify by walking through 
538 the example <em>helloworld</em> program.
539
540 Here is the callback function that will be called when the button is
541 "clicked". We ignore both the widget and the data in this example, but
542 it is not hard to do things with them. The next example will use the
543 data argument to tell us which button was pressed.
544
545 <tscreen><verb>
546 void hello( GtkWidget *widget,
547             gpointer   data )
548 {
549     g_print ("Hello World\n");
550 }
551 </verb></tscreen>
552
553 The next callback is a bit special. The "delete_event" occurs when the
554 window manager sends this event to the application. We have a choice
555 here as to what to do about these events. We can ignore them, make
556 some sort of response, or simply quit the application.
557
558 The value you return in this callback lets GTK know what action to
559 take.  By returning TRUE, we let it know that we don't want to have
560 the "destroy" signal emitted, keeping our application running. By
561 returning FALSE, we ask that "destroy" is emitted, which in turn will
562 call our "destroy" signal handler.
563
564 <tscreen><verb>
565 gint delete_event( GtkWidget *widget,
566                    GdkEvent  *event,
567                    gpointer   data )
568 {
569     g_print ("delete event occurred\n");
570
571     return (TRUE); 
572 }
573 </verb></tscreen>
574
575 Here is another callback function which causes the program to quit by
576 calling gtk_main_quit(). This function tells GTK that it is to exit
577 from gtk_main when control is returned to it.
578
579 <tscreen><verb>
580 void destroy( GtkWidget *widget,
581               gpointer   data )
582 {
583     gtk_main_quit ();
584 }
585 </verb></tscreen>
586
587 I assume you know about the main() function... yes, as with other
588 applications, all GTK applications will also have one of these.
589
590 <tscreen><verb>
591 int main( int   argc,
592           char *argv[] )
593 {
594 </verb></tscreen>
595
596 This next part, declares a pointer to a structure of type
597 GtkWidget. These are used below to create a window and a button.
598
599 <tscreen><verb>
600     GtkWidget *window;
601     GtkWidget *button;
602 </verb></tscreen>
603
604 Here is our gtk_init again. As before, this initializes the toolkit,
605 and parses the arguments found on the command line. Any argument it
606 recognizes from the command line, it removes from the list, and
607 modifies argc and argv to make it look like they never existed,
608 allowing your application to parse the remaining arguments.
609
610 <tscreen><verb>
611     gtk_init (&amp;argc, &amp;argv);
612 </verb></tscreen>
613
614 Create a new window. This is fairly straight forward. Memory is
615 allocated for the GtkWidget *window structure so it now points to a
616 valid structure. It sets up a new window, but it is not displayed
617 until we call gtk_widget_show(window) near the end of our program.
618
619 <tscreen><verb>
620     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
621 </verb></tscreen>
622
623 Here is an example of connecting a signal handler to an object, in
624 this case, the window. Here, the "destroy" signal is caught. This is
625 emitted when we use the window manager to kill the window (and we
626 return FALSE in the "delete_event" handler), or when we use the
627 gtk_widget_destroy() call passing in the window widget as the object
628 to destroy. By setting this up, we handle both cases with a single
629 call. Here, it just calls the destroy() function defined above with a
630 NULL argument, which quits GTK for us.
631
632 The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform type
633 casting and checking for us, as well as aid the readability of the
634 code.
635
636 <tscreen><verb>
637     gtk_signal_connect (GTK_OBJECT (window), "destroy",
638                         GTK_SIGNAL_FUNC (destroy), NULL);
639 </verb></tscreen>
640
641 This next function is used to set an attribute of a container object.
642 This just sets the window so it has a blank area along the inside of
643 it 10 pixels wide where no widgets will go. There are other similar
644 functions which we will look at in the section on
645 <ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
646
647 And again, GTK_CONTAINER is a macro to perform type casting.
648
649 <tscreen><verb>
650     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
651 </verb></tscreen>
652
653 This call creates a new button. It allocates space for a new GtkWidget
654 structure in memory, initializes it, and makes the button pointer
655 point to it. It will have the label "Hello World" on it when
656 displayed.
657
658 <tscreen><verb>
659     button = gtk_button_new_with_label ("Hello World");
660 </verb></tscreen>
661
662 Here, we take this button, and make it do something useful. We attach
663 a signal handler to it so when it emits the "clicked" signal, our
664 hello() function is called. The data is ignored, so we simply pass in
665 NULL to the hello() callback function. Obviously, the "clicked" signal
666 is emitted when we click the button with our mouse pointer.
667
668 <tscreen><verb>
669     gtk_signal_connect (GTK_OBJECT (button), "clicked",
670                         GTK_SIGNAL_FUNC (hello), NULL);
671 </verb></tscreen>
672
673 We are also going to use this button to exit our program. This will
674 illustrate how the "destroy" signal may come from either the window
675 manager, or our program. When the button is "clicked", same as above,
676 it calls the first hello() callback function, and then this one in the
677 order they are set up. You may have as many callback functions as you
678 need, and all will be executed in the order you connected
679 them. Because the gtk_widget_destroy() function accepts only a
680 GtkWidget *widget as an argument, we use the
681 gtk_signal_connect_object() function here instead of straight
682 gtk_signal_connect().
683
684 <tscreen><verb>
685     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
686                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
687                                GTK_OBJECT (window));
688 </verb></tscreen>
689
690 This is a packing call, which will be explained in depth later on. But
691 it is fairly easy to understand. It simply tells GTK that the button
692 is to be placed in the window where it will be displayed. Note that a
693 GTK container can only contain one widget. There are other widgets,
694 that are described later, which are designed to layout multiple
695 widgets in various ways.
696  
697 <tscreen><verb>
698     gtk_container_add (GTK_CONTAINER (window), button);
699 </verb></tscreen>
700
701 Now we have everything set up the way we want it to be. With all the
702 signal handlers in place, and the button placed in the window where it
703 should be, we ask GTK to "show" the widgets on the screen. The window
704 widget is shown last so the whole window will pop up at once rather
705 than seeing the window pop up, and then the button form inside of
706 it. Although with such a simple example, you'd never notice.
707
708 <tscreen><verb>
709     gtk_widget_show (button);
710
711     gtk_widget_show (window);
712 </verb></tscreen>
713
714 And of course, we call gtk_main() which waits for events to come from
715 the X server and will call on the widgets to emit signals when these
716 events come.
717
718 <tscreen><verb>
719     gtk_main ();
720 </verb></tscreen>
721
722 And the final return. Control returns here after gtk_quit() is called.
723
724 <tscreen><verb>
725     return 0;
726 </verb></tscreen>
727
728 Now, when we click the mouse button on a GTK button, the widget emits
729 a "clicked" signal. In order for us to use this information, our
730 program sets up a signal handler to catch that signal, which
731 dispatches the function of our choice. In our example, when the button
732 we created is "clicked", the hello() function is called with a NULL
733 argument, and then the next handler for this signal is called. This
734 calls the gtk_widget_destroy() function, passing it the window widget
735 as its argument, destroying the window widget. This causes the window
736 to emit the "destroy" signal, which is caught, and calls our destroy()
737 callback function, which simply exits GTK.
738
739 Another course of events, is to use the window manager to kill the
740 window. This will cause the "delete_event" to be emitted. This will
741 call our "delete_event" handler. If we return TRUE here, the window
742 will be left as is and nothing will happen. Returning FALSE will cause
743 GTK to emit the "destroy" signal which of course, calls the "destroy"
744 callback, exiting GTK.
745
746 Note that these signals are not the same as the Unix system signals,
747 and are not implemented using them, although the terminology is almost
748 identical.
749
750 <!-- ***************************************************************** -->
751 <sect>Moving On
752 <!-- ***************************************************************** -->
753
754 <!-- ----------------------------------------------------------------- -->
755 <sect1>Data Types
756 <p>
757 There are a few things you probably noticed in the previous examples
758 that need explaining. The gint, gchar etc. that you see are typedefs
759 to int and char respectively. This is done to get around that nasty
760 dependency on the size of simple data types when doing calculations.
761
762 A good example is "gint32" which will be typedef'd to a 32 bit integer
763 for any given platform, whether it be the 64 bit alpha, or the 32 bit
764 i386. The typedefs are very straight forward and intuitive. They are
765 all defined in glib/glib.h (which gets included from gtk.h).
766
767 You'll also notice the ability to use GtkWidget when the function
768 calls for a GtkObject. GTK is an object oriented design, and a widget
769 is an object.
770
771 <!-- ----------------------------------------------------------------- -->
772 <sect1>More on Signal Handlers
773 <p>
774 Lets take another look at the gtk_signal_connect declaration.
775
776 <tscreen><verb>
777 gint gtk_signal_connect( GtkObject *object,
778                          gchar *name,
779                          GtkSignalFunc func,
780                          gpointer func_data );
781 </verb></tscreen>
782
783 Notice the gint return value? This is a tag that identifies your
784 callback function. As stated above, you may have as many callbacks per
785 signal and per object as you need, and each will be executed in turn,
786 in the order they were attached.
787
788 This tag allows you to remove this callback from the list by using:
789
790 <tscreen><verb>
791 void gtk_signal_disconnect( GtkObject *object,
792                             gint id );
793 </verb></tscreen>
794
795 So, by passing in the widget you wish to remove the handler from, and
796 the tag returned by one of the signal_connect functions, you can
797 disconnect a signal handler.
798
799 Another function to remove all the signal handers from an object is:
800
801 <tscreen><verb>
802 void gtk_signal_handlers_destroy( GtkObject *object );
803 </verb></tscreen>
804
805 This call is fairly self explanatory. It simply removes all the
806 current signal handlers from the object passed in as the first
807 argument.
808
809 <!-- ----------------------------------------------------------------- -->
810 <sect1>An Upgraded Hello World
811 <p>
812 Let's take a look at a slightly improved <em>helloworld</em> with
813 better examples of callbacks. This will also introduce us to our next
814 topic, packing widgets.
815
816 <tscreen><verb>
817 /* example-start helloworld2 helloworld2.c */
818
819 #include <gtk/gtk.h>
820
821 /* Our new improved callback.  The data passed to this function
822  * is printed to stdout. */
823 void callback( GtkWidget *widget,
824                gpointer   data )
825 {
826     g_print ("Hello again - %s was pressed\n", (char *) data);
827 }
828
829 /* another callback */
830 void delete_event( GtkWidget *widget,
831                    GdkEvent  *event,
832                    gpointer   data )
833 {
834     gtk_main_quit ();
835 }
836
837 int main( int   argc,
838           char *argv[] )
839 {
840     /* GtkWidget is the storage type for widgets */
841     GtkWidget *window;
842     GtkWidget *button;
843     GtkWidget *box1;
844
845     /* This is called in all GTK applications. Arguments are parsed
846      * from the command line and are returned to the application. */
847     gtk_init (&amp;argc, &amp;argv);
848
849     /* Create a new window */
850     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
851
852     /* This is a new call, this just sets the title of our
853      * new window to "Hello Buttons!" */
854     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
855
856     /* Here we just set a handler for delete_event that immediately
857      * exits GTK. */
858     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
859                         GTK_SIGNAL_FUNC (delete_event), NULL);
860
861     /* Sets the border width of the window. */
862     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
863
864     /* We create a box to pack widgets into.  This is described in detail
865      * in the "packing" section. The box is not really visible, it
866      * is just used as a tool to arrange widgets. */
867     box1 = gtk_hbox_new(FALSE, 0);
868
869     /* Put the box into the main window. */
870     gtk_container_add (GTK_CONTAINER (window), box1);
871
872     /* Creates a new button with the label "Button 1". */
873     button = gtk_button_new_with_label ("Button 1");
874
875     /* Now when the button is clicked, we call the "callback" function
876      * with a pointer to "button 1" as its argument */
877     gtk_signal_connect (GTK_OBJECT (button), "clicked",
878                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
879
880     /* Instead of gtk_container_add, we pack this button into the invisible
881      * box, which has been packed into the window. */
882     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
883
884     /* Always remember this step, this tells GTK that our preparation for
885      * this button is complete, and it can now be displayed. */
886     gtk_widget_show(button);
887
888     /* Do these same steps again to create a second button */
889     button = gtk_button_new_with_label ("Button 2");
890
891     /* Call the same callback function with a different argument,
892      * passing a pointer to "button 2" instead. */
893     gtk_signal_connect (GTK_OBJECT (button), "clicked",
894                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
895
896     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
897
898     /* The order in which we show the buttons is not really important, but I
899      * recommend showing the window last, so it all pops up at once. */
900     gtk_widget_show(button);
901
902     gtk_widget_show(box1);
903
904     gtk_widget_show (window);
905
906     /* Rest in gtk_main and wait for the fun to begin! */
907     gtk_main ();
908
909     return(0);
910 }
911 /* example-end */
912 </verb></tscreen>
913
914 Compile this program using the same linking arguments as our first
915 example.  You'll notice this time there is no easy way to exit the
916 program, you have to use your window manager or command line to kill
917 it. A good exercise for the reader would be to insert a third "Quit"
918 button that will exit the program. You may also wish to play with the
919 options to gtk_box_pack_start() while reading the next section.  Try
920 resizing the window, and observe the behavior.
921
922 Just as a side note, there is another useful define for
923 gtk_window_new() - GTK_WINDOW_DIALOG. This interacts with the window
924 manager a little differently and should be used for transient windows.
925
926 <!-- ***************************************************************** -->
927 <sect>Packing Widgets
928 <!-- ***************************************************************** -->
929 <p>
930 When creating an application, you'll want to put more than one widget
931 inside a window. Our first <em>helloworld</em> example only used one
932 widget so we could simply use a gtk_container_add call to "pack" the
933 widget into the window. But when you want to put more than one widget
934 into a window, how do you control where that widget is positioned?
935 This is where packing comes in.
936
937 <!-- ----------------------------------------------------------------- -->
938 <sect1>Theory of Packing Boxes
939 <p>
940 Most packing is done by creating boxes as in the example above. These
941 are invisible widget containers that we can pack our widgets into
942 which come in two forms, a horizontal box, and a vertical box. When
943 packing widgets into a horizontal box, the objects are inserted
944 horizontally from left to right or right to left depending on the call
945 used. In a vertical box, widgets are packed from top to bottom or vice
946 versa. You may use any combination of boxes inside or beside other
947 boxes to create the desired effect.
948
949 To create a new horizontal box, we use a call to gtk_hbox_new(), and
950 for vertical boxes, gtk_vbox_new().The gtk_box_pack_start() and
951 gtk_box_pack_end() functions are used to place objects inside of these
952 containers. The gtk_box_pack_start() function will start at the top
953 and work its way down in a vbox, and pack left to right in an hbox.
954 gtk_box_pack_end() will do the opposite, packing from bottom to top in
955 a vbox, and right to left in an hbox. Using these functions allow us
956 to right justify or left justify our widgets and may be mixed in any
957 way to achieve the desired effect. We will use gtk_box_pack_start() in
958 most of our examples. An object may be another container or a
959 widget. In fact, many widgets are actually containers themselves,
960 including the button, but we usually only use a label inside a button.
961
962 By using these calls, GTK knows where you want to place your widgets
963 so it can do automatic resizing and other nifty things. There's also a
964 number of options as to how your widgets should be packed. As you can
965 imagine, this method gives us a quite a bit of flexibility when
966 placing and creating widgets.
967
968 <!-- ----------------------------------------------------------------- -->
969 <sect1>Details of Boxes
970 <p>
971 Because of this flexibility, packing boxes in GTK can be confusing at
972 first. There are a lot of options, and it's not immediately obvious how
973 they all fit together. In the end however, there are basically five
974 different styles.
975
976 <? <CENTER> >
977 <?
978 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
979 HEIGHT="235" ALT="Box Packing Example Image">
980 >
981 <? </CENTER> >
982
983 Each line contains one horizontal box (hbox) with several buttons. The
984 call to gtk_box_pack is shorthand for the call to pack each of the
985 buttons into the hbox. Each of the buttons is packed into the hbox the
986 same way (i.e. same arguments to the gtk_box_pack_start() function).
987
988 This is the declaration of the gtk_box_pack_start function.
989
990 <tscreen><verb>
991 void gtk_box_pack_start( GtkBox    *box,
992                          GtkWidget *child,
993                          gint       expand,
994                          gint       fill,
995                          gint       padding );
996 </verb></tscreen>
997
998 The first argument is the box you are packing the object into, the
999 second is the object. The objects will all be buttons for now, so
1000 we'll be packing buttons into boxes.
1001
1002 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1003 controls whether the widgets are laid out in the box to fill in all
1004 the extra space in the box so the box is expanded to fill the area
1005 alloted to it (TRUE).  Or the box is shrunk to just fit the widgets
1006 (FALSE). Setting expand to FALSE will allow you to do right and left
1007 justification of your widgets.  Otherwise, they will all expand to fit
1008 into the box, and the same effect could be achieved by using only one
1009 of gtk_box_pack_start or gtk_box_pack_end.
1010
1011 The fill argument to the gtk_box_pack functions control whether the
1012 extra space is allocated to the objects themselves (TRUE), or as extra
1013 padding in the box around these objects (FALSE). It only has an effect
1014 if the expand argument is also TRUE.
1015
1016 When creating a new box, the function looks like this:
1017
1018 <tscreen><verb>
1019 GtkWidget *gtk_hbox_new (gint homogeneous,
1020                          gint spacing);
1021 </verb></tscreen>
1022
1023 The homogeneous argument to gtk_hbox_new (and the same for
1024 gtk_vbox_new) controls whether each object in the box has the same
1025 size (i.e. the same width in an hbox, or the same height in a
1026 vbox). If it is set, the expand argument to the gtk_box_pack routines
1027 is always turned on.
1028
1029 What's the difference between spacing (set when the box is created)
1030 and padding (set when elements are packed)? Spacing is added between
1031 objects, and padding is added on either side of an object. The
1032 following figure should make it clearer:
1033
1034 <? <CENTER> >
1035 <?
1036 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1037 HEIGHT="213" VSPACE="15" HSPACE="10"
1038 ALT="Box Packing Example Image">
1039 >
1040 <? </CENTER> >
1041
1042 Here is the code used to create the above images. I've commented it
1043 fairly heavily so hopefully you won't have any problems following
1044 it. Compile it yourself and play with it.
1045
1046 <!-- ----------------------------------------------------------------- -->
1047 <sect1>Packing Demonstration Program
1048 <p>
1049 <tscreen><verb>
1050 /* example-start packbox packbox.c */
1051
1052 #include <stdio.h>
1053 #include "gtk/gtk.h"
1054
1055 void delete_event( GtkWidget *widget,
1056                    GdkEvent  *event,
1057                    gpointer   data )
1058 {
1059     gtk_main_quit ();
1060 }
1061
1062 /* Make a new hbox filled with button-labels. Arguments for the 
1063  * variables we're interested are passed in to this function. 
1064  * We do not show the box, but do show everything inside. */
1065 GtkWidget *make_box( gint homogeneous,
1066                      gint spacing,
1067                      gint expand,
1068                      gint fill,
1069                      gint padding ) 
1070 {
1071     GtkWidget *box;
1072     GtkWidget *button;
1073     char padstr[80];
1074     
1075     /* Create a new hbox with the appropriate homogeneous
1076      * and spacing settings */
1077     box = gtk_hbox_new (homogeneous, spacing);
1078     
1079     /* Create a series of buttons with the appropriate settings */
1080     button = gtk_button_new_with_label ("gtk_box_pack");
1081     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1082     gtk_widget_show (button);
1083     
1084     button = gtk_button_new_with_label ("(box,");
1085     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1086     gtk_widget_show (button);
1087     
1088     button = gtk_button_new_with_label ("button,");
1089     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1090     gtk_widget_show (button);
1091     
1092     /* Create a button with the label depending on the value of
1093      * expand. */
1094     if (expand == TRUE)
1095             button = gtk_button_new_with_label ("TRUE,");
1096     else
1097             button = gtk_button_new_with_label ("FALSE,");
1098     
1099     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1100     gtk_widget_show (button);
1101     
1102     /* This is the same as the button creation for "expand"
1103      * above, but uses the shorthand form. */
1104     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1105     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1106     gtk_widget_show (button);
1107     
1108     sprintf (padstr, "%d);", padding);
1109     
1110     button = gtk_button_new_with_label (padstr);
1111     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1112     gtk_widget_show (button);
1113     
1114     return box;
1115 }
1116
1117 int main( int   argc,
1118           char *argv[]) 
1119 {
1120     GtkWidget *window;
1121     GtkWidget *button;
1122     GtkWidget *box1;
1123     GtkWidget *box2;
1124     GtkWidget *separator;
1125     GtkWidget *label;
1126     GtkWidget *quitbox;
1127     int which;
1128     
1129     /* Our init, don't forget this! :) */
1130     gtk_init (&amp;argc, &amp;argv);
1131     
1132     if (argc != 2) {
1133         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1134         /* this just does cleanup in GTK, and exits with an exit status of 1. */
1135         gtk_exit (1);
1136     }
1137     
1138     which = atoi (argv[1]);
1139
1140     /* Create our window */
1141     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1142
1143     /* You should always remember to connect the destroy signal to the
1144      * main window. This is very important for proper intuitive
1145      * behavior */
1146     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1147                         GTK_SIGNAL_FUNC (delete_event), NULL);
1148     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1149     
1150     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1151      * This allows us to stack the horizontal boxes filled with buttons one
1152      * on top of the other in this vbox. */
1153     box1 = gtk_vbox_new (FALSE, 0);
1154     
1155     /* which example to show. These correspond to the pictures above. */
1156     switch (which) {
1157     case 1:
1158         /* create a new label. */
1159         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1160         
1161         /* Align the label to the left side.  We'll discuss this function and 
1162          * others in the section on Widget Attributes. */
1163         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1164
1165         /* Pack the label into the vertical box (vbox box1).  Remember that 
1166          * widgets added to a vbox will be packed one on top of the other in
1167          * order. */
1168         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1169         
1170         /* Show the label */
1171         gtk_widget_show (label);
1172         
1173         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1174          * expand = FALSE, fill = FALSE, padding = 0 */
1175         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1176         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1177         gtk_widget_show (box2);
1178
1179         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1180          * expand = FALSE, fill = FALSE, padding = 0 */
1181         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1182         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1183         gtk_widget_show (box2);
1184         
1185         /* Args are: homogeneous, spacing, expand, fill, padding */
1186         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1187         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1188         gtk_widget_show (box2);
1189         
1190         /* Creates a separator, we'll learn more about these later, 
1191          * but they are quite simple. */
1192         separator = gtk_hseparator_new ();
1193         
1194         /* Cack the separator into the vbox. Remember each of these
1195          * widgets are being packed into a vbox, so they'll be stacked
1196          * vertically. */
1197         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1198         gtk_widget_show (separator);
1199         
1200         /* Create another new label, and show it. */
1201         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1202         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1203         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1204         gtk_widget_show (label);
1205         
1206         /* Args are: homogeneous, spacing, expand, fill, padding */
1207         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1208         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1209         gtk_widget_show (box2);
1210         
1211         /* Args are: homogeneous, spacing, expand, fill, padding */
1212         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1213         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1214         gtk_widget_show (box2);
1215         
1216         /* Another new separator. */
1217         separator = gtk_hseparator_new ();
1218         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1219         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1220         gtk_widget_show (separator);
1221         
1222         break;
1223
1224     case 2:
1225
1226         /* Create a new label, remember box1 is a vbox as created 
1227          * near the beginning of main() */
1228         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1229         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1230         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1231         gtk_widget_show (label);
1232         
1233         /* Args are: homogeneous, spacing, expand, fill, padding */
1234         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1235         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1236         gtk_widget_show (box2);
1237         
1238         /* Args are: homogeneous, spacing, expand, fill, padding */
1239         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1240         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1241         gtk_widget_show (box2);
1242         
1243         separator = gtk_hseparator_new ();
1244         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1245         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1246         gtk_widget_show (separator);
1247         
1248         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1249         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1250         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1251         gtk_widget_show (label);
1252         
1253         /* Args are: homogeneous, spacing, expand, fill, padding */
1254         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1255         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1256         gtk_widget_show (box2);
1257         
1258         /* Args are: homogeneous, spacing, expand, fill, padding */
1259         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1260         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1261         gtk_widget_show (box2);
1262         
1263         separator = gtk_hseparator_new ();
1264         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1265         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1266         gtk_widget_show (separator);
1267         break;
1268     
1269     case 3:
1270
1271         /* This demonstrates the ability to use gtk_box_pack_end() to
1272          * right justify widgets. First, we create a new box as before. */
1273         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1274
1275         /* Create the label that will be put at the end. */
1276         label = gtk_label_new ("end");
1277         /* Pack it using gtk_box_pack_end(), so it is put on the right
1278          * side of the hbox created in the make_box() call. */
1279         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1280         /* Show the label. */
1281         gtk_widget_show (label);
1282         
1283         /* Pack box2 into box1 (the vbox remember ? :) */
1284         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1285         gtk_widget_show (box2);
1286         
1287         /* A separator for the bottom. */
1288         separator = gtk_hseparator_new ();
1289         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1290          * high. This is so the hbox we created will also be 400 pixels wide,
1291          * and the "end" label will be separated from the other labels in the
1292          * hbox. Otherwise, all the widgets in the hbox would be packed as
1293          * close together as possible. */
1294         gtk_widget_set_usize (separator, 400, 5);
1295         /* pack the separator into the vbox (box1) created near the start 
1296          * of main() */
1297         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1298         gtk_widget_show (separator);    
1299     }
1300     
1301     /* Create another new hbox.. remember we can use as many as we need! */
1302     quitbox = gtk_hbox_new (FALSE, 0);
1303     
1304     /* Our quit button. */
1305     button = gtk_button_new_with_label ("Quit");
1306     
1307     /* Setup the signal to destroy the window. Remember that this will send
1308      * the "destroy" signal to the window which will be caught by our signal
1309      * handler as defined above. */
1310     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1311                                GTK_SIGNAL_FUNC (gtk_main_quit),
1312                                GTK_OBJECT (window));
1313     /* Pack the button into the quitbox.
1314      * The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1315     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1316     /* pack the quitbox into the vbox (box1) */
1317     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1318     
1319     /* Pack the vbox (box1) which now contains all our widgets, into the
1320      * main window. */
1321     gtk_container_add (GTK_CONTAINER (window), box1);
1322     
1323     /* And show everything left */
1324     gtk_widget_show (button);
1325     gtk_widget_show (quitbox);
1326     
1327     gtk_widget_show (box1);
1328     /* Showing the window last so everything pops up at once. */
1329     gtk_widget_show (window);
1330     
1331     /* And of course, our main function. */
1332     gtk_main ();
1333
1334     /* Control returns here when gtk_main_quit() is called, but not when 
1335      * gtk_exit is used. */
1336     
1337     return(0);
1338 }
1339 /* example-end */
1340 </verb></tscreen>
1341
1342 <!-- ----------------------------------------------------------------- -->
1343 <sect1>Packing Using Tables
1344 <p>
1345 Let's take a look at another way of packing - Tables. These can be
1346 extremely useful in certain situations.
1347
1348 Using tables, we create a grid that we can place widgets in. The
1349 widgets may take up as many spaces as we specify.
1350
1351 The first thing to look at of course, is the gtk_table_new function:
1352
1353 <tscreen><verb>
1354 GtkWidget *gtk_table_new( gint rows,
1355                           gint columns,
1356                           gint homogeneous );
1357 </verb></tscreen>
1358
1359 The first argument is the number of rows to make in the table, while
1360 the second, obviously, is the number of columns.
1361
1362 The homogeneous argument has to do with how the table's boxes are
1363 sized. If homogeneous is TRUE, the table boxes are resized to the size
1364 of the largest widget in the table. If homogeneous is FALSE, the size
1365 of a table boxes is dictated by the tallest widget in its same row,
1366 and the widest widget in its column.
1367
1368 The rows and columns are laid out from 0 to n, where n was the number
1369 specified in the call to gtk_table_new. So, if you specify rows = 2
1370 and columns = 2, the layout would look something like this:
1371
1372 <tscreen><verb>
1373  0          1          2
1374 0+----------+----------+
1375  |          |          |
1376 1+----------+----------+
1377  |          |          |
1378 2+----------+----------+
1379 </verb></tscreen>
1380
1381 Note that the coordinate system starts in the upper left hand corner.
1382 To place a widget into a box, use the following function:
1383
1384 <tscreen><verb>
1385 void gtk_table_attach( GtkTable  *table,
1386                        GtkWidget *child,
1387                        gint       left_attach,
1388                        gint       right_attach,
1389                        gint       top_attach,
1390                        gint       bottom_attach,
1391                        gint       xoptions,
1392                        gint       yoptions,
1393                        gint       xpadding,
1394                        gint       ypadding );
1395 </verb></tscreen>                                      
1396
1397 Where the first argument ("table") is the table you've created and the
1398 second ("child") the widget you wish to place in the table.
1399
1400 The left and right attach arguments specify where to place the widget,
1401 and how many boxes to use. If you want a button in the lower right
1402 table entry of our 2x2 table, and want it to fill that entry ONLY,
1403 left_attach would be = 1, right_attach = 2, top_attach = 1,
1404 bottom_attach = 2.
1405
1406 Now, if you wanted a widget to take up the whole top row of our 2x2
1407 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1408 bottom_attach = 1.
1409
1410 The xoptions and yoptions are used to specify packing options and may
1411 be bitwise OR'ed together to allow multiple options.
1412
1413 These options are:
1414 <itemize>
1415 <item>GTK_FILL - If the table box is larger than the widget, and
1416 GTK_FILL is specified, the widget will expand to use all the room
1417 available.
1418
1419 <item>GTK_SHRINK - If the table widget was allocated less space then
1420 was requested (usually by the user resizing the window), then the
1421 widgets would normally just be pushed off the bottom of the window and
1422 disappear. If GTK_SHRINK is specified, the widgets will shrink with
1423 the table.
1424
1425 <item>GTK_EXPAND - This will cause the table to expand to use up any
1426 remaining space in the window.
1427 </itemize>
1428
1429 Padding is just like in boxes, creating a clear area around the widget
1430 specified in pixels.
1431
1432 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1433
1434 <tscreen><verb>
1435 void gtk_table_attach_defaults( GtkTable  *table,
1436                                 GtkWidget *widget,
1437                                 gint       left_attach,
1438                                 gint       right_attach,
1439                                 gint       top_attach,
1440                                 gint       bottom_attach );
1441 </verb></tscreen>
1442
1443 The X and Y options default to GTK_FILL | GTK_EXPAND, and X and Y
1444 padding are set to 0. The rest of the arguments are identical to the
1445 previous function.
1446
1447 We also have gtk_table_set_row_spacing() and
1448 gtk_table_set_col_spacing().  This places spacing between the rows at
1449 the specified row or column.
1450
1451 <tscreen><verb>
1452 void gtk_table_set_row_spacing( GtkTable *table,
1453                                 gint      row,
1454                                 gint      spacing );
1455 </verb></tscreen>
1456
1457 and
1458
1459 <tscreen><verb>
1460 void gtk_table_set_col_spacing ( GtkTable *table,
1461                                  gint      column,
1462                                  gint      spacing );
1463 </verb></tscreen>
1464
1465 Note that for columns, the space goes to the right of the column, and
1466 for rows, the space goes below the row.
1467
1468 You can also set a consistent spacing of all rows and/or columns with:
1469
1470 <tscreen><verb>
1471 void gtk_table_set_row_spacings( GtkTable *table,
1472                                  gint      spacing );
1473 </verb></tscreen>
1474
1475 And,
1476
1477 <tscreen><verb>
1478 void gtk_table_set_col_spacings( GtkTable *table,
1479                                  gint      spacing );
1480 </verb></tscreen>
1481
1482 Note that with these calls, the last row and last column do not get
1483 any spacing.
1484
1485 <!-- ----------------------------------------------------------------- -->
1486 <sect1>Table Packing Example
1487 <p>
1488 Here we make a window with three buttons in a 2x2 table.
1489 The first two buttons will be placed in the upper row.
1490 A third, quit button, is placed in the lower row, spanning both columns.
1491 Which means it should look something like this:
1492
1493 <? <CENTER> >
1494 <?
1495 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1496 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1497 >
1498 <? </CENTER> >
1499
1500 Here's the source code:
1501
1502 <tscreen><verb>
1503 /* example-start table table.c */
1504
1505 #include <gtk/gtk.h>
1506
1507 /* Our callback.
1508  * The data passed to this function is printed to stdout */
1509 void callback( GtkWidget *widget,
1510                gpointer   data )
1511 {
1512     g_print ("Hello again - %s was pressed\n", (char *) data);
1513 }
1514
1515 /* This callback quits the program */
1516 void delete_event( GtkWidget *widget,
1517                    GdkEvent  *event,
1518                    gpointer   data )
1519 {
1520     gtk_main_quit ();
1521 }
1522
1523 int main( int   argc,
1524           char *argv[] )
1525 {
1526     GtkWidget *window;
1527     GtkWidget *button;
1528     GtkWidget *table;
1529
1530     gtk_init (&amp;argc, &amp;argv);
1531
1532     /* Create a new window */
1533     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1534
1535     /* Set the window title */
1536     gtk_window_set_title (GTK_WINDOW (window), "Table");
1537
1538     /* Set a handler for delete_event that immediately
1539      * exits GTK. */
1540     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1541                         GTK_SIGNAL_FUNC (delete_event), NULL);
1542
1543     /* Sets the border width of the window. */
1544     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1545
1546     /* Create a 2x2 table */
1547     table = gtk_table_new (2, 2, TRUE);
1548
1549     /* Put the table in the main window */
1550     gtk_container_add (GTK_CONTAINER (window), table);
1551
1552     /* Create first button */
1553     button = gtk_button_new_with_label ("button 1");
1554
1555     /* When the button is clicked, we call the "callback" function
1556      * with a pointer to "button 1" as its argument */
1557     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1558               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1559
1560
1561     /* Insert button 1 into the upper left quadrant of the table */
1562     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1563
1564     gtk_widget_show (button);
1565
1566     /* Create second button */
1567
1568     button = gtk_button_new_with_label ("button 2");
1569
1570     /* When the button is clicked, we call the "callback" function
1571      * with a pointer to "button 2" as its argument */
1572     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1573               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1574     /* Insert button 2 into the upper right quadrant of the table */
1575     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1576
1577     gtk_widget_show (button);
1578
1579     /* Create "Quit" button */
1580     button = gtk_button_new_with_label ("Quit");
1581
1582     /* When the button is clicked, we call the "delete_event" function
1583      * and the program exits */
1584     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1585                         GTK_SIGNAL_FUNC (delete_event), NULL);
1586
1587     /* Insert the quit button into the both 
1588      * lower quadrants of the table */
1589     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1590
1591     gtk_widget_show (button);
1592
1593     gtk_widget_show (table);
1594     gtk_widget_show (window);
1595
1596     gtk_main ();
1597
1598     return 0;
1599 }
1600 /* example-end */
1601 </verb></tscreen>
1602
1603 <!-- ***************************************************************** -->
1604 <sect>Widget Overview
1605 <!-- ***************************************************************** -->
1606 <p>
1607 The general steps to creating a widget in GTK are:
1608 <enum>
1609 <item> gtk_*_new - one of various functions to create a new widget.
1610 These are all detailed in this section.
1611
1612 <item> Connect all signals and events we wish to use to the
1613 appropriate handlers.
1614
1615 <item> Set the attributes of the widget.
1616
1617 <item> Pack the widget into a container using the appropriate call
1618 such as gtk_container_add() or gtk_box_pack_start().
1619
1620 <item> gtk_widget_show() the widget.
1621 </enum>
1622
1623 gtk_widget_show() lets GTK know that we are done setting the
1624 attributes of the widget, and it is ready to be displayed. You may
1625 also use gtk_widget_hide to make it disappear again. The order in
1626 which you show the widgets is not important, but I suggest showing the
1627 window last so the whole window pops up at once rather than seeing the
1628 individual widgets come up on the screen as they're formed. The
1629 children of a widget (a window is a widget too) will not be displayed
1630 until the window itself is shown using the gtk_widget_show() function.
1631
1632 <!-- ----------------------------------------------------------------- -->
1633 <sect1> Casting
1634 <p>
1635 You'll notice as you go on, that GTK uses a type casting system. This
1636 is always done using macros that both test the ability to cast the
1637 given item, and perform the cast. Some common ones you will see are:
1638
1639 <itemize>
1640 <item> GTK_WIDGET(widget)
1641 <item> GTK_OBJECT(object)
1642 <item> GTK_SIGNAL_FUNC(function)
1643 <item> GTK_CONTAINER(container)
1644 <item> GTK_WINDOW(window)
1645 <item> GTK_BOX(box)
1646 </itemize>
1647
1648 These are all used to cast arguments in functions. You'll see them in the
1649 examples, and can usually tell when to use them simply by looking at the
1650 function's declaration.
1651
1652 As you can see below in the class hierarchy, all GtkWidgets are
1653 derived from the GtkObject base class. This means you can use a widget
1654 in any place the function asks for an object - simply use the
1655 GTK_OBJECT() macro.
1656
1657 For example:
1658
1659 <tscreen><verb>
1660 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1661                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1662 </verb></tscreen> 
1663
1664 This casts the button into an object, and provides a cast for the
1665 function pointer to the callback.
1666
1667 Many widgets are also containers. If you look in the class hierarchy
1668 below, you'll notice that many widgets derive from the GtkContainer
1669 class. Any one of these widgets may be used with the GTK_CONTAINER
1670 macro to pass them to functions that ask for containers.
1671
1672 Unfortunately, these macros are not extensively covered in the
1673 tutorial, but I recommend taking a look through the GTK header
1674 files. It can be very educational. In fact, it's not difficult to
1675 learn how a widget works just by looking at the function declarations.
1676
1677 <!-- ----------------------------------------------------------------- -->
1678 <sect1>Widget Hierarchy
1679 <p>
1680 For your reference, here is the class hierarchy tree used to implement widgets.
1681
1682 <tscreen><verb>
1683  GtkObject
1684   +GtkWidget
1685   | +GtkMisc
1686   | | +GtkLabel
1687   | | | +GtkAccelLabel
1688   | | | `GtkTipsQuery
1689   | | +GtkArrow
1690   | | +GtkImage
1691   | | `GtkPixmap
1692   | +GtkContainer
1693   | | +GtkBin
1694   | | | +GtkAlignment
1695   | | | +GtkFrame
1696   | | | | `GtkAspectFrame
1697   | | | +GtkButton
1698   | | | | +GtkToggleButton
1699   | | | | | `GtkCheckButton
1700   | | | | |   `GtkRadioButton
1701   | | | | `GtkOptionMenu
1702   | | | +GtkItem
1703   | | | | +GtkMenuItem
1704   | | | | | +GtkCheckMenuItem
1705   | | | | | | `GtkRadioMenuItem
1706   | | | | | `GtkTearoffMenuItem
1707   | | | | +GtkListItem
1708   | | | | `GtkTreeItem
1709   | | | +GtkWindow
1710   | | | | +GtkColorSelectionDialog
1711   | | | | +GtkDialog
1712   | | | | | `GtkInputDialog
1713   | | | | +GtkDrawWindow
1714   | | | | +GtkFileSelection
1715   | | | | +GtkFontSelectionDialog
1716   | | | | `GtkPlug
1717   | | | +GtkEventBox
1718   | | | +GtkHandleBox
1719   | | | +GtkScrolledWindow
1720   | | | `GtkViewport
1721   | | +GtkBox
1722   | | | +GtkButtonBox
1723   | | | | +GtkHButtonBox
1724   | | | | `GtkVButtonBox
1725   | | | +GtkVBox
1726   | | | | +GtkColorSelection
1727   | | | | `GtkGammaCurve
1728   | | | `GtkHBox
1729   | | |   +GtkCombo
1730   | | |   `GtkStatusbar
1731   | | +GtkCList
1732   | | | `GtkCTree
1733   | | +GtkFixed
1734   | | +GtkNotebook
1735   | | | `GtkFontSelection
1736   | | +GtkPaned
1737   | | | +GtkHPaned
1738   | | | `GtkVPaned
1739   | | +GtkLayout
1740   | | +GtkList
1741   | | +GtkMenuShell
1742   | | | +GtkMenuBar
1743   | | | `GtkMenu
1744   | | +GtkPacker
1745   | | +GtkSocket
1746   | | +GtkTable
1747   | | +GtkToolbar
1748   | | `GtkTree
1749   | +GtkCalendar
1750   | +GtkDrawingArea
1751   | | `GtkCurve
1752   | +GtkEditable
1753   | | +GtkEntry
1754   | | | `GtkSpinButton
1755   | | `GtkText
1756   | +GtkRuler
1757   | | +GtkHRuler
1758   | | `GtkVRuler
1759   | +GtkRange
1760   | | +GtkScale
1761   | | | +GtkHScale
1762   | | | `GtkVScale
1763   | | `GtkScrollbar
1764   | |   +GtkHScrollbar
1765   | |   `GtkVScrollbar
1766   | +GtkSeparator
1767   | | +GtkHSeparator
1768   | | `GtkVSeparator
1769   | +GtkPreview
1770   | `GtkProgress
1771   |   `GtkProgressBar
1772   +GtkData
1773   | +GtkAdjustment
1774   | `GtkTooltips
1775   `GtkItemFactory
1776 </verb></tscreen>
1777
1778 <!-- ----------------------------------------------------------------- -->
1779 <sect1>Widgets Without Windows
1780 <p>
1781 The following widgets do not have an associated window. If you want to
1782 capture events, you'll have to use the GtkEventBox. See the section on
1783 the <ref id="sec_EventBox" name="EventBox"> widget.
1784
1785 <tscreen><verb>
1786 GtkAlignment
1787 GtkArrow
1788 GtkBin
1789 GtkBox
1790 GtkImage
1791 GtkItem
1792 GtkLabel
1793 GtkPixmap
1794 GtkScrolledWindow
1795 GtkSeparator
1796 GtkTable
1797 GtkAspectFrame
1798 GtkFrame
1799 GtkVBox
1800 GtkHBox
1801 GtkVSeparator
1802 GtkHSeparator
1803 </verb></tscreen>
1804
1805 We'll further our exploration of GTK by examining each widget in turn,
1806 creating a few simple functions to display them. Another good source
1807 is the testgtk.c program that comes with GTK. It can be found in
1808 gtk/testgtk.c.
1809
1810 <!-- ***************************************************************** -->
1811 <sect>The Button Widget
1812 <!-- ***************************************************************** -->
1813
1814 <!-- ----------------------------------------------------------------- -->
1815 <sect1>Normal Buttons
1816 <p>
1817 We've almost seen all there is to see of the button widget. It's
1818 pretty simple. There are however two ways to create a button. You can
1819 use the gtk_button_new_with_label() to create a button with a label,
1820 or use gtk_button_new() to create a blank button. It's then up to you
1821 to pack a label or pixmap into this new button. To do this, create a
1822 new box, and then pack your objects into this box using the usual
1823 gtk_box_pack_start, and then use gtk_container_add to pack the box
1824 into the button.
1825
1826 Here's an example of using gtk_button_new to create a button with a
1827 picture and a label in it. I've broken up the code to create a box
1828 from the rest so you can use it in your programs. There are further
1829 examples of using pixmaps later in the tutorial.
1830
1831 <tscreen><verb>
1832 /* example-start buttons buttons.c */
1833
1834 #include <gtk/gtk.h>
1835
1836 /* Create a new hbox with an image and a label packed into it
1837  * and return the box. */
1838
1839 GtkWidget *xpm_label_box( GtkWidget *parent,
1840                           gchar     *xpm_filename,
1841                           gchar     *label_text )
1842 {
1843     GtkWidget *box1;
1844     GtkWidget *label;
1845     GtkWidget *pixmapwid;
1846     GdkPixmap *pixmap;
1847     GdkBitmap *mask;
1848     GtkStyle *style;
1849
1850     /* Create box for xpm and label */
1851     box1 = gtk_hbox_new (FALSE, 0);
1852     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1853
1854     /* Get the style of the button to get the
1855      * background color. */
1856     style = gtk_widget_get_style(parent);
1857
1858     /* Now on to the xpm stuff */
1859     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1860                                          &amp;style->bg[GTK_STATE_NORMAL],
1861                                          xpm_filename);
1862     pixmapwid = gtk_pixmap_new (pixmap, mask);
1863
1864     /* Create a label for the button */
1865     label = gtk_label_new (label_text);
1866
1867     /* Pack the pixmap and label into the box */
1868     gtk_box_pack_start (GTK_BOX (box1),
1869                         pixmapwid, FALSE, FALSE, 3);
1870
1871     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1872
1873     gtk_widget_show(pixmapwid);
1874     gtk_widget_show(label);
1875
1876     return(box1);
1877 }
1878
1879 /* Our usual callback function */
1880 void callback( GtkWidget *widget,
1881                gpointer   data )
1882 {
1883     g_print ("Hello again - %s was pressed\n", (char *) data);
1884 }
1885
1886
1887 int main( int   argc,
1888           char *argv[] )
1889 {
1890     /* GtkWidget is the storage type for widgets */
1891     GtkWidget *window;
1892     GtkWidget *button;
1893     GtkWidget *box1;
1894
1895     gtk_init (&amp;argc, &amp;argv);
1896
1897     /* Create a new window */
1898     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1899
1900     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1901
1902     /* It's a good idea to do this for all windows. */
1903     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1904                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1905
1906     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1907                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1908
1909
1910     /* Sets the border width of the window. */
1911     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1912     gtk_widget_realize(window);
1913
1914     /* Create a new button */
1915     button = gtk_button_new ();
1916
1917     /* Connect the "clicked" signal of the button to our callback */
1918     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1919                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1920
1921     /* This calls our box creating function */
1922     box1 = xpm_label_box(window, "info.xpm", "cool button");
1923
1924     /* Pack and show all our widgets */
1925     gtk_widget_show(box1);
1926
1927     gtk_container_add (GTK_CONTAINER (button), box1);
1928
1929     gtk_widget_show(button);
1930
1931     gtk_container_add (GTK_CONTAINER (window), button);
1932
1933     gtk_widget_show (window);
1934
1935     /* Rest in gtk_main and wait for the fun to begin! */
1936     gtk_main ();
1937
1938     return(0);
1939 }
1940 /* example-end */
1941 </verb></tscreen>
1942
1943 The xpm_label_box function could be used to pack xpm's and labels into
1944 any widget that can be a container.
1945
1946 The Button widget has the following signals:
1947
1948 <itemize>
1949 <item> pressed
1950 <item> released
1951 <item> clicked
1952 <item> enter
1953 <item> leave
1954 </itemize>
1955
1956 <!-- ----------------------------------------------------------------- -->
1957 <sect1> Toggle Buttons
1958 <p>
1959 Toggle buttons are derived from normal buttons and are very similar,
1960 except they will always be in one of two states, alternated by a
1961 click. They may be depressed, and when you click again, they will pop
1962 back up. Click again, and they will pop back down.
1963
1964 Toggle buttons are the basis for check buttons and radio buttons, as
1965 such, many of the calls used for toggle buttons are inherited by radio
1966 and check buttons. I will point these out when we come to them.
1967
1968 Creating a new toggle button:
1969
1970 <tscreen><verb>
1971 GtkWidget *gtk_toggle_button_new( void );
1972
1973 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
1974 </verb></tscreen>
1975
1976 As you can imagine, these work identically to the normal button widget
1977 calls. The first creates a blank toggle button, and the second, a
1978 button with a label widget already packed into it.
1979
1980 To retrieve the state of the toggle widget, including radio and check
1981 buttons, we use a GTK macro as shown in our example below. This tests
1982 the state of the toggle in a callback. The signal of interest emitted
1983 to us by toggle buttons (the toggle button, check button, and radio
1984 button widgets), is the "toggled" signal. To check the state of these
1985 buttons, set up a signal handler to catch the toggled signal, and use
1986 the macro to determine its state. The callback will look something
1987 like:
1988
1989 <tscreen><verb>
1990 void toggle_button_callback (GtkWidget *widget, gpointer data)
1991 {
1992     if (GTK_TOGGLE_BUTTON (widget)->active) 
1993     {
1994         /* If control reaches here, the toggle button is down */
1995     
1996     } else {
1997     
1998         /* If control reaches here, the toggle button is up */
1999     }
2000 }
2001 </verb></tscreen>
2002
2003 <tscreen><verb>
2004 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2005                                   gint             state );
2006 </verb></tscreen>
2007
2008 The above call can be used to set the state of the toggle button, and
2009 its children the radio and check buttons. Passing in your created
2010 button as the first argument, and a TRUE or FALSE for the second state
2011 argument to specify whether it should be down (depressed) or up
2012 (released). Default is up, or FALSE.
2013
2014 Note that when you use the gtk_toggle_button_set_active() function, and
2015 the state is actually changed, it causes the "clicked" signal to be
2016 emitted from the button.
2017
2018 <tscreen><verb>
2019 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2020 </verb></tscreen>
2021
2022 This simply toggles the button, and emits the "toggled" signal.
2023
2024 <!-- ----------------------------------------------------------------- -->
2025 <sect1> Check Buttons
2026 <p>
2027 Check buttons inherent many properties and functions from the the
2028 toggle buttons above, but look a little different. Rather than being
2029 buttons with text inside them, they are small squares with the text to
2030 the right of them. These are often used for toggling options on and
2031 off in applications.
2032
2033 The two creation functions are similar to those of the normal button.
2034
2035 <tscreen><verb>
2036 GtkWidget *gtk_check_button_new( void );
2037
2038 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2039 </verb></tscreen>
2040
2041 The new_with_label function creates a check button with a label beside
2042 it.
2043
2044 Checking the state of the check button is identical to that of the
2045 toggle button.
2046
2047 <!-- ----------------------------------------------------------------- -->
2048 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2049 <p>
2050 Radio buttons are similar to check buttons except they are grouped so
2051 that only one may be selected/depressed at a time. This is good for
2052 places in your application where you need to select from a short list
2053 of options.
2054
2055 Creating a new radio button is done with one of these calls:
2056
2057 <tscreen><verb>
2058 GtkWidget *gtk_radio_button_new( GSList *group );
2059
2060 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2061                                             gchar  *label );
2062 </verb></tscreen>
2063
2064 You'll notice the extra argument to these calls. They require a group
2065 to perform their duty properly. The first call to
2066 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2067 should pass NULL as the first argument. Then create a group using:
2068
2069 <tscreen><verb>
2070 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2071 </verb></tscreen>
2072
2073 The important thing to remember is that gtk_radio_button_group must be
2074 called for each new button added to the group, with the previous
2075 button passed in as an argument. The result is then passed into the
2076 call to gtk_radio_button_new or gtk_radio_button_new_with_label. This
2077 allows a chain of buttons to be established. The example below should
2078 make this clear.
2079
2080 You can shorten this slightly by using the following syntax, which
2081 removes the need for a variable to hold the list of buttons. This form
2082 is used in the example to create the third button:
2083
2084 <tscreen><verb>
2085      button2 = gtk_radio_button_new_with_label(
2086                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2087                  "button2");
2088 </verb></tscreen>
2089
2090 It is also a good idea to explicitly set which button should be the
2091 default depressed button with:
2092
2093 <tscreen><verb>
2094 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2095                                   gint             state );
2096 </verb></tscreen>
2097
2098 This is described in the section on toggle buttons, and works in
2099 exactly the same way.
2100
2101 The following example creates a radio button group with three buttons.
2102
2103 <tscreen><verb>
2104 /* example-start radiobuttons radiobuttons.c */
2105
2106 #include <gtk/gtk.h>
2107 #include <glib.h>
2108
2109 void close_application( GtkWidget *widget,
2110                         GdkEvent  *event,
2111                         gpointer   data )
2112 {
2113   gtk_main_quit();
2114 }
2115
2116 int main( int   argc,
2117           char *argv[] )
2118 {
2119     GtkWidget *window = NULL;
2120     GtkWidget *box1;
2121     GtkWidget *box2;
2122     GtkWidget *button;
2123     GtkWidget *separator;
2124     GSList *group;
2125   
2126     gtk_init(&amp;argc,&amp;argv);    
2127       
2128     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2129   
2130     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2131                         GTK_SIGNAL_FUNC(close_application),
2132                         NULL);
2133
2134     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2135     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2136
2137     box1 = gtk_vbox_new (FALSE, 0);
2138     gtk_container_add (GTK_CONTAINER (window), box1);
2139     gtk_widget_show (box1);
2140
2141     box2 = gtk_vbox_new (FALSE, 10);
2142     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2143     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2144     gtk_widget_show (box2);
2145
2146     button = gtk_radio_button_new_with_label (NULL, "button1");
2147     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2148     gtk_widget_show (button);
2149
2150     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2151     button = gtk_radio_button_new_with_label(group, "button2");
2152     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2153     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2154     gtk_widget_show (button);
2155
2156     button = gtk_radio_button_new_with_label(
2157                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2158                  "button3");
2159     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2160     gtk_widget_show (button);
2161
2162     separator = gtk_hseparator_new ();
2163     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2164     gtk_widget_show (separator);
2165
2166     box2 = gtk_vbox_new (FALSE, 10);
2167     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2168     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2169     gtk_widget_show (box2);
2170
2171     button = gtk_button_new_with_label ("close");
2172     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2173                                GTK_SIGNAL_FUNC(close_application),
2174                                GTK_OBJECT (window));
2175     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2176     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2177     gtk_widget_grab_default (button);
2178     gtk_widget_show (button);
2179     gtk_widget_show (window);
2180      
2181     gtk_main();
2182
2183     return(0);
2184 }
2185 /* example-end */
2186 </verb></tscreen>
2187
2188 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2189
2190 <!-- ***************************************************************** -->
2191 <sect> Adjustments <label id="sec_Adjustment">
2192 <!-- ***************************************************************** -->
2193 <p>
2194 GTK+ has various widgets that can be visually adjusted by the user
2195 using the mouse or the keyboard, such as the range widgets, described
2196 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2197 section. There are also a few widgets that display some adjustable
2198 portion of a larger area of data, such as the text widget and the
2199 viewport widget.
2200
2201 Obviously, an application needs to be able to react to changes the
2202 user makes in range widgets. One way to do this would be to have each
2203 widget emit its own type of signal when its adjustment changes, and
2204 either pass the new value to the signal handler, or require it to look
2205 inside the widget's data structure in order to ascertain the value.
2206 But you may also want to connect the adjustments of several widgets
2207 together, so that adjusting one adjusts the others. The most obvious
2208 example of this is connecting a scrollbar to a panning viewport or a
2209 scrolling text area. If each widget has its own way of setting or
2210 getting the adjustment value, then the programmer may have to write
2211 their own signal handlers to translate between the output of one
2212 widget's signal and the "input" of another's adjustment setting
2213 function.
2214
2215 GTK+ solves this problem using the GtkAdjustment object, which is a
2216 way for widgets to store and pass adjustment information in an
2217 abstract and flexible form. The most obvious use of GtkAdjustment is
2218 to store the configuration parameters and values of range widgets,
2219 such as scrollbars and scale controls. However, since GtkAdjustments
2220 are derived from GtkObject, they have some special powers beyond those
2221 of normal data structures. Most importantly, they can emit signals,
2222 just like widgets, and these signals can be used not only to allow
2223 your program to react to user input on adjustable widgets, but also to
2224 propagate adjustment values transparently between adjustable widgets.
2225
2226 <sect1> Creating an Adjustment
2227 <p>
2228 You create an adjustment using:
2229
2230 <tscreen><verb>
2231 GtkObject *gtk_adjustment_new( gfloat value,
2232                                gfloat lower,
2233                                gfloat upper,
2234                                gfloat step_increment,
2235                                gfloat page_increment,
2236                                gfloat page_size );
2237 </verb></tscreen>
2238
2239 The <tt/value/ argument is the initial value you want to give to the
2240 adjustment, usually corresponding to the topmost or leftmost position
2241 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2242 value which the adjustment can hold. The <tt/step_increment/ argument
2243 specifies the "smaller" of the two increments by which the user can
2244 change the value, while the <tt/page_increment/ is the "larger" one.
2245 The <tt/page_size/ argument usually corresponds somehow to the visible
2246 area of a panning widget. The <tt/upper/ argument is used to represent
2247 the bottom most or right most coordinate in a panning widget's
2248 child. Therefore it is <em/not/ always the largest number that
2249 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2250 usually non-zero.
2251
2252 <!-- ----------------------------------------------------------------- -->
2253 <sect1> Using Adjustments the Easy Way
2254 <p>
2255 The adjustable widgets can be roughly divided into those which use and
2256 require specific units for these values and those which treat them as
2257 arbitrary numbers. The group which treats the values as arbitrary
2258 numbers includes the range widgets (scrollbars and scales, the
2259 progress bar widget, and the spin button widget). These widgets are
2260 all the widgets which are typically "adjusted" directly by the user
2261 with the mouse or keyboard. They will treat the <tt/lower/ and
2262 <tt/upper/ values of an adjustment as a range within which the user
2263 can manipulate the adjustment's <tt/value/. By default, they will only
2264 modify the <tt/value/ of an adjustment.
2265
2266 The other group includes the text widget, the viewport widget, the
2267 compound list widget, and the scrolled window widget. All of these
2268 widgets use pixel values for their adjustments. These are also all
2269 widgets which are typically "adjusted" indirectly using scrollbars.
2270 While all widgets which use adjustments can either create their own
2271 adjustments or use ones you supply, you'll generally want to let this
2272 particular category of widgets create its own adjustments. Usually,
2273 they will eventually override all the values except the <tt/value/
2274 itself in whatever adjustments you give them, but the results are, in
2275 general, undefined (meaning, you'll have to read the source code to
2276 find out, and it may be different from widget to widget).
2277
2278 Now, you're probably thinking, since text widgets and viewports insist
2279 on setting everything except the <tt/value/ of their adjustments,
2280 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2281 you <em/share/ an adjustment object between a scrollbar and a text
2282 widget, manipulating the scrollbar will automagically adjust the text
2283 widget?  Of course it will! Just like this:
2284
2285 <tscreen><verb>
2286   /* creates its own adjustments */
2287   text = gtk_text_new (NULL, NULL);
2288   /* uses the newly-created adjustment for the scrollbar as well */
2289   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2290 </verb></tscreen>
2291
2292 </sect1>
2293 <!-- ----------------------------------------------------------------- -->
2294 <sect1> Adjustment Internals
2295 <p>
2296 Ok, you say, that's nice, but what if I want to create my own handlers
2297 to respond when the user adjusts a range widget or a spin button, and
2298 how do I get at the value of the adjustment in these handlers?  To
2299 answer these questions and more, let's start by taking a look at
2300 <tt>struct _GtkAdjustment</tt> itself:
2301
2302 <tscreen><verb>
2303 struct _GtkAdjustment
2304 {
2305   GtkData data;
2306   
2307   gfloat lower;
2308   gfloat upper;
2309   gfloat value;
2310   gfloat step_increment;
2311   gfloat page_increment;
2312   gfloat page_size;
2313 };     
2314 </verb></tscreen>
2315
2316 The first thing you should know is that there aren't any handy-dandy
2317 macros or accessor functions for getting the <tt/value/ out of a
2318 GtkAdjustment, so you'll have to (horror of horrors) do it like a
2319 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2320 (Object)</tt> macro does run-time type checking (as do all the GTK+
2321 type-casting macros, actually).
2322
2323 Since, when you set the <tt/value/ of an adjustment, you generally
2324 want the change to be reflected by every widget that uses this
2325 adjustment, GTK+ provides this convenience function to do this:
2326
2327 <tscreen><verb>
2328 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2329                                gfloat         value );
2330 </verb></tscreen>
2331
2332 As mentioned earlier, GtkAdjustment is a subclass of GtkObject just
2333 like all the various widgets, and thus it is able to emit signals.
2334 This is, of course, why updates happen automagically when you share an
2335 adjustment object between a scrollbar and another adjustable widget;
2336 all adjustable widgets connect signal handlers to their adjustment's
2337 <tt/value_changed/ signal, as can your program. Here's the definition
2338 of this signal in <tt/struct _GtkAdjustmentClass/:
2339
2340 <tscreen><verb>
2341   void (* value_changed) (GtkAdjustment *adjustment);
2342 </verb></tscreen>
2343
2344 The various widgets that use the GtkAdjustment object will emit this
2345 signal on an adjustment whenever they change its value. This happens
2346 both when user input causes the slider to move on a range widget, as
2347 well as when the program explicitly changes the value with
2348 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2349 widget, and you want to change the rotation of a picture whenever its
2350 value changes, you would create a callback like this:
2351
2352 <tscreen><verb>
2353 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2354 {
2355   set_picture_rotation (picture, adj->value);
2356 ...
2357 </verb></tscreen>
2358
2359 and connect it to the scale widget's adjustment like this:
2360
2361 <tscreen><verb>
2362 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2363                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2364 </verb></tscreen>
2365
2366 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2367 fields of its adjustment, such as when a user adds more text to a text
2368 widget?  In this case, it emits the <tt/changed/ signal, which looks
2369 like this:
2370
2371 <tscreen><verb>
2372   void (* changed)       (GtkAdjustment *adjustment);
2373 </verb></tscreen>
2374
2375 Range widgets typically connect a handler to this signal, which
2376 changes their appearance to reflect the change - for example, the size
2377 of the slider in a scrollbar will grow or shrink in inverse proportion
2378 to the difference between the <tt/lower/ and <tt/upper/ values of its
2379 adjustment.
2380
2381 You probably won't ever need to attach a handler to this signal,
2382 unless you're writing a new type of range widget.  However, if you
2383 change any of the values in a GtkAdjustment directly, you should emit
2384 this signal on it to reconfigure whatever widgets are using it, like
2385 this:
2386
2387 <tscreen><verb>
2388 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2389 </verb></tscreen>
2390
2391 Now go forth and adjust!
2392 </sect1>
2393 </sect>
2394
2395 <!-- ***************************************************************** -->
2396 <sect> Range Widgets<label id="sec_Range_Widgets">
2397 <!-- ***************************************************************** -->
2398
2399 <p>
2400 The category of range widgets includes the ubiquitous scrollbar widget
2401 and the less common "scale" widget. Though these two types of widgets
2402 are generally used for different purposes, they are quite similar in
2403 function and implementation. All range widgets share a set of common
2404 graphic elements, each of which has its own X window and receives
2405 events. They all contain a "trough" and a "slider" (what is sometimes
2406 called a "thumbwheel" in other GUI environments). Dragging the slider
2407 with the pointer moves it back and forth within the trough, while
2408 clicking in the trough advances the slider towards the location of the
2409 click, either completely, or by a designated amount, depending on
2410 which mouse button is used.
2411
2412 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2413 all range widgets are associated with an adjustment object, from which
2414 they calculate the length of the slider and it's position within the
2415 trough. When the user manipulates the slider, the range widget will
2416 change the value of the adjustment.
2417
2418 <!-- ----------------------------------------------------------------- -->
2419 <sect1> Scrollbar Widgets
2420 <p>
2421 These are your standard, run-of-the-mill scrollbars. These should be
2422 used only for scrolling some other widget, such as a list, a text box,
2423 or a viewport (and it's generally easier to use the scrolled window
2424 widget in most cases).  For other purposes, you should use scale
2425 widgets, as they are friendlier and more featureful.
2426
2427 There are separate types for horizontal and vertical scrollbars.
2428 There really isn't much to say about these. You create them with the
2429 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2430 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2431
2432 <tscreen><verb>
2433 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2434
2435 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2436 </verb></tscreen>
2437
2438 and that's about it (if you don't believe me, look in the header
2439 files!).  The <tt/adjustment/ argument can either be a pointer to an
2440 existing GtkAdjustment, or NULL, in which case one will be created for
2441 you. Specifying NULL might actually be useful in this case, if you
2442 wish to pass the newly-created adjustment to the constructor function
2443 of some other widget which will configure it for you, such as a text
2444 widget.
2445 </sect1>
2446
2447 <!-- ----------------------------------------------------------------- -->
2448 <sect1> Scale Widgets
2449 <p>
2450 Scale widgets are used to allow the user to visually select and
2451 manipulate a value within a specific range. You might want to use a
2452 scale widget, for example, to adjust the magnification level on a
2453 zoomed preview of a picture, or to control the brightness of a colour,
2454 or to specify the number of minutes of inactivity before a screensaver
2455 takes over the screen.
2456
2457 <!-- ----------------------------------------------------------------- -->
2458 <sect2>Creating a Scale Widget
2459 <p>
2460 As with scrollbars, there are separate widget types for horizontal and
2461 vertical scale widgets. (Most programmers seem to favour horizontal
2462 scale widgets). Since they work essentially the same way, there's no
2463 need to treat them separately here. The following functions, defined
2464 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2465 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2466 widgets, respectively:
2467
2468 <tscreen>
2469 <verb>
2470 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2471
2472 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2473 </verb>
2474 </tscreen>
2475
2476 The <tt/adjustment/ argument can either be an adjustment which has
2477 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2478 which case, an anonymous GtkAdjustment is created with all of its
2479 values set to <tt/0.0/ (which isn't very useful in this case). In
2480 order to avoid confusing yourself, you probably want to create your
2481 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2482 value actually corresponds to the highest value the user can select.
2483 (If you're <em/already/ thoroughly confused, read the section on <ref
2484 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2485 what exactly adjustments do and how to create and manipulate them).
2486
2487 <!-- ----------------------------------------------------------------- -->
2488 <sect2> Functions and Signals (well, functions, at least)
2489 <p>
2490 Scale widgets can display their current value as a number beside the
2491 trough. The default behaviour is to show the value, but you can change
2492 this with this function:
2493
2494 <tscreen><verb>
2495 void gtk_scale_set_draw_value( GtkScale *scale,
2496                                gint      draw_value );
2497 </verb></tscreen>
2498
2499 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2500 <tt/FALSE/, with predictable consequences for either one.
2501
2502 The value displayed by a scale widget is rounded to one decimal point
2503 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2504 change this with:
2505
2506 <tscreen>
2507 <verb>
2508 void gtk_scale_set_digits( GtkScale *scale,
2509                             gint     digits );
2510 </verb>
2511 </tscreen>
2512
2513 where <tt/digits/ is the number of decimal places you want. You can
2514 set <tt/digits/ to anything you like, but no more than 13 decimal
2515 places will actually be drawn on screen.
2516
2517 Finally, the value can be drawn in different positions
2518 relative to the trough:
2519
2520 <tscreen>
2521 <verb>
2522 void gtk_scale_set_value_pos( GtkScale        *scale,
2523                               GtkPositionType  pos );
2524 </verb>
2525 </tscreen>
2526
2527 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2528 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2529 following values:
2530
2531 <itemize>
2532 <item> GTK_POS_LEFT
2533 <item> GTK_POS_RIGHT
2534 <item> GTK_POS_TOP
2535 <item> GTK_POS_BOTTOM
2536 </itemize>
2537
2538 If you position the value on the "side" of the trough (e.g. on the top
2539 or bottom of a horizontal scale widget), then it will follow the
2540 slider up and down the trough.
2541
2542 All the preceding functions are defined in
2543 <tt>&lt;gtk/gtkscale.h&gt;</tt>.
2544 </sect2>
2545 </sect1>
2546
2547 <!-- ----------------------------------------------------------------- -->
2548 <sect1> Common Functions <label id="sec_Range_Functions">
2549 <p>
2550 The GtkRange widget class is fairly complicated internally, but, like
2551 all the "base class" widgets, most of its complexity is only
2552 interesting if you want to hack on it. Also, almost all of the
2553 functions and signals it defines are only really used in writing
2554 derived widgets. There are, however, a few useful functions that are
2555 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2556 widgets.
2557
2558 <!-- ----------------------------------------------------------------- -->
2559 <sect2> Setting the Update Policy
2560 <p>
2561 The "update policy" of a range widget defines at what points during
2562 user interaction it will change the <tt/value/ field of its
2563 GtkAdjustment and emit the "value_changed" signal on this
2564 GtkAdjustment. The update policies, defined in
2565 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2566 are:
2567
2568 <itemize>
2569 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2570 "value_changed" signal is emitted continuously, i.e. whenever the
2571 slider is moved by even the tiniest amount.
2572 </item>
2573 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2574 only emitted once the slider has stopped moving and the user has
2575 released the mouse button.
2576 </item>
2577 <item>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emitted
2578 when the user releases the mouse button, or if the slider stops moving
2579 for a short period of time.
2580 </item>
2581 </itemize>
2582
2583 The update policy of a range widget can be set by casting it using the
2584 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2585
2586 <tscreen><verb>
2587 void gtk_range_set_update_policy( GtkRange      *range,
2588                                   GtkUpdateType  policy) ;
2589 </verb></tscreen>
2590
2591 <!-- ----------------------------------------------------------------- -->
2592 <sect2>Getting and Setting Adjustments
2593 <p>
2594 Getting and setting the adjustment for a range widget "on the fly" is
2595 done, predictably, with:
2596
2597 <tscreen><verb>
2598 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2599
2600 void gtk_range_set_adjustment( GtkRange      *range,
2601                                GtkAdjustment *adjustment );
2602 </verb></tscreen>
2603
2604 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2605 which <tt/range/ is connected.
2606
2607 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2608 the adjustment that <tt/range/ is already using, regardless of whether
2609 you changed any of its fields or not. If you pass it a new
2610 GtkAdjustment, it will unreference the old one if it exists (possibly
2611 destroying it), connect the appropriate signals to the new one, and
2612 call the private function <tt/gtk_range_adjustment_changed()/, which
2613 will (or at least, is supposed to...) recalculate the size and/or
2614 position of the slider and redraw if necessary. As mentioned in the
2615 section on adjustments, if you wish to reuse the same GtkAdjustment,
2616 when you modify its values directly, you should emit the "changed"
2617 signal on it, like this:
2618
2619 <tscreen><verb>
2620 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2621 </verb></tscreen>
2622 </sect2>
2623 </sect1>
2624
2625 <!-- ----------------------------------------------------------------- -->
2626 <sect1> Key and Mouse bindings
2627 <p>
2628 All of the GTK+ range widgets react to mouse clicks in more or less
2629 the same way. Clicking button-1 in the trough will cause its
2630 adjustment's <tt/page_increment/ to be added or subtracted from its
2631 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2632 button-2 in the trough will jump the slider to the point at which the
2633 button was clicked. Clicking any button on a scrollbar's arrows will
2634 cause its adjustment's value to change <tt/step_increment/ at a time.
2635
2636 It may take a little while to get used to, but by default, scrollbars
2637 as well as scale widgets can take the keyboard focus in GTK+. If you
2638 think your users will find this too confusing, you can always disable
2639 this by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:
2640
2641 <tscreen><verb>
2642 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2643 </verb></tscreen>
2644
2645 The key bindings (which are, of course, only active when the widget
2646 has focus) are slightly different between horizontal and vertical
2647 range widgets, for obvious reasons. They are also not quite the same
2648 for scale widgets as they are for scrollbars, for somewhat less
2649 obvious reasons (possibly to avoid confusion between the keys for
2650 horizontal and vertical scrollbars in scrolled windows, where both
2651 operate on the same area).
2652
2653 <sect2> Vertical Range Widgets
2654 <p>
2655 All vertical range widgets can be operated with the up and down arrow
2656 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2657 arrows move the slider up and down by <tt/step_increment/, while
2658 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2659
2660 The user can also move the slider all the way to one end or the other
2661 of the trough using the keyboard. With the GtkVScale widget, this is
2662 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2663 GtkVScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2664 and <tt>Control-Page Down</tt>.
2665
2666 <!-- ----------------------------------------------------------------- -->
2667 <sect2> Horizontal Range Widgets
2668 <p>
2669 The left and right arrow keys work as you might expect in these
2670 widgets, moving the slider back and forth by <tt/step_increment/. The
2671 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2672 For the GtkHScale widget, moving the slider by <tt/page_increment/ is
2673 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2674 while for GtkHScrollbar, it's done with <tt>Control-Home</tt> and
2675 <tt>Control-End</tt>.
2676 </sect2>
2677 </sect1>
2678
2679 <!-- ----------------------------------------------------------------- -->
2680 <sect1> Example<label id="sec_Range_Example">
2681 <p>
2682 This example is a somewhat modified version of the "range controls"
2683 test from <tt/testgtk.c/. It basically puts up a window with three
2684 range widgets all connected to the same adjustment, and a couple of
2685 controls for adjusting some of the parameters mentioned above and in
2686 the seciton on adjustments, so you can see how they affect the way
2687 these widgets work for the user.
2688
2689 <tscreen><verb>
2690 /* example-start rangewidgets rangewidgets.c */
2691
2692 #include <gtk/gtk.h>
2693
2694 GtkWidget *hscale, *vscale;
2695
2696 void cb_pos_menu_select( GtkWidget       *item,
2697                          GtkPositionType  pos )
2698 {
2699     /* Set the value position on both scale widgets */
2700     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2701     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2702 }
2703
2704 void cb_update_menu_select( GtkWidget     *item,
2705                             GtkUpdateType  policy )
2706 {
2707     /* Set the update policy for both scale widgets */
2708     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2709     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2710 }
2711
2712 void cb_digits_scale( GtkAdjustment *adj )
2713 {
2714     /* Set the number of decimal places to which adj->value is rounded */
2715     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2716     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2717 }
2718
2719 void cb_page_size( GtkAdjustment *get,
2720                    GtkAdjustment *set )
2721 {
2722     /* Set the page size and page increment size of the sample
2723      * adjustment to the value specified by the "Page Size" scale */
2724     set->page_size = get->value;
2725     set->page_increment = get->value;
2726     /* Now emit the "changed" signal to reconfigure all the widgets that
2727      * are attached to this adjustment */
2728     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2729 }
2730
2731 void cb_draw_value( GtkToggleButton *button )
2732 {
2733     /* Turn the value display on the scale widgets off or on depending
2734      *  on the state of the checkbutton */
2735     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2736     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2737 }
2738
2739 /* Convenience functions */
2740
2741 GtkWidget *make_menu_item( gchar         *name,
2742                            GtkSignalFunc  callback,
2743                            gpointer       data )
2744 {
2745     GtkWidget *item;
2746   
2747     item = gtk_menu_item_new_with_label (name);
2748     gtk_signal_connect (GTK_OBJECT (item), "activate",
2749                         callback, data);
2750     gtk_widget_show (item);
2751
2752     return(item);
2753 }
2754
2755 void scale_set_default_values( GtkScale *scale )
2756 {
2757     gtk_range_set_update_policy (GTK_RANGE (scale),
2758                                  GTK_UPDATE_CONTINUOUS);
2759     gtk_scale_set_digits (scale, 1);
2760     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2761     gtk_scale_set_draw_value (scale, TRUE);
2762 }
2763
2764 /* makes the sample window */
2765
2766 void create_range_controls( void )
2767 {
2768     GtkWidget *window;
2769     GtkWidget *box1, *box2, *box3;
2770     GtkWidget *button;
2771     GtkWidget *scrollbar;
2772     GtkWidget *separator;
2773     GtkWidget *opt, *menu, *item;
2774     GtkWidget *label;
2775     GtkWidget *scale;
2776     GtkObject *adj1, *adj2;
2777
2778     /* Standard window-creating stuff */
2779     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2780     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2781                         GTK_SIGNAL_FUNC(gtk_main_quit),
2782                         NULL);
2783     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2784
2785     box1 = gtk_vbox_new (FALSE, 0);
2786     gtk_container_add (GTK_CONTAINER (window), box1);
2787     gtk_widget_show (box1);
2788
2789     box2 = gtk_hbox_new (FALSE, 10);
2790     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2791     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2792     gtk_widget_show (box2);
2793
2794     /* calue, lower, upper, step_increment, page_increment, page_size */
2795     /* Note that the page_size value only makes a difference for
2796      * scrollbar widgets, and the highest value you'll get is actually
2797      * (upper - page_size). */
2798     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2799   
2800     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2801     scale_set_default_values (GTK_SCALE (vscale));
2802     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2803     gtk_widget_show (vscale);
2804
2805     box3 = gtk_vbox_new (FALSE, 10);
2806     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2807     gtk_widget_show (box3);
2808
2809     /* Reuse the same adjustment */
2810     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2811     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2812     scale_set_default_values (GTK_SCALE (hscale));
2813     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2814     gtk_widget_show (hscale);
2815
2816     /* Reuse the same adjustment again */
2817     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2818     /* Notice how this causes the scales to always be updated
2819      * continuously when the scrollbar is moved */
2820     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2821                                  GTK_UPDATE_CONTINUOUS);
2822     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2823     gtk_widget_show (scrollbar);
2824
2825     box2 = gtk_hbox_new (FALSE, 10);
2826     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2827     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2828     gtk_widget_show (box2);
2829
2830     /* A checkbutton to control whether the value is displayed or not */
2831     button = gtk_check_button_new_with_label("Display value on scale widgets");
2832     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2833     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2834                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2835     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2836     gtk_widget_show (button);
2837   
2838     box2 = gtk_hbox_new (FALSE, 10);
2839     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2840
2841     /* An option menu to change the position of the value */
2842     label = gtk_label_new ("Scale Value Position:");
2843     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2844     gtk_widget_show (label);
2845   
2846     opt = gtk_option_menu_new();
2847     menu = gtk_menu_new();
2848
2849     item = make_menu_item ("Top",
2850                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2851                            GINT_TO_POINTER (GTK_POS_TOP));
2852     gtk_menu_append (GTK_MENU (menu), item);
2853   
2854     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2855                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2856     gtk_menu_append (GTK_MENU (menu), item);
2857   
2858     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2859                            GINT_TO_POINTER (GTK_POS_LEFT));
2860     gtk_menu_append (GTK_MENU (menu), item);
2861   
2862     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2863                             GINT_TO_POINTER (GTK_POS_RIGHT));
2864     gtk_menu_append (GTK_MENU (menu), item);
2865   
2866     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2867     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2868     gtk_widget_show (opt);
2869
2870     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2871     gtk_widget_show (box2);
2872
2873     box2 = gtk_hbox_new (FALSE, 10);
2874     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2875
2876     /* Yet another option menu, this time for the update policy of the
2877      * scale widgets */
2878     label = gtk_label_new ("Scale Update Policy:");
2879     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2880     gtk_widget_show (label);
2881   
2882     opt = gtk_option_menu_new();
2883     menu = gtk_menu_new();
2884   
2885     item = make_menu_item ("Continuous",
2886                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2887                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2888     gtk_menu_append (GTK_MENU (menu), item);
2889   
2890     item = make_menu_item ("Discontinuous",
2891                             GTK_SIGNAL_FUNC (cb_update_menu_select),
2892                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2893     gtk_menu_append (GTK_MENU (menu), item);
2894   
2895     item = make_menu_item ("Delayed",
2896                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2897                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2898     gtk_menu_append (GTK_MENU (menu), item);
2899   
2900     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2901     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2902     gtk_widget_show (opt);
2903   
2904     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2905     gtk_widget_show (box2);
2906
2907     box2 = gtk_hbox_new (FALSE, 10);
2908     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2909   
2910     /* A GtkHScale widget for adjusting the number of digits on the
2911      * sample scales. */
2912     label = gtk_label_new ("Scale Digits:");
2913     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2914     gtk_widget_show (label);
2915
2916     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
2917     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2918                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
2919     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2920     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2921     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2922     gtk_widget_show (scale);
2923
2924     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2925     gtk_widget_show (box2);
2926   
2927     box2 = gtk_hbox_new (FALSE, 10);
2928     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2929   
2930     /* And, one last GtkHScale widget for adjusting the page size of the
2931      * scrollbar. */
2932     label = gtk_label_new ("Scrollbar Page Size:");
2933     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2934     gtk_widget_show (label);
2935
2936     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
2937     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2938                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
2939     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2940     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2941     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2942     gtk_widget_show (scale);
2943
2944     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2945     gtk_widget_show (box2);
2946
2947     separator = gtk_hseparator_new ();
2948     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2949     gtk_widget_show (separator);
2950
2951     box2 = gtk_vbox_new (FALSE, 10);
2952     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2953     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2954     gtk_widget_show (box2);
2955
2956     button = gtk_button_new_with_label ("Quit");
2957     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2958                                GTK_SIGNAL_FUNC(gtk_main_quit),
2959                                NULL);
2960     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2961     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2962     gtk_widget_grab_default (button);
2963     gtk_widget_show (button);
2964
2965     gtk_widget_show (window);
2966 }
2967
2968 int main( int   argc,
2969           char *argv[] )
2970 {
2971     gtk_init(&amp;argc, &amp;argv);
2972
2973     create_range_controls();
2974
2975     gtk_main();
2976
2977     return(0);
2978 }
2979
2980 /* example-end */
2981 </verb></tscreen>
2982 </sect1>
2983 </sect>
2984
2985 <!-- ***************************************************************** -->
2986 <sect> Miscellaneous Widgets
2987 <!-- ***************************************************************** -->
2988
2989 <!-- ----------------------------------------------------------------- -->
2990 <sect1> Labels
2991 <p>
2992 Labels are used a lot in GTK, and are relatively simple. Labels emit
2993 no signals as they do not have an associated X window. If you need to
2994 catch signals, or do clipping, use the <ref id="sec_EventBox"
2995 name="EventBox"> widget.
2996
2997 To create a new label, use:
2998
2999 <tscreen><verb>
3000 GtkWidget *gtk_label_new( char *str );
3001 </verb></tscreen>
3002
3003 Where the sole argument is the string you wish the label to display.
3004
3005 To change the label's text after creation, use the function:
3006
3007 <tscreen><verb>
3008 void gtk_label_set_text( GtkLabel *label,
3009                          char     *str );
3010 </verb></tscreen>
3011
3012 Where the first argument is the label you created previously (cast
3013 using the GTK_LABEL() macro), and the second is the new string.
3014
3015 The space needed for the new string will be automatically adjusted if
3016 needed. You can produce multi-line labels by putting line breaks in
3017 the label string.
3018
3019 To retrieve the current string, use:
3020
3021 <tscreen><verb>
3022 void gtk_label_get( GtkLabel  *label,
3023                     char     **str );
3024 </verb></tscreen>
3025
3026 Where the first argument is the label you've created, and the second,
3027 the return for the string. Do not free the return string, as it is
3028 used internally by GTK.
3029
3030 The label text can be justified using:
3031
3032 <tscreen><verb>
3033 void gtk_label_set_justify( GtkLabel         *label,
3034                             GtkJustification  jtype );
3035 </verb></tscreen>
3036
3037 Values for <tt/jtype/ are:
3038 <itemize>
3039 <item> GTK_JUSTIFY_LEFT
3040 <item> GTK_JUSTIFY_RIGHT
3041 <item> GTK_JUSTIFY_CENTER (the default)
3042 <item> GTK_JUSTIFY_FILL
3043 </itemize>
3044
3045 The label widget is also capable of line wrapping the text
3046 automatically. This can be activated using:
3047
3048 <tscreen><verb>
3049 void gtk_label_set_line_wrap (GtkLabel *label,
3050                               gboolean  wrap);
3051 </verb></tscreen>
3052
3053 The <//wrap/ argument takes a TRUE or FALSE value.
3054
3055 If you want your label underlined, then you can set a pattern on the
3056 label:
3057
3058 <tscreen><verb>
3059 void       gtk_label_set_pattern   (GtkLabel          *label,
3060                                     const gchar       *pattern);
3061 </verb></tscreen>
3062
3063 The pattern argument indicates how the underlining should look. It
3064 consists of a string of underscore and space characters. An underscore
3065 indicates that the corresponding character in the label should be
3066 underlined. For example, the string <verb/"__     __"/ would underline the
3067 first two characters and eigth and ninth characters.
3068
3069 Below is a short example to illustrate these functions. This example
3070 makes use of the Frame widget to better demonstrate the label
3071 styles. You can ignore this for now as the <ref id="sec_Frames"
3072 name="Frame"> widget is explained later on.
3073
3074 <tscreen><verb>
3075 /* example-start label label.c */
3076
3077 #include <gtk/gtk.h>
3078
3079 int main( int   argc,
3080           char *argv[] )
3081 {
3082   static GtkWidget *window = NULL;
3083   GtkWidget *hbox;
3084   GtkWidget *vbox;
3085   GtkWidget *frame;
3086   GtkWidget *label;
3087
3088   /* Initialise GTK */
3089   gtk_init(&amp;argc, &amp;argv);
3090
3091   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3092   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3093                       GTK_SIGNAL_FUNC(gtk_main_quit),
3094                       NULL);
3095
3096   gtk_window_set_title (GTK_WINDOW (window), "Label");
3097   vbox = gtk_vbox_new (FALSE, 5);
3098   hbox = gtk_hbox_new (FALSE, 5);
3099   gtk_container_add (GTK_CONTAINER (window), hbox);
3100   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3101   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3102   
3103   frame = gtk_frame_new ("Normal Label");
3104   label = gtk_label_new ("This is a Normal label");
3105   gtk_container_add (GTK_CONTAINER (frame), label);
3106   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3107   
3108   frame = gtk_frame_new ("Multi-line Label");
3109   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3110                          "Third line");
3111   gtk_container_add (GTK_CONTAINER (frame), label);
3112   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3113   
3114   frame = gtk_frame_new ("Left Justified Label");
3115   label = gtk_label_new ("This is a Left-Justified\n" \
3116                          "Multi-line label.\nThird      line");
3117   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3118   gtk_container_add (GTK_CONTAINER (frame), label);
3119   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3120   
3121   frame = gtk_frame_new ("Right Justified Label");
3122   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3123                          "Fourth line, (j/k)");
3124   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3125   gtk_container_add (GTK_CONTAINER (frame), label);
3126   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3127
3128   vbox = gtk_vbox_new (FALSE, 5);
3129   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3130   frame = gtk_frame_new ("Line wrapped label");
3131   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3132                          "should not be taking up the entire             " /* big space to test spacing */\
3133                          "width allocated to it, but automatically " \
3134                          "wraps the words to fit.  " \
3135                          "The time has come, for all good men, to come to " \
3136                          "the aid of their party.  " \
3137                          "The sixth sheik's six sheep's sick.\n" \
3138                          "     It supports multiple paragraphs correctly, " \
3139                          "and  correctly   adds "\
3140                          "many          extra  spaces. ");
3141   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3142   gtk_container_add (GTK_CONTAINER (frame), label);
3143   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3144   
3145   frame = gtk_frame_new ("Filled, wrapped label");
3146   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3147                          "It should be taking "\
3148                          "up the entire              width allocated to it.  " \
3149                          "Here is a seneance to prove "\
3150                          "my point.  Here is another sentence. "\
3151                          "Here comes the sun, do de do de do.\n"\
3152                          "    This is a new paragraph.\n"\
3153                          "    This is another newer, longer, better " \
3154                          "paragraph.  It is coming to an end, "\
3155                          "unfortunately.");
3156   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3157   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3158   gtk_container_add (GTK_CONTAINER (frame), label);
3159   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3160   
3161   frame = gtk_frame_new ("Underlined label");
3162   label = gtk_label_new ("This label is underlined!\n"
3163                          "This one is underlined in quite a funky fashion");
3164   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3165   gtk_label_set_pattern (GTK_LABEL (label),
3166                          "_________________________ _ _________ _ ______     __ _______ ___");
3167   gtk_container_add (GTK_CONTAINER (frame), label);
3168   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3169   
3170   gtk_widget_show_all (window);
3171
3172   gtk_main ();
3173   
3174   return(0);
3175 }
3176 /* example-end */
3177 </verb></tscreen>
3178
3179 <!-- ----------------------------------------------------------------- -->
3180 <sect1> Arrows
3181 <p>
3182 The Arrow widget draws an arrowhead, facing in a number of possible
3183 directions and having a number of possible styles. It can be very
3184 useful when placed on a button in many applications.
3185
3186 There are only two functions for manipulating an Arrow widget:
3187
3188 <tscreen><verb>
3189 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3190                           GtkShadowType  shadow_type );
3191
3192 void gtk_arrow_set( GtkArrow      *arrow,
3193                     GtkArrowType   arrow_type,
3194                     GtkShadowType  shadow_type );
3195 </verb></tscreen>
3196
3197 The first creates a new arrow widget with the indicated type and
3198 appearance. The second allows these values to be altered
3199 retrospectively. The <tt/arrow_type/ argument may take one of the
3200 following values:
3201
3202 <itemize>
3203 <item> GTK_ARROW_UP
3204 <item> GTK_ARROW_DOWN
3205 <item> GTK_ARROW_LEFT
3206 <item> GTK_ARROW_RIGHT
3207 </itemize>
3208
3209 These values obviously indicate the direction in which the arrow will
3210 point. The <tt/shadow_type/ argument may take one of these values:
3211
3212 <itemize>
3213 <item> GTK_SHADOW_IN
3214 <item> GTK_SHADOW_OUT (the default)
3215 <item> GTK_SHADOW_ETCHED_IN
3216 <item> GTK_SHADOW_ETCHED_OUT
3217 </itemize>
3218
3219 Here's a brief example to illustrate their use.
3220
3221 <tscreen><verb>
3222 /* example-start arrow arrow.c */
3223
3224 #include <gtk/gtk.h>
3225
3226 /* Create an Arrow widget with the specified parameters
3227  * and pack it into a button */
3228 GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3229                                 GtkShadowType shadow_type )
3230 {
3231   GtkWidget *button;
3232   GtkWidget *arrow;
3233
3234   button = gtk_button_new();
3235   arrow = gtk_arrow_new (arrow_type, shadow_type);
3236
3237   gtk_container_add (GTK_CONTAINER (button), arrow);
3238   
3239   gtk_widget_show(button);
3240   gtk_widget_show(arrow);
3241
3242   return(button);
3243 }
3244
3245 int main( int   argc,
3246           char *argv[] )
3247 {
3248   /* GtkWidget is the storage type for widgets */
3249   GtkWidget *window;
3250   GtkWidget *button;
3251   GtkWidget *box;
3252
3253   /* Initialize the toolkit */
3254   gtk_init (&amp;argc, &amp;argv);
3255
3256   /* Create a new window */
3257   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3258
3259   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3260
3261   /* It's a good idea to do this for all windows. */
3262   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3263                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3264
3265   /* Sets the border width of the window. */
3266   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3267
3268   /* Create a box to hold the arrows/buttons */
3269   box = gtk_hbox_new (FALSE, 0);
3270   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3271   gtk_container_add (GTK_CONTAINER (window), box);
3272
3273   /* Pack and show all our widgets */
3274   gtk_widget_show(box);
3275
3276   button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN);
3277   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3278
3279   button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3280   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3281   
3282   button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3283   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3284   
3285   button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3286   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3287   
3288   gtk_widget_show (window);
3289   
3290   /* Rest in gtk_main and wait for the fun to begin! */
3291   gtk_main ();
3292   
3293   return(0);
3294 }
3295 /* example-end */
3296 </verb></tscreen>
3297
3298 <!-- ----------------------------------------------------------------- -->
3299 <sect1>The Tooltips Widget
3300 <p>
3301 These are the little text strings that pop up when you leave your
3302 pointer over a button or other widget for a few seconds. They are easy
3303 to use, so I will just explain them without giving an example. If you
3304 want to see some code, take a look at the testgtk.c program
3305 distributed with GTK.
3306
3307 Widgets that do not receieve events (widgets that do not have their
3308 own window) will not work with tooltips.
3309
3310 The first call you will use creates a new tooltip. You only need to do
3311 this once for a set of tooltips as the <tt/GtkTooltip/ object this
3312 function returns can be used to create multiple tooltips.
3313
3314 <tscreen><verb>
3315 GtkTooltips *gtk_tooltips_new( void );
3316 </verb></tscreen>
3317
3318 Once you have created a new tooltip, and the widget you wish to use it
3319 on, simply use this call to set it:
3320
3321 <tscreen><verb>
3322 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3323                            GtkWidget   *widget,
3324                            const gchar *tip_text,
3325                            const gchar *tip_private );
3326 </verb></tscreen>
3327
3328 The first argument is the tooltip you've already created, followed by
3329 the widget you wish to have this tooltip pop up for, and the text you
3330 wish it to say. The last argument is a text string that can be used as
3331 an identifier when using GtkTipsQuery to implement context sensitive
3332 help. For now, you can set it to NULL.
3333
3334 <!-- TODO: sort out what how to do the context sensitive help -->
3335
3336 Here's a short example:
3337
3338 <tscreen><verb>
3339 GtkTooltips *tooltips;
3340 GtkWidget *button;
3341 .
3342 .
3343 .
3344 tooltips = gtk_tooltips_new ();
3345 button = gtk_button_new_with_label ("button 1");
3346 .
3347 .
3348 .
3349 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3350 </verb></tscreen>
3351
3352 There are other calls that can be used with tooltips. I will just list
3353 them with a brief description of what they do.
3354
3355 <tscreen><verb>
3356 void gtk_tooltips_enable( GtkTooltips *tooltips );
3357 </verb></tscreen>
3358
3359 Enable a disabled set of tooltips.
3360
3361 <tscreen><verb>
3362 void gtk_tooltips_disable( GtkTooltips *tooltips );
3363 </verb></tscreen>
3364
3365 Disable an enabled set of tooltips.
3366
3367 <tscreen><verb>
3368 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3369                              gint         delay );
3370
3371 </verb></tscreen>
3372
3373 Sets how many milliseconds you have to hold your pointer over the
3374 widget before the tooltip will pop up. The default is 500
3375 milliseconds (half a second).
3376
3377 <tscreen><verb>
3378 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3379                               GdkColor    *background,
3380                               GdkColor    *foreground );
3381 </verb></tscreen>
3382
3383 Set the foreground and background color of the tooltips.
3384
3385 And that's all the functions associated with tooltips. More than
3386 you'll ever want to know :-)
3387
3388 <!-- ----------------------------------------------------------------- -->
3389 <sect1> Progress Bars <label id="sec_ProgressBar">
3390 <p>
3391 Progress bars are used to show the status of an operation. They are
3392 pretty easy to use, as you will see with the code below. But first
3393 lets start out with the calls to create a new progress bar.
3394
3395 There are two ways to create a progress bar, one simple one takes
3396 no arguments, and one that takes a GtkAdjustment object as an
3397 argument. If the former is used, the progress bar creates it's own
3398 adjustment object.
3399
3400 <tscreen><verb>
3401 GtkWidget *gtk_progress_bar_new( void );
3402
3403 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3404 </verb></tscreen>
3405
3406 The second method has the advantage that we can use the adjustment
3407 object to specify our own range parameters for the progress bar.
3408
3409 Now that the progress bar has been created we can use it.
3410
3411 <tscreen><verb>
3412 void gtk_progress_bar_update( GtkProgressBar *pbar,
3413                               gfloat          percentage );
3414 </verb></tscreen>
3415
3416 The first argument is the progress bar you wish to operate on, and the
3417 second argument is the amount 'completed', meaning the amount the
3418 progress bar has been filled from 0-100%. This is passed to the
3419 function as a real number ranging from 0 to 1.
3420
3421 GTK v1.1 has added new functionality to the progress bar that enables
3422 it to display it's value in different ways, and to inform the user of
3423 its current value and its range.
3424
3425 A progress bar may be set to one of a number of orientations using the
3426 function
3427
3428 <tscreen><verb>
3429 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3430                                        GtkProgressBarOrientation orientation );
3431 </verb></tscreen>
3432
3433 Where the <tt/orientation/ argument may take one of the following
3434 values to indicate the direction in which the progress bar moves:
3435
3436 <itemize>
3437 <item> GTK_PROGRESS_LEFT_TO_RIGHT
3438 <item> GTK_PROGRESS_RIGHT_TO_LEFT
3439 <item> GTK_PROGRESS_BOTTOM_TO_TOP
3440 <item> GTK_PROGRESS_TOP_TO_BOTTOM
3441 </itemize>
3442
3443 When used as a measure of how far a process has progressed, the
3444 GtkProgressBar can be set to display it's value in either a continuous
3445 or discrete mode. In continuous mode, the progress bar is updated for
3446 each value. In discrete mode, the progress bar is updated in a number
3447 of discrete blocks. The number of blocks is also configurable.
3448
3449 The style of a progress bar can be set using the following function.
3450
3451 <tscreen><verb>
3452 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3453                                      GtkProgressBarStyle  style );
3454 </verb></tscreen>
3455
3456 The <tt/style/ parameter can take one of two values:
3457
3458 <itemize>
3459 <item>GTK_PROGRESS_CONTINUOUS
3460 <item>GTK_PROGRESS_DISCRETE
3461 </itemize>
3462
3463 The number of discrete blocks can be set by calling
3464
3465 <tscreen><verb>
3466 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3467                                            guint           blocks );
3468 </verb></tscreen>
3469
3470 As well as indicating the amount of progress that has occured, the
3471 progress bar may be set to just indicate that there is some
3472 activity. This can be useful in situations where progress cannot be
3473 measured against a value range. Activity mode is not effected by the
3474 bar style that is described above, and overrides it.This mode is
3475 selected by the following function.
3476
3477 <tscreen><verb>
3478 void gtk_progress_set_activity_mode( GtkProgress *progress,
3479                                      guint        activity_mode );
3480 </verb></tscreen>
3481
3482 The step size of the activity indicator, and the number of blocks are
3483 set using the following functions.
3484
3485 <tscreen><verb>
3486 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3487                                          guint           step );
3488
3489 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3490                                            guint           blocks );
3491 </verb></tscreen>
3492
3493 When in continuous mode, the progress bar can also display a
3494 configurable text string within it's trough, using the following
3495 function.
3496
3497 <tscreen><verb>
3498 void gtk_progress_set_format_string( GtkProgress *progress,
3499                                      gchar       *format);
3500 </verb></tscreen>
3501
3502 The <tt/format/ argument is similiar to one that would be used in a C
3503 <tt/printf/ statement. The following directives may be used within the
3504 format string:
3505
3506 <itemize>
3507 <item> %p - percentage
3508 <item> %v - value
3509 <item> %l - lower range value
3510 <item> %u - upper range value
3511 </itemize>
3512  
3513 Progress Bars are usually used with timeouts or other such functions
3514 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3515 Functions">) to give the illusion of multitasking. All will employ the
3516 gtk_progress_bar_update function in the same manner.
3517
3518 Here is an example of the progress bar, updated using timeouts.  This
3519 code also shows you how to reset the Progress Bar.
3520
3521 <tscreen><verb>
3522 /* example-start progressbar progressbar.c */
3523
3524 #include <gtk/gtk.h>
3525
3526 typedef struct _ProgressData {
3527     GtkWidget *window;
3528     GtkWidget *pbar;
3529     int timer;
3530 } ProgressData;
3531
3532 /* Update the value of the progress bar so that we get
3533  * some movement */
3534 gint progress_timeout( gpointer data )
3535 {
3536     gfloat new_val;
3537     GtkAdjustment *adj;
3538
3539     adj = GTK_PROGRESS (data)->adjustment;
3540
3541     /* Calculate the value of the progress bar using the
3542      * value range set in the adjustment object */
3543     new_val = adj->value + 1;
3544     if (new_val > adj->upper)
3545       new_val = adj->lower;
3546
3547     /* Set the new value */
3548     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3549
3550     /* As this is a timeout function, return TRUE so that it
3551      * continues to get called */
3552     return(TRUE);
3553
3554
3555 /* Callback that toggles the text display within the progress
3556  * bar trough */
3557 void toggle_show_text( GtkWidget    *widget,
3558                        ProgressData *pdata )
3559 {
3560     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3561                                 GTK_TOGGLE_BUTTON (widget)->active);
3562 }
3563
3564 /* Callback that toggles the activity mode of the progress
3565  * bar */
3566 void toggle_activity_mode( GtkWidget    *widget,
3567                            ProgressData *pdata )
3568 {
3569     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3570                                     GTK_TOGGLE_BUTTON (widget)->active);
3571 }
3572
3573 /* Callback that toggles the continuous mode of the progress
3574  * bar */
3575 void set_continuous_mode( GtkWidget    *widget,
3576                           ProgressData *pdata )
3577 {
3578     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3579                                     GTK_PROGRESS_CONTINUOUS);
3580 }
3581
3582 /* Callback that toggles the discrete mode of the progress
3583  * bar */
3584 void set_discrete_mode( GtkWidget    *widget,
3585                         ProgressData *pdata )
3586 {
3587     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3588                                     GTK_PROGRESS_DISCRETE);
3589 }
3590  
3591 /* Clean up allocated memory and remove the timer */
3592 void destroy_progress( GtkWidget     *widget,
3593                        ProgressData *pdata)
3594 {
3595     gtk_timeout_remove (pdata->timer);
3596     pdata->timer = 0;
3597     pdata->window = NULL;
3598     g_free(pdata);
3599     gtk_main_quit();
3600 }
3601
3602 int main( int   argc,
3603           char *argv[])
3604 {
3605     ProgressData *pdata;
3606     GtkWidget *align;
3607     GtkWidget *separator;
3608     GtkWidget *table;
3609     GtkAdjustment *adj;
3610     GtkWidget *button;
3611     GtkWidget *check;
3612     GtkWidget *vbox;
3613
3614     gtk_init (&amp;argc, &amp;argv);
3615
3616     /* Allocate memory for the data that is passwd to the callbacks */
3617     pdata = g_malloc( sizeof(ProgressData) );
3618   
3619     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3620     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3621
3622     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3623                         GTK_SIGNAL_FUNC (destroy_progress),
3624                         pdata);
3625     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3626     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3627
3628     vbox = gtk_vbox_new (FALSE, 5);
3629     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3630     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3631     gtk_widget_show(vbox);
3632   
3633     /* Create a centering alignment object */
3634     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3635     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3636     gtk_widget_show(align);
3637
3638     /* Create a GtkAdjusment object to hold the range of the
3639      * progress bar */
3640     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3641
3642     /* Create the GtkProgressBar using the adjustment */
3643     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3644
3645     /* Set the format of the string that can be displayed in the
3646      * trough of the progress bar:
3647      * %p - percentage
3648      * %v - value
3649      * %l - lower range value
3650      * %u - upper range value */
3651     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3652                                     "%v from [%l-%u] (=%p%%)");
3653     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3654     gtk_widget_show(pdata->pbar);
3655
3656     /* Add a timer callback to update the value of the progress bar */
3657     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3658
3659     separator = gtk_hseparator_new ();
3660     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3661     gtk_widget_show(separator);
3662
3663     /* rows, columns, homogeneous */
3664     table = gtk_table_new (2, 3, FALSE);
3665     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3666     gtk_widget_show(table);
3667
3668     /* Add a check button to select displaying of the trough text */
3669     check = gtk_check_button_new_with_label ("Show text");
3670     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3671                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3672                       5, 5);
3673     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3674                         GTK_SIGNAL_FUNC (toggle_show_text),
3675                         pdata);
3676     gtk_widget_show(check);
3677
3678     /* Add a check button to toggle activity mode */
3679     check = gtk_check_button_new_with_label ("Activity mode");
3680     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3681                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3682                       5, 5);
3683     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3684                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3685                         pdata);
3686     gtk_widget_show(check);
3687
3688     separator = gtk_vseparator_new ();
3689     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3690                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3691                       5, 5);
3692     gtk_widget_show(separator);
3693
3694     /* Add a radio button to select continuous display mode */
3695     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3696     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3697                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3698                       5, 5);
3699     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3700                         GTK_SIGNAL_FUNC (set_continuous_mode),
3701                         pdata);
3702     gtk_widget_show (button);
3703
3704     /* Add a radio button to select discrete display mode */
3705     button = gtk_radio_button_new_with_label(
3706                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3707                "Discrete");
3708     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3709                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3710                       5, 5);
3711     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3712                         GTK_SIGNAL_FUNC (set_discrete_mode),
3713                         pdata);
3714     gtk_widget_show (button);
3715
3716     separator = gtk_hseparator_new ();
3717     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3718     gtk_widget_show(separator);
3719
3720     /* Add a button to exit the program */
3721     button = gtk_button_new_with_label ("close");
3722     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3723                                (GtkSignalFunc) gtk_widget_destroy,
3724                                GTK_OBJECT (pdata->window));
3725     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3726
3727     /* This makes it so the button is the default. */
3728     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3729
3730     /* This grabs this button to be the default button. Simply hitting
3731      * the "Enter" key will cause this button to activate. */
3732     gtk_widget_grab_default (button);
3733     gtk_widget_show(button);
3734
3735     gtk_widget_show (pdata->window);
3736
3737     gtk_main ();
3738     
3739     return(0);
3740 }
3741 /* example-end */
3742 </verb></tscreen>
3743
3744 <!-- ----------------------------------------------------------------- -->
3745 <sect1> Dialogs
3746 <p>
3747 The Dialog widget is very simple, and is actually just a window with a
3748 few things pre-packed into it for you. The structure for a Dialog is:
3749
3750 <tscreen><verb>
3751 struct GtkDialog
3752 {
3753       GtkWindow window;
3754     
3755       GtkWidget *vbox;
3756       GtkWidget *action_area;
3757 };
3758 </verb></tscreen>
3759
3760 So you see, it simply creates a window, and then packs a vbox into the
3761 top, then a separator, and then an hbox for the "action_area".
3762
3763 The Dialog widget can be used for pop-up messages to the user, and
3764 other similar tasks. It is really basic, and there is only one
3765 function for the dialog box, which is:
3766
3767 <tscreen><verb>
3768 GtkWidget *gtk_dialog_new( void );
3769 </verb></tscreen>
3770
3771 So to create a new dialog box, use,
3772
3773 <tscreen><verb>
3774     GtkWidget *window;
3775     window = gtk_dialog_new ();
3776 </verb></tscreen>
3777
3778 This will create the dialog box, and it is now up to you to use it.
3779 you could pack a button in the action_area by doing something like this:
3780
3781 <tscreen><verb>
3782     button = ...
3783     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3784                         button, TRUE, TRUE, 0);
3785     gtk_widget_show (button);
3786 </verb></tscreen>
3787
3788 And you could add to the vbox area by packing, for instance, a label 
3789 in it, try something like this:
3790
3791 <tscreen><verb>
3792     label = gtk_label_new ("Dialogs are groovy");
3793     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3794                         label, TRUE, TRUE, 0);
3795     gtk_widget_show (label);
3796 </verb></tscreen>
3797
3798 As an example in using the dialog box, you could put two buttons in
3799 the action_area, a Cancel button and an Ok button, and a label in the
3800 vbox area, asking the user a question or giving an error etc. Then
3801 you could attach a different signal to each of the buttons and perform
3802 the operation the user selects.
3803
3804 If the simple functionality provided by the default vertical and
3805 horizontal boxes in the two areas does't give you enough control for
3806 your application, then you can simply pack another layout widget into
3807 the boxes provided. For example, you could pack a table into the
3808 vertical box.
3809
3810 <!-- ----------------------------------------------------------------- -->
3811 <sect1> Pixmaps <label id="sec_Pixmaps">
3812 <p>
3813 Pixmaps are data structures that contain pictures. These pictures can
3814 be used in various places, but most visibly as icons on the X-Windows
3815 desktop, or as cursors. A bitmap is a 2-color pixmap.
3816
3817 To use pixmaps in GTK, we must first build a GdkPixmap structure using
3818 routines from the GDK layer. Pixmaps can either be created from
3819 in-memory data, or from data read from a file. We'll go through each
3820 of the calls to create a pixmap.
3821
3822 <tscreen><verb>
3823 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
3824                                         gchar     *data,
3825                                         gint       width,
3826                                         gint       height );
3827 </verb></tscreen>
3828
3829 This routine is used to create a single-plane pixmap (2 colors) from
3830 data in memory. Each bit of the data represents whether that pixel is
3831 off or on. Width and height are in pixels. The GdkWindow pointer is
3832 to the current window, since a pixmap resources are meaningful only in
3833 the context of the screen where it is to be displayed.
3834
3835 <tscreen><verb>
3836 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
3837                                         gchar     *data,
3838                                         gint       width,
3839                                         gint       height,
3840                                         gint       depth,
3841                                         GdkColor  *fg,
3842                                         GdkColor  *bg );
3843 </verb></tscreen>
3844
3845 This is used to create a pixmap of the given depth (number of colors) from
3846 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
3847 background color to use.
3848
3849 <tscreen><verb>
3850 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
3851                                        GdkBitmap  **mask,
3852                                        GdkColor    *transparent_color,
3853                                        const gchar *filename );
3854 </verb></tscreen>
3855
3856 XPM format is a readable pixmap representation for the X Window
3857 System. It is widely used and many different utilities are available
3858 for creating image files in this format. The file specified by
3859 filename must contain an image in that format and it is loaded into
3860 the pixmap structure. The mask specifies which bits of the pixmap are
3861 opaque. All other bits are colored using the color specified by
3862 transparent_color. An example using this follows below.
3863
3864 <tscreen><verb>
3865 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
3866                                          GdkBitmap **mask,
3867                                          GdkColor   *transparent_color,
3868                                          gchar     **data );
3869 </verb></tscreen>
3870
3871 Small images can be incorporated into a program as data in the XPM
3872 format.  A pixmap is created using this data, instead of reading it
3873 from a file.  An example of such data is
3874
3875 <tscreen><verb>
3876 /* XPM */
3877 static const char * xpm_data[] = {
3878 "16 16 3 1",
3879 "       c None",
3880 ".      c #000000000000",
3881 "X      c #FFFFFFFFFFFF",
3882 "                ",
3883 "   ......       ",
3884 "   .XXX.X.      ",
3885 "   .XXX.XX.     ",
3886 "   .XXX.XXX.    ",
3887 "   .XXX.....    ",
3888 "   .XXXXXXX.    ",
3889 "   .XXXXXXX.    ",
3890 "   .XXXXXXX.    ",
3891 "   .XXXXXXX.    ",
3892 "   .XXXXXXX.    ",
3893 "   .XXXXXXX.    ",
3894 "   .XXXXXXX.    ",
3895 "   .........    ",
3896 "                ",
3897 "                "};
3898 </verb></tscreen>
3899
3900 When we're done using a pixmap and not likely to reuse it again soon,
3901 it is a good idea to release the resource using
3902 gdk_pixmap_unref(). Pixmaps should be considered a precious resource.
3903
3904 Once we've created a pixmap, we can display it as a GTK widget. We
3905 must create a GTK pixmap widget to contain the GDK pixmap. This is
3906 done using
3907
3908 <tscreen><verb>
3909 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
3910                            GdkBitmap *mask );
3911 </verb></tscreen>
3912
3913 The other pixmap widget calls are
3914
3915 <tscreen><verb>
3916 guint gtk_pixmap_get_type( void );
3917
3918 void  gtk_pixmap_set( GtkPixmap  *pixmap,
3919                       GdkPixmap  *val,
3920                       GdkBitmap  *mask );
3921
3922 void  gtk_pixmap_get( GtkPixmap  *pixmap,
3923                       GdkPixmap **val,
3924                       GdkBitmap **mask);
3925 </verb></tscreen>
3926
3927 gtk_pixmap_set is used to change the pixmap that the widget is currently
3928 managing. Val is the pixmap created using GDK.
3929
3930 The following is an example of using a pixmap in a button.
3931
3932 <tscreen><verb>
3933 /* example-start pixmap pixmap.c */
3934
3935 #include <gtk/gtk.h>
3936
3937
3938 /* XPM data of Open-File icon */
3939 static const char * xpm_data[] = {
3940 "16 16 3 1",
3941 "       c None",
3942 ".      c #000000000000",
3943 "X      c #FFFFFFFFFFFF",
3944 "                ",
3945 "   ......       ",
3946 "   .XXX.X.      ",
3947 "   .XXX.XX.     ",
3948 "   .XXX.XXX.    ",
3949 "   .XXX.....    ",
3950 "   .XXXXXXX.    ",
3951 "   .XXXXXXX.    ",
3952 "   .XXXXXXX.    ",
3953 "   .XXXXXXX.    ",
3954 "   .XXXXXXX.    ",
3955 "   .XXXXXXX.    ",
3956 "   .XXXXXXX.    ",
3957 "   .........    ",
3958 "                ",
3959 "                "};
3960
3961
3962 /* when invoked (via signal delete_event), terminates the application.
3963  */
3964 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
3965     gtk_main_quit();
3966 }
3967
3968
3969 /* is invoked when the button is clicked.  It just prints a message.
3970  */
3971 void button_clicked( GtkWidget *widget, gpointer data ) {
3972     printf( "button clicked\n" );
3973 }
3974
3975 int main( int argc, char *argv[] )
3976 {
3977     /* GtkWidget is the storage type for widgets */
3978     GtkWidget *window, *pixmapwid, *button;
3979     GdkPixmap *pixmap;
3980     GdkBitmap *mask;
3981     GtkStyle *style;
3982     
3983     /* create the main window, and attach delete_event signal to terminating
3984        the application */
3985     gtk_init( &amp;argc, &amp;argv );
3986     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3987     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
3988                         GTK_SIGNAL_FUNC (close_application), NULL );
3989     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
3990     gtk_widget_show( window );
3991
3992     /* now for the pixmap from gdk */
3993     style = gtk_widget_get_style( window );
3994     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
3995                                            &amp;style->bg[GTK_STATE_NORMAL],
3996                                            (gchar **)xpm_data );
3997
3998     /* a pixmap widget to contain the pixmap */
3999     pixmapwid = gtk_pixmap_new( pixmap, mask );
4000     gtk_widget_show( pixmapwid );
4001
4002     /* a button to contain the pixmap widget */
4003     button = gtk_button_new();
4004     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
4005     gtk_container_add( GTK_CONTAINER(window), button );
4006     gtk_widget_show( button );
4007
4008     gtk_signal_connect( GTK_OBJECT(button), "clicked",
4009                         GTK_SIGNAL_FUNC(button_clicked), NULL );
4010
4011     /* show the window */
4012     gtk_main ();
4013           
4014     return 0;
4015 }
4016 /* example-end */
4017 </verb></tscreen>
4018
4019 To load a file from an XPM data file called icon0.xpm in the current
4020 directory, we would have created the pixmap thus
4021
4022 <tscreen><verb>
4023     /* load a pixmap from a file */
4024     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
4025                                          &amp;style->bg[GTK_STATE_NORMAL],
4026                                          "./icon0.xpm" );
4027     pixmapwid = gtk_pixmap_new( pixmap, mask );
4028     gtk_widget_show( pixmapwid );
4029     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
4030 </verb></tscreen>
4031
4032 A disadvantage of using pixmaps is that the displayed object is always
4033 rectangular, regardless of the image. We would like to create desktops
4034 and applications with icons that have more natural shapes. For
4035 example, for a game interface, we would like to have round buttons to
4036 push. The way to do this is using shaped windows.
4037
4038 A shaped window is simply a pixmap where the background pixels are
4039 transparent. This way, when the background image is multi-colored, we
4040 don't overwrite it with a rectangular, non-matching border around our
4041 icon. The following example displays a full wheelbarrow image on the
4042 desktop.
4043
4044 <tscreen><verb>
4045 /* example-start wheelbarrow wheelbarrow.c */
4046
4047 #include <gtk/gtk.h>
4048
4049 /* XPM */
4050 static char * WheelbarrowFull_xpm[] = {
4051 "48 48 64 1",
4052 "       c None",
4053 ".      c #DF7DCF3CC71B",
4054 "X      c #965875D669A6",
4055 "o      c #71C671C671C6",
4056 "O      c #A699A289A699",
4057 "+      c #965892489658",
4058 "@      c #8E38410330C2",
4059 "#      c #D75C7DF769A6",
4060 "$      c #F7DECF3CC71B",
4061 "%      c #96588A288E38",
4062 "&amp;      c #A69992489E79",
4063 "*      c #8E3886178E38",
4064 "=      c #104008200820",
4065 "-      c #596510401040",
4066 ";      c #C71B30C230C2",
4067 ":      c #C71B9A699658",
4068 ">      c #618561856185",
4069 ",      c #20811C712081",
4070 "<      c #104000000000",
4071 "1      c #861720812081",
4072 "2      c #DF7D4D344103",
4073 "3      c #79E769A671C6",
4074 "4      c #861782078617",
4075 "5      c #41033CF34103",
4076 "6      c #000000000000",
4077 "7      c #49241C711040",
4078 "8      c #492445144924",
4079 "9      c #082008200820",
4080 "0      c #69A618611861",
4081 "q      c #B6DA71C65144",
4082 "w      c #410330C238E3",
4083 "e      c #CF3CBAEAB6DA",
4084 "r      c #71C6451430C2",
4085 "t      c #EFBEDB6CD75C",
4086 "y      c #28A208200820",
4087 "u      c #186110401040",
4088 "i      c #596528A21861",
4089 "p      c #71C661855965",
4090 "a      c #A69996589658",
4091 "s      c #30C228A230C2",
4092 "d      c #BEFBA289AEBA",
4093 "f      c #596545145144",
4094 "g      c #30C230C230C2",
4095 "h      c #8E3882078617",
4096 "j      c #208118612081",
4097 "k      c #38E30C300820",
4098 "l      c #30C2208128A2",
4099 "z      c #38E328A238E3",
4100 "x      c #514438E34924",
4101 "c      c #618555555965",
4102 "v      c #30C2208130C2",
4103 "b      c #38E328A230C2",
4104 "n      c #28A228A228A2",
4105 "m      c #41032CB228A2",
4106 "M      c #104010401040",
4107 "N      c #492438E34103",
4108 "B      c #28A2208128A2",
4109 "V      c #A699596538E3",
4110 "C      c #30C21C711040",
4111 "Z      c #30C218611040",
4112 "A      c #965865955965",
4113 "S      c #618534D32081",
4114 "D      c #38E31C711040",
4115 "F      c #082000000820",
4116 "                                                ",
4117 "          .XoO                                  ",
4118 "         +@#$%o&amp;                                ",
4119 "         *=-;#::o+                              ",
4120 "           >,<12#:34                            ",
4121 "             45671#:X3                          ",
4122 "               +89<02qwo                        ",
4123 "e*                >,67;ro                       ",
4124 "ty>                 459@>+&amp;&amp;                    ",
4125 "$2u+                  ><ipas8*                  ",
4126 "%$;=*                *3:.Xa.dfg>                ",
4127 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
4128 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
4129 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
4130 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
4131 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
4132 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
4133 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
4134 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
4135 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
4136 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
4137 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
4138 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
4139 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
4140 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
4141 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
4142 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
4143 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
4144 "              p;<69BvwwsszslllbBlllllllu<5+     ",
4145 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
4146 "               c1-699Blvlllllu7k96MMMg4         ",
4147 "               *10y8n6FjvllllB<166668           ",
4148 "                S-kg+>666<M<996-y6n<8*          ",
4149 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
4150 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
4151 "                 N-k-<>     >=01-kuu666>        ",
4152 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
4153 "                 Ou0<>       o66y<ulw<66&amp;       ",
4154 "                  *kk5       >66By7=xu664       ",
4155 "                   <<M4      466lj<Mxu66o       ",
4156 "                   *>>       +66uv,zN666*       ",
4157 "                              566,xxj669        ",
4158 "                              4666FF666>        ",
4159 "                               >966666M         ",
4160 "                                oM6668+         ",
4161 "                                  *4            ",
4162 "                                                ",
4163 "                                                "};
4164
4165
4166 /* When invoked (via signal delete_event), terminates the application */
4167 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4168     gtk_main_quit();
4169 }
4170
4171 int main (int argc, char *argv[])
4172 {
4173     /* GtkWidget is the storage type for widgets */
4174     GtkWidget *window, *pixmap, *fixed;
4175     GdkPixmap *gdk_pixmap;
4176     GdkBitmap *mask;
4177     GtkStyle *style;
4178     GdkGC *gc;
4179     
4180     /* Create the main window, and attach delete_event signal to terminate
4181      * the application.  Note that the main window will not have a titlebar
4182      * since we're making it a popup. */
4183     gtk_init (&amp;argc, &amp;argv);
4184     window = gtk_window_new( GTK_WINDOW_POPUP );
4185     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4186                         GTK_SIGNAL_FUNC (close_application), NULL);
4187     gtk_widget_show (window);
4188
4189     /* Now for the pixmap and the pixmap widget */
4190     style = gtk_widget_get_default_style();
4191     gc = style->black_gc;
4192     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
4193                                              &amp;style->bg[GTK_STATE_NORMAL],
4194                                              WheelbarrowFull_xpm );
4195     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
4196     gtk_widget_show( pixmap );
4197
4198     /* To display the pixmap, we use a fixed widget to place the pixmap */
4199     fixed = gtk_fixed_new();
4200     gtk_widget_set_usize( fixed, 200, 200 );
4201     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
4202     gtk_container_add( GTK_CONTAINER(window), fixed );
4203     gtk_widget_show( fixed );
4204
4205     /* This masks out everything except for the image itself */
4206     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
4207     
4208     /* show the window */
4209     gtk_widget_set_uposition( window, 20, 400 );
4210     gtk_widget_show( window );
4211     gtk_main ();
4212           
4213     return(0);
4214 }
4215 /* example-end */
4216 </verb></tscreen>
4217
4218 To make the wheelbarrow image sensitive, we could attach the button
4219 press event signal to make it do something. The following few lines
4220 would make the picture sensitive to a mouse button being pressed which
4221 makes the application terminate.
4222
4223 <tscreen><verb>
4224     gtk_widget_set_events( window,
4225                           gtk_widget_get_events( window ) |
4226                           GDK_BUTTON_PRESS_MASK );
4227
4228    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
4229                        GTK_SIGNAL_FUNC(close_application), NULL );
4230 </verb></tscreen>
4231
4232 <!-- ----------------------------------------------------------------- -->
4233 <sect1>Rulers
4234 <p>
4235 Ruler widgets are used to indicate the location of the mouse pointer
4236 in a given window. A window can have a vertical ruler spanning across
4237 the width and a horizontal ruler spanning down the height. A small
4238 triangular indicator on the ruler shows the exact location of the
4239 pointer relative to the ruler.
4240
4241 A ruler must first be created. Horizontal and vertical rulers are
4242 created using
4243
4244 <tscreen><verb>
4245 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4246
4247 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4248 </verb></tscreen>
4249
4250 Once a ruler is created, we can define the unit of measurement. Units
4251 of measure for rulers can be GTK_PIXELS, GTK_INCHES or
4252 GTK_CENTIMETERS. This is set using
4253
4254 <tscreen><verb>
4255 void gtk_ruler_set_metric( GtkRuler      *ruler,
4256                            GtkMetricType  metric );
4257 </verb></tscreen>
4258
4259 The default measure is GTK_PIXELS.
4260
4261 <tscreen><verb>
4262     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4263 </verb></tscreen>
4264
4265 Other important characteristics of a ruler are how to mark the units
4266 of scale and where the position indicator is initially placed. These
4267 are set for a ruler using
4268
4269 <tscreen><verb>
4270 void gtk_ruler_set_range( GtkRuler *ruler,
4271                           gfloat    lower,
4272                           gfloat    upper,
4273                           gfloat    position,
4274                           gfloat    max_size );
4275 </verb></tscreen>
4276
4277 The lower and upper arguments define the extent of the ruler, and
4278 max_size is the largest possible number that will be displayed.
4279 Position defines the initial position of the pointer indicator within
4280 the ruler.
4281
4282 A vertical ruler can span an 800 pixel wide window thus
4283
4284 <tscreen><verb>
4285     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4286 </verb></tscreen>
4287
4288 The markings displayed on the ruler will be from 0 to 800, with a
4289 number for every 100 pixels. If instead we wanted the ruler to range
4290 from 7 to 16, we would code
4291
4292 <tscreen><verb>
4293     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4294 </verb></tscreen>
4295
4296 The indicator on the ruler is a small triangular mark that indicates
4297 the position of the pointer relative to the ruler. If the ruler is
4298 used to follow the mouse pointer, the motion_notify_event signal
4299 should be connected to the motion_notify_event method of the ruler.
4300 To follow all mouse movements within a window area, we would use
4301
4302 <tscreen><verb>
4303 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4304
4305     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4306            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4307            GTK_OBJECT(ruler) );
4308 </verb></tscreen>
4309
4310 The following example creates a drawing area with a horizontal ruler
4311 above it and a vertical ruler to the left of it. The size of the
4312 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4313 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4314 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4315 Placement of the drawing area and the rulers is done using a table.
4316
4317 <tscreen><verb>
4318 /* example-start rulers rulers.c */
4319
4320 #include <gtk/gtk.h>
4321
4322 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4323
4324 #define XSIZE  600
4325 #define YSIZE  400
4326
4327 /* This routine gets control when the close button is clicked */
4328 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4329     gtk_main_quit();
4330 }
4331
4332 /* The main routine */
4333 int main( int argc, char *argv[] ) {
4334     GtkWidget *window, *table, *area, *hrule, *vrule;
4335
4336     /* Initialize GTK and create the main window */
4337     gtk_init( &amp;argc, &amp;argv );
4338
4339     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4340     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4341             GTK_SIGNAL_FUNC( close_application ), NULL);
4342     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4343
4344     /* Create a table for placing the ruler and the drawing area */
4345     table = gtk_table_new( 3, 2, FALSE );
4346     gtk_container_add( GTK_CONTAINER(window), table );
4347
4348     area = gtk_drawing_area_new();
4349     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4350     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4351                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4352     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
4353
4354     /* The horizontal ruler goes on top. As the mouse moves across the drawing area,
4355      * a motion_notify_event is passed to the appropriate event handler for the ruler. */
4356     hrule = gtk_hruler_new();
4357     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4358     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4359     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4360                                (GtkSignalFunc)EVENT_METHOD(hrule, motion_notify_event),
4361                                GTK_OBJECT(hrule) );
4362     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4363     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4364                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4365     
4366     /* The vertical ruler goes on the left. As the mouse moves across the drawing area,
4367      * a motion_notify_event is passed to the appropriate event handler for the ruler. */
4368     vrule = gtk_vruler_new();
4369     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4370     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4371     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4372                                (GtkSignalFunc)
4373                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->motion_notify_event,
4374                                GTK_OBJECT(vrule) );
4375     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4376                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4377
4378     /* Now show everything */
4379     gtk_widget_show( area );
4380     gtk_widget_show( hrule );
4381     gtk_widget_show( vrule );
4382     gtk_widget_show( table );
4383     gtk_widget_show( window );
4384     gtk_main();
4385
4386     return(0);
4387 }
4388 /* example-end */
4389 </verb></tscreen>
4390
4391 <!-- ----------------------------------------------------------------- -->
4392 <sect1>Statusbars
4393 <p>
4394 Statusbars are simple widgets used to display a text message. They
4395 keep a stack of the messages pushed onto them, so that popping the
4396 current message will re-display the previous text message.
4397
4398 In order to allow different parts of an application to use the same
4399 statusbar to display messages, the statusbar widget issues Context
4400 Identifiers which are used to identify different 'users'. The message
4401 on top of the stack is the one displayed, no matter what context it is
4402 in. Messages are stacked in last-in-first-out order, not context
4403 identifier order.
4404
4405 A statusbar is created with a call to:
4406
4407 <tscreen><verb>
4408 GtkWidget *gtk_statusbar_new( void );
4409 </verb></tscreen>
4410
4411 A new Context Identifier is requested using a call to the following 
4412 function with a short textual description of the context:
4413
4414 <tscreen><verb>
4415 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4416                                     const gchar  *context_description );
4417 </verb></tscreen>
4418
4419 There are three functions that can operate on statusbars:
4420
4421 <tscreen><verb>
4422 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4423                           guint         context_id,
4424                           gchar        *text );
4425
4426 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4427                         guint         context_id );
4428
4429 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4430                            guint         context_id,
4431                            guint         message_id ); 
4432 </verb></tscreen>
4433
4434 The first, gtk_statusbar_push, is used to add a new message to the
4435 statusbar.  It returns a Message Identifier, which can be passed later
4436 to the function gtk_statusbar_remove to remove the message with the
4437 given Message and Context Identifiers from the statusbar's stack.
4438
4439 The function gtk_statusbar_pop removes the message highest in the
4440 stack with the given Context Identifier.
4441
4442 The following example creates a statusbar and two buttons, one for
4443 pushing items onto the statusbar, and one for popping the last item
4444 back off.
4445
4446 <tscreen><verb>
4447 /* example-start statusbar statusbar.c */
4448
4449 #include <gtk/gtk.h>
4450 #include <glib.h>
4451
4452 GtkWidget *status_bar;
4453
4454 void push_item (GtkWidget *widget, gpointer data)
4455 {
4456   static int count = 1;
4457   char buff[20];
4458
4459   g_snprintf(buff, 20, "Item %d", count++);
4460   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4461
4462   return;
4463 }
4464
4465 void pop_item (GtkWidget *widget, gpointer data)
4466 {
4467   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4468   return;
4469 }
4470
4471 int main (int argc, char *argv[])
4472 {
4473
4474     GtkWidget *window;
4475     GtkWidget *vbox;
4476     GtkWidget *button;
4477
4478     gint context_id;
4479
4480     gtk_init (&amp;argc, &amp;argv);
4481
4482     /* create a new window */
4483     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4484     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4485     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4486     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4487                        (GtkSignalFunc) gtk_exit, NULL);
4488  
4489     vbox = gtk_vbox_new(FALSE, 1);
4490     gtk_container_add(GTK_CONTAINER(window), vbox);
4491     gtk_widget_show(vbox);
4492           
4493     status_bar = gtk_statusbar_new();      
4494     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4495     gtk_widget_show (status_bar);
4496
4497     context_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(status_bar), "Statusbar example");
4498
4499     button = gtk_button_new_with_label("push item");
4500     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4501         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4502     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4503     gtk_widget_show(button);              
4504
4505     button = gtk_button_new_with_label("pop last item");
4506     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4507         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4508     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4509     gtk_widget_show(button);              
4510
4511     /* always display the window as the last step so it all splashes on
4512      * the screen at once. */
4513     gtk_widget_show(window);
4514
4515     gtk_main ();
4516
4517     return 0;
4518 }
4519 /* example-end */
4520 </verb></tscreen>
4521
4522 <!-- ----------------------------------------------------------------- -->
4523 <sect1>Text Entries
4524 <p>
4525 The Entry widget allows text to be typed and displayed in a single line
4526 text box. The text may be set with function calls that allow new text
4527 to replace, prepend or append the current contents of the Entry widget.
4528
4529 There are two functions for creating Entry widgets:
4530
4531 <tscreen><verb>
4532 GtkWidget *gtk_entry_new( void );
4533
4534 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4535 </verb></tscreen>
4536
4537 The first just creates a new Entry widget, whilst the second creates a
4538 new Entry and sets a limit on the length of the text within the Entry.
4539
4540 There are several functions for altering the text which is currently
4541 within the Entry widget.
4542
4543 <tscreen><verb>
4544 void gtk_entry_set_text( GtkEntry    *entry,
4545                          const gchar *text );
4546
4547 void gtk_entry_append_text( GtkEntry    *entry,
4548                             const gchar *text );
4549
4550 void gtk_entry_prepend_text( GtkEntry    *entry,
4551                              const gchar *text );
4552 </verb></tscreen>
4553
4554 The function gtk_entry_set_text sets the contents of the Entry widget,
4555 replacing the current contents. The functions gtk_entry_append_text
4556 and gtk_entry_prepend_text allow the current contents to be appended
4557 and prepended to.
4558
4559 The next function allows the current insertion point to be set.
4560
4561 <tscreen><verb>
4562 void gtk_entry_set_position( GtkEntry *entry,
4563                              gint      position );
4564 </verb></tscreen>
4565
4566 The contents of the Entry can be retrieved by using a call to the
4567 following function. This is useful in the callback functions described below.
4568
4569 <tscreen><verb>
4570 gchar *gtk_entry_get_text( GtkEntry *entry );
4571 </verb></tscreen>
4572
4573 If we don't want the contents of the Entry to be changed by someone typing
4574 into it, we can change its editable state.
4575
4576 <tscreen><verb>
4577 void gtk_entry_set_editable( GtkEntry *entry,
4578                              gboolean  editable );
4579 </verb></tscreen>
4580
4581 The function above allows us to toggle the editable state of the
4582 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4583 argument.
4584
4585 If we are using the Entry where we don't want the text entered to be
4586 visible, for example when a password is being entered, we can use the
4587 following function, which also takes a boolean flag.
4588
4589 <tscreen><verb>
4590 void gtk_entry_set_visibility( GtkEntry *entry,
4591                                gboolean  visible );
4592 </verb></tscreen>
4593
4594 A region of the text may be set as selected by using the following
4595 function. This would most often be used after setting some default
4596 text in an Entry, making it easy for the user to remove it.
4597
4598 <tscreen><verb>
4599 void gtk_entry_select_region( GtkEntry *entry,
4600                               gint      start,
4601                               gint      end );
4602 </verb></tscreen>
4603
4604 If we want to catch when the user has entered text, we can connect to
4605 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4606 user hits the enter key within the Entry widget. Changed is raised
4607 when the text changes at all, e.g. for every character entered or
4608 removed.
4609
4610 The following code is an example of using an Entry widget.
4611
4612 <tscreen><verb>
4613 /* example-start entry entry.c */
4614
4615 #include <gtk/gtk.h>
4616
4617 void enter_callback(GtkWidget *widget, GtkWidget *entry)
4618 {
4619   gchar *entry_text;
4620   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4621   printf("Entry contents: %s\n", entry_text);
4622 }
4623
4624 void entry_toggle_editable (GtkWidget *checkbutton,
4625                                    GtkWidget *entry)
4626 {
4627   gtk_entry_set_editable(GTK_ENTRY(entry),
4628                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4629 }
4630
4631 void entry_toggle_visibility (GtkWidget *checkbutton,
4632                                    GtkWidget *entry)
4633 {
4634   gtk_entry_set_visibility(GTK_ENTRY(entry),
4635                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4636 }
4637
4638 int main (int argc, char *argv[])
4639 {
4640
4641     GtkWidget *window;
4642     GtkWidget *vbox, *hbox;
4643     GtkWidget *entry;
4644     GtkWidget *button;
4645     GtkWidget *check;
4646
4647     gtk_init (&amp;argc, &amp;argv);
4648
4649     /* create a new window */
4650     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4651     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4652     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4653     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4654                        (GtkSignalFunc) gtk_exit, NULL);
4655
4656     vbox = gtk_vbox_new (FALSE, 0);
4657     gtk_container_add (GTK_CONTAINER (window), vbox);
4658     gtk_widget_show (vbox);
4659
4660     entry = gtk_entry_new_with_max_length (50);
4661     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4662                        GTK_SIGNAL_FUNC(enter_callback),
4663                        entry);
4664     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4665     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4666     gtk_entry_select_region (GTK_ENTRY (entry),
4667                              0, GTK_ENTRY(entry)->text_length);
4668     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4669     gtk_widget_show (entry);
4670
4671     hbox = gtk_hbox_new (FALSE, 0);
4672     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4673     gtk_widget_show (hbox);
4674                                   
4675     check = gtk_check_button_new_with_label("Editable");
4676     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4677     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4678                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4679     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4680     gtk_widget_show (check);
4681     
4682     check = gtk_check_button_new_with_label("Visible");
4683     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4684     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4685                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4686     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4687     gtk_widget_show (check);
4688                                    
4689     button = gtk_button_new_with_label ("Close");
4690     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4691                                GTK_SIGNAL_FUNC(gtk_exit),
4692                                GTK_OBJECT (window));
4693     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4694     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4695     gtk_widget_grab_default (button);
4696     gtk_widget_show (button);
4697     
4698     gtk_widget_show(window);
4699
4700     gtk_main();
4701     return(0);
4702 }
4703 /* example-end */
4704 </verb></tscreen>
4705
4706 <!-- ----------------------------------------------------------------- -->
4707 <sect1> Color Selection
4708 <p>
4709 The color selection widget is, not surprisingly, a widget for
4710 interactive selection of colors. This composite widget lets the user
4711 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
4712 Saturation, Value) triples.  This is done either by adjusting single
4713 values with sliders or entries, or by picking the desired color from a
4714 hue-saturation wheel/value bar.  Optionally, the opacity of the color
4715 can also be set.
4716
4717 The color selection widget currently emits only one signal,
4718 "color_changed", which is emitted whenever the current color in the
4719 widget changes, either when the user changes it or if it's set
4720 explicitly through gtk_color_selection_set_color().
4721
4722 Lets have a look at what the color selection widget has to offer
4723 us. The widget comes in two flavours: gtk_color_selection and
4724 gtk_color_selection_dialog.
4725
4726 <tscreen><verb>
4727 GtkWidget *gtk_color_selection_new( void );
4728 </verb></tscreen>
4729         
4730 You'll probably not be using this constructor directly. It creates an
4731 orphan GtkColorSelection widget which you'll have to parent
4732 yourself. The GtkColorSelection widget inherits from the GtkVBox
4733 widget.
4734
4735 <tscreen><verb> 
4736 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
4737 </verb></tscreen>
4738
4739 This is the most common color selection constructor. It creates a
4740 GtkColorSelectionDialog, which inherits from a GtkDialog. It consists
4741 of a GtkFrame containing a GtkColorSelection widget, a GtkHSeparator
4742 and a GtkHBox with three buttons, "Ok", "Cancel" and "Help". You can
4743 reach these buttons by accessing the "ok_button", "cancel_button" and
4744 "help_button" widgets in the GtkColorSelectionDialog structure,
4745 (i.e. GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
4746
4747 <tscreen><verb>
4748 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
4749                                             GtkUpdateType      policy );
4750 </verb></tscreen>
4751
4752 This function sets the update policy. The default policy is
4753 GTK_UPDATE_CONTINUOUS which means that the current color is updated
4754 continuously when the user drags the sliders or presses the mouse and
4755 drags in the hue-saturation wheel or value bar. If you experience
4756 performance problems, you may want to set the policy to
4757 GTK_UPDATE_DISCONTINUOUS or GTK_UPDATE_DELAYED.
4758
4759 <tscreen><verb>
4760 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
4761                                       gint               use_opacity );
4762 </verb></tscreen>
4763
4764 The color selection widget supports adjusting the opacity of a color
4765 (also known as the alpha channel). This is disabled by
4766 default. Calling this function with use_opacity set to TRUE enables
4767 opacity. Likewise, use_opacity set to FALSE will disable opacity.
4768
4769 <tscreen><verb>
4770 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
4771                                     gdouble           *color );
4772 </verb></tscreen>
4773
4774 You can set the current color explicitly by calling this function with
4775 a pointer to an array of colors (gdouble). The length of the array
4776 depends on whether opacity is enabled or not. Position 0 contains the
4777 red component, 1 is green, 2 is blue and opacity is at position 3
4778 (only if opacity is enabled, see
4779 gtk_color_selection_set_opacity()). All values are between 0.0 and
4780 1.0.
4781
4782 <tscreen><verb>
4783 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
4784                                     gdouble           *color );
4785 </verb></tscreen>
4786
4787 When you need to query the current color, typically when you've
4788 received a "color_changed" signal, you use this function. Color is a
4789 pointer to the array of colors to fill in. See the
4790 gtk_color_selection_set_color() function for the description of this
4791 array.
4792
4793 <!-- Need to do a whole section on DnD - TRG
4794 Drag and drop
4795 -------------
4796
4797 The color sample areas (right under the hue-saturation wheel) supports
4798 drag and drop. The type of drag and drop is "application/x-color". The
4799 message data consists of an array of 4 (or 5 if opacity is enabled)
4800 gdouble values, where the value at position 0 is 0.0 (opacity on) or
4801 1.0 (opacity off) followed by the red, green and blue values at
4802 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
4803 is passed in the value at position 4.
4804 -->
4805
4806 Here's a simple example demonstrating the use of the
4807 GtkColorSelectionDialog. The program displays a window containing a
4808 drawing area. Clicking on it opens a color selection dialog, and
4809 changing the color in the color selection dialog changes the
4810 background color.
4811
4812 <tscreen><verb>
4813 /* example-start colorsel colorsel.c */
4814
4815 #include <glib.h>
4816 #include <gdk/gdk.h>
4817 #include <gtk/gtk.h>
4818
4819 GtkWidget *colorseldlg = NULL;
4820 GtkWidget *drawingarea = NULL;
4821
4822 /* Color changed handler */
4823
4824 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
4825 {
4826   gdouble color[3];
4827   GdkColor gdk_color;
4828   GdkColormap *colormap;
4829
4830   /* Get drawingarea colormap */
4831
4832   colormap = gdk_window_get_colormap (drawingarea->window);
4833
4834   /* Get current color */
4835
4836   gtk_color_selection_get_color (colorsel,color);
4837
4838   /* Fit to a unsigned 16 bit integer (0..65535) and insert into the GdkColor structure */
4839
4840   gdk_color.red = (guint16)(color[0]*65535.0);
4841   gdk_color.green = (guint16)(color[1]*65535.0);
4842   gdk_color.blue = (guint16)(color[2]*65535.0);
4843
4844   /* Allocate color */
4845
4846   gdk_color_alloc (colormap, &amp;gdk_color);
4847
4848   /* Set window background color */
4849
4850   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
4851
4852   /* Clear window */
4853
4854   gdk_window_clear (drawingarea->window);
4855 }
4856
4857 /* Drawingarea event handler */
4858
4859 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
4860 {
4861   gint handled = FALSE;
4862   GtkWidget *colorsel;
4863
4864   /* Check if we've received a button pressed event */
4865
4866   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
4867     {
4868       /* Yes, we have an event and there's no colorseldlg yet! */
4869
4870       handled = TRUE;
4871
4872       /* Create color selection dialog */
4873
4874       colorseldlg = gtk_color_selection_dialog_new("Select background color");
4875
4876       /* Get the GtkColorSelection widget */
4877
4878       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
4879
4880       /* Connect to the "color_changed" signal, set the client-data to the colorsel widget */
4881
4882       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
4883         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
4884
4885       /* Show the dialog */
4886
4887       gtk_widget_show(colorseldlg);
4888     }
4889
4890   return handled;
4891 }
4892
4893 /* Close down and exit handler */
4894
4895 void destroy_window (GtkWidget *widget, gpointer client_data)
4896 {
4897   gtk_main_quit ();
4898 }
4899
4900 /* Main */
4901
4902 gint main (gint argc, gchar *argv[])
4903 {
4904   GtkWidget *window;
4905
4906   /* Initialize the toolkit, remove gtk-related commandline stuff */
4907
4908   gtk_init (&amp;argc,&amp;argv);
4909
4910   /* Create toplevel window, set title and policies */
4911
4912   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4913   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
4914   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
4915
4916   /* Attach to the "delete" and "destroy" events so we can exit */
4917
4918   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
4919     (GtkSignalFunc)destroy_window, (gpointer)window);
4920
4921   gtk_signal_connect (GTK_OBJECT(window), "destroy",
4922     (GtkSignalFunc)destroy_window, (gpointer)window);
4923   
4924   /* Create drawingarea, set size and catch button events */
4925
4926   drawingarea = gtk_drawing_area_new ();
4927
4928   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
4929
4930   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
4931
4932   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
4933     (GtkSignalFunc)area_event, (gpointer)drawingarea);
4934   
4935   /* Add drawingarea to window, then show them both */
4936
4937   gtk_container_add (GTK_CONTAINER(window), drawingarea);
4938
4939   gtk_widget_show (drawingarea);
4940   gtk_widget_show (window);
4941   
4942   /* Enter the gtk main loop (this never returns) */
4943
4944   gtk_main ();
4945
4946   /* Satisfy grumpy compilers */
4947
4948   return(0);
4949 }
4950 /* example-end */
4951 </verb></tscreen>
4952
4953 <!-- ----------------------------------------------------------------- -->
4954 <sect1> File Selections
4955 <p>
4956 The file selection widget is a quick and simple way to display a File
4957 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
4958 great way to cut down on programming time.
4959
4960 To create a new file selection box use:
4961
4962 <tscreen><verb>
4963 GtkWidget *gtk_file_selection_new( gchar *title );
4964 </verb></tscreen>
4965
4966 To set the filename, for example to bring up a specific directory, or
4967 give a default filename, use this function:
4968
4969 <tscreen><verb>
4970 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
4971                                       gchar            *filename );
4972 </verb></tscreen>
4973
4974 To grab the text that the user has entered or clicked on, use this 
4975 function:
4976
4977 <tscreen><verb>
4978 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
4979 </verb></tscreen>
4980
4981 There are also pointers to the widgets contained within the file 
4982 selection widget. These are:
4983
4984 <itemize>
4985 <item>dir_list
4986 <item>file_list
4987 <item>selection_entry
4988 <item>selection_text
4989 <item>main_vbox
4990 <item>ok_button
4991 <item>cancel_button
4992 <item>help_button
4993 </itemize>
4994
4995 Most likely you will want to use the ok_button, cancel_button, and
4996 help_button pointers in signaling their use.
4997
4998 Included here is an example stolen from testgtk.c, modified to run on
4999 its own. As you will see, there is nothing much to creating a file
5000 selection widget. While in this example the Help button appears on the
5001 screen, it does nothing as there is not a signal attached to it.
5002
5003 <tscreen><verb>
5004 /* example-start filesel filesel.c */
5005
5006 #include <gtk/gtk.h>
5007
5008 /* Get the selected filename and print it to the console */
5009 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
5010 {
5011     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
5012 }
5013
5014 void destroy (GtkWidget *widget, gpointer data)
5015 {
5016     gtk_main_quit ();
5017 }
5018
5019 int main (int argc, char *argv[])
5020 {
5021     GtkWidget *filew;
5022     
5023     gtk_init (&amp;argc, &amp;argv);
5024     
5025     /* Create a new file selection widget */
5026     filew = gtk_file_selection_new ("File selection");
5027     
5028     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
5029                         (GtkSignalFunc) destroy, &amp;filew);
5030     /* Connect the ok_button to file_ok_sel function */
5031     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
5032                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
5033     
5034     /* Connect the cancel_button to destroy the widget */
5035     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button),
5036                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
5037                                GTK_OBJECT (filew));
5038     
5039     /* Lets set the filename, as if this were a save dialog, and we are giving
5040      a default filename */
5041     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
5042                                      "penguin.png");
5043     
5044     gtk_widget_show(filew);
5045     gtk_main ();
5046     return 0;
5047 }
5048 /* example-end */
5049 </verb></tscreen>
5050
5051 <!-- ***************************************************************** -->
5052 <sect> Container Widgets
5053 <!-- ***************************************************************** -->
5054
5055 <!-- ----------------------------------------------------------------- -->   
5056 <sect1>The EventBox <label id="sec_EventBox">
5057 <p> 
5058 Some GTK widgets don't have associated X windows, so they just draw on
5059 their parents. Because of this, they cannot receive events and if they
5060 are incorrectly sized, they don't clip so you can get messy
5061 overwriting etc. If you require more from these widgets, the EventBox
5062 is for you.
5063
5064 At first glance, the EventBox widget might appear to be totally
5065 useless. It draws nothing on the screen and responds to no
5066 events. However, it does serve a function - it provides an X window
5067 for its child widget. This is important as many GTK widgets do not
5068 have an associated X window. Not having an X window saves memory and
5069 improves performance, but also has some drawbacks. A widget without an
5070 X window cannot receive events, and does not perform any clipping on
5071 its contents. Although the name <em/EventBox/ emphasizes the
5072 event-handling function, the widget can also be used for clipping.
5073 (and more, see the example below).
5074
5075 To create a new EventBox widget, use:
5076
5077 <tscreen><verb>
5078 GtkWidget *gtk_event_box_new( void );
5079 </verb></tscreen>
5080
5081 A child widget can then be added to this EventBox:
5082
5083 <tscreen><verb>
5084     gtk_container_add( GTK_CONTAINER(event_box), child_widget );
5085 </verb></tscreen>
5086
5087 The following example demonstrates both uses of an EventBox - a label
5088 is created that is clipped to a small box, and set up so that a
5089 mouse-click on the label causes the program to exit. Resizing the
5090 window reveals varying amounts of the label.
5091
5092 <tscreen><verb>
5093 /* example-start eventbox eventbox.c */
5094
5095 #include <gtk/gtk.h>
5096
5097 int 
5098 main (int argc, char *argv[])
5099 {
5100     GtkWidget *window;
5101     GtkWidget *event_box;
5102     GtkWidget *label;
5103     
5104     gtk_init (&amp;argc, &amp;argv);
5105     
5106     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5107     
5108     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
5109     
5110     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5111                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5112     
5113     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5114     
5115     /* Create an EventBox and add it to our toplevel window */
5116     
5117     event_box = gtk_event_box_new ();
5118     gtk_container_add (GTK_CONTAINER(window), event_box);
5119     gtk_widget_show (event_box);
5120     
5121     /* Create a long label */
5122     
5123     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
5124     gtk_container_add (GTK_CONTAINER (event_box), label);
5125     gtk_widget_show (label);
5126     
5127     /* Clip it short. */
5128     gtk_widget_set_usize (label, 110, 20);
5129     
5130     /* And bind an action to it */
5131     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
5132     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
5133                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5134     
5135     /* Yet one more thing you need an X window for ... */
5136     
5137     gtk_widget_realize (event_box);
5138     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
5139     
5140     gtk_widget_show (window);
5141     
5142     gtk_main ();
5143     
5144     return(0);
5145 }
5146 /* example-end */
5147 </verb></tscreen>
5148
5149 <!-- ----------------------------------------------------------------- -->   
5150 <sect1>The Alignment widget <label id="sec_Alignment">
5151 <p>
5152 The alignment widget allows you to place a widget within its window at
5153 a position and size relative to the size of the Alignment widget
5154 itself. For example, it can be very useful for centering a widget
5155 within the window.
5156
5157 There are only two functions associated with the Alignment widget:
5158
5159 <tscreen><verb>
5160 GtkWidget* gtk_alignment_new( gfloat xalign,
5161                               gfloat yalign,
5162                               gfloat xscale,
5163                               gfloat yscale );
5164
5165 void gtk_alignment_set( GtkAlignment *alignment,
5166                         gfloat        xalign,
5167                         gfloat        yalign,
5168                         gfloat        xscale,
5169                         gfloat        yscale );
5170 </verb></tscreen>
5171
5172 The first function creates a new Alignment widget with the specified
5173 parameters. The second function allows the alignment paramters of an
5174 exisiting Alignment widget to be altered.
5175
5176 All four alignment parameters are floating point numbers which can
5177 range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
5178 affect the position of the widget placed within the Alignment
5179 widget. The <tt/xscale/ and <tt/yscale/ arguments effect the amount of
5180 space allocated to the widget.
5181
5182 A child widget can be added to this Alignment widget using:
5183
5184 <tscreen><verb>
5185     gtk_container_add( GTK_CONTAINER(alignment), child_widget );
5186 </verb></tscreen>
5187
5188 For an example of using an Alignment widget, refer to the example for
5189 the <ref id="sec_ProgressBar" name="Progress Bar"> widget.
5190
5191 <!-- ----------------------------------------------------------------- -->
5192 <sect1> Fixed Container
5193 <p>
5194 The Fixed container allows you to place widgets at a fixed position
5195 within it's window, relative to it's upper left hand corner. The
5196 position of the widgets can be changed dynamically.
5197
5198 There are only three functions associated with the fixed widget:
5199
5200 <tscreen><verb>
5201 GtkWidget* gtk_fixed_new( void );
5202
5203 void gtk_fixed_put( GtkFixed  *fixed,
5204                     GtkWidget *widget,
5205                     gint16     x,
5206                     gint16     y );
5207
5208 void gtk_fixed_move( GtkFixed  *fixed,
5209                      GtkWidget *widget,
5210                      gint16     x,
5211                      gint16     y );
5212 </verb></tscreen>
5213
5214 The function <tt/gtk_fixed_new/ allows you to create a new Fixed
5215 container.
5216
5217 <tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
5218 the position specified by <tt/x/ and <tt/y/.
5219
5220 <tt/gtk_fixed_move/ allows the specified widget to be moved to a new
5221 position.
5222
5223 The following example illustrates how to use the Fixed Container.
5224
5225 <tscreen><verb>
5226 /* example-start fixed fixed.c */
5227
5228 #include <gtk/gtk.h>
5229
5230 /* I'm going to be lazy and use some global variables to
5231  * store the position of the widget within the fixed
5232  * container */
5233 gint x=50;
5234 gint y=50;
5235
5236 /* This callback function moves the button to a new position
5237  * in the Fixed container. */
5238 void move_button( GtkWidget *widget,
5239                   GtkWidget *fixed )
5240 {
5241   x = (x+30)%300;
5242   y = (y+50)%300;
5243   gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); 
5244 }
5245
5246 int main( int   argc,
5247           char *argv[] )
5248 {
5249   /* GtkWidget is the storage type for widgets */
5250   GtkWidget *window;
5251   GtkWidget *fixed;
5252   GtkWidget *button;
5253   gint i;
5254
5255   /* Initialise GTK */
5256   gtk_init(&amp;argc, &amp;argv);
5257     
5258   /* Create a new window */
5259   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5260   gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
5261
5262   /* Here we connect the "destroy" event to a signal handler */ 
5263   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5264                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5265  
5266   /* Sets the border width of the window. */
5267   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5268
5269   /* Create a Fixed Container */
5270   fixed = gtk_fixed_new();
5271   gtk_container_add(GTK_CONTAINER(window), fixed);
5272   gtk_widget_show(fixed);
5273   
5274   for (i = 1 ; i <= 3 ; i++) {
5275     /* Creates a new button with the label "Press me" */
5276     button = gtk_button_new_with_label ("Press me");
5277   
5278     /* When the button receives the "clicked" signal, it will call the
5279      * function move_button() passing it the Fixed Containter as its
5280      * argument. */
5281     gtk_signal_connect (GTK_OBJECT (button), "clicked",
5282                         GTK_SIGNAL_FUNC (move_button), fixed);
5283   
5284     /* This packs the button into the fixed containers window. */
5285     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
5286   
5287     /* The final step is to display this newly created widget. */
5288     gtk_widget_show (button);
5289   }
5290
5291   /* Display the window */
5292   gtk_widget_show (window);
5293     
5294   /* Enter the event loop */
5295   gtk_main ();
5296     
5297   return(0);
5298 }
5299 /* example-end */
5300 </verb></tscreen>
5301
5302 <!-- ----------------------------------------------------------------- -->
5303 <sect1> Frames <label id="sec_Frames">
5304 <p>
5305 Frames can be used to enclose one or a group of widgets with a box
5306 which can optionally be labelled. The position of the label and the
5307 style of the box can be altered to suit.
5308
5309 A Frame can be created with the following function:
5310
5311 <tscreen><verb>
5312 GtkWidget *gtk_frame_new( const gchar *label );
5313 </verb></tscreen>
5314
5315 The label is by default placed in the upper left hand corner of the
5316 frame. A value of NULL for the <tt/label/ argument will result in no
5317 label being displayed. The text of the label can be changed using the
5318 next function.
5319
5320 <tscreen><verb>
5321 void gtk_frame_set_label( GtkFrame    *frame,
5322                           const gchar *label );
5323 </verb></tscreen>
5324
5325 The position of the label can be changed using this function:
5326
5327 <tscreen><verb>
5328 void gtk_frame_set_label_align( GtkFrame *frame,
5329                                 gfloat    xalign,
5330                                 gfloat    yalign );
5331 </verb></tscreen>
5332
5333 <tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
5334 indicates the position of the label along the top horizontal of the
5335 frame. <tt/yalign/ is not currently used. The default value of xalign
5336 is 0.0 which places the label at the left hand end of the frame.
5337
5338 The next function alters the style of the box that is used to outline
5339 the frame.
5340
5341 <tscreen><verb>
5342 void gtk_frame_set_shadow_type( GtkFrame      *frame,
5343                                 GtkShadowType  type);
5344 </verb></tscreen>
5345
5346 The <tt/type/ argument can take one of the following values:
5347 <itemize>
5348 <item> GTK_SHADOW_NONE
5349 <item> GTK_SHADOW_IN
5350 <item> GTK_SHADOW_OUT
5351 <item> GTK_SHADOW_ETCHED_IN (the default)
5352 <item> GTK_SHADOW_ETCHED_OUT
5353 </itemize>
5354
5355 The following code example illustrates the use of the Frame widget.
5356
5357 <tscreen><verb>
5358 /* example-start frame frame.c */
5359
5360 #include <gtk/gtk.h>
5361
5362 int main( int   argc,
5363           char *argv[] )
5364 {
5365   /* GtkWidget is the storage type for widgets */
5366   GtkWidget *window;
5367   GtkWidget *frame;
5368   GtkWidget *button;
5369   gint i;
5370
5371   /* Initialise GTK */
5372   gtk_init(&amp;argc, &amp;argv);
5373     
5374   /* Create a new window */
5375   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5376   gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
5377
5378   /* Here we connect the "destroy" event to a signal handler */ 
5379   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5380                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5381
5382   gtk_widget_set_usize(window, 300, 300);
5383   /* Sets the border width of the window. */
5384   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5385
5386   /* Create a Frame */
5387   frame = gtk_frame_new(NULL);
5388   gtk_container_add(GTK_CONTAINER(window), frame);
5389
5390   /* Set the frames label */
5391   gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
5392
5393   /* Align the label at the right of the frame */
5394   gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
5395
5396   /* Set the style of the frame */
5397   gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
5398
5399   gtk_widget_show(frame);
5400   
5401   /* Display the window */
5402   gtk_widget_show (window);
5403     
5404   /* Enter the event loop */
5405   gtk_main ();
5406     
5407   return(0);
5408 }
5409 /* example-end */
5410
5411 </verb></tscreen>
5412
5413 <!-- ----------------------------------------------------------------- -->   
5414 <sect1> Aspect Frames
5415 <p>
5416 The aspect frame widget is like a frame widget, except that it also
5417 enforces the aspect ratio (that is, the ratio of the width to the
5418 height) of the child widget to have a certain value, adding extra
5419 space if necessary. This is useful, for instance, if you want to
5420 preview a larger image. The size of the preview should vary when the
5421 user resizes the window, but the aspect ratio needs to always match
5422 the original image.
5423   
5424 To create a new aspect frame use:
5425    
5426 <tscreen><verb>
5427 GtkWidget *gtk_aspect_frame_new( const gchar *label,
5428                                  gfloat       xalign,
5429                                  gfloat       yalign,
5430                                  gfloat       ratio,
5431                                  gint         obey_child);
5432 </verb></tscreen>
5433    
5434 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
5435 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
5436 widget will match the aspect ratio of the ideal size it requests.
5437 Otherwise, it is given by <tt/ratio/.
5438    
5439 To change the options of an existing aspect frame, you can use:
5440    
5441 <tscreen><verb>
5442 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
5443                            gfloat          xalign,
5444                            gfloat          yalign,
5445                            gfloat          ratio,
5446                            gint            obey_child);
5447 </verb></tscreen>
5448    
5449 As an example, the following program uses an AspectFrame to present a
5450 drawing area whose aspect ratio will always be 2:1, no matter how the
5451 user resizes the top-level window.
5452    
5453 <tscreen><verb>
5454 /* example-start aspectframe aspectframe.c */
5455
5456 #include <gtk/gtk.h>
5457    
5458 int
5459 main (int argc, char *argv[])
5460 {
5461     GtkWidget *window;
5462     GtkWidget *aspect_frame;
5463     GtkWidget *drawing_area;
5464     gtk_init (&amp;argc, &amp;argv);
5465    
5466     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5467     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
5468     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5469                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5470     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5471    
5472     /* Create an aspect_frame and add it to our toplevel window */
5473    
5474     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
5475                                          0.5, /* center x */
5476                                          0.5, /* center y */
5477                                          2, /* xsize/ysize = 2 */
5478                                          FALSE /* ignore child's aspect */);
5479    
5480     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
5481     gtk_widget_show (aspect_frame);
5482    
5483     /* Now add a child widget to the aspect frame */
5484    
5485     drawing_area = gtk_drawing_area_new ();
5486    
5487     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
5488      * window since we are forcing a 2x1 aspect ratio */
5489     gtk_widget_set_usize (drawing_area, 200, 200);
5490     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
5491     gtk_widget_show (drawing_area);
5492    
5493     gtk_widget_show (window);
5494     gtk_main ();
5495     return 0;
5496 }
5497 /* example-end */
5498 </verb></tscreen>
5499
5500 <!-- ----------------------------------------------------------------- -->   
5501 <sect1> Paned Window Widgets
5502 <p>
5503 The paned window widgets are useful when you want to divide an area
5504 into two parts, with the relative size of the two parts controlled by
5505 the user. A groove is drawn between the two portions with a handle
5506 that the user can drag to change the ratio. The division can either be
5507 horizontal (HPaned) or vertical (VPaned).
5508    
5509 To create a new paned window, call one of:
5510    
5511 <tscreen><verb>
5512 GtkWidget *gtk_hpaned_new (void);
5513
5514 GtkWidget *gtk_vpaned_new (void);
5515 </verb></tscreen>
5516
5517 After creating the paned window widget, you need to add child widgets
5518 to its two halves. To do this, use the functions:
5519    
5520 <tscreen><verb>
5521 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
5522
5523 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
5524 </verb></tscreen>
5525    
5526 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
5527 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
5528 right or bottom half of the paned window.
5529
5530 A paned widget can be changed visually using the following two
5531 functions.
5532
5533 <tscreen><verb>
5534 void gtk_paned_set_handle_size( GtkPaned *paned,
5535                                 guint16   size);
5536
5537 void gtk_paned_set_gutter_size( GtkPaned *paned,
5538                                 guint16   size);
5539 </verb></tscreen>
5540
5541 The first of these sets the size of the handle and the second sets the
5542 size of the gutter that is between the two parts of the paned window.
5543
5544 As an example, we will create part of the user interface of an
5545 imaginary email program. A window is divided into two portions
5546 vertically, with the top portion being a list of email messages and
5547 the bottom portion the text of the email message. Most of the program
5548 is pretty straightforward. A couple of points to note: text can't be
5549 added to a Text widget until it is realized. This could be done by
5550 calling <tt/gtk_widget_realize()/, but as a demonstration of an
5551 alternate technique, we connect a handler to the "realize" signal to
5552 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
5553 of the items in the table containing the text window and its
5554 scrollbars, so that when the bottom portion is made smaller, the
5555 correct portions shrink instead of being pushed off the bottom of the
5556 window.
5557
5558 <tscreen><verb>
5559 /* example-start paned paned.c */
5560
5561 #include <gtk/gtk.h>
5562    
5563 /* Create the list of "messages" */
5564 GtkWidget *
5565 create_list (void)
5566 {
5567
5568     GtkWidget *scrolled_window;
5569     GtkWidget *list;
5570     GtkWidget *list_item;
5571    
5572     int i;
5573     char buffer[16];
5574    
5575     /* Create a new scrolled window, with scrollbars only if needed */
5576     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
5577     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
5578                                     GTK_POLICY_AUTOMATIC, 
5579                                     GTK_POLICY_AUTOMATIC);
5580    
5581     /* Create a new list and put it in the scrolled window */
5582     list = gtk_list_new ();
5583     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
5584                                            list);
5585     gtk_widget_show (list);
5586    
5587     /* Add some messages to the window */
5588     for (i=0; i<10; i++) {
5589
5590         sprintf(buffer,"Message #%d",i);
5591         list_item = gtk_list_item_new_with_label (buffer);
5592         gtk_container_add (GTK_CONTAINER(list), list_item);
5593         gtk_widget_show (list_item);
5594
5595     }
5596    
5597     return scrolled_window;
5598 }
5599    
5600 /* Add some text to our text widget - this is a callback that is invoked
5601 when our window is realized. We could also force our window to be
5602 realized with gtk_widget_realize, but it would have to be part of
5603 a hierarchy first */
5604
5605 void
5606 realize_text (GtkWidget *text, gpointer data)
5607 {
5608     gtk_text_freeze (GTK_TEXT (text));
5609     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
5610     "From: pathfinder@nasa.gov\n"
5611     "To: mom@nasa.gov\n"
5612     "Subject: Made it!\n"
5613     "\n"
5614     "We just got in this morning. The weather has been\n"
5615     "great - clear but cold, and there are lots of fun sights.\n"
5616     "Sojourner says hi. See you soon.\n"
5617     " -Path\n", -1);
5618    
5619     gtk_text_thaw (GTK_TEXT (text));
5620 }
5621    
5622 /* Create a scrolled text area that displays a "message" */
5623 GtkWidget *
5624 create_text (void)
5625 {
5626     GtkWidget *table;
5627     GtkWidget *text;
5628     GtkWidget *hscrollbar;
5629     GtkWidget *vscrollbar;
5630    
5631     /* Create a table to hold the text widget and scrollbars */
5632     table = gtk_table_new (2, 2, FALSE);
5633    
5634     /* Put a text widget in the upper left hand corner. Note the use of
5635      * GTK_SHRINK in the y direction */
5636     text = gtk_text_new (NULL, NULL);
5637     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
5638                       GTK_FILL | GTK_EXPAND,
5639                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
5640     gtk_widget_show (text);
5641    
5642     /* Put a HScrollbar in the lower left hand corner */
5643     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
5644     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
5645                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
5646     gtk_widget_show (hscrollbar);
5647    
5648     /* And a VScrollbar in the upper right */
5649     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
5650     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
5651                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
5652     gtk_widget_show (vscrollbar);
5653    
5654     /* Add a handler to put a message in the text widget when it is realized */
5655     gtk_signal_connect (GTK_OBJECT (text), "realize",
5656                         GTK_SIGNAL_FUNC (realize_text), NULL);
5657    
5658     return table;
5659 }
5660    
5661 int
5662 main (int argc, char *argv[])
5663 {
5664     GtkWidget *window;
5665     GtkWidget *vpaned;
5666     GtkWidget *list;
5667     GtkWidget *text;
5668
5669     gtk_init (&amp;argc, &amp;argv);
5670    
5671     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5672     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
5673     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5674                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5675     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5676     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
5677
5678     /* create a vpaned widget and add it to our toplevel window */
5679    
5680     vpaned = gtk_vpaned_new ();
5681     gtk_container_add (GTK_CONTAINER(window), vpaned);
5682     gtk_paned_set_handle_size (GTK_PANED(vpaned),
5683                                10);
5684     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
5685                                15);                       
5686     gtk_widget_show (vpaned);
5687    
5688     /* Now create the contents of the two halves of the window */
5689    
5690     list = create_list ();
5691     gtk_paned_add1 (GTK_PANED(vpaned), list);
5692     gtk_widget_show (list);
5693    
5694     text = create_text ();
5695     gtk_paned_add2 (GTK_PANED(vpaned), text);
5696     gtk_widget_show (text);
5697     gtk_widget_show (window);
5698     gtk_main ();
5699     return 0;
5700 }
5701 /* example-end */
5702 </verb></tscreen>
5703
5704 <!-- ----------------------------------------------------------------- -->
5705 <sect1>Viewports <label id="sec_Viewports">
5706 <p>
5707 It is unlikely that you will ever need to use the Viewport widget
5708 directly. You are much more likely to use the
5709 <ref id="sec_ScrolledWindows" name="Scrolled Windows"> widget which
5710 itself uses the Viewport.
5711
5712 A viewport widget allows you to place a larger widget within it such
5713 that you can view a part of it at a time. It uses
5714 <ref id="sec_Adjustment" name="Adjustments"> to define the area that
5715 is currently in view.
5716
5717 A Viewport is created with the function
5718
5719 <tscreen><verb>
5720 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
5721                              GtkAdjustment *vadjustment );
5722 </verb></tscreen>
5723
5724 As you can see you can specify the horizontal and vertical Adjustments
5725 that the widget is to use when you create the widget. It will create
5726 it's own if you pass NULL as the value of the arguments.
5727
5728 You can get and set the adjustments after the widget has been created
5729 using the following four functions:
5730
5731 <tscreen><verb>
5732 GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
5733
5734 GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
5735
5736 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
5737                                    GtkAdjustment *adjustment );
5738
5739 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
5740                                    GtkAdjustment *adjustment );
5741 </verb></tscreen>
5742
5743 The only other viewport function is used to alter its appearance:
5744
5745 <tscreen><verb>
5746 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
5747                                    GtkShadowType  type );
5748 </verb></tscreen>
5749
5750 Possible values for the <tt/type/ parameter are:
5751 <itemize>
5752 <item> GTK_SHADOW_NONE,
5753 <item> GTK_SHADOW_IN,
5754 <item> GTK_SHADOW_OUT,
5755 <item> GTK_SHADOW_ETCHED_IN,
5756 <item> GTK_SHADOW_ETCHED_OUT
5757 </itemize>
5758
5759 <!-- ----------------------------------------------------------------- -->
5760 <sect1>Scrolled Windows <label id="sec_ScrolledWindows">
5761 <p>
5762 Scrolled windows are used to create a scrollable area inside a real
5763 window.  You may insert any type of widget into a scrolled window, and
5764 it will be accessible regardless of the size by using the scrollbars.
5765
5766 The following function is used to create a new scrolled window.
5767
5768 <tscreen><verb>
5769 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
5770                                     GtkAdjustment *vadjustment );
5771 </verb></tscreen>
5772
5773 Where the first argument is the adjustment for the horizontal
5774 direction, and the second, the adjustment for the vertical direction.
5775 These are almost always set to NULL.
5776
5777 <tscreen><verb>
5778 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
5779                                      GtkPolicyType      hscrollbar_policy,
5780                                      GtkPolicyType      vscrollbar_policy );
5781 </verb></tscreen>
5782
5783 This sets the policy to be used with respect to the scrollbars.
5784 The first argument is the scrolled window you wish to change. The second
5785 sets the policy for the horizontal scrollbar, and the third the policy for 
5786 the vertical scrollbar.
5787
5788 The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
5789 GTK_POLICY_AUTOMATIC will automatically decide whether you need
5790 scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
5791 there.
5792
5793 You can then place your object into the scrolled window using the
5794 following function.
5795
5796 <tscreen><verb>
5797 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
5798                                             GtkWidget         *child);
5799 </verb></tscreen>
5800
5801 Here is a simple example that packs 100 toggle buttons into a scrolled
5802 window.  I've only commented on the parts that may be new to you.
5803
5804 <tscreen><verb>
5805 /* example-start scrolledwin scrolledwin.c */
5806
5807 #include <gtk/gtk.h>
5808
5809 void destroy(GtkWidget *widget, gpointer data)
5810 {
5811     gtk_main_quit();
5812 }
5813
5814 int main (int argc, char *argv[])
5815 {
5816     static GtkWidget *window;
5817     GtkWidget *scrolled_window;
5818     GtkWidget *table;
5819     GtkWidget *button;
5820     char buffer[32];
5821     int i, j;
5822     
5823     gtk_init (&amp;argc, &amp;argv);
5824     
5825     /* Create a new dialog window for the scrolled window to be
5826      * packed into. A dialog is just like a normal window except it has a 
5827      * vbox and a horizontal separator packed into it. It's just a shortcut
5828      * for creating dialogs */
5829     window = gtk_dialog_new ();
5830     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5831                         (GtkSignalFunc) destroy, NULL);
5832     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
5833     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5834     gtk_widget_set_usize(window, 300, 300);
5835     
5836     /* create a new scrolled window. */
5837     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
5838     
5839     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
5840     
5841     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
5842      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
5843      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
5844      * there.  The first one is the horizontal scrollbar, the second, 
5845      * the vertical. */
5846     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
5847                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
5848     /* The dialog window is created with a vbox packed into it. */                                                              
5849     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
5850                         TRUE, TRUE, 0);
5851     gtk_widget_show (scrolled_window);
5852     
5853     /* create a table of 10 by 10 squares. */
5854     table = gtk_table_new (10, 10, FALSE);
5855     
5856     /* set the spacing to 10 on x and 10 on y */
5857     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
5858     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
5859     
5860     /* pack the table into the scrolled window */
5861     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
5862                                            table);
5863     gtk_widget_show (table);
5864     
5865     /* this simply creates a grid of toggle buttons on the table
5866      * to demonstrate the scrolled window. */
5867     for (i = 0; i < 10; i++)
5868        for (j = 0; j < 10; j++) {
5869           sprintf (buffer, "button (%d,%d)\n", i, j);
5870           button = gtk_toggle_button_new_with_label (buffer);
5871           gtk_table_attach_defaults (GTK_TABLE (table), button,
5872                                      i, i+1, j, j+1);
5873           gtk_widget_show (button);
5874        }
5875     
5876     /* Add a "close" button to the bottom of the dialog */
5877     button = gtk_button_new_with_label ("close");
5878     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5879                                (GtkSignalFunc) gtk_widget_destroy,
5880                                GTK_OBJECT (window));
5881     
5882     /* this makes it so the button is the default. */
5883     
5884     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5885     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
5886     
5887     /* This grabs this button to be the default button. Simply hitting
5888      * the "Enter" key will cause this button to activate. */
5889     gtk_widget_grab_default (button);
5890     gtk_widget_show (button);
5891     
5892     gtk_widget_show (window);
5893     
5894     gtk_main();
5895     
5896     return(0);
5897 }
5898 /* example-end */
5899 </verb></tscreen>
5900
5901 Try playing with resizing the window. You'll notice how the scrollbars
5902 react. You may also wish to use the gtk_widget_set_usize() call to set
5903 the default size of the window or other widgets.
5904
5905 <!-- ----------------------------------------------------------------- -->   
5906 <sect1>Button Boxes
5907 <p>
5908 Button Boxes are a convenient way to quickly layout a group of
5909 buttons. They come in both horizontal and vertical flavours. You
5910 create a new Button Box with one of the following calls, which create
5911 a horizontal or vertical box, respectively:
5912
5913 <tscreen><verb>
5914 GtkWidget *gtk_hbutton_box_new( void );
5915
5916 GtkWidget *gtk_vbutton_box_new( void );
5917 </verb></tscreen>
5918
5919 The only attributes pertaining to button boxes effect how the buttons
5920 are layed out. You can change the spacing between the buttons with:
5921
5922 <tscreen><verb>
5923 void gtk_hbutton_box_set_spacing_default( gint spacing );
5924
5925 void gtk_vbutton_box_set_spacing_default( gint spacing );
5926 </verb></tscreen>
5927
5928 Similarly, the current spacing values can be queried using:
5929
5930 <tscreen><verb>
5931 gint gtk_hbutton_box_get_spacing_default( void );
5932
5933 gint gtk_vbutton_box_get_spacing_default( void );
5934 </verb></tscreen>
5935
5936 The second attribute that we can access effects the layour of the
5937 buttons within the box. It is set using one of:
5938
5939 <tscreen><verb>
5940 void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
5941
5942 void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
5943 </verb></tscreen>
5944
5945 The <tt/layout/ argument can take one of the following values:
5946
5947 <itemize>
5948 <item> GTK_BUTTONBOX_DEFAULT_STYLE
5949 <item> GTK_BUTTONBOX_SPREAD
5950 <item> GTK_BUTTONBOX_EDGE
5951 <item> GTK_BUTTONBOX_START
5952 <item> GTK_BUTTONBOX_END
5953 </itemize>
5954
5955 The current layout setting can be retrieved using:
5956
5957 <tscreen><verb>
5958 GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
5959
5960 GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
5961 </verb></tscreen>
5962
5963 Buttons are added to a Button Box using the usual function:
5964
5965 <tscreen><verb>
5966     gtk_container_add( GTK_CONTAINER(button_box), child_widget );
5967 </verb></tscreen>
5968
5969 Here's an example that illustrates all the different layout settings
5970 for Button Boxes.
5971
5972 <tscreen><verb>
5973 /* example-start buttonbox buttonbox.c */
5974
5975 #include <gtk/gtk.h>
5976
5977 /* Create a Button Box with the specified parameters */
5978 GtkWidget *create_bbox (gint  horizontal,
5979                         char* title,
5980                         gint  spacing,
5981                         gint  child_w,
5982                         gint  child_h,
5983                         gint  layout)
5984 {
5985   GtkWidget *frame;
5986   GtkWidget *bbox;
5987   GtkWidget *button;
5988
5989   frame = gtk_frame_new (title);
5990
5991   if (horizontal)
5992     bbox = gtk_hbutton_box_new ();
5993   else
5994     bbox = gtk_vbutton_box_new ();
5995
5996   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
5997   gtk_container_add (GTK_CONTAINER (frame), bbox);
5998
5999   /* Set the appearance of the Button Box */
6000   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
6001   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
6002   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
6003
6004   button = gtk_button_new_with_label ("OK");
6005   gtk_container_add (GTK_CONTAINER (bbox), button);
6006
6007   button = gtk_button_new_with_label ("Cancel");
6008   gtk_container_add (GTK_CONTAINER (bbox), button);
6009
6010   button = gtk_button_new_with_label ("Help");
6011   gtk_container_add (GTK_CONTAINER (bbox), button);
6012
6013   return(frame);
6014 }
6015
6016 int main( int   argc,
6017           char *argv[] )
6018 {
6019   static GtkWidget* window = NULL;
6020   GtkWidget *main_vbox;
6021   GtkWidget *vbox;
6022   GtkWidget *hbox;
6023   GtkWidget *frame_horz;
6024   GtkWidget *frame_vert;
6025
6026   /* Initialize GTK */
6027   gtk_init( &amp;argc, &amp;argv );
6028
6029   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6030   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
6031
6032   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6033                       GTK_SIGNAL_FUNC(gtk_main_quit),
6034                       NULL);
6035
6036   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6037
6038   main_vbox = gtk_vbox_new (FALSE, 0);
6039   gtk_container_add (GTK_CONTAINER (window), main_vbox);
6040
6041   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
6042   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
6043
6044   vbox = gtk_vbox_new (FALSE, 0);
6045   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6046   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
6047
6048   gtk_box_pack_start (GTK_BOX (vbox),
6049            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
6050                       TRUE, TRUE, 0);
6051
6052   gtk_box_pack_start (GTK_BOX (vbox),
6053            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6054                       TRUE, TRUE, 5);
6055
6056   gtk_box_pack_start (GTK_BOX (vbox),
6057            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6058                       TRUE, TRUE, 5);
6059
6060   gtk_box_pack_start (GTK_BOX (vbox),
6061            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
6062                       TRUE, TRUE, 5);
6063
6064   frame_vert = gtk_frame_new ("Vertical Button Boxes");
6065   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
6066
6067   hbox = gtk_hbox_new (FALSE, 0);
6068   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6069   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
6070
6071   gtk_box_pack_start (GTK_BOX (hbox),
6072            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
6073                       TRUE, TRUE, 0);
6074
6075   gtk_box_pack_start (GTK_BOX (hbox),
6076            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6077                       TRUE, TRUE, 5);
6078
6079   gtk_box_pack_start (GTK_BOX (hbox),
6080            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6081                       TRUE, TRUE, 5);
6082
6083   gtk_box_pack_start (GTK_BOX (hbox),
6084            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
6085                       TRUE, TRUE, 5);
6086
6087   gtk_widget_show_all (window);
6088
6089   /* Enter the event loop */
6090   gtk_main ();
6091     
6092   return(0);
6093 }
6094 /* example-end */
6095 </verb></tscreen>
6096
6097 <!-- ----------------------------------------------------------------- -->   
6098 <sect1>Toolbar
6099 <p>
6100 Toolbars are usually used to group some number of widgets in order to
6101 simplify customization of their look and layout. Typically a toolbar
6102 consists of buttons with icons, labels and tooltips, but any other
6103 widget can also be put inside a toolbar. Finally, items can be
6104 arranged horizontally or vertically and buttons can be displayed with
6105 icons, labels or both.
6106
6107 Creating a toolbar is (as one may already suspect) done with the
6108 following function:
6109
6110 <tscreen><verb>
6111 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
6112                             GtkToolbarStyle  style );
6113 </verb></tscreen>
6114
6115 where orientation may be one of:
6116
6117 <tscreen><verb>
6118   GTK_ORIENTATION_HORIZONTAL    
6119   GTK_ORIENTATION_VERTICAL
6120 </verb></tscreen>
6121
6122 and style one of:
6123
6124 <tscreen><verb>
6125   GTK_TOOLBAR_TEXT
6126   GTK_TOOLBAR_ICONS
6127   GTK_TOOLBAR_BOTH
6128 </verb></tscreen>
6129
6130 The style applies to all the buttons created with the `item' functions
6131 (not to buttons inserted into toolbar as separate widgets).
6132
6133 After creating a toolbar one can append, prepend and insert items
6134 (that means simple buttons) into the toolbar. To describe an item we
6135 need a label text, a tooltip text, a private tooltip text, an icon for
6136 the button and a callback function for it. For example, to append or
6137 prepend an item you may use the following functions:
6138
6139 <tscreen><verb>
6140 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
6141                                     const char    *text,
6142                                     const char    *tooltip_text,
6143                                     const char    *tooltip_private_text,
6144                                     GtkWidget     *icon,
6145                                     GtkSignalFunc  callback,
6146                                     gpointer       user_data );
6147
6148 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
6149                                      const char    *text,
6150                                      const char    *tooltip_text,
6151                                      const char    *tooltip_private_text,
6152                                      GtkWidget     *icon,
6153                                      GtkSignalFunc  callback,
6154                                      gpointer       user_data );
6155 </verb></tscreen>
6156
6157 If you want to use gtk_toolbar_insert_item, the only additional
6158 parameter which must be specified is the position in which the item
6159 should be inserted, thus:
6160
6161 <tscreen><verb>
6162 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
6163                                     const char    *text,
6164                                     const char    *tooltip_text,
6165                                     const char    *tooltip_private_text,
6166                                     GtkWidget     *icon,
6167                                     GtkSignalFunc  callback,
6168                                     gpointer       user_data,
6169                                     gint           position );
6170 </verb></tscreen>
6171
6172 To simplify adding spaces between toolbar items, you may use the
6173 following functions:
6174
6175 <tscreen><verb>
6176 void gtk_toolbar_append_space( GtkToolbar *toolbar );
6177
6178 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
6179
6180 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
6181                                gint        position );
6182  
6183 </verb></tscreen>
6184
6185 While the size of the added space can be set globally for a
6186 whole toolbar with the function:
6187
6188 <tscreen><verb>
6189 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
6190                                  gint        space_size) ;
6191 </verb></tscreen>
6192
6193 If it's required, the orientation of a toolbar and its style can be
6194 changed `on the fly' using the following functions:
6195
6196 <tscreen><verb>
6197 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
6198                                   GtkOrientation  orientation );
6199
6200 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
6201                             GtkToolbarStyle  style );
6202
6203 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
6204                                gint        enable );
6205 </verb></tscreen>
6206
6207 Where <tt/orientation/ is one of GTK_ORIENTATION_HORIZONTAL or
6208 GTK_ORIENTATION_VERTICAL. The <tt/style/ is used to set appearance of
6209 the toolbar items by using one of GTK_TOOLBAR_ICONS, GTK_TOOLBAR_TEXT
6210 or GTK_TOOLBAR_BOTH.
6211
6212 To show some other things that can be done with a toolbar, let's take
6213 the following program (we'll interrupt the listing with some
6214 additional explanations):
6215
6216 <tscreen><verb>
6217 #include <gtk/gtk.h>
6218
6219 #include "gtk.xpm"
6220
6221 /* This function is connected to the Close button or
6222  * closing the window from the WM */
6223 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
6224 {
6225   gtk_main_quit ();
6226 }
6227 </verb></tscreen>
6228
6229 The above beginning seems for sure familiar to you if it's not your first
6230 GTK program. There is one additional thing though, we include a nice XPM
6231 picture to serve as an icon for all of the buttons.
6232
6233 <tscreen><verb>
6234 GtkWidget* close_button; // this button will emit signal to close application
6235 GtkWidget* tooltips_button; // to enable/disable tooltips
6236 GtkWidget* text_button,
6237          * icon_button,
6238          * both_button; // radio buttons for toolbar style
6239 GtkWidget* entry; // a text entry to show packing any widget into toolbar
6240 </verb></tscreen>
6241
6242 In fact not all of the above widgets are needed here, but to make things
6243 clearer I put them all together.
6244
6245 <tscreen><verb>
6246 /* that's easy... when one of the buttons is toggled, we just
6247  * check which one is active and set the style of the toolbar
6248  * accordingly
6249  * ATTENTION: our toolbar is passed as data to callback ! */
6250 void radio_event (GtkWidget *widget, gpointer data)
6251 {
6252   if (GTK_TOGGLE_BUTTON (text_button)->active) 
6253     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
6254   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
6255     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
6256   else if (GTK_TOGGLE_BUTTON (both_button)->active)
6257     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
6258 }
6259
6260 /* even easier, just check given toggle button and enable/disable 
6261  * tooltips */
6262 void toggle_event (GtkWidget *widget, gpointer data)
6263 {
6264   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
6265                             GTK_TOGGLE_BUTTON (widget)->active );
6266 }
6267 </verb></tscreen>
6268
6269 The above are just two callback functions that will be called when
6270 one of the buttons on a toolbar is pressed. You should already be
6271 familiar with things like this if you've already used toggle buttons (and
6272 radio buttons).
6273
6274 <tscreen><verb>
6275 int main (int argc, char *argv[])
6276 {
6277   /* Here is our main window (a dialog) and a handle for the handlebox */
6278   GtkWidget* dialog;
6279   GtkWidget* handlebox;
6280
6281   /* Ok, we need a toolbar, an icon with a mask (one for all of 
6282      the buttons) and an icon widget to put this icon in (but 
6283      we'll create a separate widget for each button) */
6284   GtkWidget * toolbar;
6285   GdkPixmap * icon;
6286   GdkBitmap * mask;
6287   GtkWidget * iconw;
6288
6289   /* this is called in all GTK application. */
6290   gtk_init (&amp;argc, &amp;argv);
6291   
6292   /* create a new window with a given title, and nice size */
6293   dialog = gtk_dialog_new ();
6294   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
6295   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
6296   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
6297
6298   /* typically we quit if someone tries to close us */
6299   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
6300                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
6301
6302   /* we need to realize the window because we use pixmaps for 
6303    * items on the toolbar in the context of it */
6304   gtk_widget_realize ( dialog );
6305
6306   /* to make it nice we'll put the toolbar into the handle box, 
6307    * so that it can be detached from the main window */
6308   handlebox = gtk_handle_box_new ();
6309   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
6310                        handlebox, FALSE, FALSE, 5 );
6311 </verb></tscreen>
6312
6313 The above should be similar to any other GTK application. Just
6314 initialization of GTK, creating the window etc.. There is only one
6315 thing that probably needs some explanation: a handle box. A handle box
6316 is just another box that can be used to pack widgets in to. The
6317 difference between it and typical boxes is that it can be detached
6318 from a parent window (or, in fact, the handle box remains in the
6319 parent, but it is reduced to a very small rectangle, while all of its
6320 contents are reparented to a new freely floating window). It is
6321 usually nice to have a detachable toolbar, so these two widgets occur
6322 together quite often.
6323
6324 <tscreen><verb>
6325   /* toolbar will be horizontal, with both icons and text, and
6326    * with 5pxl spaces between items and finally, 
6327    * we'll also put it into our handlebox */
6328   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
6329                               GTK_TOOLBAR_BOTH );
6330   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
6331   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
6332   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
6333
6334   /* now we create icon with mask: we'll reuse it to create
6335    * icon widgets for toolbar items */
6336   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
6337       &amp;dialog->style->white, gtk_xpm );
6338 </verb></tscreen>
6339
6340 Well, what we do above is just a straight-forward initialization of
6341 the toolbar widget and creation of a GDK pixmap with its mask. If you
6342 want to know something more about using pixmaps, refer to GDK
6343 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
6344 earlier in this tutorial.
6345
6346 <tscreen><verb>
6347   /* our first item is <close> button */
6348   iconw = gtk_pixmap_new ( icon, mask ); // icon widget
6349   close_button = 
6350     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), // our toolbar
6351                               "Close",               // button label
6352                               "Closes this app",     // tooltip for this button
6353                               "Private",             // tooltip private string
6354                               iconw,                 // icon widget
6355                               GTK_SIGNAL_FUNC (delete_event), // a signal
6356                               NULL );
6357   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); // space after item
6358 </verb></tscreen>
6359
6360 In the above code you see the simplest case: adding a button to
6361 toolbar.  Just before appending a new item, we have to construct a
6362 pixmap widget to serve as an icon for this item; this step will have
6363 to be repeated for each new item. Just after the item we also add a
6364 space, so the following items will not touch each other. As you see
6365 gtk_toolbar_append_item returns a pointer to our newly created button
6366 widget, so that we can work with it in the normal way.
6367
6368 <tscreen><verb>
6369   /* now, let's make our radio buttons group... */
6370   iconw = gtk_pixmap_new ( icon, mask );
6371   icon_button = 
6372     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6373                                GTK_TOOLBAR_CHILD_RADIOBUTTON, // a type of element
6374                                NULL,                          // pointer to widget
6375                                "Icon",                        // label
6376                                "Only icons in toolbar",       // tooltip
6377                                "Private",                     // tooltip private string
6378                                iconw,                         // icon
6379                                GTK_SIGNAL_FUNC (radio_event), // signal
6380                                toolbar);                      // data for signal
6381   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6382 </verb></tscreen>
6383
6384 Here we begin creating a radio buttons group. To do this we use
6385 gtk_toolbar_append_element.  In fact, using this function one can also
6386 add simple items or even spaces (type = GTK_TOOLBAR_CHILD_SPACE or
6387 GTK_TOOLBAR_CHILD_BUTTON). In the above case we start creating a radio
6388 group. In creating other radio buttons for this group a pointer to the
6389 previous button in the group is required, so that a list of buttons
6390 can be easily constructed (see the section on <ref
6391 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
6392 tutorial).
6393
6394 <tscreen><verb>
6395   /* following radio buttons refer to previous ones */
6396   iconw = gtk_pixmap_new ( icon, mask );
6397   text_button = 
6398     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6399                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
6400                                icon_button,
6401                                "Text",
6402                                "Only texts in toolbar",
6403                                "Private",
6404                                iconw,
6405                                GTK_SIGNAL_FUNC (radio_event),
6406                                toolbar);
6407   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6408                                           
6409   iconw = gtk_pixmap_new ( icon, mask );
6410   both_button = 
6411     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6412                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
6413                                text_button,
6414                                "Both",
6415                                "Icons and text in toolbar",
6416                                "Private",
6417                                iconw,
6418                                GTK_SIGNAL_FUNC (radio_event),
6419                                toolbar);
6420   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6421   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
6422 </verb></tscreen>
6423
6424 In the end we have set the state of one of the buttons manually (otherwise
6425 they all stay in active state, preventing us from switching between them).
6426
6427 <tscreen><verb>
6428   /* here we have just a simple toggle button */
6429   iconw = gtk_pixmap_new ( icon, mask );
6430   tooltips_button = 
6431     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6432                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
6433                                NULL,
6434                                "Tooltips",
6435                                "Toolbar with or without tips",
6436                                "Private",
6437                                iconw,
6438                                GTK_SIGNAL_FUNC (toggle_event),
6439                                toolbar);
6440   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6441   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
6442 </verb></tscreen>
6443
6444 A toggle button can be created in the obvious way (if one knows how to create
6445 radio buttons already).
6446
6447 <tscreen><verb>
6448   /* to pack a widget into toolbar, we only have to 
6449    * create it and append it with an appropriate tooltip */
6450   entry = gtk_entry_new ();
6451   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
6452                              entry, 
6453                              "This is just an entry", 
6454                              "Private" );
6455
6456   /* well, it isn't created within thetoolbar, so we must still show it */
6457   gtk_widget_show ( entry );
6458 </verb></tscreen>
6459
6460 As you see, adding any kind of widget to a toolbar is simple. The
6461 one thing you have to remember is that this widget must be shown manually
6462 (contrary to other items which will be shown together with the toolbar).
6463
6464 <tscreen><verb>
6465   /* that's it ! let's show everything. */
6466   gtk_widget_show ( toolbar );
6467   gtk_widget_show (handlebox);
6468   gtk_widget_show ( dialog );
6469
6470   /* rest in gtk_main and wait for the fun to begin! */
6471   gtk_main ();
6472   
6473   return 0;
6474 }
6475 </verb></tscreen>
6476
6477 So, here we are at the end of toolbar tutorial. Of course, to appreciate
6478 it in full you need also this nice XPM icon, so here it is:
6479
6480 <tscreen><verb>
6481 /* XPM */
6482 static char * gtk_xpm[] = {
6483 "32 39 5 1",
6484 ".      c none",
6485 "+      c black",
6486 "@      c #3070E0",
6487 "#      c #F05050",
6488 "$      c #35E035",
6489 "................+...............",
6490 "..............+++++.............",
6491 "............+++++@@++...........",
6492 "..........+++++@@@@@@++.........",
6493 "........++++@@@@@@@@@@++........",
6494 "......++++@@++++++++@@@++.......",
6495 ".....+++@@@+++++++++++@@@++.....",
6496 "...+++@@@@+++@@@@@@++++@@@@+....",
6497 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
6498 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
6499 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
6500 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
6501 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
6502 ".+####+++@@@+++++++@@@@@+@$$$$@.",
6503 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
6504 ".+######++++@@@@@@@++@$$$$$$$$+.",
6505 ".+#######+##+@@@@+++$$$$$$@@$$+.",
6506 ".+###+++##+##+@@++@$$$$$$++$$$+.",
6507 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
6508 ".+###++++++#+++@$$@+@$$@++$$$@+.",
6509 ".+####+++++++#++$$@+@$$++$$$$+..",
6510 ".++####++++++#++$$@+@$++@$$$$+..",
6511 ".+#####+++++##++$$++@+++$$$$$+..",
6512 ".++####+++##+#++$$+++++@$$$$$+..",
6513 ".++####+++####++$$++++++@$$$@+..",
6514 ".+#####++#####++$$+++@++++@$@+..",
6515 ".+#####++#####++$$++@$$@+++$@@..",
6516 ".++####++#####++$$++$$$$$+@$@++.",
6517 ".++####++#####++$$++$$$$$$$$+++.",
6518 ".+++####+#####++$$++$$$$$$$@+++.",
6519 "..+++#########+@$$+@$$$$$$+++...",
6520 "...+++########+@$$$$$$$$@+++....",
6521 ".....+++######+@$$$$$$$+++......",
6522 "......+++#####+@$$$$$@++........",
6523 ".......+++####+@$$$$+++.........",
6524 ".........++###+$$$@++...........",
6525 "..........++##+$@+++............",
6526 "...........+++++++..............",
6527 ".............++++..............."};
6528 </verb></tscreen>
6529
6530 <!-- ----------------------------------------------------------------- -->
6531 <sect1> Notebooks
6532 <p>
6533 The NoteBook Widget is a collection of 'pages' that overlap each
6534 other, each page contains different information. This widget has
6535 become more common lately in GUI programming, and it is a good way to
6536 show blocks of similar information that warrant separation in their
6537 display.
6538
6539 The first function call you will need to know, as you can probably
6540 guess by now, is used to create a new notebook widget.
6541
6542 <tscreen><verb>
6543 GtkWidget *gtk_notebook_new( void );
6544 </verb></tscreen>
6545
6546 Once the notebook has been created, there are a number of functions
6547 that operate on the notebook widget. Let's look at them individually.
6548
6549 The first one we will look at is how to position the page indicators.
6550 These page indicators or 'tabs' as they are referred to, can be
6551 positioned in four ways: top, bottom, left, or right.
6552
6553 <tscreen><verb>
6554 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
6555                                GtkPositionType  pos );
6556 </verb></tscreen>
6557
6558 GtkPostionType will be one of the following, and they are pretty self explanatory:
6559 <itemize>
6560 <item> GTK_POS_LEFT
6561 <item> GTK_POS_RIGHT
6562 <item> GTK_POS_TOP
6563 <item> GTK_POS_BOTTOM
6564 </itemize>
6565
6566 GTK_POS_TOP is the default.
6567
6568 Next we will look at how to add pages to the notebook. There are three
6569 ways to add pages to the NoteBook. Let's look at the first two
6570 together as they are quite similar.
6571
6572 <tscreen><verb>
6573 void gtk_notebook_append_page( GtkNotebook *notebook,
6574                                GtkWidget   *child,
6575                                GtkWidget   *tab_label );
6576
6577 void gtk_notebook_prepend_page( GtkNotebook *notebook,
6578                                 GtkWidget   *child,
6579                                 GtkWidget   *tab_label );
6580 </verb></tscreen>
6581
6582 These functions add pages to the notebook by inserting them from the
6583 back of the notebook (append), or the front of the notebook (prepend).
6584 <tt/child/ is the widget that is placed within the notebook page, and
6585 <tt/tab_label/ is the label for the page being added. The <tt/child/
6586 widget must be created separately, and is typically a set of options
6587 setout witin one of the other container widgets, such as a table.
6588
6589 The final function for adding a page to the notebook contains all of
6590 the properties of the previous two, but it allows you to specify what
6591 position you want the page to be in the notebook.
6592
6593 <tscreen><verb>
6594 void gtk_notebook_insert_page( GtkNotebook *notebook,
6595                                GtkWidget   *child,
6596                                GtkWidget   *tab_label,
6597                                gint         position );
6598 </verb></tscreen>
6599
6600 The parameters are the same as _append_ and _prepend_ except it
6601 contains an extra parameter, <tt/position/.  This parameter is used to
6602 specify what place this page will be inserted into.
6603
6604 Now that we know how to add a page, lets see how we can remove a page
6605 from the notebook.
6606
6607 <tscreen><verb>
6608 void gtk_notebook_remove_page( GtkNotebook *notebook,
6609                                gint         page_num );
6610 </verb></tscreen>
6611
6612 This function takes the page specified by <tt/page_num/ and removes it
6613 from the widget pointed to by <tt/notebook/.
6614
6615 To find out what the current page is in a notebook use the function:
6616
6617 <tscreen><verb>
6618 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
6619 </verb></tscreen>
6620
6621 These next two functions are simple calls to move the notebook page
6622 forward or backward. Simply provide the respective function call with
6623 the notebook widget you wish to operate on. Note: when the NoteBook is
6624 currently on the last page, and gtk_notebook_next_page is called, the
6625 notebook will wrap back to the first page. Likewise, if the NoteBook
6626 is on the first page, and gtk_notebook_prev_page is called, the
6627 notebook will wrap to the last page.
6628
6629 <tscreen><verb>
6630 void gtk_notebook_next_page( GtkNoteBook *notebook );
6631
6632 void gtk_notebook_prev_page( GtkNoteBook *notebook );
6633 </verb></tscreen>
6634
6635 This next function sets the 'active' page. If you wish the notebook to
6636 be opened to page 5 for example, you would use this function.  Without
6637 using this function, the notebook defaults to the first page.
6638
6639 <tscreen><verb>
6640 void gtk_notebook_set_page( GtkNotebook *notebook,
6641                             gint         page_num );
6642 </verb></tscreen>
6643
6644 The next two functions add or remove the notebook page tabs and the
6645 notebook border respectively.
6646
6647 <tscreen><verb>
6648 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
6649                                  gboolean     show_tabs);
6650
6651 void gtk_notebook_set_show_border( GtkNotebook *notebook,
6652                                    gboolean     show_border );
6653 </verb></tscreen>
6654
6655 The next function is useful when the you have a large number of pages,
6656 and the tabs don't fit on the page. It allows the tabs to be scrolled
6657 through using two arrow buttons.
6658
6659 <tscreen><verb>
6660 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
6661                                   gboolean     scrollable );
6662 </verb></tscreen>
6663
6664 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
6665 TRUE or FALSE.
6666
6667 Now lets look at an example, it is expanded from the testgtk.c code
6668 that comes with the GTK distribution. This small program creates a
6669 window with a notebook and six buttons. The notebook contains 11
6670 pages, added in three different ways, appended, inserted, and
6671 prepended. The buttons allow you rotate the tab positions, add/remove
6672 the tabs and border, remove a page, change pages in both a forward and
6673 backward manner, and exit the program.
6674
6675 <tscreen><verb>
6676 /* example-start notebook notebook.c */
6677
6678 #include <gtk/gtk.h>
6679
6680 /* This function rotates the position of the tabs */
6681 void rotate_book (GtkButton *button, GtkNotebook *notebook)
6682 {
6683     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
6684 }
6685
6686 /* Add/Remove the page tabs and the borders */
6687 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
6688 {
6689     gint tval = FALSE;
6690     gint bval = FALSE;
6691     if (notebook->show_tabs == 0)
6692             tval = TRUE; 
6693     if (notebook->show_border == 0)
6694             bval = TRUE;
6695     
6696     gtk_notebook_set_show_tabs (notebook, tval);
6697     gtk_notebook_set_show_border (notebook, bval);
6698 }
6699
6700 /* Remove a page from the notebook */
6701 void remove_book (GtkButton *button, GtkNotebook *notebook)
6702 {
6703     gint page;
6704     
6705     page = gtk_notebook_get_current_page(notebook);
6706     gtk_notebook_remove_page (notebook, page);
6707     /* Need to refresh the widget -- 
6708      This forces the widget to redraw itself. */
6709     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
6710 }
6711
6712 void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
6713 {
6714     gtk_main_quit ();
6715 }
6716
6717 int main (int argc, char *argv[])
6718 {
6719     GtkWidget *window;
6720     GtkWidget *button;
6721     GtkWidget *table;
6722     GtkWidget *notebook;
6723     GtkWidget *frame;
6724     GtkWidget *label;
6725     GtkWidget *checkbutton;
6726     int i;
6727     char bufferf[32];
6728     char bufferl[32];
6729     
6730     gtk_init (&amp;argc, &amp;argv);
6731     
6732     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6733     
6734     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
6735                         GTK_SIGNAL_FUNC (delete), NULL);
6736     
6737     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6738
6739     table = gtk_table_new(3,6,FALSE);
6740     gtk_container_add (GTK_CONTAINER (window), table);
6741     
6742     /* Create a new notebook, place the position of the tabs */
6743     notebook = gtk_notebook_new ();
6744     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
6745     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
6746     gtk_widget_show(notebook);
6747     
6748     /* Lets append a bunch of pages to the notebook */
6749     for (i=0; i < 5; i++) {
6750         sprintf(bufferf, "Append Frame %d", i+1);
6751         sprintf(bufferl, "Page %d", i+1);
6752         
6753         frame = gtk_frame_new (bufferf);
6754         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
6755         gtk_widget_set_usize (frame, 100, 75);
6756         gtk_widget_show (frame);
6757         
6758         label = gtk_label_new (bufferf);
6759         gtk_container_add (GTK_CONTAINER (frame), label);
6760         gtk_widget_show (label);
6761         
6762         label = gtk_label_new (bufferl);
6763         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
6764     }
6765       
6766     /* Now lets add a page to a specific spot */
6767     checkbutton = gtk_check_button_new_with_label ("Check me please!");
6768     gtk_widget_set_usize(checkbutton, 100, 75);
6769     gtk_widget_show (checkbutton);
6770    
6771     label = gtk_label_new ("Add page");
6772     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
6773     
6774     /* Now finally lets prepend pages to the notebook */
6775     for (i=0; i < 5; i++) {
6776         sprintf(bufferf, "Prepend Frame %d", i+1);
6777         sprintf(bufferl, "PPage %d", i+1);
6778         
6779         frame = gtk_frame_new (bufferf);
6780         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
6781         gtk_widget_set_usize (frame, 100, 75);
6782         gtk_widget_show (frame);
6783         
6784         label = gtk_label_new (bufferf);
6785         gtk_container_add (GTK_CONTAINER (frame), label);
6786         gtk_widget_show (label);
6787         
6788         label = gtk_label_new (bufferl);
6789         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
6790     }
6791     
6792     /* Set what page to start at (page 4) */
6793     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
6794
6795     /* Create a bunch of buttons */
6796     button = gtk_button_new_with_label ("close");
6797     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6798                                GTK_SIGNAL_FUNC (delete), NULL);
6799     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
6800     gtk_widget_show(button);
6801     
6802     button = gtk_button_new_with_label ("next page");
6803     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6804                                (GtkSignalFunc) gtk_notebook_next_page,
6805                                GTK_OBJECT (notebook));
6806     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
6807     gtk_widget_show(button);
6808     
6809     button = gtk_button_new_with_label ("prev page");
6810     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6811                                (GtkSignalFunc) gtk_notebook_prev_page,
6812                                GTK_OBJECT (notebook));
6813     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
6814     gtk_widget_show(button);
6815     
6816     button = gtk_button_new_with_label ("tab position");
6817     gtk_signal_connect (GTK_OBJECT (button), "clicked",
6818                         (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
6819     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
6820     gtk_widget_show(button);
6821     
6822     button = gtk_button_new_with_label ("tabs/border on/off");
6823     gtk_signal_connect (GTK_OBJECT (button), "clicked",
6824                         (GtkSignalFunc) tabsborder_book,
6825                         GTK_OBJECT (notebook));
6826     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
6827     gtk_widget_show(button);
6828     
6829     button = gtk_button_new_with_label ("remove page");
6830     gtk_signal_connect (GTK_OBJECT (button), "clicked",
6831                         (GtkSignalFunc) remove_book,
6832                         GTK_OBJECT(notebook));
6833     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
6834     gtk_widget_show(button);
6835     
6836     gtk_widget_show(table);
6837     gtk_widget_show(window);
6838     
6839     gtk_main ();
6840     
6841     return(0);
6842 }
6843 /* example-end */
6844 </verb></tscreen>
6845
6846 Hopefully this helps you on your way with creating notebooks for your
6847 GTK applications.
6848
6849 <!-- ***************************************************************** -->
6850 <sect>CList Widget
6851 <!-- ***************************************************************** -->
6852
6853 <!-- ----------------------------------------------------------------- -->
6854 <p>
6855 The GtkCList widget has replaced the GtkList widget (which is still
6856 available).
6857
6858 The GtkCList widget is a multi-column list widget that is capable of
6859 handling literally thousands of rows of information. Each column can
6860 optionally have a title, which itself is optionally active, allowing
6861 us to bind a function to its selection.
6862
6863 <!-- ----------------------------------------------------------------- -->
6864 <sect1>Creating a GtkCList widget
6865 <p>
6866 Creating a GtkCList is quite straightforward, once you have learned
6867 about widgets in general. It provides the almost standard two ways,
6868 that is the hard way, and the easy way. But before we create it, there
6869 is one thing we should figure out beforehand: how many columns should
6870 it have?
6871
6872 Not all columns have to be visible and can be used to store data that
6873 is related to a certain cell in the list.
6874
6875 <tscreen><verb>
6876 GtkWidget *gtk_clist_new ( gint columns );
6877
6878 GtkWidget *gtk_clist_new_with_titles( gint   columns,
6879                                       gchar *titles[] );
6880 </verb></tscreen>
6881
6882 The first form is very straight forward, the second might require some
6883 explanation. Each column can have a title associated with it, and this
6884 title can be a label or a button that reacts when we click on it. If
6885 we use the second form, we must provide pointers to the title texts,
6886 and the number of pointers should equal the number of columns
6887 specified. Of course we can always use the first form, and manually
6888 add titles later.
6889
6890 Note: the GtkCList widget does not have it's own scrollbars and should
6891 be placed within a GtkScrolledWindow widget if your require this
6892 functionality. This is a change from the GTK 1.0 implementation.
6893
6894 <!-- ----------------------------------------------------------------- -->
6895 <sect1>Modes of operation
6896 <p>
6897 There are several attributes that can be used to alter the behaviour of
6898 a GtkCList. First there is
6899
6900 <tscreen><verb>
6901 void gtk_clist_set_selection_mode( GtkCList         *clist,
6902                                    GtkSelectionMode  mode );
6903 </verb></tscreen>
6904
6905 which, as the name implies, sets the selection mode of the GtkCList. The first
6906 argument is the GtkCList widget, and the second specifies the cell selection
6907 mode (they are defined in gtkenums.h). At the time of this writing, the following
6908 modes are available to us:
6909
6910 <itemize>
6911 <item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
6912 pointer for a single selected item.
6913
6914 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list contains no
6915 widgets or insensitive ones only, otherwise it contains a GList pointer for
6916 one GList structure, and therefore exactly one list item.
6917
6918 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list items are
6919 selected or a GList pointer for the first selected item. That in turn points
6920 to a GList structure for the second selected item and so on. This is currently
6921 the <bf>default</bf> for the GtkCList widget.
6922
6923 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
6924 </itemize>
6925
6926 Others might be added in later revisions of GTK.
6927
6928 We can also define what the border of the GtkCList widget should look
6929 like. It is done through
6930
6931 <tscreen><verb>
6932 void gtk_clist_set_shadow_type( GtkCList      *clist,
6933                                 GtkShadowType  border );
6934 </verb></tscreen>
6935
6936 And the possible values for the second argument are
6937
6938 <itemize>
6939 <item> GTK_SHADOW_NONE
6940
6941 <item> GTK_SHADOW_IN
6942
6943 <item> GTK_SHADOW_OUT
6944
6945 <item> GTK_SHADOW_ETCHED_IN
6946
6947 <item> GTK_SHADOW_ETCHED_OUT
6948 </itemize>
6949
6950 <!-- ----------------------------------------------------------------- -->
6951 <sect1>Working with titles
6952 <p>
6953 When you create a GtkCList widget, you will also get a set of title
6954 buttons automatically. They live in the top of the CList window, and
6955 can act either as normal buttons that respond to being pressed, or
6956 they can be passive, in which case they are nothing more than a
6957 title. There are four different calls that aid us in setting the
6958 status of the title buttons.
6959
6960 <tscreen><verb>
6961 void gtk_clist_column_title_active( GtkCList *clist,
6962                                      gint     column );
6963
6964 void gtk_clist_column_title_passive( GtkCList *clist,
6965                                      gint      column );
6966
6967 void gtk_clist_column_titles_active( GtkCList *clist );
6968
6969 void gtk_clist_column_titles_passive( GtkCList *clist );
6970 </verb></tscreen>
6971
6972 An active title is one which acts as a normal button, a passive one is
6973 just a label. The first two calls above will activate/deactivate the
6974 title button above the specific column, while the last two calls
6975 activate/deactivate all title buttons in the supplied clist widget.
6976
6977 But of course there are those cases when we don't want them at all,
6978 and so they can be hidden and shown at will using the following two
6979 calls.
6980
6981 <tscreen><verb>
6982 void gtk_clist_column_titles_show( GtkCList *clist );
6983
6984 void gtk_clist_column_titles_hide( GtkCList *clist );
6985 </verb></tscreen>
6986
6987 For titles to be really useful we need a mechanism to set and change
6988 them, and this is done using
6989
6990 <tscreen><verb>
6991 void gtk_clist_set_column_title( GtkCList *clist,
6992                                  gint      column,
6993                                  gchar    *title );
6994 </verb></tscreen>
6995
6996 Note that only the title of one column can be set at a time, so if all
6997 the titles are known from the beginning, then I really suggest using
6998 gtk_clist_new_with_titles (as described above) to set them. Saves you
6999 coding time, and makes your program smaller. There are some cases
7000 where getting the job done the manual way is better, and that's when
7001 not all titles will be text. GtkCList provides us with title buttons
7002 that can in fact incorporate whole widgets, for example a pixmap. It's
7003 all done through
7004
7005 <tscreen><verb>
7006 void gtk_clist_set_column_widget( GtkCList  *clist,
7007                                   gint       column,
7008                                   GtkWidget *widget );
7009 </verb></tscreen>
7010
7011 which should require no special explanation.
7012
7013 <!-- ----------------------------------------------------------------- -->
7014 <sect1>Manipulating the list itself
7015 <p>
7016 It is possible to change the justification for a column, and it is
7017 done through
7018
7019 <tscreen><verb>
7020 void gtk_clist_set_column_justification( GtkCList         *clist,
7021                                          gint              column,
7022                                          GtkJustification  justification );
7023 </verb></tscreen>
7024
7025 The GtkJustification type can take the following values:
7026
7027 <itemize>
7028 <item>GTK_JUSTIFY_LEFT - The text in the column will begin from the
7029 left edge.
7030
7031 <item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the
7032 right edge.
7033
7034 <item>GTK_JUSTIFY_CENTER - The text is placed in the center of the
7035 column.
7036
7037 <item>GTK_JUSTIFY_FILL - The text will use up all available space in
7038 the column. It is normally done by inserting extra blank spaces
7039 between words (or between individual letters if it's a single
7040 word). Much in the same way as any ordinary WYSIWYG text editor.
7041 </itemize>
7042
7043 The next function is a very important one, and should be standard in
7044 the setup of all GtkCList widgets. When the list is created, the width
7045 of the various columns are chosen to match their titles, and since
7046 this is seldom the right width we have to set it using
7047
7048 <tscreen><verb>
7049 void gtk_clist_set_column_width( GtkCList *clist,
7050                                  gint      column,
7051                                  gint      width );
7052 </verb></tscreen>
7053
7054 Note that the width is given in pixels and not letters. The same goes
7055 for the height of the cells in the columns, but as the default value
7056 is the height of the current font this isn't as critical to the
7057 application. Still, it is done through
7058
7059 <tscreen><verb>
7060 void gtk_clist_set_row_height( GtkCList *clist,
7061                                gint      height );
7062 </verb></tscreen>
7063
7064 Again, note that the height is given in pixels.
7065
7066 We can also move the list around without user interaction, however, it
7067 does require that we know what we are looking for. Or in other words,
7068 we need the row and column of the item we want to scroll to.
7069
7070 <tscreen><verb>
7071 void gtk_clist_moveto( GtkCList *clist,
7072                        gint      row,
7073                        gint      column,
7074                        gfloat    row_align,
7075                        gfloat    col_align );
7076 </verb></tscreen>
7077
7078 The gfloat row_align is pretty important to understand. It's a value
7079 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
7080 the row appears at the top, while if the value of row_align is 1.0,
7081 the row will appear at the bottom instead. All other values between
7082 0.0 and 1.0 are also valid and will place the row between the top and
7083 the bottom. The last argument, gfloat col_align works in the same way,
7084 though 0.0 marks left and 1.0 marks right instead.
7085
7086 Depending on the application's needs, we don't have to scroll to an
7087 item that is already visible to us. So how do we know if it is
7088 visible? As usual, there is a function to find that out as well.
7089
7090 <tscreen><verb>
7091 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
7092                                         gint      row );
7093 </verb></tscreen>
7094
7095 The return value is is one of the following:
7096
7097 <itemize>
7098 <item>GTK_VISIBILITY_NONE
7099
7100 <item>GTK_VISIBILITY_PARTIAL
7101
7102 <item>GTK_VISIBILITY_FULL
7103 </itemize>
7104
7105 Note that it will only tell us if a row is visible. Currently there is
7106 no way to determine this for a column. We can get partial information
7107 though, because if the return is GTK_VISIBILITY_PARTIAL, then some of
7108 it is hidden, but we don't know if it is the row that is being cut by
7109 the lower edge of the listbox, or if the row has columns that are
7110 outside.
7111
7112 We can also change both the foreground and background colors of a
7113 particular row. This is useful for marking the row selected by the
7114 user, and the two functions that is used to do it are
7115
7116 <tscreen><verb>
7117 void gtk_clist_set_foreground( GtkCList *clist,
7118                                gint      row,
7119                                GdkColor *color );
7120
7121 void gtk_clist_set_background( GtkCList *clist,
7122                                gint      row,
7123                                GdkColor *color );
7124 </verb></tscreen>
7125
7126 Please note that the colors must have been previously allocated.
7127
7128 <!-- ----------------------------------------------------------------- -->
7129 <sect1>Adding rows to the list
7130 <p>
7131 We can add rows in three ways. They can be prepended or appended to
7132 the list using
7133
7134 <tscreen><verb>
7135 gint gtk_clist_prepend( GtkCList *clist,
7136                         gchar    *text[] );
7137
7138 gint gtk_clist_append( GtkCList *clist,
7139                        gchar    *text[] );
7140 </verb></tscreen>
7141
7142 The return value of these two functions indicate the index of the row
7143 that was just added. We can insert a row at a given place using
7144
7145 <tscreen><verb>
7146 void gtk_clist_insert( GtkCList *clist,
7147                        gint      row,
7148                        gchar    *text[] );
7149 </verb></tscreen>
7150
7151 In these calls we have to provide a collection of pointers that are
7152 the texts we want to put in the columns. The number of pointers should
7153 equal the number of columns in the list. If the text[] argument is
7154 NULL, then there will be no text in the columns of the row. This is
7155 useful, for example, if we want to add pixmaps instead (something that
7156 has to be done manually).
7157
7158 Also, please note that the numbering of both rows and columns start at 0.
7159
7160 To remove an individual row we use
7161
7162 <tscreen><verb>
7163 void gtk_clist_remove( GtkCList *clist,
7164                        gint      row );
7165 </verb></tscreen>
7166
7167 There is also a call that removes all rows in the list. This is a lot
7168 faster than calling gtk_clist_remove once for each row, which is the
7169 only alternative.
7170
7171 <tscreen><verb>
7172 void gtk_clist_clear( GtkCList *clist );
7173 </verb></tscreen>
7174
7175 There are also two convenience functions that should be used when a
7176 lot of changes have to be made to the list. This is to prevent the
7177 list flickering while being repeatedly updated, which may be highly
7178 annoying to the user. So instead it is a good idea to freeze the list,
7179 do the updates to it, and finally thaw it which causes the list to be
7180 updated on the screen.
7181
7182 <tscreen><verb>
7183 void gtk_clist_freeze( GtkCList * clist );
7184
7185 void gtk_clist_thaw( GtkCList * clist );
7186 </verb></tscreen>
7187
7188 <!-- ----------------------------------------------------------------- -->
7189 <sect1>Setting text and pixmaps in the cells
7190 <p>
7191 A cell can contain a pixmap, text or both. To set them the following
7192 functions are used.
7193
7194 <tscreen><verb>
7195 void gtk_clist_set_text( GtkCList *clist,
7196                          gint      row,
7197                          gint      column,
7198                          gchar    *text );
7199
7200 void gtk_clist_set_pixmap( GtkCList  *clist,
7201                            gint       row,
7202                            gint       column,
7203                            GdkPixmap *pixmap,
7204                            GdkBitmap *mask );
7205
7206 void gtk_clist_set_pixtext( GtkCList  *clist,
7207                             gint       row,
7208                             gint       column,
7209                             gchar     *text,
7210                             guint8     spacing,
7211                             GdkPixmap *pixmap,
7212                             GdkBitmap *mask );
7213 </verb></tscreen>
7214
7215 It's quite straightforward. All the calls have the GtkCList as the
7216 first argument, followed by the row and column of the cell, followed
7217 by the data to be set. The <tt/spacing/ argument in
7218 gtk_clist_set_pixtext is the number of pixels between the pixmap and
7219 the beginning of the text.
7220
7221 To read back the data, we instead use
7222
7223 <tscreen><verb>
7224 gint gtk_clist_get_text( GtkCList  *clist,
7225                          gint       row,
7226                          gint       column,
7227                          gchar    **text );
7228
7229 gint gtk_clist_get_pixmap( GtkCList   *clist,
7230                            gint        row,
7231                            gint        column,
7232                            GdkPixmap **pixmap,
7233                            GdkBitmap **mask );
7234
7235 gint gtk_clist_get_pixtext( GtkCList   *clist,
7236                             gint        row,
7237                             gint        column,
7238                             gchar     **text,
7239                             guint8     *spacing,
7240                             GdkPixmap **pixmap,
7241                             GdkBitmap **mask );
7242 </verb></tscreen>
7243
7244 It isn't necessary to read it all back in case you aren't
7245 interested. Any of the pointers that are meant for return values (all
7246 except the clist) can be NULL. So if we want to read back only the
7247 text from a cell that is of type pixtext, then we would do the
7248 following, assuming that clist, row and column already exist:
7249
7250 <tscreen><verb>
7251 gchar *mytext;
7252
7253 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
7254 </verb></tscreen>
7255
7256 There is one more call that is related to what's inside a cell in the
7257 clist, and that's
7258
7259 <tscreen><verb>
7260 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
7261                                      gint      row,
7262                                      gint      column );
7263 </verb></tscreen>
7264
7265 which returns the type of data in a cell. The return value is one of
7266
7267 <itemize>
7268 <item>GTK_CELL_EMPTY
7269
7270 <item>GTK_CELL_TEXT
7271
7272 <item>GTK_CELL_PIXMAP
7273
7274 <item>GTK_CELL_PIXTEXT
7275
7276 <item>GTK_CELL_WIDGET
7277 </itemize>
7278
7279 There is also a function that will let us set the indentation, both
7280 vertical and horizontal, of a cell. The indentation value is of type
7281 gint, given in pixels, and can be both positive and negative.
7282
7283 <tscreen><verb>
7284 void gtk_clist_set_shift( GtkCList *clist,
7285                           gint      row,
7286                           gint      column,
7287                           gint      vertical,
7288                           gint      horizontal );
7289 </verb></tscreen>
7290
7291 <!-- ----------------------------------------------------------------- -->
7292 <sect1>Storing data pointers
7293 <p>
7294 With a GtkCList it is possible to set a data pointer for a row. This
7295 pointer will not be visible for the user, but is merely a convenience
7296 for the programmer to associate a row with a pointer to some
7297 additional data.
7298
7299 The functions should be fairly self-explanatory by now
7300
7301 <tscreen><verb>
7302 void gtk_clist_set_row_data( GtkCList *clist,
7303                              gint      row,
7304                              gpointer  data );
7305
7306 void gtk_clist_set_row_data_full( GtkCList         *clist,
7307                                   gint              row,
7308                                   gpointer          data,
7309                                   GtkDestroyNotify  destroy );
7310
7311 gpointer gtk_clist_get_row_data( GtkCList *clist,
7312                                  gint      row );
7313
7314 gint gtk_clist_find_row_from_data( GtkCList *clist,
7315                                    gpointer  data );
7316 </verb></tscreen>
7317
7318 <!-- ----------------------------------------------------------------- -->
7319 <sect1>Working with selections
7320 <p>
7321 There are also functions available that let us force the (un)selection
7322 of a row. These are
7323
7324 <tscreen><verb>
7325 void gtk_clist_select_row( GtkCList *clist,
7326                            gint      row,
7327                            gint      column );
7328
7329 void gtk_clist_unselect_row( GtkCList *clist,
7330                              gint      row,
7331                              gint      column );
7332 </verb></tscreen>
7333
7334 And also a function that will take x and y coordinates (for example,
7335 read from the mousepointer), and map that onto the list, returning the
7336 corresponding row and column.
7337
7338 <tscreen><verb>
7339 gint gtk_clist_get_selection_info( GtkCList *clist,
7340                                    gint      x,
7341                                    gint      y,
7342                                    gint     *row,
7343                                    gint     *column );
7344 </verb></tscreen>
7345
7346 When we detect something of interest, it might be movement of the
7347 pointer, a click somewhere in the list, we can read the pointer
7348 coordinates and find out where in the list the pointer is. Cumbersome?
7349 Luckily, there is a simpler way...
7350
7351 <!-- ----------------------------------------------------------------- -->
7352 <sect1>The signals that bring it together
7353 <p>
7354 As with all other widgets, there are a few signals that can be used. The
7355 GtkCList widget is derived from the GtkContainer widget, and so has all the
7356 same signals, but also the adds following:
7357
7358 <itemize>
7359 <item>select_row - This signal will send the following information, in
7360 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
7361
7362 <item>unselect_row - When the user unselects a row, this signal is
7363 activated. It sends the same information as select_row
7364
7365 <item>click_column - Send GtkCList *clist, gint column
7366 </itemize>
7367
7368 So if we want to connect a callback to select_row, the callback
7369 function would be declared like this
7370
7371 <tscreen><verb>
7372 void select_row_callback(GtkWidget *widget,
7373                          gint row,
7374                          gint column,
7375                          GdkEventButton *event,
7376                          gpointer data);
7377 </verb></tscreen>
7378
7379 The callback is connected as usual with
7380
7381 <tscreen><verb>
7382 gtk_signal_connect(GTK_OBJECT( clist),
7383                    "select_row"
7384                    GTK_SIGNAL_FUNC(select_row_callback),
7385                    NULL);
7386 </verb></tscreen>
7387
7388 <!-- ----------------------------------------------------------------- -->
7389 <sect1>A GtkCList example
7390 <p>
7391
7392 <tscreen><verb>
7393 /* example-start clist clist.c */
7394
7395 #include        <gtk/gtk.h>
7396 #include        <glib.h>
7397
7398 /* These are just the prototypes of the various callbacks */
7399 void button_add_clicked( GtkWidget *button, gpointer data);
7400 void button_clear_clicked( GtkWidget *button, gpointer data);
7401 void button_hide_show_clicked( GtkWidget *button, gpointer data);
7402 void selection_made( GtkWidget *clist, gint row, gint column,
7403                      GdkEventButton *event, gpointer data);
7404
7405 gint main (int argc, gchar *argv[])
7406 {                                  
7407     GtkWidget       *window;
7408     GtkWidget       *vbox, *hbox;
7409     GtkWidget       *clist;
7410     GtkWidget       *button_add, *button_clear, *button_hide_show;    
7411     gchar           *titles[2] = {"Ingredients","Amount"};
7412
7413     gtk_init(&amp;argc, &amp;argv);
7414     
7415     
7416     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
7417     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
7418
7419     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
7420     gtk_signal_connect(GTK_OBJECT(window),
7421                        "destroy",
7422                        GTK_SIGNAL_FUNC(gtk_main_quit),
7423                        NULL);
7424     
7425     vbox=gtk_vbox_new(FALSE, 5);
7426     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
7427     gtk_container_add(GTK_CONTAINER(window), vbox);
7428     gtk_widget_show(vbox);
7429     
7430     /* Create the GtkCList. For this example we use 2 columns */
7431     clist = gtk_clist_new_with_titles( 2, titles);
7432
7433     /* When a selection is made, we want to know about it. The callback
7434      * used is selection_made, and its code can be found further down */
7435     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
7436                        GTK_SIGNAL_FUNC(selection_made),
7437                        NULL);
7438
7439     /* It isn't necessary to shadow the border, but it looks nice :) */
7440     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
7441
7442     /* What however is important, is that we set the column widths as
7443      * they will never be right otherwise. Note that the columns are
7444      * numbered from 0 and up (to 1 in this case).
7445      */
7446     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
7447
7448     /* Add the GtkCList widget to the vertical box and show it. */
7449     gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
7450     gtk_widget_show(clist);
7451
7452     /* Create the buttons and add them to the window. See the button
7453      * tutorial for more examples and comments on this.
7454      */
7455     hbox = gtk_hbox_new(FALSE, 0);
7456     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
7457     gtk_widget_show(hbox);
7458
7459     button_add = gtk_button_new_with_label("Add List");
7460     button_clear = gtk_button_new_with_label("Clear List");
7461     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
7462
7463     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
7464     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
7465     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
7466
7467     /* Connect our callbacks to the three buttons */
7468     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
7469                               GTK_SIGNAL_FUNC(button_add_clicked),
7470                               (gpointer) clist);
7471     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
7472                               GTK_SIGNAL_FUNC(button_clear_clicked),
7473                               (gpointer) clist);
7474     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
7475                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
7476                               (gpointer) clist);
7477
7478     gtk_widget_show(button_add);
7479     gtk_widget_show(button_clear);
7480     gtk_widget_show(button_hide_show);
7481
7482     /* The interface is completely set up so we show the window and
7483      * enter the gtk_main loop.
7484      */
7485     gtk_widget_show(window);
7486     gtk_main();
7487     
7488     return(0);
7489 }
7490
7491 /* User clicked the "Add List" button. */
7492 void button_add_clicked( GtkWidget *button, gpointer data)
7493 {
7494     int         indx;
7495
7496     /* Something silly to add to the list. 4 rows of 2 columns each */
7497     gchar      *drink[4][2] = {{"Milk", "3 Oz"},
7498                                {"Water", "6 l"},
7499                                {"Carrots", "2"},
7500                                {"Snakes", "55"}};
7501
7502     /* Here we do the actual adding of the text. It's done once for
7503      * each row.
7504      */
7505     for( indx=0; indx < 4; indx++)
7506         gtk_clist_append( (GtkCList*) data, drink[indx]);
7507
7508     return;
7509 }
7510
7511 /* User clicked the "Clear List" button. */
7512 void button_clear_clicked( GtkWidget *button, gpointer data)
7513 {
7514     /* Clear the list using gtk_clist_clear. This is much faster than
7515      * calling gtk_clist_remove once for each row.
7516      */
7517     gtk_clist_clear((GtkCList*) data);
7518
7519     return;
7520 }
7521
7522 /* The user clicked the "Hide/Show titles" button. */
7523 void button_hide_show_clicked( GtkWidget *button, gpointer data)
7524 {
7525     /* Just a flag to remember the status. 0 = currently visible */
7526     static short int flag = 0;
7527
7528     if (flag == 0)
7529     {
7530         /* Hide the titles and set the flag to 1 */
7531         gtk_clist_column_titles_hide((GtkCList*) data);
7532         flag++;
7533     }
7534     else
7535     {
7536         /* Show the titles and reset flag to 0 */
7537         gtk_clist_column_titles_show((GtkCList*) data);
7538         flag--;
7539     }
7540
7541     return;
7542 }
7543
7544 /* If we come here, then the user has selected a row in the list. */
7545 void selection_made( GtkWidget *clist, gint row, gint column,
7546                      GdkEventButton *event, gpointer data)
7547 {
7548     gchar       *text;
7549
7550     /* Get the text that is stored in the selected row and column
7551      * which was clicked in. We will receive it as a pointer in the
7552      * argument text.
7553      */
7554     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
7555
7556     /* Just prints some information about the selected row */
7557     g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
7558
7559     return;
7560 }
7561 /* example-end */
7562 </verb></tscreen>
7563                     
7564 <!-- ***************************************************************** -->
7565 <sect> Tree Widget <label id="sec_Tree_Widgets">
7566 <!-- ***************************************************************** -->
7567 <p>
7568 The purpose of tree widgets is to display hierarchically-organized
7569 data. The GtkTree widget itself is a vertical container for widgets of
7570 type GtkTreeItem. GtkTree itself is not terribly different from
7571 GtkList - both are derived directly from GtkContainer, and the
7572 GtkContainer methods work in the same way on GtkTree widgets as on
7573 GtkList widgets. The difference is that GtkTree widgets can be nested
7574 within other GtkTree widgets. We'll see how to do this shortly.
7575
7576 The GtkTree widget has its own window, and defaults to a white
7577 background, as does GtkList. Also, most of the GtkTree methods work in
7578 the same way as the corresponding GtkList ones. However, GtkTree is
7579 not derived from GtkList, so you cannot use them interchangeably.
7580
7581 <sect1> Creating a Tree
7582 <p>
7583 A GtkTree is created in the usual way, using:
7584
7585 <tscreen><verb>
7586 GtkWidget* gtk_tree_new( void );
7587 </verb></tscreen>
7588
7589 Like the GtkList widget, a GtkTree will simply keep growing as more
7590 items are added to it, as well as when subtrees are expanded.  For
7591 this reason, they are almost always packed into a
7592 GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
7593 scrolled window to ensure that it is big enough to see the tree's
7594 items, as the default size for GtkScrolledWindow is quite small.
7595
7596 Now that you have a tree, you'll probably want to add some items to
7597 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
7598 explains the gory details of GtkTreeItem. For now, it'll suffice to
7599 create one, using:
7600
7601 <tscreen><verb>
7602 GtkWidget* gtk_tree_item_new_with_label( gchar *label );
7603 </verb></tscreen>
7604
7605 You can then add it to the tree using one of the following (see
7606 <ref id="sec_GtkTree_Functions" name="Functions and Macros">
7607 below for more options):
7608
7609 <tscreen><verb>
7610 void gtk_tree_append( GtkTree    *tree,
7611                        GtkWidget *tree_item );
7612
7613 void gtk_tree_prepend( GtkTree   *tree,
7614                        GtkWidget *tree_item );
7615 </verb></tscreen>
7616
7617 Note that you must add items to a GtkTree one at a time - there is no
7618 equivalent to gtk_list_*_items().
7619
7620 <!-- ----------------------------------------------------------------- -->
7621 <sect1> Adding a Subtree
7622 <p>
7623 A subtree is created like any other GtkTree widget. A subtree is added
7624 to another tree beneath a tree item, using:
7625
7626 <tscreen><verb>
7627 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
7628                                 GtkWidget   *subtree );
7629 </verb></tscreen>
7630
7631 You do not need to call gtk_widget_show() on a subtree before or after
7632 adding it to a GtkTreeItem. However, you <em>must</em> have added the
7633 GtkTreeItem in question to a parent tree before calling
7634 gtk_tree_item_set_subtree(). This is because, technically, the parent
7635 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
7636 rather the GtkTree which holds that GtkTreeItem.
7637
7638 When you add a subtree to a GtkTreeItem, a plus or minus sign appears
7639 beside it, which the user can click on to "expand" or "collapse" it,
7640 meaning, to show or hide its subtree. GtkTreeItems are collapsed by
7641 default. Note that when you collapse a GtkTreeItem, any selected
7642 items in its subtree remain selected, which may not be what the user
7643 expects.
7644
7645 <!-- ----------------------------------------------------------------- -->
7646 <sect1> Handling the Selection List
7647 <p>
7648 As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
7649 it is possible to control the behaviour of the tree (somewhat) by
7650 setting the selection type using:
7651
7652 <tscreen><verb>
7653 void gtk_tree_set_selection_mode( GtkTree          *tree,
7654                                   GtkSelectionMode  mode );
7655 </verb></tscreen>
7656
7657 The semantics associated with the various selection modes are
7658 described in the section on the GtkList widget. As with the GtkList
7659 widget, the "select_child", "unselect_child" (not really - see <ref
7660 id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
7661 and "selection_changed" signals are emitted when list items are
7662 selected or unselected. However, in order to take advantage of these
7663 signals, you need to know <em>which</em> GtkTree widget they will be
7664 emitted by, and where to find the list of selected items.
7665
7666 This is a source of potential confusion. The best way to explain this
7667 is that though all GtkTree widgets are created equal, some are more
7668 equal than others. All GtkTree widgets have their own X window, and
7669 can therefore receive events such as mouse clicks (if their
7670 GtkTreeItems or their children don't catch them first!). However, to
7671 make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
7672 behave in a sane manner, the list of selected items is specific to the
7673 topmost GtkTree widget in a hierarchy, known as the "root tree".
7674
7675 Thus, accessing the <tt>selection</tt>field directly in an arbitrary
7676 GtkTree widget is not a good idea unless you <em>know</em> it's the
7677 root tree.  Instead, use the GTK_TREE_SELECTION (Tree) macro, which
7678 gives the root tree's selection list as a GList pointer. Of course,
7679 this list can include items that are not in the subtree in question if 
7680 the selection type is GTK_SELECTION_MULTIPLE.
7681
7682 Finally, the "select_child" (and "unselect_child", in theory) signals
7683 are emitted by all trees, but the "selection_changed" signal is only
7684 emitted by the root tree. Consequently, if you want to handle the
7685 "select_child" signal for a tree and all its subtrees, you will have
7686 to call gtk_signal_connect() for every subtree.
7687
7688 <sect1> Tree Widget Internals
7689 <p>
7690 The GtkTree's struct definition looks like this:
7691
7692 <tscreen><verb>
7693 struct _GtkTree
7694 {
7695   GtkContainer container;
7696
7697   GList *children;
7698   
7699   GtkTree* root_tree; /* owner of selection list */
7700   GtkWidget* tree_owner;
7701   GList *selection;
7702   guint level;
7703   guint indent_value;
7704   guint current_indent;
7705   guint selection_mode : 2;
7706   guint view_mode : 1;
7707   guint view_line : 1;
7708 };
7709 </verb></tscreen>
7710
7711 The perils associated with accessing the <tt>selection</tt> field
7712 directly have already been mentioned. The other important fields of
7713 the struct can also be accessed with handy macros or class functions.
7714 GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
7715 whether a tree is the root tree in a GtkTree hierarchy, while
7716 GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
7717 GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
7718 to use one of the gtk_widget_*() functions on it).
7719
7720 Instead of directly accessing the children field of a GtkTree widget,
7721 it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
7722 to the gtk_container_children() function. This creates a duplicate of
7723 the original list, so it's advisable to free it up using g_list_free()
7724 after you're done with it, or to iterate on it destructively, like
7725 this:
7726
7727 <tscreen><verb>
7728     children = gtk_container_children (GTK_CONTAINER (tree));
7729     while (children) {
7730       do_something_nice (GTK_TREE_ITEM (children->data));
7731       children = g_list_remove_link (children, children);
7732 }
7733 </verb></tscreen>
7734
7735 The <tt>tree_owner</tt> field is defined only in subtrees, where it
7736 points to the GtkTreeItem widget which holds the tree in question.
7737 The <tt>level</tt> field indicates how deeply nested a particular tree
7738 is; root trees have level 0, and each successive level of subtrees has
7739 a level one greater than the parent level. This field is set only
7740 after a GtkTree widget is actually mapped (i.e. drawn on the screen).
7741
7742 <sect2> Signals<label id="sec_GtkTree_Signals">
7743 <p>
7744 <tscreen><verb>
7745 void selection_changed( GtkTree *tree );
7746 </verb></tscreen>
7747
7748 This signal will be emitted whenever the <tt>selection</tt> field of a
7749 GtkTree has changed. This happens when a child of the GtkTree is
7750 selected or deselected.
7751
7752 <tscreen><verb>
7753 void select_child( GtkTree   *tree,
7754                    GtkWidget *child );
7755 </verb></tscreen>
7756
7757 This signal is emitted when a child of the GtkTree is about to get
7758 selected. This happens on calls to gtk_tree_select_item(),
7759 gtk_tree_select_child(), on <em>all</em> button presses and calls to
7760 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
7761 indirectly triggered on other occasions where children get added to or
7762 removed from the GtkTree.
7763
7764 <tscreen><verb>
7765 void unselect_child (GtkTree   *tree,
7766                      GtkWidget *child);
7767 </verb></tscreen>
7768
7769 This signal is emitted when a child of the GtkTree is about to get
7770 deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
7771 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
7772 other occasions, but <em>not</em> when a button press deselects a
7773 child, nor on emission of the "toggle" signal by gtk_item_toggle().
7774
7775 <sect2> Functions and Macros<label id="sec_GtkTree_Functions">
7776 <p>
7777 <tscreen><verb>
7778 guint gtk_tree_get_type( void );
7779 </verb></tscreen>
7780
7781 Returns the `GtkTree' type identifier.
7782
7783 <tscreen><verb>
7784 GtkWidget* gtk_tree_new( void );
7785 </verb></tscreen>
7786
7787 Create a new GtkTree object. The new widget is returned as a pointer
7788 to a GtkWidget object. NULL is returned on failure.
7789
7790 <tscreen><verb>
7791 void gtk_tree_append( GtkTree   *tree,
7792                       GtkWidget *tree_item );
7793 </verb></tscreen>
7794
7795 Append a tree item to a GtkTree.
7796
7797 <tscreen><verb>
7798 void gtk_tree_prepend( GtkTree   *tree,
7799                        GtkWidget *tree_item );
7800 </verb></tscreen>
7801
7802 Prepend a tree item to a GtkTree.
7803
7804 <tscreen><verb>
7805 void gtk_tree_insert( GtkTree   *tree,
7806                       GtkWidget *tree_item,
7807                       gint       position );
7808 </verb></tscreen>
7809
7810 Insert a tree item into a GtkTree at the position in the list
7811 specified by <tt>position.</tt>
7812
7813 <tscreen><verb>
7814 void gtk_tree_remove_items( GtkTree *tree,
7815                             GList   *items );
7816 </verb></tscreen>
7817
7818 Remove a list of items (in the form of a GList *) from a GtkTree.
7819 Note that removing an item from a tree dereferences (and thus usually)
7820 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
7821 subtrees in that subtree.  If you want to remove only one item, you
7822 can use gtk_container_remove().
7823
7824 <tscreen><verb>
7825 void gtk_tree_clear_items( GtkTree *tree,
7826                            gint     start,
7827                            gint     end );
7828 </verb></tscreen>
7829
7830 Remove the items from position <tt>start</tt> to position <tt>end</tt>
7831 from a GtkTree.  The same warning about dereferencing applies here, as
7832 gtk_tree_clear_items() simply constructs a list and passes it to
7833 gtk_tree_remove_items().
7834
7835 <tscreen><verb>
7836 void gtk_tree_select_item( GtkTree *tree,
7837                            gint     item );
7838 </verb></tscreen>
7839
7840 Emits the "select_item" signal for the child at position
7841 <tt>item</tt>, thus selecting the child (unless you unselect it in a
7842 signal handler).
7843
7844 <tscreen><verb>
7845 void gtk_tree_unselect_item( GtkTree *tree,
7846                              gint     item );
7847 </verb></tscreen>
7848
7849 Emits the "unselect_item" signal for the child at position
7850 <tt>item</tt>, thus unselecting the child.
7851
7852 <tscreen><verb>
7853 void gtk_tree_select_child( GtkTree   *tree,
7854                             GtkWidget *tree_item );
7855 </verb></tscreen>
7856
7857 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
7858 selecting it.
7859
7860 <tscreen><verb>
7861 void gtk_tree_unselect_child( GtkTree   *tree,
7862                               GtkWidget *tree_item );
7863 </verb></tscreen>
7864
7865 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
7866 thus unselecting it.
7867
7868 <tscreen><verb>
7869 gint gtk_tree_child_position( GtkTree   *tree,
7870                               GtkWidget *child );
7871 </verb></tscreen>
7872
7873 Returns the position in the tree of <tt>child</tt>, unless
7874 <tt>child</tt> is not in the tree, in which case it returns -1.
7875
7876 <tscreen><verb>
7877 void gtk_tree_set_selection_mode( GtkTree          *tree,
7878                                   GtkSelectionMode  mode );
7879 </verb></tscreen>
7880
7881 Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
7882 default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
7883 GTK_SELECTION_EXTENDED. This is only defined for root trees, which
7884 makes sense, since the root tree "owns" the selection. Setting it for
7885 subtrees has no effect at all; the value is simply ignored.
7886
7887 <tscreen><verb>
7888 void gtk_tree_set_view_mode( GtkTree         *tree,
7889                              GtkTreeViewMode  mode ); 
7890 </verb></tscreen>
7891
7892 Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
7893 default) or GTK_TREE_VIEW_ITEM.  The view mode propagates from a tree
7894 to its subtrees, and can't be set exclusively to a subtree (this is
7895 not exactly true - see the example code comments).
7896
7897 The term "view mode" is rather ambiguous - basically, it controls the
7898 way the highlight is drawn when one of a tree's children is selected.
7899 If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
7900 highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
7901 (i.e. usually the label) is highlighted.
7902
7903 <tscreen><verb>
7904 void gtk_tree_set_view_lines( GtkTree *tree,
7905                               guint    flag );
7906 </verb></tscreen>
7907
7908 Controls whether connecting lines between tree items are drawn.
7909 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
7910 which case they aren't.
7911
7912 <tscreen><verb>
7913 GtkTree *GTK_TREE (gpointer obj);
7914 </verb></tscreen>
7915
7916 Cast a generic pointer to `GtkTree *'.
7917
7918 <tscreen><verb>
7919 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
7920 </verb></tscreen>
7921
7922 Cast a generic pointer to `GtkTreeClass*'.
7923
7924 <tscreen><verb>
7925 gint GTK_IS_TREE (gpointer obj);
7926 </verb></tscreen>
7927
7928 Determine if a generic pointer refers to a `GtkTree' object.
7929
7930 <tscreen><verb>
7931 gint GTK_IS_ROOT_TREE (gpointer obj)
7932 </verb></tscreen>
7933
7934 Determine if a generic pointer refers to a `GtkTree' object
7935 <em>and</em> is a root tree. Though this will accept any pointer, the
7936 results of passing it a pointer that does not refer to a GtkTree are
7937 undefined and possibly harmful.
7938
7939 <tscreen><verb>
7940 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
7941 </verb></tscreen>
7942
7943 Return the root tree of a pointer to a `GtkTree' object. The above
7944 warning applies.
7945
7946 <tscreen><verb>
7947 GList *GTK_TREE_SELECTION( gpointer obj)
7948 </verb></tscreen>
7949
7950 Return the selection list of the root tree of a `GtkTree' object. The
7951 above warning applies here, too.
7952
7953 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
7954 <p>
7955 The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
7956 which in turn is derived from GtkBin.  Therefore, the item itself is a
7957 generic container holding exactly one child widget, which can be of
7958 any type.  The GtkTreeItem widget has a number of extra fields, but
7959 the only one we need be concerned with is the <tt>subtree</tt> field.
7960
7961 The definition for the GtkTreeItem struct looks like this:
7962
7963 <tscreen><verb>
7964 struct _GtkTreeItem
7965 {
7966   GtkItem item;
7967
7968   GtkWidget *subtree;
7969   GtkWidget *pixmaps_box;
7970   GtkWidget *plus_pix_widget, *minus_pix_widget;
7971
7972   GList *pixmaps;               /* pixmap node for this items color depth */
7973
7974   guint expanded : 1;
7975 };
7976 </verb></tscreen>
7977
7978 The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
7979 on the plus/minus symbol which controls expansion and collapsing.  The
7980 <tt>pixmaps</tt> field points to an internal data structure.  Since
7981 you can always obtain the subtree of a GtkTreeItem in a (relatively)
7982 type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
7983 probably advisable never to touch the insides of a GtkTreeItem unless
7984 you <em>really</em> know what you're doing.
7985
7986 Since it is directly derived from a GtkItem it can be treated as such
7987 by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
7988 label, so the convenience function gtk_list_item_new_with_label() is
7989 provided. The same effect can be achieved using code like the
7990 following, which is actually copied verbatim from
7991 gtk_tree_item_new_with_label():
7992
7993 <tscreen><verb>
7994 tree_item = gtk_tree_item_new ();
7995 label_widget = gtk_label_new (label);
7996 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
7997
7998 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
7999 gtk_widget_show (label_widget);
8000 </verb></tscreen>
8001
8002 As one is not forced to add a GtkLabel to a GtkTreeItem, you could
8003 also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
8004 app will likely be quite unpopular in this case) to the GtkTreeItem.
8005
8006 If you remove all the items from a subtree, it will be destroyed and
8007 unparented, unless you reference it beforehand, and the GtkTreeItem
8008 which owns it will be collapsed.  So, if you want it to stick around,
8009 do something like the following:
8010
8011 <tscreen><verb>
8012 gtk_widget_ref (tree);
8013 owner = GTK_TREE(tree)->tree_owner;
8014 gtk_container_remove (GTK_CONTAINER(tree), item);
8015 if (tree->parent == NULL){
8016   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
8017   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
8018 }
8019 else
8020   gtk_widget_unref (tree);
8021 </verb></tscreen>
8022
8023 Finally, drag-n-drop <em>does</em> work with GtkTreeItems.  You just
8024 have to make sure that the GtkTreeItem you want to make into a drag
8025 item or a drop site has not only been added to a GtkTree, but that
8026 each successive parent widget has a parent itself, all the way back to
8027 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
8028 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
8029
8030 <sect2> Signals
8031 <p>
8032 GtkTreeItem inherits the "select", "deselect", and "toggle" signals
8033 from GtkItem.  In addition, it adds two signals of its own, "expand"
8034 and "collapse".
8035
8036 <tscreen><verb>
8037 void select( GtkItem *tree_item );
8038 </verb></tscreen>
8039
8040 This signal is emitted when an item is about to be selected, either
8041 after it has been clicked on by the user, or when the program calls
8042 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
8043
8044 <tscreen><verb>
8045 void deselect( GtkItem *tree_item );
8046 </verb></tscreen>
8047
8048 This signal is emitted when an item is about to be unselected, either
8049 after it has been clicked on by the user, or when the program calls
8050 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
8051 GtkTreeItems, it is also emitted by gtk_tree_unselect_child(), and
8052 sometimes gtk_tree_select_child().
8053
8054 <tscreen><verb>
8055 void toggle( GtkItem *tree_item );
8056 </verb></tscreen>
8057
8058 This signal is emitted when the program calls gtk_item_toggle().  The
8059 effect it has when emitted on a GtkTreeItem is to call
8060 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
8061 item's parent tree, if the item has a parent tree.  If it doesn't,
8062 then the highlight is reversed on the item.
8063
8064 <tscreen><verb>
8065 void expand( GtkTreeItem *tree_item );
8066 </verb></tscreen>
8067
8068 This signal is emitted when the tree item's subtree is about to be
8069 expanded, that is, when the user clicks on the plus sign next to the
8070 item, or when the program calls gtk_tree_item_expand().
8071
8072 <tscreen><verb>
8073 void collapse( GtkTreeItem *tree_item );
8074 </verb></tscreen>
8075
8076 This signal is emitted when the tree item's subtree is about to be
8077 collapsed, that is, when the user clicks on the minus sign next to the
8078 item, or when the program calls gtk_tree_item_collapse().
8079
8080 <sect2> Functions and Macros
8081 <p>
8082 <tscreen><verb>
8083 guint gtk_tree_item_get_type( void );
8084 </verb></tscreen>
8085
8086 Returns the `GtkTreeItem' type identifier.
8087
8088 <tscreen><verb>
8089 GtkWidget* gtk_tree_item_new( void );
8090 </verb></tscreen>
8091
8092 Create a new GtkTreeItem object. The new widget is returned as a
8093 pointer to a GtkWidget object. NULL is returned on failure.
8094
8095 <tscreen><verb>
8096 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
8097 </verb></tscreen>
8098
8099 Create a new GtkTreeItem object, having a single GtkLabel as the sole
8100 child. The new widget is returned as a pointer to a GtkWidget
8101 object. NULL is returned on failure.
8102
8103 <tscreen><verb>
8104 void gtk_tree_item_select( GtkTreeItem *tree_item );
8105 </verb></tscreen>
8106
8107 This function is basically a wrapper around a call to gtk_item_select
8108 (GTK_ITEM (tree_item)) which will emit the select signal.
8109
8110 <tscreen><verb>
8111 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
8112 </verb></tscreen>
8113
8114 This function is basically a wrapper around a call to
8115 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
8116 signal.
8117
8118 <tscreen><verb>
8119 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8120                                 GtkWidget   *subtree );
8121 </verb></tscreen>
8122
8123 This function adds subtree to tree_item, showing it if tree_item is
8124 expanded, or hiding it if tree_item is collapsed. Again, remember that
8125 the tree_item must have already been added to a tree for this to work.
8126
8127 <tscreen><verb>
8128 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
8129 </verb></tscreen>
8130
8131 This removes all of tree_item's subtree's children (thus unreferencing
8132 and destroying it, any of its children's subtrees, and so on...), then
8133 removes the subtree itself, and hides the plus/minus sign.
8134
8135 <tscreen><verb>
8136 void gtk_tree_item_expand( GtkTreeItem *tree_item );
8137 </verb></tscreen>
8138
8139 This emits the "expand" signal on tree_item, which expands it.
8140
8141 <tscreen><verb>
8142 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
8143 </verb></tscreen>
8144
8145 This emits the "collapse" signal on tree_item, which collapses it.
8146
8147 <tscreen><verb>
8148 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
8149 </verb></tscreen>
8150
8151 Cast a generic pointer to `GtkTreeItem*'.
8152
8153 <tscreen><verb>
8154 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
8155 </verb></tscreen>
8156
8157 Cast a generic pointer to `GtkTreeItemClass'.
8158
8159 <tscreen><verb>
8160 gint GTK_IS_TREE_ITEM (gpointer obj)
8161 </verb></tscreen>
8162
8163 Determine if a generic pointer refers to a `GtkTreeItem' object.
8164  
8165 <tscreen><verb>
8166 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
8167 </verb></tscreen>
8168
8169 Returns a tree item's subtree (obj should point to a `GtkTreeItem'
8170 object).
8171
8172 <sect1> Tree Example
8173 <p>
8174 This is somewhat like the tree example in testgtk.c, but a lot less
8175 complete (although much better commented).  It puts up a window with a
8176 tree, and connects all the signals for the relevant objects, so you
8177 can see when they are emitted.
8178
8179 <tscreen><verb>
8180 /* example-start tree tree.c */
8181
8182 #include <gtk/gtk.h>
8183
8184 /* for all the GtkItem:: and GtkTreeItem:: signals */
8185 static void cb_itemsignal (GtkWidget *item, gchar *signame)
8186 {
8187   gchar *name;
8188   GtkLabel *label;
8189
8190   /* It's a GtkBin, so it has one child, which we know to be a
8191      label, so get that */
8192   label = GTK_LABEL (GTK_BIN (item)->child);
8193   /* Get the text of the label */
8194   gtk_label_get (label, &amp;name);
8195   /* Get the level of the tree which the item is in */
8196   g_print ("%s called for item %s->%p, level %d\n", signame, name,
8197            item, GTK_TREE (item->parent)->level);
8198 }
8199
8200 /* Note that this is never called */
8201 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
8202                                GtkWidget *subtree)
8203 {
8204   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
8205            root_tree, subtree, child);
8206 }
8207
8208 /* Note that this is called every time the user clicks on an item,
8209    whether it is already selected or not. */
8210 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
8211                              GtkWidget *subtree)
8212 {
8213   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
8214            root_tree, subtree, child);
8215 }
8216
8217 static void cb_selection_changed (GtkWidget *tree)
8218 {
8219   GList *i;
8220   
8221   g_print ("selection_change called for tree %p\n", tree);
8222   g_print ("selected objects are:\n");
8223
8224   i = GTK_TREE_SELECTION(tree);
8225   while (i){
8226     gchar *name;
8227     GtkLabel *label;
8228     GtkWidget *item;
8229
8230     /* Get a GtkWidget pointer from the list node */
8231     item = GTK_WIDGET (i->data);
8232     label = GTK_LABEL (GTK_BIN (item)->child);
8233     gtk_label_get (label, &amp;name);
8234     g_print ("\t%s on level %d\n", name, GTK_TREE
8235              (item->parent)->level);
8236     i = i->next;
8237   }
8238 }
8239
8240 int main (int argc, char *argv[])
8241 {
8242   GtkWidget *window, *scrolled_win, *tree;
8243   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
8244                                "Maurice"};
8245   gint i;
8246
8247   gtk_init (&amp;argc, &amp;argv);
8248
8249   /* a generic toplevel window */
8250   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8251   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
8252                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
8253   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
8254
8255   /* A generic scrolled window */
8256   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8257   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8258                                   GTK_POLICY_AUTOMATIC,
8259                                   GTK_POLICY_AUTOMATIC);
8260   gtk_widget_set_usize (scrolled_win, 150, 200);
8261   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
8262   gtk_widget_show (scrolled_win);
8263   
8264   /* Create the root tree */
8265   tree = gtk_tree_new();
8266   g_print ("root tree is %p\n", tree);
8267   /* connect all GtkTree:: signals */
8268   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
8269                       GTK_SIGNAL_FUNC(cb_select_child), tree);
8270   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
8271                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
8272   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
8273                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
8274   /* Add it to the scrolled window */
8275   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
8276                                          tree);
8277   /* Set the selection mode */
8278   gtk_tree_set_selection_mode (GTK_TREE(tree),
8279                                GTK_SELECTION_MULTIPLE);
8280   /* Show it */
8281   gtk_widget_show (tree);
8282
8283   for (i = 0; i < 5; i++){
8284     GtkWidget *subtree, *item;
8285     gint j;
8286
8287     /* Create a tree item */
8288     item = gtk_tree_item_new_with_label (itemnames[i]);
8289     /* Connect all GtkItem:: and GtkTreeItem:: signals */
8290     gtk_signal_connect (GTK_OBJECT(item), "select",
8291                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
8292     gtk_signal_connect (GTK_OBJECT(item), "deselect",
8293                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
8294     gtk_signal_connect (GTK_OBJECT(item), "toggle",
8295                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
8296     gtk_signal_connect (GTK_OBJECT(item), "expand",
8297                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
8298     gtk_signal_connect (GTK_OBJECT(item), "collapse",
8299                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
8300     /* Add it to the parent tree */
8301     gtk_tree_append (GTK_TREE(tree), item);
8302     /* Show it - this can be done at any time */
8303     gtk_widget_show (item);
8304     /* Create this item's subtree */
8305     subtree = gtk_tree_new();
8306     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
8307              subtree);
8308
8309     /* This is still necessary if you want these signals to be called
8310        for the subtree's children.  Note that selection_change will be 
8311        signalled for the root tree regardless. */
8312     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
8313                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
8314     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
8315                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
8316     /* This has absolutely no effect, because it is completely ignored 
8317        in subtrees */
8318     gtk_tree_set_selection_mode (GTK_TREE(subtree),
8319                                  GTK_SELECTION_SINGLE);
8320     /* Neither does this, but for a rather different reason - the
8321        view_mode and view_line values of a tree are propagated to
8322        subtrees when they are mapped.  So, setting it later on would
8323        actually have a (somewhat unpredictable) effect */
8324     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
8325     /* Set this item's subtree - note that you cannot do this until
8326        AFTER the item has been added to its parent tree! */
8327     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
8328
8329     for (j = 0; j < 5; j++){
8330       GtkWidget *subitem;
8331
8332       /* Create a subtree item, in much the same way */
8333       subitem = gtk_tree_item_new_with_label (itemnames[j]);
8334       /* Connect all GtkItem:: and GtkTreeItem:: signals */
8335       gtk_signal_connect (GTK_OBJECT(subitem), "select",
8336                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
8337       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
8338                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
8339       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
8340                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
8341       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
8342                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
8343       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
8344                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
8345       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
8346       /* Add it to its parent tree */
8347       gtk_tree_append (GTK_TREE(subtree), subitem);
8348       /* Show it */
8349       gtk_widget_show (subitem);
8350     }
8351   }
8352
8353   /* Show the window and loop endlessly */
8354   gtk_widget_show (window);
8355   gtk_main();
8356   return 0;
8357 }
8358 /* example-end */
8359 </verb></tscreen>
8360
8361 <!-- ***************************************************************** -->
8362 <sect>Menu Widget
8363 <!-- ***************************************************************** -->
8364 <p>
8365 There are two ways to create menus, there's the easy way, and there's
8366 the hard way. Both have their uses, but you can usually use the
8367 itemfactory (the easy way). The "hard" way is to create all the menus
8368 using the calls directly. The easy way is to use the gtk_item_factory
8369 calls. This is much simpler, but there are advantages and
8370 disadvantages to each approach.
8371
8372 The itemfactory is much easier to use, and to add new menus to,
8373 although writing a few wrapper functions to create menus using the
8374 manual method could go a long way towards usability. With the
8375 menufactory, it is not possible to add images or the character '/' to
8376 the menus.
8377
8378 <!-- ----------------------------------------------------------------- -->
8379 <sect1>Manual Menu Creation
8380 <p>
8381 In the true tradition of teaching, we'll show you the hard way
8382 first. <tt>:)</>
8383
8384 There are three widgets that go into making a menubar and submenus:
8385 <itemize>
8386 <item>a menu item, which is what the user wants to select, e.g. 'Save'
8387 <item>a menu, which acts as a container for the menu items, and
8388 <item>a menubar, which is a container for each of the individual
8389 menus.
8390 </itemize>
8391
8392 This is slightly complicated by the fact that menu item widgets are
8393 used for two different things. They are both the widgets that are
8394 packed into the menu, and the widget that is packed into the menubar,
8395 which, when selected, activates the menu.
8396
8397 Let's look at the functions that are used to create menus and
8398 menubars.  This first function is used to create a new menubar.
8399
8400 <tscreen>
8401 <verb>
8402 GtkWidget *gtk_menu_bar_new( void );
8403 </verb>
8404 </tscreen>
8405
8406 This rather self explanatory function creates a new menubar. You use
8407 gtk_container_add to pack this into a window, or the box_pack
8408 functions to pack it into a box - the same as buttons.
8409
8410 <tscreen><verb>
8411 GtkWidget *gtk_menu_new( void );
8412 </verb></tscreen>
8413
8414 This function returns a pointer to a new menu, it is never actually
8415 shown (with gtk_widget_show), it is just a container for the menu
8416 items. Hopefully this will become more clear when you look at the
8417 example below.
8418
8419 The next two calls are used to create menu items that are packed into
8420 the menu (and menubar).
8421
8422 <tscreen><verb>
8423 GtkWidget *gtk_menu_item_new( void );
8424 </verb></tscreen>
8425
8426 and
8427
8428 <tscreen><verb>
8429 GtkWidget *gtk_menu_item_new_with_label( const char *label );
8430 </verb></tscreen>
8431
8432 These calls are used to create the menu items that are to be
8433 displayed.  Remember to differentiate between a "menu" as created with
8434 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
8435 functions. The menu item will be an actual button with an associated
8436 action, whereas a menu will be a container holding menu items.
8437
8438 The gtk_menu_new_with_label and gtk_menu_new functions are just as
8439 you'd expect after reading about the buttons. One creates a new menu
8440 item with a label already packed into it, and the other just creates a
8441 blank menu item.
8442
8443 Once you've created a menu item you have to put it into a menu. This
8444 is done using the function gtk_menu_append. In order to capture when
8445 the item is selected by the user, we need to connect to the
8446 <tt/activate/ signal in the usual way. So, if we wanted to create a
8447 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/ and
8448 <tt/Quit/ the code would look something like:
8449
8450 <tscreen><verb>
8451     file_menu = gtk_menu_new();    /* Don't need to show menus */
8452
8453     /* Create the menu items */
8454     open_item = gtk_menu_item_new_with_label("Open");
8455     save_item = gtk_menu_item_new_with_label("Save");
8456     quit_item = gtk_menu_item_new_with_label("Quit");
8457
8458     /* Add them to the menu */
8459     gtk_menu_append( GTK_MENU(file_menu), open_item);
8460     gtk_menu_append( GTK_MENU(file_menu), save_item);
8461     gtk_menu_append( GTK_MENU(file_menu), quit_item);
8462
8463     /* Attach the callback functions to the activate signal */
8464     gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
8465                                GTK_SIGNAL_FUNC(menuitem_response),
8466                                (gpointer) "file.open");
8467     gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
8468                                GTK_SIGNAL_FUNC(menuitem_response),
8469                                (gpointer) "file.save");
8470
8471     /* We can attach the Quit menu item to our exit function */
8472     gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
8473                                GTK_SIGNAL_FUNC(destroy),
8474                                (gpointer) "file.quit");
8475
8476     /* We do need to show menu items */
8477     gtk_widget_show( open_item );
8478     gtk_widget_show( save_item );
8479     gtk_widget_show( quit_item );
8480 </verb></tscreen>
8481
8482 At this point we have our menu. Now we need to create a menubar and a
8483 menu item for the <tt/File/ entry, to which we add our menu. The code
8484 looks like this:
8485
8486 <tscreen><verb>
8487     menu_bar = gtk_menu_bar_new();
8488     gtk_container_add( GTK_CONTAINER(window), menu_bar);
8489     gtk_widget_show( menu_bar );
8490
8491     file_item = gtk_menu_item_new_with_label("File");
8492     gtk_widget_show(file_item);
8493 </verb></tscreen>
8494
8495 Now we need to associate the menu with <tt/file_item/. This is done
8496 with the function
8497
8498 <tscreen>
8499 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
8500                                 GtkWidget   *submenu );
8501 </tscreen>
8502
8503 So, our example would continue with
8504
8505 <tscreen><verb>
8506     gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu );
8507 </verb></tscreen>
8508
8509 All that is left to do is to add the menu to the menubar, which is
8510 accomplished using the function
8511
8512 <tscreen>
8513 void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);
8514 </tscreen>
8515
8516 which in our case looks like this:
8517
8518 <tscreen><verb>
8519     gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );
8520 </verb></tscreen>
8521
8522 If we wanted the menu right justified on the menubar, such as help
8523 menus often are, we can use the following function (again on
8524 <tt/file_item/ in the current example) before attaching it to the
8525 menubar.
8526
8527 <tscreen><verb>
8528 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
8529 </verb></tscreen>
8530
8531 Here is a summary of the steps needed to create a menu bar with menus
8532 attached:
8533
8534 <itemize>
8535 <item> Create a new menu using gtk_menu_new()
8536 <item> Use multiple calls to gtk_menu_item_new() for each item you
8537 wish to have on your menu. And use gtk_menu_append() to put each of
8538 these new items on to the menu.
8539 <item> Create a menu item using gtk_menu_item_new(). This will be the
8540 root of the menu, the text appearing here will be on the menubar
8541 itself.
8542 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
8543 menu item (the one created in the above step).
8544 <item> Create a new menubar using gtk_menu_bar_new. This step only
8545 needs to be done once when creating a series of menus on one menu bar.
8546 <item> Use gtk_menu_bar_append to put the root menu onto the menubar.
8547 </itemize>
8548
8549 Creating a popup menu is nearly the same. The difference is that the
8550 menu is not posted `automatically' by a menubar, but explicitly by
8551 calling the function gtk_menu_popup() from a button-press event, for
8552 example.  Take these steps:
8553
8554 <itemize>
8555 <item>Create an event handling function. It needs to have the
8556 prototype
8557 <tscreen>
8558 static gint handler( GtkWidget *widget,
8559                      GdkEvent  *event );
8560 </tscreen>
8561 and it will use the event to find out where to pop up the menu.
8562 <item>In the event handler, if the event is a mouse button press,
8563 treat <tt>event</tt> as a button event (which it is) and use it as
8564 shown in the sample code to pass information to gtk_menu_popup().
8565 <item>Bind that event handler to a widget with
8566 <tscreen>
8567     gtk_signal_connect_object(GTK_OBJECT(widget), "event",
8568                               GTK_SIGNAL_FUNC (handler),
8569                               GTK_OBJECT(menu));
8570 </tscreen>
8571 where <tt>widget</tt> is the widget you are binding to,
8572 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
8573 created with gtk_menu_new(). This can be a menu which is also posted
8574 by a menu bar, as shown in the sample code.
8575 </itemize>
8576
8577 <!-- ----------------------------------------------------------------- -->
8578 <sect1>Manual Menu Example
8579 <p>
8580 That should about do it. Let's take a look at an example to help clarify.
8581
8582 <tscreen><verb>
8583 /* example-start menu menu.c */
8584
8585 #include <gtk/gtk.h>
8586
8587 static gint button_press (GtkWidget *, GdkEvent *);
8588 static void menuitem_response (gchar *);
8589
8590 int main (int argc, char *argv[])
8591 {
8592
8593     GtkWidget *window;
8594     GtkWidget *menu;
8595     GtkWidget *menu_bar;
8596     GtkWidget *root_menu;
8597     GtkWidget *menu_items;
8598     GtkWidget *vbox;
8599     GtkWidget *button;
8600     char buf[128];
8601     int i;
8602
8603     gtk_init (&amp;argc, &amp;argv);
8604
8605     /* create a new window */
8606     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
8607     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
8608     gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
8609     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
8610                        (GtkSignalFunc) gtk_main_quit, NULL);
8611
8612     /* Init the menu-widget, and remember -- never
8613      * gtk_show_widget() the menu widget!! 
8614      * This is the menu that holds the menu items, the one that
8615      * will pop up when you click on the "Root Menu" in the app */
8616     menu = gtk_menu_new();
8617
8618     /* Next we make a little loop that makes three menu-entries for "test-menu".
8619      * Notice the call to gtk_menu_append.  Here we are adding a list of
8620      * menu items to our menu.  Normally, we'd also catch the "clicked"
8621      * signal on each of the menu items and setup a callback for it,
8622      * but it's omitted here to save space. */
8623
8624     for(i = 0; i < 3; i++)
8625         {
8626             /* Copy the names to the buf. */
8627             sprintf(buf, "Test-undermenu - %d", i);
8628
8629             /* Create a new menu-item with a name... */
8630             menu_items = gtk_menu_item_new_with_label(buf);
8631
8632             /* ...and add it to the menu. */
8633             gtk_menu_append(GTK_MENU (menu), menu_items);
8634
8635             /* Do something interesting when the menuitem is selected */
8636             gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
8637                 GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf));
8638
8639             /* Show the widget */
8640             gtk_widget_show(menu_items);
8641         }
8642
8643     /* This is the root menu, and will be the label
8644      * displayed on the menu bar.  There won't be a signal handler attached,
8645      * as it only pops up the rest of the menu when pressed. */
8646     root_menu = gtk_menu_item_new_with_label("Root Menu");
8647
8648     gtk_widget_show(root_menu);
8649
8650     /* Now we specify that we want our newly created "menu" to be the menu
8651      * for the "root menu" */
8652     gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
8653
8654     /* A vbox to put a menu and a button in: */
8655     vbox = gtk_vbox_new(FALSE, 0);
8656     gtk_container_add(GTK_CONTAINER(window), vbox);
8657     gtk_widget_show(vbox);
8658
8659     /* Create a menu-bar to hold the menus and add it to our main window */
8660     menu_bar = gtk_menu_bar_new();
8661     gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
8662     gtk_widget_show(menu_bar);
8663
8664     /* Create a button to which to attach menu as a popup */
8665     button = gtk_button_new_with_label("press me");
8666     gtk_signal_connect_object(GTK_OBJECT(button), "event",
8667         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
8668     gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
8669     gtk_widget_show(button);
8670
8671     /* And finally we append the menu-item to the menu-bar -- this is the
8672      * "root" menu-item I have been raving about =) */
8673     gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
8674
8675     /* always display the window as the last step so it all splashes on
8676      * the screen at once. */
8677     gtk_widget_show(window);
8678
8679     gtk_main ();
8680
8681     return 0;
8682 }
8683
8684 /* Respond to a button-press by posting a menu passed in as widget.
8685  *
8686  * Note that the "widget" argument is the menu being posted, NOT
8687  * the button that was pressed.
8688  */
8689
8690 static gint button_press (GtkWidget *widget, GdkEvent *event)
8691 {
8692
8693     if (event->type == GDK_BUTTON_PRESS) {
8694         GdkEventButton *bevent = (GdkEventButton *) event; 
8695         gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
8696                         bevent->button, bevent->time);
8697         /* Tell calling code that we have handled this event; the buck
8698          * stops here. */
8699         return TRUE;
8700     }
8701
8702     /* Tell calling code that we have not handled this event; pass it on. */
8703     return FALSE;
8704 }
8705
8706
8707 /* Print a string when a menu item is selected */
8708
8709 static void menuitem_response (gchar *string)
8710 {
8711     printf("%s\n", string);
8712 }
8713 /* example-end */
8714 </verb></tscreen>
8715
8716 You may also set a menu item to be insensitive and, using an accelerator
8717 table, bind keys to menu functions.
8718
8719 <!-- ----------------------------------------------------------------- -->
8720 <sect1>Using GtkItemFactory
8721 <p>
8722 Now that we've shown you the hard way, here's how you do it using the
8723 gtk_item_factory calls.
8724
8725 <!-- ----------------------------------------------------------------- -->
8726 <sect1>Item Factory Example
8727 <p>
8728 Here is an example using the GTK item factory.
8729
8730 <tscreen><verb>
8731 /* example-start menu itemfactory.c */
8732
8733 #include <gtk/gtk.h>
8734 #include <strings.h>
8735
8736 /* Obligatory basic callback */
8737 static void print_hello(GtkWidget *w, gpointer data) {
8738   g_message("Hello, World!\n");
8739 }
8740
8741 /* This is the GtkItemFactoryEntry structure used to generate new menus.
8742    Item 1: The menu path. The letter after the underscore indicates an
8743            accelerator key once the menu is open.
8744    Item 2: The accelerator key for the entry
8745    Item 3: The callback function.
8746    Item 4: The callback action.  This changes the parameters with
8747            which the function is called.  The default is 0.
8748    Item 5: The item type, used to define what kind of an item it is.
8749            Here are the possible values:
8750
8751            NULL               -> "<Item>"
8752            ""                 -> "<Item>"
8753            "<Title>"          -> create a title item
8754            "<Item>"           -> create a simple item
8755            "<CheckItem>"      -> create a check item
8756            "<ToggleItem>"     -> create a toggle item
8757            "<RadioItem>"      -> create a radio item
8758            <path>             -> path of a radio item to link against
8759            "<Separator>"      -> create a separator
8760            "<Branch>"         -> create an item to hold sub items
8761            "<LastBranch>"     -> create a right justified branch 
8762 */
8763
8764 static GtkItemFactoryEntry menu_items[] = {
8765   {"/_File",         NULL,         NULL, 0, "<Branch>"},
8766   {"/File/_New",     "<control>N", print_hello, 0, NULL},
8767   {"/File/_Open",    "<control>O", print_hello, 0, NULL},
8768   {"/File/_Save",    "<control>S", print_hello, 0, NULL},
8769   {"/File/Save _As", NULL,         NULL, 0, NULL},
8770   {"/File/sep1",     NULL,         NULL, 0, "<Separator>"},
8771   {"/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL},
8772   {"/_Options",      NULL,         NULL, 0, "<Branch>"},
8773   {"/Options/Test",  NULL,         NULL, 0, NULL},
8774   {"/_Help",         NULL,         NULL, 0, "<LastBranch>"},
8775   {"/_Help/About",   NULL,         NULL, 0, NULL},
8776 };
8777
8778
8779 void get_main_menu(GtkWidget *window, GtkWidget ** menubar) {
8780   int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
8781   GtkItemFactory *item_factory;
8782   GtkAccelGroup *accel_group;
8783
8784   accel_group = gtk_accel_group_new();
8785
8786   /* This function initializes the item factory.
8787      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
8788               or GTK_TYPE_OPTION_MENU.
8789      Param 2: The path of the menu.
8790      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
8791               the accelerator table while generating menus.
8792   */
8793
8794   item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", 
8795                                        accel_group);
8796
8797   /* This function generates the menu items. Pass the item factory,
8798      the number of items in the array, the array itself, and any
8799      callback data for the the menu items. */
8800   gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
8801
8802   /* Attach the new accelerator group to the window. */
8803   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
8804
8805   if (menubar)
8806     /* Finally, return the actual menu bar created by the item factory. */ 
8807     *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
8808 }
8809
8810 int main(int argc, char *argv[]) {
8811   GtkWidget *window;
8812   GtkWidget *main_vbox;
8813   GtkWidget *menubar;
8814   
8815   gtk_init(&amp;argc, &amp;argv);
8816   
8817   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
8818   gtk_signal_connect(GTK_OBJECT(window), "destroy", 
8819                      GTK_SIGNAL_FUNC(gtk_main_quit), 
8820                      "WM destroy");
8821   gtk_window_set_title(GTK_WINDOW(window), "Item Factory");
8822   gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);
8823   
8824   main_vbox = gtk_vbox_new(FALSE, 1);
8825   gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
8826   gtk_container_add(GTK_CONTAINER(window), main_vbox);
8827   gtk_widget_show(main_vbox);
8828   
8829   get_main_menu(window, &amp;menubar);
8830   gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
8831   gtk_widget_show(menubar);
8832   
8833   gtk_widget_show(window);
8834   gtk_main();
8835   
8836   return(0);
8837 }
8838 /* example-end */
8839 </verb></tscreen>
8840
8841
8842 For now, there's only this example.  An explanation and lots 'o' comments
8843 will follow later.
8844
8845 <!-- ***************************************************************** -->
8846 <sect> Text Widget
8847 <!-- ***************************************************************** -->
8848 <p>
8849 The Text widget allows multiple lines of text to be displayed and
8850 edited.  It supports both multi-colored and multi-font text, allowing
8851 them to be mixed in any way we wish. It also has a wide set of key
8852 based text editing commands, which are compatible with Emacs.
8853
8854 The text widget supports full cut-and-paste facilities, including the
8855 use of double- and triple-click to select a word and a whole line,
8856 respectively.
8857
8858 <!-- ----------------------------------------------------------------- -->
8859 <sect1>Creating and Configuring a Text box
8860 <p>
8861 There is only one function for creating a new Text widget.
8862
8863 <tscreen><verb>
8864 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
8865                          GtkAdjustment *vadj );
8866 </verb></tscreen>
8867
8868 The arguments allow us to give the Text widget pointers to Adjustments
8869 that can be used to track the viewing position of the widget. Passing
8870 NULL values to either or both of these arguments will cause the
8871 gtk_text_new function to create its own.
8872
8873 <tscreen><verb>
8874 void gtk_text_set_adjustments( GtkText       *text,
8875                                GtkAdjustment *hadj,
8876                                GtkAdjustment *vadj );
8877 </verb></tscreen>
8878
8879 The above function allows the horizontal and vertical adjustments of a
8880 text widget to be changed at any time.
8881
8882 The text widget will not automatically create its own scrollbars when
8883 the amount of text to be displayed is too long for the display
8884 window. We therefore have to create and add them to the display layout
8885 ourselves.
8886
8887 <tscreen><verb>
8888   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
8889   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
8890   gtk_widget_show (vscrollbar);
8891 </verb></tscreen>
8892
8893 The above code snippet creates a new vertical scrollbar, and attaches
8894 it to the vertical adjustment of the text widget, <tt/text/. It then
8895 packs it into a box in the normal way.
8896
8897 Note, currently the GtkText widget does not support horizontal
8898 scrollbars.
8899
8900 There are two main ways in which a Text widget can be used: to allow
8901 the user to edit a body of text, or to allow us to display multiple
8902 lines of text to the user. In order for us to switch between these
8903 modes of operation, the text widget has the following function:
8904
8905 <tscreen><verb>
8906 void gtk_text_set_editable( GtkText *text,
8907                             gint     editable );
8908 </verb></tscreen>
8909
8910 The <tt/editable/ argument is a TRUE or FALSE value that specifies
8911 whether the user is permitted to edit the contents of the Text
8912 widget. When the text widget is editable, it will display a cursor at
8913 the current insertion point.
8914
8915 You are not, however, restricted to just using the text widget in
8916 these two modes. You can toggle the editable state of the text widget
8917 at any time, and can insert text at any time.
8918
8919 The text widget wraps lines of text that are too long to fit onto a
8920 single line of the display window. Its default behaviour is to break
8921 words across line breaks. This can be changed using the next function:
8922
8923 <tscreen><verb>
8924 void gtk_text_set_word_wrap( GtkText *text,
8925                              gint     word_wrap );
8926 </verb></tscreen>
8927
8928 Using this function allows us to specify that the text widget should
8929 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
8930 TRUE or FALSE value.
8931
8932 <!-- ----------------------------------------------------------------- -->
8933 <sect1>Text Manipulation
8934 <P>
8935 The current insertion point of a Text widget can be set using
8936 <tscreen><verb>
8937 void gtk_text_set_point( GtkText *text,
8938                          guint    index );
8939 </verb></tscreen>
8940
8941 where <tt/index/ is the position to set the insertion point.
8942
8943 Analogous to this is the function for getting the current insertion
8944 point:
8945
8946 <tscreen><verb>
8947 guint gtk_text_get_point( GtkText *text );
8948 </verb></tscreen>
8949
8950 A function that is useful in combination with the above two functions
8951 is
8952
8953 <tscreen><verb>
8954 guint gtk_text_get_length( GtkText *text );
8955 </verb></tscreen>
8956
8957 which returns the current length of the Text widget. The length is the
8958 number of characters that are within the text block of the widget,
8959 including characters such as carriage-return, which marks the end of
8960 lines.
8961
8962 In order to insert text at the current insertion point of a Text
8963 widget, the function gtk_text_insert is used, which also allows us to
8964 specify background and foreground colors and a font for the text.
8965
8966 <tscreen><verb>
8967 void gtk_text_insert( GtkText    *text,
8968                       GdkFont    *font,
8969                       GdkColor   *fore,
8970                       GdkColor   *back,
8971                       const char *chars,
8972                       gint        length );
8973 </verb></tscreen>
8974
8975 Passing a value of <tt/NULL/ in as the value for the foreground color,
8976 background colour or font will result in the values set within the
8977 widget style to be used. Using a value of <tt/-1/ for the length
8978 parameter will result in the whole of the text string given being
8979 inserted.
8980
8981 The text widget is one of the few within GTK that redraws itself
8982 dynamically, outside of the gtk_main function. This means that all
8983 changes to the contents of the text widget take effect
8984 immediately. This may be undesirable when performing multiple changes
8985 to the text widget. In order to allow us to perform multiple updates
8986 to the text widget without it continuously redrawing, we can freeze
8987 the widget, which temporarily stops it from automatically redrawing
8988 itself every time it is changed. We can then thaw the widget after our
8989 updates are complete.
8990
8991 The following two functions perform this freeze and thaw action:
8992
8993 <tscreen><verb>
8994 void gtk_text_freeze( GtkText *text );
8995
8996 void gtk_text_thaw( GtkText *text );         
8997 </verb></tscreen>
8998
8999 Text is deleted from the text widget relative to the current insertion
9000 point by the following two functions. The return value is a TRUE or
9001 FALSE indicator of whether the operation was successful.
9002
9003 <tscreen><verb>
9004 gint gtk_text_backward_delete( GtkText *text,
9005                                guint    nchars );
9006
9007 gint gtk_text_forward_delete ( GtkText *text,
9008                                guint    nchars );
9009 </verb></tscreen>
9010
9011 If you want to retrieve the contents of the text widget, then the
9012 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
9013 character at position <tt/index/ within the text widget <tt/t/.
9014
9015 To retrieve larger blocks of text, we can use the function
9016
9017 <tscreen><verb>
9018 gchar *gtk_editable_get_chars( GtkEditable *editable,
9019                                gint         start_pos,
9020                                gint         end_pos );   
9021 </verb></tscreen>
9022
9023 This is a function of the parent class of the text widget. A value of
9024 -1 as <tt/end_pos/ signifies the end of the text. The index of the
9025 text starts at 0.
9026
9027 The function allocates a new chunk of memory for the text block, so
9028 don't forget to free it with a call to g_free when you have finished
9029 with it.
9030  
9031 <!-- ----------------------------------------------------------------- -->
9032 <sect1>Keyboard Shortcuts
9033 <p>
9034 The text widget has a number of pre-installed keyboard shortcuts for
9035 common editing, motion and selection functions. These are accessed
9036 using Control and Alt key combinations.
9037
9038 In addition to these, holding down the Control key whilst using cursor
9039 key movement will move the cursor by words rather than
9040 characters. Holding down Shift whilst using cursor movement will
9041 extend the selection.
9042
9043 <sect2>Motion Shortcuts
9044 <p>
9045 <itemize>
9046 <item> Ctrl-A   Beginning of line
9047 <item> Ctrl-E   End of line
9048 <item> Ctrl-N   Next Line
9049 <item> Ctrl-P   Previous Line
9050 <item> Ctrl-B   Backward one character
9051 <item> Ctrl-F   Forward one character
9052 <item> Alt-B    Backward one word
9053 <item> Alt-F    Forward one word
9054 </itemize>
9055
9056 <sect2>Editing Shortcuts
9057 <p>
9058 <itemize>
9059 <item> Ctrl-H   Delete Backward Character (Backspace)
9060 <item> Ctrl-D   Delete Forward Character (Delete)
9061 <item> Ctrl-W   Delete Backward Word
9062 <item> Alt-D    Delete Forward Word
9063 <item> Ctrl-K   Delete to end of line
9064 <item> Ctrl-U   Delete line
9065 </itemize>
9066
9067 <sect2>Selection Shortcuts
9068 <p>
9069 <itemize>
9070 <item> Ctrl-X   Cut to clipboard
9071 <item> Ctrl-C   Copy to clipboard
9072 <item> Ctrl-V   Paste from clipboard
9073 </itemize>
9074
9075 <!-- ----------------------------------------------------------------- -->
9076 <sect1>A GtkText Example
9077 <p>
9078 <tscreen><verb>
9079 /* example-start text text.c */
9080
9081 /* text.c */
9082
9083 #include <stdio.h>
9084 #include <gtk/gtk.h>
9085
9086 void text_toggle_editable (GtkWidget *checkbutton,
9087                            GtkWidget *text)
9088 {
9089   gtk_text_set_editable(GTK_TEXT(text),
9090                         GTK_TOGGLE_BUTTON(checkbutton)->active);
9091 }
9092
9093 void text_toggle_word_wrap (GtkWidget *checkbutton,
9094                             GtkWidget *text)
9095 {
9096   gtk_text_set_word_wrap(GTK_TEXT(text),
9097                          GTK_TOGGLE_BUTTON(checkbutton)->active);
9098 }
9099
9100 void close_application( GtkWidget *widget, gpointer data )
9101 {
9102        gtk_main_quit();
9103 }
9104
9105 int main (int argc, char *argv[])
9106 {
9107   GtkWidget *window;
9108   GtkWidget *box1;
9109   GtkWidget *box2;
9110   GtkWidget *hbox;
9111   GtkWidget *button;
9112   GtkWidget *check;
9113   GtkWidget *separator;
9114   GtkWidget *table;
9115   GtkWidget *vscrollbar;
9116   GtkWidget *text;
9117   GdkColormap *cmap;
9118   GdkColor colour;
9119   GdkFont *fixed_font;
9120
9121   FILE *infile;
9122
9123   gtk_init (&amp;argc, &amp;argv);
9124  
9125   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9126   gtk_widget_set_usize (window, 600, 500);
9127   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
9128   gtk_signal_connect (GTK_OBJECT (window), "destroy",
9129                       GTK_SIGNAL_FUNC(close_application),
9130                       NULL);
9131   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
9132   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9133   
9134   
9135   box1 = gtk_vbox_new (FALSE, 0);
9136   gtk_container_add (GTK_CONTAINER (window), box1);
9137   gtk_widget_show (box1);
9138   
9139   
9140   box2 = gtk_vbox_new (FALSE, 10);
9141   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9142   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9143   gtk_widget_show (box2);
9144   
9145   
9146   table = gtk_table_new (2, 2, FALSE);
9147   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
9148   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
9149   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
9150   gtk_widget_show (table);
9151   
9152   /* Create the GtkText widget */
9153   text = gtk_text_new (NULL, NULL);
9154   gtk_text_set_editable (GTK_TEXT (text), TRUE);
9155   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
9156                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
9157                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
9158   gtk_widget_show (text);
9159
9160   /* Add a vertical scrollbar to the GtkText widget */
9161   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
9162   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
9163                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
9164   gtk_widget_show (vscrollbar);
9165
9166   /* Get the system colour map and allocate the colour red */
9167   cmap = gdk_colormap_get_system();
9168   colour.red = 0xffff;
9169   colour.green = 0;
9170   colour.blue = 0;
9171   if (!gdk_color_alloc(cmap, &amp;colour)) {
9172     g_error("couldn't allocate colour");
9173   }
9174
9175   /* Load a fixed font */
9176   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
9177
9178   /* Realizing a widget creates a window for it, ready for us to insert some text */
9179   gtk_widget_realize (text);
9180
9181   /* Freeze the text widget, ready for multiple updates */
9182   gtk_text_freeze (GTK_TEXT (text));
9183   
9184   /* Insert some coloured text */
9185   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9186                    "Supports ", -1);
9187   gtk_text_insert (GTK_TEXT (text), NULL, &amp;colour, NULL,
9188                    "colored ", -1);
9189   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9190                    "text and different ", -1);
9191   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
9192                    "fonts\n\n", -1);
9193   
9194   /* Load the file text.c into the text window */
9195
9196   infile = fopen("text.c", "r");
9197   
9198   if (infile) {
9199     char buffer[1024];
9200     int nchars;
9201     
9202     while (1)
9203       {
9204         nchars = fread(buffer, 1, 1024, infile);
9205         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
9206                          NULL, buffer, nchars);
9207         
9208         if (nchars < 1024)
9209           break;
9210       }
9211     
9212     fclose (infile);
9213   }
9214
9215   /* Thaw the text widget, allowing the updates to become visible */  
9216   gtk_text_thaw (GTK_TEXT (text));
9217   
9218   hbox = gtk_hbutton_box_new ();
9219   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9220   gtk_widget_show (hbox);
9221
9222   check = gtk_check_button_new_with_label("Editable");
9223   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9224   gtk_signal_connect (GTK_OBJECT(check), "toggled",
9225                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
9226   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9227   gtk_widget_show (check);
9228   check = gtk_check_button_new_with_label("Wrap Words");
9229   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9230   gtk_signal_connect (GTK_OBJECT(check), "toggled",
9231                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
9232   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9233   gtk_widget_show (check);
9234
9235   separator = gtk_hseparator_new ();
9236   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9237   gtk_widget_show (separator);
9238
9239   box2 = gtk_vbox_new (FALSE, 10);
9240   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9241   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9242   gtk_widget_show (box2);
9243   
9244   button = gtk_button_new_with_label ("close");
9245   gtk_signal_connect (GTK_OBJECT (button), "clicked",
9246                       GTK_SIGNAL_FUNC(close_application),
9247                       NULL);
9248   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9249   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9250   gtk_widget_grab_default (button);
9251   gtk_widget_show (button);
9252
9253   gtk_widget_show (window);
9254
9255   gtk_main ();
9256   
9257   return(0);       
9258 }
9259 /* example-end */
9260 </verb></tscreen>
9261
9262
9263 <!-- ***************************************************************** -->
9264 <sect> Undocumented Widgets
9265 <!-- ***************************************************************** -->
9266 <p>
9267 These all require authors! :) Please consider contributing to our
9268 tutorial.
9269
9270 If you must use one of these widgets that are undocumented, I strongly
9271 suggest you take a look at their respective header files in the GTK
9272 distribution. GTK's function names are very descriptive. Once you
9273 have an understanding of how things work, it's not difficult to figure
9274 out how to use a widget simply by looking at its function
9275 declarations. This, along with a few examples from others' code, and
9276 it should be no problem.
9277
9278 When you do come to understand all the functions of a new undocumented
9279 widget, please consider writing a tutorial on it so others may benefit
9280 from your time.
9281
9282 <!-- ----------------------------------------------------------------- -->
9283 <sect1> Calendar
9284 <p>
9285 <!-- ----------------------------------------------------------------- -->
9286 <sect1> Combo box
9287 <p>
9288 <!-- ----------------------------------------------------------------- -->
9289 <sect1> CTree
9290 <p>
9291 <!-- ----------------------------------------------------------------- -->
9292 <sect1> Curves
9293 <p>
9294 <!-- ----------------------------------------------------------------- -->
9295 <sect1> Drawing Area
9296 <p>
9297 <!-- ----------------------------------------------------------------- -->
9298 <sect1> Font Selection Dialog
9299 <p>
9300 <!-- ----------------------------------------------------------------- -->
9301 <sect1> Gamma Curve
9302 <p>
9303 <!-- ----------------------------------------------------------------- -->
9304 <sect1> Image
9305 <p>
9306 <!-- ----------------------------------------------------------------- -->
9307 <sect1> Layout
9308 <p>
9309 <!-- ----------------------------------------------------------------- -->
9310 <sect1> Packer
9311 <p>
9312 <!-- ----------------------------------------------------------------- -->
9313 <sect1> Plugs and Sockets
9314 <p>
9315 <!-- ----------------------------------------------------------------- -->
9316 <sect1> Preview
9317 <p>
9318 <!-- ----------------------------------------------------------------- -->
9319 <sect1> Spin Button
9320 <p>
9321
9322 <!--
9323
9324 (This may need to be rewritten to follow the style of the rest of the tutorial)
9325
9326 <tscreen><verb>
9327
9328 Previews serve a number of purposes in GIMP/GTK. The most important one is
9329 this. High quality images may take up to tens of megabytes of memory - easy!
9330 Any operation on an image that big is bound to take a long time. If it takes
9331 you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after
9332 you make an error) to choose the desired modification, it make take you
9333 literally hours to make the right one - if you don't run out of memory
9334 first. People who have spent hours in color darkrooms know the feeling.
9335 Previews to the rescue!
9336
9337 But the annoyance of the delay is not the only issue. Oftentimes it is
9338 helpful to compare the Before and After versions side-by-side or at least
9339 back-to-back. If you're working with big images and 10 second delays,
9340 obtaining the Before and After impressions is, to say the least, difficult.
9341 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
9342 out for most people, while back-to-back is more like back-to-1001, 1002,
9343 ..., 1010-back! Previews to the rescue!
9344
9345 But there's more. Previews allow for side-by-side pre-previews. In other
9346 words, you write a plug-in (e.g. the filterpack simulation) which would have
9347 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
9348 An approach like this acts as a sort of a preview palette and is very
9349 effective for subtle changes. Let's go previews!
9350
9351 There's more. For certain plug-ins real-time image-specific human
9352 intervention maybe necessary. In the SuperNova plug-in, for example, the
9353 user is asked to enter the coordinates of the center of the future
9354 supernova. The easiest way to do this, really, is to present the user with a
9355 preview and ask him to interactively select the spot. Let's go previews!
9356
9357 Finally, a couple of misc uses. One can use previews even when not working
9358 with big images. For example, they are useful when rendering complicated
9359 patterns. (Just check out the venerable Diffraction plug-in + many other
9360 ones!) As another example, take a look at the colormap rotation plug-in
9361 (work in progress). You can also use previews for little logos inside you
9362 plug-ins and even for an image of yourself, The Author. Let's go previews!
9363
9364 When Not to Use Previews
9365
9366 Don't use previews for graphs, drawing etc. GDK is much faster for that. Use
9367 previews only for rendered images!
9368
9369 Let's go previews!
9370
9371 You can stick a preview into just about anything. In a vbox, an hbox, a
9372 table, a button, etc. But they look their best in tight frames around them.
9373 Previews by themselves do not have borders and look flat without them. (Of
9374 course, if the flat look is what you want...) Tight frames provide the
9375 necessary borders.
9376
9377                                [Image][Image]
9378
9379 Previews in many ways are like any other widgets in GTK (whatever that
9380 means) except they possess an additional feature: they need to be filled with
9381 some sort of an image! First, we will deal exclusively with the GTK aspect
9382 of previews and then we'll discuss how to fill them.
9383
9384 GtkWidget *preview!
9385
9386 Without any ado:
9387
9388                               /* Create a preview widget,
9389                               set its size, an show it */
9390 GtkWidget *preview;
9391 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
9392                               /*Other option:
9393                               GTK_PREVIEW_GRAYSCALE);*/
9394 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
9395 gtk_widget_show(preview);
9396 my_preview_rendering_function(preview);
9397
9398 Oh yeah, like I said, previews look good inside frames, so how about:
9399
9400 GtkWidget *create_a_preview(int        Width,
9401                             int        Height,
9402                             int        Colorfulness)
9403 {
9404   GtkWidget *preview;
9405   GtkWidget *frame;
9406   
9407   frame = gtk_frame_new(NULL);
9408   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
9409   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
9410   gtk_widget_show(frame);
9411
9412   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
9413                                        :GTK_PREVIEW_GRAYSCALE);
9414   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
9415   gtk_container_add(GTK_CONTAINER(frame),preview);
9416   gtk_widget_show(preview);
9417
9418   my_preview_rendering_function(preview);
9419   return frame;
9420 }
9421
9422 That's my basic preview. This routine returns the "parent" frame so you can
9423 place it somewhere else in your interface. Of course, you can pass the
9424 parent frame to this routine as a parameter. In many situations, however,
9425 the contents of the preview are changed continually by your application. In
9426 this case you may want to pass a pointer to the preview to a
9427 "create_a_preview()" and thus have control of it later.
9428
9429 One more important note that may one day save you a lot of time. Sometimes
9430 it is desirable to label you preview. For example, you may label the preview
9431 containing the original image as "Original" and the one containing the
9432 modified image as "Less Original". It might occur to you to pack the
9433 preview along with the appropriate label into a vbox. The unexpected caveat
9434 is that if the label is wider than the preview (which may happen for a
9435 variety of reasons unforseeable to you, from the dynamic decision on the
9436 size of the preview to the size of the font) the frame expands and no longer
9437 fits tightly over the preview. The same problem can probably arise in other
9438 situations as well.
9439
9440                                    [Image]
9441
9442 The solution is to place the preview and the label into a 2x1 table and by
9443 attaching them with the following parameters (this is one possible variations
9444 of course. The key is no GTK_FILL in the second attachment):
9445
9446 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
9447                  0,
9448                  GTK_EXPAND|GTK_FILL,
9449                  0,0);
9450 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
9451                  GTK_EXPAND,
9452                  GTK_EXPAND,
9453                  0,0);
9454
9455
9456 And here's the result:
9457
9458                                    [Image]
9459
9460 Misc
9461
9462 Making a preview clickable is achieved most easily by placing it in a
9463 button. It also adds a nice border around the preview and you may not even
9464 need to place it in a frame. See the Filter Pack Simulation plug-in for an
9465 example.
9466
9467 This is pretty much it as far as GTK is concerned.
9468
9469 Filling In a Preview
9470
9471 In order to familiarize ourselves with the basics of filling in previews,
9472 let's create the following pattern (contrived by trial and error):
9473
9474                                    [Image]
9475
9476 void
9477 my_preview_rendering_function(GtkWidget     *preview)
9478 {
9479 #define SIZE 100
9480 #define HALF (SIZE/2)
9481
9482   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
9483   gint i, j;                             /* Coordinates    */
9484   double r, alpha, x, y;
9485
9486   if (preview==NULL) return; /* I usually add this when I want */
9487                              /* to avoid silly crashes. You    */
9488                              /* should probably make sure that */
9489                              /* everything has been nicely     */
9490                              /* initialized!                   */
9491   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
9492                                          /* glib.h contains ABS(x).   */
9493         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
9494         row[i*3+1] = 128;                /* Define Green              */
9495         row[i*3+2] = 224;                /* Define Blue               */
9496       }                                  /* "+0" is for alignment!    */
9497       else {
9498         row[i*3+0] = r*255;
9499         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
9500         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
9501       }
9502     }
9503     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
9504     /* Insert "row" into "preview" starting at the point with  */
9505     /* coordinates (0,j) first column, j_th row extending SIZE */
9506     /* pixels to the right */
9507   }
9508
9509   free(row); /* save some space */
9510   gtk_widget_draw(preview,NULL); /* what does this do? */
9511   gdk_flush(); /* or this? */
9512 }
9513
9514 Non-GIMP users can have probably seen enough to do a lot of things already.
9515 For the GIMP users I have a few pointers to add.
9516
9517 Image Preview
9518
9519 It is probably wise to keep a reduced version of the image around with just
9520 enough pixels to fill the preview. This is done by selecting every n'th
9521 pixel where n is the ratio of the size of the image to the size of the
9522 preview. All further operations (including filling in the previews) are then
9523 performed on the reduced number of pixels only. The following is my
9524 implementation of reducing the image. (Keep in mind that I've had only basic
9525 C!)
9526
9527 (UNTESTED CODE ALERT!!!)
9528
9529 typedef struct {
9530   gint      width;
9531   gint      height;
9532   gint      bbp;
9533   guchar    *rgb;
9534   guchar    *mask;
9535 } ReducedImage;
9536
9537 enum {
9538   SELECTION_ONLY,
9539   SELECTION_IN_CONTEXT,
9540   ENTIRE_IMAGE
9541 };
9542
9543 ReducedImage *Reduce_The_Image(GDrawable *drawable,
9544                                GDrawable *mask,
9545                                gint LongerSize,
9546                                gint Selection)
9547 {
9548   /* This function reduced the image down to the the selected preview size */
9549   /* The preview size is determine by LongerSize, i.e. the greater of the  */
9550   /* two dimensions. Works for RGB images only!                            */
9551   gint RH, RW;          /* Reduced height and reduced width                */
9552   gint width, height;   /* Width and Height of the area being reduced      */
9553   gint bytes=drawable->bpp;
9554   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
9555
9556   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
9557   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
9558   GPixelRgn srcPR, srcMask;
9559   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
9560                              /* image.                                     */
9561
9562   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
9563   width  = x2-x1;
9564   height = y2-y1;
9565   /* If there's a SELECTION, we got its bounds!)
9566
9567   if (width != drawable->width &amp;&amp; height != drawable->height)
9568     NoSelectionMade=FALSE;
9569   /* Become aware of whether the user has made an active selection   */
9570   /* This will become important later, when creating a reduced mask. */
9571
9572   /* If we want to preview the entire image, overrule the above!  */
9573   /* Of course, if no selection has been made, this does nothing! */
9574   if (Selection==ENTIRE_IMAGE) {
9575     x1=0;
9576     x2=drawable->width;
9577     y1=0;
9578     y2=drawable->height;
9579   }
9580
9581   /* If we want to preview a selection with some surrounding area we */
9582   /* have to expand it a little bit. Consider it a bit of a riddle. */
9583   if (Selection==SELECTION_IN_CONTEXT) {
9584     x1=MAX(0,                x1-width/2.0);
9585     x2=MIN(drawable->width,  x2+width/2.0);
9586     y1=MAX(0,                y1-height/2.0);
9587     y2=MIN(drawable->height, y2+height/2.0);
9588   }
9589
9590   /* How we can determine the width and the height of the area being */
9591   /* reduced.                                                        */
9592   width  = x2-x1;
9593   height = y2-y1;
9594
9595   /* The lines below determine which dimension is to be the longer   */
9596   /* side. The idea borrowed from the supernova plug-in. I suspect I */
9597   /* could've thought of it myself, but the truth must be told.      */
9598   /* Plagiarism stinks!                                               */
9599   if (width>height) {
9600     RW=LongerSize;
9601     RH=(float) height * (float) LongerSize/ (float) width;
9602   }
9603   else {
9604     RH=LongerSize;
9605     RW=(float)width * (float) LongerSize/ (float) height;
9606   }
9607
9608   /* The entire image is stretched into a string! */
9609   tempRGB   = (guchar *) malloc(RW*RH*bytes);
9610   tempmask  = (guchar *) malloc(RW*RH);
9611
9612   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height, FALSE, FALSE);
9613   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height, FALSE, FALSE);
9614
9615   /* Grab enough to save a row of image and a row of mask. */
9616   src_row       = (guchar *) malloc (width*bytes);
9617   src_mask_row  = (guchar *) malloc (width);
9618
9619   for (i=0; i < RH; i++) {
9620     whichrow=(float)i*(float)height/(float)RH;
9621     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
9622     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
9623
9624     for (j=0; j < RW; j++) {
9625       whichcol=(float)j*(float)width/(float)RW;
9626
9627       /* No selection made = each point is completely selected! */
9628       if (NoSelectionMade)
9629         tempmask[i*RW+j]=255;
9630       else
9631         tempmask[i*RW+j]=src_mask_row[whichcol];
9632
9633       /* Add the row to the one long string which now contains the image! */
9634       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
9635       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
9636       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
9637
9638       /* Hold on to the alpha as well */
9639       if (bytes==4)
9640         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
9641     }
9642   }
9643   temp->bpp=bytes;
9644   temp->width=RW;
9645   temp->height=RH;
9646   temp->rgb=tempRGB;
9647   temp->mask=tempmask;
9648   return temp;
9649 }
9650
9651 The following is a preview function which used the same ReducedImage type!
9652 Note that it uses fakes transparency (if one is present by means of
9653 fake_transparency which is defined as follows:
9654
9655 gint fake_transparency(gint i, gint j)
9656 {
9657   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
9658     return 64;
9659   else
9660     return 196;
9661 }
9662
9663 Now here's the preview function:
9664
9665 void
9666 my_preview_render_function(GtkWidget     *preview,
9667                            gint          changewhat,
9668                            gint          changewhich)
9669 {
9670   gint Inten, bytes=drawable->bpp;
9671   gint i, j, k;
9672   float partial;
9673   gint RW=reduced->width;
9674   gint RH=reduced->height;
9675   guchar *row=malloc(bytes*RW);;
9676
9677
9678   for (i=0; i < RH; i++) {
9679     for (j=0; j < RW; j++) {
9680
9681       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
9682       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
9683       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
9684
9685       if (bytes==4)
9686         for (k=0; k<3; k++) {
9687           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
9688           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
9689         }
9690     }
9691     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
9692   }
9693
9694   free(a);
9695   gtk_widget_draw(preview,NULL);
9696   gdk_flush();
9697 }
9698
9699 Applicable Routines
9700
9701 guint           gtk_preview_get_type           (void);
9702 /* No idea */
9703 void            gtk_preview_uninit             (void);
9704 /* No idea */
9705 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
9706 /* Described above */
9707 void            gtk_preview_size               (GtkPreview      *preview,
9708                                                 gint             width,
9709                                                 gint             height);
9710 /* Allows you to resize an existing preview.    */
9711 /* Apparently there's a bug in GTK which makes  */
9712 /* this process messy. A way to clean up a mess */
9713 /* is to manually resize the window containing  */
9714 /* the preview after resizing the preview.      */
9715
9716 void            gtk_preview_put                (GtkPreview      *preview,
9717                                                 GdkWindow       *window,
9718                                                 GdkGC           *gc,
9719                                                 gint             srcx,
9720                                                 gint             srcy,
9721                                                 gint             destx,
9722                                                 gint             desty,
9723                                                 gint             width,
9724                                                 gint             height);
9725 /* No idea */
9726
9727 void            gtk_preview_put_row            (GtkPreview      *preview,
9728                                                 guchar          *src,
9729                                                 guchar          *dest,
9730                                                 gint             x,
9731                                                 gint             y,
9732                                                 gint             w);
9733 /* No idea */
9734
9735 void            gtk_preview_draw_row           (GtkPreview      *preview,
9736                                                 guchar          *data,
9737                                                 gint             x,
9738                                                 gint             y,
9739                                                 gint             w);
9740 /* Described in the text */
9741
9742 void            gtk_preview_set_expand         (GtkPreview      *preview,
9743                                                 gint             expand);
9744 /* No idea */
9745
9746 /* No clue for any of the below but    */
9747 /* should be standard for most widgets */
9748 void            gtk_preview_set_gamma          (double           gamma);
9749 void            gtk_preview_set_color_cube     (guint            nred_shades,
9750                                                 guint            ngreen_shades,
9751                                                 guint            nblue_shades,
9752                                                 guint            ngray_shades);
9753 void            gtk_preview_set_install_cmap   (gint             install_cmap);
9754 void            gtk_preview_set_reserved       (gint             nreserved);
9755 GdkVisual*      gtk_preview_get_visual         (void);
9756 GdkColormap*    gtk_preview_get_cmap           (void);
9757 GtkPreviewInfo* gtk_preview_get_info           (void);
9758
9759 That's all, folks!
9760
9761 </verb></tscreen>
9762
9763 -->
9764
9765 <!-- ***************************************************************** -->
9766 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
9767 <!-- ***************************************************************** -->
9768 <p>
9769 This describes the functions used to operate on widgets.  These can be
9770 used to set style, padding, size etc.
9771
9772 (Maybe I should make a whole section on accelerators.)
9773
9774 <tscreen><verb>
9775 void gtk_widget_install_accelerator( GtkWidget           *widget,
9776                                      GtkAcceleratorTable *table,
9777                                      gchar               *signal_name,
9778                                      gchar                key,
9779                                      guint8               modifiers );
9780
9781 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
9782                                      GtkAcceleratorTable *table,
9783                                      gchar               *signal_name);
9784
9785 void gtk_widget_activate( GtkWidget *widget );
9786
9787 void gtk_widget_set_name( GtkWidget *widget,
9788                           gchar     *name );
9789
9790 gchar *gtk_widget_get_name( GtkWidget *widget );
9791
9792 void gtk_widget_set_sensitive( GtkWidget *widget,
9793                                gint       sensitive );
9794
9795 void gtk_widget_set_style( GtkWidget *widget,
9796                            GtkStyle  *style );
9797                                            
9798 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
9799
9800 GtkStyle *gtk_widget_get_default_style( void );
9801
9802 void gtk_widget_set_uposition( GtkWidget *widget,
9803                                gint       x,
9804                                gint       y );
9805
9806 void gtk_widget_set_usize( GtkWidget *widget,
9807                            gint       width,
9808                            gint       height );
9809
9810 void gtk_widget_grab_focus( GtkWidget *widget );
9811
9812 void gtk_widget_show( GtkWidget *widget );
9813
9814 void gtk_widget_hide( GtkWidget *widget );
9815 </verb></tscreen>
9816
9817 <!-- ***************************************************************** -->
9818 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
9819 <!-- ***************************************************************** -->
9820
9821 <!-- ----------------------------------------------------------------- -->
9822 <sect1>Timeouts
9823 <p>
9824 You may be wondering how you make GTK do useful work when in gtk_main.
9825 Well, you have several options. Using the following functions you can
9826 create a timeout function that will be called every "interval"
9827 milliseconds.
9828
9829 <tscreen><verb>
9830 gint gtk_timeout_add( guint32     interval,
9831                       GtkFunction function,
9832                       gpointer    data );
9833 </verb></tscreen>
9834
9835 The first argument is the number of milliseconds between calls to your
9836 function. The second argument is the function you wish to have called,
9837 and the third, the data passed to this callback function. The return
9838 value is an integer "tag" which may be used to stop the timeout by
9839 calling:
9840
9841 <tscreen><verb>
9842 void gtk_timeout_remove( gint tag );
9843 </verb></tscreen>
9844
9845 You may also stop the timeout function by returning zero or FALSE from
9846 your callback function. Obviously this means if you want your function
9847 to continue to be called, it should return a non-zero value,
9848 i.e. TRUE.
9849
9850 The declaration of your callback should look something like this:
9851
9852 <tscreen><verb>
9853 gint timeout_callback( gpointer data );
9854 </verb></tscreen>
9855
9856 <!-- ----------------------------------------------------------------- -->
9857 <sect1>Monitoring IO
9858 <p>
9859 A nifty feature of GDK (the library that underlies GTK), is the
9860 ability to have it check for data on a file descriptor for you (as
9861 returned by open(2) or socket(2)). This is especially useful for
9862 networking applications. The function:
9863
9864 <tscreen><verb>
9865 gint gdk_input_add( gint              source,
9866                     GdkInputCondition condition,
9867                     GdkInputFunction  function,
9868                     gpointer          data );
9869 </verb></tscreen>
9870
9871 Where the first argument is the file descriptor you wish to have
9872 watched, and the second specifies what you want GDK to look for. This
9873 may be one of:
9874
9875 <itemize>
9876 <item>GDK_INPUT_READ - Call your function when there is data ready for
9877 reading on your file descriptor.
9878
9879 <item>GDK_INPUT_WRITE - Call your function when the file descriptor is
9880 ready for writing.
9881 </itemize>
9882
9883 As I'm sure you've figured out already, the third argument is the
9884 function you wish to have called when the above conditions are
9885 satisfied, and the fourth is the data to pass to this function.
9886
9887 The return value is a tag that may be used to stop GDK from monitoring
9888 this file descriptor using the following function.
9889
9890 <tscreen><verb>
9891 void gdk_input_remove( gint tag );
9892 </verb></tscreen>
9893
9894 The callback function should be declared as:
9895
9896 <tscreen><verb>
9897 void input_callback( gpointer          data,
9898                      gint              source, 
9899                      GdkInputCondition condition );
9900 </verb></tscreen>
9901
9902 Where <tt/source/ and <tt/condition/ are as specified above.
9903
9904 <!-- ----------------------------------------------------------------- -->
9905 <sect1>Idle Functions
9906 <p>
9907 <!-- TODO: Need to check on idle priorities - TRG -->
9908 What if you have a function you want called when nothing else is
9909 happening ?
9910
9911 <tscreen><verb>
9912 gint gtk_idle_add( GtkFunction function,
9913                    gpointer    data );
9914 </verb></tscreen>
9915
9916 This causes GTK to call the specified function whenever nothing else
9917 is happening.
9918
9919 <tscreen><verb>
9920 void gtk_idle_remove( gint tag );
9921 </verb></tscreen>
9922
9923 I won't explain the meaning of the arguments as they follow very much
9924 like the ones above. The function pointed to by the first argument to
9925 gtk_idle_add will be called whenever the opportunity arises. As with
9926 the others, returning FALSE will stop the idle function from being
9927 called.
9928
9929 <!-- ***************************************************************** -->
9930 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
9931 <!-- ***************************************************************** -->
9932
9933 <!-- ----------------------------------------------------------------- -->
9934 <sect1>Signal Functions
9935
9936 <!-- ----------------------------------------------------------------- -->
9937 <sect2>Connecting and Disconnecting Signal Handlers
9938 <p>
9939
9940 <tscreen><verb>
9941 guint gtk_signal_connect( GtkObject     *object,
9942                           const gchar   *name,
9943                           GtkSignalFunc  func,
9944                           gpointer       func_data );
9945
9946 guint gtk_signal_connect_after( GtkObject     *object,
9947                                 const gchar   *name,
9948                                 GtkSignalFunc  func,
9949                                 gpointer       func_data );
9950
9951 guint gtk_signal_connect_object( GtkObject     *object,
9952                                  const gchar   *name,
9953                                  GtkSignalFunc  func,
9954                                  GtkObject     *slot_object );
9955
9956 guint gtk_signal_connect_object_after( GtkObject     *object,
9957                                        const gchar   *name,
9958                                        GtkSignalFunc  func,
9959                                        GtkObject     *slot_object );
9960
9961 guint gtk_signal_connect_full( GtkObject          *object,
9962                                const gchar        *name,
9963                                GtkSignalFunc       func,
9964                                GtkCallbackMarshal  marshal,
9965                                gpointer            data,
9966                                GtkDestroyNotify    destroy_func,
9967                                gint                object_signal,
9968                                gint                after );
9969
9970 guint gtk_signal_connect_interp( GtkObject          *object,
9971                                  const gchar        *name,
9972                                  GtkCallbackMarshal  func,
9973                                  gpointer            data,
9974                                  GtkDestroyNotify    destroy_func,
9975                                  gint                after );
9976
9977 void gtk_signal_connect_object_while_alive( GtkObject     *object,
9978                                             const gchar   *signal,
9979                                             GtkSignalFunc  func,
9980                                             GtkObject     *alive_object );
9981
9982 void gtk_signal_connect_while_alive( GtkObject     *object,
9983                                      const gchar   *signal,
9984                                      GtkSignalFunc  func,
9985                                      gpointer       func_data,
9986                                      GtkObject     *alive_object );
9987
9988 void gtk_signal_disconnect( GtkObject *object,
9989                             guint      handler_id );
9990
9991 void gtk_signal_disconnect_by_func( GtkObject     *object,
9992                                     GtkSignalFunc  func,
9993                                     gpointer       data );
9994 </verb></tscreen>
9995
9996 <!-- ----------------------------------------------------------------- -->
9997 <sect2>Blocking and Unblocking Signal Handlers
9998 <p>
9999 <tscreen><verb>
10000 void gtk_signal_handler_block( GtkObject *object,
10001                                guint      handler_id);
10002
10003 void gtk_signal_handler_block_by_func( GtkObject     *object,
10004                                        GtkSignalFunc  func,
10005                                        gpointer       data );
10006
10007 void gtk_signal_handler_block_by_data( GtkObject *object,
10008                                        gpointer   data );
10009
10010 void gtk_signal_handler_unblock( GtkObject *object,
10011                                  guint      handler_id );
10012
10013 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
10014                                          GtkSignalFunc  func,
10015                                          gpointer       data );
10016
10017 void gtk_signal_handler_unblock_by_data( GtkObject *object,
10018                                          gpointer   data );
10019 </verb></tscreen>
10020
10021 <!-- ----------------------------------------------------------------- -->
10022 <sect2>Emitting and Stopping Signals
10023 <p>
10024 <tscreen><verb>
10025 void gtk_signal_emit( GtkObject *object,
10026                       guint      signal_id,
10027                       ... );
10028
10029 void gtk_signal_emit_by_name( GtkObject   *object,
10030                               const gchar *name,
10031                               ... );
10032
10033 void gtk_signal_emitv( GtkObject *object,
10034                        guint      signal_id,
10035                        GtkArg    *params );
10036
10037 void gtk_signal_emitv_by_name( GtkObject   *object,
10038                                const gchar *name,
10039                                GtkArg      *params );
10040
10041 guint gtk_signal_n_emissions( GtkObject *object,
10042                               guint      signal_id );
10043
10044 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
10045                                       const gchar *name );
10046
10047 void gtk_signal_emit_stop( GtkObject *object,
10048                            guint      signal_id );
10049
10050 void gtk_signal_emit_stop_by_name( GtkObject   *object,
10051                                    const gchar *name );
10052 </verb></tscreen>
10053
10054 <!-- ----------------------------------------------------------------- -->
10055 <sect1>Signal Emission and Propagation
10056 <p>
10057 Signal emission is the process wherby GTK runs all handlers for a
10058 specific object and signal.
10059
10060 First, note that the return value from a signal emission is the return
10061 value of the <em>last</em> handler executed. Since event signals are
10062 all of type GTK_RUN_LAST, this will be the default (GTK supplied)
10063 default handler, unless you connect with gtk_signal_connect_after().
10064
10065 The way an event (say GTK_BUTTON_PRESS) is handled, is:
10066 <itemize>
10067 <item>Start with the widget where the event occured.
10068
10069 <item>Emit the generic "event" signal. If that signal handler returns
10070 a value of TRUE, stop all processing.
10071
10072 <item>Otherwise, emit a specific, "button_press_event" signal. If that
10073 returns TRUE, stop all processing.
10074
10075 <item>Otherwise, go to the widget's parent, and repeat the above steps.
10076
10077 <item>Contimue until some signal handler returns TRUE, or until the
10078 top-level widget is reached.
10079 </itemize>
10080
10081 Some consequences of the above are:
10082 <itemize>
10083 <item>Your handler's return value will have no effect if there is a
10084 default handler, unless you connect with gtk_signal_connect_after().
10085
10086 <item>To prevent the default handler from being run, you need to
10087 connect with gtk_signal_connect() and use
10088 gtk_signal_emit_stop_by_name() - the return value only affects whether
10089 the signal is propagated, not the current emission.
10090 </itemize>
10091
10092 <!-- ***************************************************************** -->
10093 <sect>Managing Selections
10094 <!-- ***************************************************************** -->
10095
10096 <!-- ----------------------------------------------------------------- -->
10097 <sect1> Overview
10098 <p>
10099 One type of interprocess communication supported by GTK is
10100 <em>selections</em>. A selection identifies a chunk of data, for
10101 instance, a portion of text, selected by the user in some fashion, for
10102 instance, by dragging with the mouse. Only one application on a
10103 display, (the <em>owner</em>) can own a particular selection at one
10104 time, so when a selection is claimed by one application, the previous
10105 owner must indicate to the user that selection has been
10106 relinquished. Other applications can request the contents of a
10107 selection in different forms, called <em>targets</em>. There can be
10108 any number of selections, but most X applications only handle one, the
10109 <em>primary selection</em>.
10110
10111 In most cases, it isn't necessary for a GTK application to deal with
10112 selections itself. The standard widgets, such as the Entry widget,
10113 already have the capability to claim the selection when appropriate
10114 (e.g., when the user drags over text), and to retrieve the contents of
10115 the selection owned by another widget, or another application (e.g.,
10116 when the user clicks the second mouse button). However, there may be
10117 cases in which you want to give other widgets the ability to supply
10118 the selection, or you wish to retrieve targets not supported by
10119 default.
10120
10121 A fundamental concept needed to understand selection handling is that
10122 of the <em>atom</em>. An atom is an integer that uniquely identifies a
10123 string (on a certain display). Certain atoms are predefined by the X
10124 server, and in some cases there are constants in <tt>gtk.h</tt>
10125 corresponding to these atoms. For instance the constant
10126 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
10127 In other cases, you should use the functions
10128 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
10129 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
10130 selections and targets are identified by atoms.
10131
10132 <!-- ----------------------------------------------------------------- -->
10133 <sect1> Retrieving the selection
10134 <p>
10135 Retrieving the selection is an asynchronous process. To start the
10136 process, you call:
10137
10138 <tscreen><verb>
10139 gint gtk_selection_convert( GtkWidget *widget, 
10140                             GdkAtom    selection, 
10141                             GdkAtom    target,
10142                             guint32    time );
10143 </verb</tscreen>
10144
10145 This <em>converts</em> the selection into the form specified by
10146 <tt/target/. If at all possible, the time field should be the time
10147 from the event that triggered the selection. This helps make sure that
10148 events occur in the order that the user requested them. However, if it
10149 is not available (for instance, if the conversion was triggered by a
10150 "clicked" signal), then you can use the constant
10151 <tt>GDK_CURRENT_TIME</tt>.
10152
10153 When the selection owner responds to the request, a
10154 "selection_received" signal is sent to your application. The handler
10155 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
10156 structure, which is defined as:
10157
10158 <tscreen><verb>
10159 struct _GtkSelectionData
10160 {
10161   GdkAtom selection;
10162   GdkAtom target;
10163   GdkAtom type;
10164   gint    format;
10165   guchar *data;
10166   gint    length;
10167 };
10168 </verb></tscreen>
10169
10170 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
10171 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
10172 identifies the type of data returned by the selection owner. Some
10173 possible values are "STRING", a string of latin-1 characters, "ATOM",
10174 a series of atoms, "INTEGER", an integer, etc. Most targets can only
10175 return one type. <tt/format/ gives the length of the units (for
10176 instance characters) in bits. Usually, you don't care about this when
10177 receiving data. <tt>data</tt> is a pointer to the returned data, and
10178 <tt>length</tt> gives the length of the returned data, in bytes. If
10179 <tt>length</tt> is negative, then an error occurred and the selection
10180 could not be retrieved. This might happen if no application owned the
10181 selection, or if you requested a target that the application didn't
10182 support. The buffer is actually guaranteed to be one byte longer than
10183 <tt>length</tt>; the extra byte will always be zero, so it isn't
10184 necessary to make a copy of strings just to null terminate them.
10185
10186 In the following example, we retrieve the special target "TARGETS",
10187 which is a list of all targets into which the selection can be
10188 converted.
10189
10190 <tscreen><verb>
10191 /* example-start selection gettargets.c */
10192
10193 #include <gtk/gtk.h>
10194
10195 void selection_received (GtkWidget *widget, 
10196                          GtkSelectionData *selection_data, 
10197                          gpointer data);
10198
10199 /* Signal handler invoked when user clicks on the "Get Targets" button */
10200 void
10201 get_targets (GtkWidget *widget, gpointer data)
10202 {
10203   static GdkAtom targets_atom = GDK_NONE;
10204
10205   /* Get the atom corresponding to the string "TARGETS" */
10206   if (targets_atom == GDK_NONE)
10207     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
10208
10209   /* And request the "TARGETS" target for the primary selection */
10210   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
10211                          GDK_CURRENT_TIME);
10212 }
10213
10214 /* Signal handler called when the selections owner returns the data */
10215 void
10216 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
10217                     gpointer data)
10218 {
10219   GdkAtom *atoms;
10220   GList *item_list;
10221   int i;
10222
10223   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
10224   if (selection_data->length < 0)
10225     {
10226       g_print ("Selection retrieval failed\n");
10227       return;
10228     }
10229   /* Make sure we got the data in the expected form */
10230   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
10231     {
10232       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
10233       return;
10234     }
10235   
10236   /* Print out the atoms we received */
10237   atoms = (GdkAtom *)selection_data->data;
10238
10239   item_list = NULL;
10240   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
10241     {
10242       char *name;
10243       name = gdk_atom_name (atoms[i]);
10244       if (name != NULL)
10245         g_print ("%s\n",name);
10246       else
10247         g_print ("(bad atom)\n");
10248     }
10249
10250   return;
10251 }
10252
10253 int 
10254 main (int argc, char *argv[])
10255 {
10256   GtkWidget *window;
10257   GtkWidget *button;
10258   
10259   gtk_init (&amp;argc, &amp;argv);
10260
10261   /* Create the toplevel window */
10262
10263   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10264   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
10265   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10266
10267   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10268                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
10269
10270   /* Create a button the user can click to get targets */
10271
10272   button = gtk_button_new_with_label ("Get Targets");
10273   gtk_container_add (GTK_CONTAINER (window), button);
10274
10275   gtk_signal_connect (GTK_OBJECT(button), "clicked",
10276                       GTK_SIGNAL_FUNC (get_targets), NULL);
10277   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
10278                       GTK_SIGNAL_FUNC (selection_received), NULL);
10279
10280   gtk_widget_show (button);
10281   gtk_widget_show (window);
10282   
10283   gtk_main ();
10284   
10285   return 0;
10286 }
10287 /* example-end */
10288 </verb></tscreen>
10289
10290 <!-- ----------------------------------------------------------------- -->
10291 <sect1> Supplying the selection 
10292 <p>
10293 Supplying the selection is a bit more complicated. You must register 
10294 handlers that will be called when your selection is requested. For
10295 each selection/target pair you will handle, you make a call to:
10296
10297 <tscreen><verb>
10298 void gtk_selection_add_handler( GtkWidget            *widget, 
10299                                 GdkAtom               selection,
10300                                 GdkAtom               target,
10301                                 GtkSelectionFunction  function,
10302                                 GtkRemoveFunction     remove_func,
10303                                 gpointer              data );
10304 </verb></tscreen>
10305
10306 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
10307 this handler will manage.  <tt/remove_func/, if not
10308 NULL, will be called when the signal handler is removed. This is
10309 useful, for instance, for interpreted languages which need to
10310 keep track of a reference count for <tt/data/.
10311
10312 The callback function has the signature:
10313
10314 <tscreen><verb>
10315 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
10316                                       GtkSelectionData *selection_data,
10317                                       gpointer          data );
10318
10319 </verb></tscreen>
10320
10321 The GtkSelectionData is the same as above, but this time, we're
10322 responsible for filling in the fields <tt/type/, <tt/format/,
10323 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
10324 important here - the X server uses it to figure out whether the data
10325 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
10326 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
10327 function:
10328
10329 <tscreen><verb>
10330 void gtk_selection_data_set( GtkSelectionData *selection_data,
10331                              GdkAtom           type,
10332                              gint              format,
10333                              guchar           *data,
10334                              gint              length );
10335 </verb></tscreen>
10336
10337 This function takes care of properly making a copy of the data so that
10338 you don't have to worry about keeping it around. (You should not fill
10339 in the fields of the GtkSelectionData structure by hand.)
10340
10341 When prompted by the user, you claim ownership of the selection by
10342 calling:
10343
10344 <tscreen><verb>
10345 gint gtk_selection_owner_set( GtkWidget *widget,
10346                               GdkAtom    selection,
10347                               guint32    time );
10348 </verb></tscreen>
10349
10350 If another application claims ownership of the selection, you will
10351 receive a "selection_clear_event".
10352
10353 As an example of supplying the selection, the following program adds
10354 selection functionality to a toggle button. When the toggle button is
10355 depressed, the program claims the primary selection. The only target
10356 supported (aside from certain targets like "TARGETS" supplied by GTK
10357 itself), is the "STRING" target. When this target is requested, a
10358 string representation of the time is returned.
10359
10360 <tscreen><verb>
10361 /* example-start selection setselection.c */
10362
10363 #include <gtk/gtk.h>
10364 #include <time.h>
10365
10366 /* Callback when the user toggles the selection */
10367 void
10368 selection_toggled (GtkWidget *widget, gint *have_selection)
10369 {
10370   if (GTK_TOGGLE_BUTTON(widget)->active)
10371     {
10372       *have_selection = gtk_selection_owner_set (widget,
10373                                                  GDK_SELECTION_PRIMARY,
10374                                                  GDK_CURRENT_TIME);
10375       /* if claiming the selection failed, we return the button to
10376          the out state */
10377       if (!*have_selection)
10378         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
10379     }
10380   else
10381     {
10382       if (*have_selection)
10383         {
10384           /* Before clearing the selection by setting the owner to NULL,
10385              we check if we are the actual owner */
10386           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
10387             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
10388                                      GDK_CURRENT_TIME);
10389           *have_selection = FALSE;
10390         }
10391     }
10392 }
10393
10394 /* Called when another application claims the selection */
10395 gint
10396 selection_clear (GtkWidget *widget, GdkEventSelection *event,
10397                  gint *have_selection)
10398 {
10399   *have_selection = FALSE;
10400   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
10401
10402   return TRUE;
10403 }
10404
10405 /* Supplies the current time as the selection. */
10406 void
10407 selection_handle (GtkWidget *widget, 
10408                   GtkSelectionData *selection_data,
10409                   gpointer data)
10410 {
10411   gchar *timestr;
10412   time_t current_time;
10413
10414   current_time = time (NULL);
10415   timestr = asctime (localtime(&amp;current_time)); 
10416   /* When we return a single string, it should not be null terminated.
10417      That will be done for us */
10418
10419   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
10420                           8, timestr, strlen(timestr));
10421 }
10422
10423 int
10424 main (int argc, char *argv[])
10425 {
10426   GtkWidget *window;
10427
10428   GtkWidget *selection_button;
10429
10430   static int have_selection = FALSE;
10431   
10432   gtk_init (&amp;argc, &amp;argv);
10433
10434   /* Create the toplevel window */
10435
10436   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10437   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
10438   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10439
10440   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10441                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
10442
10443   /* Create a toggle button to act as the selection */
10444
10445   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
10446   gtk_container_add (GTK_CONTAINER (window), selection_button);
10447   gtk_widget_show (selection_button);
10448
10449   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
10450                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
10451   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
10452                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
10453
10454   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
10455                              GDK_SELECTION_TYPE_STRING,
10456                              selection_handle, NULL);
10457
10458   gtk_widget_show (selection_button);
10459   gtk_widget_show (window);
10460   
10461   gtk_main ();
10462   
10463   return 0;
10464 }
10465 /* example-end */
10466 </verb></tscreen>
10467
10468
10469 <!-- ***************************************************************** -->
10470 <sect>glib<label id="sec_glib">
10471 <!-- ***************************************************************** -->
10472 <p>
10473 glib provides many useful functions and definitions available for use
10474 when creating GDK and GTK applications. I will list them all here with
10475 a brief explanation. Many are duplicates of standard libc functions so
10476 I won't go into detail on those. This is mostly to be used as a reference,
10477 so you know what is available for use.
10478
10479 <!-- ----------------------------------------------------------------- -->
10480 <sect1>Definitions
10481 <p>
10482 Definitions for the extremes of many of the standard types are:
10483
10484 <tscreen><verb>
10485 G_MINFLOAT
10486 G_MAXFLOAT
10487 G_MINDOUBLE
10488 G_MAXDOUBLE
10489 G_MINSHORT
10490 G_MAXSHORT
10491 G_MININT
10492 G_MAXINT
10493 G_MINLONG
10494 G_MAXLONG
10495 </verb></tscreen>
10496
10497 Also, the following typedefs. The ones left unspecified are dynamically set
10498 depending on the architecture. Remember to avoid counting on the size of a
10499 pointer if you want to be portable! E.g., a pointer on an Alpha is 8 bytes, but 4
10500 on Intel.
10501
10502 <tscreen><verb>
10503 char   gchar;
10504 short  gshort;
10505 long   glong;
10506 int    gint;
10507 char   gboolean;
10508
10509 unsigned char   guchar;
10510 unsigned short  gushort;
10511 unsigned long   gulong;
10512 unsigned int    guint;
10513
10514 float   gfloat;
10515 double  gdouble;
10516 long double gldouble;
10517
10518 void* gpointer;
10519
10520 gint8
10521 guint8
10522 gint16
10523 guint16
10524 gint32
10525 guint32
10526 </verb></tscreen>
10527
10528 <!-- ----------------------------------------------------------------- -->
10529 <sect1>Doubly Linked Lists
10530 <p>
10531 The following functions are used to create, manage, and destroy doubly
10532 linked lists.  I assume you know what linked lists are, as it is beyond the scope
10533 of this document to explain them.  Of course, it's not required that you
10534 know these for general use of GTK, but they are nice to know.
10535
10536 <tscreen><verb>
10537 GList *g_list_alloc( void );
10538
10539 void g_list_free( GList *list );
10540
10541 void g_list_free_1( GList *list );
10542
10543 GList *g_list_append( GList     *list,
10544                       gpointer   data );
10545                            
10546 GList *g_list_prepend( GList    *list,
10547                        gpointer  data );
10548                         
10549 GList *g_list_insert( GList    *list,
10550                       gpointer  data,
10551                             gint      position );
10552
10553 GList *g_list_remove( GList    *list,
10554                       gpointer  data );
10555                            
10556 GList *g_list_remove_link( GList *list,
10557                            GList *link );
10558
10559 GList *g_list_reverse( GList *list );
10560
10561 GList *g_list_nth( GList *list,
10562                    gint   n );
10563                            
10564 GList *g_list_find( GList    *list,
10565                     gpointer  data );
10566
10567 GList *g_list_last( GList *list );
10568
10569 GList *g_list_first( GList *list );
10570
10571 gint g_list_length( GList *list );
10572
10573 void g_list_foreach( GList    *list,
10574                      GFunc     func,
10575                      gpointer  user_data );
10576 </verb></tscreen>                                             
10577
10578 <!-- ----------------------------------------------------------------- -->
10579 <sect1>Singly Linked Lists
10580 <p>
10581 Many of the above functions for singly linked lists are identical to the
10582 above. Here is a complete list:
10583 <tscreen><verb>
10584 GSList *g_slist_alloc( void );
10585
10586 void g_slist_free( GSList *list );
10587
10588 void g_slist_free_1( GSList *list );
10589
10590 GSList *g_slist_append( GSList   *list,
10591                         gpointer  data );
10592                 
10593 GSList *g_slist_prepend( GSList   *list,
10594                          gpointer  data );
10595                              
10596 GSList *g_slist_insert( GSList   *list,
10597                         gpointer  data,
10598                             gint      position );
10599                              
10600 GSList *g_slist_remove( GSList   *list,
10601                         gpointer  data );
10602                              
10603 GSList *g_slist_remove_link( GSList *list,
10604                              GSList *link );
10605                              
10606 GSList *g_slist_reverse( GSList *list );
10607
10608 GSList *g_slist_nth( GSList *list,
10609                      gint    n );
10610                              
10611 GSList *g_slist_find( GSList   *list,
10612                       gpointer  data );
10613                              
10614 GSList *g_slist_last( GSList *list );
10615
10616 gint g_slist_length( GSList *list );
10617
10618 void g_slist_foreach( GSList   *list,
10619                       GFunc     func,
10620                             gpointer  user_data );
10621         
10622 </verb></tscreen>
10623
10624 <!-- ----------------------------------------------------------------- -->
10625 <sect1>Memory Management
10626 <p>
10627 <tscreen><verb>
10628 gpointer g_malloc( gulong size );
10629 </verb></tscreen>
10630
10631 This is a replacement for malloc(). You do not need to check the return
10632 value as it is done for you in this function.
10633
10634 <tscreen><verb>
10635 gpointer g_malloc0( gulong size );
10636 </verb></tscreen>
10637
10638 Same as above, but zeroes the memory before returning a pointer to it.
10639
10640 <tscreen><verb>
10641 gpointer g_realloc( gpointer mem,
10642                     gulong   size );
10643 </verb></tscreen>
10644
10645 Relocates "size" bytes of memory starting at "mem".  Obviously, the
10646 memory should have been previously allocated.
10647
10648 <tscreen><verb>
10649 void g_free( gpointer mem );
10650 </verb></tscreen>
10651
10652 Frees memory. Easy one.
10653
10654 <tscreen><verb>
10655 void g_mem_profile( void );
10656 </verb></tscreen>
10657
10658 Dumps a profile of used memory, but requires that you add #define
10659 MEM_PROFILE to the top of glib/gmem.c and re-make and make install.
10660
10661 <tscreen><verb>
10662 void g_mem_check( gpointer mem );
10663 </verb></tscreen>
10664
10665 Checks that a memory location is valid.  Requires you add #define
10666 MEM_CHECK to the top of gmem.c and re-make and make install.
10667
10668 <!-- ----------------------------------------------------------------- -->
10669 <sect1>Timers
10670 <p>
10671 Timer functions..
10672
10673 <tscreen><verb>
10674 GTimer *g_timer_new( void );
10675
10676 void g_timer_destroy( GTimer *timer );
10677
10678 void g_timer_start( GTimer  *timer );
10679
10680 void g_timer_stop( GTimer  *timer );
10681
10682 void g_timer_reset( GTimer  *timer );
10683
10684 gdouble g_timer_elapsed( GTimer *timer,
10685                          gulong *microseconds );
10686 </verb></tscreen>                        
10687
10688 <!-- ----------------------------------------------------------------- -->
10689 <sect1>String Handling
10690 <p>
10691 A whole mess of string handling functions. They all look very interesting, and
10692 probably better for many purposes than the standard C string functions, but
10693 require documentation.
10694
10695 <tscreen><verb>
10696 GString *g_string_new( gchar *init );
10697
10698 void g_string_free( GString *string,
10699                     gint     free_segment );
10700                              
10701 GString *g_string_assign( GString *lval,
10702                           gchar   *rval );
10703                              
10704 GString *g_string_truncate( GString *string,
10705                             gint     len );
10706                              
10707 GString *g_string_append( GString *string,
10708                           gchar   *val );
10709                             
10710 GString *g_string_append_c( GString *string,
10711                             gchar    c );
10712         
10713 GString *g_string_prepend( GString *string,
10714                            gchar   *val );
10715                              
10716 GString *g_string_prepend_c( GString *string,
10717                              gchar    c );
10718         
10719 void g_string_sprintf( GString *string,
10720                        gchar   *fmt,
10721                        ...);
10722         
10723 void g_string_sprintfa ( GString *string,
10724                          gchar   *fmt,
10725                          ... );
10726 </verb></tscreen>                                                         
10727
10728 <!-- ----------------------------------------------------------------- -->
10729 <sect1>Utility and Error Functions
10730 <p>
10731 <tscreen><verb>
10732 gchar *g_strdup( const gchar *str );
10733 </verb></tscreen>
10734
10735 Replacement strdup function.  Copies the original strings contents to
10736 newly allocated memory, and returns a pointer to it.
10737
10738 <tscreen><verb>
10739 gchar *g_strerror( gint errnum );
10740 </verb></tscreen>
10741
10742 I recommend using this for all error messages.  It's much nicer, and more
10743 portable than perror() or others.  The output is usually of the form:
10744
10745 <tscreen><verb>
10746 program name:function that failed:file or further description:strerror
10747 </verb></tscreen>
10748
10749 Here's an example of one such call used in our hello_world program:
10750
10751 <tscreen><verb>
10752 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
10753 </verb></tscreen>
10754
10755 <tscreen><verb>
10756 void g_error( gchar *format, ... );
10757 </verb></tscreen>
10758
10759 Prints an error message. The format is just like printf, but it
10760 prepends "** ERROR **: " to your message, and exits the program.  
10761 Use only for fatal errors.
10762
10763 <tscreen><verb>
10764 void g_warning( gchar *format, ... );
10765 </verb></tscreen>
10766
10767 Same as above, but prepends "** WARNING **: ", and does not exit the
10768 program.
10769
10770 <tscreen><verb>
10771 void g_message( gchar *format, ... );
10772 </verb></tscreen>
10773
10774 Prints "message: " prepended to the string you pass in.
10775
10776 <tscreen><verb>
10777 void g_print( gchar *format, ... );
10778 </verb></tscreen>
10779
10780 Replacement for printf().
10781
10782 And our last function:
10783
10784 <tscreen><verb>
10785 gchar *g_strsignal( gint signum );
10786 </verb></tscreen>
10787
10788 Prints out the name of the Unix system signal given the signal number.
10789 Useful in generic signal handling functions.
10790
10791 All of the above are more or less just stolen from glib.h.  If anyone cares
10792 to document any function, just send me an email!
10793
10794 <!-- ***************************************************************** -->
10795 <sect>GTK's rc Files
10796 <!-- ***************************************************************** -->
10797 <p>
10798 GTK has its own way of dealing with application defaults, by using rc
10799 files. These can be used to set the colors of just about any widget, and
10800 can also be used to tile pixmaps onto the background of some widgets.  
10801
10802 <!-- ----------------------------------------------------------------- -->
10803 <sect1>Functions For rc Files 
10804 <p>
10805 When your application starts, you should include a call to:
10806
10807 <tscreen><verb>
10808 void gtk_rc_parse( char *filename );
10809 </verb></tscreen>
10810
10811 Passing in the filename of your rc file. This will cause GTK to parse
10812 this file, and use the style settings for the widget types defined
10813 there.
10814
10815 If you wish to have a special set of widgets that can take on a
10816 different style from others, or any other logical division of widgets,
10817 use a call to:
10818
10819 <tscreen><verb>
10820 void gtk_widget_set_name( GtkWidget *widget,
10821                           gchar     *name );
10822 </verb></tscreen>
10823
10824 Passing your newly created widget as the first argument, and the name
10825 you wish to give it as the second. This will allow you to change the
10826 attributes of this widget by name through the rc file.
10827
10828 If we use a call something like this:
10829
10830 <tscreen><verb>
10831 button = gtk_button_new_with_label ("Special Button");
10832 gtk_widget_set_name (button, "special button");
10833 </verb></tscreen>
10834
10835 Then this button is given the name "special button" and may be addressed by
10836 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
10837
10838 The example rc file below, sets the properties of the main window, and lets
10839 all children of that main window inherit the style described by the "main
10840 button" style.  The code used in the application is:
10841
10842 <tscreen><verb>
10843 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10844 gtk_widget_set_name (window, "main window");
10845 </verb></tscreen>
10846
10847 And then the style is defined in the rc file using:
10848
10849 <tscreen><verb>
10850 widget "main window.*GtkButton*" style "main_button"
10851 </verb></tscreen>
10852
10853 Which sets all the GtkButton widgets in the "main window" to the
10854 "main_buttons" style as defined in the rc file.
10855
10856 As you can see, this is a fairly powerful and flexible system.  Use your
10857 imagination as to how best to take advantage of this.
10858
10859 <!-- ----------------------------------------------------------------- -->
10860 <sect1>GTK's rc File Format
10861 <p>
10862 The format of the GTK file is illustrated in the example below. This is
10863 the testgtkrc file from the GTK distribution, but I've added a
10864 few comments and things. You may wish to include this explanation
10865 your application to allow the user to fine tune his application.
10866
10867 There are several directives to change the attributes of a widget.
10868
10869 <itemize>
10870 <item>fg - Sets the foreground color of a widget.
10871 <item>bg - Sets the background color of a widget.
10872 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
10873 <item>font - Sets the font to be used with the given widget.
10874 </itemize>
10875
10876 In addition to this, there are several states a widget can be in, and you
10877 can set different colors, pixmaps and fonts for each state. These states are:
10878
10879 <itemize>
10880 <item>NORMAL - The normal state of a widget, without the mouse over top of
10881 it, and not being pressed etc.
10882 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
10883 using this state will be in effect.
10884 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
10885 the attributes assigned by this tag will be in effect.
10886 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
10887 activated, it will take these attributes.
10888 <item>SELECTED - When an object is selected, it takes these attributes.
10889 </itemize>
10890
10891 When using the "fg" and "bg" keywords to set the colors of widgets, the
10892 format is:
10893
10894 <tscreen><verb>
10895 fg[<STATE>] = { Red, Green, Blue }
10896 </verb></tscreen>
10897
10898 Where STATE is one of the above states (PRELIGHT, ACTIVE etc), and the Red,
10899 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
10900 white. They must be in float form, or they will register as 0, so a straight 
10901 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
10902 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
10903
10904 bg_pixmap is very similar to the above, except the colors are replaced by a
10905 filename.
10906
10907 pixmap_path is a list of paths separated by ":"'s.  These paths will be
10908 searched for any pixmap you specify.
10909
10910 The font directive is simply:
10911 <tscreen><verb>
10912 font = "<font name>"
10913 </verb></tscreen>
10914
10915 Where the only hard part is figuring out the font string. Using xfontsel or
10916 similar utility should help.
10917
10918 The "widget_class" sets the style of a class of widgets. These classes are
10919 listed in the widget overview on the class hierarchy.
10920
10921 The "widget" directive sets a specifically named set of widgets to a
10922 given style, overriding any style set for the given widget class.
10923 These widgets are registered inside the application using the
10924 gtk_widget_set_name() call. This allows you to specify the attributes of a
10925 widget on a per widget basis, rather than setting the attributes of an
10926 entire widget class. I urge you to document any of these special widgets so
10927 users may customize them.
10928
10929 When the keyword <tt>parent</> is used as an attribute, the widget will take on
10930 the attributes of its parent in the application.
10931
10932 When defining a style, you may assign the attributes of a previously defined
10933 style to this new one.
10934
10935 <tscreen><verb>
10936 style "main_button" = "button"
10937 {
10938   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10939   bg[PRELIGHT] = { 0.75, 0, 0 }
10940 }
10941 </verb></tscreen>
10942
10943 This example takes the "button" style, and creates a new "main_button" style
10944 simply by changing the font and prelight background color of the "button"
10945 style.
10946
10947 Of course, many of these attributes don't apply to all widgets. It's a
10948 simple matter of common sense really. Anything that could apply, should.
10949
10950 <!-- ----------------------------------------------------------------- -->
10951 <sect1>Example rc file
10952 <p>
10953
10954 <tscreen><verb>
10955 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
10956 #
10957 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
10958 #
10959 # style <name> [= <name>]
10960 # {
10961 #   <option>
10962 # }
10963 #
10964 # widget <widget_set> style <style_name>
10965 # widget_class <widget_class_set> style <style_name>
10966
10967
10968 # Here is a list of all the possible states.  Note that some do not apply to
10969 # certain widgets.
10970 #
10971 # NORMAL - The normal state of a widget, without the mouse over top of
10972 # it, and not being pressed etc.
10973 #
10974 # PRELIGHT - When the mouse is over top of the widget, colors defined
10975 # using this state will be in effect.
10976 #
10977 # ACTIVE - When the widget is pressed or clicked it will be active, and
10978 # the attributes assigned by this tag will be in effect.
10979 #
10980 # INSENSITIVE - When a widget is set insensitive, and cannot be
10981 # activated, it will take these attributes.
10982 #
10983 # SELECTED - When an object is selected, it takes these attributes.
10984 #
10985 # Given these states, we can set the attributes of the widgets in each of
10986 # these states using the following directives.
10987 #
10988 # fg - Sets the foreground color of a widget.
10989 # fg - Sets the background color of a widget.
10990 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
10991 # font - Sets the font to be used with the given widget.
10992 #
10993
10994 # This sets a style called "button".  The name is not really important, as
10995 # it is assigned to the actual widgets at the bottom of the file.
10996
10997 style "window"
10998 {
10999   #This sets the padding around the window to the pixmap specified.
11000   #bg_pixmap[<STATE>] = "<pixmap filename>"
11001   bg_pixmap[NORMAL] = "warning.xpm"
11002 }
11003
11004 style "scale"
11005 {
11006   #Sets the foreground color (font color) to red when in the "NORMAL"
11007   #state.
11008   
11009   fg[NORMAL] = { 1.0, 0, 0 }
11010   
11011   #Sets the background pixmap of this widget to that of its parent.
11012   bg_pixmap[NORMAL] = "<parent>"
11013 }
11014
11015 style "button"
11016 {
11017   # This shows all the possible states for a button.  The only one that
11018   # doesn't apply is the SELECTED state.
11019   
11020   fg[PRELIGHT] = { 0, 1.0, 1.0 }
11021   bg[PRELIGHT] = { 0, 0, 1.0 }
11022   bg[ACTIVE] = { 1.0, 0, 0 }
11023   fg[ACTIVE] = { 0, 1.0, 0 }
11024   bg[NORMAL] = { 1.0, 1.0, 0 }
11025   fg[NORMAL] = { .99, 0, .99 }
11026   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
11027   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
11028 }
11029
11030 # In this example, we inherit the attributes of the "button" style and then
11031 # override the font and background color when prelit to create a new
11032 # "main_button" style.
11033
11034 style "main_button" = "button"
11035 {
11036   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11037   bg[PRELIGHT] = { 0.75, 0, 0 }
11038 }
11039
11040 style "toggle_button" = "button"
11041 {
11042   fg[NORMAL] = { 1.0, 0, 0 }
11043   fg[ACTIVE] = { 1.0, 0, 0 }
11044   
11045   # This sets the background pixmap of the toggle_button to that of its
11046   # parent widget (as defined in the application).
11047   bg_pixmap[NORMAL] = "<parent>"
11048 }
11049
11050 style "text"
11051 {
11052   bg_pixmap[NORMAL] = "marble.xpm"
11053   fg[NORMAL] = { 1.0, 1.0, 1.0 }
11054 }
11055
11056 style "ruler"
11057 {
11058   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
11059 }
11060
11061 # pixmap_path "~/.pixmaps"
11062
11063 # These set the widget types to use the styles defined above.
11064 # The widget types are listed in the class hierarchy, but could probably be
11065 # just listed in this document for the users reference.
11066
11067 widget_class "GtkWindow" style "window"
11068 widget_class "GtkDialog" style "window"
11069 widget_class "GtkFileSelection" style "window"
11070 widget_class "*Gtk*Scale" style "scale"
11071 widget_class "*GtkCheckButton*" style "toggle_button"
11072 widget_class "*GtkRadioButton*" style "toggle_button"
11073 widget_class "*GtkButton*" style "button"
11074 widget_class "*Ruler" style "ruler"
11075 widget_class "*GtkText" style "text"
11076
11077 # This sets all the buttons that are children of the "main window" to
11078 # the main_button style.  These must be documented to be taken advantage of.
11079 widget "main window.*GtkButton*" style "main_button"
11080 </verb></tscreen>
11081
11082 <!-- ***************************************************************** -->
11083 <sect>Writing Your Own Widgets 
11084 <!-- ***************************************************************** -->
11085
11086 <!-- ----------------------------------------------------------------- -->
11087 <sect1> Overview
11088 <p>
11089 Although the GTK distribution comes with many types of widgets that
11090 should cover most basic needs, there may come a time when you need to
11091 create your own new widget type. Since GTK uses widget inheritance
11092 extensively, and there is already a widget that is close to what you want,
11093 it is often possible to make a useful new widget type in
11094 just a few lines of code. But before starting work on a new widget, check
11095 around first to make sure that someone has not already written
11096 it. This will prevent duplication of effort and keep the number of
11097 GTK widgets out there to a minimum, which will help keep both the code
11098 and the interface of different applications consistent. As a flip side
11099 to this, once you finish your widget, announce it to the world so
11100 other people can benefit. The best place to do this is probably the
11101 <tt>gtk-list</tt>.
11102
11103 Complete sources for the example widgets are available at the place you 
11104 got this tutorial, or from:
11105
11106 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
11107 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
11108
11109
11110 <!-- ----------------------------------------------------------------- -->
11111 <sect1> The Anatomy Of A Widget
11112 <p>
11113 In order to create a new widget, it is important to have an
11114 understanding of how GTK objects work. This section is just meant as a
11115 brief overview. See the reference documentation for the details. 
11116
11117 GTK widgets are implemented in an object oriented fashion. However,
11118 they are implemented in standard C. This greatly improves portability
11119 and stability over using current generation C++ compilers; however,
11120 it does mean that the widget writer has to pay attention to some of
11121 the implementation details. The information common to all instances of
11122 one class of widgets (e.g., to all Button widgets) is stored in the 
11123 <em>class structure</em>. There is only one copy of this in
11124 which is stored information about the class's signals
11125 (which act like virtual functions in C). To support inheritance, the
11126 first field in the class structure must be a copy of the parent's
11127 class structure. The declaration of the class structure of GtkButtton
11128 looks like:
11129
11130 <tscreen><verb>
11131 struct _GtkButtonClass
11132 {
11133   GtkContainerClass parent_class;
11134
11135   void (* pressed)  (GtkButton *button);
11136   void (* released) (GtkButton *button);
11137   void (* clicked)  (GtkButton *button);
11138   void (* enter)    (GtkButton *button);
11139   void (* leave)    (GtkButton *button);
11140 };
11141 </verb></tscreen>
11142
11143 When a button is treated as a container (for instance, when it is
11144 resized), its class structure can be cast to GtkContainerClass, and
11145 the relevant fields used to handle the signals.
11146
11147 There is also a structure for each widget that is created on a
11148 per-instance basis. This structure has fields to store information that
11149 is different for each instance of the widget. We'll call this
11150 structure the <em>object structure</em>. For the Button class, it looks
11151 like:
11152
11153 <tscreen><verb>
11154 struct _GtkButton
11155 {
11156   GtkContainer container;
11157
11158   GtkWidget *child;
11159
11160   guint in_button : 1;
11161   guint button_down : 1;
11162 };
11163 </verb></tscreen>
11164
11165 Note that, similar to the class structure, the first field is the
11166 object structure of the parent class, so that this structure can be
11167 cast to the parent class's object structure as needed.
11168
11169 <!-- ----------------------------------------------------------------- -->
11170 <sect1> Creating a Composite widget
11171
11172 <!-- ----------------------------------------------------------------- -->
11173 <sect2> Introduction
11174 <p>
11175 One type of widget that you may be interested in creating is a
11176 widget that is merely an aggregate of other GTK widgets. This type of
11177 widget does nothing that couldn't be done without creating new
11178 widgets, but provides a convenient way of packaging user interface
11179 elements for reuse. The FileSelection and ColorSelection widgets in
11180 the standard distribution are examples of this type of widget.
11181
11182 The example widget that we'll create in this section is the Tictactoe
11183 widget, a 3x3 array of toggle buttons which triggers a signal when all
11184 three buttons in a row, column, or on one of the diagonals are
11185 depressed. 
11186
11187 <!-- ----------------------------------------------------------------- -->
11188 <sect2> Choosing a parent class
11189 <p>
11190 The parent class for a composite widget is typically the container
11191 class that holds all of the elements of the composite widget. For
11192 example, the parent class of the FileSelection widget is the
11193 Dialog class. Since our buttons will be arranged in a table, it
11194 might seem natural to make our parent class the GtkTable
11195 class. Unfortunately, this turns out not to work. The creation of a
11196 widget is divided among two functions - a <tt/WIDGETNAME_new()/
11197 function that the user calls, and a <tt/WIDGETNAME_init()/ function
11198 which does the basic work of initializing the widget which is
11199 independent of the arguments passed to the <tt/_new()/
11200 function. Descendent widgets only call the <tt/_init/ function of
11201 their parent widget. But this division of labor doesn't work well for
11202 tables, which when created, need to know the number of rows and
11203 columns in the table. Unless we want to duplicate most of the
11204 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
11205 best avoid deriving it from GtkTable. For that reason, we derive it
11206 from GtkVBox instead, and stick our table inside the VBox.
11207
11208 <!-- ----------------------------------------------------------------- -->
11209 <sect2> The header file
11210 <p>
11211 Each widget class has a header file which declares the object and
11212 class structures for that widget, along with public functions. 
11213 A couple of features are worth pointing out. To prevent duplicate
11214 definitions, we wrap the entire header file in:
11215
11216 <tscreen><verb>
11217 #ifndef __TICTACTOE_H__
11218 #define __TICTACTOE_H__
11219 .
11220 .
11221 .
11222 #endif /* __TICTACTOE_H__ */
11223 </verb></tscreen>
11224
11225 And to keep C++ programs that include the header file happy, in:
11226
11227 <tscreen><verb>
11228 #ifdef __cplusplus
11229 extern "C" {
11230 #endif /* __cplusplus */
11231 .
11232 .
11233 .
11234 #ifdef __cplusplus
11235 }
11236 #endif /* __cplusplus */
11237 </verb></tscreen>
11238
11239 Along with the functions and structures, we declare three standard
11240 macros in our header file, <tt/TICTACTOE(obj)/,
11241 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
11242 pointer into a pointer to the object or class structure, and check
11243 if an object is a Tictactoe widget respectively.
11244
11245 Here is the complete header file:
11246
11247 <tscreen><verb>
11248 /* tictactoe.h */
11249
11250 #ifndef __TICTACTOE_H__
11251 #define __TICTACTOE_H__
11252
11253 #include <gdk/gdk.h>
11254 #include <gtk/gtkvbox.h>
11255
11256 #ifdef __cplusplus
11257 extern "C" {
11258 #endif /* __cplusplus */
11259
11260 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
11261 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
11262 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
11263
11264
11265 typedef struct _Tictactoe       Tictactoe;
11266 typedef struct _TictactoeClass  TictactoeClass;
11267
11268 struct _Tictactoe
11269 {
11270   GtkVBox vbox;
11271   
11272   GtkWidget *buttons[3][3];
11273 };
11274
11275 struct _TictactoeClass
11276 {
11277   GtkVBoxClass parent_class;
11278
11279   void (* tictactoe) (Tictactoe *ttt);
11280 };
11281
11282 guint          tictactoe_get_type        (void);
11283 GtkWidget*     tictactoe_new             (void);
11284 void           tictactoe_clear           (Tictactoe *ttt);
11285
11286 #ifdef __cplusplus
11287 }
11288 #endif /* __cplusplus */
11289
11290 #endif /* __TICTACTOE_H__ */
11291
11292 </verb></tscreen>
11293
11294 <!-- ----------------------------------------------------------------- -->
11295 <sect2> The <tt/_get_type()/ function.
11296 <p>
11297 We now continue on to the implementation of our widget. A core
11298 function for every widget is the function
11299 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
11300 GTK about the widget class, and gets an ID that uniquely identifies
11301 the widget class. Upon subsequent calls, it just returns the ID.
11302
11303 <tscreen><verb>
11304 guint
11305 tictactoe_get_type ()
11306 {
11307   static guint ttt_type = 0;
11308
11309   if (!ttt_type)
11310     {
11311       GtkTypeInfo ttt_info =
11312       {
11313         "Tictactoe",
11314         sizeof (Tictactoe),
11315         sizeof (TictactoeClass),
11316         (GtkClassInitFunc) tictactoe_class_init,
11317         (GtkObjectInitFunc) tictactoe_init,
11318         (GtkArgSetFunc) NULL,
11319         (GtkArgGetFunc) NULL
11320       };
11321
11322       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
11323     }
11324
11325   return ttt_type;
11326 }
11327 </verb></tscreen>
11328
11329 The GtkTypeInfo structure has the following definition:
11330
11331 <tscreen><verb>
11332 struct _GtkTypeInfo
11333 {
11334   gchar *type_name;
11335   guint object_size;
11336   guint class_size;
11337   GtkClassInitFunc class_init_func;
11338   GtkObjectInitFunc object_init_func;
11339   GtkArgSetFunc arg_set_func;
11340   GtkArgGetFunc arg_get_func;
11341 };
11342 </verb></tscreen>
11343
11344 The fields of this structure are pretty self-explanatory. We'll ignore
11345 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
11346 but as yet largely
11347 unimplemented, role in allowing widget options to be conveniently set
11348 from interpreted languages. Once GTK has a correctly filled in copy of
11349 this structure, it knows how to create objects of a particular widget
11350 type. 
11351
11352 <!-- ----------------------------------------------------------------- -->
11353 <sect2> The <tt/_class_init()/ function
11354 <p>
11355 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
11356 the widget's class structure, and sets up any signals for the
11357 class. For our Tictactoe widget it looks like:
11358
11359 <tscreen><verb>
11360
11361 enum {
11362   TICTACTOE_SIGNAL,
11363   LAST_SIGNAL
11364 };
11365
11366 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
11367
11368 static void
11369 tictactoe_class_init (TictactoeClass *class)
11370 {
11371   GtkObjectClass *object_class;
11372
11373   object_class = (GtkObjectClass*) class;
11374   
11375   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
11376                                          GTK_RUN_FIRST,
11377                                          object_class->type,
11378                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
11379                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
11380
11381
11382   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
11383
11384   class->tictactoe = NULL;
11385 }
11386 </verb></tscreen>
11387
11388 Our widget has just one signal, the <tt/tictactoe/ signal that is
11389 invoked when a row, column, or diagonal is completely filled in. Not
11390 every composite widget needs signals, so if you are reading this for
11391 the first time, you may want to skip to the next section now, as
11392 things are going to get a bit complicated.
11393
11394 The function:
11395
11396 <tscreen><verb>
11397 gint gtk_signal_new( const gchar         *name,
11398                      GtkSignalRunType     run_type,
11399                      GtkType              object_type,
11400                      gint                 function_offset,
11401                      GtkSignalMarshaller  marshaller,
11402                      GtkType              return_val,
11403                      guint                nparams,
11404                      ...);
11405 </verb></tscreen>
11406
11407 Creates a new signal. The parameters are:
11408
11409 <itemize>
11410 <item> <tt/name/: The name of the signal.
11411 <item> <tt/run_type/: Whether the default handler runs before or after
11412 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
11413 although there are other possibilities.
11414 <item> <tt/object_type/: The ID of the object that this signal applies
11415 to. (It will also apply to that objects descendents)
11416 <item> <tt/function_offset/: The offset within the class structure of
11417 a pointer to the default handler.
11418 <item> <tt/marshaller/: A function that is used to invoke the signal
11419 handler. For signal handlers that have no arguments other than the
11420 object that emitted the signal and user data, we can use the
11421 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
11422 <item> <tt/return_val/: The type of the return val.
11423 <item> <tt/nparams/: The number of parameters of the signal handler
11424 (other than the two default ones mentioned above)
11425 <item> <tt/.../: The types of the parameters.
11426 </itemize>
11427
11428 When specifying types, the <tt/GtkType/ enumeration is used:
11429
11430 <tscreen><verb>
11431 typedef enum
11432 {
11433   GTK_TYPE_INVALID,
11434   GTK_TYPE_NONE,
11435   GTK_TYPE_CHAR,
11436   GTK_TYPE_BOOL,
11437   GTK_TYPE_INT,
11438   GTK_TYPE_UINT,
11439   GTK_TYPE_LONG,
11440   GTK_TYPE_ULONG,
11441   GTK_TYPE_FLOAT,
11442   GTK_TYPE_DOUBLE,
11443   GTK_TYPE_STRING,
11444   GTK_TYPE_ENUM,
11445   GTK_TYPE_FLAGS,
11446   GTK_TYPE_BOXED,
11447   GTK_TYPE_FOREIGN,
11448   GTK_TYPE_CALLBACK,
11449   GTK_TYPE_ARGS,
11450
11451   GTK_TYPE_POINTER,
11452
11453   /* it'd be great if the next two could be removed eventually */
11454   GTK_TYPE_SIGNAL,
11455   GTK_TYPE_C_CALLBACK,
11456
11457   GTK_TYPE_OBJECT
11458
11459 } GtkFundamentalType;
11460 </verb></tscreen>
11461
11462 <tt/gtk_signal_new()/ returns a unique integer identifier for the
11463 signal, that we store in the <tt/tictactoe_signals/ array, which we
11464 index using an enumeration. (Conventionally, the enumeration elements
11465 are the signal name, uppercased, but here there would be a conflict
11466 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
11467 instead.
11468
11469 After creating our signals, we need to tell GTK to associate our
11470 signals with the Tictactoe class. We do that by calling
11471 <tt/gtk_object_class_add_signals()/. We then set the pointer which
11472 points to the default handler for the `tictactoe' signal to NULL,
11473 indicating that there is no default action.
11474
11475 <!-- ----------------------------------------------------------------- -->
11476 <sect2> The <tt/_init()/ function.
11477 <p>
11478 Each widget class also needs a function to initialize the object
11479 structure. Usually, this function has the fairly limited role of
11480 setting the fields of the structure to default values. For composite
11481 widgets, however, this function also creates the component widgets.
11482
11483 <tscreen><verb>
11484 static void
11485 tictactoe_init (Tictactoe *ttt)
11486 {
11487   GtkWidget *table;
11488   gint i,j;
11489   
11490   table = gtk_table_new (3, 3, TRUE);
11491   gtk_container_add (GTK_CONTAINER(ttt), table);
11492   gtk_widget_show (table);
11493
11494   for (i=0;i<3; i++)
11495     for (j=0;j<3; j++)
11496       {
11497         ttt->buttons[i][j] = gtk_toggle_button_new ();
11498         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
11499                                    i, i+1, j, j+1);
11500         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
11501                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
11502         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
11503         gtk_widget_show (ttt->buttons[i][j]);
11504       }
11505 }
11506 </verb></tscreen>
11507
11508 <!-- ----------------------------------------------------------------- -->
11509 <sect2> And the rest...
11510 <p>
11511 There is one more function that every widget (except for base widget
11512 types like GtkBin that cannot be instantiated) needs to have - the
11513 function that the user calls to create an object of that type. This is
11514 conventionally called <tt/WIDGETNAME_new()/. In some
11515 widgets, though not for the Tictactoe widgets, this function takes
11516 arguments, and does some setup based on the arguments. The other two
11517 functions are specific to the Tictactoe widget. 
11518
11519 <tt/tictactoe_clear()/ is a public function that resets all the
11520 buttons in the widget to the up position. Note the use of
11521 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
11522 button toggles from being triggered unnecessarily.
11523
11524 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
11525 user clicks on a button. It checks to see if there are any winning
11526 combinations that involve the toggled button, and if so, emits
11527 the "tictactoe" signal.
11528
11529 <tscreen><verb>  
11530 GtkWidget*
11531 tictactoe_new ()
11532 {
11533   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
11534 }
11535
11536 void           
11537 tictactoe_clear (Tictactoe *ttt)
11538 {
11539   int i,j;
11540
11541   for (i=0;i<3;i++)
11542     for (j=0;j<3;j++)
11543       {
11544         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
11545         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
11546                                      FALSE);
11547         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
11548       }
11549 }
11550
11551 static void
11552 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
11553 {
11554   int i,k;
11555
11556   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11557                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11558                              { 0, 1, 2 }, { 0, 1, 2 } };
11559   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11560                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11561                              { 0, 1, 2 }, { 2, 1, 0 } };
11562
11563   int success, found;
11564
11565   for (k=0; k<8; k++)
11566     {
11567       success = TRUE;
11568       found = FALSE;
11569
11570       for (i=0;i<3;i++)
11571         {
11572           success = success &amp;&amp; 
11573             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
11574           found = found ||
11575             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
11576         }
11577       
11578       if (success &amp;&amp; found)
11579         {
11580           gtk_signal_emit (GTK_OBJECT (ttt), 
11581                            tictactoe_signals[TICTACTOE_SIGNAL]);
11582           break;
11583         }
11584     }
11585 }
11586 </verb></tscreen>
11587
11588 And finally, an example program using our Tictactoe widget:
11589
11590 <tscreen><verb>
11591 #include <gtk/gtk.h>
11592 #include "tictactoe.h"
11593
11594 /* Invoked when a row, column or diagonal is completed */
11595 void
11596 win (GtkWidget *widget, gpointer data)
11597 {
11598   g_print ("Yay!\n");
11599   tictactoe_clear (TICTACTOE (widget));
11600 }
11601
11602 int 
11603 main (int argc, char *argv[])
11604 {
11605   GtkWidget *window;
11606   GtkWidget *ttt;
11607   
11608   gtk_init (&amp;argc, &amp;argv);
11609
11610   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11611   
11612   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
11613   
11614   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11615                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11616   
11617   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11618
11619   /* Create a new Tictactoe widget */
11620   ttt = tictactoe_new ();
11621   gtk_container_add (GTK_CONTAINER (window), ttt);
11622   gtk_widget_show (ttt);
11623
11624   /* And attach to its "tictactoe" signal */
11625   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
11626                       GTK_SIGNAL_FUNC (win), NULL);
11627
11628   gtk_widget_show (window);
11629   
11630   gtk_main ();
11631   
11632   return 0;
11633 }
11634
11635 </verb></tscreen>
11636
11637 <!-- ----------------------------------------------------------------- -->
11638 <sect1> Creating a widget from scratch.
11639
11640 <!-- ----------------------------------------------------------------- -->
11641 <sect2> Introduction
11642 <p>
11643 In this section, we'll learn more about how widgets display themselves
11644 on the screen and interact with events. As an example of this, we'll
11645 create an analog dial widget with a pointer that the user can drag to
11646 set the value.
11647
11648 <!-- ----------------------------------------------------------------- -->
11649 <sect2> Displaying a widget on the screen
11650 <p>
11651 There are several steps that are involved in displaying on the screen.
11652 After the widget is created with a call to <tt/WIDGETNAME_new()/,
11653 several more functions are needed:
11654
11655 <itemize>
11656 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
11657 window for the widget if it has one.
11658 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
11659 <tt/gtk_widget_show()/. It is responsible for making sure the widget
11660 is actually drawn on the screen (<em/mapped/). For a container class,
11661 it must also make calls to <tt/map()/> functions of any child widgets.
11662 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
11663 is called for the widget or one of its ancestors. It makes the actual
11664 calls to the drawing functions to draw the widget on the screen. For
11665 container widgets, this function must make calls to
11666 <tt/gtk_widget_draw()/ for its child widgets.
11667 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
11668 widget. It makes the necessary calls to the drawing functions to draw
11669 the exposed portion on the screen. For container widgets, this
11670 function must generate expose events for its child widgets which don't
11671 have their own windows. (If they have their own windows, then X will
11672 generate the necessary expose events)
11673 </itemize>
11674
11675 You might notice that the last two functions are quite similar - each
11676 is responsible for drawing the widget on the screen. In fact many
11677 types of widgets don't really care about the difference between the
11678 two. The default <tt/draw()/ function in the widget class simply
11679 generates a synthetic expose event for the redrawn area. However, some
11680 types of widgets can save work by distinguishing between the two
11681 functions. For instance, if a widget has multiple X windows, then
11682 since expose events identify the exposed window, it can redraw only
11683 the affected window, which is not possible for calls to <tt/draw()/.
11684
11685 Container widgets, even if they don't care about the difference for
11686 themselves, can't simply use the default <tt/draw()/ function because
11687 their child widgets might care about the difference. However,
11688 it would be wasteful to duplicate the drawing code between the two
11689 functions. The convention is that such widgets have a function called
11690 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
11691 widget, that is then called by the <tt/draw()/ and <tt/expose()/
11692 functions.
11693
11694 In our example approach, since the dial widget is not a container
11695 widget, and only has a single window, we can take the simplest
11696 approach and use the default <tt/draw()/ function and only implement
11697 an <tt/expose()/ function.
11698
11699 <!-- ----------------------------------------------------------------- -->
11700 <sect2> The origins of the Dial Widget
11701 <p>
11702 Just as all land animals are just variants on the first amphibian that
11703 crawled up out of the mud, Gtk widgets tend to start off as variants
11704 of some other, previously written widget.  Thus, although this section
11705 is entitled `Creating a Widget from Scratch', the Dial widget really
11706 began with the source code for the Range widget. This was picked as a
11707 starting point because it would be nice if our Dial had the same
11708 interface as the Scale widgets which are just specialized descendents
11709 of the Range widget. So, though the source code is presented below in
11710 finished form, it should not be implied that it was written, <em>deus
11711 ex machina</em> in this fashion. Also, if you aren't yet familiar with
11712 how scale widgets work from the application writer's point of view, it
11713 would be a good idea to look them over before continuing.
11714
11715 <!-- ----------------------------------------------------------------- -->
11716 <sect2> The Basics
11717 <p>
11718 Quite a bit of our widget should look pretty familiar from the
11719 Tictactoe widget. First, we have a header file:
11720
11721 <tscreen><verb>
11722 /* GTK - The GIMP Toolkit
11723  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
11724  *
11725  * This library is free software; you can redistribute it and/or
11726  * modify it under the terms of the GNU Library General Public
11727  * License as published by the Free Software Foundation; either
11728  * version 2 of the License, or (at your option) any later version.
11729  *
11730  * This library is distributed in the hope that it will be useful,
11731  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11732  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11733  * Library General Public License for more details.
11734  *
11735  * You should have received a copy of the GNU Library General Public
11736  * License along with this library; if not, write to the Free
11737  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11738  */
11739
11740 #ifndef __GTK_DIAL_H__
11741 #define __GTK_DIAL_H__
11742
11743 #include <gdk/gdk.h>
11744 #include <gtk/gtkadjustment.h>
11745 #include <gtk/gtkwidget.h>
11746
11747
11748 #ifdef __cplusplus
11749 extern "C" {
11750 #endif /* __cplusplus */
11751
11752
11753 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
11754 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
11755 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
11756
11757
11758 typedef struct _GtkDial        GtkDial;
11759 typedef struct _GtkDialClass   GtkDialClass;
11760
11761 struct _GtkDial
11762 {
11763   GtkWidget widget;
11764
11765   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
11766   guint policy : 2;
11767
11768   /* Button currently pressed or 0 if none */
11769   guint8 button;
11770
11771   /* Dimensions of dial components */
11772   gint radius;
11773   gint pointer_width;
11774
11775   /* ID of update timer, or 0 if none */
11776   guint32 timer;
11777
11778   /* Current angle */
11779   gfloat angle;
11780
11781   /* Old values from adjustment stored so we know when something changes */
11782   gfloat old_value;
11783   gfloat old_lower;
11784   gfloat old_upper;
11785
11786   /* The adjustment object that stores the data for this dial */
11787   GtkAdjustment *adjustment;
11788 };
11789
11790 struct _GtkDialClass
11791 {
11792   GtkWidgetClass parent_class;
11793 };
11794
11795
11796 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
11797 guint          gtk_dial_get_type               (void);
11798 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
11799 void           gtk_dial_set_update_policy      (GtkDial      *dial,
11800                                                 GtkUpdateType  policy);
11801
11802 void           gtk_dial_set_adjustment         (GtkDial      *dial,
11803                                                 GtkAdjustment *adjustment);
11804 #ifdef __cplusplus
11805 }
11806 #endif /* __cplusplus */
11807
11808
11809 #endif /* __GTK_DIAL_H__ */
11810 </verb></tscreen>
11811
11812 Since there is quite a bit more going on in this widget, than the last
11813 one, we have more fields in the data structure, but otherwise things
11814 are pretty similar.
11815
11816 Next, after including header files, and declaring a few constants,
11817 we have some functions to provide information about the widget
11818 and initialize it:
11819
11820 <tscreen><verb>
11821 #include <math.h>
11822 #include <stdio.h>
11823 #include <gtk/gtkmain.h>
11824 #include <gtk/gtksignal.h>
11825
11826 #include "gtkdial.h"
11827
11828 #define SCROLL_DELAY_LENGTH  300
11829 #define DIAL_DEFAULT_SIZE 100
11830
11831 /* Forward declarations */
11832
11833 [ omitted to save space ]
11834
11835 /* Local data */
11836
11837 static GtkWidgetClass *parent_class = NULL;
11838
11839 guint
11840 gtk_dial_get_type ()
11841 {
11842   static guint dial_type = 0;
11843
11844   if (!dial_type)
11845     {
11846       GtkTypeInfo dial_info =
11847       {
11848         "GtkDial",
11849         sizeof (GtkDial),
11850         sizeof (GtkDialClass),
11851         (GtkClassInitFunc) gtk_dial_class_init,
11852         (GtkObjectInitFunc) gtk_dial_init,
11853         (GtkArgSetFunc) NULL,
11854         (GtkArgGetFunc) NULL,
11855       };
11856
11857       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
11858     }
11859
11860   return dial_type;
11861 }
11862
11863 static void
11864 gtk_dial_class_init (GtkDialClass *class)
11865 {
11866   GtkObjectClass *object_class;
11867   GtkWidgetClass *widget_class;
11868
11869   object_class = (GtkObjectClass*) class;
11870   widget_class = (GtkWidgetClass*) class;
11871
11872   parent_class = gtk_type_class (gtk_widget_get_type ());
11873
11874   object_class->destroy = gtk_dial_destroy;
11875
11876   widget_class->realize = gtk_dial_realize;
11877   widget_class->expose_event = gtk_dial_expose;
11878   widget_class->size_request = gtk_dial_size_request;
11879   widget_class->size_allocate = gtk_dial_size_allocate;
11880   widget_class->button_press_event = gtk_dial_button_press;
11881   widget_class->button_release_event = gtk_dial_button_release;
11882   widget_class->motion_notify_event = gtk_dial_motion_notify;
11883 }
11884
11885 static void
11886 gtk_dial_init (GtkDial *dial)
11887 {
11888   dial->button = 0;
11889   dial->policy = GTK_UPDATE_CONTINUOUS;
11890   dial->timer = 0;
11891   dial->radius = 0;
11892   dial->pointer_width = 0;
11893   dial->angle = 0.0;
11894   dial->old_value = 0.0;
11895   dial->old_lower = 0.0;
11896   dial->old_upper = 0.0;
11897   dial->adjustment = NULL;
11898 }
11899
11900 GtkWidget*
11901 gtk_dial_new (GtkAdjustment *adjustment)
11902 {
11903   GtkDial *dial;
11904
11905   dial = gtk_type_new (gtk_dial_get_type ());
11906
11907   if (!adjustment)
11908     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
11909
11910   gtk_dial_set_adjustment (dial, adjustment);
11911
11912   return GTK_WIDGET (dial);
11913 }
11914
11915 static void
11916 gtk_dial_destroy (GtkObject *object)
11917 {
11918   GtkDial *dial;
11919
11920   g_return_if_fail (object != NULL);
11921   g_return_if_fail (GTK_IS_DIAL (object));
11922
11923   dial = GTK_DIAL (object);
11924
11925   if (dial->adjustment)
11926     gtk_object_unref (GTK_OBJECT (dial->adjustment));
11927
11928   if (GTK_OBJECT_CLASS (parent_class)->destroy)
11929     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
11930 }
11931 </verb></tscreen>
11932
11933 Note that this <tt/init()/ function does less than for the Tictactoe
11934 widget, since this is not a composite widget, and the <tt/new()/
11935 function does more, since it now has an argument. Also, note that when
11936 we store a pointer to the Adjustment object, we increment its
11937 reference count, (and correspondingly decrement when we no longer use
11938 it) so that GTK can keep track of when it can be safely destroyed.
11939
11940 <p>
11941 Also, there are a few function to manipulate the widget's options:
11942
11943 <tscreen><verb>
11944 GtkAdjustment*
11945 gtk_dial_get_adjustment (GtkDial *dial)
11946 {
11947   g_return_val_if_fail (dial != NULL, NULL);
11948   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
11949
11950   return dial->adjustment;
11951 }
11952
11953 void
11954 gtk_dial_set_update_policy (GtkDial      *dial,
11955                              GtkUpdateType  policy)
11956 {
11957   g_return_if_fail (dial != NULL);
11958   g_return_if_fail (GTK_IS_DIAL (dial));
11959
11960   dial->policy = policy;
11961 }
11962
11963 void
11964 gtk_dial_set_adjustment (GtkDial      *dial,
11965                           GtkAdjustment *adjustment)
11966 {
11967   g_return_if_fail (dial != NULL);
11968   g_return_if_fail (GTK_IS_DIAL (dial));
11969
11970   if (dial->adjustment)
11971     {
11972       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
11973       gtk_object_unref (GTK_OBJECT (dial->adjustment));
11974     }
11975
11976   dial->adjustment = adjustment;
11977   gtk_object_ref (GTK_OBJECT (dial->adjustment));
11978
11979   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
11980                       (GtkSignalFunc) gtk_dial_adjustment_changed,
11981                       (gpointer) dial);
11982   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
11983                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
11984                       (gpointer) dial);
11985
11986   dial->old_value = adjustment->value;
11987   dial->old_lower = adjustment->lower;
11988   dial->old_upper = adjustment->upper;
11989
11990   gtk_dial_update (dial);
11991 }
11992 </verb></tscreen>
11993
11994 <sect2> <tt/gtk_dial_realize()/
11995
11996 <p>
11997 Now we come to some new types of functions. First, we have a function
11998 that does the work of creating the X window. Notice that a mask is
11999 passed to the function <tt/gdk_window_new()/ which specifies which fields of
12000 the GdkWindowAttr structure actually have data in them (the remaining
12001 fields will be given default values). Also worth noting is the way the
12002 event mask of the widget is created. We call
12003 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
12004 has specified for this widget (with <tt/gtk_widget_set_events()/, and
12005 add the events that we are interested in ourselves.
12006
12007 <p>
12008 After creating the window, we set its style and background, and put a
12009 pointer to the widget in the user data field of the GdkWindow. This
12010 last step allows GTK to dispatch events for this window to the correct
12011 widget.
12012
12013 <tscreen><verb>
12014 static void
12015 gtk_dial_realize (GtkWidget *widget)
12016 {
12017   GtkDial *dial;
12018   GdkWindowAttr attributes;
12019   gint attributes_mask;
12020
12021   g_return_if_fail (widget != NULL);
12022   g_return_if_fail (GTK_IS_DIAL (widget));
12023
12024   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
12025   dial = GTK_DIAL (widget);
12026
12027   attributes.x = widget->allocation.x;
12028   attributes.y = widget->allocation.y;
12029   attributes.width = widget->allocation.width;
12030   attributes.height = widget->allocation.height;
12031   attributes.wclass = GDK_INPUT_OUTPUT;
12032   attributes.window_type = GDK_WINDOW_CHILD;
12033   attributes.event_mask = gtk_widget_get_events (widget) | 
12034     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
12035     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
12036     GDK_POINTER_MOTION_HINT_MASK;
12037   attributes.visual = gtk_widget_get_visual (widget);
12038   attributes.colormap = gtk_widget_get_colormap (widget);
12039
12040   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
12041   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
12042
12043   widget->style = gtk_style_attach (widget->style, widget->window);
12044
12045   gdk_window_set_user_data (widget->window, widget);
12046
12047   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
12048 }
12049 </verb></tscreen>
12050
12051 <sect2> Size negotiation
12052
12053 <p>
12054 Before the first time that the window containing a widget is
12055 displayed, and whenever the layout of the window changes, GTK asks
12056 each child widget for its desired size. This request is handled by the
12057 function, <tt/gtk_dial_size_request()/. Since our widget isn't a
12058 container widget, and has no real constraints on its size, we just
12059 return a reasonable default value.
12060
12061 <tscreen><verb>
12062 static void 
12063 gtk_dial_size_request (GtkWidget      *widget,
12064                        GtkRequisition *requisition)
12065 {
12066   requisition->width = DIAL_DEFAULT_SIZE;
12067   requisition->height = DIAL_DEFAULT_SIZE;
12068 }
12069 </verb></tscreen>
12070
12071 <p>
12072 After all the widgets have requested an ideal size, the layout of the
12073 window is computed and each child widget is notified of its actual
12074 size. Usually, this will at least as large as the requested size, but
12075 if for instance, the user has resized the window, it may occasionally
12076 be smaller than the requested size. The size notification is handled
12077 by the function <tt/gtk_dial_size_allocate()/. Notice that as well as
12078 computing the sizes of some component pieces for future use, this
12079 routine also does the grunt work of moving the widgets X window into
12080 the new position and size.
12081
12082 <tscreen><verb>
12083 static void
12084 gtk_dial_size_allocate (GtkWidget     *widget,
12085                         GtkAllocation *allocation)
12086 {
12087   GtkDial *dial;
12088
12089   g_return_if_fail (widget != NULL);
12090   g_return_if_fail (GTK_IS_DIAL (widget));
12091   g_return_if_fail (allocation != NULL);
12092
12093   widget->allocation = *allocation;
12094   if (GTK_WIDGET_REALIZED (widget))
12095     {
12096       dial = GTK_DIAL (widget);
12097
12098       gdk_window_move_resize (widget->window,
12099                               allocation->x, allocation->y,
12100                               allocation->width, allocation->height);
12101
12102       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
12103       dial->pointer_width = dial->radius / 5;
12104     }
12105 }
12106 </verb></tscreen>.
12107
12108 <!-- ----------------------------------------------------------------- -->
12109 <sect2> <tt/gtk_dial_expose()/
12110
12111 <p>
12112 As mentioned above, all the drawing of this widget is done in the
12113 handler for expose events. There's not much to remark on here except
12114 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
12115 three dimensional shading according to the colors stored in the
12116 widget's style.
12117
12118 <tscreen><verb>
12119 static gint
12120 gtk_dial_expose (GtkWidget      *widget,
12121                  GdkEventExpose *event)
12122 {
12123   GtkDial *dial;
12124   GdkPoint points[3];
12125   gdouble s,c;
12126   gdouble theta;
12127   gint xc, yc;
12128   gint tick_length;
12129   gint i;
12130
12131   g_return_val_if_fail (widget != NULL, FALSE);
12132   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12133   g_return_val_if_fail (event != NULL, FALSE);
12134
12135   if (event->count > 0)
12136     return FALSE;
12137   
12138   dial = GTK_DIAL (widget);
12139
12140   gdk_window_clear_area (widget->window,
12141                          0, 0,
12142                          widget->allocation.width,
12143                          widget->allocation.height);
12144
12145   xc = widget->allocation.width/2;
12146   yc = widget->allocation.height/2;
12147
12148   /* Draw ticks */
12149
12150   for (i=0; i<25; i++)
12151     {
12152       theta = (i*M_PI/18. - M_PI/6.);
12153       s = sin(theta);
12154       c = cos(theta);
12155
12156       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
12157       
12158       gdk_draw_line (widget->window,
12159                      widget->style->fg_gc[widget->state],
12160                      xc + c*(dial->radius - tick_length),
12161                      yc - s*(dial->radius - tick_length),
12162                      xc + c*dial->radius,
12163                      yc - s*dial->radius);
12164     }
12165
12166   /* Draw pointer */
12167
12168   s = sin(dial->angle);
12169   c = cos(dial->angle);
12170
12171
12172   points[0].x = xc + s*dial->pointer_width/2;
12173   points[0].y = yc + c*dial->pointer_width/2;
12174   points[1].x = xc + c*dial->radius;
12175   points[1].y = yc - s*dial->radius;
12176   points[2].x = xc - s*dial->pointer_width/2;
12177   points[2].y = yc - c*dial->pointer_width/2;
12178
12179   gtk_draw_polygon (widget->style,
12180                     widget->window,
12181                     GTK_STATE_NORMAL,
12182                     GTK_SHADOW_OUT,
12183                     points, 3,
12184                     TRUE);
12185   
12186   return FALSE;
12187 }
12188 </verb></tscreen>
12189
12190 <!-- ----------------------------------------------------------------- -->
12191 <sect2> Event handling
12192
12193 <p>
12194
12195 The rest of the widget's code handles various types of events, and
12196 isn't too different from what would be found in many GTK
12197 applications. Two types of events can occur - either the user can
12198 click on the widget with the mouse and drag to move the pointer, or
12199 the value of the Adjustment object can change due to some external
12200 circumstance. 
12201
12202 <p>
12203 When the user clicks on the widget, we check to see if the click was
12204 appropriately near the pointer, and if so, store then button that the
12205 user clicked with in the <tt/button/ field of the widget
12206 structure, and grab all mouse events with a call to
12207 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
12208 value of the control to be recomputed (by the function
12209 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
12210 set, "value_changed" events are either generated instantly
12211 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
12212 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
12213 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
12214
12215 <tscreen><verb>
12216 static gint
12217 gtk_dial_button_press (GtkWidget      *widget,
12218                        GdkEventButton *event)
12219 {
12220   GtkDial *dial;
12221   gint dx, dy;
12222   double s, c;
12223   double d_parallel;
12224   double d_perpendicular;
12225
12226   g_return_val_if_fail (widget != NULL, FALSE);
12227   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12228   g_return_val_if_fail (event != NULL, FALSE);
12229
12230   dial = GTK_DIAL (widget);
12231
12232   /* Determine if button press was within pointer region - we 
12233      do this by computing the parallel and perpendicular distance of
12234      the point where the mouse was pressed from the line passing through
12235      the pointer */
12236   
12237   dx = event->x - widget->allocation.width / 2;
12238   dy = widget->allocation.height / 2 - event->y;
12239   
12240   s = sin(dial->angle);
12241   c = cos(dial->angle);
12242   
12243   d_parallel = s*dy + c*dx;
12244   d_perpendicular = fabs(s*dx - c*dy);
12245   
12246   if (!dial->button &&
12247       (d_perpendicular < dial->pointer_width/2) &&
12248       (d_parallel > - dial->pointer_width))
12249     {
12250       gtk_grab_add (widget);
12251
12252       dial->button = event->button;
12253
12254       gtk_dial_update_mouse (dial, event->x, event->y);
12255     }
12256
12257   return FALSE;
12258 }
12259
12260 static gint
12261 gtk_dial_button_release (GtkWidget      *widget,
12262                           GdkEventButton *event)
12263 {
12264   GtkDial *dial;
12265
12266   g_return_val_if_fail (widget != NULL, FALSE);
12267   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12268   g_return_val_if_fail (event != NULL, FALSE);
12269
12270   dial = GTK_DIAL (widget);
12271
12272   if (dial->button == event->button)
12273     {
12274       gtk_grab_remove (widget);
12275
12276       dial->button = 0;
12277
12278       if (dial->policy == GTK_UPDATE_DELAYED)
12279         gtk_timeout_remove (dial->timer);
12280       
12281       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
12282           (dial->old_value != dial->adjustment->value))
12283         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12284     }
12285
12286   return FALSE;
12287 }
12288
12289 static gint
12290 gtk_dial_motion_notify (GtkWidget      *widget,
12291                          GdkEventMotion *event)
12292 {
12293   GtkDial *dial;
12294   GdkModifierType mods;
12295   gint x, y, mask;
12296
12297   g_return_val_if_fail (widget != NULL, FALSE);
12298   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12299   g_return_val_if_fail (event != NULL, FALSE);
12300
12301   dial = GTK_DIAL (widget);
12302
12303   if (dial->button != 0)
12304     {
12305       x = event->x;
12306       y = event->y;
12307
12308       if (event->is_hint || (event->window != widget->window))
12309         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
12310
12311       switch (dial->button)
12312         {
12313         case 1:
12314           mask = GDK_BUTTON1_MASK;
12315           break;
12316         case 2:
12317           mask = GDK_BUTTON2_MASK;
12318           break;
12319         case 3:
12320           mask = GDK_BUTTON3_MASK;
12321           break;
12322         default:
12323           mask = 0;
12324           break;
12325         }
12326
12327       if (mods & mask)
12328         gtk_dial_update_mouse (dial, x,y);
12329     }
12330
12331   return FALSE;
12332 }
12333
12334 static gint
12335 gtk_dial_timer (GtkDial *dial)
12336 {
12337   g_return_val_if_fail (dial != NULL, FALSE);
12338   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
12339
12340   if (dial->policy == GTK_UPDATE_DELAYED)
12341     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12342
12343   return FALSE;
12344 }
12345
12346 static void
12347 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
12348 {
12349   gint xc, yc;
12350   gfloat old_value;
12351
12352   g_return_if_fail (dial != NULL);
12353   g_return_if_fail (GTK_IS_DIAL (dial));
12354
12355   xc = GTK_WIDGET(dial)->allocation.width / 2;
12356   yc = GTK_WIDGET(dial)->allocation.height / 2;
12357
12358   old_value = dial->adjustment->value;
12359   dial->angle = atan2(yc-y, x-xc);
12360
12361   if (dial->angle < -M_PI/2.)
12362     dial->angle += 2*M_PI;
12363
12364   if (dial->angle < -M_PI/6)
12365     dial->angle = -M_PI/6;
12366
12367   if (dial->angle > 7.*M_PI/6.)
12368     dial->angle = 7.*M_PI/6.;
12369
12370   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
12371     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
12372
12373   if (dial->adjustment->value != old_value)
12374     {
12375       if (dial->policy == GTK_UPDATE_CONTINUOUS)
12376         {
12377           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12378         }
12379       else
12380         {
12381           gtk_widget_draw (GTK_WIDGET(dial), NULL);
12382
12383           if (dial->policy == GTK_UPDATE_DELAYED)
12384             {
12385               if (dial->timer)
12386                 gtk_timeout_remove (dial->timer);
12387
12388               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
12389                                              (GtkFunction) gtk_dial_timer,
12390                                              (gpointer) dial);
12391             }
12392         }
12393     }
12394 }
12395 </verb></tscreen>
12396
12397 <p>
12398 Changes to the Adjustment by external means are communicated to our
12399 widget by the `changed' and `value_changed' signals. The handlers
12400 for these functions call <tt/gtk_dial_update()/ to validate the
12401 arguments, compute the new pointer angle, and redraw the widget (by
12402 calling <tt/gtk_widget_draw()/).
12403
12404 <tscreen><verb>
12405 static void
12406 gtk_dial_update (GtkDial *dial)
12407 {
12408   gfloat new_value;
12409   
12410   g_return_if_fail (dial != NULL);
12411   g_return_if_fail (GTK_IS_DIAL (dial));
12412
12413   new_value = dial->adjustment->value;
12414   
12415   if (new_value < dial->adjustment->lower)
12416     new_value = dial->adjustment->lower;
12417
12418   if (new_value > dial->adjustment->upper)
12419     new_value = dial->adjustment->upper;
12420
12421   if (new_value != dial->adjustment->value)
12422     {
12423       dial->adjustment->value = new_value;
12424       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12425     }
12426
12427   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
12428     (dial->adjustment->upper - dial->adjustment->lower);
12429
12430   gtk_widget_draw (GTK_WIDGET(dial), NULL);
12431 }
12432
12433 static void
12434 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
12435                               gpointer       data)
12436 {
12437   GtkDial *dial;
12438
12439   g_return_if_fail (adjustment != NULL);
12440   g_return_if_fail (data != NULL);
12441
12442   dial = GTK_DIAL (data);
12443
12444   if ((dial->old_value != adjustment->value) ||
12445       (dial->old_lower != adjustment->lower) ||
12446       (dial->old_upper != adjustment->upper))
12447     {
12448       gtk_dial_update (dial);
12449
12450       dial->old_value = adjustment->value;
12451       dial->old_lower = adjustment->lower;
12452       dial->old_upper = adjustment->upper;
12453     }
12454 }
12455
12456 static void
12457 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
12458                                     gpointer       data)
12459 {
12460   GtkDial *dial;
12461
12462   g_return_if_fail (adjustment != NULL);
12463   g_return_if_fail (data != NULL);
12464
12465   dial = GTK_DIAL (data);
12466
12467   if (dial->old_value != adjustment->value)
12468     {
12469       gtk_dial_update (dial);
12470
12471       dial->old_value = adjustment->value;
12472     }
12473 }
12474 </verb></tscreen>
12475
12476 <!-- ----------------------------------------------------------------- -->
12477 <sect2> Possible Enhancements
12478 <p>
12479
12480 The Dial widget as we've described it so far runs about 670 lines of
12481 code. Although that might sound like a fair bit, we've really
12482 accomplished quite a bit with that much code, especially since much of
12483 that length is headers and boilerplate. However, there are quite a few
12484 more enhancements that could be made to this widget:
12485
12486 <itemize>
12487 <item> If you try this widget out, you'll find that there is some
12488 flashing as the pointer is dragged around. This is because the entire
12489 widget is erased every time the pointer is moved before being
12490 redrawn. Often, the best way to handle this problem is to draw to an
12491 offscreen pixmap, then copy the final results onto the screen in one
12492 step. (The ProgressBar widget draws itself in this fashion.)
12493
12494 <item> The user should be able to use the up and down arrow keys to
12495 increase and decrease the value.
12496
12497 <item> It would be nice if the widget had buttons to increase and
12498 decrease the value in small or large steps. Although it would be
12499 possible to use embedded Button widgets for this, we would also like
12500 the buttons to auto-repeat when held down, as the arrows on a
12501 scrollbar do. Most of the code to implement this type of behavior can
12502 be found in the GtkRange widget.
12503
12504 <item> The Dial widget could be made into a container widget with a
12505 single child widget positioned at the bottom between the buttons
12506 mentioned above. The user could then add their choice of a label or
12507 entry widget to display the current value of the dial.
12508
12509 </itemize>
12510
12511 <!-- ----------------------------------------------------------------- -->
12512 <sect1> Learning More
12513
12514 <p>
12515 Only a small part of the many details involved in creating widgets
12516 could be described above. If you want to write your own widgets, the
12517 best source of examples is the GTK source itself. Ask yourself some
12518 questions about the widget you want to write: is it a Container
12519 widget? does it have its own window? is it a modification of an
12520 existing widget? Then find a similar widget, and start making changes.
12521 Good luck!
12522
12523 <!-- ***************************************************************** -->
12524 <sect>Scribble, A Simple Example Drawing Program
12525 <!-- ***************************************************************** -->
12526
12527 <!-- ----------------------------------------------------------------- -->
12528 <sect1> Overview
12529
12530 <p>
12531 In this section, we will build a simple drawing program. In the
12532 process, we will examine how to handle mouse events, how to draw in a
12533 window, and how to do drawing better by using a backing pixmap. After
12534 creating the simple drawing program, we will extend it by adding
12535 support for XInput devices, such as drawing tablets. GTK provides
12536 support routines which makes getting extended information, such as
12537 pressure and tilt, from such devices quite easy.
12538
12539 <!-- ----------------------------------------------------------------- -->
12540 <sect1> Event Handling
12541
12542 <p>
12543 The GTK signals we have already discussed are for high-level actions,
12544 such as a menu item being selected. However, sometimes it is useful to
12545 learn about lower-level occurrences, such as the mouse being moved, or
12546 a key being pressed. There are also GTK signals corresponding to these
12547 low-level <em>events</em>. The handlers for these signals have an
12548 extra parameter which is a pointer to a structure containing
12549 information about the event. For instance, motion events handlers are
12550 passed a pointer to a GdkEventMotion structure which looks (in part)
12551 like:
12552
12553 <tscreen><verb>
12554 struct _GdkEventMotion
12555 {
12556   GdkEventType type;
12557   GdkWindow *window;
12558   guint32 time;
12559   gdouble x;
12560   gdouble y;
12561   ...
12562   guint state;
12563   ...
12564 };
12565 </verb></tscreen>
12566
12567 <tt/type/ will be set to the event type, in this case
12568 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
12569 occurred. <tt/x/ and <tt/y/ give the coordinates of the event,
12570 and <tt/state/ specifies the modifier state when the event
12571 occurred (that is, it specifies which modifier keys and mouse buttons
12572 were pressed.) It is the bitwise OR of some of the following:
12573
12574 <tscreen><verb>
12575 GDK_SHIFT_MASK  
12576 GDK_LOCK_MASK   
12577 GDK_CONTROL_MASK
12578 GDK_MOD1_MASK   
12579 GDK_MOD2_MASK   
12580 GDK_MOD3_MASK   
12581 GDK_MOD4_MASK   
12582 GDK_MOD5_MASK   
12583 GDK_BUTTON1_MASK
12584 GDK_BUTTON2_MASK
12585 GDK_BUTTON3_MASK
12586 GDK_BUTTON4_MASK
12587 GDK_BUTTON5_MASK
12588 </verb></tscreen>
12589
12590 <p>
12591 As for other signals, to determine what happens when an event occurs
12592 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
12593 know which events we want to be notified about. To do this, we call
12594 the function:
12595
12596 <tscreen><verb>
12597 void gtk_widget_set_events (GtkWidget *widget,
12598                             gint      events);
12599 </verb></tscreen>
12600
12601 The second field specifies the events we are interested in. It
12602 is the bitwise OR of constants that specify different types
12603 of events. For future reference the event types are:
12604
12605 <tscreen><verb>
12606 GDK_EXPOSURE_MASK
12607 GDK_POINTER_MOTION_MASK
12608 GDK_POINTER_MOTION_HINT_MASK
12609 GDK_BUTTON_MOTION_MASK     
12610 GDK_BUTTON1_MOTION_MASK    
12611 GDK_BUTTON2_MOTION_MASK    
12612 GDK_BUTTON3_MOTION_MASK    
12613 GDK_BUTTON_PRESS_MASK      
12614 GDK_BUTTON_RELEASE_MASK    
12615 GDK_KEY_PRESS_MASK         
12616 GDK_KEY_RELEASE_MASK       
12617 GDK_ENTER_NOTIFY_MASK      
12618 GDK_LEAVE_NOTIFY_MASK      
12619 GDK_FOCUS_CHANGE_MASK      
12620 GDK_STRUCTURE_MASK         
12621 GDK_PROPERTY_CHANGE_MASK   
12622 GDK_PROXIMITY_IN_MASK      
12623 GDK_PROXIMITY_OUT_MASK     
12624 </verb></tscreen>
12625
12626 There are a few subtle points that have to be observed when calling
12627 <tt/gtk_widget_set_events()/. First, it must be called before the X window
12628 for a GTK widget is created. In practical terms, this means you
12629 should call it immediately after creating the widget. Second, the
12630 widget must have an associated X window. For efficiency, many widget
12631 types do not have their own window, but draw in their parent's window.
12632 These widgets are:
12633
12634 <tscreen><verb>
12635 GtkAlignment
12636 GtkArrow
12637 GtkBin
12638 GtkBox
12639 GtkImage
12640 GtkItem
12641 GtkLabel
12642 GtkPixmap
12643 GtkScrolledWindow
12644 GtkSeparator
12645 GtkTable
12646 GtkAspectFrame
12647 GtkFrame
12648 GtkVBox
12649 GtkHBox
12650 GtkVSeparator
12651 GtkHSeparator
12652 </verb></tscreen>
12653
12654 To capture events for these widgets, you need to use an EventBox
12655 widget. See the section on the <ref id="sec_EventBox"
12656 name="EventBox"> widget for details.
12657
12658 <p>
12659 For our drawing program, we want to know when the mouse button is
12660 pressed and when the mouse is moved, so we specify
12661 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
12662 want to know when we need to redraw our window, so we specify
12663 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
12664 Configure event when our window size changes, we don't have to specify
12665 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
12666 automatically specified for all windows.
12667
12668 <p>
12669 It turns out, however, that there is a problem with just specifying
12670 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
12671 motion event to the event queue every time the user moves the mouse.
12672 Imagine that it takes us 0.1 seconds to handle a motion event, but the
12673 X server queues a new motion event every 0.05 seconds. We will soon
12674 get way behind the users drawing. If the user draws for 5 seconds,
12675 it will take us another 5 seconds to catch up after they release 
12676 the mouse button! What we would like is to only get one motion
12677 event for each event we process. The way to do this is to 
12678 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
12679
12680 <p>
12681 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
12682 us a motion event the first time the pointer moves after entering
12683 our window, or after a button press or release event. Subsequent 
12684 motion events will be suppressed until we explicitly ask for
12685 the position of the pointer using the function:
12686
12687 <tscreen><verb>
12688 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
12689                                           gint            *x,
12690                                           gint            *y,
12691                                           GdkModifierType *mask);
12692 </verb></tscreen>
12693
12694 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
12695 has a simpler interface, but turns out not to be very useful, since
12696 it only retrieves the position of the mouse, not whether the buttons
12697 are pressed.)
12698
12699 <p>
12700 The code to set the events for our window then looks like:
12701
12702 <tscreen><verb>
12703   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
12704                       (GtkSignalFunc) expose_event, NULL);
12705   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
12706                       (GtkSignalFunc) configure_event, NULL);
12707   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
12708                       (GtkSignalFunc) motion_notify_event, NULL);
12709   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
12710                       (GtkSignalFunc) button_press_event, NULL);
12711
12712   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
12713                          | GDK_LEAVE_NOTIFY_MASK
12714                          | GDK_BUTTON_PRESS_MASK
12715                          | GDK_POINTER_MOTION_MASK
12716                          | GDK_POINTER_MOTION_HINT_MASK);
12717 </verb></tscreen>
12718
12719 We'll save the "expose_event" and "configure_event" handlers for
12720 later. The "motion_notify_event" and "button_press_event" handlers
12721 pretty simple:
12722
12723 <tscreen><verb>
12724 static gint
12725 button_press_event (GtkWidget *widget, GdkEventButton *event)
12726 {
12727   if (event->button == 1 &amp;&amp; pixmap != NULL)
12728       draw_brush (widget, event->x, event->y);
12729
12730   return TRUE;
12731 }
12732
12733 static gint
12734 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
12735 {
12736   int x, y;
12737   GdkModifierType state;
12738
12739   if (event->is_hint)
12740     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
12741   else
12742     {
12743       x = event->x;
12744       y = event->y;
12745       state = event->state;
12746     }
12747     
12748   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
12749     draw_brush (widget, x, y);
12750   
12751   return TRUE;
12752 }
12753 </verb></tscreen>
12754
12755 <!-- ----------------------------------------------------------------- -->
12756 <sect1> The DrawingArea Widget, And Drawing
12757
12758 <p>
12759 We know turn to the process of drawing on the screen. The 
12760 widget we use for this is the DrawingArea widget. A drawing area
12761 widget is essentially an X window and nothing more. It is a blank
12762 canvas in which we can draw whatever we like. A drawing area
12763 is created using the call:
12764
12765 <tscreen><verb>
12766 GtkWidget* gtk_drawing_area_new        (void);
12767 </verb></tscreen>
12768
12769 A default size for the widget can be specified by calling:
12770
12771 <tscreen><verb>
12772 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
12773                                         gint                 width,
12774                                         gint                 height);
12775 </verb></tscreen>
12776
12777 This default size can be overridden, as is true for all widgets,
12778 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
12779 be overridden if the user manually resizes the the window containing
12780 the drawing area.
12781
12782 <p>
12783 It should be noted that when we create a DrawingArea widget, we are,
12784 <em>completely</em> responsible for drawing the contents. If our
12785 window is obscured then uncovered, we get an exposure event and must
12786 redraw what was previously hidden.
12787
12788 <p>
12789 Having to remember everything that was drawn on the screen so we
12790 can properly redraw it can, to say the least, be a nuisance. In
12791 addition, it can be visually distracting if portions of the
12792 window are cleared, then redrawn step by step. The solution to
12793 this problem is to use an offscreen <em>backing pixmap</em>.
12794 Instead of drawing directly to the screen, we draw to an image
12795 stored in server memory but not displayed, then when the image
12796 changes or new portions of the image are displayed, we copy the
12797 relevant portions onto the screen.
12798
12799 <p>
12800 To create an offscreen pixmap, we call the function:
12801
12802 <tscreen><verb>
12803 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
12804                                          gint        width,
12805                                          gint        height,
12806                                          gint        depth);
12807 </verb></tscreen>
12808
12809 The <tt>window</tt> parameter specifies a GDK window that this pixmap
12810 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
12811 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
12812 depth</em>, that is the number of bits per pixel, for the new window.
12813 If the depth is specified as <tt>-1</tt>, it will match the depth
12814 of <tt>window</tt>.
12815
12816 <p>
12817 We create the pixmap in our "configure_event" handler. This event
12818 is generated whenever the window changes size, including when it
12819 is originally created.
12820
12821 <tscreen><verb>
12822 /* Backing pixmap for drawing area */
12823 static GdkPixmap *pixmap = NULL;
12824
12825 /* Create a new backing pixmap of the appropriate size */
12826 static gint
12827 configure_event (GtkWidget *widget, GdkEventConfigure *event)
12828 {
12829   if (pixmap)
12830     gdk_pixmap_unref(pixmap);
12831
12832   pixmap = gdk_pixmap_new(widget->window,
12833                           widget->allocation.width,
12834                           widget->allocation.height,
12835                           -1);
12836   gdk_draw_rectangle (pixmap,
12837                       widget->style->white_gc,
12838                       TRUE,
12839                       0, 0,
12840                       widget->allocation.width,
12841                       widget->allocation.height);
12842
12843   return TRUE;
12844 }
12845 </verb></tscreen>
12846
12847 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
12848 initially to white. We'll say more about that in a moment.
12849
12850 <p>
12851 Our exposure event handler then simply copies the relevant portion
12852 of the pixmap onto the screen (we determine the area we need
12853 to redraw by using the event->area field of the exposure event):
12854
12855 <tscreen><verb>
12856 /* Redraw the screen from the backing pixmap */
12857 static gint
12858 expose_event (GtkWidget *widget, GdkEventExpose *event)
12859 {
12860   gdk_draw_pixmap(widget->window,
12861                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
12862                   pixmap,
12863                   event->area.x, event->area.y,
12864                   event->area.x, event->area.y,
12865                   event->area.width, event->area.height);
12866
12867   return FALSE;
12868 }
12869 </verb></tscreen>
12870
12871 We've now seen how to keep the screen up to date with our pixmap, but
12872 how do we actually draw interesting stuff on our pixmap?  There are a
12873 large number of calls in GTK's GDK library for drawing on
12874 <em>drawables</em>. A drawable is simply something that can be drawn
12875 upon. It can be a window, a pixmap, or a bitmap (a black and white
12876 image).  We've already seen two such calls above,
12877 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
12878 complete list is:
12879
12880 <tscreen><verb>
12881 gdk_draw_line ()
12882 gdk_draw_rectangle ()
12883 gdk_draw_arc ()
12884 gdk_draw_polygon ()
12885 gdk_draw_string ()
12886 gdk_draw_text ()
12887 gdk_draw_pixmap ()
12888 gdk_draw_bitmap ()
12889 gdk_draw_image ()
12890 gdk_draw_points ()
12891 gdk_draw_segments ()
12892 </verb></tscreen>
12893
12894 See the reference documentation or the header file
12895 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
12896 These functions all share the same first two arguments. The first
12897 argument is the drawable to draw upon, the second argument is a
12898 <em>graphics context</em> (GC). 
12899
12900 <p>
12901 A graphics context encapsulates information about things such as
12902 foreground and background color and line width. GDK has a full set of
12903 functions for creating and modifying graphics contexts, but to keep
12904 things simple we'll just use predefined graphics contexts. Each widget
12905 has an associated style. (Which can be modified in a gtkrc file, see
12906 the section GTK's rc file.) This, among other things, stores a number
12907 of graphics contexts. Some examples of accessing these graphics
12908 contexts are:
12909
12910 <tscreen><verb>
12911 widget->style->white_gc
12912 widget->style->black_gc
12913 widget->style->fg_gc[GTK_STATE_NORMAL]
12914 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
12915 </verb></tscreen>
12916
12917 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
12918 <tt>light_gc</tt> are indexed by a parameter of type
12919 <tt>GtkStateType</tt> which can take on the values:
12920
12921 <tscreen><verb>
12922 GTK_STATE_NORMAL,
12923 GTK_STATE_ACTIVE,
12924 GTK_STATE_PRELIGHT,
12925 GTK_STATE_SELECTED,
12926 GTK_STATE_INSENSITIVE
12927 </verb></tscreen>
12928
12929 For instance, the for <tt/GTK_STATE_SELECTED/ the default foreground
12930 color is white and the default background color, dark blue.
12931
12932 <p>
12933 Our function <tt>draw_brush()</tt>, which does the actual drawing
12934 on the screen, is then:
12935
12936 <tscreen><verb>
12937 /* Draw a rectangle on the screen */
12938 static void
12939 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
12940 {
12941   GdkRectangle update_rect;
12942
12943   update_rect.x = x - 5;
12944   update_rect.y = y - 5;
12945   update_rect.width = 10;
12946   update_rect.height = 10;
12947   gdk_draw_rectangle (pixmap,
12948                       widget->style->black_gc,
12949                       TRUE,
12950                       update_rect.x, update_rect.y,
12951                       update_rect.width, update_rect.height);
12952   gtk_widget_draw (widget, &amp;update_rect);
12953 }
12954 </verb></tscreen>
12955
12956 After we draw the rectangle representing the brush onto the pixmap,
12957 we call the function:
12958
12959 <tscreen><verb>
12960 void       gtk_widget_draw                (GtkWidget           *widget,
12961                                            GdkRectangle        *area);
12962 </verb></tscreen>
12963
12964 which notifies X that the area given by the <tt>area</tt> parameter
12965 needs to be updated. X will eventually generate an expose event
12966 (possibly combining the areas passed in several calls to
12967 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
12968 to copy the relevant portions to the screen.
12969
12970 <p>
12971 We have now covered the entire drawing program except for a few
12972 mundane details like creating the main window. The complete
12973 source code is available from the location from which you got
12974 this tutorial, or from:
12975
12976 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12977 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12978
12979
12980 <!-- ----------------------------------------------------------------- -->
12981 <sect1> Adding XInput support
12982
12983 <p>
12984
12985 It is now possible to buy quite inexpensive input devices such 
12986 as drawing tablets, which allow drawing with a much greater
12987 ease of artistic expression than does a mouse. The simplest way
12988 to use such devices is simply as a replacement for the mouse,
12989 but that misses out many of the advantages of these devices,
12990 such as:
12991
12992 <itemize>
12993 <item> Pressure sensitivity
12994 <item> Tilt reporting
12995 <item> Sub-pixel positioning
12996 <item> Multiple inputs (for example, a stylus with a point and eraser)
12997 </itemize>
12998
12999 For information about the XInput extension, see the <htmlurl
13000 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13001 name="XInput-HOWTO">.
13002
13003 <p>
13004 If we examine the full definition of, for example, the GdkEventMotion
13005 structure, we see that it has fields to support extended device
13006 information.
13007
13008 <tscreen><verb>
13009 struct _GdkEventMotion
13010 {
13011   GdkEventType type;
13012   GdkWindow *window;
13013   guint32 time;
13014   gdouble x;
13015   gdouble y;
13016   gdouble pressure;
13017   gdouble xtilt;
13018   gdouble ytilt;
13019   guint state;
13020   gint16 is_hint;
13021   GdkInputSource source;
13022   guint32 deviceid;
13023 };
13024 </verb></tscreen>
13025
13026 <tt/pressure/ gives the pressure as a floating point number between
13027 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
13028 -1 and 1, corresponding to the degree of tilt in each direction.
13029 <tt/source/ and <tt/deviceid/ specify the device for which the
13030 event occurred in two different ways. <tt/source/ gives some simple
13031 information about the type of device. It can take the enumeration
13032 values.
13033
13034 <tscreen><verb>
13035 GDK_SOURCE_MOUSE
13036 GDK_SOURCE_PEN
13037 GDK_SOURCE_ERASER
13038 GDK_SOURCE_CURSOR
13039 </verb></tscreen>
13040
13041 <tt/deviceid/ specifies a unique numeric ID for the device. This can
13042 be used to find out further information about the device using the
13043 <tt/gdk_input_list_devices()/ call (see below). The special value
13044 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
13045 the mouse.)
13046
13047 <sect2> Enabling extended device information
13048
13049 <p>
13050 To let GTK know about our interest in the extended device information,
13051 we merely have to add a single line to our program:
13052
13053 <tscreen><verb>
13054 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
13055 </verb></tscreen>
13056
13057 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
13058 we are interested in extension events, but only if we don't have
13059 to draw our own cursor. See the section <ref
13060 id="sec_Further_Sophistications" name="Further Sophistications"> below
13061 for more information about drawing the cursor. We could also 
13062 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
13063 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
13064 back to the default condition.
13065
13066 <p>
13067 This is not completely the end of the story however. By default,
13068 no extension devices are enabled. We need a mechanism to allow
13069 users to enable and configure their extension devices. GTK provides
13070 the InputDialog widget to automate this process. The following
13071 procedure manages an InputDialog widget. It creates the dialog if
13072 it isn't present, and raises it to the top otherwise.
13073
13074 <tscreen><verb>
13075 void
13076 input_dialog_destroy (GtkWidget *w, gpointer data)
13077 {
13078   *((GtkWidget **)data) = NULL;
13079 }
13080
13081 void
13082 create_input_dialog ()
13083 {
13084   static GtkWidget *inputd = NULL;
13085
13086   if (!inputd)
13087     {
13088       inputd = gtk_input_dialog_new();
13089
13090       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
13091                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
13092       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
13093                                  "clicked",
13094                                  (GtkSignalFunc)gtk_widget_hide,
13095                                  GTK_OBJECT(inputd));
13096       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
13097
13098       gtk_widget_show (inputd);
13099     }
13100   else
13101     {
13102       if (!GTK_WIDGET_MAPPED(inputd))
13103         gtk_widget_show(inputd);
13104       else
13105         gdk_window_raise(inputd->window);
13106     }
13107 }
13108 </verb></tscreen>
13109
13110 (You might want to take note of the way we handle this dialog.  By
13111 connecting to the "destroy" signal, we make sure that we don't keep a
13112 pointer to dialog around after it is destroyed - that could lead to a
13113 segfault.)
13114
13115 <p>
13116 The InputDialog has two buttons "Close" and "Save", which by default
13117 have no actions assigned to them. In the above function we make
13118 "Close" hide the dialog, hide the "Save" button, since we don't
13119 implement saving of XInput options in this program.
13120
13121 <sect2> Using extended device information
13122
13123 <p>
13124 Once we've enabled the device, we can just use the extended 
13125 device information in the extra fields of the event structures.
13126 In fact, it is always safe to use this information since these
13127 fields will have reasonable default values even when extended
13128 events are not enabled.
13129
13130 <p>
13131 Once change we do have to make is to call
13132 <tt/gdk_input_window_get_pointer()/ instead of
13133 <tt/gdk_window_get_pointer/. This is necessary because
13134 <tt/gdk_window_get_pointer/ doesn't return the extended device
13135 information.
13136
13137 <tscreen><verb>
13138 void gdk_input_window_get_pointer     (GdkWindow       *window,
13139                                        guint32         deviceid,
13140                                        gdouble         *x,
13141                                        gdouble         *y,
13142                                        gdouble         *pressure,
13143                                        gdouble         *xtilt,
13144                                        gdouble         *ytilt,
13145                                        GdkModifierType *mask);
13146 </verb></tscreen>
13147
13148 When calling this function, we need to specify the device ID as
13149 well as the window. Usually, we'll get the device ID from the
13150 <tt/deviceid/ field of an event structure. Again, this function
13151 will return reasonable values when extension events are not
13152 enabled. (In this case, <tt/event->deviceid/ will have the value
13153 <tt/GDK_CORE_POINTER/).
13154
13155 So the basic structure of our button-press and motion event handlers,
13156 doesn't change much - we just need to add code to deal with the
13157 extended information.
13158
13159 <tscreen><verb>
13160 static gint
13161 button_press_event (GtkWidget *widget, GdkEventButton *event)
13162 {
13163   print_button_press (event->deviceid);
13164   
13165   if (event->button == 1 &amp;&amp; pixmap != NULL)
13166     draw_brush (widget, event->source, event->x, event->y, event->pressure);
13167
13168   return TRUE;
13169 }
13170
13171 static gint
13172 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13173 {
13174   gdouble x, y;
13175   gdouble pressure;
13176   GdkModifierType state;
13177
13178   if (event->is_hint)
13179     gdk_input_window_get_pointer (event->window, event->deviceid,
13180                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
13181   else
13182     {
13183       x = event->x;
13184       y = event->y;
13185       pressure = event->pressure;
13186       state = event->state;
13187     }
13188     
13189   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13190     draw_brush (widget, event->source, x, y, pressure);
13191   
13192   return TRUE;
13193 }
13194 </verb></tscreen>
13195
13196 We also need to do something with the new information. Our new
13197 <tt/draw_brush()/ function draws with a different color for
13198 each <tt/event->source/ and changes the brush size depending
13199 on the pressure.
13200
13201 <tscreen><verb>
13202 /* Draw a rectangle on the screen, size depending on pressure,
13203    and color on the type of device */
13204 static void
13205 draw_brush (GtkWidget *widget, GdkInputSource source,
13206             gdouble x, gdouble y, gdouble pressure)
13207 {
13208   GdkGC *gc;
13209   GdkRectangle update_rect;
13210
13211   switch (source)
13212     {
13213     case GDK_SOURCE_MOUSE:
13214       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
13215       break;
13216     case GDK_SOURCE_PEN:
13217       gc = widget->style->black_gc;
13218       break;
13219     case GDK_SOURCE_ERASER:
13220       gc = widget->style->white_gc;
13221       break;
13222     default:
13223       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
13224     }
13225
13226   update_rect.x = x - 10 * pressure;
13227   update_rect.y = y - 10 * pressure;
13228   update_rect.width = 20 * pressure;
13229   update_rect.height = 20 * pressure;
13230   gdk_draw_rectangle (pixmap, gc, TRUE,
13231                       update_rect.x, update_rect.y,
13232                       update_rect.width, update_rect.height);
13233   gtk_widget_draw (widget, &amp;update_rect);
13234 }
13235 </verb></tscreen>
13236
13237 <sect2> Finding out more about a device
13238
13239 <p>
13240 As an example of how to find out more about a device, our program
13241 will print the name of the device that generates each button
13242 press. To find out the name of a device, we call the function:
13243
13244 <tscreen><verb>
13245 GList *gdk_input_list_devices               (void);
13246 </verb></tscreen>
13247
13248 which returns a GList (a linked list type from the glib library)
13249 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
13250 as:
13251
13252 <tscreen><verb>
13253 struct _GdkDeviceInfo
13254 {
13255   guint32 deviceid;
13256   gchar *name;
13257   GdkInputSource source;
13258   GdkInputMode mode;
13259   gint has_cursor;
13260   gint num_axes;
13261   GdkAxisUse *axes;
13262   gint num_keys;
13263   GdkDeviceKey *keys;
13264 };
13265 </verb></tscreen>
13266
13267 Most of these fields are configuration information that you
13268 can ignore unless you are implemented XInput configuration
13269 saving. The we are interested in here is <tt/name/ which is
13270 simply the name that X assigns to the device. The other field
13271 that isn't configuration information is <tt/has_cursor/. If
13272 <tt/has_cursor/ is false, then we we need to draw our own
13273 cursor. But since we've specified <tt/GDK_EXTENSION_EVENTS_CURSOR/,
13274 we don't have to worry about this.
13275
13276 <p>
13277 Our <tt/print_button_press()/ function simply iterates through
13278 the returned list until it finds a match, then prints out
13279 the name of the device.
13280
13281 <tscreen><verb>
13282 static void
13283 print_button_press (guint32 deviceid)
13284 {
13285   GList *tmp_list;
13286
13287   /* gdk_input_list_devices returns an internal list, so we shouldn't
13288      free it afterwards */
13289   tmp_list = gdk_input_list_devices();
13290
13291   while (tmp_list)
13292     {
13293       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
13294
13295       if (info->deviceid == deviceid)
13296         {
13297           printf("Button press on device '%s'\n", info->name);
13298           return;
13299         }
13300
13301       tmp_list = tmp_list->next;
13302     }
13303 }
13304 </verb></tscreen>
13305
13306 That completes the changes to `XInputize' our program. As with
13307 the first version, the complete source is available at the location
13308 from which you got this tutorial, or from:
13309
13310 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13311 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13312
13313
13314 <sect2> Further sophistications <label id="sec_Further_Sophistications">
13315
13316 <p>
13317 Although our program now supports XInput quite well, it lacks some
13318 features we would want in a full-featured application. First, the user
13319 probably doesn't want to have to configure their device each time they
13320 run the program, so we should allow them to save the device
13321 configuration. This is done by iterating through the return of
13322 <tt/gdk_input_list_devices()/ and writing out the configuration to a
13323 file.
13324
13325 <p>
13326 To restore the state next time the program is run, GDK provides
13327 functions to change device configuration:
13328
13329 <tscreen><verb>
13330 gdk_input_set_extension_events()
13331 gdk_input_set_source()
13332 gdk_input_set_mode()
13333 gdk_input_set_axes()
13334 gdk_input_set_key()
13335 </verb></tscreen>
13336
13337 (The list returned from <tt/gdk_input_list_devices()/ should not be
13338 modified directly.) An example of doing this can be found in the
13339 drawing program gsumi. (Available from <htmlurl
13340 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
13341 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
13342 would be nice to have a standard way of doing this for all
13343 applications. This probably belongs at a slightly higher level than
13344 GTK, perhaps in the GNOME library.
13345
13346 <p>
13347 Another major omission that we have mentioned above is the lack of
13348 cursor drawing. Platforms other than XFree86 currently do not allow
13349 simultaneously using a device as both the core pointer and directly by
13350 an application. See the <url
13351 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13352 name="XInput-HOWTO"> for more information about this. This means that
13353 applications that want to support the widest audience need to draw
13354 their own cursor.
13355
13356 <p>
13357 An application that draws its own cursor needs to do two things:
13358 determine if the current device needs a cursor drawn or not, and
13359 determine if the current device is in proximity. (If the current
13360 device is a drawing tablet, it's a nice touch to make the cursor 
13361 disappear when the stylus is lifted from the tablet. When the
13362 device is touching the stylus, that is called "in proximity.")
13363 The first is done by searching the device list, as we did
13364 to find out the device name. The second is achieved by selecting
13365 "proximity_out" events. An example of drawing one's own cursor is
13366 found in the 'testinput' program found in the GTK distribution.
13367
13368 <!-- ***************************************************************** -->
13369 <sect>Tips For Writing GTK Applications
13370 <!-- ***************************************************************** -->
13371
13372 <p>
13373 This section is simply a gathering of wisdom, general style guidelines
13374 and hints to creating good GTK applications. It is totally useless
13375 right now cause its only a topic sentence :)
13376
13377 Use GNU autoconf and automake!  They are your friends :) I am planning
13378 to make a quick intro on them here.
13379
13380 <!-- ***************************************************************** -->
13381 <sect>Contributing <label id="sec_Contributing">
13382 <!-- ***************************************************************** -->
13383
13384 <p>
13385 This document, like so much other great software out there, was
13386 created for free by volunteers.  If you are at all knowledgeable about
13387 any aspect of GTK that does not already have documentation, please
13388 consider contributing to this document.
13389 <p>
13390 If you do decide to contribute, please mail your text to Tony Gale,
13391 <tt><htmlurl url="mailto:gale@gtk.org"
13392 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
13393 document is free, and any addition by you provide must also be
13394 free. That is, people may use any portion of your examples in their
13395 programs, and copies of this document may be distributed at will etc.
13396 <p>
13397 Thank you.
13398
13399 <!-- ***************************************************************** -->
13400 <sect>Credits
13401 <!-- ***************************************************************** -->
13402 <p>
13403 I would like to thank the following for their contributions to this text.
13404
13405 <itemize>
13406 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
13407 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
13408
13409 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
13410 name="raph@acm.org"></tt>
13411 for hello world ala GTK, widget packing, and general all around wisdom.
13412 He's also generously donated a home for this tutorial.
13413
13414 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
13415 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
13416 and the ability to make it :)
13417
13418 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
13419 name="werner.koch@guug.de"></tt> for converting the original plain text to
13420 SGML, and the widget class hierarchy.
13421
13422 <item>Mark Crichton <tt><htmlurl
13423 url="mailto:crichton@expert.cc.purdue.edu"
13424 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
13425 and the table packing tutorial.
13426
13427 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
13428 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
13429 patch to the distro).  He's also responsible for the selections code
13430 and tutorial, as well as the sections on writing your own GTK widgets,
13431 and the example application. Thanks a lot Owen for all you help!
13432
13433 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
13434 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
13435 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
13436 lot Mark!  You've been a great help.
13437
13438 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
13439 name="timj@psynet.net"></tt> for his great job on the Lists
13440 Widget. His excellent work on automatically extracting the widget tree
13441 and signal information from GTK. Thanks Tim :)
13442
13443 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
13444 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
13445 tutorial.
13446
13447 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
13448 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
13449
13450 <item>David Huggins-Daines <tt><htmlurl
13451 url="mailto:bn711@freenet.carleton.ca"
13452 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
13453 Widget sections.
13454
13455 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
13456 name="mars@lysator.liu.se"></tt> for the GtkCList section
13457 </itemize>
13458
13459 And to all of you who commented and helped refine this document.
13460
13461 Thanks.
13462
13463 <!-- ***************************************************************** -->
13464 <sect> Tutorial Copyright and Permissions Notice
13465 <!-- ***************************************************************** -->
13466
13467 <p>
13468 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
13469
13470 Copyright (C) 1998-1999 Tony Gale.
13471
13472 Permission is granted to make and distribute verbatim copies of this 
13473 manual provided the copyright notice and this permission notice are 
13474 preserved on all copies.
13475
13476 Permission is granted to copy and distribute modified versions of 
13477 this document under the conditions for verbatim copying, provided that 
13478 this copyright notice is included exactly as in the original,
13479 and that the entire resulting derived work is distributed under 
13480 the terms of a permission notice identical to this one.
13481 <P>Permission is granted to copy and distribute translations of this 
13482 document into another language, under the above conditions for modified 
13483 versions.
13484
13485 If you are intending to incorporate this document into a published 
13486 work, please contact the maintainer, and we will make an effort 
13487 to ensure that you have the most up to date information available.
13488
13489 There is no guarantee that this document lives up to its intended
13490 purpose.  This is simply provided as a free resource.  As such,
13491 the authors and maintainers of the information provided within can
13492 not make any guarantee that the information is even accurate.
13493
13494 <!-- ***************************************************************** -->
13495 <appendix>
13496 <!-- ***************************************************************** -->
13497
13498 <!-- ***************************************************************** -->
13499 <sect> GTK Signals <label id="sec_GTK_Signals">
13500 <!-- ***************************************************************** -->
13501 <p>
13502 As GTK is an object oriented widget set, it has a hierarchy of
13503 inheritance. This inheritance mechanism applies for
13504 signals. Therefore, you should refer to the widget hierarchy tree when
13505 using the signals listed in this section.
13506
13507 <!-- ----------------------------------------------------------------- -->
13508 <sect1>GtkObject
13509 <!-- ----------------------------------------------------------------- -->
13510 <p>
13511 <tscreen><verb>
13512 void GtkObject::destroy (GtkObject *,
13513                          gpointer);
13514 </verb></tscreen>
13515
13516 <!-- ----------------------------------------------------------------- -->
13517 <sect1>GtkWidget
13518 <!-- ----------------------------------------------------------------- -->
13519 <p>
13520 <tscreen><verb>
13521
13522 void GtkWidget::show    (GtkWidget *,
13523                          gpointer);
13524 void GtkWidget::hide    (GtkWidget *,
13525                          gpointer);
13526 void GtkWidget::map     (GtkWidget *,
13527                          gpointer);
13528 void GtkWidget::unmap   (GtkWidget *,
13529                          gpointer);
13530 void GtkWidget::realize (GtkWidget *,
13531                          gpointer);
13532 void GtkWidget::unrealize       (GtkWidget *,
13533                                  gpointer);
13534 void GtkWidget::draw    (GtkWidget *,
13535                          ggpointer,
13536                          gpointer);
13537 void GtkWidget::draw-focus      (GtkWidget *,
13538                                  gpointer);
13539 void GtkWidget::draw-default    (GtkWidget *,
13540                                  gpointer);
13541 void GtkWidget::size-request    (GtkWidget *,
13542                                  ggpointer,
13543                                  gpointer);
13544 void GtkWidget::size-allocate   (GtkWidget *,
13545                                  ggpointer,
13546                                  gpointer);
13547 void GtkWidget::state-changed   (GtkWidget *,
13548                                  GtkStateType,
13549                                  gpointer);
13550 void GtkWidget::parent-set      (GtkWidget *,
13551                                  GtkObject *,
13552                                  gpointer);
13553 void GtkWidget::style-set       (GtkWidget *,
13554                                  GtkStyle *,
13555                                  gpointer);
13556 void GtkWidget::add-accelerator (GtkWidget *,
13557                                  gguint,
13558                                  GtkAccelGroup *,
13559                                  gguint,
13560                                  GdkModifierType,
13561                                  GtkAccelFlags,
13562                                  gpointer);
13563 void GtkWidget::remove-accelerator      (GtkWidget *,
13564                                          GtkAccelGroup *,
13565                                          gguint,
13566                                          GdkModifierType,
13567                                          gpointer);
13568 gboolean GtkWidget::event       (GtkWidget *,
13569                                  GdkEvent *,
13570                                  gpointer);
13571 gboolean GtkWidget::button-press-event  (GtkWidget *,
13572                                          GdkEvent *,
13573                                          gpointer);
13574 gboolean GtkWidget::button-release-event        (GtkWidget *,
13575                                                  GdkEvent *,
13576                                                  gpointer);
13577 gboolean GtkWidget::motion-notify-event (GtkWidget *,
13578                                          GdkEvent *,
13579                                          gpointer);
13580 gboolean GtkWidget::delete-event        (GtkWidget *,
13581                                          GdkEvent *,
13582                                          gpointer);
13583 gboolean GtkWidget::destroy-event       (GtkWidget *,
13584                                          GdkEvent *,
13585                                          gpointer);
13586 gboolean GtkWidget::expose-event        (GtkWidget *,
13587                                          GdkEvent *,
13588                                          gpointer);
13589 gboolean GtkWidget::key-press-event     (GtkWidget *,
13590                                          GdkEvent *,
13591                                          gpointer);
13592 gboolean GtkWidget::key-release-event   (GtkWidget *,
13593                                          GdkEvent *,
13594                                          gpointer);
13595 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
13596                                          GdkEvent *,
13597                                          gpointer);
13598 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
13599                                          GdkEvent *,
13600                                          gpointer);
13601 gboolean GtkWidget::configure-event     (GtkWidget *,
13602                                          GdkEvent *,
13603                                          gpointer);
13604 gboolean GtkWidget::focus-in-event      (GtkWidget *,
13605                                          GdkEvent *,
13606                                          gpointer);
13607 gboolean GtkWidget::focus-out-event     (GtkWidget *,
13608                                          GdkEvent *,
13609                                          gpointer);
13610 gboolean GtkWidget::map-event   (GtkWidget *,
13611                                  GdkEvent *,
13612                                  gpointer);
13613 gboolean GtkWidget::unmap-event (GtkWidget *,
13614                                  GdkEvent *,
13615                                  gpointer);
13616 gboolean GtkWidget::property-notify-event       (GtkWidget *,
13617                                                  GdkEvent *,
13618                                                  gpointer);
13619 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
13620                                                  GdkEvent *,
13621                                                  gpointer);
13622 gboolean GtkWidget::selection-request-event     (GtkWidget *,
13623                                                  GdkEvent *,
13624                                                  gpointer);
13625 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
13626                                                  GdkEvent *,
13627                                                  gpointer);
13628 void GtkWidget::selection-get   (GtkWidget *,
13629                                  GtkSelectionData *,
13630                                  gguint,
13631                                  gpointer);
13632 void GtkWidget::selection-received      (GtkWidget *,
13633                                          GtkSelectionData *,
13634                                          gguint,
13635                                          gpointer);
13636 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
13637                                          GdkEvent *,
13638                                          gpointer);
13639 gboolean GtkWidget::proximity-out-event (GtkWidget *,
13640                                          GdkEvent *,
13641                                          gpointer);
13642 void GtkWidget::drag-begin      (GtkWidget *,
13643                                  GdkDragContext *,
13644                                  gpointer);
13645 void GtkWidget::drag-end        (GtkWidget *,
13646                                  GdkDragContext *,
13647                                  gpointer);
13648 void GtkWidget::drag-data-delete        (GtkWidget *,
13649                                          GdkDragContext *,
13650                                          gpointer);
13651 void GtkWidget::drag-leave      (GtkWidget *,
13652                                  GdkDragContext *,
13653                                  gguint,
13654                                  gpointer);
13655 gboolean GtkWidget::drag-motion (GtkWidget *,
13656                                  GdkDragContext *,
13657                                  ggint,
13658                                  ggint,
13659                                  gguint,
13660                                  gpointer);
13661 gboolean GtkWidget::drag-drop   (GtkWidget *,
13662                                  GdkDragContext *,
13663                                  ggint,
13664                                  ggint,
13665                                  gguint,
13666                                  gpointer);
13667 void GtkWidget::drag-data-get   (GtkWidget *,
13668                                  GdkDragContext *,
13669                                  GtkSelectionData *,
13670                                  gguint,
13671                                  gguint,
13672                                  gpointer);
13673 void GtkWidget::drag-data-received      (GtkWidget *,
13674                                          GdkDragContext *,
13675                                          ggint,
13676                                          ggint,
13677                                          GtkSelectionData *,
13678                                          gguint,
13679                                          gguint,
13680                                          gpointer);
13681 gboolean GtkWidget::client-event        (GtkWidget *,
13682                                          GdkEvent *,
13683                                          gpointer);
13684 gboolean GtkWidget::no-expose-event     (GtkWidget *,
13685                                          GdkEvent *,
13686                                          gpointer);
13687 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
13688                                                  GdkEvent *,
13689                                                  gpointer);
13690 void GtkWidget::debug-msg       (GtkWidget *,
13691                                  GtkString *,
13692                                  gpointer);
13693 </verb></tscreen>
13694
13695 <!-- ----------------------------------------------------------------- -->
13696 <sect1>GtkData
13697 <!-- ----------------------------------------------------------------- -->
13698 <p>
13699 <tscreen><verb>
13700 void GtkData::disconnect        (GtkData *,
13701                                  gpointer);
13702 </verb></tscreen>
13703
13704 <!-- ----------------------------------------------------------------- -->
13705 <sect1>GtkContainer
13706 <!-- ----------------------------------------------------------------- -->
13707 <p>
13708 <tscreen><verb>
13709 void GtkContainer::add  (GtkContainer *,
13710                          GtkWidget *,
13711                          gpointer);
13712 void GtkContainer::remove       (GtkContainer *,
13713                                  GtkWidget *,
13714                                  gpointer);
13715 void GtkContainer::check-resize (GtkContainer *,
13716                                  gpointer);
13717 GtkDirectionType GtkContainer::focus    (GtkContainer *,
13718                                          GtkDirectionType,
13719                                          gpointer);
13720 void GtkContainer::set-focus-child      (GtkContainer *,
13721                                          GtkWidget *,
13722                                          gpointer);
13723 </verb></tscreen>
13724
13725 <!-- ----------------------------------------------------------------- -->
13726 <sect1>GtkCalendar
13727 <!-- ----------------------------------------------------------------- -->
13728 <p>
13729 <tscreen><verb>
13730 void GtkCalendar::month-changed (GtkCalendar *,
13731                                  gpointer);
13732 void GtkCalendar::day-selected  (GtkCalendar *,
13733                                  gpointer);
13734 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
13735                                                  gpointer);
13736 void GtkCalendar::prev-month    (GtkCalendar *,
13737                                  gpointer);
13738 void GtkCalendar::next-month    (GtkCalendar *,
13739                                  gpointer);
13740 void GtkCalendar::prev-year     (GtkCalendar *,
13741                                  gpointer);
13742 void GtkCalendar::next-year     (GtkCalendar *,
13743                                  gpointer);
13744 </verb></tscreen>
13745
13746 <!-- ----------------------------------------------------------------- -->
13747 <sect1>GtkEditable
13748 <!-- ----------------------------------------------------------------- -->
13749 <p>
13750 <tscreen><verb>
13751 void GtkEditable::changed       (GtkEditable *,
13752                                  gpointer);
13753 void GtkEditable::insert-text   (GtkEditable *,
13754                                  GtkString *,
13755                                  ggint,
13756                                  ggpointer,
13757                                  gpointer);
13758 void GtkEditable::delete-text   (GtkEditable *,
13759                                  ggint,
13760                                  ggint,
13761                                  gpointer);
13762 void GtkEditable::activate      (GtkEditable *,
13763                                  gpointer);
13764 void GtkEditable::set-editable  (GtkEditable *,
13765                                  gboolean,
13766                                  gpointer);
13767 void GtkEditable::move-cursor   (GtkEditable *,
13768                                  ggint,
13769                                  ggint,
13770                                  gpointer);
13771 void GtkEditable::move-word     (GtkEditable *,
13772                                  ggint,
13773                                  gpointer);
13774 void GtkEditable::move-page     (GtkEditable *,
13775                                  ggint,
13776                                  ggint,
13777                                  gpointer);
13778 void GtkEditable::move-to-row   (GtkEditable *,
13779                                  ggint,
13780                                  gpointer);
13781 void GtkEditable::move-to-column        (GtkEditable *,
13782                                          ggint,
13783                                          gpointer);
13784 void GtkEditable::kill-char     (GtkEditable *,
13785                                  ggint,
13786                                  gpointer);
13787 void GtkEditable::kill-word     (GtkEditable *,
13788                                  ggint,
13789                                  gpointer);
13790 void GtkEditable::kill-line     (GtkEditable *,
13791                                  ggint,
13792                                  gpointer);
13793 void GtkEditable::cut-clipboard (GtkEditable *,
13794                                  gpointer);
13795 void GtkEditable::copy-clipboard        (GtkEditable *,
13796                                          gpointer);
13797 void GtkEditable::paste-clipboard       (GtkEditable *,
13798                                          gpointer);
13799 </verb></tscreen>
13800
13801 <!-- ----------------------------------------------------------------- -->
13802 <sect1>GtkTipsQuery
13803 <!-- ----------------------------------------------------------------- -->
13804 <p>
13805 <tscreen><verb>
13806 void GtkTipsQuery::start-query  (GtkTipsQuery *,
13807                                  gpointer);
13808 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
13809                                  gpointer);
13810 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
13811                                          GtkWidget *,
13812                                          GtkString *,
13813                                          GtkString *,
13814                                          gpointer);
13815 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
13816                                          GtkWidget *,
13817                                          GtkString *,
13818                                          GtkString *,
13819                                          GdkEvent *,
13820                                          gpointer);
13821 </verb></tscreen>
13822
13823 <!-- ----------------------------------------------------------------- -->
13824 <sect1>GtkCList
13825 <!-- ----------------------------------------------------------------- -->
13826 <p>
13827 <tscreen><verb>
13828 void GtkCList::select-row       (GtkCList *,
13829                                  ggint,
13830                                  ggint,
13831                                  GdkEvent *,
13832                                  gpointer);
13833 void GtkCList::unselect-row     (GtkCList *,
13834                                  ggint,
13835                                  ggint,
13836                                  GdkEvent *,
13837                                  gpointer);
13838 void GtkCList::row-move (GtkCList *,
13839                          ggint,
13840                          ggint,
13841                          gpointer);
13842 void GtkCList::click-column     (GtkCList *,
13843                                  ggint,
13844                                  gpointer);
13845 void GtkCList::resize-column    (GtkCList *,
13846                                  ggint,
13847                                  ggint,
13848                                  gpointer);
13849 void GtkCList::toggle-focus-row (GtkCList *,
13850                                  gpointer);
13851 void GtkCList::select-all       (GtkCList *,
13852                                  gpointer);
13853 void GtkCList::unselect-all     (GtkCList *,
13854                                  gpointer);
13855 void GtkCList::undo-selection   (GtkCList *,
13856                                  gpointer);
13857 void GtkCList::start-selection  (GtkCList *,
13858                                  gpointer);
13859 void GtkCList::end-selection    (GtkCList *,
13860                                  gpointer);
13861 void GtkCList::toggle-add-mode  (GtkCList *,
13862                                  gpointer);
13863 void GtkCList::extend-selection (GtkCList *,
13864                                  GtkScrollType,
13865                                  ggfloat,
13866                                  gboolean,
13867                                  gpointer);
13868 void GtkCList::scroll-vertical  (GtkCList *,
13869                                  GtkScrollType,
13870                                  ggfloat,
13871                                  gpointer);
13872 void GtkCList::scroll-horizontal        (GtkCList *,
13873                                          GtkScrollType,
13874                                          ggfloat,
13875                                          gpointer);
13876 void GtkCList::abort-column-resize      (GtkCList *,
13877                                          gpointer);
13878 </verb></tscreen>
13879
13880 <!-- ----------------------------------------------------------------- -->
13881 <sect1>GtkNotebook
13882 <!-- ----------------------------------------------------------------- -->
13883 <p>
13884 <tscreen><verb>
13885 void GtkNotebook::switch-page   (GtkNotebook *,
13886                                  ggpointer,
13887                                  gguint,
13888                                  gpointer);
13889
13890 </verb></tscreen>
13891
13892 <!-- ----------------------------------------------------------------- -->
13893 <sect1>GtkList
13894 <!-- ----------------------------------------------------------------- -->
13895 <p>
13896 <tscreen><verb>
13897 void GtkList::selection-changed (GtkList *,
13898                                  gpointer);
13899 void GtkList::select-child      (GtkList *,
13900                                  GtkWidget *,
13901                                  gpointer);
13902 void GtkList::unselect-child    (GtkList *,
13903                                  GtkWidget *,
13904                                  gpointer);
13905 </verb></tscreen>
13906
13907 <!-- ----------------------------------------------------------------- -->
13908 <sect1>GtkMenuShell
13909 <!-- ----------------------------------------------------------------- -->
13910 <p>
13911 <tscreen><verb>
13912 void GtkMenuShell::deactivate   (GtkMenuShell *,
13913                                  gpointer);
13914 void GtkMenuShell::selection-done       (GtkMenuShell *,
13915                                          gpointer);
13916 void GtkMenuShell::move-current (GtkMenuShell *,
13917                                  GtkMenuDirectionType,
13918                                  gpointer);
13919 void GtkMenuShell::activate-current     (GtkMenuShell *,
13920                                          gboolean,
13921                                          gpointer);
13922 void GtkMenuShell::cancel       (GtkMenuShell *,
13923                                  gpointer);
13924 </verb></tscreen>
13925
13926 <!-- ----------------------------------------------------------------- -->
13927 <sect1>GtkToolbar
13928 <!-- ----------------------------------------------------------------- -->
13929 <p>
13930 <tscreen><verb>
13931 void GtkToolbar::orientation-changed    (GtkToolbar *,
13932                                          ggint,
13933                                          gpointer);
13934 void GtkToolbar::style-changed  (GtkToolbar *,
13935                                  ggint,
13936                                  gpointer);
13937 </verb></tscreen>
13938
13939 <!-- ----------------------------------------------------------------- -->
13940 <sect1>GtkTree
13941 <!-- ----------------------------------------------------------------- -->
13942 <p>
13943 <tscreen><verb>
13944 void GtkTree::selection-changed (GtkTree *,
13945                                  gpointer);
13946 void GtkTree::select-child      (GtkTree *,
13947                                  GtkWidget *,
13948                                  gpointer);
13949 void GtkTree::unselect-child    (GtkTree *,
13950                                  GtkWidget *,
13951                                  gpointer);
13952 </verb></tscreen>
13953
13954 <!-- ----------------------------------------------------------------- -->
13955 <sect1>GtkButton
13956 <!-- ----------------------------------------------------------------- -->
13957 <p>
13958 <tscreen><verb>
13959 void GtkButton::pressed (GtkButton *,
13960                          gpointer);
13961 void GtkButton::released        (GtkButton *,
13962                                  gpointer);
13963 void GtkButton::clicked (GtkButton *,
13964                          gpointer);
13965 void GtkButton::enter   (GtkButton *,
13966                          gpointer);
13967 void GtkButton::leave   (GtkButton *,
13968                          gpointer);
13969 </verb></tscreen>
13970
13971 <!-- ----------------------------------------------------------------- -->
13972 <sect1>GtkItem
13973 <!-- ----------------------------------------------------------------- -->
13974 <p>
13975 <tscreen><verb>
13976 void GtkItem::select    (GtkItem *,
13977                          gpointer);
13978 void GtkItem::deselect  (GtkItem *,
13979                          gpointer);
13980 void GtkItem::toggle    (GtkItem *,
13981                          gpointer);
13982 </verb></tscreen>
13983
13984 <!-- ----------------------------------------------------------------- -->
13985 <sect1>GtkWindow
13986 <!-- ----------------------------------------------------------------- -->
13987 <p>
13988 <tscreen><verb>
13989 void GtkWindow::set-focus       (GtkWindow *,
13990                                  ggpointer,
13991                                  gpointer);
13992 </verb></tscreen>
13993
13994 <!-- ----------------------------------------------------------------- -->
13995 <sect1>GtkHandleBox
13996 <!-- ----------------------------------------------------------------- -->
13997 <p>
13998 <tscreen><verb>
13999 void GtkHandleBox::child-attached       (GtkHandleBox *,
14000                                          GtkWidget *,
14001                                          gpointer);
14002 void GtkHandleBox::child-detached       (GtkHandleBox *,
14003                                          GtkWidget *,
14004                                          gpointer);
14005 </verb></tscreen>
14006
14007 <!-- ----------------------------------------------------------------- -->
14008 <sect1>GtkToggleButton
14009 <!-- ----------------------------------------------------------------- -->
14010 <p>
14011 <tscreen><verb>
14012 void GtkToggleButton::toggled   (GtkToggleButton *,
14013                                  gpointer);
14014
14015 </verb></tscreen>
14016
14017 <!-- ----------------------------------------------------------------- -->
14018 <sect1>GtkMenuItem
14019 <!-- ----------------------------------------------------------------- -->
14020 <p>
14021 <tscreen><verb>
14022 void GtkMenuItem::activate      (GtkMenuItem *,
14023                                  gpointer);
14024 void GtkMenuItem::activate-item (GtkMenuItem *,
14025                                  gpointer);
14026 </verb></tscreen>
14027
14028 <!-- ----------------------------------------------------------------- -->
14029 <sect1>GtkListItem
14030 <!-- ----------------------------------------------------------------- -->
14031 <p>
14032 <tscreen><verb>
14033 void GtkListItem::toggle-focus-row      (GtkListItem *,
14034                                          gpointer);
14035 void GtkListItem::select-all    (GtkListItem *,
14036                                  gpointer);
14037 void GtkListItem::unselect-all  (GtkListItem *,
14038                                  gpointer);
14039 void GtkListItem::undo-selection        (GtkListItem *,
14040                                          gpointer);
14041 void GtkListItem::start-selection       (GtkListItem *,
14042                                          gpointer);
14043 void GtkListItem::end-selection (GtkListItem *,
14044                                  gpointer);
14045 void GtkListItem::toggle-add-mode       (GtkListItem *,
14046                                          gpointer);
14047 void GtkListItem::extend-selection      (GtkListItem *,
14048                                          GtkEnum,
14049                                          ggfloat,
14050                                          gboolean,
14051                                          gpointer);
14052 void GtkListItem::scroll-vertical       (GtkListItem *,
14053                                          GtkEnum,
14054                                          ggfloat,
14055                                          gpointer);
14056 void GtkListItem::scroll-horizontal     (GtkListItem *,
14057                                          GtkEnum,
14058                                          ggfloat,
14059                                          gpointer);
14060 </verb></tscreen>
14061
14062 <!-- ----------------------------------------------------------------- -->
14063 <sect1>GtkTreeItem
14064 <!-- ----------------------------------------------------------------- -->
14065 <p>
14066 <tscreen><verb>
14067 void GtkTreeItem::collapse      (GtkTreeItem *,
14068                                  gpointer);
14069 void GtkTreeItem::expand        (GtkTreeItem *,
14070                                  gpointer);
14071 </verb></tscreen>
14072
14073 <!-- ----------------------------------------------------------------- -->
14074 <sect1>GtkCheckMenuItem
14075 <!-- ----------------------------------------------------------------- -->
14076 <p>
14077 <tscreen><verb>
14078 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
14079                                  gpointer);
14080 </verb></tscreen>
14081
14082 <!-- ----------------------------------------------------------------- -->
14083 <sect1>GtkInputDialog
14084 <!-- ----------------------------------------------------------------- -->
14085 <p>
14086 <tscreen><verb>
14087 void GtkInputDialog::enable-device      (GtkInputDialog *,
14088                                          ggint,
14089                                          gpointer);
14090 void GtkInputDialog::disable-device     (GtkInputDialog *,
14091                                          ggint,
14092                                          gpointer);
14093 </verb></tscreen>
14094
14095 <!-- ----------------------------------------------------------------- -->
14096 <sect1>GtkColorSelection
14097 <!-- ----------------------------------------------------------------- -->
14098 <p>
14099 <tscreen><verb>
14100 void GtkColorSelection::color-changed   (GtkColorSelection *,
14101                                          gpointer);
14102 </verb></tscreen>
14103
14104 <!-- ----------------------------------------------------------------- -->
14105 <sect1>GtkStatusBar
14106 <!-- ----------------------------------------------------------------- -->
14107 <p>
14108 <tscreen><verb>
14109 void GtkStatusbar::text-pushed  (GtkStatusbar *,
14110                                  gguint,
14111                                  GtkString *,
14112                                  gpointer);
14113 void GtkStatusbar::text-popped  (GtkStatusbar *,
14114                                  gguint,
14115                                  GtkString *,
14116                                  gpointer);
14117 </verb></tscreen>
14118
14119 <!-- ----------------------------------------------------------------- -->
14120 <sect1>GtkCTree
14121 <!-- ----------------------------------------------------------------- -->
14122 <p>
14123 <tscreen><verb>
14124 void GtkCTree::tree-select-row  (GtkCTree *,
14125                                  GtkCTreeNode *,
14126                                  ggint,
14127                                  gpointer);
14128 void GtkCTree::tree-unselect-row        (GtkCTree *,
14129                                          GtkCTreeNode *,
14130                                          ggint,
14131                                          gpointer);
14132 void GtkCTree::tree-expand      (GtkCTree *,
14133                                  GtkCTreeNode *,
14134                                  gpointer);
14135 void GtkCTree::tree-collapse    (GtkCTree *,
14136                                  ggpointer,
14137                                  gpointer);
14138 void GtkCTree::tree-move        (GtkCTree *,
14139                                  GtkCTreeNode *,
14140                                  GtkCTreeNode *,
14141                                  GtkCTreeNode *,
14142                                  gpointer);
14143 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
14144                                                  GtkCTreeExpansionType,
14145                                                  gpointer);
14146 </verb></tscreen>
14147
14148 <!-- ----------------------------------------------------------------- -->
14149 <sect1>GtkCurve
14150 <!-- ----------------------------------------------------------------- -->
14151 <p>
14152 <tscreen><verb>
14153 void GtkCurve::curve-type-changed       (GtkCurve *,
14154                                          gpointer);
14155 </verb></tscreen>
14156
14157 <!-- ----------------------------------------------------------------- -->
14158 <sect1>GtkAdjustment
14159 <!-- ----------------------------------------------------------------- -->
14160 <p>
14161 <tscreen><verb>
14162 void GtkAdjustment::changed     (GtkAdjustment *,
14163                                  gpointer);
14164 void GtkAdjustment::value-changed       (GtkAdjustment *,
14165                                          gpointer);
14166 </verb></tscreen>
14167
14168 <!-- ***************************************************************** -->
14169 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
14170 <!-- ***************************************************************** -->
14171 <p>
14172 The follwing data types are passed into event handlers by GTK+. For
14173 each data type listed, the signals that use this data type are listed.
14174
14175 <itemize>
14176 <item>  GdkEvent
14177           <itemize>
14178           <item>drag_end_event
14179           </itemize>
14180
14181 <item>  GdkEventType
14182
14183 <item>  GdkEventAny
14184           <itemize>
14185           <item>delete_event
14186           <item>destroy_event
14187           <item>map_event
14188           <item>unmap_event
14189           <item>no_expose_event
14190           </itemize>
14191
14192 <item>  GdkEventExpose
14193           <itemize>
14194           <item>expose_event
14195           </itemize>
14196
14197 <item>  GdkEventNoExpose
14198
14199 <item>  GdkEventVisibility
14200
14201 <item>  GdkEventMotion
14202           <itemize>
14203           <item>motion_notify_event
14204           </itemize>
14205
14206 <item>  GdkEventButton
14207           <itemize>
14208           <item>button_press_event
14209           <item>button_release_event
14210           </itemize>
14211
14212 <item>  GdkEventKey
14213           <itemize>
14214           <item>key_press_event
14215           <item>key_release_event
14216           </itemize>
14217
14218 <item>  GdkEventCrossing
14219           <itemize>
14220           <item>enter_notify_event
14221           <item>leave_notify_event
14222           </itemize>
14223
14224 <item>  GdkEventFocus
14225           <itemize>
14226           <item>focus_in_event
14227           <item>focus_out_event
14228           </itemize>
14229
14230 <item>  GdkEventConfigure
14231           <itemize>
14232           <item>configure_event
14233           </itemize>
14234
14235 <item>  GdkEventProperty
14236           <itemize>
14237           <item>property_notify_event
14238           </itemize>
14239
14240 <item>  GdkEventSelection
14241           <itemize>
14242           <item>selection_clear_event
14243           <item>selection_request_event
14244           <item>selection_notify_event
14245           </itemize>
14246
14247 <item>  GdkEventProximity
14248           <itemize>
14249           <item>proximity_in_event
14250           <item>proximity_out_event
14251           </itemize>
14252
14253 <item>  GdkEventDragBegin
14254           <itemize>
14255           <item>drag_begin_event
14256           </itemize>
14257
14258 <item>  GdkEventDragRequest
14259           <itemize>
14260           <item>drag_request_event
14261           </itemize>
14262
14263 <item>  GdkEventDropEnter
14264           <itemize>
14265           <item>drop_enter_event
14266           </itemize>
14267
14268 <item>  GdkEventDropLeave
14269           <itemize>
14270           <item>drop_leave_event
14271           </itemize>
14272
14273 <item>  GdkEventDropDataAvailable
14274           <itemize>
14275           <item>drop_data_available_event
14276           </itemize>
14277
14278 <item>  GdkEventClient
14279           <itemize>
14280           <item>client_event
14281           </itemize>
14282
14283 <item>  GdkEventOther
14284           <itemize>
14285           <item>other_event
14286           </itemize>
14287 </itemize>
14288
14289 The data type <tt/GdkEventType/ is a special data type that is used by
14290 all the other data types as an indicator of the data type being passed
14291 to the signal handler. As you will see below, each of the event data
14292 structures has a member of this type. It is defined as an enumeration
14293 type as follows:
14294
14295 <tscreen><verb>
14296 typedef enum
14297 {
14298   GDK_NOTHING           = -1,
14299   GDK_DELETE            = 0,
14300   GDK_DESTROY           = 1,
14301   GDK_EXPOSE            = 2,
14302   GDK_MOTION_NOTIFY     = 3,
14303   GDK_BUTTON_PRESS      = 4,
14304   GDK_2BUTTON_PRESS     = 5,
14305   GDK_3BUTTON_PRESS     = 6,
14306   GDK_BUTTON_RELEASE    = 7,
14307   GDK_KEY_PRESS         = 8,
14308   GDK_KEY_RELEASE       = 9,
14309   GDK_ENTER_NOTIFY      = 10,
14310   GDK_LEAVE_NOTIFY      = 11,
14311   GDK_FOCUS_CHANGE      = 12,
14312   GDK_CONFIGURE         = 13,
14313   GDK_MAP               = 14,
14314   GDK_UNMAP             = 15,
14315   GDK_PROPERTY_NOTIFY   = 16,
14316   GDK_SELECTION_CLEAR   = 17,
14317   GDK_SELECTION_REQUEST = 18,
14318   GDK_SELECTION_NOTIFY  = 19,
14319   GDK_PROXIMITY_IN      = 20,
14320   GDK_PROXIMITY_OUT     = 21,
14321   GDK_DRAG_BEGIN        = 22,
14322   GDK_DRAG_REQUEST      = 23,
14323   GDK_DROP_ENTER        = 24,
14324   GDK_DROP_LEAVE        = 25,
14325   GDK_DROP_DATA_AVAIL   = 26,
14326   GDK_CLIENT_EVENT      = 27,
14327   GDK_VISIBILITY_NOTIFY = 28,
14328   GDK_NO_EXPOSE         = 29,
14329   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
14330 } GdkEventType;
14331 </verb></tscreen>
14332
14333 The other event type that is different from the others is
14334 <tt/GdkEvent/ itself. This is a union of all the other
14335 data types, which allows it to be cast to a specific
14336 event data type within a signal handler.
14337
14338 <!-- Just a big list for now, needs expanding upon - TRG -->
14339 So, the event data types are defined as follows:
14340
14341 <tscreen><verb>
14342 struct _GdkEventAny
14343 {
14344   GdkEventType type;
14345   GdkWindow *window;
14346   gint8 send_event;
14347 };
14348
14349 struct _GdkEventExpose
14350 {
14351   GdkEventType type;
14352   GdkWindow *window;
14353   gint8 send_event;
14354   GdkRectangle area;
14355   gint count; /* If non-zero, how many more events follow. */
14356 };
14357
14358 struct _GdkEventNoExpose
14359 {
14360   GdkEventType type;
14361   GdkWindow *window;
14362   gint8 send_event;
14363   /* XXX: does anyone need the X major_code or minor_code fields? */
14364 };
14365
14366 struct _GdkEventVisibility
14367 {
14368   GdkEventType type;
14369   GdkWindow *window;
14370   gint8 send_event;
14371   GdkVisibilityState state;
14372 };
14373
14374 struct _GdkEventMotion
14375 {
14376   GdkEventType type;
14377   GdkWindow *window;
14378   gint8 send_event;
14379   guint32 time;
14380   gdouble x;
14381   gdouble y;
14382   gdouble pressure;
14383   gdouble xtilt;
14384   gdouble ytilt;
14385   guint state;
14386   gint16 is_hint;
14387   GdkInputSource source;
14388   guint32 deviceid;
14389   gdouble x_root, y_root;
14390 };
14391
14392 struct _GdkEventButton
14393 {
14394   GdkEventType type;
14395   GdkWindow *window;
14396   gint8 send_event;
14397   guint32 time;
14398   gdouble x;
14399   gdouble y;
14400   gdouble pressure;
14401   gdouble xtilt;
14402   gdouble ytilt;
14403   guint state;
14404   guint button;
14405   GdkInputSource source;
14406   guint32 deviceid;
14407   gdouble x_root, y_root;
14408 };
14409
14410 struct _GdkEventKey
14411 {
14412   GdkEventType type;
14413   GdkWindow *window;
14414   gint8 send_event;
14415   guint32 time;
14416   guint state;
14417   guint keyval;
14418   gint length;
14419   gchar *string;
14420 };
14421
14422 struct _GdkEventCrossing
14423 {
14424   GdkEventType type;
14425   GdkWindow *window;
14426   gint8 send_event;
14427   GdkWindow *subwindow;
14428   GdkNotifyType detail;
14429 };
14430
14431 struct _GdkEventFocus
14432 {
14433   GdkEventType type;
14434   GdkWindow *window;
14435   gint8 send_event;
14436   gint16 in;
14437 };
14438
14439 struct _GdkEventConfigure
14440 {
14441   GdkEventType type;
14442   GdkWindow *window;
14443   gint8 send_event;
14444   gint16 x, y;
14445   gint16 width;
14446   gint16 height;
14447 };
14448
14449 struct _GdkEventProperty
14450 {
14451   GdkEventType type;
14452   GdkWindow *window;
14453   gint8 send_event;
14454   GdkAtom atom;
14455   guint32 time;
14456   guint state;
14457 };
14458
14459 struct _GdkEventSelection
14460 {
14461   GdkEventType type;
14462   GdkWindow *window;
14463   gint8 send_event;
14464   GdkAtom selection;
14465   GdkAtom target;
14466   GdkAtom property;
14467   guint32 requestor;
14468   guint32 time;
14469 };
14470
14471 /* This event type will be used pretty rarely. It only is important
14472    for XInput aware programs that are drawing their own cursor */
14473
14474 struct _GdkEventProximity
14475 {
14476   GdkEventType type;
14477   GdkWindow *window;
14478   gint8 send_event;
14479   guint32 time;
14480   GdkInputSource source;
14481   guint32 deviceid;
14482 };
14483
14484 struct _GdkEventDragRequest
14485 {
14486   GdkEventType type;
14487   GdkWindow *window;
14488   gint8 send_event;
14489   guint32 requestor;
14490   union {
14491     struct {
14492       guint protocol_version:4;
14493       guint sendreply:1;
14494       guint willaccept:1;
14495       guint delete_data:1; /* Do *not* delete if link is sent, only
14496                               if data is sent */
14497       guint senddata:1;
14498       guint reserved:22;
14499     } flags;
14500     glong allflags;
14501   } u;
14502   guint8 isdrop; /* This gdk event can be generated by a couple of
14503                     X events - this lets the app know whether the
14504                     drop really occurred or we just set the data */
14505
14506   GdkPoint drop_coords;
14507   gchar *data_type;
14508   guint32 timestamp;
14509 };
14510
14511 struct _GdkEventDragBegin
14512 {
14513   GdkEventType type;
14514   GdkWindow *window;
14515   gint8 send_event;
14516   union {
14517     struct {
14518       guint protocol_version:4;
14519       guint reserved:28;
14520     } flags;
14521     glong allflags;
14522   } u;
14523 };
14524
14525 struct _GdkEventDropEnter
14526 {
14527   GdkEventType type;
14528   GdkWindow *window;
14529   gint8 send_event;
14530   guint32 requestor;
14531   union {
14532     struct {
14533       guint protocol_version:4;
14534       guint sendreply:1;
14535       guint extended_typelist:1;
14536       guint reserved:26;
14537     } flags;
14538     glong allflags;
14539   } u;
14540 };
14541
14542 struct _GdkEventDropLeave
14543 {
14544   GdkEventType type;
14545   GdkWindow *window;
14546   gint8 send_event;
14547   guint32 requestor;
14548   union {
14549     struct {
14550       guint protocol_version:4;
14551       guint reserved:28;
14552     } flags;
14553     glong allflags;
14554   } u;
14555 };
14556
14557 struct _GdkEventDropDataAvailable
14558 {
14559   GdkEventType type;
14560   GdkWindow *window;
14561   gint8 send_event;
14562   guint32 requestor;
14563   union {
14564     struct {
14565       guint protocol_version:4;
14566       guint isdrop:1;
14567       guint reserved:25;
14568     } flags;
14569     glong allflags;
14570   } u;
14571   gchar *data_type; /* MIME type */
14572   gulong data_numbytes;
14573   gpointer data;
14574   guint32 timestamp;
14575   GdkPoint coords;
14576 };
14577
14578 struct _GdkEventClient
14579 {
14580   GdkEventType type;
14581   GdkWindow *window;
14582   gint8 send_event;
14583   GdkAtom message_type;
14584   gushort data_format;
14585   union {
14586     char b[20];
14587     short s[10];
14588     long l[5];
14589   } data;
14590 };
14591
14592 struct _GdkEventOther
14593 {
14594   GdkEventType type;
14595   GdkWindow *window;
14596   gint8 send_event;
14597   GdkXEvent *xevent;
14598 };
14599 </verb></tscreen>
14600
14601 <!-- ***************************************************************** -->
14602 <sect> Code Examples
14603 <!-- ***************************************************************** -->
14604 <p>
14605 Below are the code examples that are used in the above text
14606 which are not included in complete form elsewhere.
14607
14608 <!-- ----------------------------------------------------------------- -->
14609 <sect1>Tictactoe
14610 <!-- ----------------------------------------------------------------- -->
14611 <sect2>tictactoe.h
14612 <p>
14613 <tscreen><verb>
14614 /* example-start tictactoe tictactoe.h */
14615
14616 /* GTK - The GIMP Toolkit
14617  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14618  *
14619  * This library is free software; you can redistribute it and/or
14620  * modify it under the terms of the GNU Library General Public
14621  * License as published by the Free Software Foundation; either
14622  * version 2 of the License, or (at your option) any later version.
14623  *
14624  * This library is distributed in the hope that it will be useful,
14625  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14626  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14627  * Library General Public License for more details.
14628  *
14629  * You should have received a copy of the GNU Library General Public
14630  * License along with this library; if not, write to the
14631  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14632  * Boston, MA 02111-1307, USA.
14633  */
14634 #ifndef __TICTACTOE_H__
14635 #define __TICTACTOE_H__
14636
14637
14638 #include <gdk/gdk.h>
14639 #include <gtk/gtkvbox.h>
14640
14641
14642 #ifdef __cplusplus
14643 extern "C" {
14644 #endif /* __cplusplus */
14645
14646 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
14647 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
14648 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
14649
14650
14651 typedef struct _Tictactoe       Tictactoe;
14652 typedef struct _TictactoeClass  TictactoeClass;
14653
14654 struct _Tictactoe
14655 {
14656   GtkVBox vbox;
14657   
14658   GtkWidget *buttons[3][3];
14659 };
14660
14661 struct _TictactoeClass
14662 {
14663   GtkVBoxClass parent_class;
14664
14665   void (* tictactoe) (Tictactoe *ttt);
14666 };
14667
14668 guint          tictactoe_get_type        (void);
14669 GtkWidget*     tictactoe_new             (void);
14670 void           tictactoe_clear           (Tictactoe *ttt);
14671
14672 #ifdef __cplusplus
14673 }
14674 #endif /* __cplusplus */
14675
14676 #endif /* __TICTACTOE_H__ */
14677
14678 /* example-end */
14679 </verb></tscreen>
14680
14681 <!-- ----------------------------------------------------------------- -->
14682 <sect2>tictactoe.c
14683 <p>
14684 <tscreen><verb>
14685 /* example-start tictactoe tictactoe.c */
14686
14687 /* GTK - The GIMP Toolkit
14688  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14689  *
14690  * This library is free software; you can redistribute it and/or
14691  * modify it under the terms of the GNU Library General Public
14692  * License as published by the Free Software Foundation; either
14693  * version 2 of the License, or (at your option) any later version.
14694  *
14695  * This library is distributed in the hope that it will be useful,
14696  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14697  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14698  * Library General Public License for more details.
14699  *
14700  * You should have received a copy of the GNU Library General Public
14701  * License along with this library; if not, write to the
14702  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14703  * Boston, MA 02111-1307, USA.
14704  */
14705 #include "gtk/gtksignal.h"
14706 #include "gtk/gtktable.h"
14707 #include "gtk/gtktogglebutton.h"
14708 #include "tictactoe.h"
14709
14710 enum {
14711   TICTACTOE_SIGNAL,
14712   LAST_SIGNAL
14713 };
14714
14715 static void tictactoe_class_init          (TictactoeClass *klass);
14716 static void tictactoe_init                (Tictactoe      *ttt);
14717 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
14718
14719 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
14720
14721 guint
14722 tictactoe_get_type ()
14723 {
14724   static guint ttt_type = 0;
14725
14726   if (!ttt_type)
14727     {
14728       GtkTypeInfo ttt_info =
14729       {
14730         "Tictactoe",
14731         sizeof (Tictactoe),
14732         sizeof (TictactoeClass),
14733         (GtkClassInitFunc) tictactoe_class_init,
14734         (GtkObjectInitFunc) tictactoe_init,
14735         (GtkArgSetFunc) NULL,
14736         (GtkArgGetFunc) NULL
14737       };
14738
14739       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
14740     }
14741
14742   return ttt_type;
14743 }
14744
14745 static void
14746 tictactoe_class_init (TictactoeClass *class)
14747 {
14748   GtkObjectClass *object_class;
14749
14750   object_class = (GtkObjectClass*) class;
14751   
14752   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
14753                                          GTK_RUN_FIRST,
14754                                          object_class->type,
14755                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
14756                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
14757
14758
14759   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
14760
14761   class->tictactoe = NULL;
14762 }
14763
14764 static void
14765 tictactoe_init (Tictactoe *ttt)
14766 {
14767   GtkWidget *table;
14768   gint i,j;
14769   
14770   table = gtk_table_new (3, 3, TRUE);
14771   gtk_container_add (GTK_CONTAINER(ttt), table);
14772   gtk_widget_show (table);
14773
14774   for (i=0;i<3; i++)
14775     for (j=0;j<3; j++)
14776       {
14777         ttt->buttons[i][j] = gtk_toggle_button_new ();
14778         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
14779                                    i, i+1, j, j+1);
14780         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
14781                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
14782         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
14783         gtk_widget_show (ttt->buttons[i][j]);
14784       }
14785 }
14786
14787 GtkWidget*
14788 tictactoe_new ()
14789 {
14790   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
14791 }
14792
14793 void           
14794 tictactoe_clear (Tictactoe *ttt)
14795 {
14796   int i,j;
14797
14798   for (i=0;i<3;i++)
14799     for (j=0;j<3;j++)
14800       {
14801         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
14802         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
14803                                      FALSE);
14804         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
14805       }
14806 }
14807
14808 static void
14809 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
14810 {
14811   int i,k;
14812
14813   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14814                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14815                              { 0, 1, 2 }, { 0, 1, 2 } };
14816   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14817                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14818                              { 0, 1, 2 }, { 2, 1, 0 } };
14819
14820   int success, found;
14821
14822   for (k=0; k<8; k++)
14823     {
14824       success = TRUE;
14825       found = FALSE;
14826
14827       for (i=0;i<3;i++)
14828         {
14829           success = success &amp;&amp; 
14830             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
14831           found = found ||
14832             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
14833         }
14834       
14835       if (success &amp;&amp; found)
14836         {
14837           gtk_signal_emit (GTK_OBJECT (ttt), 
14838                            tictactoe_signals[TICTACTOE_SIGNAL]);
14839           break;
14840         }
14841     }
14842 }
14843
14844 /* example-end */
14845 </verb></tscreen>
14846
14847 <!-- ----------------------------------------------------------------- -->
14848 <sect2>ttt_test.c
14849 <p>
14850 <tscreen><verb>
14851 /* example-start tictactoe ttt_test.c */
14852
14853 #include <gtk/gtk.h>
14854 #include "tictactoe.h"
14855
14856 void
14857 win (GtkWidget *widget, gpointer data)
14858 {
14859   g_print ("Yay!\n");
14860   tictactoe_clear (TICTACTOE (widget));
14861 }
14862
14863 int 
14864 main (int argc, char *argv[])
14865 {
14866   GtkWidget *window;
14867   GtkWidget *ttt;
14868   
14869   gtk_init (&amp;argc, &amp;argv);
14870
14871   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14872   
14873   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
14874   
14875   gtk_signal_connect (GTK_OBJECT (window), "destroy",
14876                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
14877   
14878   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
14879
14880   ttt = tictactoe_new ();
14881   
14882   gtk_container_add (GTK_CONTAINER (window), ttt);
14883   gtk_widget_show (ttt);
14884
14885   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
14886                       GTK_SIGNAL_FUNC (win), NULL);
14887
14888   gtk_widget_show (window);
14889   
14890   gtk_main ();
14891   
14892   return 0;
14893 }
14894
14895 /* example-end */
14896 </verb></tscreen>
14897
14898 <!-- ----------------------------------------------------------------- -->
14899 <sect1> GtkDial
14900
14901 <!-- ----------------------------------------------------------------- -->
14902 <sect2> gtkdial.h
14903 <p>
14904 <tscreen><verb>
14905 /* example-start gtkdial gtkdial.h */
14906
14907 /* GTK - The GIMP Toolkit
14908  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14909  *
14910  * This library is free software; you can redistribute it and/or
14911  * modify it under the terms of the GNU Library General Public
14912  * License as published by the Free Software Foundation; either
14913  * version 2 of the License, or (at your option) any later version.
14914  *
14915  * This library is distributed in the hope that it will be useful,
14916  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14917  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14918  * Library General Public License for more details.
14919  *
14920  * You should have received a copy of the GNU Library General Public
14921  * License along with this library; if not, write to the
14922  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14923  * Boston, MA 02111-1307, USA.
14924  */
14925 #ifndef __GTK_DIAL_H__
14926 #define __GTK_DIAL_H__
14927
14928
14929 #include <gdk/gdk.h>
14930 #include <gtk/gtkadjustment.h>
14931 #include <gtk/gtkwidget.h>
14932
14933
14934 #ifdef __cplusplus
14935 extern "C" {
14936 #endif /* __cplusplus */
14937
14938
14939 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
14940 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
14941 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
14942
14943
14944 typedef struct _GtkDial        GtkDial;
14945 typedef struct _GtkDialClass   GtkDialClass;
14946
14947 struct _GtkDial
14948 {
14949   GtkWidget widget;
14950
14951   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
14952   guint policy : 2;
14953
14954   /* Button currently pressed or 0 if none */
14955   guint8 button;
14956
14957   /* Dimensions of dial components */
14958   gint radius;
14959   gint pointer_width;
14960
14961   /* ID of update timer, or 0 if none */
14962   guint32 timer;
14963
14964   /* Current angle */
14965   gfloat angle;
14966
14967   /* Old values from adjustment stored so we know when something changes */
14968   gfloat old_value;
14969   gfloat old_lower;
14970   gfloat old_upper;
14971
14972   /* The adjustment object that stores the data for this dial */
14973   GtkAdjustment *adjustment;
14974 };
14975
14976 struct _GtkDialClass
14977 {
14978   GtkWidgetClass parent_class;
14979 };
14980
14981
14982 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
14983 guint          gtk_dial_get_type               (void);
14984 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
14985 void           gtk_dial_set_update_policy      (GtkDial      *dial,
14986                                                 GtkUpdateType  policy);
14987
14988 void           gtk_dial_set_adjustment         (GtkDial      *dial,
14989                                                 GtkAdjustment *adjustment);
14990 #ifdef __cplusplus
14991 }
14992 #endif /* __cplusplus */
14993
14994
14995 #endif /* __GTK_DIAL_H__ */
14996 /* example-end */
14997 </verb></tscreen>
14998
14999 <!-- ----------------------------------------------------------------- -->
15000 <sect2> gtkdial.c
15001 <p>
15002 <tscreen><verb>
15003 /* example-start gtkdial gtkdial.c */
15004
15005 /* GTK - The GIMP Toolkit
15006  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15007  *
15008  * This library is free software; you can redistribute it and/or
15009  * modify it under the terms of the GNU Library General Public
15010  * License as published by the Free Software Foundation; either
15011  * version 2 of the License, or (at your option) any later version.
15012  *
15013  * This library is distributed in the hope that it will be useful,
15014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15016  * Library General Public License for more details.
15017  *
15018  * You should have received a copy of the GNU Library General Public
15019  * License along with this library; if not, write to the
15020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15021  * Boston, MA 02111-1307, USA.
15022  */
15023 #include <math.h>
15024 #include <stdio.h>
15025 #include <gtk/gtkmain.h>
15026 #include <gtk/gtksignal.h>
15027
15028 #include "gtkdial.h"
15029
15030 #define SCROLL_DELAY_LENGTH  300
15031 #define DIAL_DEFAULT_SIZE 100
15032
15033 /* Forward declarations */
15034
15035 static void gtk_dial_class_init               (GtkDialClass    *klass);
15036 static void gtk_dial_init                     (GtkDial         *dial);
15037 static void gtk_dial_destroy                  (GtkObject        *object);
15038 static void gtk_dial_realize                  (GtkWidget        *widget);
15039 static void gtk_dial_size_request             (GtkWidget      *widget,
15040                                                GtkRequisition *requisition);
15041 static void gtk_dial_size_allocate            (GtkWidget     *widget,
15042                                                GtkAllocation *allocation);
15043 static gint gtk_dial_expose                   (GtkWidget        *widget,
15044                                                 GdkEventExpose   *event);
15045 static gint gtk_dial_button_press             (GtkWidget        *widget,
15046                                                 GdkEventButton   *event);
15047 static gint gtk_dial_button_release           (GtkWidget        *widget,
15048                                                 GdkEventButton   *event);
15049 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
15050                                                 GdkEventMotion   *event);
15051 static gint gtk_dial_timer                    (GtkDial         *dial);
15052
15053 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
15054 static void gtk_dial_update                   (GtkDial *dial);
15055 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
15056                                                 gpointer          data);
15057 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
15058                                                 gpointer          data);
15059
15060 /* Local data */
15061
15062 static GtkWidgetClass *parent_class = NULL;
15063
15064 guint
15065 gtk_dial_get_type ()
15066 {
15067   static guint dial_type = 0;
15068
15069   if (!dial_type)
15070     {
15071       GtkTypeInfo dial_info =
15072       {
15073         "GtkDial",
15074         sizeof (GtkDial),
15075         sizeof (GtkDialClass),
15076         (GtkClassInitFunc) gtk_dial_class_init,
15077         (GtkObjectInitFunc) gtk_dial_init,
15078         (GtkArgSetFunc) NULL,
15079         (GtkArgGetFunc) NULL,
15080       };
15081
15082       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
15083     }
15084
15085   return dial_type;
15086 }
15087
15088 static void
15089 gtk_dial_class_init (GtkDialClass *class)
15090 {
15091   GtkObjectClass *object_class;
15092   GtkWidgetClass *widget_class;
15093
15094   object_class = (GtkObjectClass*) class;
15095   widget_class = (GtkWidgetClass*) class;
15096
15097   parent_class = gtk_type_class (gtk_widget_get_type ());
15098
15099   object_class->destroy = gtk_dial_destroy;
15100
15101   widget_class->realize = gtk_dial_realize;
15102   widget_class->expose_event = gtk_dial_expose;
15103   widget_class->size_request = gtk_dial_size_request;
15104   widget_class->size_allocate = gtk_dial_size_allocate;
15105   widget_class->button_press_event = gtk_dial_button_press;
15106   widget_class->button_release_event = gtk_dial_button_release;
15107   widget_class->motion_notify_event = gtk_dial_motion_notify;
15108 }
15109
15110 static void
15111 gtk_dial_init (GtkDial *dial)
15112 {
15113   dial->button = 0;
15114   dial->policy = GTK_UPDATE_CONTINUOUS;
15115   dial->timer = 0;
15116   dial->radius = 0;
15117   dial->pointer_width = 0;
15118   dial->angle = 0.0;
15119   dial->old_value = 0.0;
15120   dial->old_lower = 0.0;
15121   dial->old_upper = 0.0;
15122   dial->adjustment = NULL;
15123 }
15124
15125 GtkWidget*
15126 gtk_dial_new (GtkAdjustment *adjustment)
15127 {
15128   GtkDial *dial;
15129
15130   dial = gtk_type_new (gtk_dial_get_type ());
15131
15132   if (!adjustment)
15133     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
15134
15135   gtk_dial_set_adjustment (dial, adjustment);
15136
15137   return GTK_WIDGET (dial);
15138 }
15139
15140 static void
15141 gtk_dial_destroy (GtkObject *object)
15142 {
15143   GtkDial *dial;
15144
15145   g_return_if_fail (object != NULL);
15146   g_return_if_fail (GTK_IS_DIAL (object));
15147
15148   dial = GTK_DIAL (object);
15149
15150   if (dial->adjustment)
15151     gtk_object_unref (GTK_OBJECT (dial->adjustment));
15152
15153   if (GTK_OBJECT_CLASS (parent_class)->destroy)
15154     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
15155 }
15156
15157 GtkAdjustment*
15158 gtk_dial_get_adjustment (GtkDial *dial)
15159 {
15160   g_return_val_if_fail (dial != NULL, NULL);
15161   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
15162
15163   return dial->adjustment;
15164 }
15165
15166 void
15167 gtk_dial_set_update_policy (GtkDial      *dial,
15168                              GtkUpdateType  policy)
15169 {
15170   g_return_if_fail (dial != NULL);
15171   g_return_if_fail (GTK_IS_DIAL (dial));
15172
15173   dial->policy = policy;
15174 }
15175
15176 void
15177 gtk_dial_set_adjustment (GtkDial      *dial,
15178                           GtkAdjustment *adjustment)
15179 {
15180   g_return_if_fail (dial != NULL);
15181   g_return_if_fail (GTK_IS_DIAL (dial));
15182
15183   if (dial->adjustment)
15184     {
15185       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
15186       gtk_object_unref (GTK_OBJECT (dial->adjustment));
15187     }
15188
15189   dial->adjustment = adjustment;
15190   gtk_object_ref (GTK_OBJECT (dial->adjustment));
15191
15192   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
15193                       (GtkSignalFunc) gtk_dial_adjustment_changed,
15194                       (gpointer) dial);
15195   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
15196                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
15197                       (gpointer) dial);
15198
15199   dial->old_value = adjustment->value;
15200   dial->old_lower = adjustment->lower;
15201   dial->old_upper = adjustment->upper;
15202
15203   gtk_dial_update (dial);
15204 }
15205
15206 static void
15207 gtk_dial_realize (GtkWidget *widget)
15208 {
15209   GtkDial *dial;
15210   GdkWindowAttr attributes;
15211   gint attributes_mask;
15212
15213   g_return_if_fail (widget != NULL);
15214   g_return_if_fail (GTK_IS_DIAL (widget));
15215
15216   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
15217   dial = GTK_DIAL (widget);
15218
15219   attributes.x = widget->allocation.x;
15220   attributes.y = widget->allocation.y;
15221   attributes.width = widget->allocation.width;
15222   attributes.height = widget->allocation.height;
15223   attributes.wclass = GDK_INPUT_OUTPUT;
15224   attributes.window_type = GDK_WINDOW_CHILD;
15225   attributes.event_mask = gtk_widget_get_events (widget) | 
15226     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
15227     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
15228     GDK_POINTER_MOTION_HINT_MASK;
15229   attributes.visual = gtk_widget_get_visual (widget);
15230   attributes.colormap = gtk_widget_get_colormap (widget);
15231
15232   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
15233   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
15234
15235   widget->style = gtk_style_attach (widget->style, widget->window);
15236
15237   gdk_window_set_user_data (widget->window, widget);
15238
15239   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
15240 }
15241
15242 static void 
15243 gtk_dial_size_request (GtkWidget      *widget,
15244                        GtkRequisition *requisition)
15245 {
15246   requisition->width = DIAL_DEFAULT_SIZE;
15247   requisition->height = DIAL_DEFAULT_SIZE;
15248 }
15249
15250 static void
15251 gtk_dial_size_allocate (GtkWidget     *widget,
15252                         GtkAllocation *allocation)
15253 {
15254   GtkDial *dial;
15255
15256   g_return_if_fail (widget != NULL);
15257   g_return_if_fail (GTK_IS_DIAL (widget));
15258   g_return_if_fail (allocation != NULL);
15259
15260   widget->allocation = *allocation;
15261   dial = GTK_DIAL (widget);
15262
15263   if (GTK_WIDGET_REALIZED (widget))
15264     {
15265
15266       gdk_window_move_resize (widget->window,
15267                               allocation->x, allocation->y,
15268                               allocation->width, allocation->height);
15269
15270     }
15271   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
15272   dial->pointer_width = dial->radius / 5;
15273 }
15274
15275 static gint
15276 gtk_dial_expose (GtkWidget      *widget,
15277                  GdkEventExpose *event)
15278 {
15279   GtkDial *dial;
15280   GdkPoint points[3];
15281   gdouble s,c;
15282   gdouble theta;
15283   gint xc, yc;
15284   gint tick_length;
15285   gint i;
15286
15287   g_return_val_if_fail (widget != NULL, FALSE);
15288   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15289   g_return_val_if_fail (event != NULL, FALSE);
15290
15291   if (event->count > 0)
15292     return FALSE;
15293   
15294   dial = GTK_DIAL (widget);
15295
15296   gdk_window_clear_area (widget->window,
15297                          0, 0,
15298                          widget->allocation.width,
15299                          widget->allocation.height);
15300
15301   xc = widget->allocation.width/2;
15302   yc = widget->allocation.height/2;
15303
15304   /* Draw ticks */
15305
15306   for (i=0; i<25; i++)
15307     {
15308       theta = (i*M_PI/18. - M_PI/6.);
15309       s = sin(theta);
15310       c = cos(theta);
15311
15312       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
15313       
15314       gdk_draw_line (widget->window,
15315                      widget->style->fg_gc[widget->state],
15316                      xc + c*(dial->radius - tick_length),
15317                      yc - s*(dial->radius - tick_length),
15318                      xc + c*dial->radius,
15319                      yc - s*dial->radius);
15320     }
15321
15322   /* Draw pointer */
15323
15324   s = sin(dial->angle);
15325   c = cos(dial->angle);
15326
15327
15328   points[0].x = xc + s*dial->pointer_width/2;
15329   points[0].y = yc + c*dial->pointer_width/2;
15330   points[1].x = xc + c*dial->radius;
15331   points[1].y = yc - s*dial->radius;
15332   points[2].x = xc - s*dial->pointer_width/2;
15333   points[2].y = yc - c*dial->pointer_width/2;
15334
15335   gtk_draw_polygon (widget->style,
15336                     widget->window,
15337                     GTK_STATE_NORMAL,
15338                     GTK_SHADOW_OUT,
15339                     points, 3,
15340                     TRUE);
15341   
15342   return FALSE;
15343 }
15344
15345 static gint
15346 gtk_dial_button_press (GtkWidget      *widget,
15347                        GdkEventButton *event)
15348 {
15349   GtkDial *dial;
15350   gint dx, dy;
15351   double s, c;
15352   double d_parallel;
15353   double d_perpendicular;
15354
15355   g_return_val_if_fail (widget != NULL, FALSE);
15356   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15357   g_return_val_if_fail (event != NULL, FALSE);
15358
15359   dial = GTK_DIAL (widget);
15360
15361   /* Determine if button press was within pointer region - we 
15362      do this by computing the parallel and perpendicular distance of
15363      the point where the mouse was pressed from the line passing through
15364      the pointer */
15365   
15366   dx = event->x - widget->allocation.width / 2;
15367   dy = widget->allocation.height / 2 - event->y;
15368   
15369   s = sin(dial->angle);
15370   c = cos(dial->angle);
15371   
15372   d_parallel = s*dy + c*dx;
15373   d_perpendicular = fabs(s*dx - c*dy);
15374   
15375   if (!dial->button &amp;&amp;
15376       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
15377       (d_parallel > - dial->pointer_width))
15378     {
15379       gtk_grab_add (widget);
15380
15381       dial->button = event->button;
15382
15383       gtk_dial_update_mouse (dial, event->x, event->y);
15384     }
15385
15386   return FALSE;
15387 }
15388
15389 static gint
15390 gtk_dial_button_release (GtkWidget      *widget,
15391                           GdkEventButton *event)
15392 {
15393   GtkDial *dial;
15394
15395   g_return_val_if_fail (widget != NULL, FALSE);
15396   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15397   g_return_val_if_fail (event != NULL, FALSE);
15398
15399   dial = GTK_DIAL (widget);
15400
15401   if (dial->button == event->button)
15402     {
15403       gtk_grab_remove (widget);
15404
15405       dial->button = 0;
15406
15407       if (dial->policy == GTK_UPDATE_DELAYED)
15408         gtk_timeout_remove (dial->timer);
15409       
15410       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
15411           (dial->old_value != dial->adjustment->value))
15412         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15413     }
15414
15415   return FALSE;
15416 }
15417
15418 static gint
15419 gtk_dial_motion_notify (GtkWidget      *widget,
15420                          GdkEventMotion *event)
15421 {
15422   GtkDial *dial;
15423   GdkModifierType mods;
15424   gint x, y, mask;
15425
15426   g_return_val_if_fail (widget != NULL, FALSE);
15427   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15428   g_return_val_if_fail (event != NULL, FALSE);
15429
15430   dial = GTK_DIAL (widget);
15431
15432   if (dial->button != 0)
15433     {
15434       x = event->x;
15435       y = event->y;
15436
15437       if (event->is_hint || (event->window != widget->window))
15438         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
15439
15440       switch (dial->button)
15441         {
15442         case 1:
15443           mask = GDK_BUTTON1_MASK;
15444           break;
15445         case 2:
15446           mask = GDK_BUTTON2_MASK;
15447           break;
15448         case 3:
15449           mask = GDK_BUTTON3_MASK;
15450           break;
15451         default:
15452           mask = 0;
15453           break;
15454         }
15455
15456       if (mods &amp; mask)
15457         gtk_dial_update_mouse (dial, x,y);
15458     }
15459
15460   return FALSE;
15461 }
15462
15463 static gint
15464 gtk_dial_timer (GtkDial *dial)
15465 {
15466   g_return_val_if_fail (dial != NULL, FALSE);
15467   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
15468
15469   if (dial->policy == GTK_UPDATE_DELAYED)
15470     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15471
15472   return FALSE;
15473 }
15474
15475 static void
15476 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
15477 {
15478   gint xc, yc;
15479   gfloat old_value;
15480
15481   g_return_if_fail (dial != NULL);
15482   g_return_if_fail (GTK_IS_DIAL (dial));
15483
15484   xc = GTK_WIDGET(dial)->allocation.width / 2;
15485   yc = GTK_WIDGET(dial)->allocation.height / 2;
15486
15487   old_value = dial->adjustment->value;
15488   dial->angle = atan2(yc-y, x-xc);
15489
15490   if (dial->angle < -M_PI/2.)
15491     dial->angle += 2*M_PI;
15492
15493   if (dial->angle < -M_PI/6)
15494     dial->angle = -M_PI/6;
15495
15496   if (dial->angle > 7.*M_PI/6.)
15497     dial->angle = 7.*M_PI/6.;
15498
15499   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
15500     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
15501
15502   if (dial->adjustment->value != old_value)
15503     {
15504       if (dial->policy == GTK_UPDATE_CONTINUOUS)
15505         {
15506           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15507         }
15508       else
15509         {
15510           gtk_widget_draw (GTK_WIDGET(dial), NULL);
15511
15512           if (dial->policy == GTK_UPDATE_DELAYED)
15513             {
15514               if (dial->timer)
15515                 gtk_timeout_remove (dial->timer);
15516
15517               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
15518                                              (GtkFunction) gtk_dial_timer,
15519                                              (gpointer) dial);
15520             }
15521         }
15522     }
15523 }
15524
15525 static void
15526 gtk_dial_update (GtkDial *dial)
15527 {
15528   gfloat new_value;
15529   
15530   g_return_if_fail (dial != NULL);
15531   g_return_if_fail (GTK_IS_DIAL (dial));
15532
15533   new_value = dial->adjustment->value;
15534   
15535   if (new_value < dial->adjustment->lower)
15536     new_value = dial->adjustment->lower;
15537
15538   if (new_value > dial->adjustment->upper)
15539     new_value = dial->adjustment->upper;
15540
15541   if (new_value != dial->adjustment->value)
15542     {
15543       dial->adjustment->value = new_value;
15544       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15545     }
15546
15547   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
15548     (dial->adjustment->upper - dial->adjustment->lower);
15549
15550   gtk_widget_draw (GTK_WIDGET(dial), NULL);
15551 }
15552
15553 static void
15554 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
15555                               gpointer       data)
15556 {
15557   GtkDial *dial;
15558
15559   g_return_if_fail (adjustment != NULL);
15560   g_return_if_fail (data != NULL);
15561
15562   dial = GTK_DIAL (data);
15563
15564   if ((dial->old_value != adjustment->value) ||
15565       (dial->old_lower != adjustment->lower) ||
15566       (dial->old_upper != adjustment->upper))
15567     {
15568       gtk_dial_update (dial);
15569
15570       dial->old_value = adjustment->value;
15571       dial->old_lower = adjustment->lower;
15572       dial->old_upper = adjustment->upper;
15573     }
15574 }
15575
15576 static void
15577 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
15578                                     gpointer       data)
15579 {
15580   GtkDial *dial;
15581
15582   g_return_if_fail (adjustment != NULL);
15583   g_return_if_fail (data != NULL);
15584
15585   dial = GTK_DIAL (data);
15586
15587   if (dial->old_value != adjustment->value)
15588     {
15589       gtk_dial_update (dial);
15590
15591       dial->old_value = adjustment->value;
15592     }
15593 }
15594 /* example-end */
15595 </verb></tscreen>
15596
15597 <!-- ----------------------------------------------------------------- -->
15598 <sect1> Scribble
15599 <p>
15600 <tscreen><verb>
15601 /* example-start scribble-simple scribble-simple.c */
15602
15603 /* GTK - The GIMP Toolkit
15604  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15605  *
15606  * This library is free software; you can redistribute it and/or
15607  * modify it under the terms of the GNU Library General Public
15608  * License as published by the Free Software Foundation; either
15609  * version 2 of the License, or (at your option) any later version.
15610  *
15611  * This library is distributed in the hope that it will be useful,
15612  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15613  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15614  * Library General Public License for more details.
15615  *
15616  * You should have received a copy of the GNU Library General Public
15617  * License along with this library; if not, write to the
15618  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15619  * Boston, MA 02111-1307, USA.
15620  */
15621
15622 #include <gtk/gtk.h>
15623
15624 /* Backing pixmap for drawing area */
15625 static GdkPixmap *pixmap = NULL;
15626
15627 /* Create a new backing pixmap of the appropriate size */
15628 static gint
15629 configure_event (GtkWidget *widget, GdkEventConfigure *event)
15630 {
15631   if (pixmap)
15632     gdk_pixmap_unref(pixmap);
15633
15634   pixmap = gdk_pixmap_new(widget->window,
15635                           widget->allocation.width,
15636                           widget->allocation.height,
15637                           -1);
15638   gdk_draw_rectangle (pixmap,
15639                       widget->style->white_gc,
15640                       TRUE,
15641                       0, 0,
15642                       widget->allocation.width,
15643                       widget->allocation.height);
15644
15645   return TRUE;
15646 }
15647
15648 /* Redraw the screen from the backing pixmap */
15649 static gint
15650 expose_event (GtkWidget *widget, GdkEventExpose *event)
15651 {
15652   gdk_draw_pixmap(widget->window,
15653                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
15654                   pixmap,
15655                   event->area.x, event->area.y,
15656                   event->area.x, event->area.y,
15657                   event->area.width, event->area.height);
15658
15659   return FALSE;
15660 }
15661
15662 /* Draw a rectangle on the screen */
15663 static void
15664 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
15665 {
15666   GdkRectangle update_rect;
15667
15668   update_rect.x = x - 5;
15669   update_rect.y = y - 5;
15670   update_rect.width = 10;
15671   update_rect.height = 10;
15672   gdk_draw_rectangle (pixmap,
15673                       widget->style->black_gc,
15674                       TRUE,
15675                       update_rect.x, update_rect.y,
15676                       update_rect.width, update_rect.height);
15677   gtk_widget_draw (widget, &amp;update_rect);
15678 }
15679
15680 static gint
15681 button_press_event (GtkWidget *widget, GdkEventButton *event)
15682 {
15683   if (event->button == 1 &amp;&amp; pixmap != NULL)
15684     draw_brush (widget, event->x, event->y);
15685
15686   return TRUE;
15687 }
15688
15689 static gint
15690 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
15691 {
15692   int x, y;
15693   GdkModifierType state;
15694
15695   if (event->is_hint)
15696     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
15697   else
15698     {
15699       x = event->x;
15700       y = event->y;
15701       state = event->state;
15702     }
15703     
15704   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15705     draw_brush (widget, x, y);
15706   
15707   return TRUE;
15708 }
15709
15710 void
15711 quit ()
15712 {
15713   gtk_exit (0);
15714 }
15715
15716 int
15717 main (int argc, char *argv[])
15718 {
15719   GtkWidget *window;
15720   GtkWidget *drawing_area;
15721   GtkWidget *vbox;
15722
15723   GtkWidget *button;
15724
15725   gtk_init (&amp;argc, &amp;argv);
15726
15727   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15728   gtk_widget_set_name (window, "Test Input");
15729
15730   vbox = gtk_vbox_new (FALSE, 0);
15731   gtk_container_add (GTK_CONTAINER (window), vbox);
15732   gtk_widget_show (vbox);
15733
15734   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15735                       GTK_SIGNAL_FUNC (quit), NULL);
15736
15737   /* Create the drawing area */
15738
15739   drawing_area = gtk_drawing_area_new ();
15740   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
15741   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
15742
15743   gtk_widget_show (drawing_area);
15744
15745   /* Signals used to handle backing pixmap */
15746
15747   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
15748                       (GtkSignalFunc) expose_event, NULL);
15749   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
15750                       (GtkSignalFunc) configure_event, NULL);
15751
15752   /* Event signals */
15753
15754   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
15755                       (GtkSignalFunc) motion_notify_event, NULL);
15756   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
15757                       (GtkSignalFunc) button_press_event, NULL);
15758
15759   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
15760                          | GDK_LEAVE_NOTIFY_MASK
15761                          | GDK_BUTTON_PRESS_MASK
15762                          | GDK_POINTER_MOTION_MASK
15763                          | GDK_POINTER_MOTION_HINT_MASK);
15764
15765   /* .. And a quit button */
15766   button = gtk_button_new_with_label ("Quit");
15767   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
15768
15769   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
15770                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
15771                              GTK_OBJECT (window));
15772   gtk_widget_show (button);
15773
15774   gtk_widget_show (window);
15775
15776   gtk_main ();
15777
15778   return 0;
15779 }
15780 /* example-end */
15781 </verb></tscreen>
15782
15783 <!-- ***************************************************************** -->
15784 <sect> List Widget
15785 <!-- ***************************************************************** -->
15786 <p>
15787 NOTE: The GtkList widget has been superseded by the GtkCList
15788 widget. It is detailed here just for completeness.
15789
15790 The GtkList widget is designed to act as a vertical container for
15791 widgets that should be of the type GtkListItem.
15792
15793 A GtkList widget has its own window to receive events and its own
15794 background color which is usually white. As it is directly derived
15795 from a GtkContainer it can be treated as such by using the
15796 GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
15797 this. One should already be familiar with the usage of a GList and
15798 its related functions g_list_*() to be able to use the GtkList widget
15799 to it full extent.
15800
15801 There is one field inside the structure definition of the GtkList
15802 widget that will be of greater interest to us, this is:
15803
15804 <tscreen><verb>
15805 struct _GtkList
15806 {
15807   ...
15808   GList *selection;
15809   guint selection_mode;
15810   ...
15811 }; 
15812 </verb></tscreen>
15813
15814 The selection field of a GtkList points to a linked list of all items
15815 that are currently selected, or NULL if the selection is empty.  So to
15816 learn about the current selection we read the GTK_LIST()->selection
15817 field, but do not modify it since the internal fields are maintained
15818 by the gtk_list_*() functions.
15819
15820 The selection_mode of the GtkList determines the selection facilities
15821 of a GtkList and therefore the contents of the GTK_LIST()->selection
15822 field. The selection_mode may be one of the following:
15823
15824 <itemize>
15825 <item> GTK_SELECTION_SINGLE - The selection is either NULL
15826                         or contains a GList pointer
15827                         for a single selected item.
15828
15829 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list
15830                         contains no widgets or insensitive
15831                         ones only, otherwise it contains
15832                         a GList pointer for one GList
15833                         structure, and therefore exactly
15834                         one list item.
15835
15836 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list
15837                         items are selected or a GList pointer
15838                         for the first selected item. That
15839                         in turn points to a GList structure
15840                         for the second selected item and so
15841                         on.
15842
15843 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
15844 </itemize>
15845
15846 The default is GTK_SELECTION_MULTIPLE.
15847
15848 <!-- ----------------------------------------------------------------- -->
15849 <sect1> Signals
15850 <p>
15851 <tscreen><verb>
15852 void selection_changed( GtkList *list );
15853 </verb></tscreen>
15854
15855 This signal will be invoked whenever the selection field of a GtkList
15856 has changed. This happens when a child of the GtkList got selected or
15857 deselected.
15858
15859 <tscreen><verb>
15860 void select_child( GtkList   *list,
15861                    GtkWidget *child);
15862 </verb></tscreen>
15863
15864 This signal is invoked when a child of the GtkList is about to get
15865 selected. This happens mainly on calls to gtk_list_select_item(),
15866 gtk_list_select_child(), button presses and sometimes indirectly
15867 triggered on some else occasions where children get added to or
15868 removed from the GtkList.
15869
15870 <tscreen><verb>
15871 void unselect_child( GtkList   *list,
15872                      GtkWidget *child );
15873 </verb></tscreen>
15874
15875 This signal is invoked when a child of the GtkList is about to get
15876 deselected. This happens mainly on calls to gtk_list_unselect_item(),
15877 gtk_list_unselect_child(), button presses and sometimes indirectly
15878 triggered on some else occasions where children get added to or
15879 removed from the GtkList.
15880
15881 <!-- ----------------------------------------------------------------- -->
15882 <sect1> Functions
15883 <p>
15884 <tscreen><verb>
15885 guint gtk_list_get_type( void );
15886 </verb></tscreen>
15887
15888 Returns the `GtkList' type identifier.
15889
15890 <tscreen><verb>
15891 GtkWidget *gtk_list_new( void );
15892 </verb></tscreen>
15893
15894 Create a new GtkList object. The new widget is returned as a pointer
15895 to a GtkWidget object. NULL is returned on failure.
15896
15897 <tscreen><verb>
15898 void gtk_list_insert_items( GtkList *list,
15899                             GList   *items,
15900                             gint     position );
15901 </verb></tscreen>
15902
15903 Insert list items into the list, starting at <tt/position/.
15904 <tt/items/ is a doubly linked list where each nodes data pointer is
15905 expected to point to a newly created GtkListItem.  The GList nodes of
15906 <tt/items/ are taken over by the list.
15907
15908 <tscreen><verb>
15909 void gtk_list_append_items( GtkList *list,
15910                             GList   *items);
15911 </verb></tscreen>
15912
15913 Insert list items just like gtk_list_insert_items() at the end of the
15914 list. The GList nodes of <tt/items/ are taken over by the list.
15915
15916 <tscreen><verb>
15917 void gtk_list_prepend_items( GtkList *list,
15918                              GList   *items);
15919 </verb></tscreen>
15920
15921 Insert list items just like gtk_list_insert_items() at the very
15922 beginning of the list. The GList nodes of <tt/items/ are taken over by
15923 the list.
15924
15925 <tscreen><verb>
15926 void gtk_list_remove_items( GtkList *list,
15927                             GList   *items);
15928 </verb></tscreen>
15929
15930 Remove list items from the list. <tt/items/ is a doubly linked list
15931 where each nodes data pointer is expected to point to a direct child
15932 of list. It is the callers responsibility to make a call to
15933 g_list_free(items) afterwards. Also the caller has to destroy the list
15934 items himself.
15935
15936 <tscreen><verb>
15937 void gtk_list_clear_items( GtkList *list,
15938                            gint start,
15939                            gint end );
15940 </verb></tscreen>
15941
15942 Remove and destroy list items from the list. A widget is affected if
15943 its current position within the list is in the range specified by
15944 <tt/start/ and <tt/end/.
15945
15946 <tscreen><verb>
15947 void gtk_list_select_item( GtkList *list,
15948                            gint     item );
15949 </verb></tscreen>
15950
15951 Invoke the select_child signal for a list item specified through its
15952 current position within the list.
15953
15954 <tscreen><verb>
15955 void gtk_list_unselect_item( GtkList *list,
15956                              gint     item);
15957 </verb></tscreen>
15958
15959 Invoke the unselect_child signal for a list item specified through its
15960 current position within the list.
15961
15962 <tscreen><verb>
15963 void gtk_list_select_child( GtkList *list,
15964                             GtkWidget *child);
15965 </verb></tscreen>
15966
15967 Invoke the select_child signal for the specified child.
15968
15969 <tscreen><verb>
15970 void gtk_list_unselect_child( GtkList   *list,
15971                               GtkWidget *child);
15972 </verb></tscreen>
15973
15974 Invoke the unselect_child signal for the specified child.
15975
15976 <tscreen><verb>
15977 gint gtk_list_child_position( GtkList *list,
15978                               GtkWidget *child);
15979 </verb></tscreen>
15980
15981 Return the position of <tt/child/ within the list. "-1" is returned on
15982 failure.
15983
15984 <tscreen><verb>
15985 void gtk_list_set_selection_mode( GtkList         *list,
15986                                   GtkSelectionMode mode );
15987 </verb></tscreen>
15988
15989 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
15990 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
15991 GTK_SELECTION_EXTENDED.
15992
15993 <tscreen><verb>
15994 GtkList *GTK_LIST( gpointer obj );
15995 </verb></tscreen>
15996
15997 Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
15998 more info.
15999
16000 <tscreen><verb>
16001 GtkListClass *GTK_LIST_CLASS( gpointer class);
16002 </verb></tscreen>
16003
16004 Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
16005 for more info.
16006
16007 <tscreen><verb>
16008 gint GTK_IS_LIST( gpointer obj);
16009 </verb></tscreen>
16010
16011 Determine if a generic pointer refers to a `GtkList' object. *Note
16012 Standard Macros::, for more info.
16013
16014 <!-- ----------------------------------------------------------------- -->
16015 <sect1> Example
16016 <p>
16017 Following is an example program that will print out the changes of the
16018 selection of a GtkList, and lets you "arrest" list items into a prison
16019 by selecting them with the rightmost mouse button.
16020
16021 <tscreen><verb>
16022 /* example-start list list.c */
16023
16024 /* Include the gtk+ header files
16025  * Include stdio.h, we need that for the printf() function
16026  */
16027 #include        <gtk/gtk.h>
16028 #include        <stdio.h>
16029
16030 /* This is our data identification string to store
16031  * data in list items
16032  */
16033 const gchar *list_item_data_key="list_item_data";
16034
16035
16036 /* prototypes for signal handler that we are going to connect
16037  * to the GtkList widget
16038  */
16039 static void  sigh_print_selection( GtkWidget *gtklist,
16040                                    gpointer   func_data);
16041
16042 static void  sigh_button_event( GtkWidget      *gtklist,
16043                                 GdkEventButton *event,
16044                                 GtkWidget      *frame );
16045
16046
16047 /* Main function to set up the user interface */
16048
16049 gint main (int    argc,
16050            gchar *argv[])
16051 {                                  
16052     GtkWidget *separator;
16053     GtkWidget *window;
16054     GtkWidget *vbox;
16055     GtkWidget *scrolled_window;
16056     GtkWidget *frame;
16057     GtkWidget *gtklist;
16058     GtkWidget *button;
16059     GtkWidget *list_item;
16060     GList *dlist;
16061     guint i;
16062     gchar buffer[64];
16063     
16064     
16065     /* Initialize gtk+ (and subsequently gdk) */
16066
16067     gtk_init(&amp;argc, &amp;argv);
16068     
16069     
16070     /* Create a window to put all the widgets in
16071      * connect gtk_main_quit() to the "destroy" event of
16072      * the window to handle window manager close-window-events
16073      */
16074     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
16075     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
16076     gtk_signal_connect(GTK_OBJECT(window),
16077                        "destroy",
16078                        GTK_SIGNAL_FUNC(gtk_main_quit),
16079                        NULL);
16080     
16081     
16082     /* Inside the window we need a box to arrange the widgets
16083      * vertically */
16084     vbox=gtk_vbox_new(FALSE, 5);
16085     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
16086     gtk_container_add(GTK_CONTAINER(window), vbox);
16087     gtk_widget_show(vbox);
16088     
16089     /* This is the scrolled window to put the GtkList widget inside */
16090     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
16091     gtk_widget_set_usize(scrolled_window, 250, 150);
16092     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
16093     gtk_widget_show(scrolled_window);
16094     
16095     /* Create the GtkList widget.
16096      * Connect the sigh_print_selection() signal handler
16097      * function to the "selection_changed" signal of the GtkList
16098      * to print out the selected items each time the selection
16099      * has changed */
16100     gtklist=gtk_list_new();
16101     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
16102                                            gtklist);
16103     gtk_widget_show(gtklist);
16104     gtk_signal_connect(GTK_OBJECT(gtklist),
16105                        "selection_changed",
16106                        GTK_SIGNAL_FUNC(sigh_print_selection),
16107                        NULL);
16108     
16109     /* We create a "Prison" to put a list item in ;) */
16110     frame=gtk_frame_new("Prison");
16111     gtk_widget_set_usize(frame, 200, 50);
16112     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
16113     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
16114     gtk_container_add(GTK_CONTAINER(vbox), frame);
16115     gtk_widget_show(frame);
16116     
16117     /* Connect the sigh_button_event() signal handler to the GtkList
16118      * which will handle the "arresting" of list items
16119      */
16120     gtk_signal_connect(GTK_OBJECT(gtklist),
16121                        "button_release_event",
16122                        GTK_SIGNAL_FUNC(sigh_button_event),
16123                        frame);
16124     
16125     /* Create a separator */
16126     separator=gtk_hseparator_new();
16127     gtk_container_add(GTK_CONTAINER(vbox), separator);
16128     gtk_widget_show(separator);
16129     
16130     /* Finally create a button and connect it's "clicked" signal
16131      * to the destruction of the window */
16132     button=gtk_button_new_with_label("Close");
16133     gtk_container_add(GTK_CONTAINER(vbox), button);
16134     gtk_widget_show(button);
16135     gtk_signal_connect_object(GTK_OBJECT(button),
16136                               "clicked",
16137                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
16138                               GTK_OBJECT(window));
16139     
16140     
16141     /* Now we create 5 list items, each having it's own
16142      * label and add them to the GtkList using gtk_container_add()
16143      * Also we query the text string from the label and
16144      * associate it with the list_item_data_key for each list item
16145      */
16146     for (i=0; i<5; i++) {
16147         GtkWidget       *label;
16148         gchar           *string;
16149         
16150         sprintf(buffer, "ListItemContainer with Label #%d", i);
16151         label=gtk_label_new(buffer);
16152         list_item=gtk_list_item_new();
16153         gtk_container_add(GTK_CONTAINER(list_item), label);
16154         gtk_widget_show(label);
16155         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
16156         gtk_widget_show(list_item);
16157         gtk_label_get(GTK_LABEL(label), &amp;string);
16158         gtk_object_set_data(GTK_OBJECT(list_item),
16159                             list_item_data_key,
16160                             string);
16161     }
16162     /* Here, we are creating another 5 labels, this time
16163      * we use gtk_list_item_new_with_label() for the creation
16164      * we can't query the text string from the label because
16165      * we don't have the labels pointer and therefore
16166      * we just associate the list_item_data_key of each
16167      * list item with the same text string.
16168      * For adding of the list items we put them all into a doubly
16169      * linked list (GList), and then add them by a single call to
16170      * gtk_list_append_items().
16171      * Because we use g_list_prepend() to put the items into the
16172      * doubly linked list, their order will be descending (instead
16173      * of ascending when using g_list_append())
16174      */
16175     dlist=NULL;
16176     for (; i<10; i++) {
16177         sprintf(buffer, "List Item with Label %d", i);
16178         list_item=gtk_list_item_new_with_label(buffer);
16179         dlist=g_list_prepend(dlist, list_item);
16180         gtk_widget_show(list_item);
16181         gtk_object_set_data(GTK_OBJECT(list_item),
16182                             list_item_data_key,
16183                             "ListItem with integrated Label");
16184     }
16185     gtk_list_append_items(GTK_LIST(gtklist), dlist);
16186     
16187     /* Finally we want to see the window, don't we? ;) */
16188     gtk_widget_show(window);
16189     
16190     /* Fire up the main event loop of gtk */
16191     gtk_main();
16192     
16193     /* We get here after gtk_main_quit() has been called which
16194      * happens if the main window gets destroyed
16195      */
16196     return(0);
16197 }
16198
16199 /* This is the signal handler that got connected to button
16200  * press/release events of the GtkList
16201  */
16202 void sigh_button_event( GtkWidget      *gtklist,
16203                         GdkEventButton *event,
16204                         GtkWidget      *frame )
16205 {
16206     /* We only do something if the third (rightmost mouse button
16207      * was released
16208      */
16209     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
16210         event->button==3) {
16211         GList           *dlist, *free_list;
16212         GtkWidget       *new_prisoner;
16213         
16214         /* Fetch the currently selected list item which
16215          * will be our next prisoner ;)
16216          */
16217         dlist=GTK_LIST(gtklist)->selection;
16218         if (dlist)
16219                 new_prisoner=GTK_WIDGET(dlist->data);
16220         else
16221                 new_prisoner=NULL;
16222         
16223         /* Look for already imprisoned list items, we
16224          * will put them back into the list.
16225          * Remember to free the doubly linked list that
16226          * gtk_container_children() returns
16227          */
16228         dlist=gtk_container_children(GTK_CONTAINER(frame));
16229         free_list=dlist;
16230         while (dlist) {
16231             GtkWidget       *list_item;
16232             
16233             list_item=dlist->data;
16234             
16235             gtk_widget_reparent(list_item, gtklist);
16236             
16237             dlist=dlist->next;
16238         }
16239         g_list_free(free_list);
16240         
16241         /* If we have a new prisoner, remove him from the
16242          * GtkList and put him into the frame "Prison".
16243          * We need to unselect the item first.
16244          */
16245         if (new_prisoner) {
16246             GList   static_dlist;
16247             
16248             static_dlist.data=new_prisoner;
16249             static_dlist.next=NULL;
16250             static_dlist.prev=NULL;
16251             
16252             gtk_list_unselect_child(GTK_LIST(gtklist),
16253                                     new_prisoner);
16254             gtk_widget_reparent(new_prisoner, frame);
16255         }
16256     }
16257 }
16258
16259 /* This is the signal handler that gets called if GtkList
16260  * emits the "selection_changed" signal
16261  */
16262 void sigh_print_selection( GtkWidget *gtklist,
16263                            gpointer   func_data)
16264 {
16265     GList   *dlist;
16266     
16267     /* Fetch the doubly linked list of selected items
16268      * of the GtkList, remember to treat this as read-only!
16269      */
16270     dlist=GTK_LIST(gtklist)->selection;
16271     
16272     /* If there are no selected items there is nothing more
16273      * to do than just telling the user so
16274      */
16275     if (!dlist) {
16276         g_print("Selection cleared\n");
16277         return;
16278     }
16279     /* Ok, we got a selection and so we print it
16280      */
16281     g_print("The selection is a ");
16282     
16283     /* Get the list item from the doubly linked list
16284      * and then query the data associated with list_item_data_key.
16285      * We then just print it */
16286     while (dlist) {
16287         GtkObject       *list_item;
16288         gchar           *item_data_string;
16289         
16290         list_item=GTK_OBJECT(dlist->data);
16291         item_data_string=gtk_object_get_data(list_item,
16292                                              list_item_data_key);
16293         g_print("%s ", item_data_string);
16294         
16295         dlist=dlist->next;
16296     }
16297     g_print("\n");
16298 }
16299 /* example-end */
16300 </verb></tscreen>
16301
16302 <!-- ----------------------------------------------------------------- -->
16303 <sect1> List Item Widget
16304 <p>
16305 The GtkListItem widget is designed to act as a container holding up to
16306 one child, providing functions for selection/deselection just like the
16307 GtkList widget requires them for its children.
16308
16309 A GtkListItem has its own window to receive events and has its own
16310 background color which is usually white.
16311
16312 As it is directly derived from a GtkItem it can be treated as such by
16313 using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
16314 this. Usually a GtkListItem just holds a label to identify e.g. a
16315 filename within a GtkList -- therefore the convenience function
16316 gtk_list_item_new_with_label() is provided. The same effect can be
16317 achieved by creating a GtkLabel on its own, setting its alignment to
16318 xalign=0 and yalign=0.5 with a subsequent container addition to the
16319 GtkListItem.
16320
16321 As one is not forced to add a GtkLabel to a GtkListItem, you could
16322 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
16323
16324 <!-- ----------------------------------------------------------------- -->
16325 <sect1> Signals
16326 <p>
16327 A GtkListItem does not create new signals on its own, but inherits
16328 the signals of a GtkItem. *Note GtkItem::, for more info.
16329
16330 <!-- ----------------------------------------------------------------- -->
16331 <sect1> Functions
16332 <p>
16333 <tscreen><verb>
16334 guint gtk_list_item_get_type( void );
16335 </verb></tscreen>
16336
16337 Returns the `GtkListItem' type identifier.
16338
16339 <tscreen><verb>
16340 GtkWidget *gtk_list_item_new( void );
16341 </verb></tscreen>
16342
16343 Create a new GtkListItem object. The new widget is returned as a
16344 pointer to a GtkWidget object. NULL is returned on failure.
16345
16346 <tscreen><verb>
16347 GtkWidget *gtk_list_item_new_with_label( gchar *label );
16348 </verb></tscreen>
16349
16350 Create a new GtkListItem object, having a single GtkLabel as the sole
16351 child. The new widget is returned as a pointer to a GtkWidget
16352 object. NULL is returned on failure.
16353
16354 <tscreen><verb>
16355 void gtk_list_item_select( GtkListItem *list_item );
16356 </verb></tscreen>
16357
16358 This function is basically a wrapper around a call to gtk_item_select
16359 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
16360 GtkItem::, for more info.
16361
16362 <tscreen><verb>
16363 void gtk_list_item_deselect( GtkListItem *list_item );
16364 </verb></tscreen>
16365
16366 This function is basically a wrapper around a call to
16367 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
16368 signal.  *Note GtkItem::, for more info.
16369
16370 <tscreen><verb>
16371 GtkListItem *GTK_LIST_ITEM( gpointer obj );
16372 </verb></tscreen>
16373
16374 Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
16375 more info.
16376
16377 <tscreen><verb>
16378 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
16379 </verb></tscreen>
16380
16381 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
16382 for more info.
16383
16384 <tscreen><verb>
16385 gint GTK_IS_LIST_ITEM( gpointer obj );
16386 </verb></tscreen>
16387
16388 Determine if a generic pointer refers to a `GtkListItem' object.
16389 *Note Standard Macros::, for more info.
16390  
16391 <!-- ----------------------------------------------------------------- -->
16392 <sect1> Example
16393 <p>
16394 Please see the GtkList example on this, which covers the usage of a
16395 GtkListItem as well.
16396
16397
16398 </article>