]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
update I've had sat around: - Grammar patch from James R. Van Zandt
[~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 Tutorial
9 <author>Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
10                               name="&lt;imain@gtk.org&gt;"></tt>,
11 Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
12                               name="&lt;gale@gtk.org&gt;"></tt>
13 <date>September 2nd, 1998
14
15 <!-- ***************************************************************** -->
16 <sect>Introduction
17 <!-- ***************************************************************** -->
18 <p>
19 GTK (GIMP Toolkit) was originally developed as a toolkit for the GIMP
20 (General Image Manipulation Program).  GTK is built on top of GDK (GIMP
21 Drawing Kit) which is basically a wrapper around the Xlib functions.  It's
22 called the GIMP toolkit because it was originally written for developing
23 the GIMP, but has now been used in several free software projects.  The
24 authors are
25 <itemize>
26 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
27                            name="petm@xcf.berkeley.edu"></tt>
28 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
29                            name="spencer@xcf.berkeley.edu"></tt>
30 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
31                            name="jmacd@xcf.berkeley.edu"></tt>
32 </itemize>
33
34 GTK is essentially an object oriented application programmers interface (API).  
35 Although written completely in
36 C, it is implemented using the idea of classes and callback functions
37 (pointers to functions).
38
39 There is also a third component called glib which contains a few
40 replacements for some standard calls, as well as some additional functions
41 for handling linked lists etc.  The replacement functions are used to 
42 increase GTK's portability, as some of the functions implemented 
43 here are not available or are nonstandard on other unicies such as 
44 g_strerror().   Some also contain enhancements to the libc versions, such as
45 g_malloc that has enhanced debugging utilities.
46
47 This tutorial is an attempt to document as much as possible of GTK, it is by 
48 no means complete.  This
49 tutorial assumes a good understanding of C, and how to create C programs.
50 It would be a great benefit for the reader to have previous X programming
51 experience, but it shouldn't be necessary.  If you are learning GTK as your
52 first widget set, please comment on how you found this tutorial, and what
53 you had trouble with.
54 Note that there is also a C++ API for GTK (GTK--) in the works, so if you
55 prefer to use C++, you should look into this instead.  There's also an
56 Objective C wrapper, and Guile bindings available, but I don't follow these.
57
58 I would very much like to hear of any problems you have learning GTK from this
59 document, and would appreciate input as to how it may be improved.
60
61 <!-- ***************************************************************** -->
62 <sect>Getting Started
63 <!-- ***************************************************************** -->
64
65 <p>
66 The first thing to do of course, is download the GTK source and install
67 it.  You can always get the latest version from ftp.gtk.org in /pub/gtk.
68 You can also view other sources of GTK information on http://www.gtk.org/
69 <htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">.
70 GTK uses GNU autoconf for
71 configuration.  Once untar'd, type ./configure --help to see a list of options.
72
73 Th GTK source distribution also contains the complete source to all of the
74 examples used in this tutorial, along with Makefiles to aid compilation.
75
76 To begin our introduction to GTK, we'll start with the simplest program 
77 possible.  This program will
78 create a 200x200 pixel window and has no way of exiting except to be
79 killed using the shell.
80
81 <tscreen><verb>
82 #include <gtk/gtk.h>
83
84 int main (int argc, char *argv[])
85 {
86     GtkWidget *window;
87     
88     gtk_init (&amp;argc, &amp;argv);
89     
90     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
91     gtk_widget_show (window);
92     
93     gtk_main ();
94     
95     return 0;
96 }
97 </verb></tscreen>
98
99 All programs will of course include gtk/gtk.h which declares the
100 variables, functions, structures etc. that will be used in your GTK 
101 application.
102
103 The next line:
104
105 <tscreen><verb>
106 gtk_init (&amp;argc, &amp;argv);
107 </verb></tscreen>
108
109 calls the function gtk_init(gint *argc, gchar ***argv) which will be
110 called in all GTK applications.  This sets up a few things for us such
111 as the default visual and color map and then proceeds to call
112 gdk_init(gint *argc, gchar ***argv).  This function initializes the
113 library for use, sets up default signal handlers, and checks the
114 arguments passed to your application on the command line, looking for one
115 of the following:
116
117 <itemize>
118 <item> <tt/--display/
119 <item> <tt/--debug-level/
120 <item> <tt/--no-xshm/
121 <item> <tt/--sync/
122 <item> <tt/--show-events/
123 <item> <tt/--no-show-events/
124 <item> <tt/--name/
125 <item> <tt/--class/
126 </itemize>
127
128 It removes these from the argument list, leaving anything it does
129 not recognize for your application to parse or ignore. This creates a set
130 of standard arguments accepted by all GTK applications.
131
132 The next two lines of code create and display a window.
133
134 <tscreen><verb>
135   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
136   gtk_widget_show (window);
137 </verb></tscreen>
138
139 The GTK_WINDOW_TOPLEVEL argument specifies that we want the window to
140 undergo window manager decoration and placement. Rather than create a
141 window of 0x0 size, a window without children is set to 200x200 by default
142 so you can still manipulate it.
143
144 The gtk_widget_show() function lets GTK know that we are done setting the
145 attributes of this widget, and that it can display it.
146
147 The last line enters the GTK main processing loop.
148
149 <tscreen><verb>
150 gtk_main ();
151 </verb></tscreen>
152
153 gtk_main() is another call you will see in every GTK application.  When
154 control reaches this point, GTK will sleep waiting for X events (such as
155 button or key presses), timeouts, or file IO notifications to occur.
156 In our simple example however, events are ignored.
157
158 <!-- ----------------------------------------------------------------- -->
159 <sect1>Hello World in GTK
160 <p>
161 OK, now for a program with a widget (a button).  It's the classic hello
162 world ala GTK.
163
164 <tscreen><verb>
165 /* example-start helloworld helloworld.c */
166
167 #include <gtk/gtk.h>
168
169 /* this is a callback function. the data arguments are ignored in this example..
170  * More on callbacks below. */
171 void hello (GtkWidget *widget, gpointer data)
172 {
173     g_print ("Hello World\n");
174 }
175
176 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
177 {
178     g_print ("delete event occurred\n");
179     /* if you return FALSE in the "delete_event" signal handler,
180      * GTK will emit the "destroy" signal.  Returning TRUE means
181      * you don't want the window to be destroyed.
182      * This is useful for popping up 'are you sure you want to quit ?'
183      * type dialogs. */
184
185     /* Change TRUE to FALSE and the main window will be destroyed with
186      * a "delete_event". */
187
188     return (TRUE);
189 }
190
191 /* another callback */
192 void destroy (GtkWidget *widget, gpointer data)
193 {
194     gtk_main_quit ();
195 }
196
197 int main (int argc, char *argv[])
198 {
199     /* GtkWidget is the storage type for widgets */
200     GtkWidget *window;
201     GtkWidget *button;
202     
203     /* this is called in all GTK applications.  arguments are parsed from
204      * the command line and are returned to the application. */
205     gtk_init (&amp;argc, &amp;argv);
206     
207     /* create a new window */
208     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
209     
210     /* when the window is given the "delete_event" signal (this is given
211     * by the window manager, usually by the 'close' option, or on the
212     * titlebar), we ask it to call the delete_event () function
213     * as defined above.  The data passed to the callback
214     * function is NULL and is ignored in the callback function. */
215     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
216                         GTK_SIGNAL_FUNC (delete_event), NULL);
217     
218     /* here we connect the "destroy" event to a signal handler.  
219      * This event occurs when we call gtk_widget_destroy() on the window,
220      * or if we return 'FALSE' in the "delete_event" callback. */
221     gtk_signal_connect (GTK_OBJECT (window), "destroy",
222                         GTK_SIGNAL_FUNC (destroy), NULL);
223     
224     /* sets the border width of the window. */
225     gtk_container_border_width (GTK_CONTAINER (window), 10);
226     
227     /* creates a new button with the label "Hello World". */
228     button = gtk_button_new_with_label ("Hello World");
229     
230     /* When the button receives the "clicked" signal, it will call the
231      * function hello() passing it NULL as its argument.  The hello() function is
232      * defined above. */
233     gtk_signal_connect (GTK_OBJECT (button), "clicked",
234                         GTK_SIGNAL_FUNC (hello), NULL);
235     
236     /* This will cause the window to be destroyed by calling
237      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
238      * signal could come from here, or the window manager. */
239     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
240                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
241                                GTK_OBJECT (window));
242     
243     /* this packs the button into the window (a gtk container). */
244     gtk_container_add (GTK_CONTAINER (window), button);
245     
246     /* the final step is to display this newly created widget... */
247     gtk_widget_show (button);
248     
249     /* and the window */
250     gtk_widget_show (window);
251     
252     /* all GTK applications must have a gtk_main().     Control ends here
253      * and waits for an event to occur (like a key press or mouse event). */
254     gtk_main ();
255     
256     return 0;
257 }
258 /* example-end */
259 </verb></tscreen>
260
261 <!-- ----------------------------------------------------------------- -->
262 <sect1>Compiling Hello World
263 <p>
264 To compile use:
265
266 <tscreen><verb>
267 gcc -Wall -g helloworld.c -o hello_world `gtk-config --cflags` \
268     `gtk-config --libs`
269 </verb></tscreen>
270
271 This uses the program <tt>gtk-config</>, which comes with gtk. This
272 program 'knows' what compiler switches are needed to compile programs
273 that use gtk. <tt>gtk-config --cflags</> will output a list of include
274 directories for the compiler to look in, and <tt>gtk-config --libs</>
275 will output the list of libraries for the compiler to link with and
276 the directories to find them in.
277
278 Note that the type of single quote used in the compile command above
279 is significant.
280
281 The libraries that are usually linked in are:
282 <itemize>
283 <item>The GTK library (-lgtk), the widget library, based on top of GDK.
284 <item>The GDK library (-lgdk), the Xlib wrapper.
285 <item>The glib library (-lglib), containing miscellaneous functions, only
286 g_print() is used in this particular example.  GTK is built on top
287 of glib so you will always require this library.  See the section on 
288 <ref id="sec_glib" name="glib"> for details.  
289 <item>The Xlib library (-lX11) which is used by GDK.
290 <item>The Xext library (-lXext).  This contains code for shared memory
291 pixmaps and other X extensions.
292 <item>The math library (-lm).  This is used by GTK for various purposes.
293 </itemize>
294
295 <!-- ----------------------------------------------------------------- -->
296 <sect1>Theory of Signals and Callbacks
297 <p>
298 Before we look in detail at hello world, we'll discuss signals and callbacks.
299 GTK is an event driven toolkit, which means it will sleep in
300 gtk_main until an event occurs and control is passed to the appropriate
301 function.
302
303 This passing of control is done using the idea of "signals".  When an 
304 event occurs, such as the press of a mouse button, the
305 appropriate signal will be "emitted" by the widget that was pressed.  
306 This is how GTK does most of its useful work. There are a set of signals
307 that all widgets inherit, such as "destroy", and there are signals that are
308 widget specific, such as "toggled" on a toggle button.
309
310 To make a button perform an action, we set up a signal handler to catch these
311 signals and call the appropriate function.  This is done by using a 
312 function such as:
313
314 <tscreen><verb>
315 gint gtk_signal_connect( GtkObject     *object,
316                          gchar         *name,
317                          GtkSignalFunc  func,
318                          gpointer       func_data );
319 </verb></tscreen>
320
321 Where the first argument is the widget which will be emitting the signal, and
322 the second, the name of the signal you wish to catch.  The third is the function
323 you wish to be called when it is caught, and the fourth, the data you wish
324 to have passed to this function.
325
326 The function specified in the third argument is called a "callback
327 function", and should generally be of the form:
328
329 <tscreen><verb>
330 void callback_func( GtkWidget *widget,
331                     gpointer   callback_data );
332 </verb></tscreen>
333
334 Where the first argument will be a pointer to the widget that emitted the 
335 signal, and the second, a pointer to the data given as the last argument
336 to the gtk_signal_connect() function as shown above.
337
338 Note that the above form for a signal callback function declaration is
339 only a general guide, as some widget specific signals generate different
340 calling parameters. For example, the GtkCList "select_row" signal provides
341 both row and column parameters.
342
343 Another call used in the hello world example, is:
344
345 <tscreen><verb>
346 gint gtk_signal_connect_object( GtkObject     *object,
347                                 gchar         *name,
348                                 GtkSignalFunc  func,
349                                 GtkObject     *slot_object );
350 </verb></tscreen>
351
352 gtk_signal_connect_object() is the same as gtk_signal_connect() except that
353 the callback function only uses one argument, a pointer to a GTK 
354 object.  So when using this function to connect signals, the callback
355 should be of the form:
356
357 <tscreen><verb>
358 void callback_func( GtkObject *object );
359 </verb></tscreen>
360
361 Where the object is usually a widget.  We usually don't setup callbacks for
362 gtk_signal_connect_object however.  They are usually used 
363 to call a GTK function that accepts a single widget or object as an
364 argument, as is the case in our hello world example.
365
366 The purpose of having two functions to connect signals is simply to allow
367 the callbacks to have a different number of arguments.  Many functions in
368 the GTK library accept only a single GtkWidget pointer as an argument, so you
369 want to use the gtk_signal_connect_object() for these, whereas for your 
370 functions, you may need to have additional data supplied to the callbacks.
371
372 <!-- ----------------------------------------------------------------- -->
373 <sect1>Events
374 <p>
375 In addition to the signal mechanism described above, there are a set of
376 <em>events</em> that reflect the X event mechanism. Callbacks may also be
377 attached to these events. These events are:
378
379 <itemize>
380 <item> event
381 <item> button_press_event
382 <item> button_release_event
383 <item> motion_notify_event
384 <item> delete_event
385 <item> destroy_event
386 <item> expose_event
387 <item> key_press_event
388 <item> key_release_event
389 <item> enter_notify_event
390 <item> leave_notify_event
391 <item> configure_event
392 <item> focus_in_event
393 <item> focus_out_event
394 <item> map_event
395 <item> unmap_event
396 <item> property_notify_event
397 <item> selection_clear_event
398 <item> selection_request_event
399 <item> selection_notify_event
400 <item> proximity_in_event
401 <item> proximity_out_event
402 <item> drag_begin_event
403 <item> drag_request_event
404 <item> drag_end_event
405 <item> drop_enter_event
406 <item> drop_leave_event
407 <item> drop_data_available_event
408 <item> other_event
409 </itemize>
410
411 In order to connect a callback function to one of these events, you use
412 the function gtk_signal_connect, as described above, using one of the
413 above event names as the <tt/name/ parameter. The callback function for
414 events has a slightly different form than that for signals:
415
416 <tscreen><verb>
417 void callback_func( GtkWidget *widget,
418                     GdkEvent  *event,
419                     gpointer   callback_data );
420 </verb></tscreen>
421
422 GdkEvent is a C <tt/union/ structure whose type will depend upon which of the
423 above events has occurred. In order for us to tell which event has been issued
424 each of the possible alternatives has a <tt/type/ parameter which reflects the
425 event being issued. The other components of the event structure will depend
426 upon the type of the event. Possible values for the type are:
427
428 <tscreen><verb>
429   GDK_NOTHING
430   GDK_DELETE
431   GDK_DESTROY
432   GDK_EXPOSE
433   GDK_MOTION_NOTIFY
434   GDK_BUTTON_PRESS
435   GDK_2BUTTON_PRESS
436   GDK_3BUTTON_PRESS
437   GDK_BUTTON_RELEASE
438   GDK_KEY_PRESS
439   GDK_KEY_RELEASE
440   GDK_ENTER_NOTIFY
441   GDK_LEAVE_NOTIFY
442   GDK_FOCUS_CHANGE
443   GDK_CONFIGURE
444   GDK_MAP
445   GDK_UNMAP
446   GDK_PROPERTY_NOTIFY
447   GDK_SELECTION_CLEAR
448   GDK_SELECTION_REQUEST
449   GDK_SELECTION_NOTIFY
450   GDK_PROXIMITY_IN
451   GDK_PROXIMITY_OUT
452   GDK_DRAG_BEGIN
453   GDK_DRAG_REQUEST
454   GDK_DROP_ENTER
455   GDK_DROP_LEAVE
456   GDK_DROP_DATA_AVAIL
457   GDK_CLIENT_EVENT
458   GDK_VISIBILITY_NOTIFY
459   GDK_NO_EXPOSE
460   GDK_OTHER_EVENT       /* Deprecated, use filters instead */
461 </verb></tscreen>
462
463 So, to connect a callback function to one of these events we would use
464 something like
465
466 <tscreen><verb>
467 gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
468                     GTK_SIGNAL_FUNC(button_press_callback), 
469                         NULL);
470 </verb></tscreen>
471
472 This assumes that <tt/button/ is a GtkButton widget. Now, when the mouse is
473 over the button and a mouse button is pressed, the function 
474 <tt/button_press_callback/ will be called. This function may be declared as:
475
476 <tscreen><verb>
477 static gint button_press_event (GtkWidget      *widget, 
478                                 GdkEventButton *event,
479                                 gpointer        data);
480 </verb></tscreen>
481
482 Note that we can declare the second argument as type <tt/GdkEventButton/
483 as we know what type of event will occur for this function to be called.
484
485 The value returned from this function indicates whether the event should
486 be propagated further by the GTK event handling mechanism. Returning
487 TRUE indicates that the event has been handled, and that it should not
488 propagate further. Returning FALSE continues the normal event handling.
489 See the section on
490 <ref id="sec_Adv_Events_and_Signals"
491 name="Advanced Event and Signal Handling"> for more details on this
492 propagation process.
493
494 For details on the GdkEvent data types, see the appendix entitled
495 <ref id="sec_GDK_Event_Types" name="GDK Event Types">.
496
497 <!-- ----------------------------------------------------------------- -->
498 <sect1>Stepping Through Hello World
499 <p>
500 Now that we know the theory behind this, lets clarify by walking through 
501 the example hello world program.
502
503 Here is the callback function that will be called when the button is
504 "clicked".  We ignore both the widget and the data in this example, but it 
505 is not hard to do things with them.  The next example will use the data 
506 argument to tell us which button was pressed.
507
508 <tscreen><verb>
509 void hello (GtkWidget *widget, gpointer data)
510 {
511     g_print ("Hello World\n");
512 }
513 </verb></tscreen>
514
515 The next callback is a bit special.  The "delete_event" occurs when the
516 window manager sends this event to the application.  We have a choice here
517 as to what to do about these events.  We can ignore them, make some sort of
518 response, or simply quit the application.
519
520 The value you return in this callback lets GTK know what action to take.
521 By returning TRUE, we let it know that we don't want to have the "destroy"
522 signal emitted, keeping our application running.  By returning FALSE, we 
523 ask that "destroy" is emitted, which in turn will call our "destroy" 
524 signal handler.
525
526 <tscreen><verb>
527 gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
528 {
529     g_print ("delete event occurred\n");
530
531     return (TRUE); 
532 }
533 </verb></tscreen>
534
535 Here is another callback function which causes the program to quit by calling
536 gtk_main_quit().  This function tells GTK that it is to exit from gtk_main
537 when control is returned to it.
538
539 <tscreen><verb>
540 void destroy (GtkWidget *widget, gpointer data)
541 {
542     gtk_main_quit ();
543 }
544 </verb></tscreen>
545
546 I assume you know about the main() function... yes, as with other
547 applications, all GTK applications will also have one of these.
548
549 <tscreen><verb>
550 int main (int argc, char *argv[])
551 {
552 </verb></tscreen>
553
554 This next part, declares a pointer to a structure of type GtkWidget.  These
555 are used below to create a window and a button.
556
557 <tscreen><verb>
558     GtkWidget *window;
559     GtkWidget *button;
560 </verb></tscreen>
561
562 Here is our gtk_init again. As before, this initializes the toolkit, and
563 parses the arguments found on the command line.  Any argument it
564 recognizes from the command line, it removes from the list, and modifies
565 argc and argv to make it look like they never existed, allowing your
566 application to parse the remaining arguments.
567
568 <tscreen><verb>
569     gtk_init (&amp;argc, &amp;argv);
570 </verb></tscreen>
571
572 Create a new window.  This is fairly straight forward.  Memory is allocated
573 for the GtkWidget *window structure so it now points to a valid structure.
574 It sets up a new window, but it is not displayed until we call
575 gtk_widget_show(window) near the end of our program.
576
577 <tscreen><verb>
578     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
579 </verb></tscreen>
580
581 Here is an example of connecting a signal handler to an object, in
582 this case, the window.  Here, the "destroy" signal is caught.  This is
583 emitted when we use the window manager to kill the window (and we return
584 TRUE in the "delete_event" handler), or when we use the
585 gtk_widget_destroy() call passing in the window widget as the object to
586 destroy. By setting this up, we handle both cases with a single call.
587 Here, it just calls the destroy() function defined above with a NULL
588 argument, which quits GTK for us.  
589
590 The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform type 
591 casting and checking for us, as well as aid the readability of the code.
592
593 <tscreen><verb>
594     gtk_signal_connect (GTK_OBJECT (window), "destroy",
595                         GTK_SIGNAL_FUNC (destroy), NULL);
596 </verb></tscreen>
597
598 This next function is used to set an attribute of a container object.  
599 This just sets the window
600 so it has a blank area along the inside of it 10 pixels wide where no
601 widgets will go.  There are other similar functions which we will look at 
602 in the section on 
603 <ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
604
605 And again, GTK_CONTAINER is a macro to perform type casting.
606
607 <tscreen><verb>
608     gtk_container_border_width (GTK_CONTAINER (window), 10);
609 </verb></tscreen>
610
611 This call creates a new button.  It allocates space for a new GtkWidget
612 structure in memory, initializes it, and makes the button pointer point to
613 it. It will have the label "Hello World" on it when displayed.
614
615 <tscreen><verb>
616     button = gtk_button_new_with_label ("Hello World");
617 </verb></tscreen>
618
619 Here, we take this button, and make it do something useful.  We attach a
620 signal handler to it so when it emits the "clicked" signal, our hello()
621 function is called.  The data is ignored, so we simply pass in NULL to the
622 hello() callback function.  Obviously, the "clicked" signal is emitted when
623 we click the button with our mouse pointer.
624
625 <tscreen><verb>
626     gtk_signal_connect (GTK_OBJECT (button), "clicked",
627                         GTK_SIGNAL_FUNC (hello), NULL);
628 </verb></tscreen>
629
630 We are also going to use this button to exit our program.  This will
631 illustrate how the "destroy"
632 signal may come from either the window manager, or our program.  When the
633 button is "clicked", same as above, it calls the first hello() callback function,
634 and then this one in the order they are set up.  You may have as many
635 callback functions as you need, and all will be executed in the order you
636 connected them.  Because the gtk_widget_destroy() function accepts only a
637 GtkWidget *widget as an argument, we use the gtk_signal_connect_object()
638 function here instead of straight gtk_signal_connect().
639
640 <tscreen><verb>
641 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
642                            GTK_SIGNAL_FUNC (gtk_widget_destroy),
643                            GTK_OBJECT (window));
644 </verb></tscreen>
645
646 This is a packing call, which will be explained in depth later on.  But it
647 is fairly easy to understand.  It simply tells GTK that the button is to be 
648 placed in the window where it will be displayed. Note that a GTK container
649 can only contain one widget. There are other widgets, that are described later,
650 which are designed to layout multiple widgets in various ways.
651  
652 <tscreen><verb>
653     gtk_container_add (GTK_CONTAINER (window), button);
654 </verb></tscreen>
655
656 Now we have everything set up the way we want it to be.  With all the
657 signal handlers in place, and the button placed in the window where it
658 should be, we ask GTK to "show" the widgets on the screen.  The window
659 widget is shown last so the whole window will pop up at once rather than
660 seeing the window pop up, and then the button form inside of it.  Although
661 with such a simple example, you'd never notice.
662
663 <tscreen><verb>
664     gtk_widget_show (button);
665
666     gtk_widget_show (window);
667 </verb></tscreen>
668
669 And of course, we call gtk_main() which waits for events to come from the X
670 server and will call on the widgets to emit signals when these events come.
671
672 <tscreen><verb>
673     gtk_main ();
674 </verb></tscreen>
675
676 And the final return.  Control returns here after gtk_quit() is called.
677
678 <tscreen><verb>
679     return 0;
680 </verb></tscreen>
681
682 Now, when we click the mouse button on a GTK button, the
683 widget emits a "clicked" signal.  In order for us to use this
684 information, our program sets up a signal handler to catch that signal, 
685 which dispatches the function of our choice. In our example, when the 
686 button we created is "clicked", the hello() function is called with a NULL
687 argument, and then the next handler for this signal is called.  This calls
688 the gtk_widget_destroy() function, passing it the window widget as its
689 argument, destroying the window widget.  This causes the window to emit the 
690 "destroy" signal, which is caught, and calls our destroy() callback 
691 function, which simply exits GTK.
692
693 Another course of events, is to use the window manager to kill the window.
694 This will cause the "delete_event" to be emitted.  This will call our
695 "delete_event" handler.  If we return TRUE here, the window will be left as
696 is and nothing will happen.  Returning FALSE will cause GTK to emit the
697 "destroy" signal which of course, calls the "destroy" callback, exiting GTK.
698
699 Note that these signals are not the same as the Unix system
700 signals, and are not implemented using them, although the terminology is
701 almost identical.
702
703 <!-- ***************************************************************** -->
704 <sect>Moving On
705 <!-- ***************************************************************** -->
706
707 <!-- ----------------------------------------------------------------- -->
708 <sect1>Data Types
709 <p>
710 There are a few things you probably noticed in the previous examples that
711 need explaining.  The gint, gchar etc. that you see are typedefs to int and 
712 char respectively.  This is done to get around that nasty dependency on the 
713 size of simple data types when doing calculations.
714
715 A good example is "gint32" which will be typedef'd to a 32 bit integer for
716 any given platform, whether it be the 64 bit alpha, or the 32 bit i386.  The
717 typedefs are very straight forward and intuitive.  They are all defined in
718 glib/glib.h (which gets included from gtk.h).
719
720 You'll also notice the ability to use GtkWidget when the function calls for 
721 a GtkObject. GTK is an object oriented design, and a widget is an object.
722
723 <!-- ----------------------------------------------------------------- -->
724 <sect1>More on Signal Handlers
725 <p>
726 Lets take another look at the gtk_signal_connect declaration.
727
728 <tscreen><verb>
729 gint gtk_signal_connect( GtkObject *object,
730                          gchar *name,
731                          GtkSignalFunc func,
732                          gpointer func_data );
733 </verb></tscreen>
734
735 Notice the gint return value ?  This is a tag that identifies your callback
736 function.  As said above, you may have as many callbacks per signal and per
737 object as you need, and each will be executed in turn, in the order they 
738 were attached.
739
740 This tag allows you to remove this callback from the list by using:
741
742 <tscreen><verb>
743 void gtk_signal_disconnect( GtkObject *object,
744                             gint id );
745 </verb></tscreen>
746
747 So, by passing in the widget you wish to remove the handler from, and the
748 tag or id returned by one of the signal_connect functions, you can
749 disconnect a signal handler.
750
751 Another function to remove all the signal handers from an object is:
752
753 <tscreen><verb>
754 void gtk_signal_handlers_destroy( GtkObject *object );
755 </verb></tscreen>
756
757 This call is fairly self explanatory.  It simply removes all the current
758 signal handlers from the object passed in as the first argument.
759
760 <!-- ----------------------------------------------------------------- -->
761 <sect1>An Upgraded Hello World
762 <p>
763 Let's take a look at a slightly improved hello world with better examples
764 of callbacks.  This will also introduce us to our next topic, packing
765 widgets.
766
767 <tscreen><verb>
768 /* example-start helloworld2 helloworld2.c */
769
770 #include <gtk/gtk.h>
771
772 /* Our new improved callback.  The data passed to this function is printed
773  * to stdout. */
774 void callback (GtkWidget *widget, gpointer data)
775 {
776     g_print ("Hello again - %s was pressed\n", (char *) data);
777 }
778
779 /* another callback */
780 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
781 {
782     gtk_main_quit ();
783 }
784
785 int main (int argc, char *argv[])
786 {
787     /* GtkWidget is the storage type for widgets */
788     GtkWidget *window;
789     GtkWidget *button;
790     GtkWidget *box1;
791
792     /* this is called in all GTK applications.  arguments are parsed from
793      * the command line and are returned to the application. */
794     gtk_init (&amp;argc, &amp;argv);
795
796     /* create a new window */
797     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
798
799     /* this is a new call, this just sets the title of our
800      * new window to "Hello Buttons!" */
801     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
802
803     /* Here we just set a handler for delete_event that immediately
804      * exits GTK. */
805     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
806                         GTK_SIGNAL_FUNC (delete_event), NULL);
807
808
809     /* sets the border width of the window. */
810     gtk_container_border_width (GTK_CONTAINER (window), 10);
811
812     /* we create a box to pack widgets into.  this is described in detail
813      * in the "packing" section below.  The box is not really visible, it
814      * is just used as a tool to arrange widgets. */
815     box1 = gtk_hbox_new(FALSE, 0);
816
817     /* put the box into the main window. */
818     gtk_container_add (GTK_CONTAINER (window), box1);
819
820     /* creates a new button with the label "Button 1". */
821     button = gtk_button_new_with_label ("Button 1");
822
823     /* Now when the button is clicked, we call the "callback" function
824      * with a pointer to "button 1" as its argument */
825     gtk_signal_connect (GTK_OBJECT (button), "clicked",
826                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
827
828     /* instead of gtk_container_add, we pack this button into the invisible
829      * box, which has been packed into the window. */
830     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
831
832     /* always remember this step, this tells GTK that our preparation for
833      * this button is complete, and it can be displayed now. */
834     gtk_widget_show(button);
835
836     /* do these same steps again to create a second button */
837     button = gtk_button_new_with_label ("Button 2");
838
839     /* call the same callback function with a different argument,
840      * passing a pointer to "button 2" instead. */
841     gtk_signal_connect (GTK_OBJECT (button), "clicked",
842                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
843
844     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
845
846     /* The order in which we show the buttons is not really important, but I
847      * recommend showing the window last, so it all pops up at once. */
848     gtk_widget_show(button);
849
850     gtk_widget_show(box1);
851
852     gtk_widget_show (window);
853
854     /* rest in gtk_main and wait for the fun to begin! */
855     gtk_main ();
856
857     return 0;
858 }
859 /* example-end */
860 </verb></tscreen>
861
862 Compile this program using the same linking arguments as our first example.
863 You'll notice this time there is no easy way to exit the program, you have 
864 to use your window manager or command line to kill it.  A good exercise 
865 for the reader would be to insert a third "Quit" button that will exit the
866 program.  You may also wish to play with the options to
867 gtk_box_pack_start() while reading the next section.  
868 Try resizing the window, and observe the behavior.
869
870 Just as a side note, there is another useful define for gtk_window_new() -
871 GTK_WINDOW_DIALOG.  This interacts with the window manager a little
872 differently and should be used for transient windows.
873
874 <!-- ***************************************************************** -->
875 <sect>Packing Widgets
876 <!-- ***************************************************************** -->
877 <p>
878 When creating an application, you'll want to put more than one widget
879 inside a window.  Our first hello world example only used one widget so we
880 could simply use a gtk_container_add call to "pack" the widget into the
881 window.  But when you want to put more than one widget into a window, how
882 do you control where that widget is positioned? This is where packing
883 comes in.
884
885 <!-- ----------------------------------------------------------------- -->
886 <sect1>Theory of Packing Boxes
887 <p>
888 Most packing is done by creating boxes as in the example above.  These are
889 invisible widget containers that we can pack our widgets into which come in
890 two forms, a horizontal box, and a vertical box.  When packing widgets
891 into a horizontal box, the objects are inserted horizontally from left to
892 right or right to left depending on the call used. In a vertical box,
893 widgets are packed from top to bottom or vice versa.  You may use any
894 combination of boxes inside or beside other boxes to create the desired
895 effect.
896
897 To create a new horizontal box, we use a call to gtk_hbox_new(), and for
898 vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and
899 gtk_box_pack_end() functions are used to place objects inside of these
900 containers.  The gtk_box_pack_start() function will start at the top and
901 work its way down in a vbox, and pack left to right in an hbox.
902 gtk_box_pack_end() will do the opposite, packing from bottom to top in a
903 vbox, and right to left in an hbox.  Using these functions allow us to
904 right justify or left justify our widgets and may be mixed in any way to
905 achieve the desired effect. We will use gtk_box_pack_start() in most of
906 our examples.  An object may be another container or a widget. In
907 fact, many widgets are actually containers themselves, including the
908 button, but we usually only use a label inside a button.
909
910 By using these calls, GTK knows where you want to place your widgets so it
911 can do automatic resizing and other nifty things. There's also a number
912 of options as to how your widgets should be packed. As you can imagine,
913 this method gives us a quite a bit of flexibility when placing and
914 creating widgets.
915
916 <!-- ----------------------------------------------------------------- -->
917 <sect1>Details of Boxes
918 <p>
919 Because of this flexibility, packing boxes in GTK can be confusing at
920 first. There are a lot of options, and it's not immediately obvious how
921 they all fit together.  In the end however, there are basically five
922 different styles.
923
924 <? <CENTER> >
925 <?
926 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528" HEIGHT="235"
927 ALT="Box Packing Example Image">
928 >
929 <? </CENTER> >
930
931 Each line contains one horizontal box (hbox) with several buttons. The
932 call to gtk_box_pack is shorthand for the call to pack each of the buttons
933 into the hbox. Each of the buttons is packed into the hbox the same way
934 (i.e. same arguments to the gtk_box_pack_start() function).
935
936 This is the declaration of the gtk_box_pack_start function.
937
938 <tscreen><verb>
939 void gtk_box_pack_start( GtkBox    *box,
940                          GtkWidget *child,
941                          gint       expand,
942                          gint       fill,
943                          gint       padding );
944 </verb></tscreen>
945
946 The first argument is the box you are packing the object into, the second
947 is the object. The objects will all be buttons for now, so we'll be
948 packing buttons into boxes.
949
950 The expand argument to gtk_box_pack_start() and gtk_box_pack_end() controls
951 whether the widgets are laid out in the box to fill in all the extra space
952 in the box so the box is expanded to fill the area alloted to it (TRUE).
953 Or the box is shrunk to just fit the widgets (FALSE). Setting expand to
954 FALSE will allow you to do right and left justification of your widgets.
955 Otherwise, they will all expand to fit into the box, and the same effect
956 could be achieved by using only one of gtk_box_pack_start or pack_end functions.
957
958 The fill argument to the gtk_box_pack functions control whether the extra
959 space is allocated to the objects themselves (TRUE), or as extra padding
960 in the box around these objects (FALSE). It only has an effect if the
961 expand argument is also TRUE.
962
963 When creating a new box, the function looks like this:
964
965 <tscreen><verb>
966 GtkWidget *gtk_hbox_new (gint homogeneous,
967                          gint spacing);
968 </verb></tscreen>
969
970 The homogeneous argument to gtk_hbox_new (and the same for gtk_vbox_new)
971 controls whether each object in the box has the same size (i.e. the same
972 width in an hbox, or the same height in a vbox). If it is set, the expand
973 argument to the gtk_box_pack routines is always turned on.
974
975 What's the difference between spacing (set when the box is created) and
976 padding (set when elements are packed)? Spacing is added between objects,
977 and padding is added on either side of an object. The following figure
978 should make it clearer:
979
980 <? <CENTER> >
981 <?
982 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509" HEIGHT="213"
983 VSPACE="15" HSPACE="10" ALT="Box Packing Example Image">
984 >
985 <? </CENTER> >
986
987 Here is the code used to create the above images.  I've commented it fairly
988 heavily so hopefully you won't have any problems following it.  Compile it 
989 yourself and play with it.
990
991 <!-- ----------------------------------------------------------------- -->
992 <sect1>Packing Demonstration Program
993 <p>
994 <tscreen><verb>
995 /* example-start packbox packbox.c */
996
997 #include <stdio.h>
998 #include "gtk/gtk.h"
999
1000 void
1001 delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
1002 {
1003     gtk_main_quit ();
1004 }
1005
1006 /* Make a new hbox filled with button-labels. Arguments for the 
1007  * variables we're interested are passed in to this function. 
1008  * We do not show the box, but do show everything inside. */
1009 GtkWidget *make_box (gint homogeneous, gint spacing,
1010                      gint expand, gint fill, gint padding) 
1011 {
1012     GtkWidget *box;
1013     GtkWidget *button;
1014     char padstr[80];
1015     
1016     /* create a new hbox with the appropriate homogeneous and spacing
1017      * settings */
1018     box = gtk_hbox_new (homogeneous, spacing);
1019     
1020     /* create a series of buttons with the appropriate settings */
1021     button = gtk_button_new_with_label ("gtk_box_pack");
1022     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1023     gtk_widget_show (button);
1024     
1025     button = gtk_button_new_with_label ("(box,");
1026     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1027     gtk_widget_show (button);
1028     
1029     button = gtk_button_new_with_label ("button,");
1030     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1031     gtk_widget_show (button);
1032     
1033     /* create a button with the label depending on the value of
1034      * expand. */
1035     if (expand == TRUE)
1036             button = gtk_button_new_with_label ("TRUE,");
1037     else
1038             button = gtk_button_new_with_label ("FALSE,");
1039     
1040     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1041     gtk_widget_show (button);
1042     
1043     /* This is the same as the button creation for "expand"
1044      * above, but uses the shorthand form. */
1045     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1046     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1047     gtk_widget_show (button);
1048     
1049     sprintf (padstr, "%d);", padding);
1050     
1051     button = gtk_button_new_with_label (padstr);
1052     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1053     gtk_widget_show (button);
1054     
1055     return box;
1056 }
1057
1058 int
1059 main (int argc, char *argv[])
1060 {
1061     GtkWidget *window;
1062     GtkWidget *button;
1063     GtkWidget *box1;
1064     GtkWidget *box2;
1065     GtkWidget *separator;
1066     GtkWidget *label;
1067     GtkWidget *quitbox;
1068     int which;
1069     
1070     /* Our init, don't forget this! :) */
1071     gtk_init (&amp;argc, &amp;argv);
1072     
1073     if (argc != 2) {
1074         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1075         /* this just does cleanup in GTK, and exits with an exit status of 1. */
1076         gtk_exit (1);
1077     }
1078     
1079     which = atoi (argv[1]);
1080
1081     /* Create our window */
1082     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1083
1084     /* You should always remember to connect the destroy signal to the
1085      * main window.  This is very important for proper intuitive
1086      * behavior */
1087     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1088                         GTK_SIGNAL_FUNC (delete_event), NULL);
1089     gtk_container_border_width (GTK_CONTAINER (window), 10);
1090     
1091     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1092      * This allows us to stack the horizontal boxes filled with buttons one
1093      * on top of the other in this vbox. */
1094     box1 = gtk_vbox_new (FALSE, 0);
1095     
1096     /* which example to show.  These correspond to the pictures above. */
1097     switch (which) {
1098     case 1:
1099         /* create a new label. */
1100         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1101         
1102         /* Align the label to the left side.  We'll discuss this function and 
1103          * others in the section on Widget Attributes. */
1104         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1105
1106         /* Pack the label into the vertical box (vbox box1).  Remember that 
1107          * widgets added to a vbox will be packed one on top of the other in
1108          * order. */
1109         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1110         
1111         /* show the label */
1112         gtk_widget_show (label);
1113         
1114         /* call our make box function - homogeneous = FALSE, spacing = 0,
1115          * expand = FALSE, fill = FALSE, padding = 0 */
1116         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1117         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1118         gtk_widget_show (box2);
1119
1120         /* call our make box function - homogeneous = FALSE, spacing = 0,
1121          * expand = FALSE, fill = FALSE, padding = 0 */
1122         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1123         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1124         gtk_widget_show (box2);
1125         
1126         /* Args are: homogeneous, spacing, expand, fill, padding */
1127         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1128         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1129         gtk_widget_show (box2);
1130         
1131         /* creates a separator, we'll learn more about these later, 
1132          * but they are quite simple. */
1133         separator = gtk_hseparator_new ();
1134         
1135         /* pack the separator into the vbox.  Remember each of these
1136          * widgets are being packed into a vbox, so they'll be stacked
1137          * vertically. */
1138         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1139         gtk_widget_show (separator);
1140         
1141         /* create another new label, and show it. */
1142         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1143         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1144         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1145         gtk_widget_show (label);
1146         
1147         /* Args are: homogeneous, spacing, expand, fill, padding */
1148         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1149         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1150         gtk_widget_show (box2);
1151         
1152         /* Args are: homogeneous, spacing, expand, fill, padding */
1153         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1154         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1155         gtk_widget_show (box2);
1156         
1157         /* another new separator. */
1158         separator = gtk_hseparator_new ();
1159         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1160         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1161         gtk_widget_show (separator);
1162         
1163         break;
1164
1165     case 2:
1166
1167         /* create a new label, remember box1 is a vbox as created 
1168          * near the beginning of main() */
1169         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1170         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1171         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1172         gtk_widget_show (label);
1173         
1174         /* Args are: homogeneous, spacing, expand, fill, padding */
1175         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1176         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1177         gtk_widget_show (box2);
1178         
1179         /* Args are: homogeneous, spacing, expand, fill, padding */
1180         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1181         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1182         gtk_widget_show (box2);
1183         
1184         separator = gtk_hseparator_new ();
1185         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1186         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1187         gtk_widget_show (separator);
1188         
1189         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1190         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1191         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1192         gtk_widget_show (label);
1193         
1194         /* Args are: homogeneous, spacing, expand, fill, padding */
1195         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1196         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1197         gtk_widget_show (box2);
1198         
1199         /* Args are: homogeneous, spacing, expand, fill, padding */
1200         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1201         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1202         gtk_widget_show (box2);
1203         
1204         separator = gtk_hseparator_new ();
1205         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1206         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1207         gtk_widget_show (separator);
1208         break;
1209     
1210     case 3:
1211
1212     /* This demonstrates the ability to use gtk_box_pack_end() to
1213          * right justify widgets.  First, we create a new box as before. */
1214         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1215         /* create the label that will be put at the end. */
1216         label = gtk_label_new ("end");
1217         /* pack it using gtk_box_pack_end(), so it is put on the right side
1218          * of the hbox created in the make_box() call. */
1219         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1220         /* show the label. */
1221         gtk_widget_show (label);
1222         
1223         /* pack box2 into box1 (the vbox remember ? :) */
1224         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1225         gtk_widget_show (box2);
1226         
1227         /* a separator for the bottom. */
1228         separator = gtk_hseparator_new ();
1229         /* this explicitly sets the separator to 400 pixels wide by 5 pixels
1230          * high.  This is so the hbox we created will also be 400 pixels wide,
1231          * and the "end" label will be separated from the other labels in the
1232          * hbox.  Otherwise, all the widgets in the hbox would be packed as
1233          * close together as possible. */
1234         gtk_widget_set_usize (separator, 400, 5);
1235         /* pack the separator into the vbox (box1) created near the start 
1236          * of main() */
1237         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1238         gtk_widget_show (separator);    
1239     }
1240     
1241     /* Create another new hbox.. remember we can use as many as we need! */
1242     quitbox = gtk_hbox_new (FALSE, 0);
1243     
1244     /* Our quit button. */
1245     button = gtk_button_new_with_label ("Quit");
1246     
1247     /* setup the signal to destroy the window.  Remember that this will send
1248      * the "destroy" signal to the window which will be caught by our signal
1249      * handler as defined above. */
1250     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1251                                GTK_SIGNAL_FUNC (gtk_main_quit),
1252                                GTK_OBJECT (window));
1253     /* pack the button into the quitbox.
1254      * The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1255     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1256     /* pack the quitbox into the vbox (box1) */
1257     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1258     
1259     /* pack the vbox (box1) which now contains all our widgets, into the
1260      * main window. */
1261     gtk_container_add (GTK_CONTAINER (window), box1);
1262     
1263     /* and show everything left */
1264     gtk_widget_show (button);
1265     gtk_widget_show (quitbox);
1266     
1267     gtk_widget_show (box1);
1268     /* Showing the window last so everything pops up at once. */
1269     gtk_widget_show (window);
1270     
1271     /* And of course, our main function. */
1272     gtk_main ();
1273
1274     /* control returns here when gtk_main_quit() is called, but not when 
1275      * gtk_exit is used. */
1276     
1277     return 0;
1278 }
1279 /* example-end */
1280 </verb></tscreen>
1281
1282 <!-- ----------------------------------------------------------------- -->
1283 <sect1>Packing Using Tables
1284 <p>
1285 Let's take a look at another way of packing - Tables.  These can be
1286 extremely useful in certain situations.
1287
1288 Using tables, we create a grid that we can place widgets in. The widgets
1289 may take up as many spaces as we specify.
1290
1291 The first thing to look at of course, is the gtk_table_new function:
1292
1293 <tscreen><verb>
1294 GtkWidget *gtk_table_new( gint rows,
1295                           gint columns,
1296                           gint homogeneous );
1297 </verb></tscreen>
1298
1299 The first argument is the number of rows to make in the table, while the
1300 second, obviously, is the number of columns.
1301
1302 The homogeneous argument has to do with how the table's boxes are sized. If
1303 homogeneous is TRUE, the table boxes are resized to the size of the largest
1304 widget in the table. If homogeneous is FALSE, the size of a table boxes is 
1305 dictated by the tallest widget in its same row, and the widest widget in its
1306 column.
1307
1308 The rows and columns are laid out from 0 to n, where n was the
1309 number specified in the call to gtk_table_new.  So, if you specify rows = 2 and 
1310 columns = 2, the layout would look something like this:
1311
1312 <tscreen><verb>
1313  0          1          2
1314 0+----------+----------+
1315  |          |          |
1316 1+----------+----------+
1317  |          |          |
1318 2+----------+----------+
1319 </verb></tscreen>
1320
1321 Note that the coordinate system starts in the upper left hand corner.  To place a 
1322 widget into a box, use the following function:
1323
1324 <tscreen><verb>
1325 void gtk_table_attach( GtkTable  *table,
1326                        GtkWidget *child,
1327                        gint       left_attach,
1328                        gint       right_attach,
1329                        gint       top_attach,
1330                        gint       bottom_attach,
1331                        gint       xoptions,
1332                        gint       yoptions,
1333                        gint       xpadding,
1334                        gint       ypadding );
1335 </verb></tscreen>                                      
1336
1337 Where the first argument ("table") is the table you've created and the second
1338 ("child") the widget you wish to place in the table.
1339
1340 The left and right attach arguments specify where to place the widget, and how
1341 many boxes to use. If you want a button in the lower right table entry 
1342 of our 2x2 table, and want it to fill that entry ONLY.  left_attach would be = 1, 
1343 right_attach = 2, top_attach = 1, bottom_attach = 2.
1344
1345 Now, if you wanted a widget to take up the whole 
1346 top row of our 2x2 table, you'd use left_attach = 0, right_attach = 2,
1347 top_attach = 0, bottom_attach = 1.
1348
1349 The xoptions and yoptions are used to specify packing options and may be OR'ed 
1350 together to allow multiple options.  
1351
1352 These options are:
1353 <itemize>
1354 <item>GTK_FILL - If the table box is larger than the widget, and GTK_FILL is
1355 specified, the widget will expand to use all the room available.
1356
1357 <item>GTK_SHRINK - If the table widget was allocated less space then was
1358 requested (usually by the user resizing the window), then the widgets would 
1359 normally just be pushed off the bottom of
1360 the window and disappear.  If GTK_SHRINK is specified, the widgets will
1361 shrink with the table.
1362
1363 <item>GTK_EXPAND - This will cause the table to expand to use up any remaining
1364 space in the window.
1365 </itemize>
1366
1367 Padding is just like in boxes, creating a clear area around the widget
1368 specified in pixels.  
1369
1370 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1371
1372 <tscreen><verb>
1373 void gtk_table_attach_defaults( GtkTable  *table,
1374                                 GtkWidget *widget,
1375                                 gint       left_attach,
1376                                 gint       right_attach,
1377                                 gint       top_attach,
1378                                 gint       bottom_attach );
1379 </verb></tscreen>
1380
1381 The X and Y options default to GTK_FILL | GTK_EXPAND, and X and Y padding
1382 are set to 0. The rest of the arguments are identical to the previous
1383 function.
1384
1385 We also have gtk_table_set_row_spacing() and gtk_table_set_col_spacing().
1386 This places spacing between the rows at the specified row or column.
1387
1388 <tscreen><verb>
1389 void gtk_table_set_row_spacing( GtkTable *table,
1390                                 gint      row,
1391                                 gint      spacing );
1392 </verb></tscreen>
1393
1394 and
1395
1396 <tscreen><verb>
1397 void gtk_table_set_col_spacing ( GtkTable *table,
1398                                  gint      column,
1399                                  gint      spacing );
1400 </verb></tscreen>
1401
1402 Note that for columns, the space goes to the right of the column, and for 
1403 rows, the space goes below the row.
1404
1405 You can also set a consistent spacing of all rows and/or columns with:
1406
1407 <tscreen><verb>
1408 void gtk_table_set_row_spacings( GtkTable *table,
1409                                  gint      spacing );
1410 </verb></tscreen>
1411
1412 And,
1413
1414 <tscreen><verb>
1415 void gtk_table_set_col_spacings( GtkTable *table,
1416                                  gint      spacing );
1417 </verb></tscreen>
1418
1419 Note that with these calls, the last row and last column do not get any 
1420 spacing.
1421
1422 <!-- ----------------------------------------------------------------- -->
1423 <sect1>Table Packing Example
1424 <p>
1425 Here we make a window with three buttons in a 2x2 table.
1426 The first two buttons will be placed in the upper row.
1427 A third, quit button, is placed in the lower row, spanning both columns.
1428 Which means it should look something like this:
1429
1430 <? <CENTER> >
1431 <?
1432 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1433 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1434 >
1435 <? </CENTER> >
1436
1437 Here's the source code:
1438
1439 <tscreen><verb>
1440 /* example-start table table.c */
1441
1442 #include <gtk/gtk.h>
1443
1444 /* our callback.
1445  * the data passed to this function is printed to stdout */
1446 void callback (GtkWidget *widget, gpointer data)
1447 {
1448     g_print ("Hello again - %s was pressed\n", (char *) data);
1449 }
1450
1451 /* this callback quits the program */
1452 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
1453 {
1454     gtk_main_quit ();
1455 }
1456
1457 int main (int argc, char *argv[])
1458 {
1459     GtkWidget *window;
1460     GtkWidget *button;
1461     GtkWidget *table;
1462
1463     gtk_init (&amp;argc, &amp;argv);
1464
1465     /* create a new window */
1466     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1467
1468     /* set the window title */
1469     gtk_window_set_title (GTK_WINDOW (window), "Table");
1470
1471     /* set a handler for delete_event that immediately
1472      * exits GTK. */
1473     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1474                         GTK_SIGNAL_FUNC (delete_event), NULL);
1475
1476     /* sets the border width of the window. */
1477     gtk_container_border_width (GTK_CONTAINER (window), 20);
1478
1479     /* create a 2x2 table */
1480     table = gtk_table_new (2, 2, TRUE);
1481
1482     /* put the table in the main window */
1483     gtk_container_add (GTK_CONTAINER (window), table);
1484
1485     /* create first button */
1486     button = gtk_button_new_with_label ("button 1");
1487
1488     /* when the button is clicked, we call the "callback" function
1489      * with a pointer to "button 1" as its argument */
1490     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1491               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1492
1493
1494     /* insert button 1 into the upper left quadrant of the table */
1495     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1496
1497     gtk_widget_show (button);
1498
1499     /* create second button */
1500
1501     button = gtk_button_new_with_label ("button 2");
1502
1503     /* when the button is clicked, we call the "callback" function
1504      * with a pointer to "button 2" as its argument */
1505     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1506               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1507     /* insert button 2 into the upper right quadrant of the table */
1508     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1509
1510     gtk_widget_show (button);
1511
1512     /* create "Quit" button */
1513     button = gtk_button_new_with_label ("Quit");
1514
1515     /* when the button is clicked, we call the "delete_event" function
1516      * and the program exits */
1517     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1518                         GTK_SIGNAL_FUNC (delete_event), NULL);
1519
1520     /* insert the quit button into the both 
1521      * lower quadrants of the table */
1522     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1523
1524     gtk_widget_show (button);
1525
1526     gtk_widget_show (table);
1527     gtk_widget_show (window);
1528
1529     gtk_main ();
1530
1531     return 0;
1532 }
1533 /* example-end */
1534 </verb></tscreen>
1535
1536 <!-- ***************************************************************** -->
1537 <sect>Widget Overview
1538 <!-- ***************************************************************** -->
1539 <p>
1540 The general steps to creating a widget in GTK are:
1541 <enum>
1542 <item> gtk_*_new - one of various functions to create a new widget.  These
1543 are all detailed in this section.
1544
1545 <item> Connect all signals and events we wish to use to the
1546 appropriate handlers.
1547
1548 <item> Set the attributes of the widget.
1549
1550 <item> Pack the widget into a container using the appropriate call such as 
1551 gtk_container_add() or gtk_box_pack_start().
1552
1553 <item> gtk_widget_show() the widget.
1554 </enum>
1555
1556 gtk_widget_show() lets GTK know that we are done setting the attributes
1557 of the widget, and it is ready to be displayed.  You may also use
1558 gtk_widget_hide to make it disappear again.  The order in which you
1559 show the widgets is not important, but I suggest showing the window
1560 last so the whole window pops up at once rather than seeing the individual
1561 widgets come up on the screen as they're formed.  The children of a widget
1562 (a window is a widget too) will not be displayed until the window itself
1563 is shown using the gtk_widget_show() function.
1564
1565 <!-- ----------------------------------------------------------------- -->
1566 <sect1> Casting
1567 <p>
1568 You'll notice as you go on, that GTK uses a type casting system.  This is
1569 always done using macros that both test the ability to cast the given item,
1570 and perform the cast.  Some common ones you will see are:
1571
1572 <itemize>
1573 <item> GTK_WIDGET(widget)
1574 <item> GTK_OBJECT(object)
1575 <item> GTK_SIGNAL_FUNC(function)
1576 <item> GTK_CONTAINER(container)
1577 <item> GTK_WINDOW(window)
1578 <item> GTK_BOX(box)
1579 </itemize>
1580
1581 These are all used to cast arguments in functions.  You'll see them in the
1582 examples, and can usually tell when to use them simply by looking at the
1583 function's declaration.
1584
1585 As you can see below in the class hierarchy, all GtkWidgets are derived from
1586 the GtkObject base class.  This means you can use a widget in any place the 
1587 function asks for an object - simply use the GTK_OBJECT() macro.
1588
1589 For example:
1590
1591 <tscreen><verb>
1592 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1593                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1594 </verb></tscreen> 
1595
1596 This casts the button into an object, and provides a cast for the function
1597 pointer to the callback.
1598
1599 Many widgets are also containers.  If you look in the class hierarchy below,
1600 you'll notice that many widgets derive from the GtkContainer class.  Any one
1601 of these widgets may be used with the GTK_CONTAINER macro to pass them to
1602 functions that ask for containers.
1603
1604 Unfortunately, these macros are not extensively covered in the tutorial, but I
1605 recommend taking a look through the GTK header files.  It can be very
1606 educational.  In fact, it's not difficult to learn how a widget works just
1607 by looking at the function declarations.
1608
1609 <!-- ----------------------------------------------------------------- -->
1610 <sect1>Widget Hierarchy
1611 <p>
1612 For your reference, here is the class hierarchy tree used to implement widgets.
1613
1614 <tscreen><verb>
1615   GtkObject
1616    +GtkData
1617    | +GtkAdjustment
1618    | `GtkTooltips
1619    `GtkWidget
1620      +GtkContainer
1621      | +GtkBin
1622      | | +GtkAlignment
1623      | | +GtkEventBox
1624      | | +GtkFrame
1625      | | | `GtkAspectFrame
1626      | | +GtkHandleBox
1627      | | +GtkItem
1628      | | | +GtkListItem
1629      | | | +GtkMenuItem
1630      | | | | `GtkCheckMenuItem
1631      | | | |   `GtkRadioMenuItem
1632      | | | `GtkTreeItem
1633      | | +GtkViewport
1634      | | `GtkWindow
1635      | |   +GtkColorSelectionDialog
1636      | |   +GtkDialog
1637      | |   | `GtkInputDialog
1638      | |   `GtkFileSelection
1639      | +GtkBox
1640      | | +GtkButtonBox
1641      | | | +GtkHButtonBox
1642      | | | `GtkVButtonBox
1643      | | +GtkHBox
1644      | | | +GtkCombo
1645      | | | `GtkStatusbar
1646      | | `GtkVBox
1647      | |   +GtkColorSelection
1648      | |   `GtkGammaCurve
1649      | +GtkButton
1650      | | +GtkOptionMenu
1651      | | `GtkToggleButton
1652      | |   `GtkCheckButton
1653      | |     `GtkRadioButton
1654      | +GtkCList
1655      |  `GtkCTree
1656      | +GtkFixed
1657      | +GtkList
1658      | +GtkMenuShell
1659      | | +GtkMenuBar
1660      | | `GtkMenu
1661      | +GtkNotebook
1662      | +GtkPaned
1663      | | +GtkHPaned
1664      | | `GtkVPaned
1665      | +GtkScrolledWindow
1666      | +GtkTable
1667      | +GtkToolbar
1668      | `GtkTree
1669      +GtkDrawingArea
1670      | `GtkCurve
1671      +GtkEditable
1672      | +GtkEntry
1673      | | `GtkSpinButton
1674      | `GtkText
1675      +GtkMisc
1676      | +GtkArrow
1677      | +GtkImage
1678      | +GtkLabel
1679      | | `GtkTipsQuery
1680      | `GtkPixmap
1681      +GtkPreview
1682      +GtkProgressBar
1683      +GtkRange
1684      | +GtkScale
1685      | | +GtkHScale
1686      | | `GtkVScale
1687      | `GtkScrollbar
1688      |   +GtkHScrollbar
1689      |   `GtkVScrollbar
1690      +GtkRuler
1691      | +GtkHRuler
1692      | `GtkVRuler
1693      `GtkSeparator
1694        +GtkHSeparator
1695        `GtkVSeparator
1696 </verb></tscreen>
1697
1698 <!-- ----------------------------------------------------------------- -->
1699 <sect1>Widgets Without Windows
1700 <p>
1701 The following widgets do not have an associated window.  If you want to
1702 capture events, you'll have to use the GtkEventBox.  See the section on   
1703 <ref id="sec_The_EventBox_Widget" name="The EventBox Widget">
1704
1705 <tscreen><verb>
1706 GtkAlignment
1707 GtkArrow
1708 GtkBin
1709 GtkBox
1710 GtkImage
1711 GtkItem
1712 GtkLabel
1713 GtkPixmap
1714 GtkScrolledWindow
1715 GtkSeparator
1716 GtkTable
1717 GtkAspectFrame
1718 GtkFrame
1719 GtkVBox
1720 GtkHBox
1721 GtkVSeparator
1722 GtkHSeparator
1723 </verb></tscreen>
1724
1725 We'll further our exploration of GTK by examining each widget in turn,
1726 creating a few simple functions to display them.  Another good source is
1727 the testgtk.c program that comes with GTK.  It can be found in
1728 gtk/testgtk.c.
1729
1730 <!-- ***************************************************************** -->
1731 <sect>The Button Widget
1732 <!-- ***************************************************************** -->
1733
1734 <!-- ----------------------------------------------------------------- -->
1735 <sect1>Normal Buttons
1736 <p>
1737 We've almost seen all there is to see of the button widget. It's pretty
1738 simple.  There are however two ways to create a button. You can use the
1739 gtk_button_new_with_label() to create a button with a label, or use
1740 gtk_button_new() to create a blank button. It's then up to you to pack a
1741 label or pixmap into this new button. To do this, create a new box, and
1742 then pack your objects into this box using the usual gtk_box_pack_start,
1743 and then use gtk_container_add to pack the box into the button.
1744
1745 Here's an example of using gtk_button_new to create a button with a
1746 picture and a label in it.  I've broken up the code to create a box from
1747 the rest so you can use it in your programs.
1748
1749 <tscreen><verb>
1750 /* example-start buttons buttons.c */
1751
1752 #include <gtk/gtk.h>
1753
1754 /* create a new hbox with an image and a label packed into it
1755  * and return the box.. */
1756
1757 GtkWidget *xpm_label_box (GtkWidget *parent, gchar *xpm_filename, gchar *label_text)
1758 {
1759     GtkWidget *box1;
1760     GtkWidget *label;
1761     GtkWidget *pixmapwid;
1762     GdkPixmap *pixmap;
1763     GdkBitmap *mask;
1764     GtkStyle *style;
1765
1766     /* create box for xpm and label */
1767     box1 = gtk_hbox_new (FALSE, 0);
1768     gtk_container_border_width (GTK_CONTAINER (box1), 2);
1769
1770     /* get style of button.. I assume it's to get the background color.
1771      * if someone knows the real reason, please enlighten me. */
1772     style = gtk_widget_get_style(parent);
1773
1774     /* now on to the xpm stuff.. load xpm */
1775     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1776                                          &amp;style->bg[GTK_STATE_NORMAL],
1777                                          xpm_filename);
1778     pixmapwid = gtk_pixmap_new (pixmap, mask);
1779
1780     /* create label for button */
1781     label = gtk_label_new (label_text);
1782
1783     /* pack the pixmap and label into the box */
1784     gtk_box_pack_start (GTK_BOX (box1),
1785                         pixmapwid, FALSE, FALSE, 3);
1786
1787     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1788
1789     gtk_widget_show(pixmapwid);
1790     gtk_widget_show(label);
1791
1792     return (box1);
1793 }
1794
1795 /* our usual callback function */
1796 void callback (GtkWidget *widget, gpointer data)
1797 {
1798     g_print ("Hello again - %s was pressed\n", (char *) data);
1799 }
1800
1801
1802 int main (int argc, char *argv[])
1803 {
1804     /* GtkWidget is the storage type for widgets */
1805     GtkWidget *window;
1806     GtkWidget *button;
1807     GtkWidget *box1;
1808
1809     gtk_init (&amp;argc, &amp;argv);
1810
1811     /* create a new window */
1812     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1813
1814     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1815
1816     /* It's a good idea to do this for all windows. */
1817     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1818                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1819
1820     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1821                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1822
1823
1824     /* sets the border width of the window. */
1825     gtk_container_border_width (GTK_CONTAINER (window), 10);
1826     gtk_widget_realize(window);
1827
1828     /* create a new button */
1829     button = gtk_button_new ();
1830
1831     /* You should be getting used to seeing most of these functions by now */
1832     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1833                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1834
1835     /* this calls our box creating function */
1836     box1 = xpm_label_box(window, "info.xpm", "cool button");
1837
1838     /* pack and show all our widgets */
1839     gtk_widget_show(box1);
1840
1841     gtk_container_add (GTK_CONTAINER (button), box1);
1842
1843     gtk_widget_show(button);
1844
1845     gtk_container_add (GTK_CONTAINER (window), button);
1846
1847     gtk_widget_show (window);
1848
1849     /* rest in gtk_main and wait for the fun to begin! */
1850     gtk_main ();
1851
1852     return 0;
1853 }
1854 /* example-end */
1855 </verb></tscreen>
1856
1857 The xpm_label_box function could be used to pack xpm's and labels into any
1858 widget that can be a container.
1859
1860 The Button widget has the following signals:
1861
1862 <itemize>
1863 <item> pressed
1864 <item> released
1865 <item> clicked
1866 <item> enter
1867 <item> leave
1868 </itemize>
1869
1870 <!-- ----------------------------------------------------------------- -->
1871 <sect1> Toggle Buttons
1872 <p>
1873 Toggle buttons are derived from normal buttons and are very similar, except
1874 they will always be in one of two states, alternated by a click.  They may
1875 be depressed, and when you click again, they will pop back up. Click again,
1876 and they will pop back down. 
1877
1878 Toggle buttons are the basis for check buttons and radio buttons, as such,
1879 many of the calls used for toggle buttons are inherited by radio and check
1880 buttons. I will point these out when we come to them.
1881
1882 Creating a new toggle button:
1883
1884 <tscreen><verb>
1885 GtkWidget *gtk_toggle_button_new( void );
1886
1887 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
1888 </verb></tscreen>
1889
1890 As you can imagine, these work identically to the normal button widget
1891 calls. The first creates a blank toggle button, and the second, a button 
1892 with a label widget already packed into it.
1893
1894 To retrieve the state of the toggle widget, including radio and check
1895 buttons, we use a macro as shown in our example below.  This tests the state
1896 of the toggle in a callback. The signal of interest emitted to us by toggle
1897 buttons (the toggle button, check button, and radio button widgets), is the
1898 "toggled" signal.  To check the state of these buttons, set up a signal
1899 handler to catch the toggled signal, and use the macro to determine its
1900 state. The callback will look something like:
1901
1902 <tscreen><verb>
1903 void toggle_button_callback (GtkWidget *widget, gpointer data)
1904 {
1905     if (GTK_TOGGLE_BUTTON (widget)->active) 
1906     {
1907         /* If control reaches here, the toggle button is down */
1908     
1909     } else {
1910     
1911         /* If control reaches here, the toggle button is up */
1912     }
1913 }
1914 </verb></tscreen>
1915
1916 <tscreen><verb>
1917 void gtk_toggle_button_set_state( GtkToggleButton *toggle_button,
1918                                   gint             state );
1919 </verb></tscreen>
1920
1921 The above call can be used to set the state of the toggle button, and its
1922 children the radio and check buttons. Passing in your created button as
1923 the first argument, and a TRUE or FALSE for the second state argument to
1924 specify whether it should be down (depressed) or up (released).  Default
1925 is up, or FALSE.
1926
1927 Note that when you use the gtk_toggle_button_set_state() function, and the
1928 state is actually changed, it causes the "clicked" signal to be emitted 
1929 from the button.
1930
1931 <tscreen><verb>
1932 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
1933 </verb></tscreen>
1934
1935 This simply toggles the button, and emits the "toggled" signal.
1936
1937 <!-- ----------------------------------------------------------------- -->
1938 <sect1> Check Buttons
1939 <p>
1940 Check buttons inherent many properties and functions from the the toggle
1941 buttons above, but look a little different. Rather than being buttons with
1942 text inside them, they are small squares with the text to the right of 
1943 them. These are often used for toggling options on and off in applications.
1944
1945 The two creation functions are similar to those of the normal button.
1946
1947 <tscreen><verb>
1948 GtkWidget *gtk_check_button_new( void );
1949
1950 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
1951 </verb></tscreen>
1952
1953 The new_with_label function creates a check button with a label beside it.
1954
1955 Checking the state of the check button is identical to that of the toggle
1956 button.
1957
1958 <!-- ----------------------------------------------------------------- -->
1959 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
1960 <p>
1961 Radio buttons are similar to check buttons except they are grouped so that
1962 only one may be selected/depressed at a time. This is good for places in
1963 your application where you need to select from a short list of options.
1964
1965 Creating a new radio button is done with one of these calls:
1966
1967 <tscreen><verb>
1968 GtkWidget *gtk_radio_button_new( GSList *group );
1969
1970 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
1971                                             gchar  *label );
1972 </verb></tscreen>
1973
1974 You'll notice the extra argument to these calls.  They require a group to
1975 perform their duty properly. The first call to
1976 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
1977 should pass NULL as the first
1978 argument. Then create a group using:
1979
1980 <tscreen><verb>
1981 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
1982 </verb></tscreen>
1983
1984 The important thing to remember is that gtk_radio_button_group must be
1985 called for each new button added to the group, with the previous button
1986 passed in as an argument. The result is then passed into the call to
1987 gtk_radio_button_new or gtk_radio_button_new_with_label. This allows a
1988 chain of buttons to be established. The example below should make this
1989 clear.
1990
1991 It is also a good idea to explicitly set which button should be the 
1992 default depressed button with:
1993
1994 <tscreen><verb>
1995 void gtk_toggle_button_set_state( GtkToggleButton *toggle_button,
1996                                   gint             state );
1997 </verb></tscreen>
1998
1999 This is described in the section on toggle buttons, and works in exactly the
2000 same way.
2001
2002 The following example creates a radio button group with three buttons.
2003
2004 <tscreen><verb>
2005 /* example-start radiobuttons radiobuttons.c */
2006
2007 #include <gtk/gtk.h>
2008 #include <glib.h>
2009
2010 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
2011   gtk_main_quit();
2012 }
2013
2014 main(int argc,char *argv[])
2015 {
2016   static GtkWidget *window = NULL;
2017   GtkWidget *box1;
2018   GtkWidget *box2;
2019   GtkWidget *button;
2020   GtkWidget *separator;
2021   GSList *group;
2022   
2023   gtk_init(&amp;argc,&amp;argv);          
2024   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2025   
2026   gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2027                       GTK_SIGNAL_FUNC(close_application),
2028                       NULL);
2029
2030   gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2031   gtk_container_border_width (GTK_CONTAINER (window), 0);
2032
2033   box1 = gtk_vbox_new (FALSE, 0);
2034   gtk_container_add (GTK_CONTAINER (window), box1);
2035   gtk_widget_show (box1);
2036
2037   box2 = gtk_vbox_new (FALSE, 10);
2038   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2039   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2040   gtk_widget_show (box2);
2041
2042   button = gtk_radio_button_new_with_label (NULL, "button1");
2043   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2044   gtk_widget_show (button);
2045
2046   group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2047   button = gtk_radio_button_new_with_label(group, "button2");
2048   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
2049   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2050   gtk_widget_show (button);
2051
2052   group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2053   button = gtk_radio_button_new_with_label(group, "button3");
2054   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2055   gtk_widget_show (button);
2056
2057   separator = gtk_hseparator_new ();
2058   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2059   gtk_widget_show (separator);
2060
2061   box2 = gtk_vbox_new (FALSE, 10);
2062   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2063   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2064   gtk_widget_show (box2);
2065
2066   button = gtk_button_new_with_label ("close");
2067   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2068                              GTK_SIGNAL_FUNC(close_application),
2069                              GTK_OBJECT (window));
2070   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2071   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2072   gtk_widget_grab_default (button);
2073   gtk_widget_show (button);
2074   gtk_widget_show (window);
2075      
2076   gtk_main();
2077   return(0);
2078 }
2079 /* example-end */
2080 </verb></tscreen>
2081
2082 You can shorten this slightly by using the following syntax, which
2083 removes the need for a variable to hold the list of buttons:
2084
2085 <tscreen><verb>
2086      button2 = gtk_radio_button_new_with_label(
2087                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2088                  "button2");
2089 </verb></tscreen>
2090
2091 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2092
2093 <!-- ***************************************************************** -->
2094 <sect> Adjustments <label id="sec_Adjustment">
2095 <!-- ***************************************************************** -->
2096 <p>
2097 GTK+ has various widgets that can be visually adjusted by the user
2098 using the mouse or the keyboard, such as the range widgets, described
2099 in the <ref id="sec_Range_Widgets" name="Range Widgets"> section. There
2100 are also a few widgets that display some adjustable portion of a larger
2101 area of data, such as the text widget and the viewport widget.
2102
2103 Obviously, an application needs to be able to react to changes the
2104 user makes in range widgets. One way to do this would be to have each
2105 widget emit its own type of signal when its adjustment changes, and
2106 either pass the new value to the signal handler, or require it to look
2107 inside the widget's data structure in order to ascertain the value.
2108 But you may also want to connect the adjustments of several widgets
2109 together, so that adjusting one adjusts the others. The most obvious
2110 example of this is connecting a scrollbar to a panning viewport or a
2111 scrolling text area. If each widget has its own way of setting or
2112 getting the adjustment value, then the programmer may have to write
2113 their own signal handlers to translate between the output of one
2114 widget's signal and the "input" of another's adjustment setting
2115 function.
2116
2117 GTK+ solves this problem using the GtkAdjustment object, which is a
2118 way for widgets to store and pass adjustment information in an
2119 abstract and flexible form. The most obvious use of GtkAdjustment is
2120 to store the configuration parameters and values of range widgets,
2121 such as scrollbars and scale controls. However, since GtkAdjustments
2122 are derived from GtkObject, they have some special powers beyond those
2123 of normal data structures. Most importantly, they can emit signals,
2124 just like widgets, and these signals can be used not only to allow
2125 your program to react to user input on adjustable widgets, but also to
2126 propagate adjustment values transparently between adjustable widgets.
2127
2128 <sect1> Creating an Adjustment
2129 <p>
2130 You create an adjustment using:
2131
2132 <tscreen><verb>
2133 GtkObject *gtk_adjustment_new( gfloat value,
2134                                gfloat lower,
2135                                gfloat upper,
2136                                gfloat step_increment,
2137                                gfloat page_increment,
2138                                gfloat page_size );
2139 </verb></tscreen>
2140
2141 The <tt/value/ argument is the initial value you want to give to the
2142 adjustment, usually corresponding to the topmost or leftmost position
2143 of an adjustable widget.  The <tt/lower/ argument specifies the lowest
2144 value which the adjustment can hold.  The <tt/step_increment/ argument
2145 specifies the "smaller" of the two increments by which the user can
2146 change the value, while the <tt/page_increment/ is the "larger" one.
2147 The <tt/page_size/ argument usually corresponds somehow to the visible
2148 area of a panning widget.  The <tt/upper/ argument is used to
2149 represent the bottom most or right most coordinate in a panning widget's
2150 child. Therefore it is <em/not/ always the largest number that
2151 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2152 usually non-zero.
2153
2154 <!-- ----------------------------------------------------------------- -->
2155 <sect1> Using Adjustments the Easy Way
2156 <p>
2157 The adjustable widgets can be roughly divided into those which use and
2158 require specific units for these values and those which treat them as
2159 arbitrary numbers. The group which treats the values as arbitrary numbers
2160 includes the range widgets (scrollbars and scales, the progress bar
2161 widget, and the spin button widget). These widgets are all the widgets
2162 which are typically "adjusted" directly by the user with the mouse or
2163 keyboard. They will treat the <tt/lower/ and <tt/upper/ values of an
2164 adjustment as a range within which the user can manipulate the
2165 adjustment's <tt/value/.  By default, they will only modify the
2166 <tt/value/ of an adjustment.
2167
2168 The other group includes the text widget, the viewport widget, the
2169 compound list widget, and the scrolled window widget. All of these
2170 widgets use pixel values for their adjustments. These are also all
2171 widgets which are typically "adjusted" indirectly using scrollbars.
2172 While all widgets which use adjustments can either create their own
2173 adjustments or use ones you supply, you'll generally want to let this
2174 particular category of widgets create its own adjustments.  Usually,
2175 they will eventually override all the values except the <tt/value/
2176 itself in whatever adjustments you give them, but the results are, in
2177 general, undefined (meaning, you'll have to read the source code to
2178 find out, and it may be different from widget to widget).
2179
2180 Now, you're probably thinking, since text widgets and viewports insist
2181 on setting everything except the <tt/value/ of their adjustments,
2182 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if you
2183 <em/share/ an adjustment object between a scrollbar and a text widget,
2184 will manipulating the scrollbar automagically adjust the text widget?
2185 Of course it will! Just like this:
2186
2187 <tscreen><verb>
2188   /* creates its own adjustments */
2189   text = gtk_text_new (NULL, NULL);
2190   /* uses the newly-created adjustment for the scrollbar as well */
2191   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2192 </verb></tscreen>
2193
2194 </sect1>
2195 <!-- ----------------------------------------------------------------- -->
2196 <sect1> Adjustment Internals
2197 <p>
2198 OK, you say, that's nice, but what if I want to create my own handlers
2199 to respond when the user adjusts a range widget or a spin button, and
2200 how do I get at the value of the adjustment in these handlers?  To
2201 answer these questions and more, let's start by taking a look at
2202 <tt>struct _GtkAdjustment</tt> itself:
2203
2204 <tscreen><verb>
2205 struct _GtkAdjustment
2206 {
2207   GtkData data;
2208   
2209   gfloat lower;
2210   gfloat upper;
2211   gfloat value;
2212   gfloat step_increment;
2213   gfloat page_increment;
2214   gfloat page_size;
2215 };     
2216 </verb></tscreen>
2217
2218 The first thing you should know is that there aren't any handy-dandy
2219 macros or accessor functions for getting the <tt/value/ out of a
2220 GtkAdjustment, so you'll have to (horror of horrors) do it like a
2221 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2222 (Object)</tt> macro does run-time type checking (as do all the GTK+
2223 type-casting macros, actually).
2224
2225 Since, when you set the <tt/value/ of an adjustment, you generally
2226 want the change to be reflected by every widget that uses this
2227 adjustment, GTK+ provides this convenience function to do this:
2228
2229 <tscreen><verb>
2230 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2231                                gfloat         value );
2232 </verb></tscreen>
2233
2234 As mentioned earlier, GtkAdjustment is a subclass of GtkObject just
2235 like all the various widgets, and thus it is able to emit signals.
2236 This is, of course, why updates hapen automagically when you share an
2237 adjustment object between a scrollbar and another adjustable widget;
2238 all adjustable widgets connect signal handlers to their adjustment's
2239 <tt/value_changed/ signal, as can your program. Here's the definition
2240 of this signal in <tt/struct _GtkAdjustmentClass/:
2241
2242 <tscreen><verb>
2243   void (* value_changed) (GtkAdjustment *adjustment);
2244 </verb></tscreen>
2245
2246 The various widgets that use the GtkAdjustment object will emit this
2247 signal on an adjustment whenever they change its value. This happens
2248 both when user input causes the slider to move on a range widget, as
2249 well as when the program explicitly changes the value with
2250 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2251 widget, and you want to change the rotation of a picture whenever its
2252 value changes, you would create a callback like this:
2253           
2254 <tscreen><verb>
2255 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2256 {
2257   set_picture_rotation (picture, adj->value);
2258 ...
2259 </verb></tscreen>
2260
2261 and connect it to the scale widget's adjustment like this:
2262
2263 <tscreen><verb>
2264 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2265                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2266 </verb></tscreen>
2267
2268 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2269 fields of its adjustment, such as when a user adds more text to a text
2270 widget?  In this case, it emits the <tt/changed/ signal, which looks
2271 like this:
2272
2273 <tscreen><verb>
2274   void (* changed)       (GtkAdjustment *adjustment);
2275 </verb></tscreen>
2276
2277 Range widgets typically connect a handler to this signal, which
2278 changes their appearance to reflect the change - for example, the size
2279 of the slider in a scrollbar will grow or shrink in inverse proportion
2280 to the difference between the <tt/lower/ and <tt/upper/ values of its
2281 adjustment.
2282
2283 You probably won't ever need to attach a handler to this signal,
2284 unless you're writing a new type of range widget.  However, if you
2285 change any of the values in a GtkAdjustment directly, you should emit
2286 this signal on it to reconfigure whatever widgets are using it, like
2287 this:
2288
2289 <tscreen><verb>
2290 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2291 </verb></tscreen>
2292
2293 Now go forth and adjust!
2294 </sect1>
2295 </sect>
2296
2297 <!-- ***************************************************************** -->
2298 <sect> Range Widgets<label id="sec_Range_Widgets">
2299 <!-- ***************************************************************** -->
2300
2301 <p>
2302 The category of range widgets includes the ubiquitous scrollbar widget
2303 and the less common "scale" widget.  Though these two types of widgets
2304 are generally used for different purposes, they are quite similar in
2305 function and implementation. All range widgets share a set of common
2306 graphic elements, each of which has its own X window and receives
2307 events.  They all contain a "trough" and a "slider" (what is sometimes
2308 called a "thumbwheel" in other GUI environments).  Dragging the slider
2309 with the pointer moves it back and forth within the trough, while
2310 clicking in the trough advances the slider towards the location of the
2311 click, either completely, or by a designated amount, depending on
2312 which mouse button is used.
2313
2314 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2315 all range widgets are associated with an adjustment object, from which
2316 they calculate the length of the slider and it's position within the 
2317 trough.  When the user manipulates the slider, the range widget
2318 will change the value of the adjustment.
2319
2320 <!-- ----------------------------------------------------------------- -->
2321 <sect1> Scrollbar Widgets
2322 <p>
2323 These are your standard, run-of-the-mill scrollbars. These should be
2324 used only for scrolling some other widget, such as a list, a text box,
2325 or a viewport (and it's generally easier to use the scrolled window
2326 widget in most cases).  For other purposes, you should use scale
2327 widgets, as they are friendlier and more featureful.
2328
2329 There are separate types for horizontal and vertical scrollbars.
2330 There really isn't much to say about these.  You create them with the
2331 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2332 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2333
2334 <tscreen><verb>
2335 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2336
2337 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2338 </verb></tscreen>
2339
2340 and that's about it (if you don't believe me, look in the header
2341 files!).  The <tt/adjustment/ argument can either be a pointer to an
2342 existing GtkAdjustment, or NULL, in which case one will be created for
2343 you. Specifying NULL might actually be useful in this case, if you
2344 wish to pass the newly-created adjustment to the constructor function
2345 of some other widget which will configure it for you, such as a text
2346 widget.
2347 </sect1>
2348
2349 <!-- ----------------------------------------------------------------- -->
2350 <sect1> Scale Widgets
2351 <p>
2352 Scale widgets are used to allow the user to visually select and
2353 manipulate a value within a specific range.  You might want to use a
2354 scale widget, for example, to adjust the magnification level on a
2355 zoomed preview of a picture, or to control the brightness of a colour,
2356 or to specify the number of minutes of inactivity before a screensaver
2357 takes over the screen.
2358
2359 <!-- ----------------------------------------------------------------- -->
2360 <sect2>Creating a Scale Widget
2361 <p>
2362 As with scrollbars, there are separate widget types for horizontal and
2363 vertical scale widgets. (Most programmers seem to favour horizontal
2364 scale widgets). Since they work essentially the same way, there's no
2365 need to treat them separately here.  The following functions, defined
2366 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2367 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2368 widgets, respectively:
2369
2370 <tscreen>
2371 <verb>
2372 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2373
2374 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2375 </verb>
2376 </tscreen>
2377
2378 The <tt/adjustment/ argument can either be an adjustment which has
2379 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2380 which case, an anonymous GtkAdjustment is created with all of its
2381 values set to <tt/0.0/ (which isn't very useful in this case).  In
2382 order to avoid confusing yourself, you probably want to create your
2383 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2384 value actually corresponds to the highest value the user can select.
2385 (If you're <em/already/ thoroughly confused, read the section on <ref
2386 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2387 what exactly adjustments do and how to create and manipulate them).
2388
2389 <!-- ----------------------------------------------------------------- -->
2390 <sect2> Functions and Signals (well, functions, at least)
2391 <p>
2392 Scale widgets can display their current value as a number beside the
2393 trough.  The default behaviour is to show the value, but you can
2394 change this with this function:
2395
2396 <tscreen><verb>
2397 void gtk_scale_set_draw_value( GtkScale *scale,
2398                                gint      draw_value );
2399 </verb></tscreen>
2400
2401 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2402 <tt/FALSE/, with predictable consequences for either one.
2403
2404 The value displayed by a scale widget is rounded to one decimal point
2405 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2406 change this with:
2407
2408 <tscreen>
2409 <verb>
2410 void gtk_scale_set_digits( GtkScale *scale,
2411                             gint     digits );
2412 </verb>
2413 </tscreen>
2414
2415 where <tt/digits/ is the number of decimal places you want.  You can
2416 set <tt/digits/ to anything you like, but no more than 13 decimal
2417 places will actually be drawn on screen.
2418
2419 Finally, the value can be drawn in different positions
2420 relative to the trough:
2421
2422 <tscreen>
2423 <verb>
2424 void gtk_scale_set_value_pos( GtkScale        *scale,
2425                               GtkPositionType  pos );
2426 </verb>
2427 </tscreen>
2428
2429 If you've read the section on the notebook widget, then you already
2430 know what the possible values of <tt/pos/ are.  They are defined as
2431 <tt>enum GtkPositionType</tt> in <tt>&lt;gtk/gtkenums.h&gt;</tt> and
2432 are pretty self-explanatory.  If you position the value on the "side"
2433 of the trough (e.g. on the top or bottom of a horizontal scale
2434 widget), then it will follow the slider up and down the trough.
2435
2436 All the preceding functions are defined in
2437 <tt>&lt;gtk/gtkscale.h&gt;</tt>.
2438 </sect2>
2439 </sect1>
2440
2441 <!-- ----------------------------------------------------------------- -->
2442 <sect1> Common Functions<label id="sec_Range_Functions">
2443 <p>
2444 The GtkRange widget class is fairly complicated internally, but, like
2445 all the "base class" widgets, most of its complexity is only
2446 interesting if you want to hack on it.  Also, almost all of the
2447 functions and signals it defines are only really used in writing
2448 derived widgets.  There are, however, a few useful functions that
2449 are defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range widgets.
2450
2451 <!-- ----------------------------------------------------------------- -->
2452 <sect2> Setting the Update Policy
2453 <p>
2454 The "update policy" of a range widget defines at what points during
2455 user interaction it will change the <tt/value/ field of its
2456 GtkAdjustment and emit the "value_changed" signal on this
2457 GtkAdjustment.  The update policies, defined in
2458 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2459 are:
2460
2461 <itemize>
2462 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2463 "value_changed" signal is emitted continuously, i.e. whenever the
2464 slider is moved by even the tiniest amount.
2465 </item>
2466 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2467 only emitted once the slider has stopped moving and the user has
2468 released the mouse button.
2469 </item>
2470 <item>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emitted
2471 when the user releases the mouse button, or if the slider stops moving
2472 for a short period of time.
2473 </item>
2474 </itemize>
2475
2476 The update policy of a range widget can be set by casting it using the
2477 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2478
2479 <tscreen><verb>
2480 void           gtk_range_set_update_policy      (GtkRange      *range,
2481                                                  GtkUpdateType  policy);
2482 </verb></tscreen>
2483
2484 <!-- ----------------------------------------------------------------- -->
2485 <sect2>Getting and Setting Adjustments
2486 <p>
2487 Getting and setting the adjustment for a range widget "on the fly" is
2488 done, predictably, with:
2489
2490 <tscreen><verb>
2491 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2492
2493 void gtk_range_set_adjustment( GtkRange      *range,
2494                                GtkAdjustment *adjustment );
2495 </verb></tscreen>
2496
2497 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2498 which <tt/range/ is connected.
2499
2500 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2501 the adjustment that <tt/range/ is already using, regardless of whether
2502 you changed any of its fields or not.  If you pass it a new
2503 GtkAdjustment, it will unreference the old one if it exists (possibly
2504 destroying it), connect the appropriate signals to the new one, and
2505 call the private function <tt/gtk_range_adjustment_changed()/, which
2506 will (or at least, is supposed to...)  recalculate the size and/or
2507 position of the slider and redraw if necessary.  As mentioned in the
2508 section on adjustments, if you wish to reuse the same GtkAdjustment,
2509 when you modify its values directly, you should emit the "changed"
2510 signal on it, like this:
2511
2512 <tscreen><verb>
2513 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2514 </verb></tscreen>
2515 </sect2>
2516 </sect1>
2517
2518 <!-- ----------------------------------------------------------------- -->
2519 <sect1> Key and Mouse bindings
2520 <p>
2521 All of the GTK+ range widgets react to mouse clicks in more or less
2522 the same way.  Clicking button 1 in the trough will cause its
2523 adjustment's <tt/page_increment/ to be added or subtracted from its
2524 <tt/value/, and the slider to be moved accordingly.  Clicking mouse button 2
2525 in the trough will jump the slider to the point at which the button
2526 was clicked.  Clicking any button on a scrollbar's arrows will cause
2527 its adjustment's value to change <tt/step_increment/ at a time.
2528
2529 It may take a little while to get used to, but by default, scrollbars
2530 as well as scale widgets can take the keyboard focus in GTK+.  If you
2531 think your users will find this too confusing, you can always disable
2532 this by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:
2533
2534 <tscreen><verb>
2535 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2536 </verb></tscreen>
2537
2538 The key bindings (which are, of course, only active when the widget
2539 has focus) are slightly different between horizontal and vertical
2540 range widgets, for obvious reasons.  They are also not quite the same
2541 for scale widgets as they are for scrollbars, for somewhat less
2542 obvious reasons (possibly to avoid confusion between the keys for
2543 horizontal and vertical scrollbars in scrolled windows, where both
2544 operate on the same area).
2545
2546 <sect2> Vertical Range Widgets
2547 <p>
2548 All vertical range widgets can be operated with the up and down arrow
2549 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys.  The
2550 arrows move the slider up and down by <tt/step_increment/, while
2551 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2552
2553 The user can also move the slider all the way to one end or the other
2554 of the trough using the keyboard.  With the GtkVScale widget, this is
2555 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2556 GtkVScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2557 and <tt>Control-Page Down</tt>.
2558
2559 <!-- ----------------------------------------------------------------- -->
2560 <sect2> Horizontal Range Widgets
2561 <p>
2562 The left and right arrow keys work as you might expect in these
2563 widgets, moving the slider back and forth by <tt/step_increment/.  The
2564 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2565 For the GtkHScale widget, moving the slider by <tt/page_increment/ is
2566 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2567 while for GtkHScrollbar, it's done with <tt>Control-Home</tt> and
2568 <tt>Control-End</tt>.
2569 </sect2>
2570 </sect1>
2571
2572 <!-- ----------------------------------------------------------------- -->
2573 <sect1> Example<label id="sec_Range_Example">
2574 <p>
2575 This example is a somewhat modified version of the "range widgets"
2576 test from <tt/testgtk.c/.  It basically puts up a window with three
2577 range widgets all connected to the same adjustment, and a couple of
2578 controls for adjusting some of the parameters mentioned above and in
2579 the seciton on adjustments, so you can see how they affect the way
2580 these widgets work for the user.
2581
2582 <tscreen><verb>
2583 /* example-start rangewidgets rangewidgets.c */
2584
2585 #include <gtk/gtk.h>
2586
2587 GtkWidget *hscale, *vscale;
2588
2589 void cb_pos_menu_select (GtkWidget *item, GtkPositionType pos)
2590 {
2591   /* set the value position on both scale widgets */
2592   gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2593   gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2594 }
2595
2596 void cb_update_menu_select (GtkWidget *item, GtkUpdateType policy)
2597 {
2598   /* set the update policy for both scale widgets */
2599   gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2600   gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2601 }
2602
2603 void cb_digits_scale (GtkAdjustment *adj)
2604 {
2605   /* set the number of decimal places to which adj->vaule is rounded
2606    */
2607   gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2608   gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2609 }
2610
2611 void cb_page_size (GtkAdjustment *get, GtkAdjustment *set)
2612 {
2613   /* set the page size and page increment size of the sample
2614      adjustment to the value specified by the "Page Size" scale */
2615   set->page_size = get->value;
2616   set->page_increment = get->value;
2617   /* now emit the "changed" signal to reconfigure all the widgets that
2618      are attached to this adjustment */
2619   gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2620 }
2621
2622 void cb_draw_value (GtkToggleButton *button)
2623 {
2624   /* turn the value display on the scale widgets off or on depending
2625      on the state of the checkbutton */
2626   gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2627   gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2628 }
2629
2630 /* convenience functions */
2631
2632 GtkWidget *make_menu_item (gchar *name, GtkSignalFunc callback,
2633                            gpointer data)
2634 {
2635   GtkWidget *item;
2636   
2637   item = gtk_menu_item_new_with_label (name);
2638   gtk_signal_connect (GTK_OBJECT (item), "activate",
2639                       callback, data);
2640   gtk_widget_show (item);
2641
2642   return item;
2643 }
2644
2645 void scale_set_default_values (GtkScale *scale)
2646 {
2647   gtk_range_set_update_policy (GTK_RANGE (scale),
2648                                GTK_UPDATE_CONTINUOUS);
2649   gtk_scale_set_digits (scale, 1);
2650   gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2651   gtk_scale_set_draw_value (scale, TRUE);
2652 }
2653
2654 /* makes the sample window */
2655
2656 void create_range_controls (void)
2657 {
2658   GtkWidget *window;
2659   GtkWidget *box1, *box2, *box3;
2660   GtkWidget *button;
2661   GtkWidget *scrollbar;
2662   GtkWidget *separator;
2663   GtkWidget *opt, *menu, *item;
2664   GtkWidget *label;
2665   GtkWidget *scale;
2666   GtkObject *adj1, *adj2;
2667
2668   /* standard window-creating stuff */
2669   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2670   gtk_signal_connect (GTK_OBJECT (window), "destroy",
2671                       GTK_SIGNAL_FUNC(gtk_main_quit),
2672                       NULL);
2673   gtk_window_set_title (GTK_WINDOW (window), "range controls");
2674
2675   box1 = gtk_vbox_new (FALSE, 0);
2676   gtk_container_add (GTK_CONTAINER (window), box1);
2677   gtk_widget_show (box1);
2678
2679   box2 = gtk_hbox_new (FALSE, 10);
2680   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2681   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2682   gtk_widget_show (box2);
2683
2684   /* value, lower, upper, step_increment, page_increment, page_size */
2685   /* note that the page_size value only makes a difference for
2686      scrollbar widgets, and the highest value you'll get is actually
2687      (upper - page_size). */
2688   adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2689   
2690   vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2691   scale_set_default_values (GTK_SCALE (vscale));
2692   gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2693   gtk_widget_show (vscale);
2694
2695   box3 = gtk_vbox_new (FALSE, 10);
2696   gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2697   gtk_widget_show (box3);
2698
2699   /* reuse the same adjustment */
2700   hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2701   gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2702   scale_set_default_values (GTK_SCALE (hscale));
2703   gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2704   gtk_widget_show (hscale);
2705
2706   /* reuse the same adjustment again */
2707   scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2708   /* notice how this causes the scales to always be updated
2709      continuously when the scrollbar is moved */
2710   gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2711                                GTK_UPDATE_CONTINUOUS);
2712   gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2713   gtk_widget_show (scrollbar);
2714
2715   box2 = gtk_hbox_new (FALSE, 10);
2716   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2717   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2718   gtk_widget_show (box2);
2719
2720   /* a checkbutton to control whether the value is displayed or not */
2721   button = gtk_check_button_new_with_label
2722     ("Display value on scale widgets");
2723   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
2724   gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC
2725                       (cb_draw_value), NULL);
2726   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2727   gtk_widget_show (button);
2728   
2729   box2 = gtk_hbox_new (FALSE, 10);
2730   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2731
2732   /* an option menu to change the position of the value */
2733   label = gtk_label_new ("Scale Value Position:");
2734   gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2735   gtk_widget_show (label);
2736   
2737   opt = gtk_option_menu_new();
2738   menu = gtk_menu_new();
2739
2740   item = make_menu_item ("Top", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2741                          GINT_TO_POINTER (GTK_POS_TOP));
2742   gtk_menu_append (GTK_MENU (menu), item);
2743   
2744   item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2745                          GINT_TO_POINTER (GTK_POS_BOTTOM));
2746   gtk_menu_append (GTK_MENU (menu), item);
2747   
2748   item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2749                          GINT_TO_POINTER (GTK_POS_LEFT));
2750   gtk_menu_append (GTK_MENU (menu), item);
2751   
2752   item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2753                          GINT_TO_POINTER (GTK_POS_RIGHT));
2754   gtk_menu_append (GTK_MENU (menu), item);
2755   
2756   gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2757   gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2758   gtk_widget_show (opt);
2759
2760   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2761   gtk_widget_show (box2);
2762
2763   box2 = gtk_hbox_new (FALSE, 10);
2764   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2765
2766   /* yet another option menu, this time for the update policy of the
2767      scale widgets */
2768   label = gtk_label_new ("Scale Update Policy:");
2769   gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2770   gtk_widget_show (label);
2771   
2772   opt = gtk_option_menu_new();
2773   menu = gtk_menu_new();
2774   
2775   item = make_menu_item ("Continuous",
2776                          GTK_SIGNAL_FUNC (cb_update_menu_select),
2777                          GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2778   gtk_menu_append (GTK_MENU (menu), item);
2779   
2780   item = make_menu_item ("Discontinuous",
2781                          GTK_SIGNAL_FUNC (cb_update_menu_select),
2782                          GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2783   gtk_menu_append (GTK_MENU (menu), item);
2784   
2785   item = make_menu_item ("Delayed",
2786                          GTK_SIGNAL_FUNC (cb_update_menu_select),
2787                          GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2788   gtk_menu_append (GTK_MENU (menu), item);
2789   
2790   gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2791   gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2792   gtk_widget_show (opt);
2793   
2794   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2795   gtk_widget_show (box2);
2796
2797   box2 = gtk_hbox_new (FALSE, 10);
2798   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2799   
2800   /* a GtkHScale widget for adjusting the number of digits on the
2801      sample scales. */
2802   label = gtk_label_new ("Scale Digits:");
2803   gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2804   gtk_widget_show (label);
2805
2806   adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
2807   gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2808                       GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
2809   scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2810   gtk_scale_set_digits (GTK_SCALE (scale), 0);
2811   gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2812   gtk_widget_show (scale);
2813
2814   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2815   gtk_widget_show (box2);
2816   
2817   box2 = gtk_hbox_new (FALSE, 10);
2818   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2819   
2820   /* And, one last GtkHScale widget for adjusting the page size of the
2821      scrollbar. */
2822   label = gtk_label_new ("Scrollbar Page Size:");
2823   gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2824   gtk_widget_show (label);
2825
2826   adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
2827   gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2828                       GTK_SIGNAL_FUNC (cb_page_size), adj1);
2829   scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2830   gtk_scale_set_digits (GTK_SCALE (scale), 0);
2831   gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2832   gtk_widget_show (scale);
2833
2834   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2835   gtk_widget_show (box2);
2836
2837   separator = gtk_hseparator_new ();
2838   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2839   gtk_widget_show (separator);
2840
2841   box2 = gtk_vbox_new (FALSE, 10);
2842   gtk_container_border_width (GTK_CONTAINER (box2), 10);
2843   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2844   gtk_widget_show (box2);
2845
2846   button = gtk_button_new_with_label ("Quit");
2847   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2848                              GTK_SIGNAL_FUNC(gtk_main_quit),
2849                              NULL);
2850   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2851   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2852   gtk_widget_grab_default (button);
2853   gtk_widget_show (button);
2854
2855   gtk_widget_show (window);
2856 }
2857
2858 int main (int argc, char *argv[])
2859 {
2860   gtk_init(&amp;argc, &amp;argv);
2861
2862   create_range_controls();
2863
2864   gtk_main();
2865
2866   return 0;
2867 }
2868
2869 /* example-end */
2870 </verb></tscreen>
2871 </sect1>
2872 </sect>
2873
2874 <!-- ***************************************************************** -->
2875 <sect> Miscellaneous Widgets
2876 <!-- ***************************************************************** -->
2877
2878 <!-- ----------------------------------------------------------------- -->
2879 <sect1> Labels
2880 <p>
2881 Labels are used a lot in GTK, and are relatively simple. Labels emit no
2882 signals as they do not have an associated X window. If you need to catch
2883 signals, or do clipping, use the EventBox widget.
2884
2885 To create a new label, use:
2886
2887 <tscreen><verb>
2888 GtkWidget *gtk_label_new( char *str );
2889 </verb></tscreen>
2890
2891 Where the sole argument is the string you wish the label to display.
2892
2893 To change the label's text after creation, use the function:
2894
2895 <tscreen><verb>
2896 void gtk_label_set( GtkLabel *label,
2897                     char     *str );
2898 </verb></tscreen>
2899
2900 Where the first argument is the label you created previously (cast using
2901 the GTK_LABEL() macro), and the second is the new string.
2902
2903 The space needed for the new string will be automatically adjusted if needed.
2904
2905 To retrieve the current string, use:
2906
2907 <tscreen><verb>
2908 void gtk_label_get( GtkLabel  *label,
2909                     char     **str );
2910 </verb></tscreen>
2911
2912 Where the first argument is the label you've created, and the second, the
2913 return for the string.
2914
2915 <!-- ----------------------------------------------------------------- -->
2916 <sect1>The Tooltips Widget
2917 <p>
2918 These are the little text strings that pop up when you leave your pointer
2919 over a button or other widget for a few seconds. They are easy to use, so I
2920 will just explain them without giving an example. If you want to see some
2921 code, take a look at the testgtk.c program distributed with GDK.
2922
2923 Some widgets (such as the label) will not work with tooltips.
2924
2925 The first call you will use to create a new tooltip. You only need to do
2926 this once in a given function. The <tt/GtkTooltip/ object this function 
2927 returns can be used to create multiple tooltips.
2928
2929 <tscreen><verb>
2930 GtkTooltips *gtk_tooltips_new( void );
2931 </verb></tscreen>
2932
2933 Once you have created a new tooltip, and the widget you wish to use it on,
2934 simply use this call to set it:
2935
2936 <tscreen><verb>
2937 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
2938                            GtkWidget   *widget,
2939                            const gchar *tip_text,
2940                            const gchar *tip_private );
2941 </verb></tscreen>
2942
2943 The first argument is the tooltip you've already created, followed by the
2944 widget you wish to have this tooltip pop up for, and the text you wish it to
2945 say. The last argument is a text string that can be used as an identifier when using
2946 GtkTipsQuery to implement context sensitive help. For now, you can set
2947 it to NULL.
2948 <!-- TODO: sort out what how to do the context sensitive help -->
2949
2950 Here's a short example:
2951
2952 <tscreen><verb>
2953 GtkTooltips *tooltips;
2954 GtkWidget *button;
2955 ...
2956 tooltips = gtk_tooltips_new ();
2957 button = gtk_button_new_with_label ("button 1");
2958 ...
2959 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
2960 </verb></tscreen>
2961
2962 There are other calls that can be used with tooltips.  I will just
2963 list them with a brief description of what they do.
2964
2965 <tscreen><verb>
2966 void gtk_tooltips_enable( GtkTooltips *tooltips );
2967 </verb></tscreen>
2968
2969 Enable a disabled set of tooltips.
2970
2971 <tscreen><verb>
2972 void gtk_tooltips_disable( GtkTooltips *tooltips );
2973 </verb></tscreen>
2974
2975 Disable an enabled set of tooltips.
2976
2977 <tscreen><verb>
2978 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
2979                              gint         delay );
2980
2981 </verb></tscreen>
2982
2983 Sets how many milliseconds you have to hold your pointer over the 
2984 widget before the tooltip will pop up.  The default is 1000 milliseconds
2985 or 1 second.
2986
2987 <tscreen><verb>
2988 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
2989                               GdkColor    *background,
2990                               GdkColor    *foreground );
2991 </verb></tscreen>
2992
2993 Set the foreground and background color of the tooltips. Again, I have no
2994 idea how to specify the colors.
2995
2996 And that's all the functions associated with tooltips. More than you'll
2997 ever want to know :)
2998
2999 <!-- ----------------------------------------------------------------- -->
3000 <sect1> Progress Bars
3001 <p>
3002 Progress bars are used to show the status of an operation.  They are pretty 
3003 easy to use, as you will see with the code below. But first lets start out 
3004 with the call to create a new progress bar.
3005
3006 <tscreen><verb>
3007 GtkWidget *gtk_progress_bar_new( void );
3008 </verb></tscreen>
3009
3010 Now that the progress bar has been created we can use it.
3011
3012 <tscreen><verb>
3013 void gtk_progress_bar_update( GtkProgressBar *pbar,
3014                               gfloat          percentage );
3015 </verb></tscreen>
3016
3017 The first argument is the progress bar you wish to operate on, and the second 
3018 argument is the amount 'completed', meaning the amount the progress bar has 
3019 been filled from 0-100%. This is passed to the function as a real number
3020 ranging from 0 to 1.
3021
3022 Progress Bars are usually used with timeouts or other such functions (see
3023 section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle Functions">) 
3024 to give the illusion of multitasking.  All will employ 
3025 the gtk_progress_bar_update function in the same manner.
3026
3027 Here is an example of the progress bar, updated using timeouts.  This 
3028 code also shows you how to reset the Progress Bar.
3029
3030 <tscreen><verb>
3031 /* example-start progressbar progressbar.c */
3032
3033 #include <gtk/gtk.h>
3034
3035 static int ptimer = 0;
3036 int pstat = TRUE;
3037
3038 /* This function increments and updates the progress bar, it also resets
3039  the progress bar if pstat is FALSE */
3040 gint progress (gpointer data)
3041 {
3042     gfloat pvalue;
3043     
3044     /* get the current value of the progress bar */
3045     pvalue = GTK_PROGRESS_BAR (data)->percentage;
3046     
3047     if ((pvalue >= 1.0) || (pstat == FALSE)) {
3048         pvalue = 0.0;
3049         pstat = TRUE;
3050     }
3051     pvalue += 0.01;
3052     
3053     gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue);
3054     
3055     return TRUE;
3056 }
3057
3058 /* This function signals a reset of the progress bar */
3059 void progress_r (void)
3060 {  
3061     pstat = FALSE;  
3062 }
3063
3064 void destroy (GtkWidget *widget, GdkEvent *event, gpointer data)
3065 {
3066     gtk_main_quit ();
3067 }
3068
3069 int main (int argc, char *argv[])
3070 {
3071     GtkWidget *window;
3072     GtkWidget *button;
3073     GtkWidget *label;
3074     GtkWidget *table;
3075     GtkWidget *pbar;
3076     
3077     gtk_init (&amp;argc, &amp;argv);
3078     
3079     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3080     
3081     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
3082                         GTK_SIGNAL_FUNC (destroy), NULL);
3083     
3084     gtk_container_border_width (GTK_CONTAINER (window), 10);
3085     
3086     table = gtk_table_new(3,2,TRUE);
3087     gtk_container_add (GTK_CONTAINER (window), table);
3088     
3089     label = gtk_label_new ("Progress Bar Example");
3090     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,2,0,1);
3091     gtk_widget_show(label);
3092     
3093     /* Create a new progress bar, pack it into the table, and show it */
3094     pbar = gtk_progress_bar_new ();
3095     gtk_table_attach_defaults(GTK_TABLE(table), pbar, 0,2,1,2);
3096     gtk_widget_show (pbar);
3097     
3098     /* Set the timeout to handle automatic updating of the progress bar */
3099     ptimer = gtk_timeout_add (100, progress, pbar);
3100     
3101     /* This button signals the progress bar to be reset */
3102     button = gtk_button_new_with_label ("Reset");
3103     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3104                         GTK_SIGNAL_FUNC (progress_r), NULL);
3105     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,2,3);
3106     gtk_widget_show(button);
3107     
3108     button = gtk_button_new_with_label ("Cancel");
3109     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3110                         GTK_SIGNAL_FUNC (destroy), NULL);
3111     
3112     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,2,3);
3113     gtk_widget_show (button);
3114     
3115     gtk_widget_show(table);
3116     gtk_widget_show(window);
3117     
3118     gtk_main ();
3119     
3120     return 0;
3121 }
3122 /* example-end */
3123 </verb></tscreen>
3124
3125 In this small program there are four areas that concern the general operation
3126 of Progress Bars, we will look at them in the order they are called.
3127
3128 <tscreen><verb>
3129     pbar = gtk_progress_bar_new ();
3130 </verb></tscreen>
3131
3132 This code creates a new progress bar, called pbar.
3133
3134 <tscreen><verb>
3135     ptimer = gtk_timeout_add (100, progress, pbar);
3136 </verb></tscreen>
3137
3138 This code uses timeouts to enable a constant time interval, timeouts are 
3139 not necessary in the use of Progress Bars. 
3140
3141 <tscreen><verb>
3142     pvalue = GTK_PROGRESS_BAR (data)->percentage;
3143 </verb></tscreen>
3144
3145 This code assigns the current value of the percentage bar to pvalue.
3146
3147 <tscreen><verb>
3148     gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue);
3149 </verb></tscreen>
3150
3151 Finally, this code updates the progress bar with the value of pvalue
3152
3153 And that is all there is to know about Progress Bars, enjoy.
3154
3155 <!-- ----------------------------------------------------------------- -->
3156 <sect1> Dialogs
3157 <p>
3158 The Dialog widget is very simple, and is actually just a window with a few
3159 things pre-packed into it for you. The structure for a Dialog is:
3160
3161 <tscreen><verb>
3162 struct GtkDialog
3163 {
3164       GtkWindow window;
3165     
3166       GtkWidget *vbox;
3167       GtkWidget *action_area;
3168 };
3169 </verb></tscreen>
3170
3171 So you see, it simply creates a window, and then packs a vbox into the top,
3172 then a separator, and then an hbox for the "action_area".
3173
3174 The Dialog widget can be used for pop-up messages to the user, and 
3175 other similar tasks.  It is really basic, and there is only one 
3176 function for the dialog box, which is:
3177
3178 <tscreen><verb>
3179 GtkWidget *gtk_dialog_new( void );
3180 </verb></tscreen>
3181
3182 So to create a new dialog box, use,
3183
3184 <tscreen><verb>
3185 GtkWidget *window;
3186 window = gtk_dialog_new ();
3187 </verb></tscreen>
3188
3189 This will create the dialog box, and it is now up to you to use it.
3190 you could pack a button in the action_area by doing something like this:
3191
3192 <tscreen><verb>
3193 button = ...
3194 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button,
3195                     TRUE, TRUE, 0);
3196 gtk_widget_show (button);
3197 </verb></tscreen>
3198
3199 And you could add to the vbox area by packing, for instance, a label 
3200 in it, try something like this:
3201
3202 <tscreen><verb>
3203 label = gtk_label_new ("Dialogs are groovy");
3204 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE,
3205                     TRUE, 0);
3206 gtk_widget_show (label);
3207 </verb></tscreen>
3208
3209 As an example in using the dialog box, you could put two buttons in 
3210 the action_area, a Cancel button and an Ok button, and a label in the vbox 
3211 area, asking the user a question or giving an error etc.  Then you could 
3212 attach a different signal to each of the buttons and perform the 
3213 operation the user selects.
3214
3215 If the simple functionality provided by the default vertical and
3216 horizontal boxes in the two areas don't give you enough control for your
3217 application, then you can simply pack another layout widget into the boxes
3218 provided. For example, you could pack a table into the vertical box.
3219
3220 <!-- ----------------------------------------------------------------- -->
3221 <sect1> Pixmaps <label id="sec_Pixmaps">
3222 <p>
3223 Pixmaps are data structures that contain pictures. These pictures can be
3224 used in various places, but most visibly as icons on the X-Windows desktop,
3225 or as cursors. A bitmap is a 2-color pixmap.
3226
3227 To use pixmaps in GTK, we must first build a GdkPixmap structure using
3228 routines from the GDK layer. Pixmaps can either be created from in-memory
3229 data, or from data read from a file. We'll go through each of the calls
3230 to create a pixmap.
3231
3232 <tscreen><verb>
3233 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
3234                                         gchar     *data,
3235                                         gint       width,
3236                                         gint       height );
3237 </verb></tscreen>
3238
3239 This routine is used to create a single-plane pixmap (2 colors) from data in
3240 memory. Each bit of the data represents whether that pixel is off or on.
3241 Width and height are in pixels. The GdkWindow pointer is to the current
3242 window, since a pixmap resources are meaningful only in the context of the
3243 screen where it is to be displayed.
3244
3245 <tscreen><verb>
3246 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
3247                                         gchar     *data,
3248                                         gint       width,
3249                                         gint       height,
3250                                         gint       depth,
3251                                         GdkColor  *fg,
3252                                         GdkColor  *bg );
3253 </verb></tscreen>
3254
3255 This is used to create a pixmap of the given depth (number of colors) from
3256 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
3257 background color to use.
3258
3259 <tscreen><verb>
3260 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
3261                                        GdkBitmap  **mask,
3262                                        GdkColor    *transparent_color,
3263                                        const gchar *filename );
3264 </verb></tscreen>
3265
3266 XPM format is a readable pixmap representation for the X Window System.  It
3267 is widely used and many different utilities are available for creating image
3268 files in this format.  The file specified by filename must contain an image
3269 in that format and it is loaded into the pixmap structure. The mask specifies
3270 which bits of the pixmap are opaque. All other bits are colored using the
3271 color specified by transparent_color. An example using this follows below.  
3272
3273 <tscreen><verb>
3274 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
3275                                          GdkBitmap **mask,
3276                                          GdkColor   *transparent_color,
3277                                          gchar     **data );
3278 </verb></tscreen>
3279
3280 Small images can be incorporated into a program as data in the XPM format.
3281 A pixmap is created using this data, instead of reading it from a file.
3282 An example of such data is
3283
3284 <tscreen><verb>
3285 /* XPM */
3286 static const char * xpm_data[] = {
3287 "16 16 3 1",
3288 "       c None",
3289 ".      c #000000000000",
3290 "X      c #FFFFFFFFFFFF",
3291 "                ",
3292 "   ......       ",
3293 "   .XXX.X.      ",
3294 "   .XXX.XX.     ",
3295 "   .XXX.XXX.    ",
3296 "   .XXX.....    ",
3297 "   .XXXXXXX.    ",
3298 "   .XXXXXXX.    ",
3299 "   .XXXXXXX.    ",
3300 "   .XXXXXXX.    ",
3301 "   .XXXXXXX.    ",
3302 "   .XXXXXXX.    ",
3303 "   .XXXXXXX.    ",
3304 "   .........    ",
3305 "                ",
3306 "                "};
3307 </verb></tscreen>
3308
3309 When we're done using a pixmap and not likely to reuse it again soon,
3310 it is a good idea to release the resource using gdk_pixmap_unref(). Pixmaps
3311 should be considered a precious resource.
3312
3313 Once we've created a pixmap, we can display it as a GTK widget. We must
3314 create a pixmap widget to contain the GDK pixmap. This is done using
3315
3316 <tscreen><verb>
3317 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
3318                            GdkBitmap *mask );
3319 </verb></tscreen>
3320
3321 The other pixmap widget calls are
3322
3323 <tscreen><verb>
3324 guint gtk_pixmap_get_type( void );
3325
3326 void  gtk_pixmap_set( GtkPixmap  *pixmap,
3327                       GdkPixmap  *val,
3328                       GdkBitmap  *mask );
3329
3330 void  gtk_pixmap_get( GtkPixmap  *pixmap,
3331                       GdkPixmap **val,
3332                       GdkBitmap **mask);
3333 </verb></tscreen>
3334
3335 gtk_pixmap_set is used to change the pixmap that the widget is currently
3336 managing. Val is the pixmap created using GDK.
3337
3338 The following is an example of using a pixmap in a button.
3339
3340 <tscreen><verb>
3341 /* example-start pixmap pixmap.c */
3342
3343 #include <gtk/gtk.h>
3344
3345
3346 /* XPM data of Open-File icon */
3347 static const char * xpm_data[] = {
3348 "16 16 3 1",
3349 "       c None",
3350 ".      c #000000000000",
3351 "X      c #FFFFFFFFFFFF",
3352 "                ",
3353 "   ......       ",
3354 "   .XXX.X.      ",
3355 "   .XXX.XX.     ",
3356 "   .XXX.XXX.    ",
3357 "   .XXX.....    ",
3358 "   .XXXXXXX.    ",
3359 "   .XXXXXXX.    ",
3360 "   .XXXXXXX.    ",
3361 "   .XXXXXXX.    ",
3362 "   .XXXXXXX.    ",
3363 "   .XXXXXXX.    ",
3364 "   .XXXXXXX.    ",
3365 "   .........    ",
3366 "                ",
3367 "                "};
3368
3369
3370 /* when invoked (via signal delete_event), terminates the application.
3371  */
3372 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
3373     gtk_main_quit();
3374 }
3375
3376
3377 /* is invoked when the button is clicked.  It just prints a message.
3378  */
3379 void button_clicked( GtkWidget *widget, gpointer data ) {
3380     printf( "button clicked\n" );
3381 }
3382
3383 int main( int argc, char *argv[] )
3384 {
3385     /* GtkWidget is the storage type for widgets */
3386     GtkWidget *window, *pixmapwid, *button;
3387     GdkPixmap *pixmap;
3388     GdkBitmap *mask;
3389     GtkStyle *style;
3390     
3391     /* create the main window, and attach delete_event signal to terminating
3392        the application */
3393     gtk_init( &amp;argc, &amp;argv );
3394     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3395     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
3396                         GTK_SIGNAL_FUNC (close_application), NULL );
3397     gtk_container_border_width( GTK_CONTAINER (window), 10 );
3398     gtk_widget_show( window );
3399
3400     /* now for the pixmap from gdk */
3401     style = gtk_widget_get_style( window );
3402     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
3403                                            &amp;style->bg[GTK_STATE_NORMAL],
3404                                            (gchar **)xpm_data );
3405
3406     /* a pixmap widget to contain the pixmap */
3407     pixmapwid = gtk_pixmap_new( pixmap, mask );
3408     gtk_widget_show( pixmapwid );
3409
3410     /* a button to contain the pixmap widget */
3411     button = gtk_button_new();
3412     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
3413     gtk_container_add( GTK_CONTAINER(window), button );
3414     gtk_widget_show( button );
3415
3416     gtk_signal_connect( GTK_OBJECT(button), "clicked",
3417                         GTK_SIGNAL_FUNC(button_clicked), NULL );
3418
3419     /* show the window */
3420     gtk_main ();
3421           
3422     return 0;
3423 }
3424 /* example-end */
3425 </verb></tscreen>
3426
3427 To load a file from an XPM data file called icon0.xpm in the current
3428 directory, we would have created the pixmap thus
3429
3430 <tscreen><verb>
3431     /* load a pixmap from a file */
3432     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
3433                                          &amp;style->bg[GTK_STATE_NORMAL],
3434                                          "./icon0.xpm" );
3435     pixmapwid = gtk_pixmap_new( pixmap, mask );
3436     gtk_widget_show( pixmapwid );
3437     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
3438 </verb></tscreen>
3439
3440 A disadvantage of using pixmaps is that the displayed object is always
3441 rectangular, regardless of the image. We would like to create desktops
3442 and applications with icons that have more natural shapes. For example,
3443 for a game interface, we would like to have round buttons to push. The
3444 way to do this is using shaped windows.
3445
3446 A shaped window is simply a pixmap where the background pixels are
3447 transparent. This way, when the background image is multi-colored, we
3448 don't overwrite it with a rectangular, non-matching border around our
3449 icon. The following example displays a full wheelbarrow image on the
3450 desktop.
3451
3452 <tscreen><verb>
3453 /* example-start wheelbarrow wheelbarrow.c */
3454
3455 #include <gtk/gtk.h>
3456
3457 /* XPM */
3458 static char * WheelbarrowFull_xpm[] = {
3459 "48 48 64 1",
3460 "       c None",
3461 ".      c #DF7DCF3CC71B",
3462 "X      c #965875D669A6",
3463 "o      c #71C671C671C6",
3464 "O      c #A699A289A699",
3465 "+      c #965892489658",
3466 "@      c #8E38410330C2",
3467 "#      c #D75C7DF769A6",
3468 "$      c #F7DECF3CC71B",
3469 "%      c #96588A288E38",
3470 "&amp;      c #A69992489E79",
3471 "*      c #8E3886178E38",
3472 "=      c #104008200820",
3473 "-      c #596510401040",
3474 ";      c #C71B30C230C2",
3475 ":      c #C71B9A699658",
3476 ">      c #618561856185",
3477 ",      c #20811C712081",
3478 "<      c #104000000000",
3479 "1      c #861720812081",
3480 "2      c #DF7D4D344103",
3481 "3      c #79E769A671C6",
3482 "4      c #861782078617",
3483 "5      c #41033CF34103",
3484 "6      c #000000000000",
3485 "7      c #49241C711040",
3486 "8      c #492445144924",
3487 "9      c #082008200820",
3488 "0      c #69A618611861",
3489 "q      c #B6DA71C65144",
3490 "w      c #410330C238E3",
3491 "e      c #CF3CBAEAB6DA",
3492 "r      c #71C6451430C2",
3493 "t      c #EFBEDB6CD75C",
3494 "y      c #28A208200820",
3495 "u      c #186110401040",
3496 "i      c #596528A21861",
3497 "p      c #71C661855965",
3498 "a      c #A69996589658",
3499 "s      c #30C228A230C2",
3500 "d      c #BEFBA289AEBA",
3501 "f      c #596545145144",
3502 "g      c #30C230C230C2",
3503 "h      c #8E3882078617",
3504 "j      c #208118612081",
3505 "k      c #38E30C300820",
3506 "l      c #30C2208128A2",
3507 "z      c #38E328A238E3",
3508 "x      c #514438E34924",
3509 "c      c #618555555965",
3510 "v      c #30C2208130C2",
3511 "b      c #38E328A230C2",
3512 "n      c #28A228A228A2",
3513 "m      c #41032CB228A2",
3514 "M      c #104010401040",
3515 "N      c #492438E34103",
3516 "B      c #28A2208128A2",
3517 "V      c #A699596538E3",
3518 "C      c #30C21C711040",
3519 "Z      c #30C218611040",
3520 "A      c #965865955965",
3521 "S      c #618534D32081",
3522 "D      c #38E31C711040",
3523 "F      c #082000000820",
3524 "                                                ",
3525 "          .XoO                                  ",
3526 "         +@#$%o&amp;                                ",
3527 "         *=-;#::o+                              ",
3528 "           >,<12#:34                            ",
3529 "             45671#:X3                          ",
3530 "               +89<02qwo                        ",
3531 "e*                >,67;ro                       ",
3532 "ty>                 459@>+&amp;&amp;                    ",
3533 "$2u+                  ><ipas8*                  ",
3534 "%$;=*                *3:.Xa.dfg>                ",
3535 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
3536 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
3537 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
3538 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
3539 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
3540 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
3541 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
3542 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
3543 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
3544 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
3545 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
3546 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
3547 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
3548 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
3549 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
3550 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
3551 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
3552 "              p;<69BvwwsszslllbBlllllllu<5+     ",
3553 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
3554 "               c1-699Blvlllllu7k96MMMg4         ",
3555 "               *10y8n6FjvllllB<166668           ",
3556 "                S-kg+>666<M<996-y6n<8*          ",
3557 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
3558 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
3559 "                 N-k-<>     >=01-kuu666>        ",
3560 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
3561 "                 Ou0<>       o66y<ulw<66&amp;       ",
3562 "                  *kk5       >66By7=xu664       ",
3563 "                   <<M4      466lj<Mxu66o       ",
3564 "                   *>>       +66uv,zN666*       ",
3565 "                              566,xxj669        ",
3566 "                              4666FF666>        ",
3567 "                               >966666M         ",
3568 "                                oM6668+         ",
3569 "                                  *4            ",
3570 "                                                ",
3571 "                                                "};
3572
3573
3574 /* when invoked (via signal delete_event), terminates the application.
3575  */
3576 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
3577     gtk_main_quit();
3578 }
3579
3580 int main (int argc, char *argv[])
3581 {
3582     /* GtkWidget is the storage type for widgets */
3583     GtkWidget *window, *pixmap, *fixed;
3584     GdkPixmap *gdk_pixmap;
3585     GdkBitmap *mask;
3586     GtkStyle *style;
3587     GdkGC *gc;
3588     
3589     /* create the main window, and attach delete_event signal to terminate
3590        the application.  Note that the main window will not have a titlebar
3591        since we're making it a popup. */
3592     gtk_init (&amp;argc, &amp;argv);
3593     window = gtk_window_new( GTK_WINDOW_POPUP );
3594     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
3595                         GTK_SIGNAL_FUNC (close_application), NULL);
3596     gtk_widget_show (window);
3597
3598     /* now for the pixmap and the pixmap widget */
3599     style = gtk_widget_get_default_style();
3600     gc = style->black_gc;
3601     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
3602                                              &amp;style->bg[GTK_STATE_NORMAL],
3603                                              WheelbarrowFull_xpm );
3604     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
3605     gtk_widget_show( pixmap );
3606
3607     /* To display the pixmap, we use a fixed widget to place the pixmap */
3608     fixed = gtk_fixed_new();
3609     gtk_widget_set_usize( fixed, 200, 200 );
3610     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
3611     gtk_container_add( GTK_CONTAINER(window), fixed );
3612     gtk_widget_show( fixed );
3613
3614     /* This masks out everything except for the image itself */
3615     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
3616     
3617     /* show the window */
3618     gtk_widget_set_uposition( window, 20, 400 );
3619     gtk_widget_show( window );
3620     gtk_main ();
3621           
3622     return 0;
3623 }
3624 /* example-end */
3625 </verb></tscreen>
3626
3627 To make the wheelbarrow image sensitive, we could attach the button press
3628 event signal to make it do something.  The following few lines would make
3629 the picture sensitive to a mouse button being pressed which makes the
3630 application terminate.
3631
3632 <tscreen><verb>
3633 gtk_widget_set_events( window,
3634                        gtk_widget_get_events( window ) |
3635                        GDK_BUTTON_PRESS_MASK );
3636
3637 gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
3638                     GTK_SIGNAL_FUNC(close_application), NULL );
3639 </verb></tscreen>
3640
3641 <!-- ----------------------------------------------------------------- -->
3642 <sect1>Rulers
3643 <p>
3644 Ruler widgets are used to indicate the location of the mouse pointer
3645 in a given window. A window can have a vertical ruler spanning across
3646 the width and a horizontal ruler spanning down the height.  A small
3647 triangular indicator on the ruler shows the exact location of the
3648 pointer relative to the ruler.
3649
3650 A ruler must first be created. Horizontal and vertical rulers are
3651 created using
3652
3653 <tscreen><verb>
3654 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
3655 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
3656 </verb></tscreen>
3657
3658 Once a ruler is created, we can define the unit of measurement. Units
3659 of measure for rulers can be GTK_PIXELS, GTK_INCHES or
3660 GTK_CENTIMETERS. This is set using
3661
3662 <tscreen><verb>
3663 void gtk_ruler_set_metric( GtkRuler      *ruler,
3664                            GtkMetricType  metric );
3665 </verb></tscreen>
3666
3667 The default measure is GTK_PIXELS.
3668
3669 <tscreen><verb>
3670 gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
3671 </verb></tscreen>
3672
3673 Other important characteristics of a ruler are how to mark the units
3674 of scale and where the position indicator is initially placed. These
3675 are set for a ruler using
3676
3677 <tscreen><verb>
3678 void gtk_ruler_set_range( GtkRuler *ruler,
3679                           gfloat    lower,
3680                           gfloat    upper,
3681                           gfloat    position,
3682                           gfloat    max_size );
3683 </verb></tscreen>
3684
3685 The lower and upper arguments define the extent of the ruler, and
3686 max_size is the largest possible number that will be displayed.
3687 Position defines the initial position of the pointer indicator within
3688 the ruler.
3689
3690 A vertical ruler can span an 800 pixel wide window thus
3691
3692 <tscreen><verb>
3693 gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
3694 </verb></tscreen>
3695
3696 The markings displayed on the ruler will be from 0 to 800, with
3697 a number for every 100 pixels. If instead we wanted the ruler to
3698 range from 7 to 16, we would code
3699
3700 <tscreen><verb>
3701 gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
3702 </verb></tscreen>
3703
3704 The indicator on the ruler is a small triangular mark that indicates
3705 the position of the pointer relative to the ruler. If the ruler is
3706 used to follow the mouse pointer, the motion_notify_event signal
3707 should be connected to the motion_notify_event method of the ruler.
3708 To follow all mouse movements within a window area, we would use
3709
3710 <tscreen><verb>
3711 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
3712
3713 gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
3714          (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
3715          GTK_OBJECT(ruler) );
3716 </verb></tscreen>
3717
3718 The following example creates a drawing area with a horizontal ruler
3719 above it and a vertical ruler to the left of it.  The size of the
3720 drawing area is 600 pixels wide by 400 pixels high. The horizontal
3721 ruler spans from 7 to 13 with a mark every 100 pixels, while the
3722 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
3723 Placement of the drawing area and the rulers are done using a table.
3724
3725 <tscreen><verb>
3726 /* example-start rulers rulers.c */
3727
3728 #include <gtk/gtk.h>
3729
3730 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
3731
3732 #define XSIZE  600
3733 #define YSIZE  400
3734
3735 /* this routine gets control when the close button is clicked
3736  */
3737 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
3738     gtk_main_quit();
3739 }
3740
3741
3742 /* the main routine
3743  */
3744 int main( int argc, char *argv[] ) {
3745     GtkWidget *window, *table, *area, *hrule, *vrule;
3746
3747     /* initialize gtk and create the main window */
3748     gtk_init( &amp;argc, &amp;argv );
3749
3750     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3751     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
3752             GTK_SIGNAL_FUNC( close_application ), NULL);
3753     gtk_container_border_width (GTK_CONTAINER (window), 10);
3754
3755     /* create a table for placing the ruler and the drawing area */
3756     table = gtk_table_new( 3, 2, FALSE );
3757     gtk_container_add( GTK_CONTAINER(window), table );
3758
3759     area = gtk_drawing_area_new();
3760     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
3761     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
3762                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
3763     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
3764
3765     /* The horizontal ruler goes on top.  As the mouse moves across the drawing area,
3766        a motion_notify_event is passed to the appropriate event handler for the ruler. */
3767     hrule = gtk_hruler_new();
3768     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
3769     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
3770     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
3771                                (GtkSignalFunc)EVENT_METHOD(hrule, motion_notify_event),
3772                                GTK_OBJECT(hrule) );
3773     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
3774     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
3775                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
3776     
3777     /* The vertical ruler goes on the left.  As the mouse moves across the drawing area,
3778        a motion_notify_event is passed to the appropriate event handler for the ruler. */
3779     vrule = gtk_vruler_new();
3780     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
3781     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
3782     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
3783                                (GtkSignalFunc)
3784                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->motion_notify_event,
3785                                GTK_OBJECT(vrule) );
3786     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
3787                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
3788
3789     /* now show everything */
3790     gtk_widget_show( area );
3791     gtk_widget_show( hrule );
3792     gtk_widget_show( vrule );
3793     gtk_widget_show( table );
3794     gtk_widget_show( window );
3795     gtk_main();
3796
3797     return 0;
3798 }
3799 /* example-end */
3800 </verb></tscreen>
3801
3802 <!-- ----------------------------------------------------------------- -->
3803 <sect1>Statusbars
3804 <p>
3805 Statusbars are simple widgets used to display a text message. They keep
3806 a stack  of the messages pushed onto them, so that popping the current
3807 message will re-display the previous text message.
3808
3809 In order to allow different parts of an application to use the same
3810 statusbar to display messages, the statusbar widget issues Context
3811 Identifiers which are used to identify different 'users'. The message on
3812 top of the stack is the one displayed, no matter what context it is in.
3813 Messages are stacked in last-in-first-out order, not context identifier order.
3814
3815 A statusbar is created with a call to:
3816
3817 <tscreen><verb>
3818 GtkWidget *gtk_statusbar_new( void );
3819 </verb></tscreen>
3820
3821 A new Context Identifier is requested using a call to the following 
3822 function with a short textual description of the context:
3823
3824 <tscreen><verb>
3825 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
3826                                     const gchar  *context_description );
3827 </verb></tscreen>
3828
3829 There are three functions that can operate on statusbars:
3830
3831 <tscreen><verb>
3832 guint gtk_statusbar_push( GtkStatusbar *statusbar,
3833                           guint         context_id,
3834                           gchar        *text );
3835
3836 void gtk_statusbar_pop( GtkStatusbar *statusbar)
3837                         guint         context_id );
3838
3839 void gtk_statusbar_remove( GtkStatusbar *statusbar,
3840                            guint         context_id,
3841                            guint         message_id ); 
3842 </verb></tscreen>
3843
3844 The first, gtk_statusbar_push, is used to add a new message to the statusbar. 
3845 It returns a Message Identifier, which can be passed later to the function
3846 gtk_statusbar_remove to remove the message with the given Message and Context
3847 Identifiers from the statusbar's stack.
3848
3849 The function gtk_statusbar_pop removes the message highest in the stack with
3850 the given Context Identifier.
3851
3852 The following example creates a statusbar and two buttons, one for pushing items
3853 onto the statusbar, and one for popping the last item back off.
3854
3855 <tscreen><verb>
3856 /* example-start statusbar statusbar.c */
3857
3858 #include <gtk/gtk.h>
3859 #include <glib.h>
3860
3861 GtkWidget *status_bar;
3862
3863 void push_item (GtkWidget *widget, gpointer data)
3864 {
3865   static int count = 1;
3866   char buff[20];
3867
3868   g_snprintf(buff, 20, "Item %d", count++);
3869   gtk_statusbar_push( GTK_STATUSBAR(status_bar), (guint) &amp;data, buff);
3870
3871   return;
3872 }
3873
3874 void pop_item (GtkWidget *widget, gpointer data)
3875 {
3876   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), (guint) &amp;data );
3877   return;
3878 }
3879
3880 int main (int argc, char *argv[])
3881 {
3882
3883     GtkWidget *window;
3884     GtkWidget *vbox;
3885     GtkWidget *button;
3886
3887     int context_id;
3888
3889     gtk_init (&amp;argc, &amp;argv);
3890
3891     /* create a new window */
3892     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
3893     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
3894     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
3895     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
3896                        (GtkSignalFunc) gtk_exit, NULL);
3897  
3898     vbox = gtk_vbox_new(FALSE, 1);
3899     gtk_container_add(GTK_CONTAINER(window), vbox);
3900     gtk_widget_show(vbox);
3901           
3902     status_bar = gtk_statusbar_new();      
3903     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
3904     gtk_widget_show (status_bar);
3905
3906     context_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(status_bar), "Statusbar example");
3907
3908     button = gtk_button_new_with_label("push item");
3909     gtk_signal_connect(GTK_OBJECT(button), "clicked",
3910         GTK_SIGNAL_FUNC (push_item), &amp;context_id);
3911     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
3912     gtk_widget_show(button);              
3913
3914     button = gtk_button_new_with_label("pop last item");
3915     gtk_signal_connect(GTK_OBJECT(button), "clicked",
3916         GTK_SIGNAL_FUNC (pop_item), &amp;context_id);
3917     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
3918     gtk_widget_show(button);              
3919
3920     /* always display the window as the last step so it all splashes on
3921      * the screen at once. */
3922     gtk_widget_show(window);
3923
3924     gtk_main ();
3925
3926     return 0;
3927 }
3928 /* example-end */
3929 </verb></tscreen>
3930
3931 <!-- ----------------------------------------------------------------- -->
3932 <sect1>Text Entries
3933 <p>
3934 The Entry widget allows text to be typed and displayed in a single line
3935 text box. The text may be set with function calls that allow new text
3936 to replace, prepend or append the current contents of the Entry widget.
3937
3938 There are two functions for creating Entry widgets:
3939
3940 <tscreen><verb>
3941 GtkWidget *gtk_entry_new( void );
3942
3943 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
3944 </verb></tscreen>
3945
3946 The first just creates a new Entry widget, whilst the second creates a
3947 new Entry and sets a limit on the length of the text within the Entry.
3948
3949 There are several functions for altering the text which is currently
3950 within the Entry widget.
3951
3952 <tscreen><verb>
3953 void gtk_entry_set_text( GtkEntry    *entry,
3954                          const gchar *text );
3955
3956 void gtk_entry_append_text( GtkEntry    *entry,
3957                             const gchar *text );
3958
3959 void gtk_entry_prepend_text( GtkEntry    *entry,
3960                              const gchar *text );
3961 </verb></tscreen>
3962
3963 The function gtk_entry_set_text sets the contents of the Entry widget,
3964 replacing the current contents. The functions gtk_entry_append_text and
3965 gtk_entry_prepend_text allow the current contents to be appended and
3966 prepended to.
3967
3968 The next function allows the current insertion point to be set.
3969
3970 <tscreen><verb>
3971 void gtk_entry_set_position( GtkEntry *entry,
3972                              gint      position );
3973 </verb></tscreen>
3974
3975 The contents of the Entry can be retrieved by using a call to the
3976 following function. This is useful in the callback functions described below.
3977
3978 <tscreen><verb>
3979 gchar *gtk_entry_get_text( GtkEntry *entry );
3980 </verb></tscreen>
3981
3982 If we don't want the contents of the Entry to be changed by someone typing
3983 into it, we can change its editable state.
3984
3985 <tscreen><verb>
3986 void gtk_entry_set_editable( GtkEntry *entry,
3987                              gboolean  editable );
3988 </verb></tscreen>
3989
3990 This function allows us to toggle the editable state of the Entry widget 
3991 by passing in a TRUE or FALSE value for the <tt/editable/ argument.
3992
3993 If we are using the Entry where we don't want the text entered to be visible,
3994 for example when a password is being entered, we can use the following
3995 function, which also takes a boolean flag.
3996
3997 <tscreen><verb>
3998 void gtk_entry_set_visibility( GtkEntry *entry,
3999                                gboolean  visible );
4000 </verb></tscreen>
4001
4002 A region of the text may be set as selected by using the following 
4003 function. This would most often be used after setting some default text 
4004 in an Entry, making it easy for the user to remove it.
4005
4006 <tscreen><verb>
4007 void gtk_entry_select_region( GtkEntry *entry,
4008                               gint      start,
4009                               gint      end );
4010 </verb></tscreen>
4011
4012 If we want to catch when the user has entered text, we can connect to the
4013 <tt/activate/ or <tt/changed/ signal. Activate is raised when the user hits 
4014 the enter key within the Entry widget. Changed is raised when the text
4015 changes at all, e.g. for every character entered or removed.
4016
4017 The following code is an example of using an Entry widget.
4018
4019 <tscreen><verb>
4020 /* example-start entry entry.c */
4021
4022 #include <gtk/gtk.h>
4023
4024 void enter_callback(GtkWidget *widget, GtkWidget *entry)
4025 {
4026   gchar *entry_text;
4027   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4028   printf("Entry contents: %s\n", entry_text);
4029 }
4030
4031 void entry_toggle_editable (GtkWidget *checkbutton,
4032                                    GtkWidget *entry)
4033 {
4034   gtk_entry_set_editable(GTK_ENTRY(entry),
4035                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4036 }
4037
4038 void entry_toggle_visibility (GtkWidget *checkbutton,
4039                                    GtkWidget *entry)
4040 {
4041   gtk_entry_set_visibility(GTK_ENTRY(entry),
4042                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4043 }
4044
4045 int main (int argc, char *argv[])
4046 {
4047
4048     GtkWidget *window;
4049     GtkWidget *vbox, *hbox;
4050     GtkWidget *entry;
4051     GtkWidget *button;
4052     GtkWidget *check;
4053
4054     gtk_init (&amp;argc, &amp;argv);
4055
4056     /* create a new window */
4057     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4058     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4059     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4060     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4061                        (GtkSignalFunc) gtk_exit, NULL);
4062
4063     vbox = gtk_vbox_new (FALSE, 0);
4064     gtk_container_add (GTK_CONTAINER (window), vbox);
4065     gtk_widget_show (vbox);
4066
4067     entry = gtk_entry_new_with_max_length (50);
4068     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4069                        GTK_SIGNAL_FUNC(enter_callback),
4070                        entry);
4071     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4072     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4073     gtk_entry_select_region (GTK_ENTRY (entry),
4074                              0, GTK_ENTRY(entry)->text_length);
4075     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4076     gtk_widget_show (entry);
4077
4078     hbox = gtk_hbox_new (FALSE, 0);
4079     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4080     gtk_widget_show (hbox);
4081                                   
4082     check = gtk_check_button_new_with_label("Editable");
4083     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4084     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4085                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4086     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
4087     gtk_widget_show (check);
4088     
4089     check = gtk_check_button_new_with_label("Visible");
4090     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4091     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4092                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4093     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
4094     gtk_widget_show (check);
4095                                    
4096     button = gtk_button_new_with_label ("Close");
4097     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4098                                GTK_SIGNAL_FUNC(gtk_exit),
4099                                GTK_OBJECT (window));
4100     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4101     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4102     gtk_widget_grab_default (button);
4103     gtk_widget_show (button);
4104     
4105     gtk_widget_show(window);
4106
4107     gtk_main();
4108     return(0);
4109 }
4110 /* example-end */
4111 </verb></tscreen>
4112
4113 <!-- ----------------------------------------------------------------- -->
4114 <sect1> Color Selection
4115 <p>
4116 The color selection widget is, not surprisingly, a widget for interactive
4117 selection of colors. This composite widget lets the user select a color by
4118 manipulating RGB (Red, Green, Blue) and HSV (Hue, Saturation, Value) triples.
4119 This is done either by adjusting single values with sliders or entries, or
4120 by picking the desired color from a hue-saturation wheel/value bar.
4121 Optionally, the opacity of the color can also be set.
4122
4123 The color selection widget currently emits only one signal,
4124 "color_changed", which is emitted whenever the current color in the widget
4125 changes, either when the user changes it or if it's set explicitly through
4126 gtk_color_selection_set_color().
4127
4128 Lets have a look at what the color selection widget has to offer us. The
4129 widget comes in two flavours; gtk_color_selection and
4130 gtk_color_selection_dialog:
4131
4132 <tscreen><verb>
4133 GtkWidget *gtk_color_selection_new( void );
4134 </verb></tscreen>
4135         
4136 You'll probably not be using this constructor directly. It creates an orphan
4137 GtkColorSelection widget which you'll have to parent yourself. The
4138 GtkColorSelection widget inherits from the GtkVBox widget.
4139
4140 <tscreen><verb> 
4141 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
4142 </verb></tscreen>
4143
4144 This is the most common color selection constructor. It creates a 
4145 GtkColorSelectionDialog, which inherits from a GtkDialog. It consists
4146 of a GtkFrame containing a GtkColorSelection widget, a GtkHSeparator and a
4147 GtkHBox with three buttons, "Ok", "Cancel" and "Help". You can reach these
4148 buttons by accessing the "ok_button", "cancel_button" and "help_button"
4149 widgets in the GtkColorSelectionDialog structure, 
4150 (i.e. GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
4151
4152 <tscreen><verb>
4153 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
4154                                             GtkUpdateType      policy );
4155 </verb></tscreen>
4156
4157 This function sets the update policy. The default policy is
4158 GTK_UPDATE_CONTINUOUS which means that the current color is updated 
4159 continuously when the user drags the sliders or presses the mouse and drags
4160 in the hue-saturation wheel or value bar. If you experience performance
4161 problems, you may want to set the policy to GTK_UPDATE_DISCONTINUOUS or 
4162 GTK_UPDATE_DELAYED.
4163
4164 <tscreen><verb>
4165 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
4166                                       gint               use_opacity );
4167 </verb></tscreen>
4168
4169 The color selection widget supports adjusting the opacity of a color
4170 (also known as the alpha channel). This is disabled by default. Calling
4171 this function with use_opacity set to TRUE enables opacity. Likewise,
4172 use_opacity set to FALSE will disable opacity.
4173
4174 <tscreen><verb>
4175 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
4176                                     gdouble           *color );
4177 </verb></tscreen>
4178
4179 You can set the current color explicitly by calling this function with
4180 a pointer to an array of colors (gdouble). The length of the array depends
4181 on whether opacity is enabled or not. Position 0 contains the red component,
4182 1 is green, 2 is blue and opacity is at position 3 (only if opacity is enabled,
4183 see gtk_color_selection_set_opacity()). All values are between 0.0 and 1.0.
4184
4185 <tscreen><verb>
4186 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
4187                                     gdouble           *color );
4188 </verb></tscreen>
4189
4190 When you need to query the current color, typically when you've received a
4191 "color_changed" signal, you use this function. Color is a pointer to the
4192 array of colors to fill in. See the gtk_color_selection_set_color() function
4193 for the description of this array.
4194
4195 <!-- Need to do a whole section on DnD - TRG
4196 Drag and drop
4197 -------------
4198
4199 The color sample areas (right under the hue-saturation wheel) supports drag and drop. The type of
4200 drag and drop is "application/x-color". The message data consists of an array of 4
4201 (or 5 if opacity is enabled) gdouble values, where the value at position 0 is 0.0 (opacity
4202 on) or 1.0 (opacity off) followed by the red, green and blue values at positions 1,2 and 3 respectively.
4203 If opacity is enabled, the opacity is passed in the value at position 4.
4204 -->
4205
4206 Here's a simple example demonstrating the use of the GtkColorSelectionDialog.
4207 The program displays a window containing a drawing area. Clicking on it opens
4208 a color selection dialog, and changing the color in the color selection dialog
4209 changes the background color.
4210
4211 <tscreen><verb>
4212 /* example-start colorsel colorsel.c */
4213
4214 #include <glib.h>
4215 #include <gdk/gdk.h>
4216 #include <gtk/gtk.h>
4217
4218 GtkWidget *colorseldlg = NULL;
4219 GtkWidget *drawingarea = NULL;
4220
4221 /* Color changed handler */
4222
4223 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
4224 {
4225   gdouble color[3];
4226   GdkColor gdk_color;
4227   GdkColormap *colormap;
4228
4229   /* Get drawingarea colormap */
4230
4231   colormap = gdk_window_get_colormap (drawingarea->window);
4232
4233   /* Get current color */
4234
4235   gtk_color_selection_get_color (colorsel,color);
4236
4237   /* Fit to a unsigned 16 bit integer (0..65535) and insert into the GdkColor structure */
4238
4239   gdk_color.red = (guint16)(color[0]*65535.0);
4240   gdk_color.green = (guint16)(color[1]*65535.0);
4241   gdk_color.blue = (guint16)(color[2]*65535.0);
4242
4243   /* Allocate color */
4244
4245   gdk_color_alloc (colormap, &amp;gdk_color);
4246
4247   /* Set window background color */
4248
4249   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
4250
4251   /* Clear window */
4252
4253   gdk_window_clear (drawingarea->window);
4254 }
4255
4256 /* Drawingarea event handler */
4257
4258 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
4259 {
4260   gint handled = FALSE;
4261   GtkWidget *colorsel;
4262
4263   /* Check if we've received a button pressed event */
4264
4265   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
4266     {
4267       /* Yes, we have an event and there's no colorseldlg yet! */
4268
4269       handled = TRUE;
4270
4271       /* Create color selection dialog */
4272
4273       colorseldlg = gtk_color_selection_dialog_new("Select background color");
4274
4275       /* Get the GtkColorSelection widget */
4276
4277       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
4278
4279       /* Connect to the "color_changed" signal, set the client-data to the colorsel widget */
4280
4281       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
4282         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
4283
4284       /* Show the dialog */
4285
4286       gtk_widget_show(colorseldlg);
4287     }
4288
4289   return handled;
4290 }
4291
4292 /* Close down and exit handler */
4293
4294 void destroy_window (GtkWidget *widget, gpointer client_data)
4295 {
4296   gtk_main_quit ();
4297 }
4298
4299 /* Main */
4300
4301 gint main (gint argc, gchar *argv[])
4302 {
4303   GtkWidget *window;
4304
4305   /* Initialize the toolkit, remove gtk-related commandline stuff */
4306
4307   gtk_init (&amp;argc,&amp;argv);
4308
4309   /* Create toplevel window, set title and policies */
4310
4311   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4312   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
4313   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
4314
4315   /* Attach to the "delete" and "destroy" events so we can exit */
4316
4317   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
4318     (GtkSignalFunc)destroy_window, (gpointer)window);
4319
4320   gtk_signal_connect (GTK_OBJECT(window), "destroy",
4321     (GtkSignalFunc)destroy_window, (gpointer)window);
4322   
4323   /* Create drawingarea, set size and catch button events */
4324
4325   drawingarea = gtk_drawing_area_new ();
4326
4327   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
4328
4329   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
4330
4331   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
4332     (GtkSignalFunc)area_event, (gpointer)drawingarea);
4333   
4334   /* Add drawingarea to window, then show them both */
4335
4336   gtk_container_add (GTK_CONTAINER(window), drawingarea);
4337
4338   gtk_widget_show (drawingarea);
4339   gtk_widget_show (window);
4340   
4341   /* Enter the gtk main loop (this never returns) */
4342
4343   gtk_main ();
4344
4345   /* Satisfy grumpy compilers */
4346
4347   return 0;
4348 }
4349 /* example-end */
4350 </verb></tscreen>
4351
4352 <!-- ----------------------------------------------------------------- -->
4353 <sect1> File Selections
4354 <p>
4355 The file selection widget is a quick and simple way to display a File 
4356 dialog box.  It comes complete with Ok, Cancel, and Help buttons, a great way
4357 to cut down on programming time.
4358
4359 To create a new file selection box use:
4360
4361 <tscreen><verb>
4362 GtkWidget *gtk_file_selection_new( gchar *title );
4363 </verb></tscreen>
4364
4365 To set the filename, for example to bring up a specific directory, or
4366 give a default filename, use this function: 
4367
4368 <tscreen><verb>
4369 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
4370                                       gchar            *filename );
4371 </verb></tscreen>
4372
4373 To grab the text that the user has entered or clicked on, use this 
4374 function:
4375
4376 <tscreen><verb>
4377 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
4378 </verb></tscreen>
4379
4380 There are also pointers to the widgets contained within the file 
4381 selection widget. These are:
4382
4383 <itemize>
4384 <item>dir_list
4385 <item>file_list
4386 <item>selection_entry
4387 <item>selection_text
4388 <item>main_vbox
4389 <item>ok_button
4390 <item>cancel_button
4391 <item>help_button
4392 </itemize>
4393
4394 Most likely you will want to use the ok_button, cancel_button, and
4395 help_button pointers in signaling their use.
4396
4397 Included here is an example stolen from testgtk.c, modified to run
4398 on its own.  As you will see, there is nothing much to creating a file 
4399 selection widget.  While in this example the Help button appears on the 
4400 screen, it does nothing as there is not a signal attached to it. 
4401
4402 <tscreen><verb>
4403 /* example-start filesel filesel.c */
4404
4405 #include <gtk/gtk.h>
4406
4407 /* Get the selected filename and print it to the console */
4408 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
4409 {
4410     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
4411 }
4412
4413 void destroy (GtkWidget *widget, gpointer data)
4414 {
4415     gtk_main_quit ();
4416 }
4417
4418 int main (int argc, char *argv[])
4419 {
4420     GtkWidget *filew;
4421     
4422     gtk_init (&amp;argc, &amp;argv);
4423     
4424     /* Create a new file selection widget */
4425     filew = gtk_file_selection_new ("File selection");
4426     
4427     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
4428                         (GtkSignalFunc) destroy, &amp;filew);
4429     /* Connect the ok_button to file_ok_sel function */
4430     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
4431                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
4432     
4433     /* Connect the cancel_button to destroy the widget */
4434     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button),
4435                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
4436                                GTK_OBJECT (filew));
4437     
4438     /* Lets set the filename, as if this were a save dialog, and we are giving
4439      a default filename */
4440     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
4441                                      "penguin.png");
4442     
4443     gtk_widget_show(filew);
4444     gtk_main ();
4445     return 0;
4446 }
4447 /* example-end */
4448 </verb></tscreen>
4449
4450 <!-- ***************************************************************** -->
4451 <sect> Container Widgets
4452 <!-- ***************************************************************** -->
4453
4454 <!-- ----------------------------------------------------------------- -->
4455 <sect1> Notebooks
4456 <p>
4457 The NoteBook Widget is a collection of 'pages' that overlap each other,
4458 each page contains different information.  This widget has become more common 
4459 lately in GUI programming, and it is a good way to show blocks of similar 
4460 information that warrant separation in their display.
4461
4462 The first function call you will need to know, as you can probably 
4463 guess by now, is used to create a new notebook widget.
4464
4465 <tscreen><verb>
4466 GtkWidget *gtk_notebook_new( void );
4467 </verb></tscreen>
4468
4469 Once the notebook has been created, there are 12 functions that 
4470 operate on the notebook widget. Let's look at them individually.
4471
4472 The first one we will look at is how to position the page indicators.
4473 These page indicators or 'tabs' as they are referred to, can be positioned
4474 in four ways: top, bottom, left, or right.
4475
4476 <tscreen><verb>
4477 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
4478                                GtkPositionType  pos );
4479 </verb></tscreen>
4480
4481 GtkPostionType will be one of the following, and they are pretty self explanatory:
4482 <itemize>
4483 <item> GTK_POS_LEFT
4484 <item> GTK_POS_RIGHT
4485 <item> GTK_POS_TOP
4486 <item> GTK_POS_BOTTOM
4487 </itemize>
4488
4489 GTK_POS_TOP is the default.
4490
4491 Next we will look at how to add pages to the notebook. There are three
4492 ways to add pages to the NoteBook.  Let's look at the first two together as 
4493 they are quite similar.
4494
4495 <tscreen><verb>
4496 void gtk_notebook_append_page( GtkNotebook *notebook,
4497                                GtkWidget   *child,
4498                                GtkWidget   *tab_label );
4499
4500 void gtk_notebook_prepend_page( GtkNotebook *notebook,
4501                                 GtkWidget   *child,
4502                                 GtkWidget   *tab_label );
4503 </verb></tscreen>
4504
4505 These functions add pages to the notebook by inserting them from the 
4506 back of the notebook (append), or the front of the notebook (prepend).  
4507 <tt/child/ is the widget that is placed within the notebook page, and
4508 <tt/tab_label/ is the label for the page being added.
4509
4510 The final function for adding a page to the notebook contains all of 
4511 the properties of the previous two, but it allows you to specify what position
4512 you want the page to be in the notebook.
4513
4514 <tscreen><verb>
4515 void gtk_notebook_insert_page( GtkNotebook *notebook,
4516                                GtkWidget   *child,
4517                                GtkWidget   *tab_label,
4518                                gint         position );
4519 </verb></tscreen>
4520
4521 The parameters are the same as _append_ and _prepend_ except it 
4522 contains an extra parameter, <tt/position/.  This parameter is used to
4523 specify what place this page will be inserted into.
4524
4525 Now that we know how to add a page, lets see how we can remove a page 
4526 from the notebook.
4527
4528 <tscreen><verb>
4529 void gtk_notebook_remove_page( GtkNotebook *notebook,
4530                                gint         page_num );
4531 </verb></tscreen>
4532
4533 This function takes the page specified by page_num and removes it from 
4534 the widget pointed to by <tt/notebook/.
4535
4536 To find out what the current page is in a notebook use the function:
4537
4538 <tscreen><verb>
4539 gint gtk_notebook_current_page( GtkNotebook *notebook );
4540 </verb></tscreen>
4541
4542 These next two functions are simple calls to move the notebook page 
4543 forward or backward. Simply provide the respective function call with the
4544 notebook widget you wish to operate on.  Note: when the NoteBook is currently
4545 on the last page, and gtk_notebook_next_page is called, the notebook will 
4546 wrap back to the first page. Likewise, if the NoteBook is on the first page, 
4547 and gtk_notebook_prev_page is called, the notebook will wrap to the last page.
4548
4549 <tscreen><verb>
4550 void gtk_notebook_next_page( GtkNoteBook *notebook );
4551
4552 void gtk_notebook_prev_page( GtkNoteBook *notebook );
4553 </verb></tscreen>
4554
4555 This next function sets the 'active' page. If you wish the
4556 notebook to be opened to page 5 for example, you would use this function.  
4557 Without using this function, the notebook defaults to the first page.
4558
4559 <tscreen><verb>
4560 void gtk_notebook_set_page( GtkNotebook *notebook,
4561                             gint         page_num );
4562 </verb></tscreen>
4563
4564 The next two functions add or remove the notebook page tabs and the 
4565 notebook border respectively.
4566
4567 <tscreen><verb>
4568 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
4569                                  gint         show_tabs);
4570
4571 void gtk_notebook_set_show_border( GtkNotebook *notebook,
4572                                    gint         show_border );
4573 </verb></tscreen>
4574
4575 show_tabs and show_border can be either TRUE or FALSE.
4576
4577 Now lets look at an example, it is expanded from the testgtk.c code 
4578 that comes with the GTK distribution, and it shows all 13 functions. This 
4579 small program creates a window with a notebook and six buttons. The notebook 
4580 contains 11 pages, added in three different ways, appended, inserted, and 
4581 prepended. The buttons allow you rotate the tab positions, add/remove the tabs
4582 and border, remove a page, change pages in both a forward and backward manner,
4583 and exit the program. 
4584
4585 <tscreen><verb>
4586 /* example-start notebook notebook.c */
4587
4588 #include <gtk/gtk.h>
4589
4590 /* This function rotates the position of the tabs */
4591 void rotate_book (GtkButton *button, GtkNotebook *notebook)
4592 {
4593     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
4594 }
4595
4596 /* Add/Remove the page tabs and the borders */
4597 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
4598 {
4599     gint tval = FALSE;
4600     gint bval = FALSE;
4601     if (notebook->show_tabs == 0)
4602             tval = TRUE; 
4603     if (notebook->show_border == 0)
4604             bval = TRUE;
4605     
4606     gtk_notebook_set_show_tabs (notebook, tval);
4607     gtk_notebook_set_show_border (notebook, bval);
4608 }
4609
4610 /* Remove a page from the notebook */
4611 void remove_book (GtkButton *button, GtkNotebook *notebook)
4612 {
4613     gint page;
4614     
4615     page = gtk_notebook_current_page(notebook);
4616     gtk_notebook_remove_page (notebook, page);
4617     /* Need to refresh the widget -- 
4618      This forces the widget to redraw itself. */
4619     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
4620 }
4621
4622 void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
4623 {
4624     gtk_main_quit ();
4625 }
4626
4627 int main (int argc, char *argv[])
4628 {
4629     GtkWidget *window;
4630     GtkWidget *button;
4631     GtkWidget *table;
4632     GtkWidget *notebook;
4633     GtkWidget *frame;
4634     GtkWidget *label;
4635     GtkWidget *checkbutton;
4636     int i;
4637     char bufferf[32];
4638     char bufferl[32];
4639     
4640     gtk_init (&amp;argc, &amp;argv);
4641     
4642     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4643     
4644     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4645                         GTK_SIGNAL_FUNC (delete), NULL);
4646     
4647     gtk_container_border_width (GTK_CONTAINER (window), 10);
4648     
4649     table = gtk_table_new(2,6,TRUE);
4650     gtk_container_add (GTK_CONTAINER (window), table);
4651     
4652     /* Create a new notebook, place the position of the tabs */
4653     notebook = gtk_notebook_new ();
4654     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
4655     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
4656     gtk_widget_show(notebook);
4657     
4658     /* lets append a bunch of pages to the notebook */
4659     for (i=0; i < 5; i++) {
4660         sprintf(bufferf, "Append Frame %d", i+1);
4661         sprintf(bufferl, "Page %d", i+1);
4662         
4663         frame = gtk_frame_new (bufferf);
4664         gtk_container_border_width (GTK_CONTAINER (frame), 10);
4665         gtk_widget_set_usize (frame, 100, 75);
4666         gtk_widget_show (frame);
4667         
4668         label = gtk_label_new (bufferf);
4669         gtk_container_add (GTK_CONTAINER (frame), label);
4670         gtk_widget_show (label);
4671         
4672         label = gtk_label_new (bufferl);
4673         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
4674     }
4675     
4676     
4677     /* now lets add a page to a specific spot */
4678     checkbutton = gtk_check_button_new_with_label ("Check me please!");
4679     gtk_widget_set_usize(checkbutton, 100, 75);
4680     gtk_widget_show (checkbutton);
4681     
4682     label = gtk_label_new ("Add spot");
4683     gtk_container_add (GTK_CONTAINER (checkbutton), label);
4684     gtk_widget_show (label);
4685     label = gtk_label_new ("Add page");
4686     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
4687     
4688     /* Now finally lets prepend pages to the notebook */
4689     for (i=0; i < 5; i++) {
4690         sprintf(bufferf, "Prepend Frame %d", i+1);
4691         sprintf(bufferl, "PPage %d", i+1);
4692         
4693         frame = gtk_frame_new (bufferf);
4694         gtk_container_border_width (GTK_CONTAINER (frame), 10);
4695         gtk_widget_set_usize (frame, 100, 75);
4696         gtk_widget_show (frame);
4697         
4698         label = gtk_label_new (bufferf);
4699         gtk_container_add (GTK_CONTAINER (frame), label);
4700         gtk_widget_show (label);
4701         
4702         label = gtk_label_new (bufferl);
4703         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
4704     }
4705     
4706     /* Set what page to start at (page 4) */
4707     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
4708     
4709     
4710     /* create a bunch of buttons */
4711     button = gtk_button_new_with_label ("close");
4712     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4713                                GTK_SIGNAL_FUNC (delete), NULL);
4714     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
4715     gtk_widget_show(button);
4716     
4717     button = gtk_button_new_with_label ("next page");
4718     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4719                                (GtkSignalFunc) gtk_notebook_next_page,
4720                                GTK_OBJECT (notebook));
4721     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
4722     gtk_widget_show(button);
4723     
4724     button = gtk_button_new_with_label ("prev page");
4725     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4726                                (GtkSignalFunc) gtk_notebook_prev_page,
4727                                GTK_OBJECT (notebook));
4728     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
4729     gtk_widget_show(button);
4730     
4731     button = gtk_button_new_with_label ("tab position");
4732     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4733                                (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
4734     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
4735     gtk_widget_show(button);
4736     
4737     button = gtk_button_new_with_label ("tabs/border on/off");
4738     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4739                                (GtkSignalFunc) tabsborder_book,
4740                                GTK_OBJECT (notebook));
4741     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
4742     gtk_widget_show(button);
4743     
4744     button = gtk_button_new_with_label ("remove page");
4745     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4746                                (GtkSignalFunc) remove_book,
4747                                GTK_OBJECT(notebook));
4748     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
4749     gtk_widget_show(button);
4750     
4751     gtk_widget_show(table);
4752     gtk_widget_show(window);
4753     
4754     gtk_main ();
4755     
4756     return 0;
4757 }
4758 /* example-end */
4759 </verb></tscreen>
4760
4761 Hopefully this helps you on your way with creating notebooks for your
4762 GTK applications.
4763
4764 <!-- ----------------------------------------------------------------- -->
4765 <sect1>Scrolled Windows
4766 <p>
4767 Scrolled windows are used to create a scrollable area inside a real window.  
4768 You may insert any type of widget into a scrolled window, and it will
4769 be accessible regardless of the size by using the scrollbars.
4770
4771 The following function is used to create a new scrolled window.
4772
4773 <tscreen><verb>
4774 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
4775                                     GtkAdjustment *vadjustment );
4776 </verb></tscreen>
4777
4778 Where the first argument is the adjustment for the horizontal
4779 direction, and the second, the adjustment for the vertical direction.
4780 These are almost always set to NULL.
4781
4782 <tscreen><verb>
4783 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
4784                                      GtkPolicyType      hscrollbar_policy,
4785                                      GtkPolicyType      vscrollbar_policy );
4786 </verb></tscreen>
4787
4788 This sets the policy to be used with respect to the scrollbars.
4789 The first argument is the scrolled window you wish to change. The second
4790 sets the policy for the horizontal scrollbar, and the third the policy for 
4791 the vertical scrollbar.
4792
4793 The policy may be one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
4794 GTK_POLICY_AUTOMATIC will automatically decide whether you need
4795 scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
4796 there.
4797
4798 Here is a simple example that packs 100 toggle buttons into a scrolled window.
4799 I've only commented on the parts that may be new to you.
4800
4801 <tscreen><verb>
4802 /* example-start scrolledwin scrolledwin.c */
4803
4804 #include <gtk/gtk.h>
4805
4806 void destroy(GtkWidget *widget, gpointer data)
4807 {
4808     gtk_main_quit();
4809 }
4810
4811 int main (int argc, char *argv[])
4812 {
4813     static GtkWidget *window;
4814     GtkWidget *scrolled_window;
4815     GtkWidget *table;
4816     GtkWidget *button;
4817     char buffer[32];
4818     int i, j;
4819     
4820     gtk_init (&amp;argc, &amp;argv);
4821     
4822     /* Create a new dialog window for the scrolled window to be
4823      * packed into.  A dialog is just like a normal window except it has a 
4824      * vbox and a horizontal separator packed into it.  It's just a shortcut
4825      * for creating dialogs */
4826     window = gtk_dialog_new ();
4827     gtk_signal_connect (GTK_OBJECT (window), "destroy",
4828                         (GtkSignalFunc) destroy, NULL);
4829     gtk_window_set_title (GTK_WINDOW (window), "dialog");
4830     gtk_container_border_width (GTK_CONTAINER (window), 0);
4831     gtk_widget_set_usize(window, 300, 300);
4832     
4833     /* create a new scrolled window. */
4834     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
4835     
4836     gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
4837     
4838     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
4839      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
4840      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
4841      * there.  The first one is the horizontal scrollbar, the second, 
4842      * the vertical. */
4843     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
4844                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
4845     /* The dialog window is created with a vbox packed into it. */                                                              
4846     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
4847                         TRUE, TRUE, 0);
4848     gtk_widget_show (scrolled_window);
4849     
4850     /* create a table of 10 by 10 squares. */
4851     table = gtk_table_new (10, 10, FALSE);
4852     
4853     /* set the spacing to 10 on x and 10 on y */
4854     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
4855     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
4856     
4857     /* pack the table into the scrolled window */
4858     gtk_container_add (GTK_CONTAINER (scrolled_window), table);
4859     gtk_widget_show (table);
4860     
4861     /* this simply creates a grid of toggle buttons on the table
4862      * to demonstrate the scrolled window. */
4863     for (i = 0; i < 10; i++)
4864        for (j = 0; j < 10; j++) {
4865           sprintf (buffer, "button (%d,%d)\n", i, j);
4866           button = gtk_toggle_button_new_with_label (buffer);
4867           gtk_table_attach_defaults (GTK_TABLE (table), button,
4868                                      i, i+1, j, j+1);
4869           gtk_widget_show (button);
4870        }
4871     
4872     /* Add a "close" button to the bottom of the dialog */
4873     button = gtk_button_new_with_label ("close");
4874     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4875                                (GtkSignalFunc) gtk_widget_destroy,
4876                                GTK_OBJECT (window));
4877     
4878     /* this makes it so the button is the default. */
4879     
4880     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4881     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
4882     
4883     /* This grabs this button to be the default button. Simply hitting
4884      * the "Enter" key will cause this button to activate. */
4885     gtk_widget_grab_default (button);
4886     gtk_widget_show (button);
4887     
4888     gtk_widget_show (window);
4889     
4890     gtk_main();
4891     
4892     return(0);
4893 }
4894 /* example-end */
4895 </verb></tscreen>
4896
4897 Try playing with resizing the window. You'll notice how the scrollbars
4898 react. You may also wish to use the gtk_widget_set_usize() call to set
4899 the default size of the window or other widgets.
4900
4901 <!-- ----------------------------------------------------------------- -->   
4902 <sect1> Paned Window Widgets
4903 <p>
4904 The paned window widgets are useful when you want to divide an area
4905 into two parts, with the relative size of the two parts controlled by
4906 the user. A groove is drawn between the two portions with a handle
4907 that the user can drag to change the ratio. The division can either
4908 be horizontal (HPaned) or vertical (VPaned).
4909    
4910 To create a new paned window, call one of:
4911    
4912 <tscreen><verb>
4913 GtkWidget *gtk_hpaned_new (void);
4914
4915 GtkWidget *gtk_vpaned_new (void);
4916 </verb></tscreen>
4917
4918 After creating the paned window widget, you need to add child widgets
4919 to its two halves. To do this, use the functions:
4920    
4921 <tscreen><verb>
4922 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
4923
4924 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
4925 </verb></tscreen>
4926    
4927 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
4928 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
4929 right or bottom half of the paned window.
4930    
4931 As an example, we will create part of the user interface of an
4932 imaginary email program. A window is divided into two portions
4933 vertically, with the top portion being a list of email messages and
4934 the bottom portion the text of the email message. Most of the program
4935 is pretty straightforward. A couple of points to note: text can't
4936 be added to a Text widget until it is realized. This could be done by
4937 calling <tt/gtk_widget_realize()/, but as a demonstration of an alternate
4938 technique, we connect a handler to the "realize" signal to add the
4939 text. Also, we need to add the <tt/GTK_SHRINK/ option to some of the
4940 items in the table containing the text window and its scrollbars, so
4941 that when the bottom portion is made smaller, the correct portions
4942 shrink instead of being pushed off the bottom of the window.
4943
4944 <tscreen><verb>
4945 /* example-start paned paned.c */
4946
4947 #include <gtk/gtk.h>
4948    
4949 /* Create the list of "messages" */
4950 GtkWidget *
4951 create_list (void)
4952 {
4953
4954     GtkWidget *scrolled_window;
4955     GtkWidget *list;
4956     GtkWidget *list_item;
4957    
4958     int i;
4959     char buffer[16];
4960    
4961     /* Create a new scrolled window, with scrollbars only if needed */
4962     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
4963     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
4964                                     GTK_POLICY_AUTOMATIC, 
4965                                     GTK_POLICY_AUTOMATIC);
4966    
4967     /* Create a new list and put it in the scrolled window */
4968     list = gtk_list_new ();
4969     gtk_container_add (GTK_CONTAINER(scrolled_window), list);
4970     gtk_widget_show (list);
4971    
4972     /* Add some messages to the window */
4973     for (i=0; i<10; i++) {
4974
4975         sprintf(buffer,"Message #%d",i);
4976         list_item = gtk_list_item_new_with_label (buffer);
4977         gtk_container_add (GTK_CONTAINER(list), list_item);
4978         gtk_widget_show (list_item);
4979
4980     }
4981    
4982     return scrolled_window;
4983 }
4984    
4985 /* Add some text to our text widget - this is a callback that is invoked
4986 when our window is realized. We could also force our window to be
4987 realized with gtk_widget_realize, but it would have to be part of
4988 a hierarchy first */
4989
4990 void
4991 realize_text (GtkWidget *text, gpointer data)
4992 {
4993     gtk_text_freeze (GTK_TEXT (text));
4994     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
4995     "From: pathfinder@nasa.gov\n"
4996     "To: mom@nasa.gov\n"
4997     "Subject: Made it!\n"
4998     "\n"
4999     "We just got in this morning. The weather has been\n"
5000     "great - clear but cold, and there are lots of fun sights.\n"
5001     "Sojourner says hi. See you soon.\n"
5002     " -Path\n", -1);
5003    
5004     gtk_text_thaw (GTK_TEXT (text));
5005 }
5006    
5007 /* Create a scrolled text area that displays a "message" */
5008 GtkWidget *
5009 create_text (void)
5010 {
5011     GtkWidget *table;
5012     GtkWidget *text;
5013     GtkWidget *hscrollbar;
5014     GtkWidget *vscrollbar;
5015    
5016     /* Create a table to hold the text widget and scrollbars */
5017     table = gtk_table_new (2, 2, FALSE);
5018    
5019     /* Put a text widget in the upper left hand corner. Note the use of
5020      * GTK_SHRINK in the y direction */
5021     text = gtk_text_new (NULL, NULL);
5022     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
5023                       GTK_FILL | GTK_EXPAND,
5024                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
5025     gtk_widget_show (text);
5026    
5027     /* Put a HScrollbar in the lower left hand corner */
5028     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
5029     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
5030                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
5031     gtk_widget_show (hscrollbar);
5032    
5033     /* And a VScrollbar in the upper right */
5034     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
5035     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
5036                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
5037     gtk_widget_show (vscrollbar);
5038    
5039     /* Add a handler to put a message in the text widget when it is realized */
5040     gtk_signal_connect (GTK_OBJECT (text), "realize",
5041                         GTK_SIGNAL_FUNC (realize_text), NULL);
5042    
5043     return table;
5044 }
5045    
5046 int
5047 main (int argc, char *argv[])
5048 {
5049     GtkWidget *window;
5050     GtkWidget *vpaned;
5051     GtkWidget *list;
5052     GtkWidget *text;
5053
5054     gtk_init (&amp;argc, &amp;argv);
5055    
5056     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5057     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
5058     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5059                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5060     gtk_container_border_width (GTK_CONTAINER (window), 10);
5061    
5062     /* create a vpaned widget and add it to our toplevel window */
5063    
5064     vpaned = gtk_vpaned_new ();
5065     gtk_container_add (GTK_CONTAINER(window), vpaned);
5066     gtk_widget_show (vpaned);
5067    
5068     /* Now create the contents of the two halves of the window */
5069    
5070     list = create_list ();
5071     gtk_paned_add1 (GTK_PANED(vpaned), list);
5072     gtk_widget_show (list);
5073    
5074     text = create_text ();
5075     gtk_paned_add2 (GTK_PANED(vpaned), text);
5076     gtk_widget_show (text);
5077     gtk_widget_show (window);
5078     gtk_main ();
5079     return 0;
5080 }
5081 /* example-end */
5082 </verb></tscreen>
5083
5084 <!-- ----------------------------------------------------------------- -->   
5085 <sect1>Toolbar
5086 <p>
5087 Toolbars are usually used to group some number of widgets in order to simplify
5088 customization of their look and layout. Typically a toolbar consists of buttons
5089 with icons, labels and tooltips, but any other widget can also
5090 be put inside a toolbar.  Finally, items can be arranged horizontally
5091 or vertically and buttons can be displayed with icons, labels or both.
5092
5093 Creating a toolbar is (as one may already suspect) done with the following
5094 function:
5095
5096 <tscreen><verb>
5097 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
5098                             GtkToolbarStyle  style );
5099 </verb></tscreen>
5100
5101 where orientation may be one of:
5102
5103 <tscreen><verb>
5104   GTK_ORIENTATION_HORIZONTAL    
5105   GTK_ORIENTATION_VERTICAL
5106 </verb></tscreen>
5107
5108 and style one of:
5109
5110 <tscreen><verb>
5111   GTK_TOOLBAR_TEXT
5112   GTK_TOOLBAR_ICONS
5113   GTK_TOOLBAR_BOTH
5114 </verb></tscreen>
5115
5116 The style applies to all the buttons created with the `item' functions
5117 (not to buttons inserted into toolbar as separate widgets).
5118
5119 After creating a toolbar one can append,prepend and insert items (that
5120 means simple buttons) into the toolbar. To describe an item we need a
5121 label text, a tooltip text, a private tooltip text, an icon
5122 for the button and a callback function for it. For example, to append
5123 an item you may use the following function:
5124
5125 <tscreen><verb>
5126 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
5127                                     const char    *text,
5128                                     const char    *tooltip_text,
5129                                     const char    *tooltip_private_text,
5130                                     GtkWidget     *icon,
5131                                     GtkSignalFunc  callback,
5132                                     gpointer       user_data );
5133 </verb></tscreen>
5134
5135 If you want to use gtk_toolbar_insert_item, the only additional parameter
5136 which must be specified is the position in which the item should be inserted.
5137
5138 To simplify adding spaces between toolbar items, you may use the following
5139 function:
5140
5141 <tscreen><verb>
5142 void gtk_toolbar_append_space( GtkToolbar *toolbar );
5143
5144 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
5145
5146 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
5147                                gint        position );
5148  
5149 </verb></tscreen>
5150
5151 While the size of the added space can be set globally for a
5152 whole toolbar with the function:
5153
5154 <tscreen><verb>
5155 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
5156                                  gint        space_size) ;
5157 </verb></tscreen>
5158
5159 If it's needed the orientation of a toolbar and its style can be changed
5160 `on the fly' using the following functions:
5161
5162 <tscreen><verb>
5163 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
5164                                   GtkOrientation  orientation );
5165
5166 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
5167                             GtkToolbarStyle  style );
5168
5169 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
5170                                gint        enable );
5171 </verb></tscreen>
5172
5173 To show some other things that can be done with a toolbar, let's take the
5174 following program (we'll interrupt the listing with some additional explanations):
5175
5176 <tscreen><verb>
5177 #include <gtk/gtk.h>
5178
5179 #include "gtk.xpm"
5180
5181 /* This function is connected to the Close button or
5182  * closing the window from the WM */
5183 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
5184 {
5185   gtk_main_quit ();
5186 }
5187 </verb></tscreen>
5188
5189 The above beginning seems for sure familiar to you if it's not your first
5190 GTK program. There is one additional thing though, we include a nice XPM
5191 picture to serve as an icon for all of the buttons.
5192
5193 <tscreen><verb>
5194 GtkWidget* close_button; // this button will emit signal to close application
5195 GtkWidget* tooltips_button; // to enable/disable tooltips
5196 GtkWidget* text_button,
5197          * icon_button,
5198          * both_button; // radio buttons for toolbar style
5199 GtkWidget* entry; // a text entry to show packing any widget into toolbar
5200 </verb></tscreen>
5201
5202 In fact not all of the above widgets are needed here, but to make things
5203 clearer I put them all together.
5204
5205 <tscreen><verb>
5206 /* that's easy... when one of the buttons is toggled, we just
5207  * check which one is active and set the style of the toolbar
5208  * accordingly
5209  * ATTENTION: our toolbar is passed as data to callback ! */
5210 void radio_event (GtkWidget *widget, gpointer data)
5211 {
5212   if (GTK_TOGGLE_BUTTON (text_button)->active) 
5213     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
5214   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
5215     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
5216   else if (GTK_TOGGLE_BUTTON (both_button)->active)
5217     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
5218 }
5219
5220 /* even easier, just check given toggle button and enable/disable 
5221  * tooltips */
5222 void toggle_event (GtkWidget *widget, gpointer data)
5223 {
5224   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
5225                             GTK_TOGGLE_BUTTON (widget)->active );
5226 }
5227 </verb></tscreen>
5228
5229 The above are just two callback functions that will be called when
5230 one of the buttons on a toolbar is pressed. You should already be
5231 familiar with things like this if you've already used toggle buttons (and
5232 radio buttons).
5233
5234 <tscreen><verb>
5235 int main (int argc, char *argv[])
5236 {
5237   /* Here is our main window (a dialog) and a handle for the handlebox */
5238   GtkWidget* dialog;
5239   GtkWidget* handlebox;
5240
5241   /* Ok, we need a toolbar, an icon with a mask (one for all of 
5242      the buttons) and an icon widget to put this icon in (but 
5243      we'll create a separate widget for each button) */
5244   GtkWidget * toolbar;
5245   GdkPixmap * icon;
5246   GdkBitmap * mask;
5247   GtkWidget * iconw;
5248
5249   /* this is called in all GTK application. */
5250   gtk_init (&amp;argc, &amp;argv);
5251   
5252   /* create a new window with a given title, and nice size */
5253   dialog = gtk_dialog_new ();
5254   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
5255   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
5256   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
5257
5258   /* typically we quit if someone tries to close us */
5259   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
5260                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
5261
5262   /* we need to realize the window because we use pixmaps for 
5263    * items on the toolbar in the context of it */
5264   gtk_widget_realize ( dialog );
5265
5266   /* to make it nice we'll put the toolbar into the handle box, 
5267    * so that it can be detached from the main window */
5268   handlebox = gtk_handle_box_new ();
5269   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
5270                        handlebox, FALSE, FALSE, 5 );
5271 </verb></tscreen>
5272
5273 The above should be similar to any other GTK application. Just initialization
5274 of GTK, creating the window etc.. There is only one thing that probably
5275 needs some explanation: a handle box. A handle box is just another box
5276 that can be used to pack widgets in to. The difference between it and typical
5277 boxes is that it can be detached from a parent window (or, in fact, the handle
5278 box remains in the parent, but it is reduced to a very small rectangle, while
5279 all of its contents are reparented to a new freely floating window). It is
5280 usually nice to have a detachable toolbar, so these two widgets occur together
5281 quite often.
5282
5283 <tscreen><verb>
5284   /* toolbar will be horizontal, with both icons and text, and
5285    * with 5pxl spaces between items and finally, 
5286    * we'll also put it into our handlebox */
5287   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
5288                               GTK_TOOLBAR_BOTH );
5289   gtk_container_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
5290   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
5291   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
5292
5293   /* now we create icon with mask: we'll reuse it to create
5294    * icon widgets for toolbar items */
5295   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
5296       &amp;dialog->style->white, gtk_xpm );
5297 </verb></tscreen>
5298
5299 Well, what we do above is just a straight-forward initialization of the toolbar
5300 widget and creation of a GDK pixmap with its mask. If you want to know
5301 something more about using pixmaps, refer to GDK documentation
5302 or to the <ref id="sec_Pixmaps" name="Pixmaps"> section earlier in this tutorial.
5303
5304 <tscreen><verb>
5305   /* our first item is <close> button */
5306   iconw = gtk_pixmap_new ( icon, mask ); // icon widget
5307   close_button = 
5308     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), // our toolbar
5309                               "Close",               // button label
5310                               "Closes this app",     // tooltip for this button
5311                               "Private",             // tooltip private string
5312                               iconw,                 // icon widget
5313                               GTK_SIGNAL_FUNC (delete_event), // a signal
5314                               NULL );
5315   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); // space after item
5316 </verb></tscreen>
5317
5318 In the above code you see the simplest case: adding a button to toolbar.
5319 Just before appending a new item, we have to construct a pixmap widget
5320 to serve as an icon for this item; this step will have to be repeated for
5321 each new item. Just after the item we also add a space, so the following
5322 items will not touch each other. As you see gtk_toolbar_append_item returns
5323 a pointer to our newly created button widget, so that we can work with it in
5324 the normal way.
5325
5326 <tscreen><verb>
5327   /* now, let's make our radio buttons group... */
5328   iconw = gtk_pixmap_new ( icon, mask );
5329   icon_button = 
5330     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5331                                GTK_TOOLBAR_CHILD_RADIOBUTTON, // a type of element
5332                                NULL,                          // pointer to widget
5333                                "Icon",                        // label
5334                                "Only icons in toolbar",       // tooltip
5335                                "Private",                     // tooltip private string
5336                                iconw,                         // icon
5337                                GTK_SIGNAL_FUNC (radio_event), // signal
5338                                toolbar);                      // data for signal
5339   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5340 </verb></tscreen>
5341
5342 Here we begin creating a radio buttons group. To do this we use gtk_toolbar_append_element.
5343 In fact, using this function one can also add simple items or even spaces
5344 (type = GTK_TOOLBAR_CHILD_SPACE or GTK_TOOLBAR_CHILD_BUTTON). In the above
5345 case we start creating a radio group. In creating other radio buttons for
5346 this group a pointer to the previous button in the group is required,
5347 so that a list of buttons can be easily constructed (see the section on
5348 <ref id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this tutorial).
5349
5350 <tscreen><verb>
5351   /* following radio buttons refer to previous ones */
5352   iconw = gtk_pixmap_new ( icon, mask );
5353   text_button = 
5354     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5355                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
5356                                icon_button,
5357                                "Text",
5358                                "Only texts in toolbar",
5359                                "Private",
5360                                iconw,
5361                                GTK_SIGNAL_FUNC (radio_event),
5362                                toolbar);
5363   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5364                                           
5365   iconw = gtk_pixmap_new ( icon, mask );
5366   both_button = 
5367     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5368                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
5369                                text_button,
5370                                "Both",
5371                                "Icons and text in toolbar",
5372                                "Private",
5373                                iconw,
5374                                GTK_SIGNAL_FUNC (radio_event),
5375                                toolbar);
5376   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5377   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(both_button),TRUE);
5378 </verb></tscreen>
5379
5380 In the end we have set the state of one of the buttons manually (otherwise
5381 they all stay in active state, preventing us from switching between them).
5382
5383 <tscreen><verb>
5384   /* here we have just a simple toggle button */
5385   iconw = gtk_pixmap_new ( icon, mask );
5386   tooltips_button = 
5387     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5388                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
5389                                NULL,
5390                                "Tooltips",
5391                                "Toolbar with or without tips",
5392                                "Private",
5393                                iconw,
5394                                GTK_SIGNAL_FUNC (toggle_event),
5395                                toolbar);
5396   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5397   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
5398 </verb></tscreen>
5399
5400 A toggle button can be created in the obvious way (if one knows how to create
5401 radio buttons already).
5402
5403 <tscreen><verb>
5404   /* to pack a widget into toolbar, we only have to 
5405    * create it and append it with an appropriate tooltip */
5406   entry = gtk_entry_new ();
5407   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
5408                              entry, 
5409                              "This is just an entry", 
5410                              "Private" );
5411
5412   /* well, it isn't created within thetoolbar, so we must still show it */
5413   gtk_widget_show ( entry );
5414 </verb></tscreen>
5415
5416 As you see, adding any kind of widget to a toolbar is simple. The
5417 one thing you have to remember is that this widget must be shown manually
5418 (contrary to other items which will be shown together with the toolbar).
5419
5420 <tscreen><verb>
5421   /* that's it ! let's show everything. */
5422   gtk_widget_show ( toolbar );
5423   gtk_widget_show (handlebox);
5424   gtk_widget_show ( dialog );
5425
5426   /* rest in gtk_main and wait for the fun to begin! */
5427   gtk_main ();
5428   
5429   return 0;
5430 }
5431 </verb></tscreen>
5432
5433 So, here we are at the end of toolbar tutorial. Of course, to appreciate
5434 it in full you need also this nice XPM icon, so here it is:
5435
5436 <tscreen><verb>
5437 /* XPM */
5438 static char * gtk_xpm[] = {
5439 "32 39 5 1",
5440 ".      c none",
5441 "+      c black",
5442 "@      c #3070E0",
5443 "#      c #F05050",
5444 "$      c #35E035",
5445 "................+...............",
5446 "..............+++++.............",
5447 "............+++++@@++...........",
5448 "..........+++++@@@@@@++.........",
5449 "........++++@@@@@@@@@@++........",
5450 "......++++@@++++++++@@@++.......",
5451 ".....+++@@@+++++++++++@@@++.....",
5452 "...+++@@@@+++@@@@@@++++@@@@+....",
5453 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
5454 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
5455 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
5456 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
5457 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
5458 ".+####+++@@@+++++++@@@@@+@$$$$@.",
5459 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
5460 ".+######++++@@@@@@@++@$$$$$$$$+.",
5461 ".+#######+##+@@@@+++$$$$$$@@$$+.",
5462 ".+###+++##+##+@@++@$$$$$$++$$$+.",
5463 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
5464 ".+###++++++#+++@$$@+@$$@++$$$@+.",
5465 ".+####+++++++#++$$@+@$$++$$$$+..",
5466 ".++####++++++#++$$@+@$++@$$$$+..",
5467 ".+#####+++++##++$$++@+++$$$$$+..",
5468 ".++####+++##+#++$$+++++@$$$$$+..",
5469 ".++####+++####++$$++++++@$$$@+..",
5470 ".+#####++#####++$$+++@++++@$@+..",
5471 ".+#####++#####++$$++@$$@+++$@@..",
5472 ".++####++#####++$$++$$$$$+@$@++.",
5473 ".++####++#####++$$++$$$$$$$$+++.",
5474 ".+++####+#####++$$++$$$$$$$@+++.",
5475 "..+++#########+@$$+@$$$$$$+++...",
5476 "...+++########+@$$$$$$$$@+++....",
5477 ".....+++######+@$$$$$$$+++......",
5478 "......+++#####+@$$$$$@++........",
5479 ".......+++####+@$$$$+++.........",
5480 ".........++###+$$$@++...........",
5481 "..........++##+$@+++............",
5482 "...........+++++++..............",
5483 ".............++++..............."};
5484 </verb></tscreen>
5485
5486 <!-- ----------------------------------------------------------------- -->   
5487 <sect1> Aspect Frames
5488 <p>
5489 The aspect frame widget is like a frame widget, except that it also
5490 enforces the aspect ratio (that is, the ratio of the width to the
5491 height) of the child widget to have a certain value, adding extra
5492 space if necessary. This is useful, for instance, if you want to
5493 preview a larger image. The size of the preview should vary when
5494 the user resizes the window, but the aspect ratio needs to always match
5495 the original image.
5496    
5497 To create a new aspect frame use:
5498    
5499 <tscreen><verb>
5500 GtkWidget *gtk_aspect_frame_new( const gchar *label,
5501                                  gfloat       xalign,
5502                                  gfloat       yalign,
5503                                  gfloat       ratio,
5504                                  gint         obey_child);
5505 </verb></tscreen>
5506    
5507 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
5508 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
5509 widget will match the aspect ratio of the ideal size it requests.
5510 Otherwise, it is given by <tt/ratio/.
5511    
5512 To change the options of an existing aspect frame, you can use:
5513    
5514 <tscreen><verb>
5515 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
5516                            gfloat          xalign,
5517                            gfloat          yalign,
5518                            gfloat          ratio,
5519                            gint            obey_child);
5520 </verb></tscreen>
5521    
5522 As an example, the following program uses an AspectFrame to
5523 present a drawing area whose aspect ratio will always be 2:1, no
5524 matter how the user resizes the top-level window.
5525    
5526 <tscreen><verb>
5527 /* example-start aspectframe aspectframe.c */
5528
5529 #include <gtk/gtk.h>
5530    
5531 int
5532 main (int argc, char *argv[])
5533 {
5534     GtkWidget *window;
5535     GtkWidget *aspect_frame;
5536     GtkWidget *drawing_area;
5537     gtk_init (&amp;argc, &amp;argv);
5538    
5539     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5540     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
5541     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5542                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5543     gtk_container_border_width (GTK_CONTAINER (window), 10);
5544    
5545     /* Create an aspect_frame and add it to our toplevel window */
5546    
5547     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
5548                                          0.5, /* center x */
5549                                          0.5, /* center y */
5550                                          2, /* xsize/ysize = 2 */
5551                                          FALSE /* ignore child's aspect */);
5552    
5553     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
5554     gtk_widget_show (aspect_frame);
5555    
5556     /* Now add a child widget to the aspect frame */
5557    
5558     drawing_area = gtk_drawing_area_new ();
5559    
5560     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
5561      * window since we are forcing a 2x1 aspect ratio */
5562     gtk_widget_set_usize (drawing_area, 200, 200);
5563     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
5564     gtk_widget_show (drawing_area);
5565    
5566     gtk_widget_show (window);
5567     gtk_main ();
5568     return 0;
5569 }
5570 /* example-end */
5571 </verb></tscreen>
5572
5573 <!-- ***************************************************************** -->
5574 <sect>CList Widget
5575 <!-- ***************************************************************** -->
5576
5577 <!-- ----------------------------------------------------------------- -->
5578 <p>
5579 The GtkCList widget has replaced the GtkList widget (which is still
5580 available).
5581
5582 The GtkCList widget is a multi-column list widget that is capable of
5583 handling literally thousands of rows of information. Each column can
5584 optionally have a title, which itself is optionally active, allowing
5585 us to bind a function to its selection.
5586
5587 <!-- ----------------------------------------------------------------- -->
5588 <sect1>Creating a GtkCList widget
5589 <p>
5590 Creating a GtkCList is quite straightforward, once you have learned about
5591 widgets in general. It provides the almost standard two ways, that is the
5592 hard way, and the easy way. But before we create it, there is one thing we
5593 should figure out beforehand: how many columns should it have?
5594
5595 Not all columns have to be visible and can be used to store data that is
5596 related to a certain cell in the list.
5597
5598 <tscreen><verb>
5599 GtkWidget *gtk_clist_new ( gint columns );
5600
5601 GtkWidget *gtk_clist_new_with_titles( gint   columns,
5602                                       gchar *titles[] );
5603 </verb></tscreen>
5604
5605 The first form is very straight forward, the second might require some
5606 explanation. Each column can have a title associated with it, and this
5607 title can be a label or a button that reacts when we click on it. If we
5608 use the second form, we must provide pointers to the title texts, and the
5609 number of pointers should equal the number of columns specified. Of course
5610 we can always use the first form, and manually add titles later.
5611
5612 <!-- ----------------------------------------------------------------- -->
5613 <sect1>Modes of operation
5614 <p>
5615 There are several attributes that can be used to alter the behaviour of
5616 a GtkCList. First there is
5617
5618 <tscreen><verb>
5619 void gtk_clist_set_selection_mode( GtkCList         *clist,
5620                                    GtkSelectionMode  mode );
5621 </verb></tscreen>
5622
5623 which, as the name implies, sets the selection mode of the GtkCList. The first
5624 argument is the GtkCList widget, and the second specifies the cell selection
5625 mode (they are defined in gtkenums.h). At the time of this writing, the following
5626 modes are available to us:
5627
5628 <itemize>
5629 <item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
5630 pointer for a single selected item.
5631
5632 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list contains no
5633 widgets or insensitive ones only, otherwise it contains a GList pointer for
5634 one GList structure, and therefore exactly one list item.
5635
5636 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list items are
5637 selected or a GList pointer for the first selected item. That in turn points
5638 to a GList structure for the second selected item and so on. This is currently
5639 the <bf>default</bf> for the GtkCList widget.
5640
5641 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
5642 </itemize>
5643
5644 Others might be added in later revisions of GTK.
5645
5646 Then there is
5647
5648 <tscreen><verb>
5649 void gtk_clist_set_policy (GtkCList * clist,
5650                            GtkPolicyType vscrollbar_policy,
5651                            GtkPolicyType hscrollbar_policy);
5652 </verb></tscreen>
5653
5654 which defines what happens to the scrollbars. The following values are possible
5655 for both the vertical and the horizontal scrollbar:
5656
5657 <itemize>
5658 <item> GTK_POLICY_ALWAYS - The scrollbar will always be there.
5659
5660 <item> GTK_POLICY_AUTOMATIC - The scrollbar will be there only when the number
5661 of items in the GtkCList exceeds the number that can be shown in the widget.
5662 </itemize>
5663
5664 We can also define what the border of the GtkCList widget should look like. It is
5665 done through
5666
5667 <tscreen><verb>
5668 void gtk_clist_set_border( GtkCList      *clist,
5669                            GtkShadowType  border );
5670 </verb></tscreen>
5671
5672 And the possible values for the second argument are
5673
5674 <itemize>
5675 <item> GTK_SHADOW_NONE
5676
5677 <item> GTK_SHADOW_IN
5678
5679 <item> GTK_SHADOW_OUT
5680
5681 <item> GTK_SHADOW_ETCHED_IN
5682
5683 <item> GTK_SHADOW_ETCHED_OUT
5684 </itemize>
5685
5686 <!-- ----------------------------------------------------------------- -->
5687 <sect1>Working with titles
5688 <p>
5689 When you create a GtkCList widget, you will also get a set of title buttons
5690 automatically. They live in the top of the CList window, and can act either
5691 as normal buttons that respond to being pressed, or they can be passive,
5692 in which case they are nothing more than a title. There are four different
5693 calls that aid us in setting the status of the title buttons.
5694
5695 <tscreen><verb>
5696 void gtk_clist_column_title_active( GtkCList *clist,
5697                                      gint     column );
5698
5699 void gtk_clist_column_title_passive( GtkCList *clist,
5700                                      gint      column );
5701
5702 void gtk_clist_column_titles_active( GtkCList *clist );
5703
5704 void gtk_clist_column_titles_passive( GtkCList *clist );
5705 </verb></tscreen>
5706
5707 An active title is one which acts as a normal button, a passive one is just
5708 a label. The first two calls above will activate/deactivate the title button
5709 above the specific column, while the last two calls activate/deactivate all
5710 title buttons in the supplied clist widget.
5711
5712 But of course there are those cases when we don't want them at all, and so
5713 they can be hidden and shown at will using the following two calls.
5714
5715 <tscreen><verb>
5716 void gtk_clist_column_titles_show( GtkCList *clist );
5717
5718 void gtk_clist_column_titles_hide( GtkCList *clist );
5719 </verb></tscreen>
5720
5721 For titles to be really useful we need a mechanism to set and change them,
5722 and this is done using
5723
5724 <tscreen><verb>
5725 void gtk_clist_set_column_title( GtkCList *clist,
5726                                  gint      column,
5727                                  gchar    *title );
5728 </verb></tscreen>
5729
5730 Note that only the title of one column can be set at a time, so if all the
5731 titles are known from the beginning, then I really suggest using
5732 gtk_clist_new_with_titles (as described above) to set them. Saves you
5733 coding time, and makes your program smaller. There are some cases where
5734 getting the job done the manual way is better, and that's when not all
5735 titles will be text. GtkCList provides us with title buttons that can in fact
5736 incorporate whole widgets, for example a pixmap. It's all done through
5737
5738 <tscreen><verb>
5739 void gtk_clist_set_column_widget( GtkCList  *clist,
5740                                   gint       column,
5741                                   GtkWidget *widget );
5742 </verb></tscreen>
5743
5744 which should require no special explanation.
5745
5746 <!-- ----------------------------------------------------------------- -->
5747 <sect1>Manipulating the list itself
5748 <p>
5749 It is possible to change the justification for a column, and it is done through
5750
5751 <tscreen><verb>
5752 void gtk_clist_set_column_justification( GtkCList         *clist,
5753                                          gint              column,
5754                                          GtkJustification  justification );
5755 </verb></tscreen>
5756
5757 The GtkJustification type can take the following values:
5758
5759 <itemize>
5760 <item>GTK_JUSTIFY_LEFT - The text in the column will begin from the left edge.
5761
5762 <item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the right edge.
5763
5764 <item>GTK_JUSTIFY_CENTER - The text is placed in the center of the column.
5765
5766 <item>GTK_JUSTIFY_FILL - The text will use up all available space in the
5767 column. It is normally done by inserting extra blank spaces between words
5768 (or between individual letters if it's a single word). Much in the same way as
5769 any ordinary WYSIWYG text editor.
5770 </itemize>
5771
5772 The next function is a very important one, and should be standard in the setup
5773 of all GtkCList widgets. When the list is created, the width of the various
5774 columns are chosen to match their titles, and since this is seldom the right
5775 width we have to set it using
5776
5777 <tscreen><verb>
5778 void gtk_clist_set_column_width( GtkCList *clist,
5779                                  gint      column,
5780                                  gint      width );
5781 </verb></tscreen>
5782
5783 Note that the width is given in pixels and not letters. The same goes for the
5784 height of the cells in the columns, but as the default value is the height of
5785 the current font this isn't as critical to the application. Still, it is done through
5786
5787 <tscreen><verb>
5788 void gtk_clist_set_row_height( GtkCList *clist,
5789                                gint      height );
5790 </verb></tscreen>
5791
5792 Again, note that the height is given in pixels.
5793
5794 We can also move the list around without user interaction, however, it does
5795 require that we know what we are looking for. Or in other words, we need the row
5796 and column of the item we want to scroll to.
5797
5798 <tscreen><verb>
5799 void gtk_clist_moveto( GtkCList *clist,
5800                        gint      row,
5801                        gint      column,
5802                        gfloat    row_align,
5803                        gfloat    col_align );
5804 </verb></tscreen>
5805
5806 The gfloat row_align is pretty important to understand. It's a value between 0.0 and
5807 1.0, where 0.0 means that we should scroll the list so the row appears at the top,
5808 while if the value of row_align is 1.0, the row will appear at the bottom instead. All
5809 other values between 0.0 and 1.0 are also valid and will place the row between the top
5810 and the bottom. The last argument, gfloat col_align works in the same way, though 0.0
5811 marks left and 1.0 marks right instead.
5812
5813 Depending on the application's needs, we don't have to scroll to an item that is
5814 already visible to us. So how do we know if it is visible? As usual, there is a function
5815 to find that out as well.
5816
5817 <tscreen><verb>
5818 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
5819                                         gint      row );
5820 </verb></tscreen>
5821
5822 The return value is is one of the following:
5823
5824 <itemize>
5825 <item>GTK_VISIBILITY_NONE
5826
5827 <item>GTK_VISIBILITY_PARTIAL
5828
5829 <item>GTK_VISIBILITY_FULL
5830 </itemize>
5831
5832 Note that it will only tell us if a row is visible. Currently there is no way to
5833 determine this for a column. We can get partial information though, because if
5834 the return is GTK_VISIBILITY_PARTIAL, then some of it is hidden, but we don't know if
5835 it is the row that is being cut by the lower edge of the listbox, or if the row has
5836 columns that are outside.
5837
5838 We can also change both the foreground and background colors of a particular
5839 row. This is useful for marking the row selected by the user, and the two functions
5840 that is used to do it are
5841
5842 <tscreen><verb>
5843 void gtk_clist_set_foreground( GtkCList *clist,
5844                                gint      row,
5845                                GdkColor *color );
5846
5847 void gtk_clist_set_background( GtkCList *clist,
5848                                gint      row,
5849                                GdkColor *color );
5850 </verb></tscreen>
5851
5852 Please note that the colors must have been previously allocated.
5853
5854 <!-- ----------------------------------------------------------------- -->
5855 <sect1>Adding rows to the list
5856 <p>
5857 We can add rows in two ways. They can be appended at the end to the list using
5858
5859 <tscreen><verb>
5860 gint gtk_clist_append( GtkCList *clist,
5861                        gchar    *text[] );
5862 </verb></tscreen>
5863
5864 or we can insert a row at a given place using
5865
5866 <tscreen><verb>
5867 void gtk_clist_insert( GtkCList *clist,
5868                        gint      row,
5869                        gchar    *text[] );
5870 </verb></tscreen>
5871
5872 In both calls we have to provide a collection of pointers that are the texts
5873 we want to put in the columns. The number of pointers should equal the number
5874 of columns in the list. If the text[] argument is NULL, then there will be no
5875 text in the columns of the row. This is useful, for example,  if we want to
5876 add pixmaps instead (something that has to be done manually).
5877
5878 Also, please note that the numbering of both rows and columns start at 0.
5879
5880 To remove an individual row we use
5881
5882 <tscreen><verb>
5883 void gtk_clist_remove( GtkCList *clist,
5884                        gint      row );
5885 </verb></tscreen>
5886
5887 There is also a call that removes all rows in the list. This is a lot faster
5888 than calling gtk_clist_remove once for each row, which is the only alternative.
5889
5890 <tscreen><verb>
5891 void gtk_clist_clear( GtkCList *clist );
5892 </verb></tscreen>
5893
5894 There are also two convenience functions that should be used when a lot of
5895 changes have to be made to the list. This is to prevent the list flickering while
5896 being repeatedly updated, which may be highly annoying to the user. So instead it
5897 is a good idea to freeze the list, do the updates to it, and finally thaw it which
5898 causes the list to be updated on the screen.
5899
5900 <tscreen><verb>
5901 void gtk_clist_freeze( GtkCList * clist );
5902
5903 void gtk_clist_thaw( GtkCList * clist );
5904 </verb></tscreen>
5905
5906 <!-- ----------------------------------------------------------------- -->
5907 <sect1>Setting text and pixmaps in the cells
5908 <p>
5909 A cell can contain a pixmap, text or both. To set them the following
5910 functions are used.
5911
5912 <tscreen><verb>
5913 void gtk_clist_set_text( GtkCList *clist,
5914                          gint      row,
5915                          gint      column,
5916                          gchar    *text );
5917
5918 void gtk_clist_set_pixmap( GtkCList  *clist,
5919                            gint       row,
5920                            gint       column,
5921                            GdkPixmap *pixmap,
5922                            GdkBitmap *mask );
5923
5924 void gtk_clist_set_pixtext( GtkCList  *clist,
5925                             gint       row,
5926                             gint       column,
5927                             gchar     *text,
5928                             guint8     spacing,
5929                             GdkPixmap *pixmap,
5930                             GdkBitmap *mask );
5931 </verb></tscreen>
5932
5933 It's quite straightforward. All the calls have the GtkCList as the first
5934 argument, followed by the row and column of the cell, followed by the data to be
5935 set. The gint8 spacing argument in gtk_clist_set_pixtext is the number of pixels
5936 between the pixmap and the beginning of the text.
5937
5938 To read back the data, we instead use
5939
5940 <tscreen><verb>
5941 gint gtk_clist_get_text( GtkCList  *clist,
5942                          gint       row,
5943                          gint       column,
5944                          gchar    **text );
5945
5946 gint gtk_clist_get_pixmap( GtkCList   *clist,
5947                            gint        row,
5948                            gint        column,
5949                            GdkPixmap **pixmap,
5950                            GdkBitmap **mask );
5951
5952 gint gtk_clist_get_pixtext( GtkCList   *clist,
5953                             gint        row,
5954                             gint        column,
5955                             gchar     **text,
5956                             guint8     *spacing,
5957                             GdkPixmap **pixmap,
5958                             GdkBitmap **mask );
5959 </verb></tscreen>
5960
5961 It isn't necessary to read it all back in case you aren't interested. Any
5962 of the pointers that are meant for return values (all except the clist) can
5963 be NULL. So if we want to read back only the text from a cell that is of
5964 type pixtext, then we would do the following, assuming that clist, row and
5965 column already exist:
5966
5967 <tscreen><verb>
5968 gchar *mytext;
5969
5970 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
5971 </verb></tscreen>
5972
5973 There is one more call that is related to what's inside a cell in the
5974 clist, and that's
5975
5976 <tscreen><verb>
5977 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
5978                                      gint      row,
5979                                      gint      column );
5980 </verb></tscreen>
5981
5982 which returns the type of data in a cell. The return value is one of
5983
5984 <itemize>
5985 <item>GTK_CELL_EMPTY
5986
5987 <item>GTK_CELL_TEXT
5988
5989 <item>GTK_CELL_PIXMAP
5990
5991 <item>GTK_CELL_PIXTEXT
5992
5993 <item>GTK_CELL_WIDGET
5994 </itemize>
5995
5996 There is also a function that will let us set the indentation, both
5997 vertical and horizontal, of a cell. The indentation value is of type gint,
5998 given in pixels, and can be both positive and negative.
5999
6000 <tscreen><verb>
6001 void gtk_clist_set_shift( GtkCList *clist,
6002                           gint      row,
6003                           gint      column,
6004                           gint      vertical,
6005                           gint      horizontal );
6006 </verb></tscreen>
6007
6008 <!-- ----------------------------------------------------------------- -->
6009 <sect1>Storing data pointers
6010 <p>
6011 With a GtkCList it is possible to set a data pointer for a row. This
6012 pointer will not be visible for the user, but is merely a convenience for
6013 the programmer to associate a row with a pointer to some additional data.
6014
6015 The functions should be fairly self-explanatory by now
6016
6017 <tscreen><verb>
6018 void gtk_clist_set_row_data( GtkCList *clist,
6019                              gint      row,
6020                              gpointer  data );
6021
6022 void gtk_clist_set_row_data_full( GtkCList         *clist,
6023                                   gint              row,
6024                                   gpointer          data,
6025                                   GtkDestroyNotify  destroy );
6026
6027 gpointer gtk_clist_get_row_data( GtkCList *clist,
6028                                  gint      row );
6029
6030 gint gtk_clist_find_row_from_data( GtkCList *clist,
6031                                    gpointer  data );
6032 </verb></tscreen>
6033
6034 <!-- ----------------------------------------------------------------- -->
6035 <sect1>Working with selections
6036 <p>
6037 There are also functions available that let us force the (un)selection
6038 of a row. These are
6039
6040 <tscreen><verb>
6041 void gtk_clist_select_row( GtkCList *clist,
6042                            gint      row,
6043                            gint      column );
6044
6045 void gtk_clist_unselect_row( GtkCList *clist,
6046                              gint      row,
6047                              gint      column );
6048 </verb></tscreen>
6049
6050 And also a function that will take x and y coordinates (for example, read from
6051 the mousepointer), and map that onto the list, returning the
6052 corresponding row and column.
6053
6054 <tscreen><verb>
6055 gint gtk_clist_get_selection_info( GtkCList *clist,
6056                                    gint      x,
6057                                    gint      y,
6058                                    gint     *row,
6059                                    gint     *column );
6060 </verb></tscreen>
6061
6062 When we detect something of interest, it might be movement of the pointer, a
6063 click somewhere in the list, we can read the pointer coordinates and find out
6064 where in the list the pointer is. Cumbersome? Luckily, there is a more simple way...
6065
6066 <!-- ----------------------------------------------------------------- -->
6067 <sect1>The signals that bring it together
6068 <p>
6069 As with all other widgets, there are a few signals that can be used. The
6070 GtkCList widget is derived from the GtkContainer widget, and so has all the
6071 same signals, but also the adds following:
6072
6073 <itemize>
6074 <item>select_row - This signal will send the following information, in
6075 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
6076
6077 <item>unselect_row - When the user unselects a row, this signal is activated. It
6078 sends the same information as select_row
6079
6080 <item>click_column - Send GtkCList *clist, gint column
6081 </itemize>
6082
6083 So if we want to connect a callback to select_row, the callback function would
6084 be declared like this
6085
6086 <tscreen><verb>
6087 void select_row_callback(GtkWidget *widget,
6088                          gint row,
6089                          gint column,
6090                          GdkEventButton *event,
6091                          gpointer data);
6092 </verb></tscreen>
6093
6094 The callback is connected as usual with
6095
6096 <tscreen><verb>
6097 gtk_signal_connect(GTK_OBJECT( clist),
6098                    "select_row"
6099                    GTK_SIGNAL_FUNC(select_row_callback),
6100                    NULL);
6101 </verb></tscreen>
6102
6103 <!-- ----------------------------------------------------------------- -->
6104 <sect1>A GtkCList example
6105 <p>
6106
6107 <tscreen><verb>
6108 /* example-start clist clist.c */
6109
6110 #include        <gtk/gtk.h>
6111 #include        <glib.h>
6112
6113 /* These are just the prototypes of the various callbacks */
6114 void button_add_clicked( GtkWidget *button, gpointer data);
6115 void button_clear_clicked( GtkWidget *button, gpointer data);
6116 void button_hide_show_clicked( GtkWidget *button, gpointer data);
6117 void selection_made( GtkWidget *clist, gint row, gint column,
6118                      GdkEventButton *event, gpointer data);
6119
6120 gint main (int argc, gchar *argv[])
6121 {                                  
6122     GtkWidget       *window;
6123     GtkWidget       *vbox, *hbox;
6124     GtkWidget       *clist;
6125     GtkWidget       *button_add, *button_clear, *button_hide_show;    
6126     gchar           *titles[2] = {"Ingredients","Amount"};
6127
6128     gtk_init(&amp;argc, &amp;argv);
6129     
6130     
6131     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
6132     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
6133
6134     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
6135     gtk_signal_connect(GTK_OBJECT(window),
6136                        "destroy",
6137                        GTK_SIGNAL_FUNC(gtk_main_quit),
6138                        NULL);
6139     
6140     vbox=gtk_vbox_new(FALSE, 5);
6141     gtk_container_border_width(GTK_CONTAINER(vbox), 5);
6142     gtk_container_add(GTK_CONTAINER(window), vbox);
6143     gtk_widget_show(vbox);
6144     
6145     /* Create the GtkCList. For this example we use 2 columns */
6146     clist = gtk_clist_new_with_titles( 2, titles);
6147
6148     /* When a selection is made, we want to know about it. The callback
6149      * used is selection_made, and its code can be found further down */
6150     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
6151                        GTK_SIGNAL_FUNC(selection_made),
6152                        NULL);
6153
6154     /* It isn't necessary to shadow the border, but it looks nice :) */
6155     gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
6156
6157     /* What however is important, is that we set the column widths as
6158      * they will never be right otherwise. Note that the columns are
6159      * numbered from 0 and up (to 1 in this case).
6160      */
6161     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
6162
6163     /* Scollbars _only when needed_ */
6164     gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
6165                                            GTK_POLICY_AUTOMATIC);
6166
6167     /* Add the GtkCList widget to the vertical box and show it. */
6168     gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
6169     gtk_widget_show(clist);
6170
6171     /* Create the buttons and add them to the window. See the button
6172      * tutorial for more examples and comments on this.
6173      */
6174     hbox = gtk_hbox_new(FALSE, 0);
6175     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
6176     gtk_widget_show(hbox);
6177
6178     button_add = gtk_button_new_with_label("Add List");
6179     button_clear = gtk_button_new_with_label("Clear List");
6180     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
6181
6182     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
6183     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
6184     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
6185
6186     /* Connect our callbacks to the three buttons */
6187     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
6188                               GTK_SIGNAL_FUNC(button_add_clicked),
6189                               (gpointer) clist);
6190     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
6191                               GTK_SIGNAL_FUNC(button_clear_clicked),
6192                               (gpointer) clist);
6193     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
6194                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
6195                               (gpointer) clist);
6196
6197     gtk_widget_show(button_add);
6198     gtk_widget_show(button_clear);
6199     gtk_widget_show(button_hide_show);
6200
6201     /* The interface is completely set up so we show the window and
6202      * enter the gtk_main loop.
6203      */
6204     gtk_widget_show(window);
6205     gtk_main();
6206     
6207     return 0;
6208 }
6209
6210 /* User clicked the "Add List" button. */
6211 void button_add_clicked( GtkWidget *button, gpointer data)
6212 {
6213     int         indx;
6214
6215     /* Something silly to add to the list. 4 rows of 2 columns each */
6216     gchar      *drink[4][2] = {{"Milk", "3 Oz"},
6217                                {"Water", "6 l"},
6218                                {"Carrots", "2"},
6219                                {"Snakes", "55"}};
6220
6221     /* Here we do the actual adding of the text. It's done once for
6222      * each row.
6223      */
6224     for( indx=0; indx < 4; indx++)
6225         gtk_clist_append( (GtkCList*) data, drink[indx]);
6226
6227     return;
6228 }
6229
6230 /* User clicked the "Clear List" button. */
6231 void button_clear_clicked( GtkWidget *button, gpointer data)
6232 {
6233     /* Clear the list using gtk_clist_clear. This is much faster than
6234      * calling gtk_clist_remove once for each row.
6235      */
6236     gtk_clist_clear((GtkCList*) data);
6237
6238     return;
6239 }
6240
6241 /* The user clicked the "Hide/Show titles" button. */
6242 void button_hide_show_clicked( GtkWidget *button, gpointer data)
6243 {
6244     /* Just a flag to remember the status. 0 = currently visible */
6245     static short int flag = 0;
6246
6247     if (flag == 0)
6248     {
6249         /* Hide the titles and set the flag to 1 */
6250         gtk_clist_column_titles_hide((GtkCList*) data);
6251         flag++;
6252     }
6253     else
6254     {
6255         /* Show the titles and reset flag to 0 */
6256         gtk_clist_column_titles_show((GtkCList*) data);
6257         flag--;
6258     }
6259
6260     return;
6261 }
6262
6263 /* If we come here, then the user has selected a row in the list. */
6264 void selection_made( GtkWidget *clist, gint row, gint column,
6265                      GdkEventButton *event, gpointer data)
6266 {
6267     gchar       *text;
6268
6269     /* Get the text that is stored in the selected row and column
6270      * which was clicked in. We will receive it as a pointer in the
6271      * argument text.
6272      */
6273     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
6274
6275     /* Just prints some information about the selected row */
6276     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);
6277
6278     return;
6279 }
6280 /* example-end */
6281 </verb></tscreen>
6282                     
6283 <!-- ***************************************************************** -->
6284 <sect> List Widget
6285 <!-- ***************************************************************** -->
6286 <p>
6287 NOTE: The GtkList widget has been superseded by the GtkCList widget.
6288
6289 The GtkList widget is designed to act as a vertical container for widgets
6290 that should be of the type GtkListItem.
6291
6292 A GtkList widget has its own window to receive events and its own
6293 background color which is usually white.  As it is directly derived from a
6294 GtkContainer it can be treated as such by using the GTK_CONTAINER(List)
6295 macro, see the GtkContainer widget for more on this.
6296 One should already be familiar with the usage of a GList and its
6297 related functions g_list_*() to be able to use the GtkList widget to
6298 it full extent.
6299
6300 There is one field inside the structure definition of the GtkList widget
6301 that will be of greater interest to us, this is:
6302
6303 <tscreen><verb>
6304 struct _GtkList
6305 {
6306   ...
6307   GList *selection;
6308   guint selection_mode;
6309   ...
6310 }; 
6311 </verb></tscreen>
6312
6313 The selection field of a GtkList points to a linked list of all items
6314 that are currently selected, or NULL if the selection is empty.
6315 So to learn about the current selection we read the GTK_LIST()->selection
6316 field, but do not modify it since the internal fields are maintained by
6317 the gtk_list_*() functions.
6318
6319 The selection_mode of the GtkList determines the selection facilities
6320 of a GtkList and therefore the contents of the GTK_LIST()->selection
6321 field. The selection_mode may be one of the following:
6322
6323 <itemize>
6324 <item> GTK_SELECTION_SINGLE - The selection is either NULL
6325                         or contains a GList pointer
6326                         for a single selected item.
6327
6328 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list
6329                         contains no widgets or insensitive
6330                         ones only, otherwise it contains
6331                         a GList pointer for one GList
6332                         structure, and therefore exactly
6333                         one list item.
6334
6335 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list
6336                         items are selected or a GList pointer
6337                         for the first selected item. That
6338                         in turn points to a GList structure
6339                         for the second selected item and so
6340                         on.
6341
6342 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
6343 </itemize>
6344
6345 The default is GTK_SELECTION_MULTIPLE.
6346
6347 <!-- ----------------------------------------------------------------- -->
6348 <sect1> Signals
6349 <p>
6350 <tscreen><verb>
6351 void selection_changed( GtkList *list );
6352 </verb></tscreen>
6353
6354 This signal will be invoked whenever the selection field
6355 of a GtkList has changed. This happens when a child of
6356 the GtkList got selected or deselected.
6357
6358 <tscreen><verb>
6359 void select_child( GtkList   *list,
6360                    GtkWidget *child);
6361 </verb></tscreen>
6362
6363 This signal is invoked when a child of the GtkList is about
6364 to get selected. This happens mainly on calls to
6365 gtk_list_select_item(), gtk_list_select_child(), button presses
6366 and sometimes indirectly triggered on some else occasions where
6367 children get added to or removed from the GtkList.
6368
6369 <tscreen><verb>
6370 void unselect_child( GtkList   *list,
6371                      GtkWidget *child );
6372 </verb></tscreen>
6373
6374 This signal is invoked when a child of the GtkList is about
6375 to get deselected. This happens mainly on calls to
6376 gtk_list_unselect_item(), gtk_list_unselect_child(), button presses
6377 and sometimes indirectly triggered on some else occasions where
6378 children get added to or removed from the GtkList.
6379
6380 <!-- ----------------------------------------------------------------- -->
6381 <sect1> Functions
6382 <p>
6383 <tscreen><verb>
6384 guint gtk_list_get_type( void );
6385 </verb></tscreen>
6386
6387 Returns the `GtkList' type identifier.
6388
6389 <tscreen><verb>
6390 GtkWidget *gtk_list_new( void );
6391 </verb></tscreen>
6392
6393 Create a new GtkList object. The new widget is returned as a pointer to a
6394 GtkWidget object. NULL is returned on failure.
6395
6396 <tscreen><verb>
6397 void gtk_list_insert_items( GtkList *list,
6398                             GList   *items,
6399                             gint     position );
6400 </verb></tscreen>
6401
6402 Insert list items into the list, starting at <tt/position/.
6403 <tt/items/ is a doubly linked list where each nodes data
6404 pointer is expected to point to a newly created GtkListItem.
6405 The GList nodes of <tt/items/ are taken over by the list.
6406
6407 <tscreen><verb>
6408 void gtk_list_append_items( GtkList *list,
6409                             GList   *items);
6410 </verb></tscreen>
6411
6412 Insert list items just like gtk_list_insert_items() at the end
6413 of the list. The GList nodes of <tt/items/ are taken over by the list.
6414
6415 <tscreen><verb>
6416 void gtk_list_prepend_items( GtkList *list,
6417                              GList   *items);
6418 </verb></tscreen>
6419
6420 Insert list items just like gtk_list_insert_items() at the very
6421 beginning of the list. The GList nodes of <tt/items/ are taken over
6422 by the list.
6423
6424 <tscreen><verb>
6425 void gtk_list_remove_items( GtkList *list,
6426                             GList   *items);
6427 </verb></tscreen>
6428
6429 Remove list items from the list. <tt/items/ is a doubly linked
6430 list where each nodes data pointer is expected to point to a
6431 direct child of list. It is the callers responsibility to make a
6432 call to g_list_free(items) afterwards. Also the caller has to
6433 destroy the list items himself.
6434
6435 <tscreen><verb>
6436 void gtk_list_clear_items( GtkList *list,
6437                            gint start,
6438                            gint end );
6439 </verb></tscreen>
6440
6441 Remove and destroy list items from the list. A widget is affected if
6442 its current position within the list is in the range specified by
6443 <tt/start/ and <tt/end/.
6444
6445 <tscreen><verb>
6446 void gtk_list_select_item( GtkList *list,
6447                            gint     item );
6448 </verb></tscreen>
6449
6450 Invoke the select_child signal for a list item
6451 specified through its current position within the list.
6452
6453 <tscreen><verb>
6454 void gtk_list_unselect_item( GtkList *list,
6455                              gint     item);
6456 </verb></tscreen>
6457
6458 Invoke the unselect_child signal for a list item
6459 specified through its current position within the list.
6460
6461 <tscreen><verb>
6462 void gtk_list_select_child( GtkList *list,
6463                             GtkWidget *child);
6464 </verb></tscreen>
6465
6466 Invoke the select_child signal for the specified child.
6467
6468 <tscreen><verb>
6469 void gtk_list_unselect_child( GtkList   *list,
6470                               GtkWidget *child);
6471 </verb></tscreen>
6472
6473 Invoke the unselect_child signal for the specified child.
6474
6475 <tscreen><verb>
6476 gint gtk_list_child_position( GtkList *list,
6477                               GtkWidget *child);
6478 </verb></tscreen>
6479
6480 Return the position of <tt/child/ within the list. "-1" is returned on failure.
6481
6482 <tscreen><verb>
6483 void gtk_list_set_selection_mode( GtkList         *list,
6484                                   GtkSelectionMode mode );
6485 </verb></tscreen>
6486
6487 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
6488 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or GTK_SELECTION_EXTENDED.
6489
6490 <tscreen><verb>
6491 GtkList *GTK_LIST( gpointer obj );
6492 </verb></tscreen>
6493
6494 Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
6495 more info.
6496
6497 <tscreen><verb>
6498 GtkListClass *GTK_LIST_CLASS( gpointer class);
6499 </verb></tscreen>
6500
6501 Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
6502 for more info.
6503
6504 <tscreen><verb>
6505 gint GTK_IS_LIST( gpointer obj);
6506 </verb></tscreen>
6507
6508 Determine if a generic pointer refers to a `GtkList' object. *Note
6509 Standard Macros::, for more info.
6510
6511 <!-- ----------------------------------------------------------------- -->
6512 <sect1> Example
6513 <p>
6514 Following is an example program that will print out the changes
6515 of the selection of a GtkList, and lets you "arrest" list items
6516 into a prison by selecting them with the rightmost mouse button.
6517
6518 <tscreen><verb>
6519 /* example-start list list.c */
6520
6521 /* include the gtk+ header files
6522  * include stdio.h, we need that for the printf() function
6523  */
6524 #include        <gtk/gtk.h>
6525 #include        <stdio.h>
6526
6527 /* this is our data identification string to store
6528  * data in list items
6529  */
6530 const   gchar   *list_item_data_key="list_item_data";
6531
6532
6533 /* prototypes for signal handler that we are going to connect
6534  * to the GtkList widget
6535  */
6536 static  void    sigh_print_selection    (GtkWidget      *gtklist,
6537                                          gpointer       func_data);
6538 static  void    sigh_button_event       (GtkWidget      *gtklist,
6539                                          GdkEventButton *event,
6540                                          GtkWidget      *frame);
6541
6542
6543 /* main function to set up the user interface */
6544
6545 gint main (int argc, gchar *argv[])
6546 {                                  
6547     GtkWidget       *separator;
6548     GtkWidget       *window;
6549     GtkWidget       *vbox;
6550     GtkWidget       *scrolled_window;
6551     GtkWidget       *frame;
6552     GtkWidget       *gtklist;
6553     GtkWidget       *button;
6554     GtkWidget       *list_item;
6555     GList           *dlist;
6556     guint           i;
6557     gchar           buffer[64];
6558     
6559     
6560     /* initialize gtk+ (and subsequently gdk) */
6561
6562     gtk_init(&amp;argc, &amp;argv);
6563     
6564     
6565     /* create a window to put all the widgets in
6566      * connect gtk_main_quit() to the "destroy" event of
6567      * the window to handle window manager close-window-events
6568      */
6569     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
6570     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
6571     gtk_signal_connect(GTK_OBJECT(window),
6572                        "destroy",
6573                        GTK_SIGNAL_FUNC(gtk_main_quit),
6574                        NULL);
6575     
6576     
6577     /* inside the window we need a box to arrange the widgets
6578      * vertically */
6579     vbox=gtk_vbox_new(FALSE, 5);
6580     gtk_container_border_width(GTK_CONTAINER(vbox), 5);
6581     gtk_container_add(GTK_CONTAINER(window), vbox);
6582     gtk_widget_show(vbox);
6583     
6584     /* this is the scrolled window to put the GtkList widget inside */
6585     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
6586     gtk_widget_set_usize(scrolled_window, 250, 150);
6587     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
6588     gtk_widget_show(scrolled_window);
6589     
6590     /* create the GtkList widget
6591      * connect the sigh_print_selection() signal handler
6592      * function to the "selection_changed" signal of the GtkList
6593      * to print out the selected items each time the selection
6594      * has changed */
6595     gtklist=gtk_list_new();
6596     gtk_container_add(GTK_CONTAINER(scrolled_window), gtklist);
6597     gtk_widget_show(gtklist);
6598     gtk_signal_connect(GTK_OBJECT(gtklist),
6599                        "selection_changed",
6600                        GTK_SIGNAL_FUNC(sigh_print_selection),
6601                        NULL);
6602     
6603     /* we create a "Prison" to put a list item in ;)
6604      */
6605     frame=gtk_frame_new("Prison");
6606     gtk_widget_set_usize(frame, 200, 50);
6607     gtk_container_border_width(GTK_CONTAINER(frame), 5);
6608     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
6609     gtk_container_add(GTK_CONTAINER(vbox), frame);
6610     gtk_widget_show(frame);
6611     
6612     /* connect the sigh_button_event() signal handler to the GtkList
6613      * which will handle the "arresting" of list items
6614      */
6615     gtk_signal_connect(GTK_OBJECT(gtklist),
6616                        "button_release_event",
6617                        GTK_SIGNAL_FUNC(sigh_button_event),
6618                        frame);
6619     
6620     /* create a separator
6621      */
6622     separator=gtk_hseparator_new();
6623     gtk_container_add(GTK_CONTAINER(vbox), separator);
6624     gtk_widget_show(separator);
6625     
6626     /* finally create a button and connect it´s "clicked" signal
6627      * to the destruction of the window
6628      */
6629     button=gtk_button_new_with_label("Close");
6630     gtk_container_add(GTK_CONTAINER(vbox), button);
6631     gtk_widget_show(button);
6632     gtk_signal_connect_object(GTK_OBJECT(button),
6633                               "clicked",
6634                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
6635                               GTK_OBJECT(window));
6636     
6637     
6638     /* now we create 5 list items, each having it´s own
6639      * label and add them to the GtkList using gtk_container_add()
6640      * also we query the text string from the label and
6641      * associate it with the list_item_data_key for each list item
6642      */
6643     for (i=0; i<5; i++) {
6644         GtkWidget       *label;
6645         gchar           *string;
6646         
6647         sprintf(buffer, "ListItemContainer with Label #%d", i);
6648         label=gtk_label_new(buffer);
6649         list_item=gtk_list_item_new();
6650         gtk_container_add(GTK_CONTAINER(list_item), label);
6651         gtk_widget_show(label);
6652         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
6653         gtk_widget_show(list_item);
6654         gtk_label_get(GTK_LABEL(label), &amp;string);
6655         gtk_object_set_data(GTK_OBJECT(list_item),
6656                             list_item_data_key,
6657                             string);
6658     }
6659     /* here, we are creating another 5 labels, this time
6660      * we use gtk_list_item_new_with_label() for the creation
6661      * we can´t query the text string from the label because
6662      * we don´t have the labels pointer and therefore
6663      * we just associate the list_item_data_key of each
6664      * list item with the same text string
6665      * for adding of the list items we put them all into a doubly
6666      * linked list (GList), and then add them by a single call to
6667      * gtk_list_append_items()
6668      * because we use g_list_prepend() to put the items into the
6669      * doubly linked list, their order will be descending (instead
6670      * of ascending when using g_list_append())
6671      */
6672     dlist=NULL;
6673     for (; i<10; i++) {
6674         sprintf(buffer, "List Item with Label %d", i);
6675         list_item=gtk_list_item_new_with_label(buffer);
6676         dlist=g_list_prepend(dlist, list_item);
6677         gtk_widget_show(list_item);
6678         gtk_object_set_data(GTK_OBJECT(list_item),
6679                             list_item_data_key,
6680                             "ListItem with integrated Label");
6681     }
6682     gtk_list_append_items(GTK_LIST(gtklist), dlist);
6683     
6684     /* finally we want to see the window, don't we? ;)
6685      */
6686     gtk_widget_show(window);
6687     
6688     /* fire up the main event loop of gtk
6689      */
6690     gtk_main();
6691     
6692     /* we get here after gtk_main_quit() has been called which
6693      * happens if the main window gets destroyed
6694      */
6695     return 0;
6696 }
6697
6698 /* this is the signal handler that got connected to button
6699  * press/release events of the GtkList
6700  */
6701 void
6702 sigh_button_event       (GtkWidget      *gtklist,
6703                          GdkEventButton *event,
6704                          GtkWidget      *frame)
6705 {
6706     /* we only do something if the third (rightmost mouse button
6707      * was released
6708      */
6709     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
6710         event->button==3) {
6711         GList           *dlist, *free_list;
6712         GtkWidget       *new_prisoner;
6713         
6714         /* fetch the currently selected list item which
6715          * will be our next prisoner ;)
6716          */
6717         dlist=GTK_LIST(gtklist)->selection;
6718         if (dlist)
6719                 new_prisoner=GTK_WIDGET(dlist->data);
6720         else
6721                 new_prisoner=NULL;
6722         
6723         /* look for already imprisoned list items, we
6724          * will put them back into the list
6725          * remember to free the doubly linked list that
6726          * gtk_container_children() returns
6727          */
6728         dlist=gtk_container_children(GTK_CONTAINER(frame));
6729         free_list=dlist;
6730         while (dlist) {
6731             GtkWidget       *list_item;
6732             
6733             list_item=dlist->data;
6734             
6735             gtk_widget_reparent(list_item, gtklist);
6736             
6737             dlist=dlist->next;
6738         }
6739         g_list_free(free_list);
6740         
6741         /* if we have a new prisoner, remove him from the
6742          * GtkList and put him into the frame "Prison"
6743          * we need to unselect the item before
6744          */
6745         if (new_prisoner) {
6746             GList   static_dlist;
6747             
6748             static_dlist.data=new_prisoner;
6749             static_dlist.next=NULL;
6750             static_dlist.prev=NULL;
6751             
6752             gtk_list_unselect_child(GTK_LIST(gtklist),
6753                                     new_prisoner);
6754             gtk_widget_reparent(new_prisoner, frame);
6755         }
6756     }
6757 }
6758
6759 /* this is the signal handler that gets called if GtkList
6760  * emits the "selection_changed" signal
6761  */
6762 void
6763 sigh_print_selection    (GtkWidget      *gtklist,
6764                          gpointer       func_data)
6765 {
6766     GList   *dlist;
6767     
6768     /* fetch the doubly linked list of selected items
6769      * of the GtkList, remember to treat this as read-only!
6770      */
6771     dlist=GTK_LIST(gtklist)->selection;
6772     
6773     /* if there are no selected items there is nothing more
6774      * to do than just telling the user so
6775      */
6776     if (!dlist) {
6777         g_print("Selection cleared\n");
6778         return;
6779     }
6780     /* ok, we got a selection and so we print it
6781      */
6782     g_print("The selection is a ");
6783     
6784     /* get the list item from the doubly linked list
6785      * and then query the data associated with list_item_data_key
6786      * we then just print it
6787      */
6788     while (dlist) {
6789         GtkObject       *list_item;
6790         gchar           *item_data_string;
6791         
6792         list_item=GTK_OBJECT(dlist->data);
6793         item_data_string=gtk_object_get_data(list_item,
6794                                              list_item_data_key);
6795         g_print("%s ", item_data_string);
6796         
6797         dlist=dlist->next;
6798     }
6799     g_print("\n");
6800 }
6801 /* example-end */
6802 </verb></tscreen>
6803
6804 <!-- ----------------------------------------------------------------- -->
6805 <sect1> List Item Widget
6806 <p>
6807 The GtkListItem widget is designed to act as a container holding up
6808 to one child, providing functions for selection/deselection just like
6809 the GtkList widget requires them for its children.
6810
6811 A GtkListItem has its own window to receive events and has its own
6812 background color which is usually white.  
6813
6814 As it is directly derived from a
6815 GtkItem it can be treated as such by using the GTK_ITEM(ListItem)
6816 macro, see the GtkItem widget for more on this.
6817 Usually a GtkListItem just holds a label to identify e.g. a filename
6818 within a GtkList -- therefore the convenience function
6819 gtk_list_item_new_with_label() is provided.  The same effect can be
6820 achieved by creating a GtkLabel on its own, setting its alignment
6821 to xalign=0 and yalign=0.5 with a subsequent container addition
6822 to the GtkListItem.
6823
6824 As one is not forced to add a GtkLabel to a GtkListItem, you could
6825 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
6826
6827 <!-- ----------------------------------------------------------------- -->
6828 <sect1> Signals
6829 <p>
6830 A GtkListItem does not create new signals on its own, but inherits
6831 the signals of a GtkItem. *Note GtkItem::, for more info.
6832
6833 <!-- ----------------------------------------------------------------- -->
6834 <sect1> Functions
6835 <p>
6836 <tscreen><verb>
6837 guint gtk_list_item_get_type( void );
6838 </verb></tscreen>
6839
6840 Returns the `GtkListItem' type identifier.
6841
6842 <tscreen><verb>
6843 GtkWidget *gtk_list_item_new( void );
6844 </verb></tscreen>
6845
6846 Create a new GtkListItem object. The new widget is returned as a pointer
6847 to a GtkWidget object. NULL is returned on failure.
6848
6849 <tscreen><verb>
6850 GtkWidget *gtk_list_item_new_with_label( gchar *label );
6851 </verb></tscreen>
6852
6853 Create a new GtkListItem object, having a single GtkLabel as
6854 the sole child. The new widget is returned as a pointer to a
6855 GtkWidget object. NULL is returned on failure.
6856
6857 <tscreen><verb>
6858 void gtk_list_item_select( GtkListItem *list_item );
6859 </verb></tscreen>
6860
6861 This function is basically a wrapper around a call to
6862 gtk_item_select (GTK_ITEM (list_item)) which will emit the
6863 select signal.
6864 *Note GtkItem::, for more info.
6865
6866 <tscreen><verb>
6867 void gtk_list_item_deselect( GtkListItem *list_item );
6868 </verb></tscreen>
6869
6870 This function is basically a wrapper around a call to
6871 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the
6872 deselect signal.
6873 *Note GtkItem::, for more info.
6874
6875 <tscreen><verb>
6876 GtkListItem *GTK_LIST_ITEM( gpointer obj );
6877 </verb></tscreen>
6878
6879 Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::,
6880 for more info.
6881
6882 <tscreen><verb>
6883 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
6884 </verb></tscreen>
6885
6886 Cast a generic pointer to GtkListItemClass*. *Note Standard
6887 Macros::, for more info.
6888
6889 <tscreen><verb>
6890 gint GTK_IS_LIST_ITEM( gpointer obj );
6891 </verb></tscreen>
6892
6893 Determine if a generic pointer refers to a `GtkListItem' object.
6894 *Note Standard Macros::, for more info.
6895  
6896 <!-- ----------------------------------------------------------------- -->
6897 <sect1> Example
6898 <p>
6899 Please see the GtkList example on this, which covers the usage of a
6900 GtkListItem as well.
6901
6902 <!-- ***************************************************************** -->
6903 <sect> Tree Widget<label id="sec_Tree_Widgets">
6904 <!-- ***************************************************************** -->
6905 <p>
6906
6907 The purpose of tree widgets is to display hierarchically-organized
6908 data. The GtkTree widget itself is a vertical container for widgets
6909 of type GtkTreeItem. GtkTree itself is not terribly different from
6910 GtkList - both are derived directly from GtkContainer, and the
6911 GtkContainer methods work in the same way on GtkTree widgets as on
6912 GtkList widgets. The difference is that GtkTree widgets can be nested
6913 within other GtkTree widgets. We'll see how to do this shortly.
6914
6915 The GtkTree widget has its own window, and defaults to a white
6916 background, as does GtkList. Also, most of the GtkTree methods work
6917 in the same way as the corresponding GtkList ones. However, GtkTree
6918 is not derived from GtkList, so you cannot use them interchangeably.
6919
6920 <sect1> Creating a Tree
6921 <p>
6922 A GtkTree is created in the usual way, using:
6923
6924 <tscreen><verb>
6925 GtkWidget* gtk_tree_new( void );
6926 </verb></tscreen>
6927
6928 Like the GtkList widget, a GtkTree will simply keep growing as more
6929 items are added to it, as well as when subtrees are expanded.
6930 For this reason, they are almost always packed into a
6931 GtkScrolledWindow. You might want to use gtk_widget_set_usize() on
6932 the scrolled window to ensure that it is big enough to see the tree's
6933 items, as the default size for GtkScrolledWindow is quite small.
6934
6935 Now that you have a tree, you'll probably want to add some items to
6936 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
6937 explains the gory details of GtkTreeItem. For now, it'll suffice to
6938 create one, using:
6939
6940 <tscreen><verb>
6941 GtkWidget* gtk_tree_item_new_with_label( gchar *label );
6942 </verb></tscreen>
6943
6944 You can then add it to the tree using one of the following (see
6945 <ref id="sec_GtkTree_Functions" name="Functions and Macros">
6946 below for more options):
6947
6948 <tscreen><verb>
6949 void gtk_tree_append( GtkTree    *tree,
6950                        GtkWidget *tree_item );
6951
6952 void gtk_tree_prepend( GtkTree   *tree,
6953                        GtkWidget *tree_item );
6954 </verb></tscreen>
6955
6956 Note that you must add items to a GtkTree one at a time - there is no
6957 equivalent to gtk_list_*_items().
6958
6959 <sect1> Adding a Subtree
6960 <p>
6961 A subtree is created like any other GtkTree widget. A subtree is added
6962 to another tree beneath a tree item, using:
6963
6964 <tscreen><verb>
6965 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
6966                                 GtkWidget   *subtree );
6967 </verb></tscreen>
6968
6969 You do not need to call gtk_widget_show() on a subtree before or after
6970 adding it to a GtkTreeItem. However, you <em>must</em> have added the
6971 GtkTreeItem in question to a parent tree before calling
6972 gtk_tree_item_set_subtree(). This is because, technically, the parent
6973 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
6974 rather the GtkTree which holds that GtkTreeItem.
6975
6976 When you add a subtree to a GtkTreeItem, a plus or minus sign appears
6977 beside it, which the user can click on to "expand" or "collapse" it,
6978 meaning, to show or hide its subtree. GtkTreeItems are collapsed by
6979 default. Note that when you collapse a GtkTreeItem, any selected
6980 items in its subtree remain selected, which may not be what the user
6981 expects.
6982
6983 <sect1> Handling the Selection List
6984 <p>
6985 As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
6986 it is possible to control the behaviour of the tree (somewhat) by
6987 setting the selection type using:
6988
6989 <tscreen><verb>
6990 void gtk_tree_set_selection_mode( GtkTree          *tree,
6991                                   GtkSelectionMode  mode );
6992 </verb></tscreen>
6993
6994 The semantics associated with the various selection modes are
6995 described in the section on the GtkList widget.  As with the GtkList
6996 widget, the "select_child", "unselect_child" (not really - see <ref
6997 id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
6998 and "selection_changed" signals are emitted when list items are
6999 selected or unselected.  However, in order to take advantage of these
7000 signals, you need to know <em>which</em> GtkTree widget they will be
7001 emitted by, and where to find the list of selected items.
7002
7003 This is a source of potential confusion. The best way to explain this
7004 is that though all GtkTree widgets are created equal, some are more
7005 equal than others. All GtkTree widgets have their own X window, and
7006 can therefore receive events such as mouse clicks (if their
7007 GtkTreeItems or their children don't catch them first!). However, to
7008 make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
7009 behave in a sane manner, the list of selected items is specific to the
7010 topmost GtkTree widget in a hierarchy, known as the "root tree".
7011
7012 Thus, accessing the <tt>selection</tt>field directly in an arbitrary
7013 GtkTree widget is not a good idea unless you <em>know</em> it's the
7014 root tree.  Instead, use the GTK_TREE_SELECTION (Tree) macro, which
7015 gives the root tree's selection list as a GList pointer. Of course,
7016 this list can include items that are not in the subtree in question if 
7017 the selection type is GTK_SELECTION_MULTIPLE.
7018
7019 Finally, the "select_child" (and "unselect_child", in theory) signals
7020 are emitted by all trees, but the "selection_changed" signal is only
7021 emitted by the root tree. Consequently, if you want to handle the
7022 "select_child" signal for a tree and all its subtrees, you will have
7023 to call gtk_signal_connect() for every subtree.
7024
7025 <sect1> Tree Widget Internals
7026 <p>
7027 The GtkTree's struct definition looks like this:
7028
7029 <tscreen><verb>
7030 struct _GtkTree
7031 {
7032   GtkContainer container;
7033
7034   GList *children;
7035   
7036   GtkTree* root_tree; /* owner of selection list */
7037   GtkWidget* tree_owner;
7038   GList *selection;
7039   guint level;
7040   guint indent_value;
7041   guint current_indent;
7042   guint selection_mode : 2;
7043   guint view_mode : 1;
7044   guint view_line : 1;
7045 };
7046 </verb></tscreen>
7047
7048 The perils associated with accessing the <tt>selection</tt> field
7049 directly have already been mentioned.  The other important fields of
7050 the struct can also be accessed with handy macros or class functions.
7051 GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
7052 whether a tree is the root tree in a GtkTree hierarchy, while
7053 GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
7054 GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
7055 to use one of the gtk_widget_*() functions on it).
7056
7057 Instead of directly accessing the children field of a GtkTree widget,
7058 it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
7059 to the gtk_container_children() function. This creates a duplicate of
7060 the original list, so it's advisable to free it up using g_list_free() 
7061 after you're done with it, or to iterate on it destructively, like
7062 this:
7063
7064 <tscreen><verb>
7065 children = gtk_container_children (GTK_CONTAINER (tree));
7066 while (children) {
7067   do_something_nice (GTK_TREE_ITEM (children->data));
7068   children = g_list_remove_link (children, children);
7069 }
7070 </verb></tscreen>
7071
7072 The <tt>tree_owner</tt> field is defined only in subtrees, where it
7073 points to the GtkTreeItem widget which holds the tree in question.
7074 The <tt>level</tt> field indicates how deeply nested a particular tree
7075 is; root trees have level 0, and each successive level of subtrees has
7076 a level one greater than the parent level.  This field is set only
7077 after a GtkTree widget is actually mapped (i.e. drawn on the screen).
7078
7079 <sect2> Signals<label id="sec_GtkTree_Signals">
7080 <p>
7081 <tscreen><verb>
7082 void selection_changed( GtkTree *tree );
7083 </verb></tscreen>
7084
7085 This signal will be emitted whenever the <tt>selection</tt> field of a
7086 GtkTree has changed. This happens when a child of the GtkTree is
7087 selected or deselected.
7088
7089 <tscreen><verb>
7090 void select_child( GtkTree   *tree,
7091                    GtkWidget *child );
7092 </verb></tscreen>
7093
7094 This signal is emitted when a child of the GtkTree is about to get
7095 selected. This happens on calls to gtk_tree_select_item(),
7096 gtk_tree_select_child(), on <em>all</em> button presses and calls to
7097 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
7098 indirectly triggered on other occasions where children get added to or
7099 removed from the GtkTree.
7100
7101 <tscreen><verb>
7102 void unselect_child (GtkTree   *tree,
7103                      GtkWidget *child);
7104 </verb></tscreen>
7105
7106 This signal is emitted when a child of the GtkTree is about to get
7107 deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
7108 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
7109 other occasions, but <em>not</em> when a button press deselects a
7110 child, nor on emission of the "toggle" signal by gtk_item_toggle().
7111
7112 <sect2> Functions and Macros<label id="sec_GtkTree_Functions">
7113 <p>
7114 <tscreen><verb>
7115 guint gtk_tree_get_type( void );
7116 </verb></tscreen>
7117
7118 Returns the `GtkTree' type identifier.
7119
7120 <tscreen><verb>
7121 GtkWidget* gtk_tree_new( void );
7122 </verb></tscreen>
7123
7124 Create a new GtkTree object. The new widget is returned as a pointer to a
7125 GtkWidget object. NULL is returned on failure.
7126
7127 <tscreen><verb>
7128 void gtk_tree_append( GtkTree   *tree,
7129                       GtkWidget *tree_item );
7130 </verb></tscreen>
7131
7132 Append a tree item to a GtkTree.
7133
7134 <tscreen><verb>
7135 void gtk_tree_prepend( GtkTree   *tree,
7136                        GtkWidget *tree_item );
7137 </verb></tscreen>
7138
7139 Prepend a tree item to a GtkTree.
7140
7141 <tscreen><verb>
7142 void gtk_tree_insert( GtkTree   *tree,
7143                       GtkWidget *tree_item,
7144                       gint       position );
7145 </verb></tscreen>
7146
7147 Insert a tree item into a GtkTree at the position in the list
7148 specified by <tt>position.</tt>
7149
7150 <tscreen><verb>
7151 void gtk_tree_remove_items( GtkTree *tree,
7152                             GList   *items );
7153 </verb></tscreen>
7154
7155 Remove a list of items (in the form of a GList *) from a GtkTree.
7156 Note that removing an item from a tree dereferences (and thus usually)
7157 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
7158 subtrees in that subtree.  If you want to remove only one item, you
7159 can use gtk_container_remove().
7160
7161 <tscreen><verb>
7162 void gtk_tree_clear_items( GtkTree *tree,
7163                            gint     start,
7164                            gint     end );
7165 </verb></tscreen>
7166
7167 Remove the items from position <tt>start</tt> to position <tt>end</tt>
7168 from a GtkTree.  The same warning about dereferencing applies here, as
7169 gtk_tree_clear_items() simply constructs a list and passes it to
7170 gtk_tree_remove_items().
7171
7172 <tscreen><verb>
7173 void gtk_tree_select_item( GtkTree *tree,
7174                            gint     item );
7175 </verb></tscreen>
7176
7177 Emits the "select_item" signal for the child at position
7178 <tt>item</tt>, thus selecting the child (unless you unselect it in a
7179 signal handler...)
7180
7181 <tscreen><verb>
7182 void gtk_tree_unselect_item( GtkTree *tree,
7183                              gint     item );
7184 </verb></tscreen>
7185
7186 Emits the "unselect_item" signal for the child at position
7187 <tt>item</tt>, thus unselecting the child.
7188
7189 <tscreen><verb>
7190 void gtk_tree_select_child( GtkTree   *tree,
7191                             GtkWidget *tree_item );
7192 </verb></tscreen>
7193
7194 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
7195 selecting it.
7196
7197 <tscreen><verb>
7198 void gtk_tree_unselect_child( GtkTree   *tree,
7199                               GtkWidget *tree_item );
7200 </verb></tscreen>
7201
7202 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
7203 thus unselecting it.
7204
7205 <tscreen><verb>
7206 gint gtk_tree_child_position( GtkTree   *tree,
7207                               GtkWidget *child );
7208 </verb></tscreen>
7209
7210 Returns the position in the tree of <tt>child</tt>, unless
7211 <tt>child</tt> is not in the tree, in which case it returns -1.
7212
7213 <tscreen><verb>
7214 void gtk_tree_set_selection_mode( GtkTree          *tree,
7215                                   GtkSelectionMode  mode );
7216 </verb></tscreen>
7217
7218 Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
7219 default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
7220 GTK_SELECTION_EXTENDED. This is only defined for root trees, which
7221 makes sense, since the root tree "owns" the selection. Setting it for
7222 subtrees has no effect at all; the value is simply ignored.
7223
7224 <tscreen><verb>
7225 void gtk_tree_set_view_mode( GtkTree         *tree,
7226                              GtkTreeViewMode  mode ); 
7227 </verb></tscreen>
7228
7229 Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
7230 default) or GTK_TREE_VIEW_ITEM.  The view mode propagates from a tree
7231 to its subtrees, and can't be set exclusively to a subtree (this is
7232 not exactly true - see the example code comments).
7233
7234 The term "view mode" is rather ambiguous - basically, it controls the
7235 way the highlight is drawn when one of a tree's children is selected.
7236 If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
7237 highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
7238 (i.e. usually the label) is highlighted.
7239
7240 <tscreen><verb>
7241 void gtk_tree_set_view_lines( GtkTree *tree,
7242                               guint    flag );
7243 </verb></tscreen>
7244
7245 Controls whether connecting lines between tree items are drawn.
7246 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
7247 which case they aren't.
7248
7249 <tscreen><verb>
7250 GtkTree *GTK_TREE (gpointer obj);
7251 </verb></tscreen>
7252
7253 Cast a generic pointer to `GtkTree *'.
7254
7255 <tscreen><verb>
7256 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
7257 </verb></tscreen>
7258
7259 Cast a generic pointer to `GtkTreeClass*'.
7260
7261 <tscreen><verb>
7262 gint GTK_IS_TREE (gpointer obj);
7263 </verb></tscreen>
7264
7265 Determine if a generic pointer refers to a `GtkTree' object.
7266
7267 <tscreen><verb>
7268 gint GTK_IS_ROOT_TREE (gpointer obj)
7269 </verb></tscreen>
7270
7271 Determine if a generic pointer refers to a `GtkTree' object
7272 <em>and</em> is a root tree. Though this will accept any pointer, the
7273 results of passing it a pointer that does not refer to a GtkTree are
7274 undefined and possibly harmful.
7275
7276 <tscreen><verb>
7277 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
7278 </verb></tscreen>
7279
7280 Return the root tree of a pointer to a `GtkTree' object. The above
7281 warning applies.
7282
7283 <tscreen><verb>
7284 GList *GTK_TREE_SELECTION( gpointer obj)
7285 </verb></tscreen>
7286
7287 Return the selection list of the root tree of a `GtkTree' object. The 
7288 above warning applies here, too.
7289
7290 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
7291 <p>
7292 The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
7293 which in turn is derived from GtkBin.  Therefore, the item itself is a
7294 generic container holding exactly one child widget, which can be of
7295 any type.  The GtkTreeItem widget has a number of extra fields, but
7296 the only one we need be concerned with is the <tt>subtree</tt> field.
7297
7298 The definition for the GtkTreeItem struct looks like this:
7299
7300 <tscreen><verb>
7301 struct _GtkTreeItem
7302 {
7303   GtkItem item;
7304
7305   GtkWidget *subtree;
7306   GtkWidget *pixmaps_box;
7307   GtkWidget *plus_pix_widget, *minus_pix_widget;
7308
7309   GList *pixmaps;               /* pixmap node for this items color depth */
7310
7311   guint expanded : 1;
7312 };
7313 </verb></tscreen>
7314
7315 The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
7316 on the plus/minus symbol which controls expansion and collapsing.  The
7317 <tt>pixmaps</tt> field points to an internal data structure.  Since
7318 you can always obtain the subtree of a GtkTreeItem in a (relatively)
7319 type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
7320 probably advisable never to touch the insides of a GtkTreeItem unless
7321 you <em>really</em> know what you're doing.
7322
7323 Since it is directly derived from a GtkItem it can be treated as such
7324 by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
7325 label, so the convenience function gtk_list_item_new_with_label() is
7326 provided. The same effect can be achieved using code like the
7327 following, which is actually copied verbatim from
7328 gtk_tree_item_new_with_label():
7329
7330 <tscreen><verb>
7331 tree_item = gtk_tree_item_new ();
7332 label_widget = gtk_label_new (label);
7333 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
7334
7335 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
7336 gtk_widget_show (label_widget);
7337 </verb></tscreen>
7338
7339 As one is not forced to add a GtkLabel to a GtkTreeItem, you could
7340 also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
7341 app will likely be quite unpopular in this case) to the GtkTreeItem.
7342
7343 If you remove all the items from a subtree, it will be destroyed and
7344 unparented, unless you reference it beforehand, and the GtkTreeItem
7345 which owns it will be collapsed.  So, if you want it to stick around,
7346 do something like the following:
7347
7348 <tscreen><verb>
7349 gtk_widget_ref (tree);
7350 owner = GTK_TREE(tree)->tree_owner;
7351 gtk_container_remove (GTK_CONTAINER(tree), item);
7352 if (tree->parent == NULL){
7353   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
7354   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
7355 }
7356 else
7357   gtk_widget_unref (tree);
7358 </verb></tscreen>
7359
7360 Finally, drag-n-drop <em>does</em> work with GtkTreeItems.  You just
7361 have to make sure that the GtkTreeItem you want to make into a drag
7362 item or a drop site has not only been added to a GtkTree, but that
7363 each successive parent widget has a parent itself, all the way back to
7364 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
7365 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
7366
7367 <sect2> Signals
7368 <p>
7369 GtkTreeItem inherits the "select", "deselect", and "toggle" signals
7370 from GtkItem.  In addition, it adds two signals of its own, "expand"
7371 and "collapse".
7372
7373 <tscreen><verb>
7374 void select( GtkItem *tree_item );
7375 </verb></tscreen>
7376
7377 This signal is emitted when an item is about to be selected, either
7378 after it has been clicked on by the user, or when the program calls
7379 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
7380
7381 <tscreen><verb>
7382 void deselect( GtkItem *tree_item );
7383 </verb></tscreen>
7384
7385 This signal is emitted when an item is about to be unselected, either
7386 after it has been clicked on by the user, or when the program calls
7387 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
7388 GtkTreeItems, it is also emitted by gtk_tree_unselect_child(), and
7389 sometimes gtk_tree_select_child().
7390
7391 <tscreen><verb>
7392 void toggle( GtkItem *tree_item );
7393 </verb></tscreen>
7394
7395 This signal is emitted when the program calls gtk_item_toggle().  The
7396 effect it has when emitted on a GtkTreeItem is to call
7397 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
7398 item's parent tree, if the item has a parent tree.  If it doesn't,
7399 then the highlight is reversed on the item.
7400
7401 <tscreen><verb>
7402 void expand( GtkTreeItem *tree_item );
7403 </verb></tscreen>
7404
7405 This signal is emitted when the tree item's subtree is about to be
7406 expanded, that is, when the user clicks on the plus sign next to the
7407 item, or when the program calls gtk_tree_item_expand().
7408
7409 <tscreen><verb>
7410 void collapse( GtkTreeItem *tree_item );
7411 </verb></tscreen>
7412
7413 This signal is emitted when the tree item's subtree is about to be
7414 collapsed, that is, when the user clicks on the minus sign next to the
7415 item, or when the program calls gtk_tree_item_collapse().
7416
7417 <sect2> Functions and Macros
7418 <p>
7419 <tscreen><verb>
7420 guint gtk_tree_item_get_type( void );
7421 </verb></tscreen>
7422
7423 Returns the `GtkTreeItem' type identifier.
7424
7425 <tscreen><verb>
7426 GtkWidget* gtk_tree_item_new( void );
7427 </verb></tscreen>
7428
7429 Create a new GtkTreeItem object. The new widget is returned as a pointer
7430 to a GtkWidget object. NULL is returned on failure.
7431
7432 <tscreen><verb>
7433 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
7434 </verb></tscreen>
7435
7436 Create a new GtkTreeItem object, having a single GtkLabel as
7437 the sole child. The new widget is returned as a pointer to a
7438 GtkWidget object. NULL is returned on failure.
7439
7440 <tscreen><verb>
7441 void gtk_tree_item_select( GtkTreeItem *tree_item );
7442 </verb></tscreen>
7443
7444 This function is basically a wrapper around a call to
7445 gtk_item_select (GTK_ITEM (tree_item)) which will emit the
7446 select signal.
7447
7448 <tscreen><verb>
7449 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
7450 </verb></tscreen>
7451
7452 This function is basically a wrapper around a call to
7453 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the
7454 deselect signal.
7455
7456 <tscreen><verb>
7457 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
7458                                 GtkWidget   *subtree );
7459 </verb></tscreen>
7460
7461 This function adds subtree to tree_item, showing it if tree_item is
7462 expanded, or hiding it if tree_item is collapsed. Again, remember
7463 that the tree_item must have already been added to a tree for this to
7464 work.
7465
7466 <tscreen><verb>
7467 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
7468 </verb></tscreen>
7469
7470 This removes all of tree_item's subtree's children (thus unreferencing
7471 and destroying it, any of its children's subtrees, and so on...), then
7472 removes the subtree itself, and hides the plus/minus sign.
7473
7474 <tscreen><verb>
7475 void gtk_tree_item_expand( GtkTreeItem *tree_item );
7476 </verb></tscreen>
7477
7478 This emits the "expand" signal on tree_item, which expands it.
7479
7480 <tscreen><verb>
7481 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
7482 </verb></tscreen>
7483
7484 This emits the "collapse" signal on tree_item, which collapses it.
7485
7486 <tscreen><verb>
7487 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
7488 </verb></tscreen>
7489
7490 Cast a generic pointer to `GtkTreeItem*'.
7491
7492 <tscreen><verb>
7493 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
7494 </verb></tscreen>
7495
7496 Cast a generic pointer to `GtkTreeItemClass'.
7497
7498 <tscreen><verb>
7499 gint GTK_IS_TREE_ITEM (gpointer obj)
7500 </verb></tscreen>
7501
7502 Determine if a generic pointer refers to a `GtkTreeItem' object.
7503  
7504 <tscreen><verb>
7505 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
7506 </verb></tscreen>
7507
7508 Returns a tree item's subtree (obj should point to a `GtkTreeItem'
7509 object).
7510
7511 <sect1> Tree Example
7512 <p>
7513 This is somewhat like the tree example in testgtk.c, but a lot less
7514 complete (although much better commented).  It puts up a window with a
7515 tree, and connects all the signals for the relevant objects, so you
7516 can see when they are emitted.
7517
7518 <tscreen><verb>
7519 /* example-start tree tree.c */
7520
7521 #include <gtk/gtk.h>
7522
7523 /* for all the GtkItem:: and GtkTreeItem:: signals */
7524 static void cb_itemsignal (GtkWidget *item, gchar *signame)
7525 {
7526   gchar *name;
7527   GtkLabel *label;
7528
7529   /* It's a GtkBin, so it has one child, which we know to be a
7530      label, so get that */
7531   label = GTK_LABEL (GTK_BIN (item)->child);
7532   /* Get the text of the label */
7533   gtk_label_get (label, &amp;name);
7534   /* Get the level of the tree which the item is in */
7535   g_print ("%s called for item %s->%p, level %d\n", signame, name,
7536            item, GTK_TREE (item->parent)->level);
7537 }
7538
7539 /* Note that this is never called */
7540 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
7541                                GtkWidget *subtree)
7542 {
7543   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
7544            root_tree, subtree, child);
7545 }
7546
7547 /* Note that this is called every time the user clicks on an item,
7548    whether it is already selected or not. */
7549 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
7550                              GtkWidget *subtree)
7551 {
7552   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
7553            root_tree, subtree, child);
7554 }
7555
7556 static void cb_selection_changed (GtkWidget *tree)
7557 {
7558   GList *i;
7559   
7560   g_print ("selection_change called for tree %p\n", tree);
7561   g_print ("selected objects are:\n");
7562
7563   i = GTK_TREE_SELECTION(tree);
7564   while (i){
7565     gchar *name;
7566     GtkLabel *label;
7567     GtkWidget *item;
7568
7569     /* Get a GtkWidget pointer from the list node */
7570     item = GTK_WIDGET (i->data);
7571     label = GTK_LABEL (GTK_BIN (item)->child);
7572     gtk_label_get (label, &amp;name);
7573     g_print ("\t%s on level %d\n", name, GTK_TREE
7574              (item->parent)->level);
7575     i = i->next;
7576   }
7577 }
7578
7579 int main (int argc, char *argv[])
7580 {
7581   GtkWidget *window, *scrolled_win, *tree;
7582   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
7583                                "Maurice"};
7584   gint i;
7585
7586   gtk_init (&amp;argc, &amp;argv);
7587
7588   /* a generic toplevel window */
7589   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7590   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
7591                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
7592   gtk_container_border_width (GTK_CONTAINER(window), 5);
7593
7594   /* A generic scrolled window */
7595   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7596   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7597                                   GTK_POLICY_AUTOMATIC,
7598                                   GTK_POLICY_AUTOMATIC);
7599   gtk_widget_set_usize (scrolled_win, 150, 200);
7600   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
7601   gtk_widget_show (scrolled_win);
7602   
7603   /* Create the root tree */
7604   tree = gtk_tree_new();
7605   g_print ("root tree is %p\n", tree);
7606   /* connect all GtkTree:: signals */
7607   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
7608                       GTK_SIGNAL_FUNC(cb_select_child), tree);
7609   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
7610                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
7611   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
7612                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
7613   /* Add it to the scrolled window */
7614   gtk_container_add (GTK_CONTAINER(scrolled_win), tree);
7615   /* Set the selection mode */
7616   gtk_tree_set_selection_mode (GTK_TREE(tree),
7617                                GTK_SELECTION_MULTIPLE);
7618   /* Show it */
7619   gtk_widget_show (tree);
7620
7621   for (i = 0; i < 5; i++){
7622     GtkWidget *subtree, *item;
7623     gint j;
7624
7625     /* Create a tree item */
7626     item = gtk_tree_item_new_with_label (itemnames[i]);
7627     /* Connect all GtkItem:: and GtkTreeItem:: signals */
7628     gtk_signal_connect (GTK_OBJECT(item), "select",
7629                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
7630     gtk_signal_connect (GTK_OBJECT(item), "deselect",
7631                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
7632     gtk_signal_connect (GTK_OBJECT(item), "toggle",
7633                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
7634     gtk_signal_connect (GTK_OBJECT(item), "expand",
7635                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
7636     gtk_signal_connect (GTK_OBJECT(item), "collapse",
7637                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
7638     /* Add it to the parent tree */
7639     gtk_tree_append (GTK_TREE(tree), item);
7640     /* Show it - this can be done at any time */
7641     gtk_widget_show (item);
7642     /* Create this item's subtree */
7643     subtree = gtk_tree_new();
7644     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
7645              subtree);
7646
7647     /* This is still necessary if you want these signals to be called
7648        for the subtree's children.  Note that selection_change will be 
7649        signalled for the root tree regardless. */
7650     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
7651                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
7652     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
7653                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
7654     /* This has absolutely no effect, because it is completely ignored 
7655        in subtrees */
7656     gtk_tree_set_selection_mode (GTK_TREE(subtree),
7657                                  GTK_SELECTION_SINGLE);
7658     /* Neither does this, but for a rather different reason - the
7659        view_mode and view_line values of a tree are propagated to
7660        subtrees when they are mapped.  So, setting it later on would
7661        actually have a (somewhat unpredictable) effect */
7662     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
7663     /* Set this item's subtree - note that you cannot do this until
7664        AFTER the item has been added to its parent tree! */
7665     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
7666
7667     for (j = 0; j < 5; j++){
7668       GtkWidget *subitem;
7669
7670       /* Create a subtree item, in much the same way */
7671       subitem = gtk_tree_item_new_with_label (itemnames[j]);
7672       /* Connect all GtkItem:: and GtkTreeItem:: signals */
7673       gtk_signal_connect (GTK_OBJECT(subitem), "select",
7674                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
7675       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
7676                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
7677       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
7678                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
7679       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
7680                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
7681       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
7682                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
7683       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
7684       /* Add it to its parent tree */
7685       gtk_tree_append (GTK_TREE(subtree), subitem);
7686       /* Show it */
7687       gtk_widget_show (subitem);
7688     }
7689   }
7690
7691   /* Show the window and loop endlessly */
7692   gtk_widget_show (window);
7693   gtk_main();
7694   return 0;
7695 }
7696 /* example-end */
7697 </verb></tscreen>
7698
7699 <!-- ***************************************************************** -->
7700 <sect>Menu Widget
7701 <!-- ***************************************************************** -->
7702 <p>
7703 There are two ways to create menus, there's the easy way, and there's the
7704 hard way. Both have their uses, but you can usually use the menufactory
7705 (the easy way). The "hard" way is to create all the menus using the calls
7706 directly. The easy way is to use the gtk_menu_factory calls. This is
7707 much simpler, but there are advantages and disadvantages to each approach.
7708
7709 The menufactory is much easier to use, and to add new menus to, although
7710 writing a few wrapper functions to create menus using the manual method 
7711 could go a long way towards usability. With the menufactory, it is not 
7712 possible to add images or the character '/' to the menus.
7713
7714 <!-- ----------------------------------------------------------------- -->
7715 <sect1>Manual Menu Creation
7716 <p>
7717 In the true tradition of teaching, we'll show you the hard
7718 way first. <tt>:)</>
7719
7720 There are three widgets that go into making a menubar and submenus:
7721 <itemize>
7722 <item>a menu item, which is what the user wants to select, e.g. 'Save'
7723 <item>a menu, which acts as a container for the menu items, and
7724 <item>a menubar, which is a container for each of the individual menus,
7725 </itemize>
7726
7727 This is slightly complicated by the fact that menu item widgets are used
7728 for two different things. They are both the widgets that are packed into
7729 the menu, and the widget that is packed into the menubar, which,
7730 when selected, activates the menu.
7731
7732 Let's look at the functions that are used to create menus and menubars.
7733 This first function is used to create a new menubar.
7734
7735 <tscreen><verb>
7736 GtkWidget *gtk_menu_bar_new( void );
7737 </verb></tscreen>
7738
7739 This rather self explanatory function creates a new menubar.  You use
7740 gtk_container_add to pack this into a window, or the box_pack functions to
7741 pack it into a box - the same as buttons.
7742
7743 <tscreen><verb>
7744 GtkWidget *gtk_menu_new( void );
7745 </verb></tscreen>
7746
7747 This function returns a pointer to a new menu, it is never actually shown
7748 (with gtk_widget_show), it is just a container for the menu items.  Hopefully this will
7749 become more clear when you look at the example below.
7750
7751 The next two calls are used to create menu items that are packed into
7752 the menu (and menubar).
7753
7754 <tscreen><verb>
7755 GtkWidget *gtk_menu_item_new( void );
7756 </verb></tscreen>
7757
7758 and
7759
7760 <tscreen><verb>
7761 GtkWidget *gtk_menu_item_new_with_label( const char *label );
7762 </verb></tscreen>
7763
7764 These calls are used to create the menu items that are to be displayed.
7765 Remember to differentiate between a "menu" as created with gtk_menu_new
7766 and a "menu item" as created by the gtk_menu_item_new functions. The
7767 menu item will be an actual button with an associated action,
7768 whereas a menu will be a container holding menu items.
7769
7770 The gtk_menu_new_with_label and gtk_menu_new functions are just as you'd expect after
7771 reading about the buttons. One creates a new menu item with a label
7772 already packed into it, and the other just creates a blank menu item.
7773
7774 Once you've created a menu item you have to put it into a menu. This is 
7775 done using the function gtk_menu_append. In order to capture when the item
7776 is selected by the user, we need to connect to the <tt/activate/ signal in
7777 the usual way. So, if we wanted to create a standard <tt/File/ menu, with
7778 the options <tt/Open/, <tt/Save/ and <tt/Quit/ the code would look something like
7779
7780 <tscreen><verb>
7781 file_menu = gtk_menu_new();    /* Don't need to show menus */
7782
7783 /* Create the menu items */
7784 open_item = gtk_menu_item_new_with_label("Open");
7785 save_item = gtk_menu_item_new_with_label("Save");
7786 quit_item = gtk_menu_item_new_with_label("Quit");
7787
7788 /* Add them to the menu */
7789 gtk_menu_append( GTK_MENU(file_menu), open_item);
7790 gtk_menu_append( GTK_MENU(file_menu), save_item);
7791 gtk_menu_append( GTK_MENU(file_menu), quit_item);
7792
7793 /* Attach the callback functions to the activate signal */
7794 gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
7795                            GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.open");
7796 gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
7797                            GTK_SIGNAL_FUNC(menuitem_response), (gpointer) "file.save");
7798
7799 /* We can attach the Quit menu item to our exit function */
7800 gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
7801                            GTK_SIGNAL_FUNC(destroy), (gpointer) "file.quit");
7802
7803 /* We do need to show menu items */
7804 gtk_widget_show( open_item );
7805 gtk_widget_show( save_item );
7806 gtk_widget_show( quit_item );
7807 </verb></tscreen>
7808
7809 At this point we have our menu. Now we need to create a menubar and a menu
7810 item for the <tt/File/ entry, to which we add our menu. The code looks like this 
7811
7812 <tscreen><verb>
7813 menu_bar = gtk_menu_bar_new();
7814 gtk_container_add( GTK_CONTAINER(window), menu_bar);
7815 gtk_widget_show( menu_bar );
7816
7817 file_item = gtk_menu_item_new_with_label("File");
7818 gtk_widget_show(file_item);
7819 </verb></tscreen>
7820
7821 Now we need to associate the menu with <tt/file_item/. This is done with the
7822 function
7823
7824 <tscreen>
7825 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
7826                                 GtkWidget   *submenu );
7827 </tscreen>
7828
7829 So, our example would continue with
7830
7831 <tscreen><verb>
7832 gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu );
7833 </verb></tscreen>
7834
7835 All that is left to do is to add the menu to the menubar, which is accomplished
7836 using the function
7837
7838 <tscreen>
7839 void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);
7840 </tscreen>
7841
7842 which in our case looks like this:
7843
7844 <tscreen><verb>
7845 gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );
7846 </verb></tscreen>
7847
7848 If we wanted the menu right justified on the menubar, such as help menus
7849 often are, we can use the following function (again on <tt/file_item/
7850 in the current example) before attaching it to the menubar.
7851
7852 <tscreen><verb>
7853 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
7854 </verb></tscreen>
7855
7856 Here is a summary of the steps needed to create a menu bar with menus attached:
7857
7858 <itemize>
7859 <item> Create a new menu using gtk_menu_new()
7860 <item> Use multiple calls to gtk_menu_item_new() for each item you wish to have
7861 on your menu. And use gtk_menu_append() to put each of these new items on 
7862 to the menu.
7863 <item> Create a menu item using gtk_menu_item_new(). This will be the root of
7864 the menu, the text appearing here will be on the menubar itself.
7865 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root menu 
7866 item (the one created in the above step).
7867 <item> Create a new menubar using gtk_menu_bar_new. This step only needs
7868 to be done once when creating a series of menus on one menu bar.
7869 <item> Use gtk_menu_bar_append to put the root menu onto the menubar.
7870 </itemize>
7871
7872 Creating a popup menu is nearly the same. The difference is that the
7873 menu is not posted `automatically' by a menubar, but explicitly by calling
7874 the function gtk_menu_popup() from a button-press event, for example.
7875 Take these steps:
7876
7877 <itemize>
7878 <item>Create an event handling function. It needs to have the prototype
7879 <tscreen>
7880 static gint handler( GtkWidget *widget,
7881                      GdkEvent  *event );
7882 </tscreen>
7883 and it will use the event to find out where to pop up the menu.
7884 <item>In the event handler, if the event is a mouse button press, treat
7885 <tt>event</tt> as a button event (which it is) and use it as
7886 shown in the sample code to pass information to gtk_menu_popup().
7887 <item>Bind that event handler to a widget with
7888 <tscreen>
7889 gtk_signal_connect_object(GTK_OBJECT(widget), "event",
7890                           GTK_SIGNAL_FUNC (handler), GTK_OBJECT(menu));
7891 </tscreen>
7892 where <tt>widget</tt> is the widget you are binding to, <tt>handler</tt>
7893 is the handling function, and <tt>menu</tt> is a menu created with
7894 gtk_menu_new().  This can be a menu which is also posted by a menu bar,
7895 as shown in the sample code.
7896 </itemize>
7897
7898 <!-- ----------------------------------------------------------------- -->
7899 <sect1>Manual Menu Example
7900 <p>
7901 That should about do it.  Let's take a look at an example to help clarify.
7902
7903 <tscreen><verb>
7904 /* example-start menu menu.c */
7905
7906 #include <gtk/gtk.h>
7907
7908 static gint button_press (GtkWidget *, GdkEvent *);
7909 static void menuitem_response (gchar *);
7910
7911 int main (int argc, char *argv[])
7912 {
7913
7914     GtkWidget *window;
7915     GtkWidget *menu;
7916     GtkWidget *menu_bar;
7917     GtkWidget *root_menu;
7918     GtkWidget *menu_items;
7919     GtkWidget *vbox;
7920     GtkWidget *button;
7921     char buf[128];
7922     int i;
7923
7924     gtk_init (&amp;argc, &amp;argv);
7925
7926     /* create a new window */
7927     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
7928     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
7929     gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
7930     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
7931                        (GtkSignalFunc) gtk_main_quit, NULL);
7932
7933     /* Init the menu-widget, and remember -- never
7934      * gtk_show_widget() the menu widget!! 
7935      * This is the menu that holds the menu items, the one that
7936      * will pop up when you click on the "Root Menu" in the app */
7937     menu = gtk_menu_new();
7938
7939     /* Next we make a little loop that makes three menu-entries for "test-menu".
7940      * Notice the call to gtk_menu_append.  Here we are adding a list of
7941      * menu items to our menu.  Normally, we'd also catch the "clicked"
7942      * signal on each of the menu items and setup a callback for it,
7943      * but it's omitted here to save space. */
7944
7945     for(i = 0; i < 3; i++)
7946         {
7947             /* Copy the names to the buf. */
7948             sprintf(buf, "Test-undermenu - %d", i);
7949
7950             /* Create a new menu-item with a name... */
7951             menu_items = gtk_menu_item_new_with_label(buf);
7952
7953             /* ...and add it to the menu. */
7954             gtk_menu_append(GTK_MENU (menu), menu_items);
7955
7956             /* Do something interesting when the menuitem is selected */
7957             gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
7958                 GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf));
7959
7960             /* Show the widget */
7961             gtk_widget_show(menu_items);
7962         }
7963
7964     /* This is the root menu, and will be the label
7965      * displayed on the menu bar.  There won't be a signal handler attached,
7966      * as it only pops up the rest of the menu when pressed. */
7967     root_menu = gtk_menu_item_new_with_label("Root Menu");
7968
7969     gtk_widget_show(root_menu);
7970
7971     /* Now we specify that we want our newly created "menu" to be the menu
7972      * for the "root menu" */
7973     gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
7974
7975     /* A vbox to put a menu and a button in: */
7976     vbox = gtk_vbox_new(FALSE, 0);
7977     gtk_container_add(GTK_CONTAINER(window), vbox);
7978     gtk_widget_show(vbox);
7979
7980     /* Create a menu-bar to hold the menus and add it to our main window */
7981     menu_bar = gtk_menu_bar_new();
7982     gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
7983     gtk_widget_show(menu_bar);
7984
7985     /* Create a button to which to attach menu as a popup */
7986     button = gtk_button_new_with_label("press me");
7987     gtk_signal_connect_object(GTK_OBJECT(button), "event",
7988         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
7989     gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
7990     gtk_widget_show(button);
7991
7992     /* And finally we append the menu-item to the menu-bar -- this is the
7993      * "root" menu-item I have been raving about =) */
7994     gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
7995
7996     /* always display the window as the last step so it all splashes on
7997      * the screen at once. */
7998     gtk_widget_show(window);
7999
8000     gtk_main ();
8001
8002     return 0;
8003 }
8004
8005 /* Respond to a button-press by posting a menu passed in as widget.
8006  *
8007  * Note that the "widget" argument is the menu being posted, NOT
8008  * the button that was pressed.
8009  */
8010
8011 static gint button_press (GtkWidget *widget, GdkEvent *event)
8012 {
8013
8014     if (event->type == GDK_BUTTON_PRESS) {
8015         GdkEventButton *bevent = (GdkEventButton *) event; 
8016         gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
8017                         bevent->button, bevent->time);
8018         /* Tell calling code that we have handled this event; the buck
8019          * stops here. */
8020         return TRUE;
8021     }
8022
8023     /* Tell calling code that we have not handled this event; pass it on. */
8024     return FALSE;
8025 }
8026
8027
8028 /* Print a string when a menu item is selected */
8029
8030 static void menuitem_response (gchar *string)
8031 {
8032     printf("%s\n", string);
8033 }
8034 /* example-end */
8035 </verb></tscreen>
8036
8037 You may also set a menu item to be insensitive and, using an accelerator
8038 table, bind keys to menu functions.
8039
8040 <!-- ----------------------------------------------------------------- -->
8041 <sect1>Using GtkMenuFactory
8042 <p>
8043 Now that we've shown you the hard way, here's how you do it using the
8044 gtk_menu_factory calls.
8045
8046 <!-- ----------------------------------------------------------------- -->
8047 <sect1>Menu Factory Example
8048 <p>
8049 Here is an example using the GTK menu factory.  This is the first file,
8050 menufactory.h.  We keep a separate menufactory.c and mfmain.c because
8051 of the global variables used in the menufactory.c file.  
8052
8053 <tscreen><verb>
8054 /* example-start menu menufactory.h */
8055
8056 #ifndef __MENUFACTORY_H__
8057 #define __MENUFACTORY_H__
8058
8059 #ifdef __cplusplus
8060 extern "C" {
8061 #endif /* __cplusplus */
8062
8063 void get_main_menu (GtkWidget *, GtkWidget **menubar);
8064
8065 #ifdef __cplusplus
8066 }
8067 #endif /* __cplusplus */
8068
8069 #endif /* __MENUFACTORY_H__ */
8070
8071 /* example-end */
8072 </verb></tscreen>
8073
8074 And here is the menufactory.c file.
8075
8076 <tscreen><verb>
8077 /* example-start menu menufactory.c */
8078
8079 #include <gtk/gtk.h>
8080 #include <strings.h>
8081
8082 #include "mfmain.h"
8083
8084 static void print_hello(GtkWidget *widget, gpointer data);
8085
8086
8087 /* this is the GtkMenuEntry structure used to create new menus.  The
8088  * first member is the menu definition string.  The second, the
8089  * default accelerator key used to access this menu function with
8090  * the keyboard.  The third is the callback function to call when
8091  * this menu item is selected (by the accelerator key, or with the
8092  * mouse.) The last member is the data to pass to your callback function.
8093  */
8094
8095 static GtkMenuEntry menu_items[] =
8096 {
8097     {"<Main>/File/New", "<control>N", print_hello, NULL},
8098     {"<Main>/File/Open", "<control>O", print_hello, NULL},
8099     {"<Main>/File/Save", "<control>S", print_hello, NULL},
8100     {"<Main>/File/Save as", NULL, NULL, NULL},
8101     {"<Main>/File/<separator>", NULL, NULL, NULL},
8102     {"<Main>/File/Quit", "<control>Q", file_quit_cmd_callback, "OK, I'll quit"},
8103     {"<Main>/Options/Test", NULL, NULL, NULL}
8104 };
8105
8106
8107 static void
8108 print_hello(GtkWidget *widget, gpointer data)
8109 {
8110     printf("hello!\n");
8111 }
8112
8113 void get_main_menu(GtkWidget *window, GtkWidget ** menubar)
8114 {
8115     int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
8116     GtkMenuFactory *factory;
8117     GtkMenuFactory *subfactory;
8118
8119     factory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
8120     subfactory = gtk_menu_factory_new(GTK_MENU_FACTORY_MENU_BAR);
8121
8122     gtk_menu_factory_add_subfactory(factory, subfactory, "<Main>");
8123     gtk_menu_factory_add_entries(factory, menu_items, nmenu_items);
8124     gtk_window_add_accelerator_table(GTK_WINDOW(window), subfactory->table);
8125     
8126     if (menubar)
8127         *menubar = subfactory->widget;
8128 }
8129
8130 /* example-end */
8131 </verb></tscreen>
8132
8133 And here's the mfmain.h
8134
8135 <tscreen><verb>
8136 /* example-start menu mfmain.h */
8137
8138 #ifndef __MFMAIN_H__
8139 #define __MFMAIN_H__
8140
8141
8142 #ifdef __cplusplus
8143 extern "C" {
8144 #endif /* __cplusplus */
8145
8146 void file_quit_cmd_callback(GtkWidget *widget, gpointer data);
8147
8148 #ifdef __cplusplus
8149 }
8150 #endif /* __cplusplus */
8151
8152 #endif /* __MFMAIN_H__ */
8153
8154 /* example-end */
8155 </verb></tscreen>
8156
8157 And mfmain.c
8158
8159 <tscreen><verb>
8160 /* example-start menu mfmain.c */
8161
8162 #include <gtk/gtk.h>
8163
8164 #include "mfmain.h"
8165 #include "menufactory.h"
8166
8167 int main(int argc, char *argv[])
8168 {
8169     GtkWidget *window;
8170     GtkWidget *main_vbox;
8171     GtkWidget *menubar;
8172     
8173     gtk_init(&amp;argc, &amp;argv);
8174     
8175     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
8176     gtk_signal_connect(GTK_OBJECT(window), "destroy", 
8177                        GTK_SIGNAL_FUNC(file_quit_cmd_callback), 
8178                        "WM destroy");
8179     gtk_window_set_title(GTK_WINDOW(window), "Menu Factory");
8180     gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);
8181     
8182     main_vbox = gtk_vbox_new(FALSE, 1);
8183     gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
8184     gtk_container_add(GTK_CONTAINER(window), main_vbox);
8185     gtk_widget_show(main_vbox);
8186     
8187     get_main_menu(window, &amp;menubar);
8188     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
8189     gtk_widget_show(menubar);
8190     
8191     gtk_widget_show(window);
8192     gtk_main();
8193     
8194     return(0);
8195 }
8196
8197 /* This is just to demonstrate how callbacks work when using the
8198  * menufactory.  Often, people put all the callbacks from the menus
8199  * in a separate file, and then have them call the appropriate functions
8200  * from there.  Keeps it more organized. */
8201 void file_quit_cmd_callback (GtkWidget *widget, gpointer data)
8202 {
8203     g_print ("%s\n", (char *) data);
8204     gtk_exit(0);
8205 }
8206
8207 /* example-end */
8208 </verb></tscreen>
8209
8210 And a makefile so it'll be easier to compile it.
8211
8212 <tscreen><verb>
8213 # Makefile.mf
8214
8215 CC      = gcc
8216 PROF    = -g
8217 C_FLAGS =  -Wall $(PROF) -L/usr/local/include -DDEBUG
8218 L_FLAGS =  $(PROF) -L/usr/X11R6/lib -L/usr/local/lib 
8219 L_POSTFLAGS = -lgtk -lgdk -lglib -lXext -lX11 -lm
8220 PROGNAME = menufactory
8221
8222 O_FILES = menufactory.o mfmain.o
8223
8224 $(PROGNAME): $(O_FILES)
8225         rm -f $(PROGNAME)
8226         $(CC) $(L_FLAGS) -o $(PROGNAME) $(O_FILES) $(L_POSTFLAGS)
8227
8228 .c.o: 
8229         $(CC) -c $(C_FLAGS) $<
8230
8231 clean: 
8232         rm -f core *.o $(PROGNAME) nohup.out
8233 distclean: clean 
8234         rm -f *~
8235 </verb></tscreen>
8236
8237 For now, there's only this example.  An explanation and lots 'o' comments
8238 will follow later.
8239
8240 <!-- ***************************************************************** -->
8241 <sect> Text Widget
8242 <!-- ***************************************************************** -->
8243 <p>
8244 The Text widget allows multiple lines of text to be displayed and edited.
8245 It supports both multi-colored and multi-font text, allowing them to be
8246 mixed in any way we wish. It also has a wide set of key based text editing
8247 commands, which are compatible with Emacs.
8248
8249 The text widget supports full cut-and-paste facilities, including the use
8250 of double- and triple-click to select a word and a whole line, respectively.
8251
8252 <!-- ----------------------------------------------------------------- -->
8253 <sect1>Creating and Configuring a Text box
8254 <p>
8255 There is only one function for creating a new Text widget.
8256 <tscreen><verb>
8257 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
8258                          GtkAdjustment *vadj );
8259 </verb></tscreen>
8260
8261 The arguments allow us to give the Text widget pointers to Adjustments
8262 that can be used to track the viewing position of the widget. Passing NULL
8263 values to either or both of these arguments will cause the gtk_text_new
8264 function to create its own.
8265
8266 <tscreen><verb>
8267 void gtk_text_set_adjustments( GtkText       *text,
8268                                GtkAdjustment *hadj,
8269                                GtkAdjustment *vadj );
8270 </verb></tscreen>
8271
8272 The above function allows the horizontal and vertical adjustments of a
8273 Text widget to be changed at any time.
8274
8275 The text widget will not automatically create its own scrollbars when
8276 the amount of text to be displayed is too long for the display window. We
8277 therefore have to create and add them to the display layout ourselves.
8278
8279 <tscreen><verb>
8280   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
8281   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
8282   gtk_widget_show (vscrollbar);
8283 </verb></tscreen>
8284
8285 The above code snippet creates a new vertical scrollbar, and attaches
8286 it to the vertical adjustment of the text widget, <tt/text/. It then packs
8287 it into a box in the normal way.
8288
8289 Note, currently the GtkText widget does not support horizontal scrollbars.
8290
8291 There are two main ways in which a Text widget can be used: to allow the
8292 user to edit a body of text, or to allow us to display multiple lines of
8293 text to the user. In order for us to switch between these modes of
8294 operation, the text widget has the following function:
8295
8296 <tscreen><verb>
8297 void gtk_text_set_editable( GtkText *text,
8298                             gint     editable );
8299 </verb></tscreen>
8300
8301 The <tt/editable/ argument is a TRUE or FALSE value that specifies whether
8302 the user is permitted to edit the contents of the Text widget. When the
8303 text widget is editable, it will display a cursor at the current insertion
8304 point.
8305
8306 You are not, however, restricted to just using the text widget in these
8307 two modes. You can toggle the editable state of the text widget at any
8308 time, and can insert text at any time.
8309
8310 The text widget wraps lines of text that are too long to
8311 fit onto a single line of the display window. Its default behaviour is
8312 to break words across line breaks. This can be changed using the next
8313 function:
8314
8315 <tscreen><verb>
8316 void gtk_text_set_word_wrap( GtkText *text,
8317                              gint     word_wrap );
8318 </verb></tscreen>
8319
8320 Using this function allows us to specify that the text widget should
8321 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
8322 TRUE or FALSE value.
8323
8324 <!-- ----------------------------------------------------------------- -->
8325 <sect1>Text Manipulation
8326 <P>
8327 The current insertion point of a Text widget can be set using
8328 <tscreen><verb>
8329 void gtk_text_set_point( GtkText *text,
8330                          guint    index );
8331 </verb></tscreen>
8332
8333 where <tt/index/ is the position to set the insertion point.
8334
8335 Analogous to this is the function for getting the current insertion point:
8336
8337 <tscreen><verb>
8338 guint gtk_text_get_point( GtkText *text );
8339 </verb></tscreen>
8340
8341 A function that is useful in combination with the above two functions is
8342
8343 <tscreen><verb>
8344 guint gtk_text_get_length( GtkText *text );
8345 </verb></tscreen>
8346
8347 which returns the current length of the Text widget. The length is the
8348 number of characters that are within the text block of the widget,
8349 including characters such as carriage-return, which marks the end of lines.
8350
8351 In order to insert text at the current insertion point of a Text
8352 widget, the function gtk_text_insert is used, which also allows us to
8353 specify background and foreground colors and a font for the text.
8354
8355 <tscreen><verb>
8356 void gtk_text_insert( GtkText    *text,
8357                       GdkFont    *font,
8358                       GdkColor   *fore,
8359                       GdkColor   *back,
8360                       const char *chars,
8361                       gint        length );
8362 </verb></tscreen>
8363
8364 Passing a value of <tt/NULL/ in as the value for the foreground color,
8365 background colour or font will result in the values set within the widget
8366 style to be used. Using a value of <tt/-1/ for the length parameter will
8367 result in the whole of the text string given being inserted.
8368
8369 The text widget is one of the few within GTK that redraws itself
8370 dynamically, outside of the gtk_main function. This means that all changes
8371 to the contents of the text widget take effect immediately. This may be
8372 undesirable when performing multiple changes to the text widget. In order
8373 to allow us to perform multiple updates to the text widget without it
8374 continuously redrawing, we can freeze the widget, which temporarily stops
8375 it from automatically redrawing itself every time it is changed. We can
8376 then thaw the widget after our updates are complete.
8377
8378 The following two functions perform this freeze and thaw action:
8379
8380 <tscreen><verb>
8381 void gtk_text_freeze( GtkText *text );
8382
8383 void gtk_text_thaw( GtkText *text );         
8384 </verb></tscreen>
8385
8386 Text is deleted from the text widget relative to the current insertion
8387 point by the following two functions. The return value is a TRUE or
8388 FALSE indicator of whether the operation was successful.
8389
8390 <tscreen><verb>
8391 gint gtk_text_backward_delete( GtkText *text,
8392                                guint    nchars );
8393
8394 gint gtk_text_forward_delete ( GtkText *text,
8395                                guint    nchars );
8396 </verb></tscreen>
8397
8398 If you want to retrieve the contents of the text widget, then the macro 
8399 <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the character at
8400 position <tt/index/ within the text widget <tt/t/.
8401
8402 To retrieve larger blocks of text, we can use the function
8403
8404 <tscreen><verb>
8405 gchar *gtk_editable_get_chars( GtkEditable *editable,
8406                                gint         start_pos,
8407                                gint         end_pos );   
8408 </verb></tscreen>
8409
8410 This is a function of the parent class of the text widget. A value of -1 as
8411 <tt/end_pos/ signifies the end of the text. The index of the text starts at 0.
8412
8413 The function allocates a new chunk of memory for the text block, so don't forget
8414 to free it with a call to g_free when you have finished with it.
8415  
8416 <!-- ----------------------------------------------------------------- -->
8417 <sect1>Keyboard Shortcuts
8418 <p>
8419 The text widget has a number of pre-installed keyboard shortcuts for common
8420 editing, motion and selection functions. These are accessed using Control
8421 and Alt key combinations.
8422
8423 In addition to these, holding down the Control key whilst using cursor key
8424 movement will move the cursor by words rather than characters. Holding down
8425 Shift whilst using cursor movement will extend the selection.
8426
8427 <sect2>Motion Shortcuts
8428 <p>
8429 <itemize>
8430 <item> Ctrl-A   Beginning of line
8431 <item> Ctrl-E   End of line
8432 <item> Ctrl-N   Next Line
8433 <item> Ctrl-P   Previous Line
8434 <item> Ctrl-B   Backward one character
8435 <item> Ctrl-F   Forward one character
8436 <item> Alt-B    Backward one word
8437 <item> Alt-F    Forward one word
8438 </itemize>
8439
8440 <sect2>Editing Shortcuts
8441 <p>
8442 <itemize>
8443 <item> Ctrl-H   Delete Backward Character (Backspace)
8444 <item> Ctrl-D   Delete Forward Character (Delete)
8445 <item> Ctrl-W   Delete Backward Word
8446 <item> Alt-D    Delete Forward Word
8447 <item> Ctrl-K   Delete to end of line
8448 <item> Ctrl-U   Delete line
8449 </itemize>
8450
8451 <sect2>Selection Shortcuts
8452 <p>
8453 <itemize>
8454 <item> Ctrl-X   Cut to clipboard
8455 <item> Ctrl-C   Copy to clipboard
8456 <item> Ctrl-V   Paste from clipboard
8457 </itemize>
8458
8459 <!-- ----------------------------------------------------------------- -->
8460 <sect1>A GtkText Example
8461 <p>
8462 <tscreen><verb>
8463 /* example-start text text.c */
8464
8465 /* text.c */
8466
8467 #include <stdio.h>
8468 #include <gtk/gtk.h>
8469
8470 void text_toggle_editable (GtkWidget *checkbutton,
8471                            GtkWidget *text)
8472 {
8473   gtk_text_set_editable(GTK_TEXT(text),
8474                         GTK_TOGGLE_BUTTON(checkbutton)->active);
8475 }
8476
8477 void text_toggle_word_wrap (GtkWidget *checkbutton,
8478                             GtkWidget *text)
8479 {
8480   gtk_text_set_word_wrap(GTK_TEXT(text),
8481                          GTK_TOGGLE_BUTTON(checkbutton)->active);
8482 }
8483
8484 void close_application( GtkWidget *widget, gpointer data )
8485 {
8486        gtk_main_quit();
8487 }
8488
8489 int main (int argc, char *argv[])
8490 {
8491   GtkWidget *window;
8492   GtkWidget *box1;
8493   GtkWidget *box2;
8494   GtkWidget *hbox;
8495   GtkWidget *button;
8496   GtkWidget *check;
8497   GtkWidget *separator;
8498   GtkWidget *table;
8499   GtkWidget *vscrollbar;
8500   GtkWidget *text;
8501   GdkColormap *cmap;
8502   GdkColor colour;
8503   GdkFont *fixed_font;
8504
8505   FILE *infile;
8506
8507   gtk_init (&amp;argc, &amp;argv);
8508  
8509   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8510   gtk_widget_set_usize (window, 600, 500);
8511   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
8512   gtk_signal_connect (GTK_OBJECT (window), "destroy",
8513                       GTK_SIGNAL_FUNC(close_application),
8514                       NULL);
8515   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
8516   gtk_container_border_width (GTK_CONTAINER (window), 0);
8517   
8518   
8519   box1 = gtk_vbox_new (FALSE, 0);
8520   gtk_container_add (GTK_CONTAINER (window), box1);
8521   gtk_widget_show (box1);
8522   
8523   
8524   box2 = gtk_vbox_new (FALSE, 10);
8525   gtk_container_border_width (GTK_CONTAINER (box2), 10);
8526   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
8527   gtk_widget_show (box2);
8528   
8529   
8530   table = gtk_table_new (2, 2, FALSE);
8531   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
8532   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
8533   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
8534   gtk_widget_show (table);
8535   
8536   /* Create the GtkText widget */
8537   text = gtk_text_new (NULL, NULL);
8538   gtk_text_set_editable (GTK_TEXT (text), TRUE);
8539   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
8540                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
8541                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
8542   gtk_widget_show (text);
8543
8544   /* Add a vertical scrollbar to the GtkText widget */
8545   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
8546   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
8547                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
8548   gtk_widget_show (vscrollbar);
8549
8550   /* Get the system colour map and allocate the colour red */
8551   cmap = gdk_colormap_get_system();
8552   colour.red = 0xffff;
8553   colour.green = 0;
8554   colour.blue = 0;
8555   if (!gdk_color_alloc(cmap, &amp;colour)) {
8556     g_error("couldn't allocate colour");
8557   }
8558
8559   /* Load a fixed font */
8560   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
8561
8562   /* Realizing a widget creates a window for it, ready for us to insert some text */
8563   gtk_widget_realize (text);
8564
8565   /* Freeze the text widget, ready for multiple updates */
8566   gtk_text_freeze (GTK_TEXT (text));
8567   
8568   /* Insert some coloured text */
8569   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
8570                    "Supports ", -1);
8571   gtk_text_insert (GTK_TEXT (text), NULL, &amp;colour, NULL,
8572                    "colored ", -1);
8573   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
8574                    "text and different ", -1);
8575   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
8576                    "fonts\n\n", -1);
8577   
8578   /* Load the file text.c into the text window */
8579
8580   infile = fopen("text.c", "r");
8581   
8582   if (infile) {
8583     char buffer[1024];
8584     int nchars;
8585     
8586     while (1)
8587       {
8588         nchars = fread(buffer, 1, 1024, infile);
8589         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
8590                          NULL, buffer, nchars);
8591         
8592         if (nchars < 1024)
8593           break;
8594       }
8595     
8596     fclose (infile);
8597   }
8598
8599   /* Thaw the text widget, allowing the updates to become visible */  
8600   gtk_text_thaw (GTK_TEXT (text));
8601   
8602   hbox = gtk_hbutton_box_new ();
8603   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
8604   gtk_widget_show (hbox);
8605
8606   check = gtk_check_button_new_with_label("Editable");
8607   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
8608   gtk_signal_connect (GTK_OBJECT(check), "toggled",
8609                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
8610   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
8611   gtk_widget_show (check);
8612   check = gtk_check_button_new_with_label("Wrap Words");
8613   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
8614   gtk_signal_connect (GTK_OBJECT(check), "toggled",
8615                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
8616   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE);
8617   gtk_widget_show (check);
8618
8619   separator = gtk_hseparator_new ();
8620   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
8621   gtk_widget_show (separator);
8622
8623   box2 = gtk_vbox_new (FALSE, 10);
8624   gtk_container_border_width (GTK_CONTAINER (box2), 10);
8625   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
8626   gtk_widget_show (box2);
8627   
8628   button = gtk_button_new_with_label ("close");
8629   gtk_signal_connect (GTK_OBJECT (button), "clicked",
8630                       GTK_SIGNAL_FUNC(close_application),
8631                       NULL);
8632   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8633   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8634   gtk_widget_grab_default (button);
8635   gtk_widget_show (button);
8636
8637   gtk_widget_show (window);
8638
8639   gtk_main ();
8640   
8641   return 0;       
8642 }
8643 /* example-end */
8644 </verb></tscreen>
8645
8646
8647 <!-- ***************************************************************** -->
8648 <sect> Undocumented Widgets
8649 <!-- ***************************************************************** -->
8650 <p>
8651 These all require authors! :)  Please consider contributing to our tutorial.
8652
8653 If you must use one of these widgets that are undocumented, I strongly
8654 suggest you take a look at their respective header files in the GTK
8655 distribution. GTK's function names are very descriptive.  Once you have an
8656 understanding of how things work, it's not difficult to figure out how to
8657 use a widget simply by looking at its function declarations.  This, along
8658 with a few examples from others' code, and it should be no problem.
8659
8660 When you do come to understand all the functions of a new undocumented
8661 widget, please consider writing a tutorial on it so others may benefit
8662 from your time.
8663
8664 <!-- ----------------------------------------------------------------- -->
8665 <sect1> Fixed Container
8666 <p>
8667 <!-- ----------------------------------------------------------------- -->
8668 <sect1> Curves
8669 <p>
8670 <!-- ----------------------------------------------------------------- -->
8671 <sect1> Previews
8672 <p>
8673
8674 (This may need to be rewritten to follow the style of the rest of the tutorial)
8675
8676 <tscreen><verb>
8677
8678 Previews serve a number of purposes in GIMP/GTK. The most important one is
8679 this. High quality images may take up to tens of megabytes of memory - easy!
8680 Any operation on an image that big is bound to take a long time. If it takes
8681 you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after
8682 you make an error) to choose the desired modification, it make take you
8683 literally hours to make the right one - if you don't run out of memory
8684 first. People who have spent hours in color darkrooms know the feeling.
8685 Previews to the rescue!
8686
8687 But the annoyance of the delay is not the only issue. Oftentimes it is
8688 helpful to compare the Before and After versions side-by-side or at least
8689 back-to-back. If you're working with big images and 10 second delays,
8690 obtaining the Before and After impressions is, to say the least, difficult.
8691 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
8692 out for most people, while back-to-back is more like back-to-1001, 1002,
8693 ..., 1010-back! Previews to the rescue!
8694
8695 But there's more. Previews allow for side-by-side pre-previews. In other
8696 words, you write a plug-in (e.g. the filterpack simulation) which would have
8697 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
8698 An approach like this acts as a sort of a preview palette and is very
8699 effective for subtle changes. Let's go previews!
8700
8701 There's more. For certain plug-ins real-time image-specific human
8702 intervention maybe necessary. In the SuperNova plug-in, for example, the
8703 user is asked to enter the coordinates of the center of the future
8704 supernova. The easiest way to do this, really, is to present the user with a
8705 preview and ask him to interactively select the spot. Let's go previews!
8706
8707 Finally, a couple of misc uses. One can use previews even when not working
8708 with big images. For example, they are useful when rendering complicated
8709 patterns. (Just check out the venerable Diffraction plug-in + many other
8710 ones!) As another example, take a look at the colormap rotation plug-in
8711 (work in progress). You can also use previews for little logos inside you
8712 plug-ins and even for an image of yourself, The Author. Let's go previews!
8713
8714 When Not to Use Previews
8715
8716 Don't use previews for graphs, drawing etc. GDK is much faster for that. Use
8717 previews only for rendered images!
8718
8719 Let's go previews!
8720
8721 You can stick a preview into just about anything. In a vbox, an hbox, a
8722 table, a button, etc. But they look their best in tight frames around them.
8723 Previews by themselves do not have borders and look flat without them. (Of
8724 course, if the flat look is what you want...) Tight frames provide the
8725 necessary borders.
8726
8727                                [Image][Image]
8728
8729 Previews in many ways are like any other widgets in GTK (whatever that
8730 means) except they possess an additional feature: they need to be filled with
8731 some sort of an image! First, we will deal exclusively with the GTK aspect
8732 of previews and then we'll discuss how to fill them.
8733
8734 GtkWidget *preview!
8735
8736 Without any ado:
8737
8738                               /* Create a preview widget,
8739                               set its size, an show it */
8740 GtkWidget *preview;
8741 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
8742                               /*Other option:
8743                               GTK_PREVIEW_GRAYSCALE);*/
8744 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
8745 gtk_widget_show(preview);
8746 my_preview_rendering_function(preview);
8747
8748 Oh yeah, like I said, previews look good inside frames, so how about:
8749
8750 GtkWidget *create_a_preview(int        Width,
8751                             int        Height,
8752                             int        Colorfulness)
8753 {
8754   GtkWidget *preview;
8755   GtkWidget *frame;
8756   
8757   frame = gtk_frame_new(NULL);
8758   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8759   gtk_container_border_width (GTK_CONTAINER(frame),0);
8760   gtk_widget_show(frame);
8761
8762   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
8763                                        :GTK_PREVIEW_GRAYSCALE);
8764   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
8765   gtk_container_add(GTK_CONTAINER(frame),preview);
8766   gtk_widget_show(preview);
8767
8768   my_preview_rendering_function(preview);
8769   return frame;
8770 }
8771
8772 That's my basic preview. This routine returns the "parent" frame so you can
8773 place it somewhere else in your interface. Of course, you can pass the
8774 parent frame to this routine as a parameter. In many situations, however,
8775 the contents of the preview are changed continually by your application. In
8776 this case you may want to pass a pointer to the preview to a
8777 "create_a_preview()" and thus have control of it later.
8778
8779 One more important note that may one day save you a lot of time. Sometimes
8780 it is desirable to label you preview. For example, you may label the preview
8781 containing the original image as "Original" and the one containing the
8782 modified image as "Less Original". It might occur to you to pack the
8783 preview along with the appropriate label into a vbox. The unexpected caveat
8784 is that if the label is wider than the preview (which may happen for a
8785 variety of reasons unforseeable to you, from the dynamic decision on the
8786 size of the preview to the size of the font) the frame expands and no longer
8787 fits tightly over the preview. The same problem can probably arise in other
8788 situations as well.
8789
8790                                    [Image]
8791
8792 The solution is to place the preview and the label into a 2x1 table and by
8793 attaching them with the following parameters (this is one possible variations
8794 of course. The key is no GTK_FILL in the second attachment):
8795
8796 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
8797                  0,
8798                  GTK_EXPAND|GTK_FILL,
8799                  0,0);
8800 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
8801                  GTK_EXPAND,
8802                  GTK_EXPAND,
8803                  0,0);
8804
8805
8806 And here's the result:
8807
8808                                    [Image]
8809
8810 Misc
8811
8812 Making a preview clickable is achieved most easily by placing it in a
8813 button. It also adds a nice border around the preview and you may not even
8814 need to place it in a frame. See the Filter Pack Simulation plug-in for an
8815 example.
8816
8817 This is pretty much it as far as GTK is concerned.
8818
8819 Filling In a Preview
8820
8821 In order to familiarize ourselves with the basics of filling in previews,
8822 let's create the following pattern (contrived by trial and error):
8823
8824                                    [Image]
8825
8826 void
8827 my_preview_rendering_function(GtkWidget     *preview)
8828 {
8829 #define SIZE 100
8830 #define HALF (SIZE/2)
8831
8832   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
8833   gint i, j;                             /* Coordinates    */
8834   double r, alpha, x, y;
8835
8836   if (preview==NULL) return; /* I usually add this when I want */
8837                              /* to avoid silly crashes. You    */
8838                              /* should probably make sure that */
8839                              /* everything has been nicely     */
8840                              /* initialized!                   */
8841   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
8842                                          /* glib.h contains ABS(x).   */
8843         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
8844         row[i*3+1] = 128;                /* Define Green              */
8845         row[i*3+2] = 224;                /* Define Blue               */
8846       }                                  /* "+0" is for alignment!    */
8847       else {
8848         row[i*3+0] = r*255;
8849         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
8850         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
8851       }
8852     }
8853     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
8854     /* Insert "row" into "preview" starting at the point with  */
8855     /* coordinates (0,j) first column, j_th row extending SIZE */
8856     /* pixels to the right */
8857   }
8858
8859   free(row); /* save some space */
8860   gtk_widget_draw(preview,NULL); /* what does this do? */
8861   gdk_flush(); /* or this? */
8862 }
8863
8864 Non-GIMP users can have probably seen enough to do a lot of things already.
8865 For the GIMP users I have a few pointers to add.
8866
8867 Image Preview
8868
8869 It is probably wise to keep a reduced version of the image around with just
8870 enough pixels to fill the preview. This is done by selecting every n'th
8871 pixel where n is the ratio of the size of the image to the size of the
8872 preview. All further operations (including filling in the previews) are then
8873 performed on the reduced number of pixels only. The following is my
8874 implementation of reducing the image. (Keep in mind that I've had only basic
8875 C!)
8876
8877 (UNTESTED CODE ALERT!!!)
8878
8879 typedef struct {
8880   gint      width;
8881   gint      height;
8882   gint      bbp;
8883   guchar    *rgb;
8884   guchar    *mask;
8885 } ReducedImage;
8886
8887 enum {
8888   SELECTION_ONLY,
8889   SELECTION_IN_CONTEXT,
8890   ENTIRE_IMAGE
8891 };
8892
8893 ReducedImage *Reduce_The_Image(GDrawable *drawable,
8894                                GDrawable *mask,
8895                                gint LongerSize,
8896                                gint Selection)
8897 {
8898   /* This function reduced the image down to the the selected preview size */
8899   /* The preview size is determine by LongerSize, i.e. the greater of the  */
8900   /* two dimensions. Works for RGB images only!                            */
8901   gint RH, RW;          /* Reduced height and reduced width                */
8902   gint width, height;   /* Width and Height of the area being reduced      */
8903   gint bytes=drawable->bpp;
8904   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
8905
8906   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
8907   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
8908   GPixelRgn srcPR, srcMask;
8909   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
8910                              /* image.                                     */
8911
8912   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
8913   width  = x2-x1;
8914   height = y2-y1;
8915   /* If there's a SELECTION, we got its bounds!)
8916
8917   if (width != drawable->width &amp;&amp; height != drawable->height)
8918     NoSelectionMade=FALSE;
8919   /* Become aware of whether the user has made an active selection   */
8920   /* This will become important later, when creating a reduced mask. */
8921
8922   /* If we want to preview the entire image, overrule the above!  */
8923   /* Of course, if no selection has been made, this does nothing! */
8924   if (Selection==ENTIRE_IMAGE) {
8925     x1=0;
8926     x2=drawable->width;
8927     y1=0;
8928     y2=drawable->height;
8929   }
8930
8931   /* If we want to preview a selection with some surrounding area we */
8932   /* have to expand it a little bit. Consider it a bit of a riddle. */
8933   if (Selection==SELECTION_IN_CONTEXT) {
8934     x1=MAX(0,                x1-width/2.0);
8935     x2=MIN(drawable->width,  x2+width/2.0);
8936     y1=MAX(0,                y1-height/2.0);
8937     y2=MIN(drawable->height, y2+height/2.0);
8938   }
8939
8940   /* How we can determine the width and the height of the area being */
8941   /* reduced.                                                        */
8942   width  = x2-x1;
8943   height = y2-y1;
8944
8945   /* The lines below determine which dimension is to be the longer   */
8946   /* side. The idea borrowed from the supernova plug-in. I suspect I */
8947   /* could've thought of it myself, but the truth must be told.      */
8948   /* Plagiarism stinks!                                               */
8949   if (width>height) {
8950     RW=LongerSize;
8951     RH=(float) height * (float) LongerSize/ (float) width;
8952   }
8953   else {
8954     RH=LongerSize;
8955     RW=(float)width * (float) LongerSize/ (float) height;
8956   }
8957
8958   /* The entire image is stretched into a string! */
8959   tempRGB   = (guchar *) malloc(RW*RH*bytes);
8960   tempmask  = (guchar *) malloc(RW*RH);
8961
8962   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height, FALSE, FALSE);
8963   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height, FALSE, FALSE);
8964
8965   /* Grab enough to save a row of image and a row of mask. */
8966   src_row       = (guchar *) malloc (width*bytes);
8967   src_mask_row  = (guchar *) malloc (width);
8968
8969   for (i=0; i < RH; i++) {
8970     whichrow=(float)i*(float)height/(float)RH;
8971     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
8972     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
8973
8974     for (j=0; j < RW; j++) {
8975       whichcol=(float)j*(float)width/(float)RW;
8976
8977       /* No selection made = each point is completely selected! */
8978       if (NoSelectionMade)
8979         tempmask[i*RW+j]=255;
8980       else
8981         tempmask[i*RW+j]=src_mask_row[whichcol];
8982
8983       /* Add the row to the one long string which now contains the image! */
8984       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
8985       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
8986       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
8987
8988       /* Hold on to the alpha as well */
8989       if (bytes==4)
8990         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
8991     }
8992   }
8993   temp->bpp=bytes;
8994   temp->width=RW;
8995   temp->height=RH;
8996   temp->rgb=tempRGB;
8997   temp->mask=tempmask;
8998   return temp;
8999 }
9000
9001 The following is a preview function which used the same ReducedImage type!
9002 Note that it uses fakes transparency (if one is present by means of
9003 fake_transparency which is defined as follows:
9004
9005 gint fake_transparency(gint i, gint j)
9006 {
9007   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
9008     return 64;
9009   else
9010     return 196;
9011 }
9012
9013 Now here's the preview function:
9014
9015 void
9016 my_preview_render_function(GtkWidget     *preview,
9017                            gint          changewhat,
9018                            gint          changewhich)
9019 {
9020   gint Inten, bytes=drawable->bpp;
9021   gint i, j, k;
9022   float partial;
9023   gint RW=reduced->width;
9024   gint RH=reduced->height;
9025   guchar *row=malloc(bytes*RW);;
9026
9027
9028   for (i=0; i < RH; i++) {
9029     for (j=0; j < RW; j++) {
9030
9031       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
9032       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
9033       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
9034
9035       if (bytes==4)
9036         for (k=0; k<3; k++) {
9037           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
9038           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
9039         }
9040     }
9041     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
9042   }
9043
9044   free(a);
9045   gtk_widget_draw(preview,NULL);
9046   gdk_flush();
9047 }
9048
9049 Applicable Routines
9050
9051 guint           gtk_preview_get_type           (void);
9052 /* No idea */
9053 void            gtk_preview_uninit             (void);
9054 /* No idea */
9055 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
9056 /* Described above */
9057 void            gtk_preview_size               (GtkPreview      *preview,
9058                                                 gint             width,
9059                                                 gint             height);
9060 /* Allows you to resize an existing preview.    */
9061 /* Apparently there's a bug in GTK which makes  */
9062 /* this process messy. A way to clean up a mess */
9063 /* is to manually resize the window containing  */
9064 /* the preview after resizing the preview.      */
9065
9066 void            gtk_preview_put                (GtkPreview      *preview,
9067                                                 GdkWindow       *window,
9068                                                 GdkGC           *gc,
9069                                                 gint             srcx,
9070                                                 gint             srcy,
9071                                                 gint             destx,
9072                                                 gint             desty,
9073                                                 gint             width,
9074                                                 gint             height);
9075 /* No idea */
9076
9077 void            gtk_preview_put_row            (GtkPreview      *preview,
9078                                                 guchar          *src,
9079                                                 guchar          *dest,
9080                                                 gint             x,
9081                                                 gint             y,
9082                                                 gint             w);
9083 /* No idea */
9084
9085 void            gtk_preview_draw_row           (GtkPreview      *preview,
9086                                                 guchar          *data,
9087                                                 gint             x,
9088                                                 gint             y,
9089                                                 gint             w);
9090 /* Described in the text */
9091
9092 void            gtk_preview_set_expand         (GtkPreview      *preview,
9093                                                 gint             expand);
9094 /* No idea */
9095
9096 /* No clue for any of the below but    */
9097 /* should be standard for most widgets */
9098 void            gtk_preview_set_gamma          (double           gamma);
9099 void            gtk_preview_set_color_cube     (guint            nred_shades,
9100                                                 guint            ngreen_shades,
9101                                                 guint            nblue_shades,
9102                                                 guint            ngray_shades);
9103 void            gtk_preview_set_install_cmap   (gint             install_cmap);
9104 void            gtk_preview_set_reserved       (gint             nreserved);
9105 GdkVisual*      gtk_preview_get_visual         (void);
9106 GdkColormap*    gtk_preview_get_cmap           (void);
9107 GtkPreviewInfo* gtk_preview_get_info           (void);
9108
9109 That's all, folks!
9110
9111 </verb></tscreen>
9112
9113 <!-- ***************************************************************** -->
9114 <sect>The EventBox Widget<label id="sec_The_EventBox_Widget">
9115 <!-- ***************************************************************** -->
9116 <p> 
9117 Some gtk widgets don't have associated X windows, so they just draw on 
9118 their parents. Because of this, they cannot receive events
9119 and if they are incorrectly sized, they don't clip so you can get
9120 messy overwriting etc. If you require more from these widgets, the
9121 EventBox is for you.
9122
9123 At first glance, the EventBox widget might appear to be totally
9124 useless. It draws nothing on the screen and responds to no
9125 events. However, it does serve a function - it provides an X window for
9126 its child widget. This is important as many GTK widgets do not
9127 have an associated X window. Not having an X window saves memory and
9128 improves performance, but also has some drawbacks. A widget without an
9129 X window cannot receive events, and does not perform any clipping on
9130 its contents. Although the name <em/EventBox/ emphasizes the
9131 event-handling function, the widget can also be used for clipping. 
9132 (And more ... see the example below.)
9133
9134 To create a new EventBox widget, use:
9135
9136 <tscreen><verb>
9137 GtkWidget *gtk_event_box_new( void );
9138 </verb></tscreen>
9139
9140 A child widget can then be added to this EventBox:
9141
9142 <tscreen><verb>
9143 gtk_container_add( GTK_CONTAINER(event_box), widget );
9144 </verb></tscreen>
9145
9146 The following example demonstrates both uses of an EventBox - a label
9147 is created that is clipped to a small box, and set up so that a
9148 mouse-click on the label causes the program to exit.
9149
9150 <tscreen><verb>
9151 /* example-start eventbox eventbox.c */
9152
9153 #include <gtk/gtk.h>
9154
9155 int 
9156 main (int argc, char *argv[])
9157 {
9158     GtkWidget *window;
9159     GtkWidget *event_box;
9160     GtkWidget *label;
9161     
9162     gtk_init (&amp;argc, &amp;argv);
9163     
9164     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9165     
9166     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9167     
9168     gtk_signal_connect (GTK_OBJECT (window), "destroy",
9169                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
9170     
9171     gtk_container_border_width (GTK_CONTAINER (window), 10);
9172     
9173     /* Create an EventBox and add it to our toplevel window */
9174     
9175     event_box = gtk_event_box_new ();
9176     gtk_container_add (GTK_CONTAINER(window), event_box);
9177     gtk_widget_show (event_box);
9178     
9179     /* Create a long label */
9180     
9181     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
9182     gtk_container_add (GTK_CONTAINER (event_box), label);
9183     gtk_widget_show (label);
9184     
9185     /* Clip it short. */
9186     gtk_widget_set_usize (label, 110, 20);
9187     
9188     /* And bind an action to it */
9189     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
9190     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
9191                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
9192     
9193     /* Yet one more thing you need an X window for ... */
9194     
9195     gtk_widget_realize (event_box);
9196     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
9197     
9198     gtk_widget_show (window);
9199     
9200     gtk_main ();
9201     
9202     return 0;
9203 }
9204 /* example-end */
9205 </verb></tscreen>
9206
9207 <!-- ***************************************************************** -->
9208 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
9209 <!-- ***************************************************************** -->
9210 <p>
9211 This describes the functions used to operate on widgets.  These can be used
9212 to set style, padding, size etc.
9213
9214 (Maybe I should make a whole section on accelerators.)
9215
9216 <tscreen><verb>
9217 void gtk_widget_install_accelerator( GtkWidget           *widget,
9218                                      GtkAcceleratorTable *table,
9219                                      gchar               *signal_name,
9220                                      gchar                key,
9221                                      guint8               modifiers );
9222
9223 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
9224                                      GtkAcceleratorTable *table,
9225                                      gchar               *signal_name);
9226
9227 void gtk_widget_activate( GtkWidget *widget );
9228
9229 void gtk_widget_set_name( GtkWidget *widget,
9230                           gchar     *name );
9231
9232 gchar *gtk_widget_get_name( GtkWidget *widget );
9233
9234 void gtk_widget_set_sensitive( GtkWidget *widget,
9235                                gint       sensitive );
9236
9237 void gtk_widget_set_style( GtkWidget *widget,
9238                            GtkStyle  *style );
9239                                            
9240 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
9241
9242 GtkStyle *gtk_widget_get_default_style( void );
9243
9244 void gtk_widget_set_uposition( GtkWidget *widget,
9245                                gint       x,
9246                                gint       y );
9247
9248 void gtk_widget_set_usize( GtkWidget *widget,
9249                            gint       width,
9250                            gint       height );
9251
9252 void gtk_widget_grab_focus( GtkWidget *widget );
9253
9254 void gtk_widget_show( GtkWidget *widget );
9255
9256 void gtk_widget_hide( GtkWidget *widget );
9257 </verb></tscreen>
9258
9259 <!-- ***************************************************************** -->
9260 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
9261 <!-- ***************************************************************** -->
9262
9263 <!-- ----------------------------------------------------------------- -->
9264 <sect1>Timeouts
9265 <p>
9266 You may be wondering how you make GTK do useful work when in gtk_main.
9267 Well, you have several options. Using the following functions you can
9268 create a timeout function that will be called every "interval"
9269 milliseconds.
9270
9271 <tscreen><verb>
9272 gint gtk_timeout_add( guint32     interval,
9273                       GtkFunction function,
9274                       gpointer    data );
9275 </verb></tscreen>
9276
9277 The first argument is the number of milliseconds between calls to your
9278 function.  The second argument is the function you wish to have called, and
9279 the third, the data passed to this callback function. The return value is
9280 an integer "tag" which may be used to stop the timeout by calling:
9281
9282 <tscreen><verb>
9283 void gtk_timeout_remove( gint tag );
9284 </verb></tscreen>
9285
9286 You may also stop the timeout function by returning zero or FALSE from
9287 your callback function. Obviously this means if you want your function to
9288 continue to be called, it should return a non-zero value, i.e. TRUE.
9289
9290 The declaration of your callback should look something like this:
9291
9292 <tscreen><verb>
9293 gint timeout_callback( gpointer data );
9294 </verb></tscreen>
9295
9296 <!-- ----------------------------------------------------------------- -->
9297 <sect1>Monitoring IO
9298 <p>
9299 Another nifty feature of GTK, is the ability to have it check for data on a
9300 file descriptor for you (as returned by open(2) or socket(2)).  This is
9301 especially useful for networking applications.  The function:
9302
9303 <tscreen><verb>
9304 gint gdk_input_add( gint              source,
9305                     GdkInputCondition condition,
9306                     GdkInputFunction  function,
9307                     gpointer          data );
9308 </verb></tscreen>
9309
9310 Where the first argument is the file descriptor you wish to have watched,
9311 and the second specifies what you want GDK to look for.  This may be one of:
9312
9313 <itemize>
9314 <item>GDK_INPUT_READ - Call your function when there is data ready for
9315 reading on your file descriptor.
9316
9317 <item>GDK_INPUT_WRITE - Call your function when the file descriptor is
9318 ready for writing.
9319 </itemize>
9320
9321 As I'm sure you've figured out already, the third argument is the function
9322 you wish to have called when the above conditions are satisfied, and the
9323 fourth is the data to pass to this function.
9324
9325 The return value is a tag that may be used to stop GDK from monitoring this
9326 file descriptor using the following function.
9327
9328 <tscreen><verb>
9329 void gdk_input_remove( gint tag );
9330 </verb></tscreen>
9331
9332 The callback function should be declared as:
9333
9334 <tscreen><verb>
9335 void input_callback( gpointer          data,
9336                      gint              source, 
9337                      GdkInputCondition condition );
9338 </verb></tscreen>
9339
9340 Where <tt/source/ and <tt/condition/ are as specified above.
9341
9342 <!-- ----------------------------------------------------------------- -->
9343 <sect1>Idle Functions
9344 <p>
9345 <!-- Need to check on idle priorities - TRG -->
9346 What if you have a function you want called when nothing else is
9347 happening ?
9348
9349 <tscreen><verb>
9350 gint gtk_idle_add( GtkFunction function,
9351                    gpointer    data );
9352 </verb></tscreen>
9353
9354 This causes GTK to call the specified function whenever nothing else is
9355 happening.
9356
9357 <tscreen><verb>
9358 void gtk_idle_remove( gint tag );
9359 </verb></tscreen>
9360
9361 I won't explain the meaning of the arguments as they follow very much like
9362 the ones above. The function pointed to by the first argument to
9363 gtk_idle_add will be called whenever the opportunity arises. As with the
9364 others, returning FALSE will stop the idle function from being called.
9365
9366 <!-- ***************************************************************** -->
9367 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
9368 <!-- ***************************************************************** -->
9369
9370 <!-- ----------------------------------------------------------------- -->
9371 <sect1>Signal Functions
9372
9373 <!-- ----------------------------------------------------------------- -->
9374 <sect2>Connecting and Disconnecting Signal Handlers
9375 <p>
9376
9377 <tscreen><verb>
9378 guint gtk_signal_connect( GtkObject     *object,
9379                           const gchar   *name,
9380                           GtkSignalFunc  func,
9381                           gpointer       func_data );
9382
9383 guint gtk_signal_connect_after( GtkObject     *object,
9384                                 const gchar   *name,
9385                                 GtkSignalFunc  func,
9386                                 gpointer       func_data );
9387
9388 guint gtk_signal_connect_object( GtkObject     *object,
9389                                  const gchar   *name,
9390                                  GtkSignalFunc  func,
9391                                  GtkObject     *slot_object );
9392
9393 guint gtk_signal_connect_object_after( GtkObject     *object,
9394                                        const gchar   *name,
9395                                        GtkSignalFunc  func,
9396                                        GtkObject     *slot_object );
9397
9398 guint gtk_signal_connect_full( GtkObject          *object,
9399                                const gchar        *name,
9400                                GtkSignalFunc       func,
9401                                GtkCallbackMarshal  marshal,
9402                                gpointer            data,
9403                                GtkDestroyNotify    destroy_func,
9404                                gint                object_signal,
9405                                gint                after );
9406
9407 guint gtk_signal_connect_interp( GtkObject          *object,
9408                                  const gchar        *name,
9409                                  GtkCallbackMarshal  func,
9410                                  gpointer            data,
9411                                  GtkDestroyNotify    destroy_func,
9412                                  gint                after );
9413
9414 void gtk_signal_connect_object_while_alive( GtkObject     *object,
9415                                             const gchar   *signal,
9416                                             GtkSignalFunc  func,
9417                                             GtkObject     *alive_object );
9418
9419 void gtk_signal_connect_while_alive( GtkObject     *object,
9420                                      const gchar   *signal,
9421                                      GtkSignalFunc  func,
9422                                      gpointer       func_data,
9423                                      GtkObject     *alive_object );
9424
9425 void gtk_signal_disconnect( GtkObject *object,
9426                             guint      handler_id );
9427
9428 void gtk_signal_disconnect_by_func( GtkObject     *object,
9429                                     GtkSignalFunc  func,
9430                                     gpointer       data );
9431 </verb></tscreen>
9432
9433 <!-- ----------------------------------------------------------------- -->
9434 <sect2>Blocking and Unblocking Signal Handlers
9435 <p>
9436 <tscreen><verb>
9437 void gtk_signal_handler_block( GtkObject *object,
9438                                guint      handler_id);
9439
9440 void gtk_signal_handler_block_by_func( GtkObject     *object,
9441                                        GtkSignalFunc  func,
9442                                        gpointer       data );
9443
9444 void gtk_signal_handler_block_by_data( GtkObject *object,
9445                                        gpointer   data );
9446
9447 void gtk_signal_handler_unblock( GtkObject *object,
9448                                  guint      handler_id );
9449
9450 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
9451                                          GtkSignalFunc  func,
9452                                          gpointer       data );
9453
9454 void gtk_signal_handler_unblock_by_data( GtkObject *object,
9455                                          gpointer   data );
9456 </verb></tscreen>
9457
9458 <!-- ----------------------------------------------------------------- -->
9459 <sect2>Emitting and Stopping Signals
9460 <p>
9461 <tscreen><verb>
9462 void gtk_signal_emit( GtkObject *object,
9463                       guint      signal_id,
9464                       ... );
9465
9466 void gtk_signal_emit_by_name( GtkObject   *object,
9467                               const gchar *name,
9468                               ... );
9469
9470 void gtk_signal_emitv( GtkObject *object,
9471                        guint      signal_id,
9472                        GtkArg    *params );
9473
9474 void gtk_signal_emitv_by_name( GtkObject   *object,
9475                                const gchar *name,
9476                                GtkArg      *params );
9477
9478 guint gtk_signal_n_emissions( GtkObject *object,
9479                               guint      signal_id );
9480
9481 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
9482                                       const gchar *name );
9483
9484 void gtk_signal_emit_stop( GtkObject *object,
9485                            guint      signal_id );
9486
9487 void gtk_signal_emit_stop_by_name( GtkObject   *object,
9488                                    const gchar *name );
9489 </verb></tscreen>
9490
9491 <!-- ----------------------------------------------------------------- -->
9492 <sect1>Signal Emission and Propagation
9493 <p>
9494 Signal emission is the process wherby GTK+ runs all handlers for a
9495 specific object and signal.
9496
9497 First, note that the return value from a signal emission is the
9498 return value of the <em>last</em> handler executed. Since event signals
9499 are all of type GTK_RUN_LAST, this will be the default (GTK+ supplied)
9500 default handler, unless you connect with gtk_signal_connect_after().
9501
9502 The way an event (say GTK_BUTTON_PRESS) is handled, is:
9503 <itemize>
9504 <item>Start with the widget where the event occured.
9505
9506 <item>Emit the generic "event" signal. If that signal handler returns
9507 a value of TRUE, stop all processing.
9508
9509 <item>Otherwise, emit a specific, "button_press_event" signal. If that
9510 returns TRUE, stop all processing.
9511
9512 <item>Otherwise, go to the widget's parent, and repeat the above steps.
9513
9514 <item>Contimue until some signal handler returns TRUE, or until the
9515 top-level widget is reached.
9516 </itemize>
9517
9518 Some consequences of the above are:
9519 <itemize>
9520 <item>Your handler's return value will have no effect if there is a
9521 default handler, unless you connect with gtk_signal_connect_after().
9522
9523 <item>To prevent the default handler from being run, you need to connect
9524 with gtk_signal_connect() and use gtk_signal_emit_stop_by_name() - the
9525 return value only affects whether the signal is propagated, not the
9526 current emission.
9527 </itemize>
9528
9529 <!-- ***************************************************************** -->
9530 <sect>Managing Selections
9531 <!-- ***************************************************************** -->
9532
9533 <!-- ----------------------------------------------------------------- -->
9534 <sect1> Overview
9535 <p>
9536 One type of interprocess communication supported by GTK is
9537 <em>selections</em>. A selection identifies a chunk of data, for
9538 instance, a portion of text, selected by the user in some fashion, for
9539 instance, by dragging with the mouse. Only one application on a
9540 display, (the <em>owner</em> can own a particular selection at one
9541 time, so when a selection is claimed by one application, the previous
9542 owner must indicate to the user that selection has been
9543 relinquished. Other applications can request the contents of a
9544 selection in different forms, called <em>targets</em>. There can be
9545 any number of selections, but most X applications only handle one, the
9546 <em>primary selection</em>.
9547
9548 In most cases, it isn't necessary for a GTK application to deal with
9549 selections itself. The standard widgets, such as the Entry widget,
9550 already have the capability to claim the selection when appropriate
9551 (e.g., when the user drags over text), and to retrieve the contents of
9552 the selection owned by another widget, or another application (e.g.,
9553 when the user clicks the second mouse button). However, there may be
9554 cases in which you want to give other widgets the ability to supply
9555 the selection, or you wish to retrieve targets not supported by
9556 default.
9557
9558 A fundamental concept needed to understand selection handling is that
9559 of the <em>atom</em>. An atom is an integer that uniquely identifies a
9560 string (on a certain display). Certain atoms are predefined by the X
9561 server, and in some cases there are constants in <tt>gtk.h</tt>
9562 corresponding to these atoms. For instance the constant
9563 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
9564 In other cases, you should use the functions
9565 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
9566 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
9567 selections and targets are identified by atoms.
9568
9569 <!-- ----------------------------------------------------------------- -->
9570 <sect1> Retrieving the selection
9571 <p>
9572 Retrieving the selection is an asynchronous process. To start the
9573 process, you call:
9574
9575 <tscreen><verb>
9576 gint gtk_selection_convert( GtkWidget *widget, 
9577                             GdkAtom    selection, 
9578                             GdkAtom    target,
9579                             guint32    time );
9580 </verb</tscreen>
9581
9582 This <em>converts</em> the selection into the form specified by
9583 <tt/target/. If at all possible, the time field should be the time
9584 from the event that triggered the selection. This helps make sure that
9585 events occur in the order that the user requested them. However, if it
9586 is not available (for instance, if the conversion was triggered by
9587 a "clicked" signal), then you can use the constant
9588 <tt>GDK_CURRENT_TIME</tt>.
9589
9590 When the selection owner responds to the request, a
9591 "selection_received" signal is sent to your application. The handler
9592 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
9593 structure, which is defined as:
9594
9595 <tscreen><verb>
9596 struct _GtkSelectionData
9597 {
9598   GdkAtom selection;
9599   GdkAtom target;
9600   GdkAtom type;
9601   gint    format;
9602   guchar *data;
9603   gint    length;
9604 };
9605 </verb></tscreen>
9606
9607 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
9608 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
9609 identifies the type of data returned by the selection owner. Some
9610 possible values are "STRING", a string of latin-1 characters, "ATOM",
9611 a series of atoms, "INTEGER", an integer, etc. Most targets can only
9612 return one type. <tt/format/ gives the length of the units (for
9613 instance characters) in bits. Usually, you don't care about this when
9614 receiving data. <tt>data</tt> is a pointer to the returned data, and
9615 <tt>length</tt> gives the length of the returned data, in bytes. If
9616 <tt>length</tt> is negative, then an error occurred and the selection
9617 could not be retrieved. This might happen if no application owned the
9618 selection, or if you requested a target that the application didn't
9619 support. The buffer is actually guaranteed to be one byte longer than
9620 <tt>length</tt>; the extra byte will always be zero, so it isn't
9621 necessary to make a copy of strings just to null terminate them.
9622
9623 In the following example, we retrieve the special target "TARGETS",
9624 which is a list of all targets into which the selection can be
9625 converted.
9626
9627 <tscreen><verb>
9628 /* example-start selection gettargets.c */
9629
9630 #include <gtk/gtk.h>
9631
9632 void selection_received (GtkWidget *widget, 
9633                          GtkSelectionData *selection_data, 
9634                          gpointer data);
9635
9636 /* Signal handler invoked when user clicks on the "Get Targets" button */
9637 void
9638 get_targets (GtkWidget *widget, gpointer data)
9639 {
9640   static GdkAtom targets_atom = GDK_NONE;
9641
9642   /* Get the atom corresponding to the string "TARGETS" */
9643   if (targets_atom == GDK_NONE)
9644     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9645
9646   /* And request the "TARGETS" target for the primary selection */
9647   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
9648                          GDK_CURRENT_TIME);
9649 }
9650
9651 /* Signal handler called when the selections owner returns the data */
9652 void
9653 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
9654                     gpointer data)
9655 {
9656   GdkAtom *atoms;
9657   GList *item_list;
9658   int i;
9659
9660   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
9661   if (selection_data->length < 0)
9662     {
9663       g_print ("Selection retrieval failed\n");
9664       return;
9665     }
9666   /* Make sure we got the data in the expected form */
9667   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
9668     {
9669       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9670       return;
9671     }
9672   
9673   /* Print out the atoms we received */
9674   atoms = (GdkAtom *)selection_data->data;
9675
9676   item_list = NULL;
9677   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
9678     {
9679       char *name;
9680       name = gdk_atom_name (atoms[i]);
9681       if (name != NULL)
9682         g_print ("%s\n",name);
9683       else
9684         g_print ("(bad atom)\n");
9685     }
9686
9687   return;
9688 }
9689
9690 int 
9691 main (int argc, char *argv[])
9692 {
9693   GtkWidget *window;
9694   GtkWidget *button;
9695   
9696   gtk_init (&amp;argc, &amp;argv);
9697
9698   /* Create the toplevel window */
9699
9700   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9701   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9702   gtk_container_border_width (GTK_CONTAINER (window), 10);
9703
9704   gtk_signal_connect (GTK_OBJECT (window), "destroy",
9705                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
9706
9707   /* Create a button the user can click to get targets */
9708
9709   button = gtk_button_new_with_label ("Get Targets");
9710   gtk_container_add (GTK_CONTAINER (window), button);
9711
9712   gtk_signal_connect (GTK_OBJECT(button), "clicked",
9713                       GTK_SIGNAL_FUNC (get_targets), NULL);
9714   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
9715                       GTK_SIGNAL_FUNC (selection_received), NULL);
9716
9717   gtk_widget_show (button);
9718   gtk_widget_show (window);
9719   
9720   gtk_main ();
9721   
9722   return 0;
9723 }
9724 /* example-end */
9725 </verb></tscreen>
9726
9727 <!-- ----------------------------------------------------------------- -->
9728 <sect1> Supplying the selection 
9729 <p>
9730 Supplying the selection is a bit more complicated. You must register 
9731 handlers that will be called when your selection is requested. For
9732 each selection/target pair you will handle, you make a call to:
9733
9734 <tscreen><verb>
9735 void gtk_selection_add_handler( GtkWidget            *widget, 
9736                                 GdkAtom               selection,
9737                                 GdkAtom               target,
9738                                 GtkSelectionFunction  function,
9739                                 GtkRemoveFunction     remove_func,
9740                                 gpointer              data );
9741 </verb></tscreen>
9742
9743 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
9744 this handler will manage.  <tt/remove_func/, if not
9745 NULL, will be called when the signal handler is removed. This is
9746 useful, for instance, for interpreted languages which need to
9747 keep track of a reference count for <tt/data/.
9748
9749 The callback function has the signature:
9750
9751 <tscreen><verb>
9752 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
9753                                       GtkSelectionData *selection_data,
9754                                       gpointer          data );
9755
9756 </verb></tscreen>
9757
9758 The GtkSelectionData is the same as above, but this time, we're
9759 responsible for filling in the fields <tt/type/, <tt/format/,
9760 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
9761 important here - the X server uses it to figure out whether the data
9762 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
9763 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
9764 function:
9765
9766 <tscreen><verb>
9767 void gtk_selection_data_set( GtkSelectionData *selection_data,
9768                              GdkAtom           type,
9769                              gint              format,
9770                              guchar           *data,
9771                              gint              length );
9772 </verb></tscreen>
9773
9774 This function takes care of properly making a copy of the data so that
9775 you don't have to worry about keeping it around. (You should not fill
9776 in the fields of the GtkSelectionData structure by hand.)
9777
9778 When prompted by the user, you claim ownership of the selection by
9779 calling:
9780
9781 <tscreen><verb>
9782 gint gtk_selection_owner_set( GtkWidget *widget,
9783                               GdkAtom    selection,
9784                               guint32    time );
9785 </verb></tscreen>
9786
9787 If another application claims ownership of the selection, you will
9788 receive a "selection_clear_event".
9789
9790 As an example of supplying the selection, the following program adds
9791 selection functionality to a toggle button. When the toggle button is
9792 depressed, the program claims the primary selection. The only target
9793 supported (aside from certain targets like "TARGETS" supplied by GTK
9794 itself), is the "STRING" target. When this target is requested, a
9795 string representation of the time is returned.
9796
9797 <tscreen><verb>
9798 /* example-start selection setselection.c */
9799
9800 #include <gtk/gtk.h>
9801 #include <time.h>
9802
9803 /* Callback when the user toggles the selection */
9804 void
9805 selection_toggled (GtkWidget *widget, gint *have_selection)
9806 {
9807   if (GTK_TOGGLE_BUTTON(widget)->active)
9808     {
9809       *have_selection = gtk_selection_owner_set (widget,
9810                                                  GDK_SELECTION_PRIMARY,
9811                                                  GDK_CURRENT_TIME);
9812       /* if claiming the selection failed, we return the button to
9813          the out state */
9814       if (!*have_selection)
9815         gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
9816     }
9817   else
9818     {
9819       if (*have_selection)
9820         {
9821           /* Before clearing the selection by setting the owner to NULL,
9822              we check if we are the actual owner */
9823           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
9824             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
9825                                      GDK_CURRENT_TIME);
9826           *have_selection = FALSE;
9827         }
9828     }
9829 }
9830
9831 /* Called when another application claims the selection */
9832 gint
9833 selection_clear (GtkWidget *widget, GdkEventSelection *event,
9834                  gint *have_selection)
9835 {
9836   *have_selection = FALSE;
9837   gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
9838
9839   return TRUE;
9840 }
9841
9842 /* Supplies the current time as the selection. */
9843 void
9844 selection_handle (GtkWidget *widget, 
9845                   GtkSelectionData *selection_data,
9846                   gpointer data)
9847 {
9848   gchar *timestr;
9849   time_t current_time;
9850
9851   current_time = time (NULL);
9852   timestr = asctime (localtime(&amp;current_time)); 
9853   /* When we return a single string, it should not be null terminated.
9854      That will be done for us */
9855
9856   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
9857                           8, timestr, strlen(timestr));
9858 }
9859
9860 int
9861 main (int argc, char *argv[])
9862 {
9863   GtkWidget *window;
9864
9865   GtkWidget *selection_button;
9866
9867   static int have_selection = FALSE;
9868   
9869   gtk_init (&amp;argc, &amp;argv);
9870
9871   /* Create the toplevel window */
9872
9873   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9874   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9875   gtk_container_border_width (GTK_CONTAINER (window), 10);
9876
9877   gtk_signal_connect (GTK_OBJECT (window), "destroy",
9878                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
9879
9880   /* Create a toggle button to act as the selection */
9881
9882   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
9883   gtk_container_add (GTK_CONTAINER (window), selection_button);
9884   gtk_widget_show (selection_button);
9885
9886   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
9887                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
9888   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
9889                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
9890
9891   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
9892                              GDK_SELECTION_TYPE_STRING,
9893                              selection_handle, NULL);
9894
9895   gtk_widget_show (selection_button);
9896   gtk_widget_show (window);
9897   
9898   gtk_main ();
9899   
9900   return 0;
9901 }
9902 /* example-end */
9903 </verb></tscreen>
9904
9905
9906 <!-- ***************************************************************** -->
9907 <sect>glib<label id="sec_glib">
9908 <!-- ***************************************************************** -->
9909 <p>
9910 glib provides many useful functions and definitions available for use
9911 when creating GDK and GTK applications. I will list them all here with
9912 a brief explanation. Many are duplicates of standard libc functions so
9913 I won't go into detail on those. This is mostly to be used as a reference,
9914 so you know what is available for use.
9915
9916 <!-- ----------------------------------------------------------------- -->
9917 <sect1>Definitions
9918 <p>
9919 Definitions for the extremes of many of the standard types are:
9920
9921 <tscreen><verb>
9922 G_MINFLOAT
9923 G_MAXFLOAT
9924 G_MINDOUBLE
9925 G_MAXDOUBLE
9926 G_MINSHORT
9927 G_MAXSHORT
9928 G_MININT
9929 G_MAXINT
9930 G_MINLONG
9931 G_MAXLONG
9932 </verb></tscreen>
9933
9934 Also, the following typedefs. The ones left unspecified are dynamically set
9935 depending on the architecture. Remember to avoid counting on the size of a
9936 pointer if you want to be portable! E.g., a pointer on an Alpha is 8 bytes, but 4
9937 on Intel.
9938
9939 <tscreen><verb>
9940 char   gchar;
9941 short  gshort;
9942 long   glong;
9943 int    gint;
9944 char   gboolean;
9945
9946 unsigned char   guchar;
9947 unsigned short  gushort;
9948 unsigned long   gulong;
9949 unsigned int    guint;
9950
9951 float   gfloat;
9952 double  gdouble;
9953 long double gldouble;
9954
9955 void* gpointer;
9956
9957 gint8
9958 guint8
9959 gint16
9960 guint16
9961 gint32
9962 guint32
9963 </verb></tscreen>
9964
9965 <!-- ----------------------------------------------------------------- -->
9966 <sect1>Doubly Linked Lists
9967 <p>
9968 The following functions are used to create, manage, and destroy doubly
9969 linked lists.  I assume you know what linked lists are, as it is beyond the scope
9970 of this document to explain them.  Of course, it's not required that you
9971 know these for general use of GTK, but they are nice to know.
9972
9973 <tscreen><verb>
9974 GList *g_list_alloc( void );
9975
9976 void g_list_free( GList *list );
9977
9978 void g_list_free_1( GList *list );
9979
9980 GList *g_list_append( GList     *list,
9981                       gpointer   data );
9982                            
9983 GList *g_list_prepend( GList    *list,
9984                        gpointer  data );
9985                         
9986 GList *g_list_insert( GList    *list,
9987                       gpointer  data,
9988                             gint      position );
9989
9990 GList *g_list_remove( GList    *list,
9991                       gpointer  data );
9992                            
9993 GList *g_list_remove_link( GList *list,
9994                            GList *link );
9995
9996 GList *g_list_reverse( GList *list );
9997
9998 GList *g_list_nth( GList *list,
9999                    gint   n );
10000                            
10001 GList *g_list_find( GList    *list,
10002                     gpointer  data );
10003
10004 GList *g_list_last( GList *list );
10005
10006 GList *g_list_first( GList *list );
10007
10008 gint g_list_length( GList *list );
10009
10010 void g_list_foreach( GList    *list,
10011                      GFunc     func,
10012                      gpointer  user_data );
10013 </verb></tscreen>                                             
10014
10015 <!-- ----------------------------------------------------------------- -->
10016 <sect1>Singly Linked Lists
10017 <p>
10018 Many of the above functions for singly linked lists are identical to the
10019 above. Here is a complete list:
10020 <tscreen><verb>
10021 GSList *g_slist_alloc( void );
10022
10023 void g_slist_free( GSList *list );
10024
10025 void g_slist_free_1( GSList *list );
10026
10027 GSList *g_slist_append( GSList   *list,
10028                         gpointer  data );
10029                 
10030 GSList *g_slist_prepend( GSList   *list,
10031                          gpointer  data );
10032                              
10033 GSList *g_slist_insert( GSList   *list,
10034                         gpointer  data,
10035                             gint      position );
10036                              
10037 GSList *g_slist_remove( GSList   *list,
10038                         gpointer  data );
10039                              
10040 GSList *g_slist_remove_link( GSList *list,
10041                              GSList *link );
10042                              
10043 GSList *g_slist_reverse( GSList *list );
10044
10045 GSList *g_slist_nth( GSList *list,
10046                      gint    n );
10047                              
10048 GSList *g_slist_find( GSList   *list,
10049                       gpointer  data );
10050                              
10051 GSList *g_slist_last( GSList *list );
10052
10053 gint g_slist_length( GSList *list );
10054
10055 void g_slist_foreach( GSList   *list,
10056                       GFunc     func,
10057                             gpointer  user_data );
10058         
10059 </verb></tscreen>
10060
10061 <!-- ----------------------------------------------------------------- -->
10062 <sect1>Memory Management
10063 <p>
10064 <tscreen><verb>
10065 gpointer g_malloc( gulong size );
10066 </verb></tscreen>
10067
10068 This is a replacement for malloc(). You do not need to check the return
10069 value as it is done for you in this function.
10070
10071 <tscreen><verb>
10072 gpointer g_malloc0( gulong size );
10073 </verb></tscreen>
10074
10075 Same as above, but zeroes the memory before returning a pointer to it.
10076
10077 <tscreen><verb>
10078 gpointer g_realloc( gpointer mem,
10079                     gulong   size );
10080 </verb></tscreen>
10081
10082 Relocates "size" bytes of memory starting at "mem".  Obviously, the
10083 memory should have been previously allocated.
10084
10085 <tscreen><verb>
10086 void g_free( gpointer mem );
10087 </verb></tscreen>
10088
10089 Frees memory. Easy one.
10090
10091 <tscreen><verb>
10092 void g_mem_profile( void );
10093 </verb></tscreen>
10094
10095 Dumps a profile of used memory, but requires that you add #define
10096 MEM_PROFILE to the top of glib/gmem.c and re-make and make install.
10097
10098 <tscreen><verb>
10099 void g_mem_check( gpointer mem );
10100 </verb></tscreen>
10101
10102 Checks that a memory location is valid.  Requires you add #define
10103 MEM_CHECK to the top of gmem.c and re-make and make install.
10104
10105 <!-- ----------------------------------------------------------------- -->
10106 <sect1>Timers
10107 <p>
10108 Timer functions..
10109
10110 <tscreen><verb>
10111 GTimer *g_timer_new( void );
10112
10113 void g_timer_destroy( GTimer *timer );
10114
10115 void g_timer_start( GTimer  *timer );
10116
10117 void g_timer_stop( GTimer  *timer );
10118
10119 void g_timer_reset( GTimer  *timer );
10120
10121 gdouble g_timer_elapsed( GTimer *timer,
10122                          gulong *microseconds );
10123 </verb></tscreen>                        
10124
10125 <!-- ----------------------------------------------------------------- -->
10126 <sect1>String Handling
10127 <p>
10128 A whole mess of string handling functions. They all look very interesting, and
10129 probably better for many purposes than the standard C string functions, but
10130 require documentation.
10131
10132 <tscreen><verb>
10133 GString *g_string_new( gchar *init );
10134
10135 void g_string_free( GString *string,
10136                     gint     free_segment );
10137                              
10138 GString *g_string_assign( GString *lval,
10139                           gchar   *rval );
10140                              
10141 GString *g_string_truncate( GString *string,
10142                             gint     len );
10143                              
10144 GString *g_string_append( GString *string,
10145                           gchar   *val );
10146                             
10147 GString *g_string_append_c( GString *string,
10148                             gchar    c );
10149         
10150 GString *g_string_prepend( GString *string,
10151                            gchar   *val );
10152                              
10153 GString *g_string_prepend_c( GString *string,
10154                              gchar    c );
10155         
10156 void g_string_sprintf( GString *string,
10157                        gchar   *fmt,
10158                        ...);
10159         
10160 void g_string_sprintfa ( GString *string,
10161                          gchar   *fmt,
10162                          ... );
10163 </verb></tscreen>                                                         
10164
10165 <!-- ----------------------------------------------------------------- -->
10166 <sect1>Utility and Error Functions
10167 <p>
10168 <tscreen><verb>
10169 gchar *g_strdup( const gchar *str );
10170 </verb></tscreen>
10171
10172 Replacement strdup function.  Copies the original strings contents to
10173 newly allocated memory, and returns a pointer to it.
10174
10175 <tscreen><verb>
10176 gchar *g_strerror( gint errnum );
10177 </verb></tscreen>
10178
10179 I recommend using this for all error messages.  It's much nicer, and more
10180 portable than perror() or others.  The output is usually of the form:
10181
10182 <tscreen><verb>
10183 program name:function that failed:file or further description:strerror
10184 </verb></tscreen>
10185
10186 Here's an example of one such call used in our hello_world program:
10187
10188 <tscreen><verb>
10189 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
10190 </verb></tscreen>
10191
10192 <tscreen><verb>
10193 void g_error( gchar *format, ... );
10194 </verb></tscreen>
10195
10196 Prints an error message. The format is just like printf, but it
10197 prepends "** ERROR **: " to your message, and exits the program.  
10198 Use only for fatal errors.
10199
10200 <tscreen><verb>
10201 void g_warning( gchar *format, ... );
10202 </verb></tscreen>
10203
10204 Same as above, but prepends "** WARNING **: ", and does not exit the
10205 program.
10206
10207 <tscreen><verb>
10208 void g_message( gchar *format, ... );
10209 </verb></tscreen>
10210
10211 Prints "message: " prepended to the string you pass in.
10212
10213 <tscreen><verb>
10214 void g_print( gchar *format, ... );
10215 </verb></tscreen>
10216
10217 Replacement for printf().
10218
10219 And our last function:
10220
10221 <tscreen><verb>
10222 gchar *g_strsignal( gint signum );
10223 </verb></tscreen>
10224
10225 Prints out the name of the Unix system signal given the signal number.
10226 Useful in generic signal handling functions.
10227
10228 All of the above are more or less just stolen from glib.h.  If anyone cares
10229 to document any function, just send me an email!
10230
10231 <!-- ***************************************************************** -->
10232 <sect>GTK's rc Files
10233 <!-- ***************************************************************** -->
10234 <p>
10235 GTK has its own way of dealing with application defaults, by using rc
10236 files. These can be used to set the colors of just about any widget, and
10237 can also be used to tile pixmaps onto the background of some widgets.  
10238
10239 <!-- ----------------------------------------------------------------- -->
10240 <sect1>Functions For rc Files 
10241 <p>
10242 When your application starts, you should include a call to:
10243
10244 <tscreen><verb>
10245 void gtk_rc_parse( char *filename );
10246 </verb></tscreen>
10247
10248 Passing in the filename of your rc file.  This will cause GTK to parse this
10249 file, and use the style settings for the widget types defined there.
10250
10251 If you wish to have a special set of widgets that can take on a different
10252 style from others, or any other logical division of widgets, use a call to:
10253
10254 <tscreen><verb>
10255 void gtk_widget_set_name( GtkWidget *widget,
10256                           gchar     *name );
10257 </verb></tscreen>
10258
10259 Passing your newly created widget as the first argument, and the name
10260 you wish to give it as the second. This will allow you to change the
10261 attributes of this widget by name through the rc file.
10262
10263 If we use a call something like this:
10264
10265 <tscreen><verb>
10266 button = gtk_button_new_with_label ("Special Button");
10267 gtk_widget_set_name (button, "special button");
10268 </verb></tscreen>
10269
10270 Then this button is given the name "special button" and may be addressed by
10271 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
10272
10273 The example rc file below, sets the properties of the main window, and lets
10274 all children of that main window inherit the style described by the "main
10275 button" style.  The code used in the application is:
10276
10277 <tscreen><verb>
10278 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10279 gtk_widget_set_name (window, "main window");
10280 </verb></tscreen>
10281
10282 And then the style is defined in the rc file using:
10283
10284 <tscreen><verb>
10285 widget "main window.*GtkButton*" style "main_button"
10286 </verb></tscreen>
10287
10288 Which sets all the GtkButton widgets in the "main window" to the
10289 "main_buttons" style as defined in the rc file.
10290
10291 As you can see, this is a fairly powerful and flexible system.  Use your
10292 imagination as to how best to take advantage of this.
10293
10294 <!-- ----------------------------------------------------------------- -->
10295 <sect1>GTK's rc File Format
10296 <p>
10297 The format of the GTK file is illustrated in the example below. This is
10298 the testgtkrc file from the GTK distribution, but I've added a
10299 few comments and things. You may wish to include this explanation
10300 your application to allow the user to fine tune his application.
10301
10302 There are several directives to change the attributes of a widget.
10303
10304 <itemize>
10305 <item>fg - Sets the foreground color of a widget.
10306 <item>bg - Sets the background color of a widget.
10307 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
10308 <item>font - Sets the font to be used with the given widget.
10309 </itemize>
10310
10311 In addition to this, there are several states a widget can be in, and you
10312 can set different colors, pixmaps and fonts for each state. These states are:
10313
10314 <itemize>
10315 <item>NORMAL - The normal state of a widget, without the mouse over top of
10316 it, and not being pressed etc.
10317 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
10318 using this state will be in effect.
10319 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
10320 the attributes assigned by this tag will be in effect.
10321 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
10322 activated, it will take these attributes.
10323 <item>SELECTED - When an object is selected, it takes these attributes.
10324 </itemize>
10325
10326 When using the "fg" and "bg" keywords to set the colors of widgets, the
10327 format is:
10328
10329 <tscreen><verb>
10330 fg[<STATE>] = { Red, Green, Blue }
10331 </verb></tscreen>
10332
10333 Where STATE is one of the above states (PRELIGHT, ACTIVE etc), and the Red,
10334 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
10335 white. They must be in float form, or they will register as 0, so a straight 
10336 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
10337 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
10338
10339 bg_pixmap is very similar to the above, except the colors are replaced by a
10340 filename.
10341
10342 pixmap_path is a list of paths separated by ":"'s.  These paths will be
10343 searched for any pixmap you specify.
10344
10345 The font directive is simply:
10346 <tscreen><verb>
10347 font = "<font name>"
10348 </verb></tscreen>
10349
10350 Where the only hard part is figuring out the font string. Using xfontsel or
10351 similar utility should help.
10352
10353 The "widget_class" sets the style of a class of widgets. These classes are
10354 listed in the widget overview on the class hierarchy.
10355
10356 The "widget" directive sets a specifically named set of widgets to a
10357 given style, overriding any style set for the given widget class.
10358 These widgets are registered inside the application using the
10359 gtk_widget_set_name() call. This allows you to specify the attributes of a
10360 widget on a per widget basis, rather than setting the attributes of an
10361 entire widget class. I urge you to document any of these special widgets so
10362 users may customize them.
10363
10364 When the keyword <tt>parent</> is used as an attribute, the widget will take on
10365 the attributes of its parent in the application.
10366
10367 When defining a style, you may assign the attributes of a previously defined
10368 style to this new one.
10369
10370 <tscreen><verb>
10371 style "main_button" = "button"
10372 {
10373   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10374   bg[PRELIGHT] = { 0.75, 0, 0 }
10375 }
10376 </verb></tscreen>
10377
10378 This example takes the "button" style, and creates a new "main_button" style
10379 simply by changing the font and prelight background color of the "button"
10380 style.
10381
10382 Of course, many of these attributes don't apply to all widgets. It's a
10383 simple matter of common sense really. Anything that could apply, should.
10384
10385 <!-- ----------------------------------------------------------------- -->
10386 <sect1>Example rc file
10387 <p>
10388
10389 <tscreen><verb>
10390 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
10391 #
10392 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
10393 #
10394 # style <name> [= <name>]
10395 # {
10396 #   <option>
10397 # }
10398 #
10399 # widget <widget_set> style <style_name>
10400 # widget_class <widget_class_set> style <style_name>
10401
10402
10403 # Here is a list of all the possible states.  Note that some do not apply to
10404 # certain widgets.
10405 #
10406 # NORMAL - The normal state of a widget, without the mouse over top of
10407 # it, and not being pressed etc.
10408 #
10409 # PRELIGHT - When the mouse is over top of the widget, colors defined
10410 # using this state will be in effect.
10411 #
10412 # ACTIVE - When the widget is pressed or clicked it will be active, and
10413 # the attributes assigned by this tag will be in effect.
10414 #
10415 # INSENSITIVE - When a widget is set insensitive, and cannot be
10416 # activated, it will take these attributes.
10417 #
10418 # SELECTED - When an object is selected, it takes these attributes.
10419 #
10420 # Given these states, we can set the attributes of the widgets in each of
10421 # these states using the following directives.
10422 #
10423 # fg - Sets the foreground color of a widget.
10424 # fg - Sets the background color of a widget.
10425 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
10426 # font - Sets the font to be used with the given widget.
10427 #
10428
10429 # This sets a style called "button".  The name is not really important, as
10430 # it is assigned to the actual widgets at the bottom of the file.
10431
10432 style "window"
10433 {
10434   #This sets the padding around the window to the pixmap specified.
10435   #bg_pixmap[<STATE>] = "<pixmap filename>"
10436   bg_pixmap[NORMAL] = "warning.xpm"
10437 }
10438
10439 style "scale"
10440 {
10441   #Sets the foreground color (font color) to red when in the "NORMAL"
10442   #state.
10443   
10444   fg[NORMAL] = { 1.0, 0, 0 }
10445   
10446   #Sets the background pixmap of this widget to that of its parent.
10447   bg_pixmap[NORMAL] = "<parent>"
10448 }
10449
10450 style "button"
10451 {
10452   # This shows all the possible states for a button.  The only one that
10453   # doesn't apply is the SELECTED state.
10454   
10455   fg[PRELIGHT] = { 0, 1.0, 1.0 }
10456   bg[PRELIGHT] = { 0, 0, 1.0 }
10457   bg[ACTIVE] = { 1.0, 0, 0 }
10458   fg[ACTIVE] = { 0, 1.0, 0 }
10459   bg[NORMAL] = { 1.0, 1.0, 0 }
10460   fg[NORMAL] = { .99, 0, .99 }
10461   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
10462   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
10463 }
10464
10465 # In this example, we inherit the attributes of the "button" style and then
10466 # override the font and background color when prelit to create a new
10467 # "main_button" style.
10468
10469 style "main_button" = "button"
10470 {
10471   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10472   bg[PRELIGHT] = { 0.75, 0, 0 }
10473 }
10474
10475 style "toggle_button" = "button"
10476 {
10477   fg[NORMAL] = { 1.0, 0, 0 }
10478   fg[ACTIVE] = { 1.0, 0, 0 }
10479   
10480   # This sets the background pixmap of the toggle_button to that of its
10481   # parent widget (as defined in the application).
10482   bg_pixmap[NORMAL] = "<parent>"
10483 }
10484
10485 style "text"
10486 {
10487   bg_pixmap[NORMAL] = "marble.xpm"
10488   fg[NORMAL] = { 1.0, 1.0, 1.0 }
10489 }
10490
10491 style "ruler"
10492 {
10493   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
10494 }
10495
10496 # pixmap_path "~/.pixmaps"
10497
10498 # These set the widget types to use the styles defined above.
10499 # The widget types are listed in the class hierarchy, but could probably be
10500 # just listed in this document for the users reference.
10501
10502 widget_class "GtkWindow" style "window"
10503 widget_class "GtkDialog" style "window"
10504 widget_class "GtkFileSelection" style "window"
10505 widget_class "*Gtk*Scale" style "scale"
10506 widget_class "*GtkCheckButton*" style "toggle_button"
10507 widget_class "*GtkRadioButton*" style "toggle_button"
10508 widget_class "*GtkButton*" style "button"
10509 widget_class "*Ruler" style "ruler"
10510 widget_class "*GtkText" style "text"
10511
10512 # This sets all the buttons that are children of the "main window" to
10513 # the main_button style.  These must be documented to be taken advantage of.
10514 widget "main window.*GtkButton*" style "main_button"
10515 </verb></tscreen>
10516
10517 <!-- ***************************************************************** -->
10518 <sect>Writing Your Own Widgets 
10519 <!-- ***************************************************************** -->
10520
10521 <!-- ----------------------------------------------------------------- -->
10522 <sect1> Overview
10523 <p>
10524 Although the GTK distribution comes with many types of widgets that
10525 should cover most basic needs, there may come a time when you need to
10526 create your own new widget type. Since GTK uses widget inheritance
10527 extensively, and there is already a widget that is close to what you want,
10528 it is often possible to make a useful new widget type in
10529 just a few lines of code. But before starting work on a new widget, check
10530 around first to make sure that someone has not already written
10531 it. This will prevent duplication of effort and keep the number of
10532 GTK widgets out there to a minimum, which will help keep both the code
10533 and the interface of different applications consistent. As a flip side
10534 to this, once you finish your widget, announce it to the world so
10535 other people can benefit. The best place to do this is probably the
10536 <tt>gtk-list</tt>.
10537
10538 Complete sources for the example widgets are available at the place you 
10539 got this tutorial, or from:
10540
10541 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
10542 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
10543
10544
10545 <!-- ----------------------------------------------------------------- -->
10546 <sect1> The Anatomy Of A Widget
10547 <p>
10548 In order to create a new widget, it is important to have an
10549 understanding of how GTK objects work. This section is just meant as a
10550 brief overview. See the reference documentation for the details. 
10551
10552 GTK widgets are implemented in an object oriented fashion. However,
10553 they are implemented in standard C. This greatly improves portability
10554 and stability over using current generation C++ compilers; however,
10555 it does mean that the widget writer has to pay attention to some of
10556 the implementation details. The information common to all instances of
10557 one class of widgets (e.g., to all Button widgets) is stored in the 
10558 <em>class structure</em>. There is only one copy of this in
10559 which is stored information about the class's signals
10560 (which act like virtual functions in C). To support inheritance, the
10561 first field in the class structure must be a copy of the parent's
10562 class structure. The declaration of the class structure of GtkButtton
10563 looks like:
10564
10565 <tscreen><verb>
10566 struct _GtkButtonClass
10567 {
10568   GtkContainerClass parent_class;
10569
10570   void (* pressed)  (GtkButton *button);
10571   void (* released) (GtkButton *button);
10572   void (* clicked)  (GtkButton *button);
10573   void (* enter)    (GtkButton *button);
10574   void (* leave)    (GtkButton *button);
10575 };
10576 </verb></tscreen>
10577
10578 When a button is treated as a container (for instance, when it is
10579 resized), its class structure can be cast to GtkContainerClass, and
10580 the relevant fields used to handle the signals.
10581
10582 There is also a structure for each widget that is created on a
10583 per-instance basis. This structure has fields to store information that
10584 is different for each instance of the widget. We'll call this
10585 structure the <em>object structure</em>. For the Button class, it looks
10586 like:
10587
10588 <tscreen><verb>
10589 struct _GtkButton
10590 {
10591   GtkContainer container;
10592
10593   GtkWidget *child;
10594
10595   guint in_button : 1;
10596   guint button_down : 1;
10597 };
10598 </verb></tscreen>
10599
10600 Note that, similar to the class structure, the first field is the
10601 object structure of the parent class, so that this structure can be
10602 cast to the parent class's object structure as needed.
10603
10604 <!-- ----------------------------------------------------------------- -->
10605 <sect1> Creating a Composite widget
10606
10607 <!-- ----------------------------------------------------------------- -->
10608 <sect2> Introduction
10609 <p>
10610 One type of widget that you may be interested in creating is a
10611 widget that is merely an aggregate of other GTK widgets. This type of
10612 widget does nothing that couldn't be done without creating new
10613 widgets, but provides a convenient way of packaging user interface
10614 elements for reuse. The FileSelection and ColorSelection widgets in
10615 the standard distribution are examples of this type of widget.
10616
10617 The example widget that we'll create in this section is the Tictactoe
10618 widget, a 3x3 array of toggle buttons which triggers a signal when all
10619 three buttons in a row, column, or on one of the diagonals are
10620 depressed. 
10621
10622 <!-- ----------------------------------------------------------------- -->
10623 <sect2> Choosing a parent class
10624 <p>
10625 The parent class for a composite widget is typically the container
10626 class that holds all of the elements of the composite widget. For
10627 example, the parent class of the FileSelection widget is the
10628 Dialog class. Since our buttons will be arranged in a table, it
10629 might seem natural to make our parent class the GtkTable
10630 class. Unfortunately, this turns out not to work. The creation of a
10631 widget is divided among two functions - a <tt/WIDGETNAME_new()/
10632 function that the user calls, and a <tt/WIDGETNAME_init()/ function
10633 which does the basic work of initializing the widget which is
10634 independent of the arguments passed to the <tt/_new()/
10635 function. Descendent widgets only call the <tt/_init/ function of
10636 their parent widget. But this division of labor doesn't work well for
10637 tables, which when created, need to know the number of rows and
10638 columns in the table. Unless we want to duplicate most of the
10639 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
10640 best avoid deriving it from GtkTable. For that reason, we derive it
10641 from GtkVBox instead, and stick our table inside the VBox.
10642
10643 <!-- ----------------------------------------------------------------- -->
10644 <sect2> The header file
10645 <p>
10646 Each widget class has a header file which declares the object and
10647 class structures for that widget, along with public functions. 
10648 A couple of features are worth pointing out. To prevent duplicate
10649 definitions, we wrap the entire header file in:
10650
10651 <tscreen><verb>
10652 #ifndef __TICTACTOE_H__
10653 #define __TICTACTOE_H__
10654 .
10655 .
10656 .
10657 #endif /* __TICTACTOE_H__ */
10658 </verb></tscreen>
10659
10660 And to keep C++ programs that include the header file happy, in:
10661
10662 <tscreen><verb>
10663 #ifdef __cplusplus
10664 extern "C" {
10665 #endif /* __cplusplus */
10666 .
10667 .
10668 .
10669 #ifdef __cplusplus
10670 }
10671 #endif /* __cplusplus */
10672 </verb></tscreen>
10673
10674 Along with the functions and structures, we declare three standard
10675 macros in our header file, <tt/TICTACTOE(obj)/,
10676 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
10677 pointer into a pointer to the object or class structure, and check
10678 if an object is a Tictactoe widget respectively.
10679
10680 Here is the complete header file:
10681
10682 <tscreen><verb>
10683 /* tictactoe.h */
10684
10685 #ifndef __TICTACTOE_H__
10686 #define __TICTACTOE_H__
10687
10688 #include <gdk/gdk.h>
10689 #include <gtk/gtkvbox.h>
10690
10691 #ifdef __cplusplus
10692 extern "C" {
10693 #endif /* __cplusplus */
10694
10695 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
10696 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
10697 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
10698
10699
10700 typedef struct _Tictactoe       Tictactoe;
10701 typedef struct _TictactoeClass  TictactoeClass;
10702
10703 struct _Tictactoe
10704 {
10705   GtkVBox vbox;
10706   
10707   GtkWidget *buttons[3][3];
10708 };
10709
10710 struct _TictactoeClass
10711 {
10712   GtkVBoxClass parent_class;
10713
10714   void (* tictactoe) (Tictactoe *ttt);
10715 };
10716
10717 guint          tictactoe_get_type        (void);
10718 GtkWidget*     tictactoe_new             (void);
10719 void           tictactoe_clear           (Tictactoe *ttt);
10720
10721 #ifdef __cplusplus
10722 }
10723 #endif /* __cplusplus */
10724
10725 #endif /* __TICTACTOE_H__ */
10726
10727 </verb></tscreen>
10728
10729 <!-- ----------------------------------------------------------------- -->
10730 <sect2> The <tt/_get_type()/ function.
10731 <p>
10732 We now continue on to the implementation of our widget. A core
10733 function for every widget is the function
10734 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
10735 GTK about the widget class, and gets an ID that uniquely identifies
10736 the widget class. Upon subsequent calls, it just returns the ID.
10737
10738 <tscreen><verb>
10739 guint
10740 tictactoe_get_type ()
10741 {
10742   static guint ttt_type = 0;
10743
10744   if (!ttt_type)
10745     {
10746       GtkTypeInfo ttt_info =
10747       {
10748         "Tictactoe",
10749         sizeof (Tictactoe),
10750         sizeof (TictactoeClass),
10751         (GtkClassInitFunc) tictactoe_class_init,
10752         (GtkObjectInitFunc) tictactoe_init,
10753         (GtkArgSetFunc) NULL,
10754         (GtkArgGetFunc) NULL
10755       };
10756
10757       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
10758     }
10759
10760   return ttt_type;
10761 }
10762 </verb></tscreen>
10763
10764 The GtkTypeInfo structure has the following definition:
10765
10766 <tscreen><verb>
10767 struct _GtkTypeInfo
10768 {
10769   gchar *type_name;
10770   guint object_size;
10771   guint class_size;
10772   GtkClassInitFunc class_init_func;
10773   GtkObjectInitFunc object_init_func;
10774   GtkArgSetFunc arg_set_func;
10775   GtkArgGetFunc arg_get_func;
10776 };
10777 </verb></tscreen>
10778
10779 The fields of this structure are pretty self-explanatory. We'll ignore
10780 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
10781 but as yet largely
10782 unimplemented, role in allowing widget options to be conveniently set
10783 from interpreted languages. Once GTK has a correctly filled in copy of
10784 this structure, it knows how to create objects of a particular widget
10785 type. 
10786
10787 <!-- ----------------------------------------------------------------- -->
10788 <sect2> The <tt/_class_init()/ function
10789 <p>
10790 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
10791 the widget's class structure, and sets up any signals for the
10792 class. For our Tictactoe widget it looks like:
10793
10794 <tscreen><verb>
10795
10796 enum {
10797   TICTACTOE_SIGNAL,
10798   LAST_SIGNAL
10799 };
10800
10801 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
10802
10803 static void
10804 tictactoe_class_init (TictactoeClass *class)
10805 {
10806   GtkObjectClass *object_class;
10807
10808   object_class = (GtkObjectClass*) class;
10809   
10810   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
10811                                          GTK_RUN_FIRST,
10812                                          object_class->type,
10813                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
10814                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
10815
10816
10817   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
10818
10819   class->tictactoe = NULL;
10820 }
10821 </verb></tscreen>
10822
10823 Our widget has just one signal, the <tt/tictactoe/ signal that is
10824 invoked when a row, column, or diagonal is completely filled in. Not
10825 every composite widget needs signals, so if you are reading this for
10826 the first time, you may want to skip to the next section now, as
10827 things are going to get a bit complicated.
10828
10829 The function:
10830
10831 <tscreen><verb>
10832 gint gtk_signal_new( const gchar         *name,
10833                      GtkSignalRunType     run_type,
10834                      GtkType              object_type,
10835                      gint                 function_offset,
10836                      GtkSignalMarshaller  marshaller,
10837                      GtkType              return_val,
10838                      guint                nparams,
10839                      ...);
10840 </verb></tscreen>
10841
10842 Creates a new signal. The parameters are:
10843
10844 <itemize>
10845 <item> <tt/name/: The name of the signal.
10846 <item> <tt/run_type/: Whether the default handler runs before or after
10847 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
10848 although there are other possibilities.
10849 <item> <tt/object_type/: The ID of the object that this signal applies
10850 to. (It will also apply to that objects descendents)
10851 <item> <tt/function_offset/: The offset within the class structure of
10852 a pointer to the default handler.
10853 <item> <tt/marshaller/: A function that is used to invoke the signal
10854 handler. For signal handlers that have no arguments other than the
10855 object that emitted the signal and user data, we can use the
10856 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
10857 <item> <tt/return_val/: The type of the return val.
10858 <item> <tt/nparams/: The number of parameters of the signal handler
10859 (other than the two default ones mentioned above)
10860 <item> <tt/.../: The types of the parameters.
10861 </itemize>
10862
10863 When specifying types, the <tt/GtkType/ enumeration is used:
10864
10865 <tscreen><verb>
10866 typedef enum
10867 {
10868   GTK_TYPE_INVALID,
10869   GTK_TYPE_NONE,
10870   GTK_TYPE_CHAR,
10871   GTK_TYPE_BOOL,
10872   GTK_TYPE_INT,
10873   GTK_TYPE_UINT,
10874   GTK_TYPE_LONG,
10875   GTK_TYPE_ULONG,
10876   GTK_TYPE_FLOAT,
10877   GTK_TYPE_DOUBLE,
10878   GTK_TYPE_STRING,
10879   GTK_TYPE_ENUM,
10880   GTK_TYPE_FLAGS,
10881   GTK_TYPE_BOXED,
10882   GTK_TYPE_FOREIGN,
10883   GTK_TYPE_CALLBACK,
10884   GTK_TYPE_ARGS,
10885
10886   GTK_TYPE_POINTER,
10887
10888   /* it'd be great if the next two could be removed eventually */
10889   GTK_TYPE_SIGNAL,
10890   GTK_TYPE_C_CALLBACK,
10891
10892   GTK_TYPE_OBJECT
10893
10894 } GtkFundamentalType;
10895 </verb></tscreen>
10896
10897 <tt/gtk_signal_new()/ returns a unique integer identifier for the
10898 signal, that we store in the <tt/tictactoe_signals/ array, which we
10899 index using an enumeration. (Conventionally, the enumeration elements
10900 are the signal name, uppercased, but here there would be a conflict
10901 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
10902 instead.
10903
10904 After creating our signals, we need to tell GTK to associate our
10905 signals with the Tictactoe class. We do that by calling
10906 <tt/gtk_object_class_add_signals()/. We then set the pointer which
10907 points to the default handler for the `tictactoe' signal to NULL,
10908 indicating that there is no default action.
10909
10910 <!-- ----------------------------------------------------------------- -->
10911 <sect2> The <tt/_init()/ function.
10912 <p>
10913 Each widget class also needs a function to initialize the object
10914 structure. Usually, this function has the fairly limited role of
10915 setting the fields of the structure to default values. For composite
10916 widgets, however, this function also creates the component widgets.
10917
10918 <tscreen><verb>
10919 static void
10920 tictactoe_init (Tictactoe *ttt)
10921 {
10922   GtkWidget *table;
10923   gint i,j;
10924   
10925   table = gtk_table_new (3, 3, TRUE);
10926   gtk_container_add (GTK_CONTAINER(ttt), table);
10927   gtk_widget_show (table);
10928
10929   for (i=0;i<3; i++)
10930     for (j=0;j<3; j++)
10931       {
10932         ttt->buttons[i][j] = gtk_toggle_button_new ();
10933         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
10934                                    i, i+1, j, j+1);
10935         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
10936                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
10937         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
10938         gtk_widget_show (ttt->buttons[i][j]);
10939       }
10940 }
10941 </verb></tscreen>
10942
10943 <!-- ----------------------------------------------------------------- -->
10944 <sect2> And the rest...
10945 <p>
10946 There is one more function that every widget (except for base widget
10947 types like GtkBin that cannot be instantiated) needs to have - the
10948 function that the user calls to create an object of that type. This is
10949 conventionally called <tt/WIDGETNAME_new()/. In some
10950 widgets, though not for the Tictactoe widgets, this function takes
10951 arguments, and does some setup based on the arguments. The other two
10952 functions are specific to the Tictactoe widget. 
10953
10954 <tt/tictactoe_clear()/ is a public function that resets all the
10955 buttons in the widget to the up position. Note the use of
10956 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
10957 button toggles from being triggered unnecessarily.
10958
10959 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
10960 user clicks on a button. It checks to see if there are any winning
10961 combinations that involve the toggled button, and if so, emits
10962 the "tictactoe" signal.
10963
10964 <tscreen><verb>  
10965 GtkWidget*
10966 tictactoe_new ()
10967 {
10968   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
10969 }
10970
10971 void           
10972 tictactoe_clear (Tictactoe *ttt)
10973 {
10974   int i,j;
10975
10976   for (i=0;i<3;i++)
10977     for (j=0;j<3;j++)
10978       {
10979         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
10980         gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
10981                                      FALSE);
10982         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
10983       }
10984 }
10985
10986 static void
10987 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
10988 {
10989   int i,k;
10990
10991   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
10992                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
10993                              { 0, 1, 2 }, { 0, 1, 2 } };
10994   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
10995                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
10996                              { 0, 1, 2 }, { 2, 1, 0 } };
10997
10998   int success, found;
10999
11000   for (k=0; k<8; k++)
11001     {
11002       success = TRUE;
11003       found = FALSE;
11004
11005       for (i=0;i<3;i++)
11006         {
11007           success = success &amp;&amp; 
11008             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
11009           found = found ||
11010             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
11011         }
11012       
11013       if (success &amp;&amp; found)
11014         {
11015           gtk_signal_emit (GTK_OBJECT (ttt), 
11016                            tictactoe_signals[TICTACTOE_SIGNAL]);
11017           break;
11018         }
11019     }
11020 }
11021 </verb></tscreen>
11022
11023 And finally, an example program using our Tictactoe widget:
11024
11025 <tscreen><verb>
11026 #include <gtk/gtk.h>
11027 #include "tictactoe.h"
11028
11029 /* Invoked when a row, column or diagonal is completed */
11030 void
11031 win (GtkWidget *widget, gpointer data)
11032 {
11033   g_print ("Yay!\n");
11034   tictactoe_clear (TICTACTOE (widget));
11035 }
11036
11037 int 
11038 main (int argc, char *argv[])
11039 {
11040   GtkWidget *window;
11041   GtkWidget *ttt;
11042   
11043   gtk_init (&amp;argc, &amp;argv);
11044
11045   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11046   
11047   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
11048   
11049   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11050                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11051   
11052   gtk_container_border_width (GTK_CONTAINER (window), 10);
11053
11054   /* Create a new Tictactoe widget */
11055   ttt = tictactoe_new ();
11056   gtk_container_add (GTK_CONTAINER (window), ttt);
11057   gtk_widget_show (ttt);
11058
11059   /* And attach to its "tictactoe" signal */
11060   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
11061                       GTK_SIGNAL_FUNC (win), NULL);
11062
11063   gtk_widget_show (window);
11064   
11065   gtk_main ();
11066   
11067   return 0;
11068 }
11069
11070 </verb></tscreen>
11071
11072 <!-- ----------------------------------------------------------------- -->
11073 <sect1> Creating a widget from scratch.
11074
11075 <!-- ----------------------------------------------------------------- -->
11076 <sect2> Introduction
11077 <p>
11078 In this section, we'll learn more about how widgets display themselves
11079 on the screen and interact with events. As an example of this, we'll
11080 create an analog dial widget with a pointer that the user can drag to
11081 set the value.
11082
11083 <!-- ----------------------------------------------------------------- -->
11084 <sect2> Displaying a widget on the screen
11085 <p>
11086 There are several steps that are involved in displaying on the screen.
11087 After the widget is created with a call to <tt/WIDGETNAME_new()/,
11088 several more functions are needed:
11089
11090 <itemize>
11091 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
11092 window for the widget if it has one.
11093 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
11094 <tt/gtk_widget_show()/. It is responsible for making sure the widget
11095 is actually drawn on the screen (<em/mapped/). For a container class,
11096 it must also make calls to <tt/map()/> functions of any child widgets.
11097 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
11098 is called for the widget or one of its ancestors. It makes the actual
11099 calls to the drawing functions to draw the widget on the screen. For
11100 container widgets, this function must make calls to
11101 <tt/gtk_widget_draw()/ for its child widgets.
11102 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
11103 widget. It makes the necessary calls to the drawing functions to draw
11104 the exposed portion on the screen. For container widgets, this
11105 function must generate expose events for its child widgets which don't
11106 have their own windows. (If they have their own windows, then X will
11107 generate the necessary expose events)
11108 </itemize>
11109
11110 You might notice that the last two functions are quite similar - each
11111 is responsible for drawing the widget on the screen. In fact many
11112 types of widgets don't really care about the difference between the
11113 two. The default <tt/draw()/ function in the widget class simply
11114 generates a synthetic expose event for the redrawn area. However, some
11115 types of widgets can save work by distinguishing between the two
11116 functions. For instance, if a widget has multiple X windows, then
11117 since expose events identify the exposed window, it can redraw only
11118 the affected window, which is not possible for calls to <tt/draw()/.
11119
11120 Container widgets, even if they don't care about the difference for
11121 themselves, can't simply use the default <tt/draw()/ function because
11122 their child widgets might care about the difference. However,
11123 it would be wasteful to duplicate the drawing code between the two
11124 functions. The convention is that such widgets have a function called
11125 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
11126 widget, that is then called by the <tt/draw()/ and <tt/expose()/
11127 functions.
11128
11129 In our example approach, since the dial widget is not a container
11130 widget, and only has a single window, we can take the simplest
11131 approach and use the default <tt/draw()/ function and only implement
11132 an <tt/expose()/ function.
11133
11134 <!-- ----------------------------------------------------------------- -->
11135 <sect2> The origins of the Dial Widget
11136 <p>
11137 Just as all land animals are just variants on the first amphibian that
11138 crawled up out of the mud, Gtk widgets tend to start off as variants
11139 of some other, previously written widget.  Thus, although this section
11140 is entitled `Creating a Widget from Scratch', the Dial widget really
11141 began with the source code for the Range widget. This was picked as a
11142 starting point because it would be nice if our Dial had the same
11143 interface as the Scale widgets which are just specialized descendents
11144 of the Range widget. So, though the source code is presented below in
11145 finished form, it should not be implied that it was written, <em>deus
11146 ex machina</em> in this fashion. Also, if you aren't yet familiar with
11147 how scale widgets work from the application writer's point of view, it
11148 would be a good idea to look them over before continuing.
11149
11150 <!-- ----------------------------------------------------------------- -->
11151 <sect2> The Basics
11152 <p>
11153 Quite a bit of our widget should look pretty familiar from the
11154 Tictactoe widget. First, we have a header file:
11155
11156 <tscreen><verb>
11157 /* GTK - The GIMP Toolkit
11158  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
11159  *
11160  * This library is free software; you can redistribute it and/or
11161  * modify it under the terms of the GNU Library General Public
11162  * License as published by the Free Software Foundation; either
11163  * version 2 of the License, or (at your option) any later version.
11164  *
11165  * This library is distributed in the hope that it will be useful,
11166  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11167  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11168  * Library General Public License for more details.
11169  *
11170  * You should have received a copy of the GNU Library General Public
11171  * License along with this library; if not, write to the Free
11172  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11173  */
11174
11175 #ifndef __GTK_DIAL_H__
11176 #define __GTK_DIAL_H__
11177
11178 #include <gdk/gdk.h>
11179 #include <gtk/gtkadjustment.h>
11180 #include <gtk/gtkwidget.h>
11181
11182
11183 #ifdef __cplusplus
11184 extern "C" {
11185 #endif /* __cplusplus */
11186
11187
11188 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
11189 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
11190 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
11191
11192
11193 typedef struct _GtkDial        GtkDial;
11194 typedef struct _GtkDialClass   GtkDialClass;
11195
11196 struct _GtkDial
11197 {
11198   GtkWidget widget;
11199
11200   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
11201   guint policy : 2;
11202
11203   /* Button currently pressed or 0 if none */
11204   guint8 button;
11205
11206   /* Dimensions of dial components */
11207   gint radius;
11208   gint pointer_width;
11209
11210   /* ID of update timer, or 0 if none */
11211   guint32 timer;
11212
11213   /* Current angle */
11214   gfloat angle;
11215
11216   /* Old values from adjustment stored so we know when something changes */
11217   gfloat old_value;
11218   gfloat old_lower;
11219   gfloat old_upper;
11220
11221   /* The adjustment object that stores the data for this dial */
11222   GtkAdjustment *adjustment;
11223 };
11224
11225 struct _GtkDialClass
11226 {
11227   GtkWidgetClass parent_class;
11228 };
11229
11230
11231 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
11232 guint          gtk_dial_get_type               (void);
11233 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
11234 void           gtk_dial_set_update_policy      (GtkDial      *dial,
11235                                                 GtkUpdateType  policy);
11236
11237 void           gtk_dial_set_adjustment         (GtkDial      *dial,
11238                                                 GtkAdjustment *adjustment);
11239 #ifdef __cplusplus
11240 }
11241 #endif /* __cplusplus */
11242
11243
11244 #endif /* __GTK_DIAL_H__ */
11245 </verb></tscreen>
11246
11247 Since there is quite a bit more going on in this widget, than the last
11248 one, we have more fields in the data structure, but otherwise things
11249 are pretty similar.
11250
11251 Next, after including header files, and declaring a few constants,
11252 we have some functions to provide information about the widget
11253 and initialize it:
11254
11255 <tscreen><verb>
11256 #include <math.h>
11257 #include <stdio.h>
11258 #include <gtk/gtkmain.h>
11259 #include <gtk/gtksignal.h>
11260
11261 #include "gtkdial.h"
11262
11263 #define SCROLL_DELAY_LENGTH  300
11264 #define DIAL_DEFAULT_SIZE 100
11265
11266 /* Forward declarations */
11267
11268 [ omitted to save space ]
11269
11270 /* Local data */
11271
11272 static GtkWidgetClass *parent_class = NULL;
11273
11274 guint
11275 gtk_dial_get_type ()
11276 {
11277   static guint dial_type = 0;
11278
11279   if (!dial_type)
11280     {
11281       GtkTypeInfo dial_info =
11282       {
11283         "GtkDial",
11284         sizeof (GtkDial),
11285         sizeof (GtkDialClass),
11286         (GtkClassInitFunc) gtk_dial_class_init,
11287         (GtkObjectInitFunc) gtk_dial_init,
11288         (GtkArgSetFunc) NULL,
11289         (GtkArgGetFunc) NULL,
11290       };
11291
11292       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
11293     }
11294
11295   return dial_type;
11296 }
11297
11298 static void
11299 gtk_dial_class_init (GtkDialClass *class)
11300 {
11301   GtkObjectClass *object_class;
11302   GtkWidgetClass *widget_class;
11303
11304   object_class = (GtkObjectClass*) class;
11305   widget_class = (GtkWidgetClass*) class;
11306
11307   parent_class = gtk_type_class (gtk_widget_get_type ());
11308
11309   object_class->destroy = gtk_dial_destroy;
11310
11311   widget_class->realize = gtk_dial_realize;
11312   widget_class->expose_event = gtk_dial_expose;
11313   widget_class->size_request = gtk_dial_size_request;
11314   widget_class->size_allocate = gtk_dial_size_allocate;
11315   widget_class->button_press_event = gtk_dial_button_press;
11316   widget_class->button_release_event = gtk_dial_button_release;
11317   widget_class->motion_notify_event = gtk_dial_motion_notify;
11318 }
11319
11320 static void
11321 gtk_dial_init (GtkDial *dial)
11322 {
11323   dial->button = 0;
11324   dial->policy = GTK_UPDATE_CONTINUOUS;
11325   dial->timer = 0;
11326   dial->radius = 0;
11327   dial->pointer_width = 0;
11328   dial->angle = 0.0;
11329   dial->old_value = 0.0;
11330   dial->old_lower = 0.0;
11331   dial->old_upper = 0.0;
11332   dial->adjustment = NULL;
11333 }
11334
11335 GtkWidget*
11336 gtk_dial_new (GtkAdjustment *adjustment)
11337 {
11338   GtkDial *dial;
11339
11340   dial = gtk_type_new (gtk_dial_get_type ());
11341
11342   if (!adjustment)
11343     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
11344
11345   gtk_dial_set_adjustment (dial, adjustment);
11346
11347   return GTK_WIDGET (dial);
11348 }
11349
11350 static void
11351 gtk_dial_destroy (GtkObject *object)
11352 {
11353   GtkDial *dial;
11354
11355   g_return_if_fail (object != NULL);
11356   g_return_if_fail (GTK_IS_DIAL (object));
11357
11358   dial = GTK_DIAL (object);
11359
11360   if (dial->adjustment)
11361     gtk_object_unref (GTK_OBJECT (dial->adjustment));
11362
11363   if (GTK_OBJECT_CLASS (parent_class)->destroy)
11364     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
11365 }
11366 </verb></tscreen>
11367
11368 Note that this <tt/init()/ function does less than for the Tictactoe
11369 widget, since this is not a composite widget, and the <tt/new()/
11370 function does more, since it now has an argument. Also, note that when
11371 we store a pointer to the Adjustment object, we increment its
11372 reference count, (and correspondingly decrement when we no longer use
11373 it) so that GTK can keep track of when it can be safely destroyed.
11374
11375 <p>
11376 Also, there are a few function to manipulate the widget's options:
11377
11378 <tscreen><verb>
11379 GtkAdjustment*
11380 gtk_dial_get_adjustment (GtkDial *dial)
11381 {
11382   g_return_val_if_fail (dial != NULL, NULL);
11383   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
11384
11385   return dial->adjustment;
11386 }
11387
11388 void
11389 gtk_dial_set_update_policy (GtkDial      *dial,
11390                              GtkUpdateType  policy)
11391 {
11392   g_return_if_fail (dial != NULL);
11393   g_return_if_fail (GTK_IS_DIAL (dial));
11394
11395   dial->policy = policy;
11396 }
11397
11398 void
11399 gtk_dial_set_adjustment (GtkDial      *dial,
11400                           GtkAdjustment *adjustment)
11401 {
11402   g_return_if_fail (dial != NULL);
11403   g_return_if_fail (GTK_IS_DIAL (dial));
11404
11405   if (dial->adjustment)
11406     {
11407       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
11408       gtk_object_unref (GTK_OBJECT (dial->adjustment));
11409     }
11410
11411   dial->adjustment = adjustment;
11412   gtk_object_ref (GTK_OBJECT (dial->adjustment));
11413
11414   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
11415                       (GtkSignalFunc) gtk_dial_adjustment_changed,
11416                       (gpointer) dial);
11417   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
11418                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
11419                       (gpointer) dial);
11420
11421   dial->old_value = adjustment->value;
11422   dial->old_lower = adjustment->lower;
11423   dial->old_upper = adjustment->upper;
11424
11425   gtk_dial_update (dial);
11426 }
11427 </verb></tscreen>
11428
11429 <sect2> <tt/gtk_dial_realize()/
11430
11431 <p>
11432 Now we come to some new types of functions. First, we have a function
11433 that does the work of creating the X window. Notice that a mask is
11434 passed to the function <tt/gdk_window_new()/ which specifies which fields of
11435 the GdkWindowAttr structure actually have data in them (the remaining
11436 fields will be given default values). Also worth noting is the way the
11437 event mask of the widget is created. We call
11438 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
11439 has specified for this widget (with <tt/gtk_widget_set_events()/, and
11440 add the events that we are interested in ourselves.
11441
11442 <p>
11443 After creating the window, we set its style and background, and put a
11444 pointer to the widget in the user data field of the GdkWindow. This
11445 last step allows GTK to dispatch events for this window to the correct
11446 widget.
11447
11448 <tscreen><verb>
11449 static void
11450 gtk_dial_realize (GtkWidget *widget)
11451 {
11452   GtkDial *dial;
11453   GdkWindowAttr attributes;
11454   gint attributes_mask;
11455
11456   g_return_if_fail (widget != NULL);
11457   g_return_if_fail (GTK_IS_DIAL (widget));
11458
11459   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
11460   dial = GTK_DIAL (widget);
11461
11462   attributes.x = widget->allocation.x;
11463   attributes.y = widget->allocation.y;
11464   attributes.width = widget->allocation.width;
11465   attributes.height = widget->allocation.height;
11466   attributes.wclass = GDK_INPUT_OUTPUT;
11467   attributes.window_type = GDK_WINDOW_CHILD;
11468   attributes.event_mask = gtk_widget_get_events (widget) | 
11469     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
11470     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
11471     GDK_POINTER_MOTION_HINT_MASK;
11472   attributes.visual = gtk_widget_get_visual (widget);
11473   attributes.colormap = gtk_widget_get_colormap (widget);
11474
11475   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
11476   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
11477
11478   widget->style = gtk_style_attach (widget->style, widget->window);
11479
11480   gdk_window_set_user_data (widget->window, widget);
11481
11482   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
11483 }
11484 </verb></tscreen>
11485
11486 <sect2> Size negotiation
11487
11488 <p>
11489 Before the first time that the window containing a widget is
11490 displayed, and whenever the layout of the window changes, GTK asks
11491 each child widget for its desired size. This request is handled by the
11492 function, <tt/gtk_dial_size_request()/. Since our widget isn't a
11493 container widget, and has no real constraints on its size, we just
11494 return a reasonable default value.
11495
11496 <tscreen><verb>
11497 static void 
11498 gtk_dial_size_request (GtkWidget      *widget,
11499                        GtkRequisition *requisition)
11500 {
11501   requisition->width = DIAL_DEFAULT_SIZE;
11502   requisition->height = DIAL_DEFAULT_SIZE;
11503 }
11504 </verb></tscreen>
11505
11506 <p>
11507 After all the widgets have requested an ideal size, the layout of the
11508 window is computed and each child widget is notified of its actual
11509 size. Usually, this will at least as large as the requested size, but
11510 if for instance, the user has resized the window, it may occasionally
11511 be smaller than the requested size. The size notification is handled
11512 by the function <tt/gtk_dial_size_allocate()/. Notice that as well as
11513 computing the sizes of some component pieces for future use, this
11514 routine also does the grunt work of moving the widgets X window into
11515 the new position and size.
11516
11517 <tscreen><verb>
11518 static void
11519 gtk_dial_size_allocate (GtkWidget     *widget,
11520                         GtkAllocation *allocation)
11521 {
11522   GtkDial *dial;
11523
11524   g_return_if_fail (widget != NULL);
11525   g_return_if_fail (GTK_IS_DIAL (widget));
11526   g_return_if_fail (allocation != NULL);
11527
11528   widget->allocation = *allocation;
11529   if (GTK_WIDGET_REALIZED (widget))
11530     {
11531       dial = GTK_DIAL (widget);
11532
11533       gdk_window_move_resize (widget->window,
11534                               allocation->x, allocation->y,
11535                               allocation->width, allocation->height);
11536
11537       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
11538       dial->pointer_width = dial->radius / 5;
11539     }
11540 }
11541 </verb></tscreen>.
11542
11543 <!-- ----------------------------------------------------------------- -->
11544 <sect2> <tt/gtk_dial_expose()/
11545
11546 <p>
11547 As mentioned above, all the drawing of this widget is done in the
11548 handler for expose events. There's not much to remark on here except
11549 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
11550 three dimensional shading according to the colors stored in the
11551 widget's style.
11552
11553 <tscreen><verb>
11554 static gint
11555 gtk_dial_expose (GtkWidget      *widget,
11556                  GdkEventExpose *event)
11557 {
11558   GtkDial *dial;
11559   GdkPoint points[3];
11560   gdouble s,c;
11561   gdouble theta;
11562   gint xc, yc;
11563   gint tick_length;
11564   gint i;
11565
11566   g_return_val_if_fail (widget != NULL, FALSE);
11567   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
11568   g_return_val_if_fail (event != NULL, FALSE);
11569
11570   if (event->count > 0)
11571     return FALSE;
11572   
11573   dial = GTK_DIAL (widget);
11574
11575   gdk_window_clear_area (widget->window,
11576                          0, 0,
11577                          widget->allocation.width,
11578                          widget->allocation.height);
11579
11580   xc = widget->allocation.width/2;
11581   yc = widget->allocation.height/2;
11582
11583   /* Draw ticks */
11584
11585   for (i=0; i<25; i++)
11586     {
11587       theta = (i*M_PI/18. - M_PI/6.);
11588       s = sin(theta);
11589       c = cos(theta);
11590
11591       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
11592       
11593       gdk_draw_line (widget->window,
11594                      widget->style->fg_gc[widget->state],
11595                      xc + c*(dial->radius - tick_length),
11596                      yc - s*(dial->radius - tick_length),
11597                      xc + c*dial->radius,
11598                      yc - s*dial->radius);
11599     }
11600
11601   /* Draw pointer */
11602
11603   s = sin(dial->angle);
11604   c = cos(dial->angle);
11605
11606
11607   points[0].x = xc + s*dial->pointer_width/2;
11608   points[0].y = yc + c*dial->pointer_width/2;
11609   points[1].x = xc + c*dial->radius;
11610   points[1].y = yc - s*dial->radius;
11611   points[2].x = xc - s*dial->pointer_width/2;
11612   points[2].y = yc - c*dial->pointer_width/2;
11613
11614   gtk_draw_polygon (widget->style,
11615                     widget->window,
11616                     GTK_STATE_NORMAL,
11617                     GTK_SHADOW_OUT,
11618                     points, 3,
11619                     TRUE);
11620   
11621   return FALSE;
11622 }
11623 </verb></tscreen>
11624
11625 <!-- ----------------------------------------------------------------- -->
11626 <sect2> Event handling
11627
11628 <p>
11629
11630 The rest of the widget's code handles various types of events, and
11631 isn't too different from what would be found in many GTK
11632 applications. Two types of events can occur - either the user can
11633 click on the widget with the mouse and drag to move the pointer, or
11634 the value of the Adjustment object can change due to some external
11635 circumstance. 
11636
11637 <p>
11638 When the user clicks on the widget, we check to see if the click was
11639 appropriately near the pointer, and if so, store then button that the
11640 user clicked with in the <tt/button/ field of the widget
11641 structure, and grab all mouse events with a call to
11642 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
11643 value of the control to be recomputed (by the function
11644 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
11645 set, "value_changed" events are either generated instantly
11646 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
11647 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
11648 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
11649
11650 <tscreen><verb>
11651 static gint
11652 gtk_dial_button_press (GtkWidget      *widget,
11653                        GdkEventButton *event)
11654 {
11655   GtkDial *dial;
11656   gint dx, dy;
11657   double s, c;
11658   double d_parallel;
11659   double d_perpendicular;
11660
11661   g_return_val_if_fail (widget != NULL, FALSE);
11662   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
11663   g_return_val_if_fail (event != NULL, FALSE);
11664
11665   dial = GTK_DIAL (widget);
11666
11667   /* Determine if button press was within pointer region - we 
11668      do this by computing the parallel and perpendicular distance of
11669      the point where the mouse was pressed from the line passing through
11670      the pointer */
11671   
11672   dx = event->x - widget->allocation.width / 2;
11673   dy = widget->allocation.height / 2 - event->y;
11674   
11675   s = sin(dial->angle);
11676   c = cos(dial->angle);
11677   
11678   d_parallel = s*dy + c*dx;
11679   d_perpendicular = fabs(s*dx - c*dy);
11680   
11681   if (!dial->button &&
11682       (d_perpendicular < dial->pointer_width/2) &&
11683       (d_parallel > - dial->pointer_width))
11684     {
11685       gtk_grab_add (widget);
11686
11687       dial->button = event->button;
11688
11689       gtk_dial_update_mouse (dial, event->x, event->y);
11690     }
11691
11692   return FALSE;
11693 }
11694
11695 static gint
11696 gtk_dial_button_release (GtkWidget      *widget,
11697                           GdkEventButton *event)
11698 {
11699   GtkDial *dial;
11700
11701   g_return_val_if_fail (widget != NULL, FALSE);
11702   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
11703   g_return_val_if_fail (event != NULL, FALSE);
11704
11705   dial = GTK_DIAL (widget);
11706
11707   if (dial->button == event->button)
11708     {
11709       gtk_grab_remove (widget);
11710
11711       dial->button = 0;
11712
11713       if (dial->policy == GTK_UPDATE_DELAYED)
11714         gtk_timeout_remove (dial->timer);
11715       
11716       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
11717           (dial->old_value != dial->adjustment->value))
11718         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
11719     }
11720
11721   return FALSE;
11722 }
11723
11724 static gint
11725 gtk_dial_motion_notify (GtkWidget      *widget,
11726                          GdkEventMotion *event)
11727 {
11728   GtkDial *dial;
11729   GdkModifierType mods;
11730   gint x, y, mask;
11731
11732   g_return_val_if_fail (widget != NULL, FALSE);
11733   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
11734   g_return_val_if_fail (event != NULL, FALSE);
11735
11736   dial = GTK_DIAL (widget);
11737
11738   if (dial->button != 0)
11739     {
11740       x = event->x;
11741       y = event->y;
11742
11743       if (event->is_hint || (event->window != widget->window))
11744         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
11745
11746       switch (dial->button)
11747         {
11748         case 1:
11749           mask = GDK_BUTTON1_MASK;
11750           break;
11751         case 2:
11752           mask = GDK_BUTTON2_MASK;
11753           break;
11754         case 3:
11755           mask = GDK_BUTTON3_MASK;
11756           break;
11757         default:
11758           mask = 0;
11759           break;
11760         }
11761
11762       if (mods & mask)
11763         gtk_dial_update_mouse (dial, x,y);
11764     }
11765
11766   return FALSE;
11767 }
11768
11769 static gint
11770 gtk_dial_timer (GtkDial *dial)
11771 {
11772   g_return_val_if_fail (dial != NULL, FALSE);
11773   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
11774
11775   if (dial->policy == GTK_UPDATE_DELAYED)
11776     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
11777
11778   return FALSE;
11779 }
11780
11781 static void
11782 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
11783 {
11784   gint xc, yc;
11785   gfloat old_value;
11786
11787   g_return_if_fail (dial != NULL);
11788   g_return_if_fail (GTK_IS_DIAL (dial));
11789
11790   xc = GTK_WIDGET(dial)->allocation.width / 2;
11791   yc = GTK_WIDGET(dial)->allocation.height / 2;
11792
11793   old_value = dial->adjustment->value;
11794   dial->angle = atan2(yc-y, x-xc);
11795
11796   if (dial->angle < -M_PI/2.)
11797     dial->angle += 2*M_PI;
11798
11799   if (dial->angle < -M_PI/6)
11800     dial->angle = -M_PI/6;
11801
11802   if (dial->angle > 7.*M_PI/6.)
11803     dial->angle = 7.*M_PI/6.;
11804
11805   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
11806     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
11807
11808   if (dial->adjustment->value != old_value)
11809     {
11810       if (dial->policy == GTK_UPDATE_CONTINUOUS)
11811         {
11812           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
11813         }
11814       else
11815         {
11816           gtk_widget_draw (GTK_WIDGET(dial), NULL);
11817
11818           if (dial->policy == GTK_UPDATE_DELAYED)
11819             {
11820               if (dial->timer)
11821                 gtk_timeout_remove (dial->timer);
11822
11823               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
11824                                              (GtkFunction) gtk_dial_timer,
11825                                              (gpointer) dial);
11826             }
11827         }
11828     }
11829 }
11830 </verb></tscreen>
11831
11832 <p>
11833 Changes to the Adjustment by external means are communicated to our
11834 widget by the `changed' and `value_changed' signals. The handlers
11835 for these functions call <tt/gtk_dial_update()/ to validate the
11836 arguments, compute the new pointer angle, and redraw the widget (by
11837 calling <tt/gtk_widget_draw()/).
11838
11839 <tscreen><verb>
11840 static void
11841 gtk_dial_update (GtkDial *dial)
11842 {
11843   gfloat new_value;
11844   
11845   g_return_if_fail (dial != NULL);
11846   g_return_if_fail (GTK_IS_DIAL (dial));
11847
11848   new_value = dial->adjustment->value;
11849   
11850   if (new_value < dial->adjustment->lower)
11851     new_value = dial->adjustment->lower;
11852
11853   if (new_value > dial->adjustment->upper)
11854     new_value = dial->adjustment->upper;
11855
11856   if (new_value != dial->adjustment->value)
11857     {
11858       dial->adjustment->value = new_value;
11859       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
11860     }
11861
11862   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
11863     (dial->adjustment->upper - dial->adjustment->lower);
11864
11865   gtk_widget_draw (GTK_WIDGET(dial), NULL);
11866 }
11867
11868 static void
11869 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
11870                               gpointer       data)
11871 {
11872   GtkDial *dial;
11873
11874   g_return_if_fail (adjustment != NULL);
11875   g_return_if_fail (data != NULL);
11876
11877   dial = GTK_DIAL (data);
11878
11879   if ((dial->old_value != adjustment->value) ||
11880       (dial->old_lower != adjustment->lower) ||
11881       (dial->old_upper != adjustment->upper))
11882     {
11883       gtk_dial_update (dial);
11884
11885       dial->old_value = adjustment->value;
11886       dial->old_lower = adjustment->lower;
11887       dial->old_upper = adjustment->upper;
11888     }
11889 }
11890
11891 static void
11892 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
11893                                     gpointer       data)
11894 {
11895   GtkDial *dial;
11896
11897   g_return_if_fail (adjustment != NULL);
11898   g_return_if_fail (data != NULL);
11899
11900   dial = GTK_DIAL (data);
11901
11902   if (dial->old_value != adjustment->value)
11903     {
11904       gtk_dial_update (dial);
11905
11906       dial->old_value = adjustment->value;
11907     }
11908 }
11909 </verb></tscreen>
11910
11911 <!-- ----------------------------------------------------------------- -->
11912 <sect2> Possible Enhancements
11913 <p>
11914
11915 The Dial widget as we've described it so far runs about 670 lines of
11916 code. Although that might sound like a fair bit, we've really
11917 accomplished quite a bit with that much code, especially since much of
11918 that length is headers and boilerplate. However, there are quite a few
11919 more enhancements that could be made to this widget:
11920
11921 <itemize>
11922 <item> If you try this widget out, you'll find that there is some
11923 flashing as the pointer is dragged around. This is because the entire
11924 widget is erased every time the pointer is moved before being
11925 redrawn. Often, the best way to handle this problem is to draw to an
11926 offscreen pixmap, then copy the final results onto the screen in one
11927 step. (The ProgressBar widget draws itself in this fashion.)
11928
11929 <item> The user should be able to use the up and down arrow keys to
11930 increase and decrease the value.
11931
11932 <item> It would be nice if the widget had buttons to increase and
11933 decrease the value in small or large steps. Although it would be
11934 possible to use embedded Button widgets for this, we would also like
11935 the buttons to auto-repeat when held down, as the arrows on a
11936 scrollbar do. Most of the code to implement this type of behavior can
11937 be found in the GtkRange widget.
11938
11939 <item> The Dial widget could be made into a container widget with a
11940 single child widget positioned at the bottom between the buttons
11941 mentioned above. The user could then add their choice of a label or
11942 entry widget to display the current value of the dial.
11943
11944 </itemize>
11945
11946 <!-- ----------------------------------------------------------------- -->
11947 <sect1> Learning More
11948
11949 <p>
11950 Only a small part of the many details involved in creating widgets
11951 could be described above. If you want to write your own widgets, the
11952 best source of examples is the GTK source itself. Ask yourself some
11953 questions about the widget you want to write: is it a Container
11954 widget? does it have its own window? is it a modification of an
11955 existing widget? Then find a similar widget, and start making changes.
11956 Good luck!
11957
11958 <!-- ***************************************************************** -->
11959 <sect>Scribble, A Simple Example Drawing Program
11960 <!-- ***************************************************************** -->
11961
11962 <!-- ----------------------------------------------------------------- -->
11963 <sect1> Overview
11964
11965 <p>
11966 In this section, we will build a simple drawing program. In the
11967 process, we will examine how to handle mouse events, how to draw in a
11968 window, and how to do drawing better by using a backing pixmap. After
11969 creating the simple drawing program, we will extend it by adding
11970 support for XInput devices, such as drawing tablets. GTK provides
11971 support routines which makes getting extended information, such as
11972 pressure and tilt, from such devices quite easy.
11973
11974 <!-- ----------------------------------------------------------------- -->
11975 <sect1> Event Handling
11976
11977 <p>
11978 The GTK signals we have already discussed are for high-level actions,
11979 such as a menu item being selected. However, sometimes it is useful to
11980 learn about lower-level occurrences, such as the mouse being moved, or
11981 a key being pressed. There are also GTK signals corresponding to these
11982 low-level <em>events</em>. The handlers for these signals have an
11983 extra parameter which is a pointer to a structure containing
11984 information about the event. For instance, motion events handlers are
11985 passed a pointer to a GdkEventMotion structure which looks (in part)
11986 like:
11987
11988 <tscreen><verb>
11989 struct _GdkEventMotion
11990 {
11991   GdkEventType type;
11992   GdkWindow *window;
11993   guint32 time;
11994   gdouble x;
11995   gdouble y;
11996   ...
11997   guint state;
11998   ...
11999 };
12000 </verb></tscreen>
12001
12002 <tt/type/ will be set to the event type, in this case
12003 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
12004 occurred. <tt/x/ and <tt/y/ give the coordinates of the event,
12005 and <tt/state/ specifies the modifier state when the event
12006 occurred (that is, it specifies which modifier keys and mouse buttons
12007 were pressed.) It is the bitwise OR of some of the following:
12008
12009 <tscreen><verb>
12010 GDK_SHIFT_MASK  
12011 GDK_LOCK_MASK   
12012 GDK_CONTROL_MASK
12013 GDK_MOD1_MASK   
12014 GDK_MOD2_MASK   
12015 GDK_MOD3_MASK   
12016 GDK_MOD4_MASK   
12017 GDK_MOD5_MASK   
12018 GDK_BUTTON1_MASK
12019 GDK_BUTTON2_MASK
12020 GDK_BUTTON3_MASK
12021 GDK_BUTTON4_MASK
12022 GDK_BUTTON5_MASK
12023 </verb></tscreen>
12024
12025 <p>
12026 As for other signals, to determine what happens when an event occurs
12027 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
12028 know which events we want to be notified about. To do this, we call
12029 the function:
12030
12031 <tscreen><verb>
12032 void gtk_widget_set_events (GtkWidget *widget,
12033                             gint      events);
12034 </verb></tscreen>
12035
12036 The second field specifies the events we are interested in. It
12037 is the bitwise OR of constants that specify different types
12038 of events. For future reference the event types are:
12039
12040 <tscreen><verb>
12041 GDK_EXPOSURE_MASK
12042 GDK_POINTER_MOTION_MASK
12043 GDK_POINTER_MOTION_HINT_MASK
12044 GDK_BUTTON_MOTION_MASK     
12045 GDK_BUTTON1_MOTION_MASK    
12046 GDK_BUTTON2_MOTION_MASK    
12047 GDK_BUTTON3_MOTION_MASK    
12048 GDK_BUTTON_PRESS_MASK      
12049 GDK_BUTTON_RELEASE_MASK    
12050 GDK_KEY_PRESS_MASK         
12051 GDK_KEY_RELEASE_MASK       
12052 GDK_ENTER_NOTIFY_MASK      
12053 GDK_LEAVE_NOTIFY_MASK      
12054 GDK_FOCUS_CHANGE_MASK      
12055 GDK_STRUCTURE_MASK         
12056 GDK_PROPERTY_CHANGE_MASK   
12057 GDK_PROXIMITY_IN_MASK      
12058 GDK_PROXIMITY_OUT_MASK     
12059 </verb></tscreen>
12060
12061 There are a few subtle points that have to be observed when calling
12062 <tt/gtk_widget_set_events()/. First, it must be called before the X window
12063 for a GTK widget is created. In practical terms, this means you
12064 should call it immediately after creating the widget. Second, the
12065 widget must have an associated X window. For efficiency, many widget
12066 types do not have their own window, but draw in their parent's window.
12067 These widgets are:
12068
12069 <tscreen><verb>
12070 GtkAlignment
12071 GtkArrow
12072 GtkBin
12073 GtkBox
12074 GtkImage
12075 GtkItem
12076 GtkLabel
12077 GtkPixmap
12078 GtkScrolledWindow
12079 GtkSeparator
12080 GtkTable
12081 GtkAspectFrame
12082 GtkFrame
12083 GtkVBox
12084 GtkHBox
12085 GtkVSeparator
12086 GtkHSeparator
12087 </verb></tscreen>
12088
12089 To capture events for these widgets, you need to use an EventBox 
12090 widget. See the section on   
12091 <ref id="sec_The_EventBox_Widget" name="The EventBox Widget"> for
12092 details.
12093
12094 <p>
12095 For our drawing program, we want to know when the mouse button is
12096 pressed and when the mouse is moved, so we specify
12097 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
12098 want to know when we need to redraw our window, so we specify
12099 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
12100 Configure event when our window size changes, we don't have to specify
12101 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
12102 automatically specified for all windows.
12103
12104 <p>
12105 It turns out, however, that there is a problem with just specifying
12106 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
12107 motion event to the event queue every time the user moves the mouse.
12108 Imagine that it takes us 0.1 seconds to handle a motion event, but the
12109 X server queues a new motion event every 0.05 seconds. We will soon
12110 get way behind the users drawing. If the user draws for 5 seconds,
12111 it will take us another 5 seconds to catch up after they release 
12112 the mouse button! What we would like is to only get one motion
12113 event for each event we process. The way to do this is to 
12114 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
12115
12116 <p>
12117 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
12118 us a motion event the first time the pointer moves after entering
12119 our window, or after a button press or release event. Subsequent 
12120 motion events will be suppressed until we explicitly ask for
12121 the position of the pointer using the function:
12122
12123 <tscreen><verb>
12124 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
12125                                           gint            *x,
12126                                           gint            *y,
12127                                           GdkModifierType *mask);
12128 </verb></tscreen>
12129
12130 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
12131 has a simpler interface, but turns out not to be very useful, since
12132 it only retrieves the position of the mouse, not whether the buttons
12133 are pressed.)
12134
12135 <p>
12136 The code to set the events for our window then looks like:
12137
12138 <tscreen><verb>
12139   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
12140                       (GtkSignalFunc) expose_event, NULL);
12141   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
12142                       (GtkSignalFunc) configure_event, NULL);
12143   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
12144                       (GtkSignalFunc) motion_notify_event, NULL);
12145   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
12146                       (GtkSignalFunc) button_press_event, NULL);
12147
12148   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
12149                          | GDK_LEAVE_NOTIFY_MASK
12150                          | GDK_BUTTON_PRESS_MASK
12151                          | GDK_POINTER_MOTION_MASK
12152                          | GDK_POINTER_MOTION_HINT_MASK);
12153 </verb></tscreen>
12154
12155 We'll save the "expose_event" and "configure_event" handlers for
12156 later. The "motion_notify_event" and "button_press_event" handlers
12157 pretty simple:
12158
12159 <tscreen><verb>
12160 static gint
12161 button_press_event (GtkWidget *widget, GdkEventButton *event)
12162 {
12163   if (event->button == 1 &amp;&amp; pixmap != NULL)
12164       draw_brush (widget, event->x, event->y);
12165
12166   return TRUE;
12167 }
12168
12169 static gint
12170 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
12171 {
12172   int x, y;
12173   GdkModifierType state;
12174
12175   if (event->is_hint)
12176     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
12177   else
12178     {
12179       x = event->x;
12180       y = event->y;
12181       state = event->state;
12182     }
12183     
12184   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
12185     draw_brush (widget, x, y);
12186   
12187   return TRUE;
12188 }
12189 </verb></tscreen>
12190
12191 <!-- ----------------------------------------------------------------- -->
12192 <sect1> The DrawingArea Widget, And Drawing
12193
12194 <p>
12195 We know turn to the process of drawing on the screen. The 
12196 widget we use for this is the DrawingArea widget. A drawing area
12197 widget is essentially an X window and nothing more. It is a blank
12198 canvas in which we can draw whatever we like. A drawing area
12199 is created using the call:
12200
12201 <tscreen><verb>
12202 GtkWidget* gtk_drawing_area_new        (void);
12203 </verb></tscreen>
12204
12205 A default size for the widget can be specified by calling:
12206
12207 <tscreen><verb>
12208 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
12209                                         gint                 width,
12210                                         gint                 height);
12211 </verb></tscreen>
12212
12213 This default size can be overridden, as is true for all widgets,
12214 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
12215 be overridden if the user manually resizes the the window containing
12216 the drawing area.
12217
12218 <p>
12219 It should be noted that when we create a DrawingArea widget, we are,
12220 <em>completely</em> responsible for drawing the contents. If our
12221 window is obscured then uncovered, we get an exposure event and must
12222 redraw what was previously hidden.
12223
12224 <p>
12225 Having to remember everything that was drawn on the screen so we
12226 can properly redraw it can, to say the least, be a nuisance. In
12227 addition, it can be visually distracting if portions of the
12228 window are cleared, then redrawn step by step. The solution to
12229 this problem is to use an offscreen <em>backing pixmap</em>.
12230 Instead of drawing directly to the screen, we draw to an image
12231 stored in server memory but not displayed, then when the image
12232 changes or new portions of the image are displayed, we copy the
12233 relevant portions onto the screen.
12234
12235 <p>
12236 To create an offscreen pixmap, we call the function:
12237
12238 <tscreen><verb>
12239 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
12240                                          gint        width,
12241                                          gint        height,
12242                                          gint        depth);
12243 </verb></tscreen>
12244
12245 The <tt>window</tt> parameter specifies a GDK window that this pixmap
12246 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
12247 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
12248 depth</em>, that is the number of bits per pixel, for the new window.
12249 If the depth is specified as <tt>-1</tt>, it will match the depth
12250 of <tt>window</tt>.
12251
12252 <p>
12253 We create the pixmap in our "configure_event" handler. This event
12254 is generated whenever the window changes size, including when it
12255 is originally created.
12256
12257 <tscreen><verb>
12258 /* Backing pixmap for drawing area */
12259 static GdkPixmap *pixmap = NULL;
12260
12261 /* Create a new backing pixmap of the appropriate size */
12262 static gint
12263 configure_event (GtkWidget *widget, GdkEventConfigure *event)
12264 {
12265   if (pixmap)
12266     gdk_pixmap_unref(pixmap);
12267
12268   pixmap = gdk_pixmap_new(widget->window,
12269                           widget->allocation.width,
12270                           widget->allocation.height,
12271                           -1);
12272   gdk_draw_rectangle (pixmap,
12273                       widget->style->white_gc,
12274                       TRUE,
12275                       0, 0,
12276                       widget->allocation.width,
12277                       widget->allocation.height);
12278
12279   return TRUE;
12280 }
12281 </verb></tscreen>
12282
12283 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
12284 initially to white. We'll say more about that in a moment.
12285
12286 <p>
12287 Our exposure event handler then simply copies the relevant portion
12288 of the pixmap onto the screen (we determine the area we need
12289 to redraw by using the event->area field of the exposure event):
12290
12291 <tscreen><verb>
12292 /* Redraw the screen from the backing pixmap */
12293 static gint
12294 expose_event (GtkWidget *widget, GdkEventExpose *event)
12295 {
12296   gdk_draw_pixmap(widget->window,
12297                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
12298                   pixmap,
12299                   event->area.x, event->area.y,
12300                   event->area.x, event->area.y,
12301                   event->area.width, event->area.height);
12302
12303   return FALSE;
12304 }
12305 </verb></tscreen>
12306
12307 We've now seen how to keep the screen up to date with our pixmap, but
12308 how do we actually draw interesting stuff on our pixmap?  There are a
12309 large number of calls in GTK's GDK library for drawing on
12310 <em>drawables</em>. A drawable is simply something that can be drawn
12311 upon. It can be a window, a pixmap, or a bitmap (a black and white
12312 image).  We've already seen two such calls above,
12313 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
12314 complete list is:
12315
12316 <tscreen><verb>
12317 gdk_draw_line ()
12318 gdk_draw_rectangle ()
12319 gdk_draw_arc ()
12320 gdk_draw_polygon ()
12321 gdk_draw_string ()
12322 gdk_draw_text ()
12323 gdk_draw_pixmap ()
12324 gdk_draw_bitmap ()
12325 gdk_draw_image ()
12326 gdk_draw_points ()
12327 gdk_draw_segments ()
12328 </verb></tscreen>
12329
12330 See the reference documentation or the header file
12331 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
12332 These functions all share the same first two arguments. The first
12333 argument is the drawable to draw upon, the second argument is a
12334 <em>graphics context</em> (GC). 
12335
12336 <p>
12337 A graphics context encapsulates information about things such as
12338 foreground and background color and line width. GDK has a full set of
12339 functions for creating and modifying graphics contexts, but to keep
12340 things simple we'll just use predefined graphics contexts. Each widget
12341 has an associated style. (Which can be modified in a gtkrc file, see
12342 the section GTK's rc file.) This, among other things, stores a number
12343 of graphics contexts. Some examples of accessing these graphics
12344 contexts are:
12345
12346 <tscreen><verb>
12347 widget->style->white_gc
12348 widget->style->black_gc
12349 widget->style->fg_gc[GTK_STATE_NORMAL]
12350 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
12351 </verb></tscreen>
12352
12353 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
12354 <tt>light_gc</tt> are indexed by a parameter of type
12355 <tt>GtkStateType</tt> which can take on the values:
12356
12357 <tscreen><verb>
12358 GTK_STATE_NORMAL,
12359 GTK_STATE_ACTIVE,
12360 GTK_STATE_PRELIGHT,
12361 GTK_STATE_SELECTED,
12362 GTK_STATE_INSENSITIVE
12363 </verb></tscreen>
12364
12365 For instance, the for <tt/GTK_STATE_SELECTED/ the default foreground
12366 color is white and the default background color, dark blue.
12367
12368 <p>
12369 Our function <tt>draw_brush()</tt>, which does the actual drawing
12370 on the screen, is then:
12371
12372 <tscreen><verb>
12373 /* Draw a rectangle on the screen */
12374 static void
12375 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
12376 {
12377   GdkRectangle update_rect;
12378
12379   update_rect.x = x - 5;
12380   update_rect.y = y - 5;
12381   update_rect.width = 10;
12382   update_rect.height = 10;
12383   gdk_draw_rectangle (pixmap,
12384                       widget->style->black_gc,
12385                       TRUE,
12386                       update_rect.x, update_rect.y,
12387                       update_rect.width, update_rect.height);
12388   gtk_widget_draw (widget, &amp;update_rect);
12389 }
12390 </verb></tscreen>
12391
12392 After we draw the rectangle representing the brush onto the pixmap,
12393 we call the function:
12394
12395 <tscreen><verb>
12396 void       gtk_widget_draw                (GtkWidget           *widget,
12397                                            GdkRectangle        *area);
12398 </verb></tscreen>
12399
12400 which notifies X that the area given by the <tt>area</tt> parameter
12401 needs to be updated. X will eventually generate an expose event
12402 (possibly combining the areas passed in several calls to
12403 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
12404 to copy the relevant portions to the screen.
12405
12406 <p>
12407 We have now covered the entire drawing program except for a few
12408 mundane details like creating the main window. The complete
12409 source code is available from the location from which you got
12410 this tutorial, or from:
12411
12412 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12413 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12414
12415
12416 <!-- ----------------------------------------------------------------- -->
12417 <sect1> Adding XInput support
12418
12419 <p>
12420
12421 It is now possible to buy quite inexpensive input devices such 
12422 as drawing tablets, which allow drawing with a much greater
12423 ease of artistic expression than does a mouse. The simplest way
12424 to use such devices is simply as a replacement for the mouse,
12425 but that misses out many of the advantages of these devices,
12426 such as:
12427
12428 <itemize>
12429 <item> Pressure sensitivity
12430 <item> Tilt reporting
12431 <item> Sub-pixel positioning
12432 <item> Multiple inputs (for example, a stylus with a point and eraser)
12433 </itemize>
12434
12435 For information about the XInput extension, see the <htmlurl
12436 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
12437 name="XInput-HOWTO">.
12438
12439 <p>
12440 If we examine the full definition of, for example, the GdkEventMotion
12441 structure, we see that it has fields to support extended device
12442 information.
12443
12444 <tscreen><verb>
12445 struct _GdkEventMotion
12446 {
12447   GdkEventType type;
12448   GdkWindow *window;
12449   guint32 time;
12450   gdouble x;
12451   gdouble y;
12452   gdouble pressure;
12453   gdouble xtilt;
12454   gdouble ytilt;
12455   guint state;
12456   gint16 is_hint;
12457   GdkInputSource source;
12458   guint32 deviceid;
12459 };
12460 </verb></tscreen>
12461
12462 <tt/pressure/ gives the pressure as a floating point number between
12463 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
12464 -1 and 1, corresponding to the degree of tilt in each direction.
12465 <tt/source/ and <tt/deviceid/ specify the device for which the
12466 event occurred in two different ways. <tt/source/ gives some simple
12467 information about the type of device. It can take the enumeration
12468 values.
12469
12470 <tscreen><verb>
12471 GDK_SOURCE_MOUSE
12472 GDK_SOURCE_PEN
12473 GDK_SOURCE_ERASER
12474 GDK_SOURCE_CURSOR
12475 </verb></tscreen>
12476
12477 <tt/deviceid/ specifies a unique numeric ID for the device. This can
12478 be used to find out further information about the device using the
12479 <tt/gdk_input_list_devices()/ call (see below). The special value
12480 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
12481 the mouse.)
12482
12483 <sect2> Enabling extended device information
12484
12485 <p>
12486 To let GTK know about our interest in the extended device information,
12487 we merely have to add a single line to our program:
12488
12489 <tscreen><verb>
12490 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
12491 </verb></tscreen>
12492
12493 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
12494 we are interested in extension events, but only if we don't have
12495 to draw our own cursor. See the section <ref
12496 id="sec_Further_Sophistications" name="Further Sophistications"> below
12497 for more information about drawing the cursor. We could also 
12498 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
12499 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
12500 back to the default condition.
12501
12502 <p>
12503 This is not completely the end of the story however. By default,
12504 no extension devices are enabled. We need a mechanism to allow
12505 users to enable and configure their extension devices. GTK provides
12506 the InputDialog widget to automate this process. The following
12507 procedure manages an InputDialog widget. It creates the dialog if
12508 it isn't present, and raises it to the top otherwise.
12509
12510 <tscreen><verb>
12511 void
12512 input_dialog_destroy (GtkWidget *w, gpointer data)
12513 {
12514   *((GtkWidget **)data) = NULL;
12515 }
12516
12517 void
12518 create_input_dialog ()
12519 {
12520   static GtkWidget *inputd = NULL;
12521
12522   if (!inputd)
12523     {
12524       inputd = gtk_input_dialog_new();
12525
12526       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
12527                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
12528       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
12529                                  "clicked",
12530                                  (GtkSignalFunc)gtk_widget_hide,
12531                                  GTK_OBJECT(inputd));
12532       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
12533
12534       gtk_widget_show (inputd);
12535     }
12536   else
12537     {
12538       if (!GTK_WIDGET_MAPPED(inputd))
12539         gtk_widget_show(inputd);
12540       else
12541         gdk_window_raise(inputd->window);
12542     }
12543 }
12544 </verb></tscreen>
12545
12546 (You might want to take note of the way we handle this dialog.  By
12547 connecting to the "destroy" signal, we make sure that we don't keep a
12548 pointer to dialog around after it is destroyed - that could lead to a
12549 segfault.)
12550
12551 <p>
12552 The InputDialog has two buttons "Close" and "Save", which by default
12553 have no actions assigned to them. In the above function we make
12554 "Close" hide the dialog, hide the "Save" button, since we don't
12555 implement saving of XInput options in this program.
12556
12557 <sect2> Using extended device information
12558
12559 <p>
12560 Once we've enabled the device, we can just use the extended 
12561 device information in the extra fields of the event structures.
12562 In fact, it is always safe to use this information since these
12563 fields will have reasonable default values even when extended
12564 events are not enabled.
12565
12566 <p>
12567 Once change we do have to make is to call
12568 <tt/gdk_input_window_get_pointer()/ instead of
12569 <tt/gdk_window_get_pointer/. This is necessary because
12570 <tt/gdk_window_get_pointer/ doesn't return the extended device
12571 information.
12572
12573 <tscreen><verb>
12574 void gdk_input_window_get_pointer     (GdkWindow       *window,
12575                                        guint32         deviceid,
12576                                        gdouble         *x,
12577                                        gdouble         *y,
12578                                        gdouble         *pressure,
12579                                        gdouble         *xtilt,
12580                                        gdouble         *ytilt,
12581                                        GdkModifierType *mask);
12582 </verb></tscreen>
12583
12584 When calling this function, we need to specify the device ID as
12585 well as the window. Usually, we'll get the device ID from the
12586 <tt/deviceid/ field of an event structure. Again, this function
12587 will return reasonable values when extension events are not
12588 enabled. (In this case, <tt/event->deviceid/ will have the value
12589 <tt/GDK_CORE_POINTER/).
12590
12591 So the basic structure of our button-press and motion event handlers,
12592 doesn't change much - we just need to add code to deal with the
12593 extended information.
12594
12595 <tscreen><verb>
12596 static gint
12597 button_press_event (GtkWidget *widget, GdkEventButton *event)
12598 {
12599   print_button_press (event->deviceid);
12600   
12601   if (event->button == 1 &amp;&amp; pixmap != NULL)
12602     draw_brush (widget, event->source, event->x, event->y, event->pressure);
12603
12604   return TRUE;
12605 }
12606
12607 static gint
12608 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
12609 {
12610   gdouble x, y;
12611   gdouble pressure;
12612   GdkModifierType state;
12613
12614   if (event->is_hint)
12615     gdk_input_window_get_pointer (event->window, event->deviceid,
12616                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
12617   else
12618     {
12619       x = event->x;
12620       y = event->y;
12621       pressure = event->pressure;
12622       state = event->state;
12623     }
12624     
12625   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
12626     draw_brush (widget, event->source, x, y, pressure);
12627   
12628   return TRUE;
12629 }
12630 </verb></tscreen>
12631
12632 We also need to do something with the new information. Our new
12633 <tt/draw_brush()/ function draws with a different color for
12634 each <tt/event->source/ and changes the brush size depending
12635 on the pressure.
12636
12637 <tscreen><verb>
12638 /* Draw a rectangle on the screen, size depending on pressure,
12639    and color on the type of device */
12640 static void
12641 draw_brush (GtkWidget *widget, GdkInputSource source,
12642             gdouble x, gdouble y, gdouble pressure)
12643 {
12644   GdkGC *gc;
12645   GdkRectangle update_rect;
12646
12647   switch (source)
12648     {
12649     case GDK_SOURCE_MOUSE:
12650       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
12651       break;
12652     case GDK_SOURCE_PEN:
12653       gc = widget->style->black_gc;
12654       break;
12655     case GDK_SOURCE_ERASER:
12656       gc = widget->style->white_gc;
12657       break;
12658     default:
12659       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
12660     }
12661
12662   update_rect.x = x - 10 * pressure;
12663   update_rect.y = y - 10 * pressure;
12664   update_rect.width = 20 * pressure;
12665   update_rect.height = 20 * pressure;
12666   gdk_draw_rectangle (pixmap, gc, TRUE,
12667                       update_rect.x, update_rect.y,
12668                       update_rect.width, update_rect.height);
12669   gtk_widget_draw (widget, &amp;update_rect);
12670 }
12671 </verb></tscreen>
12672
12673 <sect2> Finding out more about a device
12674
12675 <p>
12676 As an example of how to find out more about a device, our program
12677 will print the name of the device that generates each button
12678 press. To find out the name of a device, we call the function:
12679
12680 <tscreen><verb>
12681 GList *gdk_input_list_devices               (void);
12682 </verb></tscreen>
12683
12684 which returns a GList (a linked list type from the glib library)
12685 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
12686 as:
12687
12688 <tscreen><verb>
12689 struct _GdkDeviceInfo
12690 {
12691   guint32 deviceid;
12692   gchar *name;
12693   GdkInputSource source;
12694   GdkInputMode mode;
12695   gint has_cursor;
12696   gint num_axes;
12697   GdkAxisUse *axes;
12698   gint num_keys;
12699   GdkDeviceKey *keys;
12700 };
12701 </verb></tscreen>
12702
12703 Most of these fields are configuration information that you
12704 can ignore unless you are implemented XInput configuration
12705 saving. The we are interested in here is <tt/name/ which is
12706 simply the name that X assigns to the device. The other field
12707 that isn't configuration information is <tt/has_cursor/. If
12708 <tt/has_cursor/ is false, then we we need to draw our own
12709 cursor. But since we've specified <tt/GDK_EXTENSION_EVENTS_CURSOR/,
12710 we don't have to worry about this.
12711
12712 <p>
12713 Our <tt/print_button_press()/ function simply iterates through
12714 the returned list until it finds a match, then prints out
12715 the name of the device.
12716
12717 <tscreen><verb>
12718 static void
12719 print_button_press (guint32 deviceid)
12720 {
12721   GList *tmp_list;
12722
12723   /* gdk_input_list_devices returns an internal list, so we shouldn't
12724      free it afterwards */
12725   tmp_list = gdk_input_list_devices();
12726
12727   while (tmp_list)
12728     {
12729       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
12730
12731       if (info->deviceid == deviceid)
12732         {
12733           printf("Button press on device '%s'\n", info->name);
12734           return;
12735         }
12736
12737       tmp_list = tmp_list->next;
12738     }
12739 }
12740 </verb></tscreen>
12741
12742 That completes the changes to `XInputize' our program. As with
12743 the first version, the complete source is available at the location
12744 from which you got this tutorial, or from:
12745
12746 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12747 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12748
12749
12750 <sect2> Further sophistications <label id="sec_Further_Sophistications">
12751
12752 <p>
12753 Although our program now supports XInput quite well, it lacks some
12754 features we would want in a full-featured application. First, the user
12755 probably doesn't want to have to configure their device each time they
12756 run the program, so we should allow them to save the device
12757 configuration. This is done by iterating through the return of
12758 <tt/gdk_input_list_devices()/ and writing out the configuration to a
12759 file.
12760
12761 <p>
12762 To restore the state next time the program is run, GDK provides
12763 functions to change device configuration:
12764
12765 <tscreen><verb>
12766 gdk_input_set_extension_events()
12767 gdk_input_set_source()
12768 gdk_input_set_mode()
12769 gdk_input_set_axes()
12770 gdk_input_set_key()
12771 </verb></tscreen>
12772
12773 (The list returned from <tt/gdk_input_list_devices()/ should not be
12774 modified directly.) An example of doing this can be found in the
12775 drawing program gsumi. (Available from <htmlurl
12776 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
12777 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
12778 would be nice to have a standard way of doing this for all
12779 applications. This probably belongs at a slightly higher level than
12780 GTK, perhaps in the GNOME library.
12781
12782 <p>
12783 Another major omission that we have mentioned above is the lack of
12784 cursor drawing. Platforms other than XFree86 currently do not allow
12785 simultaneously using a device as both the core pointer and directly by
12786 an application. See the <url
12787 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
12788 name="XInput-HOWTO"> for more information about this. This means that
12789 applications that want to support the widest audience need to draw
12790 their own cursor.
12791
12792 <p>
12793 An application that draws its own cursor needs to do two things:
12794 determine if the current device needs a cursor drawn or not, and
12795 determine if the current device is in proximity. (If the current
12796 device is a drawing tablet, it's a nice touch to make the cursor 
12797 disappear when the stylus is lifted from the tablet. When the
12798 device is touching the stylus, that is called "in proximity.")
12799 The first is done by searching the device list, as we did
12800 to find out the device name. The second is achieved by selecting
12801 "proximity_out" events. An example of drawing one's own cursor is
12802 found in the 'testinput' program found in the GTK distribution.
12803
12804 <!-- ***************************************************************** -->
12805 <sect>Tips For Writing GTK Applications
12806 <!-- ***************************************************************** -->
12807
12808 <p>
12809 This section is simply a gathering of wisdom, general style guidelines and hints to
12810 creating good GTK applications. It is totally useless right now cause its
12811 only a topic sentence :)
12812
12813 Use GNU autoconf and automake!  They are your friends :)  I am planning to
12814 make a quick intro on them here.
12815
12816 <!-- ***************************************************************** -->
12817 <sect>Contributing
12818 <!-- ***************************************************************** -->
12819
12820 <p>
12821 This document, like so much other great software out there, was created for
12822 free by volunteers.  If you are at all knowledgeable about any aspect of GTK
12823 that does not already have documentation, please consider contributing to
12824 this document.
12825 <p>
12826 If you do decide to contribute, please mail your text to Tony Gale, 
12827 <tt><htmlurl url="mailto:gale@gtk.org"
12828 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this 
12829 document is free, and any addition by yourself must also be free.  That is, 
12830 people may use any portion of your examples in their programs, and copies 
12831 of this document may be distributed at will etc.
12832 <p>
12833 Thank you.
12834
12835 <!-- ***************************************************************** -->
12836 <sect>Credits
12837 <!-- ***************************************************************** -->
12838 <p>
12839 I would like to thank the following for their contributions to this text.
12840
12841 <itemize>
12842 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
12843 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
12844
12845 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
12846 name="raph@acm.org"></tt>
12847 for hello world ala GTK, widget packing, and general all around wisdom.
12848 He's also generously donated a home for this tutorial.
12849
12850 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
12851 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
12852 and the ability to make it :)
12853
12854 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
12855 name="werner.koch@guug.de"></tt> for converting the original plain text to
12856 SGML, and the widget class hierarchy.
12857
12858 <item>Mark Crichton <tt><htmlurl url="mailto:crichton@expert.cc.purdue.edu"
12859 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code, and
12860 the table packing tutorial.
12861
12862 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
12863 name="owt1@cornell.edu"></tt> for the EventBox widget section (and
12864 the patch to the distro).  He's also responsible for the selections code and
12865 tutorial, as well as the sections on writing your own GTK widgets, and the
12866 example application.  Thanks a lot Owen for all you help!
12867
12868 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
12869 name="mvboom42@calvin.edu"></tt> for his wonderful work on the Notebook,
12870 Progress Bar, Dialogs, and File selection widgets.  Thanks a lot Mark!
12871 You've been a great help.
12872
12873 <item>Tim Janik <tt><htmlurl url="mailto:timj@psynet.net"
12874 name="timj@psynet.net"></tt> for his great job on the Lists Widget.
12875 Thanks Tim :)
12876
12877 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
12878 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap tutorial.
12879
12880 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
12881 name="johnsonm@redhat.com"></tt> for info and code for popup menus. 
12882
12883 <item>David Huggins-Daines <tt><htmlurl url="mailto:bn711@freenet.carleton.ca"
12884 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree Widget
12885 sections. 
12886
12887 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
12888 name="mars@lysator.liu.se"></tt> for the GtkCList section
12889 </itemize>
12890 <p>
12891 And to all of you who commented and helped refine this document.
12892 <p>
12893 Thanks.
12894
12895 <!-- ***************************************************************** -->
12896 <sect> Tutorial Copyright and Permissions Notice
12897 <!-- ***************************************************************** -->
12898
12899 <p>
12900 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
12901
12902 Copyright (C) 1998 Tony Gale.
12903 <p>
12904 Permission is granted to make and distribute verbatim copies of this 
12905 manual provided the copyright notice and this permission notice are 
12906 preserved on all copies.
12907 <P>Permission is granted to copy and distribute modified versions of 
12908 this document under the conditions for verbatim copying, provided that 
12909 this copyright notice is included exactly as in the original,
12910 and that the entire resulting derived work is distributed under 
12911 the terms of a permission notice identical to this one.
12912 <P>Permission is granted to copy and distribute translations of this 
12913 document into another language, under the above conditions for modified 
12914 versions.
12915 <P>If you are intending to incorporate this document into a published 
12916 work, please contact the maintainer, and we will make an effort 
12917 to ensure that you have the most up to date information available.
12918 <P>There is no guarantee that this document lives up to its intended
12919 purpose.  This is simply provided as a free resource.  As such,
12920 the authors and maintainers of the information provided within can
12921 not make any guarantee that the information is even accurate.
12922
12923 <!-- ***************************************************************** -->
12924 <appendix>
12925 <!-- ***************************************************************** -->
12926
12927 <!-- ***************************************************************** -->
12928 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
12929 <!-- ***************************************************************** -->
12930 <p>
12931 The follwing data types are passed into event handlers by GTK+. For
12932 each data type listed, the signals that use this data type are listed.
12933
12934 <itemize>
12935 <item>  GdkEvent
12936           <itemize>
12937           <item>drag_end_event
12938           </itemize>
12939
12940 <item>  GdkEventType
12941
12942 <item>  GdkEventAny
12943           <itemize>
12944           <item>delete_event
12945           <item>destroy_event
12946           <item>map_event
12947           <item>unmap_event
12948           <item>no_expose_event
12949           </itemize>
12950
12951 <item>  GdkEventExpose
12952           <itemize>
12953           <item>expose_event
12954           </itemize>
12955
12956 <item>  GdkEventNoExpose
12957
12958 <item>  GdkEventVisibility
12959
12960 <item>  GdkEventMotion
12961           <itemize>
12962           <item>motion_notify_event
12963           </itemize>
12964
12965 <item>  GdkEventButton
12966           <itemize>
12967           <item>button_press_event
12968           <item>button_release_event
12969           </itemize>
12970
12971 <item>  GdkEventKey
12972           <itemize>
12973           <item>key_press_event
12974           <item>key_release_event
12975           </itemize>
12976
12977 <item>  GdkEventCrossing
12978           <itemize>
12979           <item>enter_notify_event
12980           <item>leave_notify_event
12981           </itemize>
12982
12983 <item>  GdkEventFocus
12984           <itemize>
12985           <item>focus_in_event
12986           <item>focus_out_event
12987           </itemize>
12988
12989 <item>  GdkEventConfigure
12990           <itemize>
12991           <item>configure_event
12992           </itemize>
12993
12994 <item>  GdkEventProperty
12995           <itemize>
12996           <item>property_notify_event
12997           </itemize>
12998
12999 <item>  GdkEventSelection
13000           <itemize>
13001           <item>selection_clear_event
13002           <item>selection_request_event
13003           <item>selection_notify_event
13004           </itemize>
13005
13006 <item>  GdkEventProximity
13007           <itemize>
13008           <item>proximity_in_event
13009           <item>proximity_out_event
13010           </itemize>
13011
13012 <item>  GdkEventDragBegin
13013           <itemize>
13014           <item>drag_begin_event
13015           </itemize>
13016
13017 <item>  GdkEventDragRequest
13018           <itemize>
13019           <item>drag_request_event
13020           </itemize>
13021
13022 <item>  GdkEventDropEnter
13023           <itemize>
13024           <item>drop_enter_event
13025           </itemize>
13026
13027 <item>  GdkEventDropLeave
13028           <itemize>
13029           <item>drop_leave_event
13030           </itemize>
13031
13032 <item>  GdkEventDropDataAvailable
13033           <itemize>
13034           <item>drop_data_available_event
13035           </itemize>
13036
13037 <item>  GdkEventClient
13038           <itemize>
13039           <item>client_event
13040           </itemize>
13041
13042 <item>  GdkEventOther
13043           <itemize>
13044           <item>other_event
13045           </itemize>
13046 </itemize>
13047
13048 The data type <tt/GdkEventType/ is a special data type that is used by
13049 all the other data types as an indicator of the data type being passed
13050 to the signal handler. As you will see below, each of the event data
13051 structures has a member of this type. It is defined as an enumeration
13052 type as follows:
13053
13054 <tscreen><verb>
13055 typedef enum
13056 {
13057   GDK_NOTHING           = -1,
13058   GDK_DELETE            = 0,
13059   GDK_DESTROY           = 1,
13060   GDK_EXPOSE            = 2,
13061   GDK_MOTION_NOTIFY     = 3,
13062   GDK_BUTTON_PRESS      = 4,
13063   GDK_2BUTTON_PRESS     = 5,
13064   GDK_3BUTTON_PRESS     = 6,
13065   GDK_BUTTON_RELEASE    = 7,
13066   GDK_KEY_PRESS         = 8,
13067   GDK_KEY_RELEASE       = 9,
13068   GDK_ENTER_NOTIFY      = 10,
13069   GDK_LEAVE_NOTIFY      = 11,
13070   GDK_FOCUS_CHANGE      = 12,
13071   GDK_CONFIGURE         = 13,
13072   GDK_MAP               = 14,
13073   GDK_UNMAP             = 15,
13074   GDK_PROPERTY_NOTIFY   = 16,
13075   GDK_SELECTION_CLEAR   = 17,
13076   GDK_SELECTION_REQUEST = 18,
13077   GDK_SELECTION_NOTIFY  = 19,
13078   GDK_PROXIMITY_IN      = 20,
13079   GDK_PROXIMITY_OUT     = 21,
13080   GDK_DRAG_BEGIN        = 22,
13081   GDK_DRAG_REQUEST      = 23,
13082   GDK_DROP_ENTER        = 24,
13083   GDK_DROP_LEAVE        = 25,
13084   GDK_DROP_DATA_AVAIL   = 26,
13085   GDK_CLIENT_EVENT      = 27,
13086   GDK_VISIBILITY_NOTIFY = 28,
13087   GDK_NO_EXPOSE         = 29,
13088   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
13089 } GdkEventType;
13090 </verb></tscreen>
13091
13092 The other event type that is different from the others is
13093 <tt/GdkEvent/ itself. This is a union of all the other
13094 data types, which allows it to be cast to a specific
13095 event data type within a signal handler.
13096
13097 <!-- Just a big list for now, needs expanding upon - TRG -->
13098 So, the event data types are defined as follows:
13099
13100 <tscreen><verb>
13101 struct _GdkEventAny
13102 {
13103   GdkEventType type;
13104   GdkWindow *window;
13105   gint8 send_event;
13106 };
13107
13108 struct _GdkEventExpose
13109 {
13110   GdkEventType type;
13111   GdkWindow *window;
13112   gint8 send_event;
13113   GdkRectangle area;
13114   gint count; /* If non-zero, how many more events follow. */
13115 };
13116
13117 struct _GdkEventNoExpose
13118 {
13119   GdkEventType type;
13120   GdkWindow *window;
13121   gint8 send_event;
13122   /* XXX: does anyone need the X major_code or minor_code fields? */
13123 };
13124
13125 struct _GdkEventVisibility
13126 {
13127   GdkEventType type;
13128   GdkWindow *window;
13129   gint8 send_event;
13130   GdkVisibilityState state;
13131 };
13132
13133 struct _GdkEventMotion
13134 {
13135   GdkEventType type;
13136   GdkWindow *window;
13137   gint8 send_event;
13138   guint32 time;
13139   gdouble x;
13140   gdouble y;
13141   gdouble pressure;
13142   gdouble xtilt;
13143   gdouble ytilt;
13144   guint state;
13145   gint16 is_hint;
13146   GdkInputSource source;
13147   guint32 deviceid;
13148   gdouble x_root, y_root;
13149 };
13150
13151 struct _GdkEventButton
13152 {
13153   GdkEventType type;
13154   GdkWindow *window;
13155   gint8 send_event;
13156   guint32 time;
13157   gdouble x;
13158   gdouble y;
13159   gdouble pressure;
13160   gdouble xtilt;
13161   gdouble ytilt;
13162   guint state;
13163   guint button;
13164   GdkInputSource source;
13165   guint32 deviceid;
13166   gdouble x_root, y_root;
13167 };
13168
13169 struct _GdkEventKey
13170 {
13171   GdkEventType type;
13172   GdkWindow *window;
13173   gint8 send_event;
13174   guint32 time;
13175   guint state;
13176   guint keyval;
13177   gint length;
13178   gchar *string;
13179 };
13180
13181 struct _GdkEventCrossing
13182 {
13183   GdkEventType type;
13184   GdkWindow *window;
13185   gint8 send_event;
13186   GdkWindow *subwindow;
13187   GdkNotifyType detail;
13188 };
13189
13190 struct _GdkEventFocus
13191 {
13192   GdkEventType type;
13193   GdkWindow *window;
13194   gint8 send_event;
13195   gint16 in;
13196 };
13197
13198 struct _GdkEventConfigure
13199 {
13200   GdkEventType type;
13201   GdkWindow *window;
13202   gint8 send_event;
13203   gint16 x, y;
13204   gint16 width;
13205   gint16 height;
13206 };
13207
13208 struct _GdkEventProperty
13209 {
13210   GdkEventType type;
13211   GdkWindow *window;
13212   gint8 send_event;
13213   GdkAtom atom;
13214   guint32 time;
13215   guint state;
13216 };
13217
13218 struct _GdkEventSelection
13219 {
13220   GdkEventType type;
13221   GdkWindow *window;
13222   gint8 send_event;
13223   GdkAtom selection;
13224   GdkAtom target;
13225   GdkAtom property;
13226   guint32 requestor;
13227   guint32 time;
13228 };
13229
13230 /* This event type will be used pretty rarely. It only is important
13231    for XInput aware programs that are drawing their own cursor */
13232
13233 struct _GdkEventProximity
13234 {
13235   GdkEventType type;
13236   GdkWindow *window;
13237   gint8 send_event;
13238   guint32 time;
13239   GdkInputSource source;
13240   guint32 deviceid;
13241 };
13242
13243 struct _GdkEventDragRequest
13244 {
13245   GdkEventType type;
13246   GdkWindow *window;
13247   gint8 send_event;
13248   guint32 requestor;
13249   union {
13250     struct {
13251       guint protocol_version:4;
13252       guint sendreply:1;
13253       guint willaccept:1;
13254       guint delete_data:1; /* Do *not* delete if link is sent, only
13255                               if data is sent */
13256       guint senddata:1;
13257       guint reserved:22;
13258     } flags;
13259     glong allflags;
13260   } u;
13261   guint8 isdrop; /* This gdk event can be generated by a couple of
13262                     X events - this lets the app know whether the
13263                     drop really occurred or we just set the data */
13264
13265   GdkPoint drop_coords;
13266   gchar *data_type;
13267   guint32 timestamp;
13268 };
13269
13270 struct _GdkEventDragBegin
13271 {
13272   GdkEventType type;
13273   GdkWindow *window;
13274   gint8 send_event;
13275   union {
13276     struct {
13277       guint protocol_version:4;
13278       guint reserved:28;
13279     } flags;
13280     glong allflags;
13281   } u;
13282 };
13283
13284 struct _GdkEventDropEnter
13285 {
13286   GdkEventType type;
13287   GdkWindow *window;
13288   gint8 send_event;
13289   guint32 requestor;
13290   union {
13291     struct {
13292       guint protocol_version:4;
13293       guint sendreply:1;
13294       guint extended_typelist:1;
13295       guint reserved:26;
13296     } flags;
13297     glong allflags;
13298   } u;
13299 };
13300
13301 struct _GdkEventDropLeave
13302 {
13303   GdkEventType type;
13304   GdkWindow *window;
13305   gint8 send_event;
13306   guint32 requestor;
13307   union {
13308     struct {
13309       guint protocol_version:4;
13310       guint reserved:28;
13311     } flags;
13312     glong allflags;
13313   } u;
13314 };
13315
13316 struct _GdkEventDropDataAvailable
13317 {
13318   GdkEventType type;
13319   GdkWindow *window;
13320   gint8 send_event;
13321   guint32 requestor;
13322   union {
13323     struct {
13324       guint protocol_version:4;
13325       guint isdrop:1;
13326       guint reserved:25;
13327     } flags;
13328     glong allflags;
13329   } u;
13330   gchar *data_type; /* MIME type */
13331   gulong data_numbytes;
13332   gpointer data;
13333   guint32 timestamp;
13334   GdkPoint coords;
13335 };
13336
13337 struct _GdkEventClient
13338 {
13339   GdkEventType type;
13340   GdkWindow *window;
13341   gint8 send_event;
13342   GdkAtom message_type;
13343   gushort data_format;
13344   union {
13345     char b[20];
13346     short s[10];
13347     long l[5];
13348   } data;
13349 };
13350
13351 struct _GdkEventOther
13352 {
13353   GdkEventType type;
13354   GdkWindow *window;
13355   gint8 send_event;
13356   GdkXEvent *xevent;
13357 };
13358 </verb></tscreen>
13359
13360 <!-- ***************************************************************** -->
13361 <sect> Code Examples
13362 <!-- ***************************************************************** -->
13363 <p>
13364 Below are the code examples that are used in the above text
13365 which are not included in complete form elsewhere.
13366
13367 <!-- ----------------------------------------------------------------- -->
13368 <sect1>Tictactoe
13369 <!-- ----------------------------------------------------------------- -->
13370 <sect2>tictactoe.h
13371 <p>
13372 <tscreen><verb>
13373 /* example-start tictactoe tictactoe.h */
13374
13375 /* GTK - The GIMP Toolkit
13376  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
13377  *
13378  * This library is free software; you can redistribute it and/or
13379  * modify it under the terms of the GNU Library General Public
13380  * License as published by the Free Software Foundation; either
13381  * version 2 of the License, or (at your option) any later version.
13382  *
13383  * This library is distributed in the hope that it will be useful,
13384  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13385  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13386  * Library General Public License for more details.
13387  *
13388  * You should have received a copy of the GNU Library General Public
13389  * License along with this library; if not, write to the
13390  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
13391  * Boston, MA 02111-1307, USA.
13392  */
13393 #ifndef __TICTACTOE_H__
13394 #define __TICTACTOE_H__
13395
13396
13397 #include <gdk/gdk.h>
13398 #include <gtk/gtkvbox.h>
13399
13400
13401 #ifdef __cplusplus
13402 extern "C" {
13403 #endif /* __cplusplus */
13404
13405 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
13406 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
13407 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
13408
13409
13410 typedef struct _Tictactoe       Tictactoe;
13411 typedef struct _TictactoeClass  TictactoeClass;
13412
13413 struct _Tictactoe
13414 {
13415   GtkVBox vbox;
13416   
13417   GtkWidget *buttons[3][3];
13418 };
13419
13420 struct _TictactoeClass
13421 {
13422   GtkVBoxClass parent_class;
13423
13424   void (* tictactoe) (Tictactoe *ttt);
13425 };
13426
13427 guint          tictactoe_get_type        (void);
13428 GtkWidget*     tictactoe_new             (void);
13429 void           tictactoe_clear           (Tictactoe *ttt);
13430
13431 #ifdef __cplusplus
13432 }
13433 #endif /* __cplusplus */
13434
13435 #endif /* __TICTACTOE_H__ */
13436
13437 /* example-end */
13438 </verb></tscreen>
13439
13440 <!-- ----------------------------------------------------------------- -->
13441 <sect2>tictactoe.c
13442 <p>
13443 <tscreen><verb>
13444 /* example-start tictactoe tictactoe.c */
13445
13446 /* GTK - The GIMP Toolkit
13447  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
13448  *
13449  * This library is free software; you can redistribute it and/or
13450  * modify it under the terms of the GNU Library General Public
13451  * License as published by the Free Software Foundation; either
13452  * version 2 of the License, or (at your option) any later version.
13453  *
13454  * This library is distributed in the hope that it will be useful,
13455  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13456  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13457  * Library General Public License for more details.
13458  *
13459  * You should have received a copy of the GNU Library General Public
13460  * License along with this library; if not, write to the
13461  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
13462  * Boston, MA 02111-1307, USA.
13463  */
13464 #include "gtk/gtksignal.h"
13465 #include "gtk/gtktable.h"
13466 #include "gtk/gtktogglebutton.h"
13467 #include "tictactoe.h"
13468
13469 enum {
13470   TICTACTOE_SIGNAL,
13471   LAST_SIGNAL
13472 };
13473
13474 static void tictactoe_class_init          (TictactoeClass *klass);
13475 static void tictactoe_init                (Tictactoe      *ttt);
13476 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
13477
13478 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
13479
13480 guint
13481 tictactoe_get_type ()
13482 {
13483   static guint ttt_type = 0;
13484
13485   if (!ttt_type)
13486     {
13487       GtkTypeInfo ttt_info =
13488       {
13489         "Tictactoe",
13490         sizeof (Tictactoe),
13491         sizeof (TictactoeClass),
13492         (GtkClassInitFunc) tictactoe_class_init,
13493         (GtkObjectInitFunc) tictactoe_init,
13494         (GtkArgSetFunc) NULL,
13495         (GtkArgGetFunc) NULL
13496       };
13497
13498       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
13499     }
13500
13501   return ttt_type;
13502 }
13503
13504 static void
13505 tictactoe_class_init (TictactoeClass *class)
13506 {
13507   GtkObjectClass *object_class;
13508
13509   object_class = (GtkObjectClass*) class;
13510   
13511   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
13512                                          GTK_RUN_FIRST,
13513                                          object_class->type,
13514                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
13515                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
13516
13517
13518   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
13519
13520   class->tictactoe = NULL;
13521 }
13522
13523 static void
13524 tictactoe_init (Tictactoe *ttt)
13525 {
13526   GtkWidget *table;
13527   gint i,j;
13528   
13529   table = gtk_table_new (3, 3, TRUE);
13530   gtk_container_add (GTK_CONTAINER(ttt), table);
13531   gtk_widget_show (table);
13532
13533   for (i=0;i<3; i++)
13534     for (j=0;j<3; j++)
13535       {
13536         ttt->buttons[i][j] = gtk_toggle_button_new ();
13537         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
13538                                    i, i+1, j, j+1);
13539         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
13540                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
13541         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
13542         gtk_widget_show (ttt->buttons[i][j]);
13543       }
13544 }
13545
13546 GtkWidget*
13547 tictactoe_new ()
13548 {
13549   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
13550 }
13551
13552 void           
13553 tictactoe_clear (Tictactoe *ttt)
13554 {
13555   int i,j;
13556
13557   for (i=0;i<3;i++)
13558     for (j=0;j<3;j++)
13559       {
13560         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
13561         gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
13562                                      FALSE);
13563         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
13564       }
13565 }
13566
13567 static void
13568 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
13569 {
13570   int i,k;
13571
13572   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
13573                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
13574                              { 0, 1, 2 }, { 0, 1, 2 } };
13575   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
13576                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
13577                              { 0, 1, 2 }, { 2, 1, 0 } };
13578
13579   int success, found;
13580
13581   for (k=0; k<8; k++)
13582     {
13583       success = TRUE;
13584       found = FALSE;
13585
13586       for (i=0;i<3;i++)
13587         {
13588           success = success &amp;&amp; 
13589             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
13590           found = found ||
13591             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
13592         }
13593       
13594       if (success &amp;&amp; found)
13595         {
13596           gtk_signal_emit (GTK_OBJECT (ttt), 
13597                            tictactoe_signals[TICTACTOE_SIGNAL]);
13598           break;
13599         }
13600     }
13601 }
13602
13603 /* example-end */
13604 </verb></tscreen>
13605
13606 <!-- ----------------------------------------------------------------- -->
13607 <sect2>ttt_test.c
13608 <p>
13609 <tscreen><verb>
13610 /* example-start tictactoe ttt_test.c */
13611
13612 #include <gtk/gtk.h>
13613 #include "tictactoe.h"
13614
13615 void
13616 win (GtkWidget *widget, gpointer data)
13617 {
13618   g_print ("Yay!\n");
13619   tictactoe_clear (TICTACTOE (widget));
13620 }
13621
13622 int 
13623 main (int argc, char *argv[])
13624 {
13625   GtkWidget *window;
13626   GtkWidget *ttt;
13627   
13628   gtk_init (&amp;argc, &amp;argv);
13629
13630   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13631   
13632   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
13633   
13634   gtk_signal_connect (GTK_OBJECT (window), "destroy",
13635                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
13636   
13637   gtk_container_border_width (GTK_CONTAINER (window), 10);
13638
13639   ttt = tictactoe_new ();
13640   
13641   gtk_container_add (GTK_CONTAINER (window), ttt);
13642   gtk_widget_show (ttt);
13643
13644   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
13645                       GTK_SIGNAL_FUNC (win), NULL);
13646
13647   gtk_widget_show (window);
13648   
13649   gtk_main ();
13650   
13651   return 0;
13652 }
13653
13654 /* example-end */
13655 </verb></tscreen>
13656
13657 <!-- ----------------------------------------------------------------- -->
13658 <sect1> GtkDial
13659
13660 <!-- ----------------------------------------------------------------- -->
13661 <sect2> gtkdial.h
13662 <p>
13663 <tscreen><verb>
13664 /* example-start gtkdial gtkdial.h */
13665
13666 /* GTK - The GIMP Toolkit
13667  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
13668  *
13669  * This library is free software; you can redistribute it and/or
13670  * modify it under the terms of the GNU Library General Public
13671  * License as published by the Free Software Foundation; either
13672  * version 2 of the License, or (at your option) any later version.
13673  *
13674  * This library is distributed in the hope that it will be useful,
13675  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13676  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13677  * Library General Public License for more details.
13678  *
13679  * You should have received a copy of the GNU Library General Public
13680  * License along with this library; if not, write to the
13681  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
13682  * Boston, MA 02111-1307, USA.
13683  */
13684 #ifndef __GTK_DIAL_H__
13685 #define __GTK_DIAL_H__
13686
13687
13688 #include <gdk/gdk.h>
13689 #include <gtk/gtkadjustment.h>
13690 #include <gtk/gtkwidget.h>
13691
13692
13693 #ifdef __cplusplus
13694 extern "C" {
13695 #endif /* __cplusplus */
13696
13697
13698 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
13699 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
13700 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
13701
13702
13703 typedef struct _GtkDial        GtkDial;
13704 typedef struct _GtkDialClass   GtkDialClass;
13705
13706 struct _GtkDial
13707 {
13708   GtkWidget widget;
13709
13710   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
13711   guint policy : 2;
13712
13713   /* Button currently pressed or 0 if none */
13714   guint8 button;
13715
13716   /* Dimensions of dial components */
13717   gint radius;
13718   gint pointer_width;
13719
13720   /* ID of update timer, or 0 if none */
13721   guint32 timer;
13722
13723   /* Current angle */
13724   gfloat angle;
13725
13726   /* Old values from adjustment stored so we know when something changes */
13727   gfloat old_value;
13728   gfloat old_lower;
13729   gfloat old_upper;
13730
13731   /* The adjustment object that stores the data for this dial */
13732   GtkAdjustment *adjustment;
13733 };
13734
13735 struct _GtkDialClass
13736 {
13737   GtkWidgetClass parent_class;
13738 };
13739
13740
13741 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
13742 guint          gtk_dial_get_type               (void);
13743 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
13744 void           gtk_dial_set_update_policy      (GtkDial      *dial,
13745                                                 GtkUpdateType  policy);
13746
13747 void           gtk_dial_set_adjustment         (GtkDial      *dial,
13748                                                 GtkAdjustment *adjustment);
13749 #ifdef __cplusplus
13750 }
13751 #endif /* __cplusplus */
13752
13753
13754 #endif /* __GTK_DIAL_H__ */
13755 /* example-end */
13756 </verb></tscreen>
13757
13758 <!-- ----------------------------------------------------------------- -->
13759 <sect2> gtkdial.c
13760 <p>
13761 <tscreen><verb>
13762 /* example-start gtkdial gtkdial.c */
13763
13764 /* GTK - The GIMP Toolkit
13765  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
13766  *
13767  * This library is free software; you can redistribute it and/or
13768  * modify it under the terms of the GNU Library General Public
13769  * License as published by the Free Software Foundation; either
13770  * version 2 of the License, or (at your option) any later version.
13771  *
13772  * This library is distributed in the hope that it will be useful,
13773  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13774  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13775  * Library General Public License for more details.
13776  *
13777  * You should have received a copy of the GNU Library General Public
13778  * License along with this library; if not, write to the
13779  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
13780  * Boston, MA 02111-1307, USA.
13781  */
13782 #include <math.h>
13783 #include <stdio.h>
13784 #include <gtk/gtkmain.h>
13785 #include <gtk/gtksignal.h>
13786
13787 #include "gtkdial.h"
13788
13789 #define SCROLL_DELAY_LENGTH  300
13790 #define DIAL_DEFAULT_SIZE 100
13791
13792 /* Forward declarations */
13793
13794 static void gtk_dial_class_init               (GtkDialClass    *klass);
13795 static void gtk_dial_init                     (GtkDial         *dial);
13796 static void gtk_dial_destroy                  (GtkObject        *object);
13797 static void gtk_dial_realize                  (GtkWidget        *widget);
13798 static void gtk_dial_size_request             (GtkWidget      *widget,
13799                                                GtkRequisition *requisition);
13800 static void gtk_dial_size_allocate            (GtkWidget     *widget,
13801                                                GtkAllocation *allocation);
13802 static gint gtk_dial_expose                   (GtkWidget        *widget,
13803                                                 GdkEventExpose   *event);
13804 static gint gtk_dial_button_press             (GtkWidget        *widget,
13805                                                 GdkEventButton   *event);
13806 static gint gtk_dial_button_release           (GtkWidget        *widget,
13807                                                 GdkEventButton   *event);
13808 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
13809                                                 GdkEventMotion   *event);
13810 static gint gtk_dial_timer                    (GtkDial         *dial);
13811
13812 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
13813 static void gtk_dial_update                   (GtkDial *dial);
13814 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
13815                                                 gpointer          data);
13816 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
13817                                                 gpointer          data);
13818
13819 /* Local data */
13820
13821 static GtkWidgetClass *parent_class = NULL;
13822
13823 guint
13824 gtk_dial_get_type ()
13825 {
13826   static guint dial_type = 0;
13827
13828   if (!dial_type)
13829     {
13830       GtkTypeInfo dial_info =
13831       {
13832         "GtkDial",
13833         sizeof (GtkDial),
13834         sizeof (GtkDialClass),
13835         (GtkClassInitFunc) gtk_dial_class_init,
13836         (GtkObjectInitFunc) gtk_dial_init,
13837         (GtkArgSetFunc) NULL,
13838         (GtkArgGetFunc) NULL,
13839       };
13840
13841       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
13842     }
13843
13844   return dial_type;
13845 }
13846
13847 static void
13848 gtk_dial_class_init (GtkDialClass *class)
13849 {
13850   GtkObjectClass *object_class;
13851   GtkWidgetClass *widget_class;
13852
13853   object_class = (GtkObjectClass*) class;
13854   widget_class = (GtkWidgetClass*) class;
13855
13856   parent_class = gtk_type_class (gtk_widget_get_type ());
13857
13858   object_class->destroy = gtk_dial_destroy;
13859
13860   widget_class->realize = gtk_dial_realize;
13861   widget_class->expose_event = gtk_dial_expose;
13862   widget_class->size_request = gtk_dial_size_request;
13863   widget_class->size_allocate = gtk_dial_size_allocate;
13864   widget_class->button_press_event = gtk_dial_button_press;
13865   widget_class->button_release_event = gtk_dial_button_release;
13866   widget_class->motion_notify_event = gtk_dial_motion_notify;
13867 }
13868
13869 static void
13870 gtk_dial_init (GtkDial *dial)
13871 {
13872   dial->button = 0;
13873   dial->policy = GTK_UPDATE_CONTINUOUS;
13874   dial->timer = 0;
13875   dial->radius = 0;
13876   dial->pointer_width = 0;
13877   dial->angle = 0.0;
13878   dial->old_value = 0.0;
13879   dial->old_lower = 0.0;
13880   dial->old_upper = 0.0;
13881   dial->adjustment = NULL;
13882 }
13883
13884 GtkWidget*
13885 gtk_dial_new (GtkAdjustment *adjustment)
13886 {
13887   GtkDial *dial;
13888
13889   dial = gtk_type_new (gtk_dial_get_type ());
13890
13891   if (!adjustment)
13892     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
13893
13894   gtk_dial_set_adjustment (dial, adjustment);
13895
13896   return GTK_WIDGET (dial);
13897 }
13898
13899 static void
13900 gtk_dial_destroy (GtkObject *object)
13901 {
13902   GtkDial *dial;
13903
13904   g_return_if_fail (object != NULL);
13905   g_return_if_fail (GTK_IS_DIAL (object));
13906
13907   dial = GTK_DIAL (object);
13908
13909   if (dial->adjustment)
13910     gtk_object_unref (GTK_OBJECT (dial->adjustment));
13911
13912   if (GTK_OBJECT_CLASS (parent_class)->destroy)
13913     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
13914 }
13915
13916 GtkAdjustment*
13917 gtk_dial_get_adjustment (GtkDial *dial)
13918 {
13919   g_return_val_if_fail (dial != NULL, NULL);
13920   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
13921
13922   return dial->adjustment;
13923 }
13924
13925 void
13926 gtk_dial_set_update_policy (GtkDial      *dial,
13927                              GtkUpdateType  policy)
13928 {
13929   g_return_if_fail (dial != NULL);
13930   g_return_if_fail (GTK_IS_DIAL (dial));
13931
13932   dial->policy = policy;
13933 }
13934
13935 void
13936 gtk_dial_set_adjustment (GtkDial      *dial,
13937                           GtkAdjustment *adjustment)
13938 {
13939   g_return_if_fail (dial != NULL);
13940   g_return_if_fail (GTK_IS_DIAL (dial));
13941
13942   if (dial->adjustment)
13943     {
13944       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
13945       gtk_object_unref (GTK_OBJECT (dial->adjustment));
13946     }
13947
13948   dial->adjustment = adjustment;
13949   gtk_object_ref (GTK_OBJECT (dial->adjustment));
13950
13951   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
13952                       (GtkSignalFunc) gtk_dial_adjustment_changed,
13953                       (gpointer) dial);
13954   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
13955                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
13956                       (gpointer) dial);
13957
13958   dial->old_value = adjustment->value;
13959   dial->old_lower = adjustment->lower;
13960   dial->old_upper = adjustment->upper;
13961
13962   gtk_dial_update (dial);
13963 }
13964
13965 static void
13966 gtk_dial_realize (GtkWidget *widget)
13967 {
13968   GtkDial *dial;
13969   GdkWindowAttr attributes;
13970   gint attributes_mask;
13971
13972   g_return_if_fail (widget != NULL);
13973   g_return_if_fail (GTK_IS_DIAL (widget));
13974
13975   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
13976   dial = GTK_DIAL (widget);
13977
13978   attributes.x = widget->allocation.x;
13979   attributes.y = widget->allocation.y;
13980   attributes.width = widget->allocation.width;
13981   attributes.height = widget->allocation.height;
13982   attributes.wclass = GDK_INPUT_OUTPUT;
13983   attributes.window_type = GDK_WINDOW_CHILD;
13984   attributes.event_mask = gtk_widget_get_events (widget) | 
13985     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
13986     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
13987     GDK_POINTER_MOTION_HINT_MASK;
13988   attributes.visual = gtk_widget_get_visual (widget);
13989   attributes.colormap = gtk_widget_get_colormap (widget);
13990
13991   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
13992   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
13993
13994   widget->style = gtk_style_attach (widget->style, widget->window);
13995
13996   gdk_window_set_user_data (widget->window, widget);
13997
13998   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
13999 }
14000
14001 static void 
14002 gtk_dial_size_request (GtkWidget      *widget,
14003                        GtkRequisition *requisition)
14004 {
14005   requisition->width = DIAL_DEFAULT_SIZE;
14006   requisition->height = DIAL_DEFAULT_SIZE;
14007 }
14008
14009 static void
14010 gtk_dial_size_allocate (GtkWidget     *widget,
14011                         GtkAllocation *allocation)
14012 {
14013   GtkDial *dial;
14014
14015   g_return_if_fail (widget != NULL);
14016   g_return_if_fail (GTK_IS_DIAL (widget));
14017   g_return_if_fail (allocation != NULL);
14018
14019   widget->allocation = *allocation;
14020   dial = GTK_DIAL (widget);
14021
14022   if (GTK_WIDGET_REALIZED (widget))
14023     {
14024
14025       gdk_window_move_resize (widget->window,
14026                               allocation->x, allocation->y,
14027                               allocation->width, allocation->height);
14028
14029     }
14030   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
14031   dial->pointer_width = dial->radius / 5;
14032 }
14033
14034 static gint
14035 gtk_dial_expose (GtkWidget      *widget,
14036                  GdkEventExpose *event)
14037 {
14038   GtkDial *dial;
14039   GdkPoint points[3];
14040   gdouble s,c;
14041   gdouble theta;
14042   gint xc, yc;
14043   gint tick_length;
14044   gint i;
14045
14046   g_return_val_if_fail (widget != NULL, FALSE);
14047   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
14048   g_return_val_if_fail (event != NULL, FALSE);
14049
14050   if (event->count > 0)
14051     return FALSE;
14052   
14053   dial = GTK_DIAL (widget);
14054
14055   gdk_window_clear_area (widget->window,
14056                          0, 0,
14057                          widget->allocation.width,
14058                          widget->allocation.height);
14059
14060   xc = widget->allocation.width/2;
14061   yc = widget->allocation.height/2;
14062
14063   /* Draw ticks */
14064
14065   for (i=0; i<25; i++)
14066     {
14067       theta = (i*M_PI/18. - M_PI/6.);
14068       s = sin(theta);
14069       c = cos(theta);
14070
14071       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
14072       
14073       gdk_draw_line (widget->window,
14074                      widget->style->fg_gc[widget->state],
14075                      xc + c*(dial->radius - tick_length),
14076                      yc - s*(dial->radius - tick_length),
14077                      xc + c*dial->radius,
14078                      yc - s*dial->radius);
14079     }
14080
14081   /* Draw pointer */
14082
14083   s = sin(dial->angle);
14084   c = cos(dial->angle);
14085
14086
14087   points[0].x = xc + s*dial->pointer_width/2;
14088   points[0].y = yc + c*dial->pointer_width/2;
14089   points[1].x = xc + c*dial->radius;
14090   points[1].y = yc - s*dial->radius;
14091   points[2].x = xc - s*dial->pointer_width/2;
14092   points[2].y = yc - c*dial->pointer_width/2;
14093
14094   gtk_draw_polygon (widget->style,
14095                     widget->window,
14096                     GTK_STATE_NORMAL,
14097                     GTK_SHADOW_OUT,
14098                     points, 3,
14099                     TRUE);
14100   
14101   return FALSE;
14102 }
14103
14104 static gint
14105 gtk_dial_button_press (GtkWidget      *widget,
14106                        GdkEventButton *event)
14107 {
14108   GtkDial *dial;
14109   gint dx, dy;
14110   double s, c;
14111   double d_parallel;
14112   double d_perpendicular;
14113
14114   g_return_val_if_fail (widget != NULL, FALSE);
14115   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
14116   g_return_val_if_fail (event != NULL, FALSE);
14117
14118   dial = GTK_DIAL (widget);
14119
14120   /* Determine if button press was within pointer region - we 
14121      do this by computing the parallel and perpendicular distance of
14122      the point where the mouse was pressed from the line passing through
14123      the pointer */
14124   
14125   dx = event->x - widget->allocation.width / 2;
14126   dy = widget->allocation.height / 2 - event->y;
14127   
14128   s = sin(dial->angle);
14129   c = cos(dial->angle);
14130   
14131   d_parallel = s*dy + c*dx;
14132   d_perpendicular = fabs(s*dx - c*dy);
14133   
14134   if (!dial->button &amp;&amp;
14135       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
14136       (d_parallel > - dial->pointer_width))
14137     {
14138       gtk_grab_add (widget);
14139
14140       dial->button = event->button;
14141
14142       gtk_dial_update_mouse (dial, event->x, event->y);
14143     }
14144
14145   return FALSE;
14146 }
14147
14148 static gint
14149 gtk_dial_button_release (GtkWidget      *widget,
14150                           GdkEventButton *event)
14151 {
14152   GtkDial *dial;
14153
14154   g_return_val_if_fail (widget != NULL, FALSE);
14155   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
14156   g_return_val_if_fail (event != NULL, FALSE);
14157
14158   dial = GTK_DIAL (widget);
14159
14160   if (dial->button == event->button)
14161     {
14162       gtk_grab_remove (widget);
14163
14164       dial->button = 0;
14165
14166       if (dial->policy == GTK_UPDATE_DELAYED)
14167         gtk_timeout_remove (dial->timer);
14168       
14169       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
14170           (dial->old_value != dial->adjustment->value))
14171         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
14172     }
14173
14174   return FALSE;
14175 }
14176
14177 static gint
14178 gtk_dial_motion_notify (GtkWidget      *widget,
14179                          GdkEventMotion *event)
14180 {
14181   GtkDial *dial;
14182   GdkModifierType mods;
14183   gint x, y, mask;
14184
14185   g_return_val_if_fail (widget != NULL, FALSE);
14186   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
14187   g_return_val_if_fail (event != NULL, FALSE);
14188
14189   dial = GTK_DIAL (widget);
14190
14191   if (dial->button != 0)
14192     {
14193       x = event->x;
14194       y = event->y;
14195
14196       if (event->is_hint || (event->window != widget->window))
14197         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
14198
14199       switch (dial->button)
14200         {
14201         case 1:
14202           mask = GDK_BUTTON1_MASK;
14203           break;
14204         case 2:
14205           mask = GDK_BUTTON2_MASK;
14206           break;
14207         case 3:
14208           mask = GDK_BUTTON3_MASK;
14209           break;
14210         default:
14211           mask = 0;
14212           break;
14213         }
14214
14215       if (mods &amp; mask)
14216         gtk_dial_update_mouse (dial, x,y);
14217     }
14218
14219   return FALSE;
14220 }
14221
14222 static gint
14223 gtk_dial_timer (GtkDial *dial)
14224 {
14225   g_return_val_if_fail (dial != NULL, FALSE);
14226   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
14227
14228   if (dial->policy == GTK_UPDATE_DELAYED)
14229     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
14230
14231   return FALSE;
14232 }
14233
14234 static void
14235 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
14236 {
14237   gint xc, yc;
14238   gfloat old_value;
14239
14240   g_return_if_fail (dial != NULL);
14241   g_return_if_fail (GTK_IS_DIAL (dial));
14242
14243   xc = GTK_WIDGET(dial)->allocation.width / 2;
14244   yc = GTK_WIDGET(dial)->allocation.height / 2;
14245
14246   old_value = dial->adjustment->value;
14247   dial->angle = atan2(yc-y, x-xc);
14248
14249   if (dial->angle < -M_PI/2.)
14250     dial->angle += 2*M_PI;
14251
14252   if (dial->angle < -M_PI/6)
14253     dial->angle = -M_PI/6;
14254
14255   if (dial->angle > 7.*M_PI/6.)
14256     dial->angle = 7.*M_PI/6.;
14257
14258   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
14259     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
14260
14261   if (dial->adjustment->value != old_value)
14262     {
14263       if (dial->policy == GTK_UPDATE_CONTINUOUS)
14264         {
14265           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
14266         }
14267       else
14268         {
14269           gtk_widget_draw (GTK_WIDGET(dial), NULL);
14270
14271           if (dial->policy == GTK_UPDATE_DELAYED)
14272             {
14273               if (dial->timer)
14274                 gtk_timeout_remove (dial->timer);
14275
14276               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
14277                                              (GtkFunction) gtk_dial_timer,
14278                                              (gpointer) dial);
14279             }
14280         }
14281     }
14282 }
14283
14284 static void
14285 gtk_dial_update (GtkDial *dial)
14286 {
14287   gfloat new_value;
14288   
14289   g_return_if_fail (dial != NULL);
14290   g_return_if_fail (GTK_IS_DIAL (dial));
14291
14292   new_value = dial->adjustment->value;
14293   
14294   if (new_value < dial->adjustment->lower)
14295     new_value = dial->adjustment->lower;
14296
14297   if (new_value > dial->adjustment->upper)
14298     new_value = dial->adjustment->upper;
14299
14300   if (new_value != dial->adjustment->value)
14301     {
14302       dial->adjustment->value = new_value;
14303       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
14304     }
14305
14306   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
14307     (dial->adjustment->upper - dial->adjustment->lower);
14308
14309   gtk_widget_draw (GTK_WIDGET(dial), NULL);
14310 }
14311
14312 static void
14313 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
14314                               gpointer       data)
14315 {
14316   GtkDial *dial;
14317
14318   g_return_if_fail (adjustment != NULL);
14319   g_return_if_fail (data != NULL);
14320
14321   dial = GTK_DIAL (data);
14322
14323   if ((dial->old_value != adjustment->value) ||
14324       (dial->old_lower != adjustment->lower) ||
14325       (dial->old_upper != adjustment->upper))
14326     {
14327       gtk_dial_update (dial);
14328
14329       dial->old_value = adjustment->value;
14330       dial->old_lower = adjustment->lower;
14331       dial->old_upper = adjustment->upper;
14332     }
14333 }
14334
14335 static void
14336 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
14337                                     gpointer       data)
14338 {
14339   GtkDial *dial;
14340
14341   g_return_if_fail (adjustment != NULL);
14342   g_return_if_fail (data != NULL);
14343
14344   dial = GTK_DIAL (data);
14345
14346   if (dial->old_value != adjustment->value)
14347     {
14348       gtk_dial_update (dial);
14349
14350       dial->old_value = adjustment->value;
14351     }
14352 }
14353 /* example-end */
14354 </verb></tscreen>
14355
14356 <!-- ----------------------------------------------------------------- -->
14357 <sect1> Scribble
14358 <p>
14359 <tscreen><verb>
14360 /* example-start scribble-simple scribble-simple.c */
14361
14362 /* GTK - The GIMP Toolkit
14363  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14364  *
14365  * This library is free software; you can redistribute it and/or
14366  * modify it under the terms of the GNU Library General Public
14367  * License as published by the Free Software Foundation; either
14368  * version 2 of the License, or (at your option) any later version.
14369  *
14370  * This library is distributed in the hope that it will be useful,
14371  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14372  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14373  * Library General Public License for more details.
14374  *
14375  * You should have received a copy of the GNU Library General Public
14376  * License along with this library; if not, write to the
14377  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14378  * Boston, MA 02111-1307, USA.
14379  */
14380
14381 #include <gtk/gtk.h>
14382
14383 /* Backing pixmap for drawing area */
14384 static GdkPixmap *pixmap = NULL;
14385
14386 /* Create a new backing pixmap of the appropriate size */
14387 static gint
14388 configure_event (GtkWidget *widget, GdkEventConfigure *event)
14389 {
14390   if (pixmap)
14391     gdk_pixmap_unref(pixmap);
14392
14393   pixmap = gdk_pixmap_new(widget->window,
14394                           widget->allocation.width,
14395                           widget->allocation.height,
14396                           -1);
14397   gdk_draw_rectangle (pixmap,
14398                       widget->style->white_gc,
14399                       TRUE,
14400                       0, 0,
14401                       widget->allocation.width,
14402                       widget->allocation.height);
14403
14404   return TRUE;
14405 }
14406
14407 /* Redraw the screen from the backing pixmap */
14408 static gint
14409 expose_event (GtkWidget *widget, GdkEventExpose *event)
14410 {
14411   gdk_draw_pixmap(widget->window,
14412                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
14413                   pixmap,
14414                   event->area.x, event->area.y,
14415                   event->area.x, event->area.y,
14416                   event->area.width, event->area.height);
14417
14418   return FALSE;
14419 }
14420
14421 /* Draw a rectangle on the screen */
14422 static void
14423 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
14424 {
14425   GdkRectangle update_rect;
14426
14427   update_rect.x = x - 5;
14428   update_rect.y = y - 5;
14429   update_rect.width = 10;
14430   update_rect.height = 10;
14431   gdk_draw_rectangle (pixmap,
14432                       widget->style->black_gc,
14433                       TRUE,
14434                       update_rect.x, update_rect.y,
14435                       update_rect.width, update_rect.height);
14436   gtk_widget_draw (widget, &amp;update_rect);
14437 }
14438
14439 static gint
14440 button_press_event (GtkWidget *widget, GdkEventButton *event)
14441 {
14442   if (event->button == 1 &amp;&amp; pixmap != NULL)
14443     draw_brush (widget, event->x, event->y);
14444
14445   return TRUE;
14446 }
14447
14448 static gint
14449 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14450 {
14451   int x, y;
14452   GdkModifierType state;
14453
14454   if (event->is_hint)
14455     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
14456   else
14457     {
14458       x = event->x;
14459       y = event->y;
14460       state = event->state;
14461     }
14462     
14463   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14464     draw_brush (widget, x, y);
14465   
14466   return TRUE;
14467 }
14468
14469 void
14470 quit ()
14471 {
14472   gtk_exit (0);
14473 }
14474
14475 int
14476 main (int argc, char *argv[])
14477 {
14478   GtkWidget *window;
14479   GtkWidget *drawing_area;
14480   GtkWidget *vbox;
14481
14482   GtkWidget *button;
14483
14484   gtk_init (&amp;argc, &amp;argv);
14485
14486   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14487   gtk_widget_set_name (window, "Test Input");
14488
14489   vbox = gtk_vbox_new (FALSE, 0);
14490   gtk_container_add (GTK_CONTAINER (window), vbox);
14491   gtk_widget_show (vbox);
14492
14493   gtk_signal_connect (GTK_OBJECT (window), "destroy",
14494                       GTK_SIGNAL_FUNC (quit), NULL);
14495
14496   /* Create the drawing area */
14497
14498   drawing_area = gtk_drawing_area_new ();
14499   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
14500   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
14501
14502   gtk_widget_show (drawing_area);
14503
14504   /* Signals used to handle backing pixmap */
14505
14506   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
14507                       (GtkSignalFunc) expose_event, NULL);
14508   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
14509                       (GtkSignalFunc) configure_event, NULL);
14510
14511   /* Event signals */
14512
14513   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
14514                       (GtkSignalFunc) motion_notify_event, NULL);
14515   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
14516                       (GtkSignalFunc) button_press_event, NULL);
14517
14518   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
14519                          | GDK_LEAVE_NOTIFY_MASK
14520                          | GDK_BUTTON_PRESS_MASK
14521                          | GDK_POINTER_MOTION_MASK
14522                          | GDK_POINTER_MOTION_HINT_MASK);
14523
14524   /* .. And a quit button */
14525   button = gtk_button_new_with_label ("Quit");
14526   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
14527
14528   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
14529                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
14530                              GTK_OBJECT (window));
14531   gtk_widget_show (button);
14532
14533   gtk_widget_show (window);
14534
14535   gtk_main ();
14536
14537   return 0;
14538 }
14539 /* example-end */
14540 </verb></tscreen>
14541
14542 </article>