]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
- Replace all uses of deprecated functions. - Replace menufactory example
[~andy/gtk] / docs / tutorial / gtk_tut.sgml
1 <!doctype linuxdoc system>
2
3 <!-- This is the tutorial marked up in SGML
4      (just to show how to write a comment)
5 -->
6
7 <article>
8 <title>GTK v1.1 Tutorial
9 <author>
10 Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
11                               name="&lt;gale@gtk.org&gt;"></tt>
12 Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
13                               name="&lt;imain@gtk.org&gt;"></tt>,
14 <date>January 27th, 1999
15
16 <!-- ***************************************************************** -->
17 <sect>Introduction
18 <!-- ***************************************************************** -->
19 <p>
20 GTK (GIMP Toolkit) was originally developed as a toolkit for the GIMP
21 (General Image Manipulation Program).  GTK is built on top of GDK
22 (GIMP Drawing Kit) which is basically a wrapper around the Xlib
23 functions.  It's called the GIMP toolkit because it was originally
24 written for developing the GIMP, but has now been used in several free
25 software projects.  The authors are:
26 <itemize>
27 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
28                            name="petm@xcf.berkeley.edu"></tt>
29 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
30                            name="spencer@xcf.berkeley.edu"></tt>
31 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
32                            name="jmacd@xcf.berkeley.edu"></tt>
33 </itemize>
34
35 GTK is essentially an object oriented application programmers
36 interface (API). Although written completely in C, it is implemented
37 using the idea of classes and callback functions (pointers to
38 functions).
39
40 There is also a third component called glib which contains a few
41 replacements for some standard calls, as well as some additional
42 functions for handling linked lists etc. The replacement functions are
43 used to increase GTK's portability, as some of the functions
44 implemented here are not available or are nonstandard on other unixes
45 such as g_strerror(). Some also contain enhancements to the libc
46 versions, such as g_malloc that has enhanced debugging utilities.
47
48 This tutorial is an attempt to document as much as possible of GTK, it
49 is by no means complete. This tutorial assumes a good understanding of
50 C, and how to create C programs. It would be a great benefit for the
51 reader to have previous X programming experience, but it shouldn't be
52 necessary. If you are learning GTK as your first widget set, please
53 comment on how you found this tutorial, and what you had trouble
54 with. Note that there is also a C++ API for GTK (GTK--) in the works,
55 so if you prefer to use C++, you should look into this
56 instead. There are also Objective C, ADA, Guile and other language
57 bindings available, but I don't follow these.
58
59 This document is a 'work in progress'. Please look for updates on 
60 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
61 name="http://www.gtk.org/">.
62
63 I would very much like to hear of any problems you have learning GTK
64 from this document, and would appreciate input as to how it may be
65 improved. Please see the section on <ref id="sec_Contributing"
66 name="Contributing"> for further information.
67
68 <!-- ***************************************************************** -->
69 <sect>Getting Started
70 <!-- ***************************************************************** -->
71
72 <p>
73 The first thing to do of course, is download the GTK source and
74 install it. You can always get the latest version from ftp.gtk.org in
75 /pub/gtk. You can also view other sources of GTK information on
76 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
77 name="http://www.gtk.org/">. GTK uses GNU autoconf for configuration.
78 Once untar'd, type ./configure --help to see a list of options.
79
80 Th GTK source distribution also contains the complete source to all of
81 the examples used in this tutorial, along with Makefiles to aid
82 compilation.
83
84 To begin our introduction to GTK, we'll start with the simplest
85 program possible. This program will create a 200x200 pixel window and
86 has no way of exiting except to be killed using the shell.
87
88 <tscreen><verb>
89 /* example-start base base.c */
90
91 #include <gtk/gtk.h>
92
93 int main( int   argc,
94           char *argv[] )
95 {
96     GtkWidget *window;
97     
98     gtk_init (&amp;argc, &amp;argv);
99     
100     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
101     gtk_widget_show  (window);
102     
103     gtk_main ();
104     
105     return(0);
106 }
107 /* example-end */
108 </verb></tscreen>
109
110 You can compile the above program with gcc using:
111 <tscreen><verb>
112 gcc base.c -o base `gtk-config --cflags --libs`
113 </verb></tscreen>
114
115 The meaning of the unusual compilation options is explained below.
116
117 All programs will of course include gtk/gtk.h which declares the
118 variables, functions, structures etc. that will be used in your GTK
119 application.
120
121 The next line:
122
123 <tscreen><verb>
124 gtk_init (&amp;argc, &amp;argv);
125 </verb></tscreen>
126
127 calls the function gtk_init(gint *argc, gchar ***argv) which will be
128 called in all GTK applications. This sets up a few things for us such
129 as the default visual and color map and then proceeds to call
130 gdk_init(gint *argc, gchar ***argv). This function initializes the
131 library for use, sets up default signal handlers, and checks the
132 arguments passed to your application on the command line, looking for
133 one of the following:
134
135 <itemize>
136 <item> <tt/--gtk-module/
137 <item> <tt/--g-fatal-warnings/
138 <item> <tt/--gtk-debug/
139 <item> <tt/--gtk-no-debug/
140 <item> <tt/--gdk-debug/
141 <item> <tt/--gdk-no-debug/
142 <item> <tt/--display/
143 <item> <tt/--sync/
144 <item> <tt/--no-xshm/
145 <item> <tt/--name/
146 <item> <tt/--class/
147 </itemize>
148
149 It removes these from the argument list, leaving anything it does not
150 recognize for your application to parse or ignore. This creates a set
151 of standard arguments accepted by all GTK applications.
152
153 The next two lines of code create and display a window.
154
155 <tscreen><verb>
156   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
157   gtk_widget_show (window);
158 </verb></tscreen>
159
160 The GTK_WINDOW_TOPLEVEL argument specifies that we want the window to
161 undergo window manager decoration and placement. Rather than create a
162 window of 0x0 size, a window without children is set to 200x200 by
163 default so you can still manipulate it.
164
165 The gtk_widget_show() function lets GTK know that we are done setting
166 the attributes of this widget, and that it can display it.
167
168 The last line enters the GTK main processing loop.
169
170 <tscreen><verb>
171   gtk_main ();
172 </verb></tscreen>
173
174 gtk_main() is another call you will see in every GTK application.
175 When control reaches this point, GTK will sleep waiting for X events
176 (such as button or key presses), timeouts, or file IO notifications to
177 occur. In our simple example however, events are ignored.
178
179 <!-- ----------------------------------------------------------------- -->
180 <sect1>Hello World in GTK
181 <p>
182 Now for a program with a widget (a button).  It's the classic
183 hello world a la GTK.
184
185 <tscreen><verb>
186 /* example-start helloworld helloworld.c */
187
188 #include <gtk/gtk.h>
189
190 /* This is a callback function. The data arguments are ignored
191  * in this example. More on callbacks below. */
192 void hello( GtkWidget *widget,
193             gpointer   data )
194 {
195     g_print ("Hello World\n");
196 }
197
198 gint delete_event( GtkWidget *widget,
199                    GdkEvent  *event,
200                    gpointer   data )
201 {
202     /* If you return FALSE in the "delete_event" signal handler,
203      * GTK will emit the "destroy" signal. Returning TRUE means
204      * you don't want the window to be destroyed.
205      * This is useful for popping up 'are you sure you want to quit?'
206      * type dialogs. */
207
208     g_print ("delete event occurred\n");
209
210     /* Change TRUE to FALSE and the main window will be destroyed with
211      * a "delete_event". */
212
213     return(TRUE);
214 }
215
216 /* Another callback */
217 void destroy( GtkWidget *widget,
218               gpointer   data )
219 {
220     gtk_main_quit();
221 }
222
223 int main( int   argc,
224           char *argv[] )
225 {
226     /* GtkWidget is the storage type for widgets */
227     GtkWidget *window;
228     GtkWidget *button;
229     
230     /* This is called in all GTK applications. Arguments are parsed
231      * from the command line and are returned to the application. */
232     gtk_init(&amp;argc, &amp;argv);
233     
234     /* create a new window */
235     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
236     
237     /* When the window is given the "delete_event" signal (this is given
238      * by the window manager, usually by the 'close' option, or on the
239      * titlebar), we ask it to call the delete_event () function
240      * as defined above. The data passed to the callback
241      * function is NULL and is ignored in the callback function. */
242     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
243                         GTK_SIGNAL_FUNC (delete_event), NULL);
244     
245     /* Here we connect the "destroy" event to a signal handler.  
246      * This event occurs when we call gtk_widget_destroy() on the window,
247      * or if we return 'FALSE' in the "delete_event" callback. */
248     gtk_signal_connect (GTK_OBJECT (window), "destroy",
249                         GTK_SIGNAL_FUNC (destroy), NULL);
250     
251     /* Sets the border width of the window. */
252     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
253     
254     /* Creates a new button with the label "Hello World". */
255     button = gtk_button_new_with_label ("Hello World");
256     
257     /* When the button receives the "clicked" signal, it will call the
258      * function hello() passing it NULL as its argument.  The hello()
259      * function is defined above. */
260     gtk_signal_connect (GTK_OBJECT (button), "clicked",
261                         GTK_SIGNAL_FUNC (hello), NULL);
262     
263     /* This will cause the window to be destroyed by calling
264      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
265      * signal could come from here, or the window manager. */
266     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
267                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
268                                GTK_OBJECT (window));
269     
270     /* This packs the button into the window (a gtk container). */
271     gtk_container_add (GTK_CONTAINER (window), button);
272     
273     /* The final step is to display this newly created widget. */
274     gtk_widget_show (button);
275     
276     /* and the window */
277     gtk_widget_show (window);
278     
279     /* All GTK applications must have a gtk_main(). Control ends here
280      * and waits for an event to occur (like a key press or
281      * mouse event). */
282     gtk_main ();
283     
284     return(0);
285 }
286 /* example-end */
287 </verb></tscreen>
288
289 <!-- ----------------------------------------------------------------- -->
290 <sect1>Compiling Hello World
291 <p>
292 To compile use:
293
294 <tscreen><verb>
295 gcc -Wall -g helloworld.c -o helloworld `gtk-config --cflags` \
296     `gtk-config --libs`
297 </verb></tscreen>
298
299 This uses the program <tt>gtk-config</>, which comes with gtk. This
300 program 'knows' what compiler switches are needed to compile programs
301 that use gtk. <tt>gtk-config --cflags</> will output a list of include
302 directories for the compiler to look in, and <tt>gtk-config --libs</>
303 will output the list of libraries for the compiler to link with and
304 the directories to find them in. In the aboce example they could have
305 been combined into a single instance, such as
306 `gtk-config --cflags --libs`.
307
308 Note that the type of single quote used in the compile command above
309 is significant.
310
311 The libraries that are usually linked in are:
312 <itemize>
313 <item>The GTK library (-lgtk), the widget library, based on top of GDK.
314 <item>The GDK library (-lgdk), the Xlib wrapper.
315 <item>The gmodule library (-lgmodule), which is used to load run time
316 extensions.
317 <item>The glib library (-lglib), containing miscellaneous functions, only
318 g_print() is used in this particular example. GTK is built on top
319 of glib so you will always require this library. See the section on 
320 <ref id="sec_glib" name="glib"> for details.
321 <item>The Xlib library (-lX11) which is used by GDK.
322 <item>The Xext library (-lXext). This contains code for shared memory
323 pixmaps and other X extensions.
324 <item>The math library (-lm). This is used by GTK for various purposes.
325 </itemize>
326
327 <!-- ----------------------------------------------------------------- -->
328 <sect1>Theory of Signals and Callbacks
329 <p>
330 Before we look in detail at <em>helloworld</em>, we'll discuss signals
331 and callbacks. GTK is an event driven toolkit, which means it will
332 sleep in gtk_main until an event occurs and control is passed to the
333 appropriate function.
334
335 This passing of control is done using the idea of "signals". When an
336 event occurs, such as the press of a mouse button, the appropriate
337 signal will be "emitted" by the widget that was pressed.  This is how
338 GTK does most of its useful work. There are a set of signals that all
339 widgets inherit, such as "destroy", and there are signals that are
340 widget specific, such as "toggled" on a toggle button.
341
342 To make a button perform an action, we set up a signal handler to
343 catch these signals and call the appropriate function. This is done by
344 using a function such as:
345
346 <tscreen><verb>
347 gint gtk_signal_connect( GtkObject     *object,
348                          gchar         *name,
349                          GtkSignalFunc  func,
350                          gpointer       func_data );
351 </verb></tscreen>
352
353 Where the first argument is the widget which will be emitting the
354 signal, and the second, the name of the signal you wish to catch. The
355 third is the function you wish to be called when it is caught, and the
356 fourth, the data you wish to have passed to this function.
357
358 The function specified in the third argument is called a "callback
359 function", and should generally be of the form:
360
361 <tscreen><verb>
362 void callback_func( GtkWidget *widget,
363                     gpointer   callback_data );
364 </verb></tscreen>
365
366 Where the first argument will be a pointer to the widget that emitted
367 the signal, and the second, a pointer to the data given as the last
368 argument to the gtk_signal_connect() function as shown above.
369
370 Note that the above form for a signal callback function declaration is
371 only a general guide, as some widget specific signals generate
372 different calling parameters. For example, the GtkCList "select_row"
373 signal provides both row and column parameters.
374
375 Another call used in the <em>helloworld</em> example, is:
376
377 <tscreen><verb>
378 gint gtk_signal_connect_object( GtkObject     *object,
379                                 gchar         *name,
380                                 GtkSignalFunc  func,
381                                 GtkObject     *slot_object );
382 </verb></tscreen>
383
384 gtk_signal_connect_object() is the same as gtk_signal_connect() except
385 that the callback function only uses one argument, a pointer to a GTK
386 object. So when using this function to connect signals, the callback
387 should be of the form:
388
389 <tscreen><verb>
390 void callback_func( GtkObject *object );
391 </verb></tscreen>
392
393 Where the object is usually a widget. We usually don't setup callbacks
394 for gtk_signal_connect_object however. They are usually used to call a
395 GTK function that accepts a single widget or object as an argument, as
396 is the case in our <em>helloworld</em> example.
397
398 The purpose of having two functions to connect signals is simply to
399 allow the callbacks to have a different number of arguments. Many
400 functions in the GTK library accept only a single GtkWidget pointer as
401 an argument, so you want to use the gtk_signal_connect_object() for
402 these, whereas for your functions, you may need to have additional
403 data supplied to the callbacks.
404
405 <!-- ----------------------------------------------------------------- -->
406 <sect1>Events
407 <p>
408 In addition to the signal mechanism described above, there are a set
409 of <em>events</em> that reflect the X event mechanism. Callbacks may
410 also be attached to these events. These events are:
411
412 <itemize>
413 <item> event
414 <item> button_press_event
415 <item> button_release_event
416 <item> motion_notify_event
417 <item> delete_event
418 <item> destroy_event
419 <item> expose_event
420 <item> key_press_event
421 <item> key_release_event
422 <item> enter_notify_event
423 <item> leave_notify_event
424 <item> configure_event
425 <item> focus_in_event
426 <item> focus_out_event
427 <item> map_event
428 <item> unmap_event
429 <item> property_notify_event
430 <item> selection_clear_event
431 <item> selection_request_event
432 <item> selection_notify_event
433 <item> proximity_in_event
434 <item> proximity_out_event
435 <item> drag_begin_event
436 <item> drag_request_event
437 <item> drag_end_event
438 <item> drop_enter_event
439 <item> drop_leave_event
440 <item> drop_data_available_event
441 <item> other_event
442 </itemize>
443
444 In order to connect a callback function to one of these events, you
445 use the function gtk_signal_connect, as described above, using one of
446 the above event names as the <tt/name/ parameter. The callback
447 function for events has a slightly different form than that for
448 signals:
449
450 <tscreen><verb>
451 void callback_func( GtkWidget *widget,
452                     GdkEvent  *event,
453                     gpointer   callback_data );
454 </verb></tscreen>
455
456 GdkEvent is a C <tt/union/ structure whose type will depend upon which
457 of the above events has occurred. In order for us to tell which event
458 has been issued each of the possible alternatives has a <tt/type/
459 parameter which reflects the event being issued. The other components
460 of the event structure will depend upon the type of the
461 event. Possible values for the type are:
462
463 <tscreen><verb>
464   GDK_NOTHING
465   GDK_DELETE
466   GDK_DESTROY
467   GDK_EXPOSE
468   GDK_MOTION_NOTIFY
469   GDK_BUTTON_PRESS
470   GDK_2BUTTON_PRESS
471   GDK_3BUTTON_PRESS
472   GDK_BUTTON_RELEASE
473   GDK_KEY_PRESS
474   GDK_KEY_RELEASE
475   GDK_ENTER_NOTIFY
476   GDK_LEAVE_NOTIFY
477   GDK_FOCUS_CHANGE
478   GDK_CONFIGURE
479   GDK_MAP
480   GDK_UNMAP
481   GDK_PROPERTY_NOTIFY
482   GDK_SELECTION_CLEAR
483   GDK_SELECTION_REQUEST
484   GDK_SELECTION_NOTIFY
485   GDK_PROXIMITY_IN
486   GDK_PROXIMITY_OUT
487   GDK_DRAG_BEGIN
488   GDK_DRAG_REQUEST
489   GDK_DROP_ENTER
490   GDK_DROP_LEAVE
491   GDK_DROP_DATA_AVAIL
492   GDK_CLIENT_EVENT
493   GDK_VISIBILITY_NOTIFY
494   GDK_NO_EXPOSE
495   GDK_OTHER_EVENT       /* Deprecated, use filters instead */
496 </verb></tscreen>
497
498 So, to connect a callback function to one of these events we would use
499 something like:
500
501 <tscreen><verb>
502 gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
503                     GTK_SIGNAL_FUNC(button_press_callback), 
504                         NULL);
505 </verb></tscreen>
506
507 This assumes that <tt/button/ is a GtkButton widget. Now, when the
508 mouse is over the button and a mouse button is pressed, the function
509 <tt/button_press_callback/ will be called. This function may be
510 declared as:
511
512 <tscreen><verb>
513 static gint button_press_event (GtkWidget      *widget, 
514                                 GdkEventButton *event,
515                                 gpointer        data);
516 </verb></tscreen>
517
518 Note that we can declare the second argument as type
519 <tt/GdkEventButton/ as we know what type of event will occur for this
520 function to be called.
521
522 The value returned from this function indicates whether the event
523 should be propagated further by the GTK event handling
524 mechanism. Returning TRUE indicates that the event has been handled,
525 and that it should not propagate further. Returning FALSE continues
526 the normal event handling.  See the section on
527 <ref id="sec_Adv_Events_and_Signals"
528 name="Advanced Event and Signal Handling"> for more details on this
529 propagation process.
530
531 For details on the GdkEvent data types, see the appendix entitled
532 <ref id="sec_GDK_Event_Types" name="GDK Event Types">.
533
534 <!-- ----------------------------------------------------------------- -->
535 <sect1>Stepping Through Hello World
536 <p>
537 Now that we know the theory behind this, lets clarify by walking through 
538 the example <em>helloworld</em> program.
539
540 Here is the callback function that will be called when the button is
541 "clicked". We ignore both the widget and the data in this example, but
542 it is not hard to do things with them. The next example will use the
543 data argument to tell us which button was pressed.
544
545 <tscreen><verb>
546 void hello( GtkWidget *widget,
547             gpointer   data )
548 {
549     g_print ("Hello World\n");
550 }
551 </verb></tscreen>
552
553 The next callback is a bit special. The "delete_event" occurs when the
554 window manager sends this event to the application. We have a choice
555 here as to what to do about these events. We can ignore them, make
556 some sort of response, or simply quit the application.
557
558 The value you return in this callback lets GTK know what action to
559 take.  By returning TRUE, we let it know that we don't want to have
560 the "destroy" signal emitted, keeping our application running. By
561 returning FALSE, we ask that "destroy" is emitted, which in turn will
562 call our "destroy" signal handler.
563
564 <tscreen><verb>
565 gint delete_event( GtkWidget *widget,
566                    GdkEvent  *event,
567                    gpointer   data )
568 {
569     g_print ("delete event occurred\n");
570
571     return (TRUE); 
572 }
573 </verb></tscreen>
574
575 Here is another callback function which causes the program to quit by
576 calling gtk_main_quit(). This function tells GTK that it is to exit
577 from gtk_main when control is returned to it.
578
579 <tscreen><verb>
580 void destroy( GtkWidget *widget,
581               gpointer   data )
582 {
583     gtk_main_quit ();
584 }
585 </verb></tscreen>
586
587 I assume you know about the main() function... yes, as with other
588 applications, all GTK applications will also have one of these.
589
590 <tscreen><verb>
591 int main( int   argc,
592           char *argv[] )
593 {
594 </verb></tscreen>
595
596 This next part, declares a pointer to a structure of type
597 GtkWidget. These are used below to create a window and a button.
598
599 <tscreen><verb>
600     GtkWidget *window;
601     GtkWidget *button;
602 </verb></tscreen>
603
604 Here is our gtk_init again. As before, this initializes the toolkit,
605 and parses the arguments found on the command line. Any argument it
606 recognizes from the command line, it removes from the list, and
607 modifies argc and argv to make it look like they never existed,
608 allowing your application to parse the remaining arguments.
609
610 <tscreen><verb>
611     gtk_init (&amp;argc, &amp;argv);
612 </verb></tscreen>
613
614 Create a new window. This is fairly straight forward. Memory is
615 allocated for the GtkWidget *window structure so it now points to a
616 valid structure. It sets up a new window, but it is not displayed
617 until we call gtk_widget_show(window) near the end of our program.
618
619 <tscreen><verb>
620     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
621 </verb></tscreen>
622
623 Here is an example of connecting a signal handler to an object, in
624 this case, the window. Here, the "destroy" signal is caught. This is
625 emitted when we use the window manager to kill the window (and we
626 return FALSE in the "delete_event" handler), or when we use the
627 gtk_widget_destroy() call passing in the window widget as the object
628 to destroy. By setting this up, we handle both cases with a single
629 call. Here, it just calls the destroy() function defined above with a
630 NULL argument, which quits GTK for us.
631
632 The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform type
633 casting and checking for us, as well as aid the readability of the
634 code.
635
636 <tscreen><verb>
637     gtk_signal_connect (GTK_OBJECT (window), "destroy",
638                         GTK_SIGNAL_FUNC (destroy), NULL);
639 </verb></tscreen>
640
641 This next function is used to set an attribute of a container object.
642 This just sets the window so it has a blank area along the inside of
643 it 10 pixels wide where no widgets will go. There are other similar
644 functions which we will look at in the section on
645 <ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
646
647 And again, GTK_CONTAINER is a macro to perform type casting.
648
649 <tscreen><verb>
650     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
651 </verb></tscreen>
652
653 This call creates a new button. It allocates space for a new GtkWidget
654 structure in memory, initializes it, and makes the button pointer
655 point to it. It will have the label "Hello World" on it when
656 displayed.
657
658 <tscreen><verb>
659     button = gtk_button_new_with_label ("Hello World");
660 </verb></tscreen>
661
662 Here, we take this button, and make it do something useful. We attach
663 a signal handler to it so when it emits the "clicked" signal, our
664 hello() function is called. The data is ignored, so we simply pass in
665 NULL to the hello() callback function. Obviously, the "clicked" signal
666 is emitted when we click the button with our mouse pointer.
667
668 <tscreen><verb>
669     gtk_signal_connect (GTK_OBJECT (button), "clicked",
670                         GTK_SIGNAL_FUNC (hello), NULL);
671 </verb></tscreen>
672
673 We are also going to use this button to exit our program. This will
674 illustrate how the "destroy" signal may come from either the window
675 manager, or our program. When the button is "clicked", same as above,
676 it calls the first hello() callback function, and then this one in the
677 order they are set up. You may have as many callback functions as you
678 need, and all will be executed in the order you connected
679 them. Because the gtk_widget_destroy() function accepts only a
680 GtkWidget *widget as an argument, we use the
681 gtk_signal_connect_object() function here instead of straight
682 gtk_signal_connect().
683
684 <tscreen><verb>
685     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
686                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
687                                GTK_OBJECT (window));
688 </verb></tscreen>
689
690 This is a packing call, which will be explained in depth later on. But
691 it is fairly easy to understand. It simply tells GTK that the button
692 is to be placed in the window where it will be displayed. Note that a
693 GTK container can only contain one widget. There are other widgets,
694 that are described later, which are designed to layout multiple
695 widgets in various ways.
696  
697 <tscreen><verb>
698     gtk_container_add (GTK_CONTAINER (window), button);
699 </verb></tscreen>
700
701 Now we have everything set up the way we want it to be. With all the
702 signal handlers in place, and the button placed in the window where it
703 should be, we ask GTK to "show" the widgets on the screen. The window
704 widget is shown last so the whole window will pop up at once rather
705 than seeing the window pop up, and then the button form inside of
706 it. Although with such a simple example, you'd never notice.
707
708 <tscreen><verb>
709     gtk_widget_show (button);
710
711     gtk_widget_show (window);
712 </verb></tscreen>
713
714 And of course, we call gtk_main() which waits for events to come from
715 the X server and will call on the widgets to emit signals when these
716 events come.
717
718 <tscreen><verb>
719     gtk_main ();
720 </verb></tscreen>
721
722 And the final return. Control returns here after gtk_quit() is called.
723
724 <tscreen><verb>
725     return 0;
726 </verb></tscreen>
727
728 Now, when we click the mouse button on a GTK button, the widget emits
729 a "clicked" signal. In order for us to use this information, our
730 program sets up a signal handler to catch that signal, which
731 dispatches the function of our choice. In our example, when the button
732 we created is "clicked", the hello() function is called with a NULL
733 argument, and then the next handler for this signal is called. This
734 calls the gtk_widget_destroy() function, passing it the window widget
735 as its argument, destroying the window widget. This causes the window
736 to emit the "destroy" signal, which is caught, and calls our destroy()
737 callback function, which simply exits GTK.
738
739 Another course of events, is to use the window manager to kill the
740 window. This will cause the "delete_event" to be emitted. This will
741 call our "delete_event" handler. If we return TRUE here, the window
742 will be left as is and nothing will happen. Returning FALSE will cause
743 GTK to emit the "destroy" signal which of course, calls the "destroy"
744 callback, exiting GTK.
745
746 Note that these signals are not the same as the Unix system signals,
747 and are not implemented using them, although the terminology is almost
748 identical.
749
750 <!-- ***************************************************************** -->
751 <sect>Moving On
752 <!-- ***************************************************************** -->
753
754 <!-- ----------------------------------------------------------------- -->
755 <sect1>Data Types
756 <p>
757 There are a few things you probably noticed in the previous examples
758 that need explaining. The gint, gchar etc. that you see are typedefs
759 to int and char respectively. This is done to get around that nasty
760 dependency on the size of simple data types when doing calculations.
761
762 A good example is "gint32" which will be typedef'd to a 32 bit integer
763 for any given platform, whether it be the 64 bit alpha, or the 32 bit
764 i386. The typedefs are very straight forward and intuitive. They are
765 all defined in glib/glib.h (which gets included from gtk.h).
766
767 You'll also notice the ability to use GtkWidget when the function
768 calls for a GtkObject. GTK is an object oriented design, and a widget
769 is an object.
770
771 <!-- ----------------------------------------------------------------- -->
772 <sect1>More on Signal Handlers
773 <p>
774 Lets take another look at the gtk_signal_connect declaration.
775
776 <tscreen><verb>
777 gint gtk_signal_connect( GtkObject *object,
778                          gchar *name,
779                          GtkSignalFunc func,
780                          gpointer func_data );
781 </verb></tscreen>
782
783 Notice the gint return value? This is a tag that identifies your
784 callback function. As stated above, you may have as many callbacks per
785 signal and per object as you need, and each will be executed in turn,
786 in the order they were attached.
787
788 This tag allows you to remove this callback from the list by using:
789
790 <tscreen><verb>
791 void gtk_signal_disconnect( GtkObject *object,
792                             gint id );
793 </verb></tscreen>
794
795 So, by passing in the widget you wish to remove the handler from, and
796 the tag returned by one of the signal_connect functions, you can
797 disconnect a signal handler.
798
799 Another function to remove all the signal handers from an object is:
800
801 <tscreen><verb>
802 void gtk_signal_handlers_destroy( GtkObject *object );
803 </verb></tscreen>
804
805 This call is fairly self explanatory. It simply removes all the
806 current signal handlers from the object passed in as the first
807 argument.
808
809 <!-- ----------------------------------------------------------------- -->
810 <sect1>An Upgraded Hello World
811 <p>
812 Let's take a look at a slightly improved <em>helloworld</em> with
813 better examples of callbacks. This will also introduce us to our next
814 topic, packing widgets.
815
816 <tscreen><verb>
817 /* example-start helloworld2 helloworld2.c */
818
819 #include <gtk/gtk.h>
820
821 /* Our new improved callback.  The data passed to this function
822  * is printed to stdout. */
823 void callback( GtkWidget *widget,
824                gpointer   data )
825 {
826     g_print ("Hello again - %s was pressed\n", (char *) data);
827 }
828
829 /* another callback */
830 void delete_event( GtkWidget *widget,
831                    GdkEvent  *event,
832                    gpointer   data )
833 {
834     gtk_main_quit ();
835 }
836
837 int main( int   argc,
838           char *argv[] )
839 {
840     /* GtkWidget is the storage type for widgets */
841     GtkWidget *window;
842     GtkWidget *button;
843     GtkWidget *box1;
844
845     /* This is called in all GTK applications. Arguments are parsed
846      * from the command line and are returned to the application. */
847     gtk_init (&amp;argc, &amp;argv);
848
849     /* Create a new window */
850     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
851
852     /* This is a new call, this just sets the title of our
853      * new window to "Hello Buttons!" */
854     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
855
856     /* Here we just set a handler for delete_event that immediately
857      * exits GTK. */
858     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
859                         GTK_SIGNAL_FUNC (delete_event), NULL);
860
861     /* Sets the border width of the window. */
862     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
863
864     /* We create a box to pack widgets into.  This is described in detail
865      * in the "packing" section. The box is not really visible, it
866      * is just used as a tool to arrange widgets. */
867     box1 = gtk_hbox_new(FALSE, 0);
868
869     /* Put the box into the main window. */
870     gtk_container_add (GTK_CONTAINER (window), box1);
871
872     /* Creates a new button with the label "Button 1". */
873     button = gtk_button_new_with_label ("Button 1");
874
875     /* Now when the button is clicked, we call the "callback" function
876      * with a pointer to "button 1" as its argument */
877     gtk_signal_connect (GTK_OBJECT (button), "clicked",
878                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
879
880     /* Instead of gtk_container_add, we pack this button into the invisible
881      * box, which has been packed into the window. */
882     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
883
884     /* Always remember this step, this tells GTK that our preparation for
885      * this button is complete, and it can now be displayed. */
886     gtk_widget_show(button);
887
888     /* Do these same steps again to create a second button */
889     button = gtk_button_new_with_label ("Button 2");
890
891     /* Call the same callback function with a different argument,
892      * passing a pointer to "button 2" instead. */
893     gtk_signal_connect (GTK_OBJECT (button), "clicked",
894                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
895
896     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
897
898     /* The order in which we show the buttons is not really important, but I
899      * recommend showing the window last, so it all pops up at once. */
900     gtk_widget_show(button);
901
902     gtk_widget_show(box1);
903
904     gtk_widget_show (window);
905
906     /* Rest in gtk_main and wait for the fun to begin! */
907     gtk_main ();
908
909     return(0);
910 }
911 /* example-end */
912 </verb></tscreen>
913
914 Compile this program using the same linking arguments as our first
915 example.  You'll notice this time there is no easy way to exit the
916 program, you have to use your window manager or command line to kill
917 it. A good exercise for the reader would be to insert a third "Quit"
918 button that will exit the program. You may also wish to play with the
919 options to gtk_box_pack_start() while reading the next section.  Try
920 resizing the window, and observe the behavior.
921
922 Just as a side note, there is another useful define for
923 gtk_window_new() - GTK_WINDOW_DIALOG. This interacts with the window
924 manager a little differently and should be used for transient windows.
925
926 <!-- ***************************************************************** -->
927 <sect>Packing Widgets
928 <!-- ***************************************************************** -->
929 <p>
930 When creating an application, you'll want to put more than one widget
931 inside a window. Our first <em>helloworld</em> example only used one
932 widget so we could simply use a gtk_container_add call to "pack" the
933 widget into the window. But when you want to put more than one widget
934 into a window, how do you control where that widget is positioned?
935 This is where packing comes in.
936
937 <!-- ----------------------------------------------------------------- -->
938 <sect1>Theory of Packing Boxes
939 <p>
940 Most packing is done by creating boxes as in the example above. These
941 are invisible widget containers that we can pack our widgets into
942 which come in two forms, a horizontal box, and a vertical box. When
943 packing widgets into a horizontal box, the objects are inserted
944 horizontally from left to right or right to left depending on the call
945 used. In a vertical box, widgets are packed from top to bottom or vice
946 versa. You may use any combination of boxes inside or beside other
947 boxes to create the desired effect.
948
949 To create a new horizontal box, we use a call to gtk_hbox_new(), and
950 for vertical boxes, gtk_vbox_new().The gtk_box_pack_start() and
951 gtk_box_pack_end() functions are used to place objects inside of these
952 containers. The gtk_box_pack_start() function will start at the top
953 and work its way down in a vbox, and pack left to right in an hbox.
954 gtk_box_pack_end() will do the opposite, packing from bottom to top in
955 a vbox, and right to left in an hbox. Using these functions allow us
956 to right justify or left justify our widgets and may be mixed in any
957 way to achieve the desired effect. We will use gtk_box_pack_start() in
958 most of our examples. An object may be another container or a
959 widget. In fact, many widgets are actually containers themselves,
960 including the button, but we usually only use a label inside a button.
961
962 By using these calls, GTK knows where you want to place your widgets
963 so it can do automatic resizing and other nifty things. There's also a
964 number of options as to how your widgets should be packed. As you can
965 imagine, this method gives us a quite a bit of flexibility when
966 placing and creating widgets.
967
968 <!-- ----------------------------------------------------------------- -->
969 <sect1>Details of Boxes
970 <p>
971 Because of this flexibility, packing boxes in GTK can be confusing at
972 first. There are a lot of options, and it's not immediately obvious how
973 they all fit together. In the end however, there are basically five
974 different styles.
975
976 <? <CENTER> >
977 <?
978 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
979 HEIGHT="235" ALT="Box Packing Example Image">
980 >
981 <? </CENTER> >
982
983 Each line contains one horizontal box (hbox) with several buttons. The
984 call to gtk_box_pack is shorthand for the call to pack each of the
985 buttons into the hbox. Each of the buttons is packed into the hbox the
986 same way (i.e. same arguments to the gtk_box_pack_start() function).
987
988 This is the declaration of the gtk_box_pack_start function.
989
990 <tscreen><verb>
991 void gtk_box_pack_start( GtkBox    *box,
992                          GtkWidget *child,
993                          gint       expand,
994                          gint       fill,
995                          gint       padding );
996 </verb></tscreen>
997
998 The first argument is the box you are packing the object into, the
999 second is the object. The objects will all be buttons for now, so
1000 we'll be packing buttons into boxes.
1001
1002 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1003 controls whether the widgets are laid out in the box to fill in all
1004 the extra space in the box so the box is expanded to fill the area
1005 alloted to it (TRUE).  Or the box is shrunk to just fit the widgets
1006 (FALSE). Setting expand to FALSE will allow you to do right and left
1007 justification of your widgets.  Otherwise, they will all expand to fit
1008 into the box, and the same effect could be achieved by using only one
1009 of gtk_box_pack_start or gtk_box_pack_end.
1010
1011 The fill argument to the gtk_box_pack functions control whether the
1012 extra space is allocated to the objects themselves (TRUE), or as extra
1013 padding in the box around these objects (FALSE). It only has an effect
1014 if the expand argument is also TRUE.
1015
1016 When creating a new box, the function looks like this:
1017
1018 <tscreen><verb>
1019 GtkWidget *gtk_hbox_new (gint homogeneous,
1020                          gint spacing);
1021 </verb></tscreen>
1022
1023 The homogeneous argument to gtk_hbox_new (and the same for
1024 gtk_vbox_new) controls whether each object in the box has the same
1025 size (i.e. the same width in an hbox, or the same height in a
1026 vbox). If it is set, the expand argument to the gtk_box_pack routines
1027 is always turned on.
1028
1029 What's the difference between spacing (set when the box is created)
1030 and padding (set when elements are packed)? Spacing is added between
1031 objects, and padding is added on either side of an object. The
1032 following figure should make it clearer:
1033
1034 <? <CENTER> >
1035 <?
1036 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1037 HEIGHT="213" VSPACE="15" HSPACE="10"
1038 ALT="Box Packing Example Image">
1039 >
1040 <? </CENTER> >
1041
1042 Here is the code used to create the above images. I've commented it
1043 fairly heavily so hopefully you won't have any problems following
1044 it. Compile it yourself and play with it.
1045
1046 <!-- ----------------------------------------------------------------- -->
1047 <sect1>Packing Demonstration Program
1048 <p>
1049 <tscreen><verb>
1050 /* example-start packbox packbox.c */
1051
1052 #include <stdio.h>
1053 #include "gtk/gtk.h"
1054
1055 void delete_event( GtkWidget *widget,
1056                    GdkEvent  *event,
1057                    gpointer   data )
1058 {
1059     gtk_main_quit ();
1060 }
1061
1062 /* Make a new hbox filled with button-labels. Arguments for the 
1063  * variables we're interested are passed in to this function. 
1064  * We do not show the box, but do show everything inside. */
1065 GtkWidget *make_box( gint homogeneous,
1066                      gint spacing,
1067                      gint expand,
1068                      gint fill,
1069                      gint padding ) 
1070 {
1071     GtkWidget *box;
1072     GtkWidget *button;
1073     char padstr[80];
1074     
1075     /* Create a new hbox with the appropriate homogeneous
1076      * and spacing settings */
1077     box = gtk_hbox_new (homogeneous, spacing);
1078     
1079     /* Create a series of buttons with the appropriate settings */
1080     button = gtk_button_new_with_label ("gtk_box_pack");
1081     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1082     gtk_widget_show (button);
1083     
1084     button = gtk_button_new_with_label ("(box,");
1085     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1086     gtk_widget_show (button);
1087     
1088     button = gtk_button_new_with_label ("button,");
1089     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1090     gtk_widget_show (button);
1091     
1092     /* Create a button with the label depending on the value of
1093      * expand. */
1094     if (expand == TRUE)
1095             button = gtk_button_new_with_label ("TRUE,");
1096     else
1097             button = gtk_button_new_with_label ("FALSE,");
1098     
1099     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1100     gtk_widget_show (button);
1101     
1102     /* This is the same as the button creation for "expand"
1103      * above, but uses the shorthand form. */
1104     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1105     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1106     gtk_widget_show (button);
1107     
1108     sprintf (padstr, "%d);", padding);
1109     
1110     button = gtk_button_new_with_label (padstr);
1111     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1112     gtk_widget_show (button);
1113     
1114     return box;
1115 }
1116
1117 int main( int   argc,
1118           char *argv[]) 
1119 {
1120     GtkWidget *window;
1121     GtkWidget *button;
1122     GtkWidget *box1;
1123     GtkWidget *box2;
1124     GtkWidget *separator;
1125     GtkWidget *label;
1126     GtkWidget *quitbox;
1127     int which;
1128     
1129     /* Our init, don't forget this! :) */
1130     gtk_init (&amp;argc, &amp;argv);
1131     
1132     if (argc != 2) {
1133         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1134         /* this just does cleanup in GTK, and exits with an exit status of 1. */
1135         gtk_exit (1);
1136     }
1137     
1138     which = atoi (argv[1]);
1139
1140     /* Create our window */
1141     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1142
1143     /* You should always remember to connect the destroy signal to the
1144      * main window. This is very important for proper intuitive
1145      * behavior */
1146     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1147                         GTK_SIGNAL_FUNC (delete_event), NULL);
1148     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1149     
1150     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1151      * This allows us to stack the horizontal boxes filled with buttons one
1152      * on top of the other in this vbox. */
1153     box1 = gtk_vbox_new (FALSE, 0);
1154     
1155     /* which example to show. These correspond to the pictures above. */
1156     switch (which) {
1157     case 1:
1158         /* create a new label. */
1159         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1160         
1161         /* Align the label to the left side.  We'll discuss this function and 
1162          * others in the section on Widget Attributes. */
1163         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1164
1165         /* Pack the label into the vertical box (vbox box1).  Remember that 
1166          * widgets added to a vbox will be packed one on top of the other in
1167          * order. */
1168         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1169         
1170         /* Show the label */
1171         gtk_widget_show (label);
1172         
1173         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1174          * expand = FALSE, fill = FALSE, padding = 0 */
1175         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1176         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1177         gtk_widget_show (box2);
1178
1179         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1180          * expand = FALSE, fill = FALSE, padding = 0 */
1181         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1182         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1183         gtk_widget_show (box2);
1184         
1185         /* Args are: homogeneous, spacing, expand, fill, padding */
1186         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1187         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1188         gtk_widget_show (box2);
1189         
1190         /* Creates a separator, we'll learn more about these later, 
1191          * but they are quite simple. */
1192         separator = gtk_hseparator_new ();
1193         
1194         /* Cack the separator into the vbox. Remember each of these
1195          * widgets are being packed into a vbox, so they'll be stacked
1196          * vertically. */
1197         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1198         gtk_widget_show (separator);
1199         
1200         /* Create another new label, and show it. */
1201         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1202         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1203         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1204         gtk_widget_show (label);
1205         
1206         /* Args are: homogeneous, spacing, expand, fill, padding */
1207         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1208         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1209         gtk_widget_show (box2);
1210         
1211         /* Args are: homogeneous, spacing, expand, fill, padding */
1212         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1213         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1214         gtk_widget_show (box2);
1215         
1216         /* Another new separator. */
1217         separator = gtk_hseparator_new ();
1218         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1219         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1220         gtk_widget_show (separator);
1221         
1222         break;
1223
1224     case 2:
1225
1226         /* Create a new label, remember box1 is a vbox as created 
1227          * near the beginning of main() */
1228         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1229         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1230         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1231         gtk_widget_show (label);
1232         
1233         /* Args are: homogeneous, spacing, expand, fill, padding */
1234         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1235         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1236         gtk_widget_show (box2);
1237         
1238         /* Args are: homogeneous, spacing, expand, fill, padding */
1239         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1240         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1241         gtk_widget_show (box2);
1242         
1243         separator = gtk_hseparator_new ();
1244         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1245         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1246         gtk_widget_show (separator);
1247         
1248         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1249         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1250         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1251         gtk_widget_show (label);
1252         
1253         /* Args are: homogeneous, spacing, expand, fill, padding */
1254         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1255         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1256         gtk_widget_show (box2);
1257         
1258         /* Args are: homogeneous, spacing, expand, fill, padding */
1259         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1260         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1261         gtk_widget_show (box2);
1262         
1263         separator = gtk_hseparator_new ();
1264         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1265         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1266         gtk_widget_show (separator);
1267         break;
1268     
1269     case 3:
1270
1271         /* This demonstrates the ability to use gtk_box_pack_end() to
1272          * right justify widgets. First, we create a new box as before. */
1273         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1274
1275         /* Create the label that will be put at the end. */
1276         label = gtk_label_new ("end");
1277         /* Pack it using gtk_box_pack_end(), so it is put on the right
1278          * side of the hbox created in the make_box() call. */
1279         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1280         /* Show the label. */
1281         gtk_widget_show (label);
1282         
1283         /* Pack box2 into box1 (the vbox remember ? :) */
1284         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1285         gtk_widget_show (box2);
1286         
1287         /* A separator for the bottom. */
1288         separator = gtk_hseparator_new ();
1289         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1290          * high. This is so the hbox we created will also be 400 pixels wide,
1291          * and the "end" label will be separated from the other labels in the
1292          * hbox. Otherwise, all the widgets in the hbox would be packed as
1293          * close together as possible. */
1294         gtk_widget_set_usize (separator, 400, 5);
1295         /* pack the separator into the vbox (box1) created near the start 
1296          * of main() */
1297         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1298         gtk_widget_show (separator);    
1299     }
1300     
1301     /* Create another new hbox.. remember we can use as many as we need! */
1302     quitbox = gtk_hbox_new (FALSE, 0);
1303     
1304     /* Our quit button. */
1305     button = gtk_button_new_with_label ("Quit");
1306     
1307     /* Setup the signal to destroy the window. Remember that this will send
1308      * the "destroy" signal to the window which will be caught by our signal
1309      * handler as defined above. */
1310     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1311                                GTK_SIGNAL_FUNC (gtk_main_quit),
1312                                GTK_OBJECT (window));
1313     /* Pack the button into the quitbox.
1314      * The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1315     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1316     /* pack the quitbox into the vbox (box1) */
1317     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1318     
1319     /* Pack the vbox (box1) which now contains all our widgets, into the
1320      * main window. */
1321     gtk_container_add (GTK_CONTAINER (window), box1);
1322     
1323     /* And show everything left */
1324     gtk_widget_show (button);
1325     gtk_widget_show (quitbox);
1326     
1327     gtk_widget_show (box1);
1328     /* Showing the window last so everything pops up at once. */
1329     gtk_widget_show (window);
1330     
1331     /* And of course, our main function. */
1332     gtk_main ();
1333
1334     /* Control returns here when gtk_main_quit() is called, but not when 
1335      * gtk_exit is used. */
1336     
1337     return(0);
1338 }
1339 /* example-end */
1340 </verb></tscreen>
1341
1342 <!-- ----------------------------------------------------------------- -->
1343 <sect1>Packing Using Tables
1344 <p>
1345 Let's take a look at another way of packing - Tables. These can be
1346 extremely useful in certain situations.
1347
1348 Using tables, we create a grid that we can place widgets in. The
1349 widgets may take up as many spaces as we specify.
1350
1351 The first thing to look at of course, is the gtk_table_new function:
1352
1353 <tscreen><verb>
1354 GtkWidget *gtk_table_new( gint rows,
1355                           gint columns,
1356                           gint homogeneous );
1357 </verb></tscreen>
1358
1359 The first argument is the number of rows to make in the table, while
1360 the second, obviously, is the number of columns.
1361
1362 The homogeneous argument has to do with how the table's boxes are
1363 sized. If homogeneous is TRUE, the table boxes are resized to the size
1364 of the largest widget in the table. If homogeneous is FALSE, the size
1365 of a table boxes is dictated by the tallest widget in its same row,
1366 and the widest widget in its column.
1367
1368 The rows and columns are laid out from 0 to n, where n was the number
1369 specified in the call to gtk_table_new. So, if you specify rows = 2
1370 and columns = 2, the layout would look something like this:
1371
1372 <tscreen><verb>
1373  0          1          2
1374 0+----------+----------+
1375  |          |          |
1376 1+----------+----------+
1377  |          |          |
1378 2+----------+----------+
1379 </verb></tscreen>
1380
1381 Note that the coordinate system starts in the upper left hand corner.
1382 To place a widget into a box, use the following function:
1383
1384 <tscreen><verb>
1385 void gtk_table_attach( GtkTable  *table,
1386                        GtkWidget *child,
1387                        gint       left_attach,
1388                        gint       right_attach,
1389                        gint       top_attach,
1390                        gint       bottom_attach,
1391                        gint       xoptions,
1392                        gint       yoptions,
1393                        gint       xpadding,
1394                        gint       ypadding );
1395 </verb></tscreen>                                      
1396
1397 Where the first argument ("table") is the table you've created and the
1398 second ("child") the widget you wish to place in the table.
1399
1400 The left and right attach arguments specify where to place the widget,
1401 and how many boxes to use. If you want a button in the lower right
1402 table entry of our 2x2 table, and want it to fill that entry ONLY,
1403 left_attach would be = 1, right_attach = 2, top_attach = 1,
1404 bottom_attach = 2.
1405
1406 Now, if you wanted a widget to take up the whole top row of our 2x2
1407 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1408 bottom_attach = 1.
1409
1410 The xoptions and yoptions are used to specify packing options and may
1411 be bitwise OR'ed together to allow multiple options.
1412
1413 These options are:
1414 <itemize>
1415 <item>GTK_FILL - If the table box is larger than the widget, and
1416 GTK_FILL is specified, the widget will expand to use all the room
1417 available.
1418
1419 <item>GTK_SHRINK - If the table widget was allocated less space then
1420 was requested (usually by the user resizing the window), then the
1421 widgets would normally just be pushed off the bottom of the window and
1422 disappear. If GTK_SHRINK is specified, the widgets will shrink with
1423 the table.
1424
1425 <item>GTK_EXPAND - This will cause the table to expand to use up any
1426 remaining space in the window.
1427 </itemize>
1428
1429 Padding is just like in boxes, creating a clear area around the widget
1430 specified in pixels.
1431
1432 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1433
1434 <tscreen><verb>
1435 void gtk_table_attach_defaults( GtkTable  *table,
1436                                 GtkWidget *widget,
1437                                 gint       left_attach,
1438                                 gint       right_attach,
1439                                 gint       top_attach,
1440                                 gint       bottom_attach );
1441 </verb></tscreen>
1442
1443 The X and Y options default to GTK_FILL | GTK_EXPAND, and X and Y
1444 padding are set to 0. The rest of the arguments are identical to the
1445 previous function.
1446
1447 We also have gtk_table_set_row_spacing() and
1448 gtk_table_set_col_spacing().  This places spacing between the rows at
1449 the specified row or column.
1450
1451 <tscreen><verb>
1452 void gtk_table_set_row_spacing( GtkTable *table,
1453                                 gint      row,
1454                                 gint      spacing );
1455 </verb></tscreen>
1456
1457 and
1458
1459 <tscreen><verb>
1460 void gtk_table_set_col_spacing ( GtkTable *table,
1461                                  gint      column,
1462                                  gint      spacing );
1463 </verb></tscreen>
1464
1465 Note that for columns, the space goes to the right of the column, and
1466 for rows, the space goes below the row.
1467
1468 You can also set a consistent spacing of all rows and/or columns with:
1469
1470 <tscreen><verb>
1471 void gtk_table_set_row_spacings( GtkTable *table,
1472                                  gint      spacing );
1473 </verb></tscreen>
1474
1475 And,
1476
1477 <tscreen><verb>
1478 void gtk_table_set_col_spacings( GtkTable *table,
1479                                  gint      spacing );
1480 </verb></tscreen>
1481
1482 Note that with these calls, the last row and last column do not get
1483 any spacing.
1484
1485 <!-- ----------------------------------------------------------------- -->
1486 <sect1>Table Packing Example
1487 <p>
1488 Here we make a window with three buttons in a 2x2 table.
1489 The first two buttons will be placed in the upper row.
1490 A third, quit button, is placed in the lower row, spanning both columns.
1491 Which means it should look something like this:
1492
1493 <? <CENTER> >
1494 <?
1495 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1496 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1497 >
1498 <? </CENTER> >
1499
1500 Here's the source code:
1501
1502 <tscreen><verb>
1503 /* example-start table table.c */
1504
1505 #include <gtk/gtk.h>
1506
1507 /* Our callback.
1508  * The data passed to this function is printed to stdout */
1509 void callback( GtkWidget *widget,
1510                gpointer   data )
1511 {
1512     g_print ("Hello again - %s was pressed\n", (char *) data);
1513 }
1514
1515 /* This callback quits the program */
1516 void delete_event( GtkWidget *widget,
1517                    GdkEvent  *event,
1518                    gpointer   data )
1519 {
1520     gtk_main_quit ();
1521 }
1522
1523 int main( int   argc,
1524           char *argv[] )
1525 {
1526     GtkWidget *window;
1527     GtkWidget *button;
1528     GtkWidget *table;
1529
1530     gtk_init (&amp;argc, &amp;argv);
1531
1532     /* Create a new window */
1533     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1534
1535     /* Set the window title */
1536     gtk_window_set_title (GTK_WINDOW (window), "Table");
1537
1538     /* Set a handler for delete_event that immediately
1539      * exits GTK. */
1540     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1541                         GTK_SIGNAL_FUNC (delete_event), NULL);
1542
1543     /* Sets the border width of the window. */
1544     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1545
1546     /* Create a 2x2 table */
1547     table = gtk_table_new (2, 2, TRUE);
1548
1549     /* Put the table in the main window */
1550     gtk_container_add (GTK_CONTAINER (window), table);
1551
1552     /* Create first button */
1553     button = gtk_button_new_with_label ("button 1");
1554
1555     /* When the button is clicked, we call the "callback" function
1556      * with a pointer to "button 1" as its argument */
1557     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1558               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1559
1560
1561     /* Insert button 1 into the upper left quadrant of the table */
1562     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1563
1564     gtk_widget_show (button);
1565
1566     /* Create second button */
1567
1568     button = gtk_button_new_with_label ("button 2");
1569
1570     /* When the button is clicked, we call the "callback" function
1571      * with a pointer to "button 2" as its argument */
1572     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1573               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1574     /* Insert button 2 into the upper right quadrant of the table */
1575     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1576
1577     gtk_widget_show (button);
1578
1579     /* Create "Quit" button */
1580     button = gtk_button_new_with_label ("Quit");
1581
1582     /* When the button is clicked, we call the "delete_event" function
1583      * and the program exits */
1584     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1585                         GTK_SIGNAL_FUNC (delete_event), NULL);
1586
1587     /* Insert the quit button into the both 
1588      * lower quadrants of the table */
1589     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1590
1591     gtk_widget_show (button);
1592
1593     gtk_widget_show (table);
1594     gtk_widget_show (window);
1595
1596     gtk_main ();
1597
1598     return 0;
1599 }
1600 /* example-end */
1601 </verb></tscreen>
1602
1603 <!-- ***************************************************************** -->
1604 <sect>Widget Overview
1605 <!-- ***************************************************************** -->
1606 <p>
1607 The general steps to creating a widget in GTK are:
1608 <enum>
1609 <item> gtk_*_new - one of various functions to create a new widget.
1610 These are all detailed in this section.
1611
1612 <item> Connect all signals and events we wish to use to the
1613 appropriate handlers.
1614
1615 <item> Set the attributes of the widget.
1616
1617 <item> Pack the widget into a container using the appropriate call
1618 such as gtk_container_add() or gtk_box_pack_start().
1619
1620 <item> gtk_widget_show() the widget.
1621 </enum>
1622
1623 gtk_widget_show() lets GTK know that we are done setting the
1624 attributes of the widget, and it is ready to be displayed. You may
1625 also use gtk_widget_hide to make it disappear again. The order in
1626 which you show the widgets is not important, but I suggest showing the
1627 window last so the whole window pops up at once rather than seeing the
1628 individual widgets come up on the screen as they're formed. The
1629 children of a widget (a window is a widget too) will not be displayed
1630 until the window itself is shown using the gtk_widget_show() function.
1631
1632 <!-- ----------------------------------------------------------------- -->
1633 <sect1> Casting
1634 <p>
1635 You'll notice as you go on, that GTK uses a type casting system. This
1636 is always done using macros that both test the ability to cast the
1637 given item, and perform the cast. Some common ones you will see are:
1638
1639 <itemize>
1640 <item> GTK_WIDGET(widget)
1641 <item> GTK_OBJECT(object)
1642 <item> GTK_SIGNAL_FUNC(function)
1643 <item> GTK_CONTAINER(container)
1644 <item> GTK_WINDOW(window)
1645 <item> GTK_BOX(box)
1646 </itemize>
1647
1648 These are all used to cast arguments in functions. You'll see them in the
1649 examples, and can usually tell when to use them simply by looking at the
1650 function's declaration.
1651
1652 As you can see below in the class hierarchy, all GtkWidgets are
1653 derived from the GtkObject base class. This means you can use a widget
1654 in any place the function asks for an object - simply use the
1655 GTK_OBJECT() macro.
1656
1657 For example:
1658
1659 <tscreen><verb>
1660 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1661                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1662 </verb></tscreen> 
1663
1664 This casts the button into an object, and provides a cast for the
1665 function pointer to the callback.
1666
1667 Many widgets are also containers. If you look in the class hierarchy
1668 below, you'll notice that many widgets derive from the GtkContainer
1669 class. Any one of these widgets may be used with the GTK_CONTAINER
1670 macro to pass them to functions that ask for containers.
1671
1672 Unfortunately, these macros are not extensively covered in the
1673 tutorial, but I recommend taking a look through the GTK header
1674 files. It can be very educational. In fact, it's not difficult to
1675 learn how a widget works just by looking at the function declarations.
1676
1677 <!-- ----------------------------------------------------------------- -->
1678 <sect1>Widget Hierarchy
1679 <p>
1680 For your reference, here is the class hierarchy tree used to implement widgets.
1681
1682 <tscreen><verb>
1683  GtkObject
1684   +GtkWidget
1685   | +GtkMisc
1686   | | +GtkLabel
1687   | | | +GtkAccelLabel
1688   | | | `GtkTipsQuery
1689   | | +GtkArrow
1690   | | +GtkImage
1691   | | `GtkPixmap
1692   | +GtkContainer
1693   | | +GtkBin
1694   | | | +GtkAlignment
1695   | | | +GtkFrame
1696   | | | | `GtkAspectFrame
1697   | | | +GtkButton
1698   | | | | +GtkToggleButton
1699   | | | | | `GtkCheckButton
1700   | | | | |   `GtkRadioButton
1701   | | | | `GtkOptionMenu
1702   | | | +GtkItem
1703   | | | | +GtkMenuItem
1704   | | | | | +GtkCheckMenuItem
1705   | | | | | | `GtkRadioMenuItem
1706   | | | | | `GtkTearoffMenuItem
1707   | | | | +GtkListItem
1708   | | | | `GtkTreeItem
1709   | | | +GtkWindow
1710   | | | | +GtkColorSelectionDialog
1711   | | | | +GtkDialog
1712   | | | | | `GtkInputDialog
1713   | | | | +GtkDrawWindow
1714   | | | | +GtkFileSelection
1715   | | | | +GtkFontSelectionDialog
1716   | | | | `GtkPlug
1717   | | | +GtkEventBox
1718   | | | +GtkHandleBox
1719   | | | +GtkScrolledWindow
1720   | | | `GtkViewport
1721   | | +GtkBox
1722   | | | +GtkButtonBox
1723   | | | | +GtkHButtonBox
1724   | | | | `GtkVButtonBox
1725   | | | +GtkVBox
1726   | | | | +GtkColorSelection
1727   | | | | `GtkGammaCurve
1728   | | | `GtkHBox
1729   | | |   +GtkCombo
1730   | | |   `GtkStatusbar
1731   | | +GtkCList
1732   | | | `GtkCTree
1733   | | +GtkFixed
1734   | | +GtkNotebook
1735   | | | `GtkFontSelection
1736   | | +GtkPaned
1737   | | | +GtkHPaned
1738   | | | `GtkVPaned
1739   | | +GtkLayout
1740   | | +GtkList
1741   | | +GtkMenuShell
1742   | | | +GtkMenuBar
1743   | | | `GtkMenu
1744   | | +GtkPacker
1745   | | +GtkSocket
1746   | | +GtkTable
1747   | | +GtkToolbar
1748   | | `GtkTree
1749   | +GtkCalendar
1750   | +GtkDrawingArea
1751   | | `GtkCurve
1752   | +GtkEditable
1753   | | +GtkEntry
1754   | | | `GtkSpinButton
1755   | | `GtkText
1756   | +GtkRuler
1757   | | +GtkHRuler
1758   | | `GtkVRuler
1759   | +GtkRange
1760   | | +GtkScale
1761   | | | +GtkHScale
1762   | | | `GtkVScale
1763   | | `GtkScrollbar
1764   | |   +GtkHScrollbar
1765   | |   `GtkVScrollbar
1766   | +GtkSeparator
1767   | | +GtkHSeparator
1768   | | `GtkVSeparator
1769   | +GtkPreview
1770   | `GtkProgress
1771   |   `GtkProgressBar
1772   +GtkData
1773   | +GtkAdjustment
1774   | `GtkTooltips
1775   `GtkItemFactory
1776 </verb></tscreen>
1777
1778 <!-- ----------------------------------------------------------------- -->
1779 <sect1>Widgets Without Windows
1780 <p>
1781 The following widgets do not have an associated window. If you want to
1782 capture events, you'll have to use the GtkEventBox. See the section on
1783 the <ref id="sec_EventBox" name="EventBox"> widget.
1784
1785 <tscreen><verb>
1786 GtkAlignment
1787 GtkArrow
1788 GtkBin
1789 GtkBox
1790 GtkImage
1791 GtkItem
1792 GtkLabel
1793 GtkPixmap
1794 GtkScrolledWindow
1795 GtkSeparator
1796 GtkTable
1797 GtkAspectFrame
1798 GtkFrame
1799 GtkVBox
1800 GtkHBox
1801 GtkVSeparator
1802 GtkHSeparator
1803 </verb></tscreen>
1804
1805 We'll further our exploration of GTK by examining each widget in turn,
1806 creating a few simple functions to display them. Another good source
1807 is the testgtk.c program that comes with GTK. It can be found in
1808 gtk/testgtk.c.
1809
1810 <!-- ***************************************************************** -->
1811 <sect>The Button Widget
1812 <!-- ***************************************************************** -->
1813
1814 <!-- ----------------------------------------------------------------- -->
1815 <sect1>Normal Buttons
1816 <p>
1817 We've almost seen all there is to see of the button widget. It's
1818 pretty simple. There are however two ways to create a button. You can
1819 use the gtk_button_new_with_label() to create a button with a label,
1820 or use gtk_button_new() to create a blank button. It's then up to you
1821 to pack a label or pixmap into this new button. To do this, create a
1822 new box, and then pack your objects into this box using the usual
1823 gtk_box_pack_start, and then use gtk_container_add to pack the box
1824 into the button.
1825
1826 Here's an example of using gtk_button_new to create a button with a
1827 picture and a label in it. I've broken up the code to create a box
1828 from the rest so you can use it in your programs. There are further
1829 examples of using pixmaps later in the tutorial.
1830
1831 <tscreen><verb>
1832 /* example-start buttons buttons.c */
1833
1834 #include <gtk/gtk.h>
1835
1836 /* Create a new hbox with an image and a label packed into it
1837  * and return the box. */
1838
1839 GtkWidget *xpm_label_box( GtkWidget *parent,
1840                           gchar     *xpm_filename,
1841                           gchar     *label_text )
1842 {
1843     GtkWidget *box1;
1844     GtkWidget *label;
1845     GtkWidget *pixmapwid;
1846     GdkPixmap *pixmap;
1847     GdkBitmap *mask;
1848     GtkStyle *style;
1849
1850     /* Create box for xpm and label */
1851     box1 = gtk_hbox_new (FALSE, 0);
1852     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1853
1854     /* Get the style of the button to get the
1855      * background color. */
1856     style = gtk_widget_get_style(parent);
1857
1858     /* Now on to the xpm stuff */
1859     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1860                                          &amp;style->bg[GTK_STATE_NORMAL],
1861                                          xpm_filename);
1862     pixmapwid = gtk_pixmap_new (pixmap, mask);
1863
1864     /* Create a label for the button */
1865     label = gtk_label_new (label_text);
1866
1867     /* Pack the pixmap and label into the box */
1868     gtk_box_pack_start (GTK_BOX (box1),
1869                         pixmapwid, FALSE, FALSE, 3);
1870
1871     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1872
1873     gtk_widget_show(pixmapwid);
1874     gtk_widget_show(label);
1875
1876     return(box1);
1877 }
1878
1879 /* Our usual callback function */
1880 void callback( GtkWidget *widget,
1881                gpointer   data )
1882 {
1883     g_print ("Hello again - %s was pressed\n", (char *) data);
1884 }
1885
1886
1887 int main( int   argc,
1888           char *argv[] )
1889 {
1890     /* GtkWidget is the storage type for widgets */
1891     GtkWidget *window;
1892     GtkWidget *button;
1893     GtkWidget *box1;
1894
1895     gtk_init (&amp;argc, &amp;argv);
1896
1897     /* Create a new window */
1898     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1899
1900     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1901
1902     /* It's a good idea to do this for all windows. */
1903     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1904                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1905
1906     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1907                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1908
1909
1910     /* Sets the border width of the window. */
1911     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1912     gtk_widget_realize(window);
1913
1914     /* Create a new button */
1915     button = gtk_button_new ();
1916
1917     /* Connect the "clicked" signal of the button to our callback */
1918     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1919                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1920
1921     /* This calls our box creating function */
1922     box1 = xpm_label_box(window, "info.xpm", "cool button");
1923
1924     /* Pack and show all our widgets */
1925     gtk_widget_show(box1);
1926
1927     gtk_container_add (GTK_CONTAINER (button), box1);
1928
1929     gtk_widget_show(button);
1930
1931     gtk_container_add (GTK_CONTAINER (window), button);
1932
1933     gtk_widget_show (window);
1934
1935     /* Rest in gtk_main and wait for the fun to begin! */
1936     gtk_main ();
1937
1938     return(0);
1939 }
1940 /* example-end */
1941 </verb></tscreen>
1942
1943 The xpm_label_box function could be used to pack xpm's and labels into
1944 any widget that can be a container.
1945
1946 The Button widget has the following signals:
1947
1948 <itemize>
1949 <item> pressed
1950 <item> released
1951 <item> clicked
1952 <item> enter
1953 <item> leave
1954 </itemize>
1955
1956 <!-- ----------------------------------------------------------------- -->
1957 <sect1> Toggle Buttons
1958 <p>
1959 Toggle buttons are derived from normal buttons and are very similar,
1960 except they will always be in one of two states, alternated by a
1961 click. They may be depressed, and when you click again, they will pop
1962 back up. Click again, and they will pop back down.
1963
1964 Toggle buttons are the basis for check buttons and radio buttons, as
1965 such, many of the calls used for toggle buttons are inherited by radio
1966 and check buttons. I will point these out when we come to them.
1967
1968 Creating a new toggle button:
1969
1970 <tscreen><verb>
1971 GtkWidget *gtk_toggle_button_new( void );
1972
1973 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
1974 </verb></tscreen>
1975
1976 As you can imagine, these work identically to the normal button widget
1977 calls. The first creates a blank toggle button, and the second, a
1978 button with a label widget already packed into it.
1979
1980 To retrieve the state of the toggle widget, including radio and check
1981 buttons, we use a GTK macro as shown in our example below. This tests
1982 the state of the toggle in a callback. The signal of interest emitted
1983 to us by toggle buttons (the toggle button, check button, and radio
1984 button widgets), is the "toggled" signal. To check the state of these
1985 buttons, set up a signal handler to catch the toggled signal, and use
1986 the macro to determine its state. The callback will look something
1987 like:
1988
1989 <tscreen><verb>
1990 void toggle_button_callback (GtkWidget *widget, gpointer data)
1991 {
1992     if (GTK_TOGGLE_BUTTON (widget)->active) 
1993     {
1994         /* If control reaches here, the toggle button is down */
1995     
1996     } else {
1997     
1998         /* If control reaches here, the toggle button is up */
1999     }
2000 }
2001 </verb></tscreen>
2002
2003 <tscreen><verb>
2004 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2005                                   gint             state );
2006 </verb></tscreen>
2007
2008 The above call can be used to set the state of the toggle button, and
2009 its children the radio and check buttons. Passing in your created
2010 button as the first argument, and a TRUE or FALSE for the second state
2011 argument to specify whether it should be down (depressed) or up
2012 (released). Default is up, or FALSE.
2013
2014 Note that when you use the gtk_toggle_button_set_active() function, and
2015 the state is actually changed, it causes the "clicked" signal to be
2016 emitted from the button.
2017
2018 <tscreen><verb>
2019 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2020 </verb></tscreen>
2021
2022 This simply toggles the button, and emits the "toggled" signal.
2023
2024 <!-- ----------------------------------------------------------------- -->
2025 <sect1> Check Buttons
2026 <p>
2027 Check buttons inherent many properties and functions from the the
2028 toggle buttons above, but look a little different. Rather than being
2029 buttons with text inside them, they are small squares with the text to
2030 the right of them. These are often used for toggling options on and
2031 off in applications.
2032
2033 The two creation functions are similar to those of the normal button.
2034
2035 <tscreen><verb>
2036 GtkWidget *gtk_check_button_new( void );
2037
2038 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2039 </verb></tscreen>
2040
2041 The new_with_label function creates a check button with a label beside
2042 it.
2043
2044 Checking the state of the check button is identical to that of the
2045 toggle button.
2046
2047 <!-- ----------------------------------------------------------------- -->
2048 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2049 <p>
2050 Radio buttons are similar to check buttons except they are grouped so
2051 that only one may be selected/depressed at a time. This is good for
2052 places in your application where you need to select from a short list
2053 of options.
2054
2055 Creating a new radio button is done with one of these calls:
2056
2057 <tscreen><verb>
2058 GtkWidget *gtk_radio_button_new( GSList *group );
2059
2060 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2061                                             gchar  *label );
2062 </verb></tscreen>
2063
2064 You'll notice the extra argument to these calls. They require a group
2065 to perform their duty properly. The first call to
2066 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2067 should pass NULL as the first argument. Then create a group using:
2068
2069 <tscreen><verb>
2070 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2071 </verb></tscreen>
2072
2073 The important thing to remember is that gtk_radio_button_group must be
2074 called for each new button added to the group, with the previous
2075 button passed in as an argument. The result is then passed into the
2076 call to gtk_radio_button_new or gtk_radio_button_new_with_label. This
2077 allows a chain of buttons to be established. The example below should
2078 make this clear.
2079
2080 You can shorten this slightly by using the following syntax, which
2081 removes the need for a variable to hold the list of buttons. This form
2082 is used in the example to create the third button:
2083
2084 <tscreen><verb>
2085      button2 = gtk_radio_button_new_with_label(
2086                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2087                  "button2");
2088 </verb></tscreen>
2089
2090 It is also a good idea to explicitly set which button should be the
2091 default depressed button with:
2092
2093 <tscreen><verb>
2094 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2095                                   gint             state );
2096 </verb></tscreen>
2097
2098 This is described in the section on toggle buttons, and works in
2099 exactly the same way.
2100
2101 The following example creates a radio button group with three buttons.
2102
2103 <tscreen><verb>
2104 /* example-start radiobuttons radiobuttons.c */
2105
2106 #include <gtk/gtk.h>
2107 #include <glib.h>
2108
2109 void close_application( GtkWidget *widget,
2110                         GdkEvent  *event,
2111                         gpointer   data )
2112 {
2113   gtk_main_quit();
2114 }
2115
2116 int main( int   argc,
2117           char *argv[] )
2118 {
2119     GtkWidget *window = NULL;
2120     GtkWidget *box1;
2121     GtkWidget *box2;
2122     GtkWidget *button;
2123     GtkWidget *separator;
2124     GSList *group;
2125   
2126     gtk_init(&amp;argc,&amp;argv);    
2127       
2128     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2129   
2130     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2131                         GTK_SIGNAL_FUNC(close_application),
2132                         NULL);
2133
2134     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2135     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2136
2137     box1 = gtk_vbox_new (FALSE, 0);
2138     gtk_container_add (GTK_CONTAINER (window), box1);
2139     gtk_widget_show (box1);
2140
2141     box2 = gtk_vbox_new (FALSE, 10);
2142     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2143     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2144     gtk_widget_show (box2);
2145
2146     button = gtk_radio_button_new_with_label (NULL, "button1");
2147     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2148     gtk_widget_show (button);
2149
2150     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2151     button = gtk_radio_button_new_with_label(group, "button2");
2152     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2153     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2154     gtk_widget_show (button);
2155
2156     button = gtk_radio_button_new_with_label(
2157                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2158                  "button3");
2159     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2160     gtk_widget_show (button);
2161
2162     separator = gtk_hseparator_new ();
2163     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2164     gtk_widget_show (separator);
2165
2166     box2 = gtk_vbox_new (FALSE, 10);
2167     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2168     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2169     gtk_widget_show (box2);
2170
2171     button = gtk_button_new_with_label ("close");
2172     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2173                                GTK_SIGNAL_FUNC(close_application),
2174                                GTK_OBJECT (window));
2175     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2176     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2177     gtk_widget_grab_default (button);
2178     gtk_widget_show (button);
2179     gtk_widget_show (window);
2180      
2181     gtk_main();
2182
2183     return(0);
2184 }
2185 /* example-end */
2186 </verb></tscreen>
2187
2188 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2189
2190 <!-- ***************************************************************** -->
2191 <sect> Adjustments <label id="sec_Adjustment">
2192 <!-- ***************************************************************** -->
2193 <p>
2194 GTK+ has various widgets that can be visually adjusted by the user
2195 using the mouse or the keyboard, such as the range widgets, described
2196 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2197 section. There are also a few widgets that display some adjustable
2198 portion of a larger area of data, such as the text widget and the
2199 viewport widget.
2200
2201 Obviously, an application needs to be able to react to changes the
2202 user makes in range widgets. One way to do this would be to have each
2203 widget emit its own type of signal when its adjustment changes, and
2204 either pass the new value to the signal handler, or require it to look
2205 inside the widget's data structure in order to ascertain the value.
2206 But you may also want to connect the adjustments of several widgets
2207 together, so that adjusting one adjusts the others. The most obvious
2208 example of this is connecting a scrollbar to a panning viewport or a
2209 scrolling text area. If each widget has its own way of setting or
2210 getting the adjustment value, then the programmer may have to write
2211 their own signal handlers to translate between the output of one
2212 widget's signal and the "input" of another's adjustment setting
2213 function.
2214
2215 GTK+ solves this problem using the GtkAdjustment object, which is a
2216 way for widgets to store and pass adjustment information in an
2217 abstract and flexible form. The most obvious use of GtkAdjustment is
2218 to store the configuration parameters and values of range widgets,
2219 such as scrollbars and scale controls. However, since GtkAdjustments
2220 are derived from GtkObject, they have some special powers beyond those
2221 of normal data structures. Most importantly, they can emit signals,
2222 just like widgets, and these signals can be used not only to allow
2223 your program to react to user input on adjustable widgets, but also to
2224 propagate adjustment values transparently between adjustable widgets.
2225
2226 <sect1> Creating an Adjustment
2227 <p>
2228 You create an adjustment using:
2229
2230 <tscreen><verb>
2231 GtkObject *gtk_adjustment_new( gfloat value,
2232                                gfloat lower,
2233                                gfloat upper,
2234                                gfloat step_increment,
2235                                gfloat page_increment,
2236                                gfloat page_size );
2237 </verb></tscreen>
2238
2239 The <tt/value/ argument is the initial value you want to give to the
2240 adjustment, usually corresponding to the topmost or leftmost position
2241 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2242 value which the adjustment can hold. The <tt/step_increment/ argument
2243 specifies the "smaller" of the two increments by which the user can
2244 change the value, while the <tt/page_increment/ is the "larger" one.
2245 The <tt/page_size/ argument usually corresponds somehow to the visible
2246 area of a panning widget. The <tt/upper/ argument is used to represent
2247 the bottom most or right most coordinate in a panning widget's
2248 child. Therefore it is <em/not/ always the largest number that
2249 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2250 usually non-zero.
2251
2252 <!-- ----------------------------------------------------------------- -->
2253 <sect1> Using Adjustments the Easy Way
2254 <p>
2255 The adjustable widgets can be roughly divided into those which use and
2256 require specific units for these values and those which treat them as
2257 arbitrary numbers. The group which treats the values as arbitrary
2258 numbers includes the range widgets (scrollbars and scales, the
2259 progress bar widget, and the spin button widget). These widgets are
2260 all the widgets which are typically "adjusted" directly by the user
2261 with the mouse or keyboard. They will treat the <tt/lower/ and
2262 <tt/upper/ values of an adjustment as a range within which the user
2263 can manipulate the adjustment's <tt/value/. By default, they will only
2264 modify the <tt/value/ of an adjustment.
2265
2266 The other group includes the text widget, the viewport widget, the
2267 compound list widget, and the scrolled window widget. All of these
2268 widgets use pixel values for their adjustments. These are also all
2269 widgets which are typically "adjusted" indirectly using scrollbars.
2270 While all widgets which use adjustments can either create their own
2271 adjustments or use ones you supply, you'll generally want to let this
2272 particular category of widgets create its own adjustments. Usually,
2273 they will eventually override all the values except the <tt/value/
2274 itself in whatever adjustments you give them, but the results are, in
2275 general, undefined (meaning, you'll have to read the source code to
2276 find out, and it may be different from widget to widget).
2277
2278 Now, you're probably thinking, since text widgets and viewports insist
2279 on setting everything except the <tt/value/ of their adjustments,
2280 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2281 you <em/share/ an adjustment object between a scrollbar and a text
2282 widget, manipulating the scrollbar will automagically adjust the text
2283 widget?  Of course it will! Just like this:
2284
2285 <tscreen><verb>
2286   /* creates its own adjustments */
2287   text = gtk_text_new (NULL, NULL);
2288   /* uses the newly-created adjustment for the scrollbar as well */
2289   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2290 </verb></tscreen>
2291
2292 </sect1>
2293 <!-- ----------------------------------------------------------------- -->
2294 <sect1> Adjustment Internals
2295 <p>
2296 Ok, you say, that's nice, but what if I want to create my own handlers
2297 to respond when the user adjusts a range widget or a spin button, and
2298 how do I get at the value of the adjustment in these handlers?  To
2299 answer these questions and more, let's start by taking a look at
2300 <tt>struct _GtkAdjustment</tt> itself:
2301
2302 <tscreen><verb>
2303 struct _GtkAdjustment
2304 {
2305   GtkData data;
2306   
2307   gfloat lower;
2308   gfloat upper;
2309   gfloat value;
2310   gfloat step_increment;
2311   gfloat page_increment;
2312   gfloat page_size;
2313 };     
2314 </verb></tscreen>
2315
2316 The first thing you should know is that there aren't any handy-dandy
2317 macros or accessor functions for getting the <tt/value/ out of a
2318 GtkAdjustment, so you'll have to (horror of horrors) do it like a
2319 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2320 (Object)</tt> macro does run-time type checking (as do all the GTK+
2321 type-casting macros, actually).
2322
2323 Since, when you set the <tt/value/ of an adjustment, you generally
2324 want the change to be reflected by every widget that uses this
2325 adjustment, GTK+ provides this convenience function to do this:
2326
2327 <tscreen><verb>
2328 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2329                                gfloat         value );
2330 </verb></tscreen>
2331
2332 As mentioned earlier, GtkAdjustment is a subclass of GtkObject just
2333 like all the various widgets, and thus it is able to emit signals.
2334 This is, of course, why updates happen automagically when you share an
2335 adjustment object between a scrollbar and another adjustable widget;
2336 all adjustable widgets connect signal handlers to their adjustment's
2337 <tt/value_changed/ signal, as can your program. Here's the definition
2338 of this signal in <tt/struct _GtkAdjustmentClass/:
2339
2340 <tscreen><verb>
2341   void (* value_changed) (GtkAdjustment *adjustment);
2342 </verb></tscreen>
2343
2344 The various widgets that use the GtkAdjustment object will emit this
2345 signal on an adjustment whenever they change its value. This happens
2346 both when user input causes the slider to move on a range widget, as
2347 well as when the program explicitly changes the value with
2348 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2349 widget, and you want to change the rotation of a picture whenever its
2350 value changes, you would create a callback like this:
2351
2352 <tscreen><verb>
2353 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2354 {
2355   set_picture_rotation (picture, adj->value);
2356 ...
2357 </verb></tscreen>
2358
2359 and connect it to the scale widget's adjustment like this:
2360
2361 <tscreen><verb>
2362 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2363                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2364 </verb></tscreen>
2365
2366 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2367 fields of its adjustment, such as when a user adds more text to a text
2368 widget?  In this case, it emits the <tt/changed/ signal, which looks
2369 like this:
2370
2371 <tscreen><verb>
2372   void (* changed)       (GtkAdjustment *adjustment);
2373 </verb></tscreen>
2374
2375 Range widgets typically connect a handler to this signal, which
2376 changes their appearance to reflect the change - for example, the size
2377 of the slider in a scrollbar will grow or shrink in inverse proportion
2378 to the difference between the <tt/lower/ and <tt/upper/ values of its
2379 adjustment.
2380
2381 You probably won't ever need to attach a handler to this signal,
2382 unless you're writing a new type of range widget.  However, if you
2383 change any of the values in a GtkAdjustment directly, you should emit
2384 this signal on it to reconfigure whatever widgets are using it, like
2385 this:
2386
2387 <tscreen><verb>
2388 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2389 </verb></tscreen>
2390
2391 Now go forth and adjust!
2392 </sect1>
2393 </sect>
2394
2395 <!-- ***************************************************************** -->
2396 <sect> Range Widgets<label id="sec_Range_Widgets">
2397 <!-- ***************************************************************** -->
2398
2399 <p>
2400 The category of range widgets includes the ubiquitous scrollbar widget
2401 and the less common "scale" widget. Though these two types of widgets
2402 are generally used for different purposes, they are quite similar in
2403 function and implementation. All range widgets share a set of common
2404 graphic elements, each of which has its own X window and receives
2405 events. They all contain a "trough" and a "slider" (what is sometimes
2406 called a "thumbwheel" in other GUI environments). Dragging the slider
2407 with the pointer moves it back and forth within the trough, while
2408 clicking in the trough advances the slider towards the location of the
2409 click, either completely, or by a designated amount, depending on
2410 which mouse button is used.
2411
2412 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2413 all range widgets are associated with an adjustment object, from which
2414 they calculate the length of the slider and it's position within the
2415 trough. When the user manipulates the slider, the range widget will
2416 change the value of the adjustment.
2417
2418 <!-- ----------------------------------------------------------------- -->
2419 <sect1> Scrollbar Widgets
2420 <p>
2421 These are your standard, run-of-the-mill scrollbars. These should be
2422 used only for scrolling some other widget, such as a list, a text box,
2423 or a viewport (and it's generally easier to use the scrolled window
2424 widget in most cases).  For other purposes, you should use scale
2425 widgets, as they are friendlier and more featureful.
2426
2427 There are separate types for horizontal and vertical scrollbars.
2428 There really isn't much to say about these. You create them with the
2429 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2430 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2431
2432 <tscreen><verb>
2433 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2434
2435 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2436 </verb></tscreen>
2437
2438 and that's about it (if you don't believe me, look in the header
2439 files!).  The <tt/adjustment/ argument can either be a pointer to an
2440 existing GtkAdjustment, or NULL, in which case one will be created for
2441 you. Specifying NULL might actually be useful in this case, if you
2442 wish to pass the newly-created adjustment to the constructor function
2443 of some other widget which will configure it for you, such as a text
2444 widget.
2445 </sect1>
2446
2447 <!-- ----------------------------------------------------------------- -->
2448 <sect1> Scale Widgets
2449 <p>
2450 Scale widgets are used to allow the user to visually select and
2451 manipulate a value within a specific range. You might want to use a
2452 scale widget, for example, to adjust the magnification level on a
2453 zoomed preview of a picture, or to control the brightness of a colour,
2454 or to specify the number of minutes of inactivity before a screensaver
2455 takes over the screen.
2456
2457 <!-- ----------------------------------------------------------------- -->
2458 <sect2>Creating a Scale Widget
2459 <p>
2460 As with scrollbars, there are separate widget types for horizontal and
2461 vertical scale widgets. (Most programmers seem to favour horizontal
2462 scale widgets). Since they work essentially the same way, there's no
2463 need to treat them separately here. The following functions, defined
2464 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2465 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2466 widgets, respectively:
2467
2468 <tscreen>
2469 <verb>
2470 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2471
2472 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2473 </verb>
2474 </tscreen>
2475
2476 The <tt/adjustment/ argument can either be an adjustment which has
2477 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2478 which case, an anonymous GtkAdjustment is created with all of its
2479 values set to <tt/0.0/ (which isn't very useful in this case). In
2480 order to avoid confusing yourself, you probably want to create your
2481 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2482 value actually corresponds to the highest value the user can select.
2483 (If you're <em/already/ thoroughly confused, read the section on <ref
2484 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2485 what exactly adjustments do and how to create and manipulate them).
2486
2487 <!-- ----------------------------------------------------------------- -->
2488 <sect2> Functions and Signals (well, functions, at least)
2489 <p>
2490 Scale widgets can display their current value as a number beside the
2491 trough. The default behaviour is to show the value, but you can change
2492 this with this function:
2493
2494 <tscreen><verb>
2495 void gtk_scale_set_draw_value( GtkScale *scale,
2496                                gint      draw_value );
2497 </verb></tscreen>
2498
2499 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2500 <tt/FALSE/, with predictable consequences for either one.
2501
2502 The value displayed by a scale widget is rounded to one decimal point
2503 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2504 change this with:
2505
2506 <tscreen>
2507 <verb>
2508 void gtk_scale_set_digits( GtkScale *scale,
2509                             gint     digits );
2510 </verb>
2511 </tscreen>
2512
2513 where <tt/digits/ is the number of decimal places you want. You can
2514 set <tt/digits/ to anything you like, but no more than 13 decimal
2515 places will actually be drawn on screen.
2516
2517 Finally, the value can be drawn in different positions
2518 relative to the trough:
2519
2520 <tscreen>
2521 <verb>
2522 void gtk_scale_set_value_pos( GtkScale        *scale,
2523                               GtkPositionType  pos );
2524 </verb>
2525 </tscreen>
2526
2527 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2528 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2529 following values:
2530
2531 <itemize>
2532 <item> GTK_POS_LEFT
2533 <item> GTK_POS_RIGHT
2534 <item> GTK_POS_TOP
2535 <item> GTK_POS_BOTTOM
2536 </itemize>
2537
2538 If you position the value on the "side" of the trough (e.g. on the top
2539 or bottom of a horizontal scale widget), then it will follow the
2540 slider up and down the trough.
2541
2542 All the preceding functions are defined in
2543 <tt>&lt;gtk/gtkscale.h&gt;</tt>.
2544 </sect2>
2545 </sect1>
2546
2547 <!-- ----------------------------------------------------------------- -->
2548 <sect1> Common Functions <label id="sec_Range_Functions">
2549 <p>
2550 The GtkRange widget class is fairly complicated internally, but, like
2551 all the "base class" widgets, most of its complexity is only
2552 interesting if you want to hack on it. Also, almost all of the
2553 functions and signals it defines are only really used in writing
2554 derived widgets. There are, however, a few useful functions that are
2555 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2556 widgets.
2557
2558 <!-- ----------------------------------------------------------------- -->
2559 <sect2> Setting the Update Policy
2560 <p>
2561 The "update policy" of a range widget defines at what points during
2562 user interaction it will change the <tt/value/ field of its
2563 GtkAdjustment and emit the "value_changed" signal on this
2564 GtkAdjustment. The update policies, defined in
2565 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2566 are:
2567
2568 <itemize>
2569 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2570 "value_changed" signal is emitted continuously, i.e. whenever the
2571 slider is moved by even the tiniest amount.
2572 </item>
2573 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2574 only emitted once the slider has stopped moving and the user has
2575 released the mouse button.
2576 </item>
2577 <item>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emitted
2578 when the user releases the mouse button, or if the slider stops moving
2579 for a short period of time.
2580 </item>
2581 </itemize>
2582
2583 The update policy of a range widget can be set by casting it using the
2584 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2585
2586 <tscreen><verb>
2587 void gtk_range_set_update_policy( GtkRange      *range,
2588                                   GtkUpdateType  policy) ;
2589 </verb></tscreen>
2590
2591 <!-- ----------------------------------------------------------------- -->
2592 <sect2>Getting and Setting Adjustments
2593 <p>
2594 Getting and setting the adjustment for a range widget "on the fly" is
2595 done, predictably, with:
2596
2597 <tscreen><verb>
2598 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2599
2600 void gtk_range_set_adjustment( GtkRange      *range,
2601                                GtkAdjustment *adjustment );
2602 </verb></tscreen>
2603
2604 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2605 which <tt/range/ is connected.
2606
2607 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2608 the adjustment that <tt/range/ is already using, regardless of whether
2609 you changed any of its fields or not. If you pass it a new
2610 GtkAdjustment, it will unreference the old one if it exists (possibly
2611 destroying it), connect the appropriate signals to the new one, and
2612 call the private function <tt/gtk_range_adjustment_changed()/, which
2613 will (or at least, is supposed to...) recalculate the size and/or
2614 position of the slider and redraw if necessary. As mentioned in the
2615 section on adjustments, if you wish to reuse the same GtkAdjustment,
2616 when you modify its values directly, you should emit the "changed"
2617 signal on it, like this:
2618
2619 <tscreen><verb>
2620 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2621 </verb></tscreen>
2622 </sect2>
2623 </sect1>
2624
2625 <!-- ----------------------------------------------------------------- -->
2626 <sect1> Key and Mouse bindings
2627 <p>
2628 All of the GTK+ range widgets react to mouse clicks in more or less
2629 the same way. Clicking button-1 in the trough will cause its
2630 adjustment's <tt/page_increment/ to be added or subtracted from its
2631 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2632 button-2 in the trough will jump the slider to the point at which the
2633 button was clicked. Clicking any button on a scrollbar's arrows will
2634 cause its adjustment's value to change <tt/step_increment/ at a time.
2635
2636 It may take a little while to get used to, but by default, scrollbars
2637 as well as scale widgets can take the keyboard focus in GTK+. If you
2638 think your users will find this too confusing, you can always disable
2639 this by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:
2640
2641 <tscreen><verb>
2642 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2643 </verb></tscreen>
2644
2645 The key bindings (which are, of course, only active when the widget
2646 has focus) are slightly different between horizontal and vertical
2647 range widgets, for obvious reasons. They are also not quite the same
2648 for scale widgets as they are for scrollbars, for somewhat less
2649 obvious reasons (possibly to avoid confusion between the keys for
2650 horizontal and vertical scrollbars in scrolled windows, where both
2651 operate on the same area).
2652
2653 <sect2> Vertical Range Widgets
2654 <p>
2655 All vertical range widgets can be operated with the up and down arrow
2656 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2657 arrows move the slider up and down by <tt/step_increment/, while
2658 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2659
2660 The user can also move the slider all the way to one end or the other
2661 of the trough using the keyboard. With the GtkVScale widget, this is
2662 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2663 GtkVScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2664 and <tt>Control-Page Down</tt>.
2665
2666 <!-- ----------------------------------------------------------------- -->
2667 <sect2> Horizontal Range Widgets
2668 <p>
2669 The left and right arrow keys work as you might expect in these
2670 widgets, moving the slider back and forth by <tt/step_increment/. The
2671 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2672 For the GtkHScale widget, moving the slider by <tt/page_increment/ is
2673 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2674 while for GtkHScrollbar, it's done with <tt>Control-Home</tt> and
2675 <tt>Control-End</tt>.
2676 </sect2>
2677 </sect1>
2678
2679 <!-- ----------------------------------------------------------------- -->
2680 <sect1> Example<label id="sec_Range_Example">
2681 <p>
2682 This example is a somewhat modified version of the "range controls"
2683 test from <tt/testgtk.c/. It basically puts up a window with three
2684 range widgets all connected to the same adjustment, and a couple of
2685 controls for adjusting some of the parameters mentioned above and in
2686 the seciton on adjustments, so you can see how they affect the way
2687 these widgets work for the user.
2688
2689 <tscreen><verb>
2690 /* example-start rangewidgets rangewidgets.c */
2691
2692 #include <gtk/gtk.h>
2693
2694 GtkWidget *hscale, *vscale;
2695
2696 void cb_pos_menu_select( GtkWidget       *item,
2697                          GtkPositionType  pos )
2698 {
2699     /* Set the value position on both scale widgets */
2700     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2701     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2702 }
2703
2704 void cb_update_menu_select( GtkWidget     *item,
2705                             GtkUpdateType  policy )
2706 {
2707     /* Set the update policy for both scale widgets */
2708     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2709     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2710 }
2711
2712 void cb_digits_scale( GtkAdjustment *adj )
2713 {
2714     /* Set the number of decimal places to which adj->value is rounded */
2715     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2716     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2717 }
2718
2719 void cb_page_size( GtkAdjustment *get,
2720                    GtkAdjustment *set )
2721 {
2722     /* Set the page size and page increment size of the sample
2723      * adjustment to the value specified by the "Page Size" scale */
2724     set->page_size = get->value;
2725     set->page_increment = get->value;
2726     /* Now emit the "changed" signal to reconfigure all the widgets that
2727      * are attached to this adjustment */
2728     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2729 }
2730
2731 void cb_draw_value( GtkToggleButton *button )
2732 {
2733     /* Turn the value display on the scale widgets off or on depending
2734      *  on the state of the checkbutton */
2735     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2736     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2737 }
2738
2739 /* Convenience functions */
2740
2741 GtkWidget *make_menu_item( gchar         *name,
2742                            GtkSignalFunc  callback,
2743                            gpointer       data )
2744 {
2745     GtkWidget *item;
2746   
2747     item = gtk_menu_item_new_with_label (name);
2748     gtk_signal_connect (GTK_OBJECT (item), "activate",
2749                         callback, data);
2750     gtk_widget_show (item);
2751
2752     return(item);
2753 }
2754
2755 void scale_set_default_values( GtkScale *scale )
2756 {
2757     gtk_range_set_update_policy (GTK_RANGE (scale),
2758                                  GTK_UPDATE_CONTINUOUS);
2759     gtk_scale_set_digits (scale, 1);
2760     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2761     gtk_scale_set_draw_value (scale, TRUE);
2762 }
2763
2764 /* makes the sample window */
2765
2766 void create_range_controls( void )
2767 {
2768     GtkWidget *window;
2769     GtkWidget *box1, *box2, *box3;
2770     GtkWidget *button;
2771     GtkWidget *scrollbar;
2772     GtkWidget *separator;
2773     GtkWidget *opt, *menu, *item;
2774     GtkWidget *label;
2775     GtkWidget *scale;
2776     GtkObject *adj1, *adj2;
2777
2778     /* Standard window-creating stuff */
2779     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2780     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2781                         GTK_SIGNAL_FUNC(gtk_main_quit),
2782                         NULL);
2783     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2784
2785     box1 = gtk_vbox_new (FALSE, 0);
2786     gtk_container_add (GTK_CONTAINER (window), box1);
2787     gtk_widget_show (box1);
2788
2789     box2 = gtk_hbox_new (FALSE, 10);
2790     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2791     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2792     gtk_widget_show (box2);
2793
2794     /* calue, lower, upper, step_increment, page_increment, page_size */
2795     /* Note that the page_size value only makes a difference for
2796      * scrollbar widgets, and the highest value you'll get is actually
2797      * (upper - page_size). */
2798     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2799   
2800     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2801     scale_set_default_values (GTK_SCALE (vscale));
2802     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2803     gtk_widget_show (vscale);
2804
2805     box3 = gtk_vbox_new (FALSE, 10);
2806     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2807     gtk_widget_show (box3);
2808
2809     /* Reuse the same adjustment */
2810     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2811     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2812     scale_set_default_values (GTK_SCALE (hscale));
2813     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2814     gtk_widget_show (hscale);
2815
2816     /* Reuse the same adjustment again */
2817     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2818     /* Notice how this causes the scales to always be updated
2819      * continuously when the scrollbar is moved */
2820     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2821                                  GTK_UPDATE_CONTINUOUS);
2822     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2823     gtk_widget_show (scrollbar);
2824
2825     box2 = gtk_hbox_new (FALSE, 10);
2826     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2827     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2828     gtk_widget_show (box2);
2829
2830     /* A checkbutton to control whether the value is displayed or not */
2831     button = gtk_check_button_new_with_label("Display value on scale widgets");
2832     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2833     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2834                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2835     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2836     gtk_widget_show (button);
2837   
2838     box2 = gtk_hbox_new (FALSE, 10);
2839     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2840
2841     /* An option menu to change the position of the value */
2842     label = gtk_label_new ("Scale Value Position:");
2843     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2844     gtk_widget_show (label);
2845   
2846     opt = gtk_option_menu_new();
2847     menu = gtk_menu_new();
2848
2849     item = make_menu_item ("Top",
2850                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2851                            GINT_TO_POINTER (GTK_POS_TOP));
2852     gtk_menu_append (GTK_MENU (menu), item);
2853   
2854     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2855                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2856     gtk_menu_append (GTK_MENU (menu), item);
2857   
2858     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2859                            GINT_TO_POINTER (GTK_POS_LEFT));
2860     gtk_menu_append (GTK_MENU (menu), item);
2861   
2862     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2863                             GINT_TO_POINTER (GTK_POS_RIGHT));
2864     gtk_menu_append (GTK_MENU (menu), item);
2865   
2866     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2867     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2868     gtk_widget_show (opt);
2869
2870     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2871     gtk_widget_show (box2);
2872
2873     box2 = gtk_hbox_new (FALSE, 10);
2874     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2875
2876     /* Yet another option menu, this time for the update policy of the
2877      * scale widgets */
2878     label = gtk_label_new ("Scale Update Policy:");
2879     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2880     gtk_widget_show (label);
2881   
2882     opt = gtk_option_menu_new();
2883     menu = gtk_menu_new();
2884   
2885     item = make_menu_item ("Continuous",
2886                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2887                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2888     gtk_menu_append (GTK_MENU (menu), item);
2889   
2890     item = make_menu_item ("Discontinuous",
2891                             GTK_SIGNAL_FUNC (cb_update_menu_select),
2892                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2893     gtk_menu_append (GTK_MENU (menu), item);
2894   
2895     item = make_menu_item ("Delayed",
2896                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2897                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2898     gtk_menu_append (GTK_MENU (menu), item);
2899   
2900     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2901     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2902     gtk_widget_show (opt);
2903   
2904     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2905     gtk_widget_show (box2);
2906
2907     box2 = gtk_hbox_new (FALSE, 10);
2908     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2909   
2910     /* A GtkHScale widget for adjusting the number of digits on the
2911      * sample scales. */
2912     label = gtk_label_new ("Scale Digits:");
2913     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2914     gtk_widget_show (label);
2915
2916     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
2917     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2918                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
2919     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2920     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2921     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2922     gtk_widget_show (scale);
2923
2924     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2925     gtk_widget_show (box2);
2926   
2927     box2 = gtk_hbox_new (FALSE, 10);
2928     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2929   
2930     /* And, one last GtkHScale widget for adjusting the page size of the
2931      * scrollbar. */
2932     label = gtk_label_new ("Scrollbar Page Size:");
2933     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2934     gtk_widget_show (label);
2935
2936     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
2937     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2938                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
2939     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2940     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2941     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2942     gtk_widget_show (scale);
2943
2944     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2945     gtk_widget_show (box2);
2946
2947     separator = gtk_hseparator_new ();
2948     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2949     gtk_widget_show (separator);
2950
2951     box2 = gtk_vbox_new (FALSE, 10);
2952     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2953     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2954     gtk_widget_show (box2);
2955
2956     button = gtk_button_new_with_label ("Quit");
2957     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2958                                GTK_SIGNAL_FUNC(gtk_main_quit),
2959                                NULL);
2960     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2961     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2962     gtk_widget_grab_default (button);
2963     gtk_widget_show (button);
2964
2965     gtk_widget_show (window);
2966 }
2967
2968 int main( int   argc,
2969           char *argv[] )
2970 {
2971     gtk_init(&amp;argc, &amp;argv);
2972
2973     create_range_controls();
2974
2975     gtk_main();
2976
2977     return(0);
2978 }
2979
2980 /* example-end */
2981 </verb></tscreen>
2982 </sect1>
2983 </sect>
2984
2985 <!-- ***************************************************************** -->
2986 <sect> Miscellaneous Widgets
2987 <!-- ***************************************************************** -->
2988
2989 <!-- ----------------------------------------------------------------- -->
2990 <sect1> Labels
2991 <p>
2992 Labels are used a lot in GTK, and are relatively simple. Labels emit
2993 no signals as they do not have an associated X window. If you need to
2994 catch signals, or do clipping, use the <ref id="sec_EventBox"
2995 name="EventBox"> widget.
2996
2997 To create a new label, use:
2998
2999 <tscreen><verb>
3000 GtkWidget *gtk_label_new( char *str );
3001 </verb></tscreen>
3002
3003 Where the sole argument is the string you wish the label to display.
3004
3005 To change the label's text after creation, use the function:
3006
3007 <tscreen><verb>
3008 void gtk_label_set_text( GtkLabel *label,
3009                          char     *str );
3010 </verb></tscreen>
3011
3012 Where the first argument is the label you created previously (cast
3013 using the GTK_LABEL() macro), and the second is the new string.
3014
3015 The space needed for the new string will be automatically adjusted if
3016 needed.
3017
3018 To retrieve the current string, use:
3019
3020 <tscreen><verb>
3021 void gtk_label_get( GtkLabel  *label,
3022                     char     **str );
3023 </verb></tscreen>
3024
3025 Where the first argument is the label you've created, and the second,
3026 the return for the string.
3027
3028 <!-- ----------------------------------------------------------------- -->
3029 <sect1>The Tooltips Widget
3030 <p>
3031 These are the little text strings that pop up when you leave your
3032 pointer over a button or other widget for a few seconds. They are easy
3033 to use, so I will just explain them without giving an example. If you
3034 want to see some code, take a look at the testgtk.c program
3035 distributed with GTK.
3036
3037 Widgets that do not receieve events (widgets that do not have their
3038 own window) will not work with tooltips.
3039
3040 The first call you will use creates a new tooltip. You only need to do
3041 this once for a set of tooltips as the <tt/GtkTooltip/ object this
3042 function returns can be used to create multiple tooltips.
3043
3044 <tscreen><verb>
3045 GtkTooltips *gtk_tooltips_new( void );
3046 </verb></tscreen>
3047
3048 Once you have created a new tooltip, and the widget you wish to use it
3049 on, simply use this call to set it:
3050
3051 <tscreen><verb>
3052 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3053                            GtkWidget   *widget,
3054                            const gchar *tip_text,
3055                            const gchar *tip_private );
3056 </verb></tscreen>
3057
3058 The first argument is the tooltip you've already created, followed by
3059 the widget you wish to have this tooltip pop up for, and the text you
3060 wish it to say. The last argument is a text string that can be used as
3061 an identifier when using GtkTipsQuery to implement context sensitive
3062 help. For now, you can set it to NULL.
3063
3064 <!-- TODO: sort out what how to do the context sensitive help -->
3065
3066 Here's a short example:
3067
3068 <tscreen><verb>
3069 GtkTooltips *tooltips;
3070 GtkWidget *button;
3071 .
3072 .
3073 .
3074 tooltips = gtk_tooltips_new ();
3075 button = gtk_button_new_with_label ("button 1");
3076 .
3077 .
3078 .
3079 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3080 </verb></tscreen>
3081
3082 There are other calls that can be used with tooltips. I will just list
3083 them with a brief description of what they do.
3084
3085 <tscreen><verb>
3086 void gtk_tooltips_enable( GtkTooltips *tooltips );
3087 </verb></tscreen>
3088
3089 Enable a disabled set of tooltips.
3090
3091 <tscreen><verb>
3092 void gtk_tooltips_disable( GtkTooltips *tooltips );
3093 </verb></tscreen>
3094
3095 Disable an enabled set of tooltips.
3096
3097 <tscreen><verb>
3098 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3099                              gint         delay );
3100
3101 </verb></tscreen>
3102
3103 Sets how many milliseconds you have to hold your pointer over the
3104 widget before the tooltip will pop up. The default is 500
3105 milliseconds (half a second).
3106
3107 <tscreen><verb>
3108 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3109                               GdkColor    *background,
3110                               GdkColor    *foreground );
3111 </verb></tscreen>
3112
3113 Set the foreground and background color of the tooltips.
3114
3115 And that's all the functions associated with tooltips. More than
3116 you'll ever want to know :-)
3117
3118 <!-- ----------------------------------------------------------------- -->
3119 <sect1> Progress Bars
3120 <p>
3121 Progress bars are used to show the status of an operation. They are
3122 pretty easy to use, as you will see with the code below. But first
3123 lets start out with the calls to create a new progress bar.
3124
3125 There are two ways to create a progress bar, one simple one takes
3126 no arguments, and one that takes a GtkAdjustment object as an
3127 argument. If the former is used, the progress bar creates it's own
3128 adjustment object.
3129
3130 <tscreen><verb>
3131 GtkWidget *gtk_progress_bar_new( void );
3132
3133 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3134 </verb></tscreen>
3135
3136 The second method has the advantage that we can use the adjustment
3137 object to specify our own range parameters for the progress bar.
3138
3139 Now that the progress bar has been created we can use it.
3140
3141 <tscreen><verb>
3142 void gtk_progress_bar_update( GtkProgressBar *pbar,
3143                               gfloat          percentage );
3144 </verb></tscreen>
3145
3146 The first argument is the progress bar you wish to operate on, and the
3147 second argument is the amount 'completed', meaning the amount the
3148 progress bar has been filled from 0-100%. This is passed to the
3149 function as a real number ranging from 0 to 1.
3150
3151 GTK v1.1 has added new functionality to the progress bar that enables
3152 it to display it's value in different ways, and to inform the user of
3153 its current value and its range.
3154
3155 A progress bar may be set to one of a number of orientations using the
3156 function
3157
3158 <tscreen><verb>
3159 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3160                                        GtkProgressBarOrientation orientation );
3161 </verb></tscreen>
3162
3163 Where the <tt/orientation/ argument may take one of the following
3164 values to indicate the direction in which the progress bar moves:
3165
3166 <itemize>
3167 <item> GTK_PROGRESS_LEFT_TO_RIGHT
3168 <item> GTK_PROGRESS_RIGHT_TO_LEFT
3169 <item> GTK_PROGRESS_BOTTOM_TO_TOP
3170 <item> GTK_PROGRESS_TOP_TO_BOTTOM
3171 </itemize>
3172
3173 When used as a measure of how far a process has progressed, the
3174 GtkProgressBar can be set to display it's value in either a continuous
3175 or discrete mode. In continuous mode, the progress bar is updated for
3176 each value. In discrete mode, the progress bar is updated in a number
3177 of discrete blocks. The number of blocks is also configurable.
3178
3179 The style of a progress bar can be set using the following function.
3180
3181 <tscreen><verb>
3182 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3183                                      GtkProgressBarStyle  style );
3184 </verb></tscreen>
3185
3186 The <tt/style/ parameter can take one of two values:
3187
3188 <itemize>
3189 <item>GTK_PROGRESS_CONTINUOUS
3190 <item>GTK_PROGRESS_DISCRETE
3191 </itemize>
3192
3193 The number of discrete blocks can be set by calling
3194
3195 <tscreen><verb>
3196 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3197                                            guint           blocks );
3198 </verb></tscreen>
3199
3200 As well as indicating the amount of progress that has occured, the
3201 progress bar may be set to just indicate that there is some
3202 activity. This can be useful in situations where progress cannot be
3203 measured against a value range. Activity mode is not effected by the
3204 bar style that is described above, and overrides it.This mode is
3205 selected by the following function.
3206
3207 <tscreen><verb>
3208 void gtk_progress_set_activity_mode( GtkProgress *progress,
3209                                      guint        activity_mode );
3210 </verb></tscreen>
3211
3212 The step size of the activity indicator, and the number of blocks are
3213 set using the following functions.
3214
3215 <tscreen><verb>
3216 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3217                                          guint           step );
3218
3219 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3220                                            guint           blocks );
3221 </verb></tscreen>
3222
3223 When in continuous mode, the progress bar can also display a
3224 configurable text string within it's trough, using the following
3225 function.
3226
3227 <tscreen><verb>
3228 void gtk_progress_set_format_string( GtkProgress *progress,
3229                                      gchar       *format);
3230 </verb></tscreen>
3231
3232 The <tt/format/ argument is similiar to one that would be used in a C
3233 <tt/printf/ statement. The following directives may be used within the
3234 format string:
3235
3236 <itemize>
3237 <item> %p - percentage
3238 <item> %v - value
3239 <item> %l - lower range value
3240 <item> %u - upper range value
3241 </itemize>
3242  
3243 Progress Bars are usually used with timeouts or other such functions
3244 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3245 Functions">) to give the illusion of multitasking. All will employ the
3246 gtk_progress_bar_update function in the same manner.
3247
3248 Here is an example of the progress bar, updated using timeouts.  This
3249 code also shows you how to reset the Progress Bar.
3250
3251 <tscreen><verb>
3252 /* example-start progressbar progressbar.c */
3253
3254 #include <gtk/gtk.h>
3255
3256 typedef struct _ProgressData {
3257     GtkWidget *window;
3258     GtkWidget *pbar;
3259     int timer;
3260 } ProgressData;
3261
3262 /* Update the value of the progress bar so that we get
3263  * some movement */
3264 gint progress_timeout( gpointer data )
3265 {
3266     gfloat new_val;
3267     GtkAdjustment *adj;
3268
3269     adj = GTK_PROGRESS (data)->adjustment;
3270
3271     /* Calculate the value of the progress bar using the
3272      * value range set in the adjustment object */
3273     new_val = adj->value + 1;
3274     if (new_val > adj->upper)
3275       new_val = adj->lower;
3276
3277     /* Set the new value */
3278     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3279
3280     /* As this is a timeout function, return TRUE so that it
3281      * continues to get called */
3282     return(TRUE);
3283
3284
3285 /* Callback that toggles the text display within the progress
3286  * bar trough */
3287 void toggle_show_text( GtkWidget    *widget,
3288                        ProgressData *pdata )
3289 {
3290     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3291                                 GTK_TOGGLE_BUTTON (widget)->active);
3292 }
3293
3294 /* Callback that toggles the activity mode of the progress
3295  * bar */
3296 void toggle_activity_mode( GtkWidget    *widget,
3297                            ProgressData *pdata )
3298 {
3299     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3300                                     GTK_TOGGLE_BUTTON (widget)->active);
3301 }
3302
3303 /* Callback that toggles the continuous mode of the progress
3304  * bar */
3305 void set_continuous_mode( GtkWidget    *widget,
3306                           ProgressData *pdata )
3307 {
3308     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3309                                     GTK_PROGRESS_CONTINUOUS);
3310 }
3311
3312 /* Callback that toggles the discrete mode of the progress
3313  * bar */
3314 void set_discrete_mode( GtkWidget    *widget,
3315                         ProgressData *pdata )
3316 {
3317     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3318                                     GTK_PROGRESS_DISCRETE);
3319 }
3320  
3321 /* Clean up allocated memory and remove the timer */
3322 void destroy_progress( GtkWidget     *widget,
3323                        ProgressData *pdata)
3324 {
3325     gtk_timeout_remove (pdata->timer);
3326     pdata->timer = 0;
3327     pdata->window = NULL;
3328     g_free(pdata);
3329     gtk_main_quit();
3330 }
3331
3332 int main( int   argc,
3333           char *argv[])
3334 {
3335     ProgressData *pdata;
3336     GtkWidget *align;
3337     GtkWidget *separator;
3338     GtkWidget *table;
3339     GtkAdjustment *adj;
3340     GtkWidget *button;
3341     GtkWidget *check;
3342     GtkWidget *vbox;
3343
3344     gtk_init (&amp;argc, &amp;argv);
3345
3346     /* Allocate memory for the data that is passwd to the callbacks */
3347     pdata = g_malloc( sizeof(ProgressData) );
3348   
3349     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3350     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3351
3352     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3353                         GTK_SIGNAL_FUNC (destroy_progress),
3354                         pdata);
3355     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3356     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3357
3358     vbox = gtk_vbox_new (FALSE, 5);
3359     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3360     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3361     gtk_widget_show(vbox);
3362   
3363     /* Create a centering alignment object */
3364     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3365     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3366     gtk_widget_show(align);
3367
3368     /* Create a GtkAdjusment object to hold the range of the
3369      * progress bar */
3370     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3371
3372     /* Create the GtkProgressBar using the adjustment */
3373     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3374
3375     /* Set the format of the string that can be displayed in the
3376      * trough of the progress bar:
3377      * %p - percentage
3378      * %v - value
3379      * %l - lower range value
3380      * %u - upper range value */
3381     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3382                                     "%v from [%l-%u] (=%p%%)");
3383     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3384     gtk_widget_show(pdata->pbar);
3385
3386     /* Add a timer callback to update the value of the progress bar */
3387     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3388
3389     separator = gtk_hseparator_new ();
3390     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3391     gtk_widget_show(separator);
3392
3393     /* rows, columns, homogeneous */
3394     table = gtk_table_new (2, 3, FALSE);
3395     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3396     gtk_widget_show(table);
3397
3398     /* Add a check button to select displaying of the trough text */
3399     check = gtk_check_button_new_with_label ("Show text");
3400     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3401                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3402                       5, 5);
3403     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3404                         GTK_SIGNAL_FUNC (toggle_show_text),
3405                         pdata);
3406     gtk_widget_show(check);
3407
3408     /* Add a check button to toggle activity mode */
3409     check = gtk_check_button_new_with_label ("Activity mode");
3410     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3411                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3412                       5, 5);
3413     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3414                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3415                         pdata);
3416     gtk_widget_show(check);
3417
3418     separator = gtk_vseparator_new ();
3419     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3420                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3421                       5, 5);
3422     gtk_widget_show(separator);
3423
3424     /* Add a radio button to select continuous display mode */
3425     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3426     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3427                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3428                       5, 5);
3429     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3430                         GTK_SIGNAL_FUNC (set_continuous_mode),
3431                         pdata);
3432     gtk_widget_show (button);
3433
3434     /* Add a radio button to select discrete display mode */
3435     button = gtk_radio_button_new_with_label(
3436                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3437                "Discrete");
3438     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3439                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3440                       5, 5);
3441     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3442                         GTK_SIGNAL_FUNC (set_discrete_mode),
3443                         pdata);
3444     gtk_widget_show (button);
3445
3446     separator = gtk_hseparator_new ();
3447     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3448     gtk_widget_show(separator);
3449
3450     /* Add a button to exit the program */
3451     button = gtk_button_new_with_label ("close");
3452     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3453                                (GtkSignalFunc) gtk_widget_destroy,
3454                                GTK_OBJECT (pdata->window));
3455     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3456
3457     /* This makes it so the button is the default. */
3458     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3459
3460     /* This grabs this button to be the default button. Simply hitting
3461      * the "Enter" key will cause this button to activate. */
3462     gtk_widget_grab_default (button);
3463     gtk_widget_show(button);
3464
3465     gtk_widget_show (pdata->window);
3466
3467     gtk_main ();
3468     
3469     return(0);
3470 }
3471 /* example-end */
3472 </verb></tscreen>
3473
3474 <!-- ----------------------------------------------------------------- -->
3475 <sect1> Dialogs
3476 <p>
3477 The Dialog widget is very simple, and is actually just a window with a
3478 few things pre-packed into it for you. The structure for a Dialog is:
3479
3480 <tscreen><verb>
3481 struct GtkDialog
3482 {
3483       GtkWindow window;
3484     
3485       GtkWidget *vbox;
3486       GtkWidget *action_area;
3487 };
3488 </verb></tscreen>
3489
3490 So you see, it simply creates a window, and then packs a vbox into the
3491 top, then a separator, and then an hbox for the "action_area".
3492
3493 The Dialog widget can be used for pop-up messages to the user, and
3494 other similar tasks. It is really basic, and there is only one
3495 function for the dialog box, which is:
3496
3497 <tscreen><verb>
3498 GtkWidget *gtk_dialog_new( void );
3499 </verb></tscreen>
3500
3501 So to create a new dialog box, use,
3502
3503 <tscreen><verb>
3504     GtkWidget *window;
3505     window = gtk_dialog_new ();
3506 </verb></tscreen>
3507
3508 This will create the dialog box, and it is now up to you to use it.
3509 you could pack a button in the action_area by doing something like this:
3510
3511 <tscreen><verb>
3512     button = ...
3513     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3514                         button, TRUE, TRUE, 0);
3515     gtk_widget_show (button);
3516 </verb></tscreen>
3517
3518 And you could add to the vbox area by packing, for instance, a label 
3519 in it, try something like this:
3520
3521 <tscreen><verb>
3522     label = gtk_label_new ("Dialogs are groovy");
3523     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3524                         label, TRUE, TRUE, 0);
3525     gtk_widget_show (label);
3526 </verb></tscreen>
3527
3528 As an example in using the dialog box, you could put two buttons in
3529 the action_area, a Cancel button and an Ok button, and a label in the
3530 vbox area, asking the user a question or giving an error etc. Then
3531 you could attach a different signal to each of the buttons and perform
3532 the operation the user selects.
3533
3534 If the simple functionality provided by the default vertical and
3535 horizontal boxes in the two areas does't give you enough control for
3536 your application, then you can simply pack another layout widget into
3537 the boxes provided. For example, you could pack a table into the
3538 vertical box.
3539
3540 <!-- ----------------------------------------------------------------- -->
3541 <sect1> Pixmaps <label id="sec_Pixmaps">
3542 <p>
3543 Pixmaps are data structures that contain pictures. These pictures can
3544 be used in various places, but most visibly as icons on the X-Windows
3545 desktop, or as cursors. A bitmap is a 2-color pixmap.
3546
3547 To use pixmaps in GTK, we must first build a GdkPixmap structure using
3548 routines from the GDK layer. Pixmaps can either be created from
3549 in-memory data, or from data read from a file. We'll go through each
3550 of the calls to create a pixmap.
3551
3552 <tscreen><verb>
3553 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
3554                                         gchar     *data,
3555                                         gint       width,
3556                                         gint       height );
3557 </verb></tscreen>
3558
3559 This routine is used to create a single-plane pixmap (2 colors) from
3560 data in memory. Each bit of the data represents whether that pixel is
3561 off or on. Width and height are in pixels. The GdkWindow pointer is
3562 to the current window, since a pixmap resources are meaningful only in
3563 the context of the screen where it is to be displayed.
3564
3565 <tscreen><verb>
3566 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
3567                                         gchar     *data,
3568                                         gint       width,
3569                                         gint       height,
3570                                         gint       depth,
3571                                         GdkColor  *fg,
3572                                         GdkColor  *bg );
3573 </verb></tscreen>
3574
3575 This is used to create a pixmap of the given depth (number of colors) from
3576 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
3577 background color to use.
3578
3579 <tscreen><verb>
3580 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
3581                                        GdkBitmap  **mask,
3582                                        GdkColor    *transparent_color,
3583                                        const gchar *filename );
3584 </verb></tscreen>
3585
3586 XPM format is a readable pixmap representation for the X Window
3587 System. It is widely used and many different utilities are available
3588 for creating image files in this format. The file specified by
3589 filename must contain an image in that format and it is loaded into
3590 the pixmap structure. The mask specifies which bits of the pixmap are
3591 opaque. All other bits are colored using the color specified by
3592 transparent_color. An example using this follows below.
3593
3594 <tscreen><verb>
3595 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
3596                                          GdkBitmap **mask,
3597                                          GdkColor   *transparent_color,
3598                                          gchar     **data );
3599 </verb></tscreen>
3600
3601 Small images can be incorporated into a program as data in the XPM
3602 format.  A pixmap is created using this data, instead of reading it
3603 from a file.  An example of such data is
3604
3605 <tscreen><verb>
3606 /* XPM */
3607 static const char * xpm_data[] = {
3608 "16 16 3 1",
3609 "       c None",
3610 ".      c #000000000000",
3611 "X      c #FFFFFFFFFFFF",
3612 "                ",
3613 "   ......       ",
3614 "   .XXX.X.      ",
3615 "   .XXX.XX.     ",
3616 "   .XXX.XXX.    ",
3617 "   .XXX.....    ",
3618 "   .XXXXXXX.    ",
3619 "   .XXXXXXX.    ",
3620 "   .XXXXXXX.    ",
3621 "   .XXXXXXX.    ",
3622 "   .XXXXXXX.    ",
3623 "   .XXXXXXX.    ",
3624 "   .XXXXXXX.    ",
3625 "   .........    ",
3626 "                ",
3627 "                "};
3628 </verb></tscreen>
3629
3630 When we're done using a pixmap and not likely to reuse it again soon,
3631 it is a good idea to release the resource using
3632 gdk_pixmap_unref(). Pixmaps should be considered a precious resource.
3633
3634 Once we've created a pixmap, we can display it as a GTK widget. We
3635 must create a GTK pixmap widget to contain the GDK pixmap. This is
3636 done using
3637
3638 <tscreen><verb>
3639 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
3640                            GdkBitmap *mask );
3641 </verb></tscreen>
3642
3643 The other pixmap widget calls are
3644
3645 <tscreen><verb>
3646 guint gtk_pixmap_get_type( void );
3647
3648 void  gtk_pixmap_set( GtkPixmap  *pixmap,
3649                       GdkPixmap  *val,
3650                       GdkBitmap  *mask );
3651
3652 void  gtk_pixmap_get( GtkPixmap  *pixmap,
3653                       GdkPixmap **val,
3654                       GdkBitmap **mask);
3655 </verb></tscreen>
3656
3657 gtk_pixmap_set is used to change the pixmap that the widget is currently
3658 managing. Val is the pixmap created using GDK.
3659
3660 The following is an example of using a pixmap in a button.
3661
3662 <tscreen><verb>
3663 /* example-start pixmap pixmap.c */
3664
3665 #include <gtk/gtk.h>
3666
3667
3668 /* XPM data of Open-File icon */
3669 static const char * xpm_data[] = {
3670 "16 16 3 1",
3671 "       c None",
3672 ".      c #000000000000",
3673 "X      c #FFFFFFFFFFFF",
3674 "                ",
3675 "   ......       ",
3676 "   .XXX.X.      ",
3677 "   .XXX.XX.     ",
3678 "   .XXX.XXX.    ",
3679 "   .XXX.....    ",
3680 "   .XXXXXXX.    ",
3681 "   .XXXXXXX.    ",
3682 "   .XXXXXXX.    ",
3683 "   .XXXXXXX.    ",
3684 "   .XXXXXXX.    ",
3685 "   .XXXXXXX.    ",
3686 "   .XXXXXXX.    ",
3687 "   .........    ",
3688 "                ",
3689 "                "};
3690
3691
3692 /* when invoked (via signal delete_event), terminates the application.
3693  */
3694 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
3695     gtk_main_quit();
3696 }
3697
3698
3699 /* is invoked when the button is clicked.  It just prints a message.
3700  */
3701 void button_clicked( GtkWidget *widget, gpointer data ) {
3702     printf( "button clicked\n" );
3703 }
3704
3705 int main( int argc, char *argv[] )
3706 {
3707     /* GtkWidget is the storage type for widgets */
3708     GtkWidget *window, *pixmapwid, *button;
3709     GdkPixmap *pixmap;
3710     GdkBitmap *mask;
3711     GtkStyle *style;
3712     
3713     /* create the main window, and attach delete_event signal to terminating
3714        the application */
3715     gtk_init( &amp;argc, &amp;argv );
3716     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3717     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
3718                         GTK_SIGNAL_FUNC (close_application), NULL );
3719     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
3720     gtk_widget_show( window );
3721
3722     /* now for the pixmap from gdk */
3723     style = gtk_widget_get_style( window );
3724     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
3725                                            &amp;style->bg[GTK_STATE_NORMAL],
3726                                            (gchar **)xpm_data );
3727
3728     /* a pixmap widget to contain the pixmap */
3729     pixmapwid = gtk_pixmap_new( pixmap, mask );
3730     gtk_widget_show( pixmapwid );
3731
3732     /* a button to contain the pixmap widget */
3733     button = gtk_button_new();
3734     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
3735     gtk_container_add( GTK_CONTAINER(window), button );
3736     gtk_widget_show( button );
3737
3738     gtk_signal_connect( GTK_OBJECT(button), "clicked",
3739                         GTK_SIGNAL_FUNC(button_clicked), NULL );
3740
3741     /* show the window */
3742     gtk_main ();
3743           
3744     return 0;
3745 }
3746 /* example-end */
3747 </verb></tscreen>
3748
3749 To load a file from an XPM data file called icon0.xpm in the current
3750 directory, we would have created the pixmap thus
3751
3752 <tscreen><verb>
3753     /* load a pixmap from a file */
3754     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
3755                                          &amp;style->bg[GTK_STATE_NORMAL],
3756                                          "./icon0.xpm" );
3757     pixmapwid = gtk_pixmap_new( pixmap, mask );
3758     gtk_widget_show( pixmapwid );
3759     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
3760 </verb></tscreen>
3761
3762 A disadvantage of using pixmaps is that the displayed object is always
3763 rectangular, regardless of the image. We would like to create desktops
3764 and applications with icons that have more natural shapes. For
3765 example, for a game interface, we would like to have round buttons to
3766 push. The way to do this is using shaped windows.
3767
3768 A shaped window is simply a pixmap where the background pixels are
3769 transparent. This way, when the background image is multi-colored, we
3770 don't overwrite it with a rectangular, non-matching border around our
3771 icon. The following example displays a full wheelbarrow image on the
3772 desktop.
3773
3774 <tscreen><verb>
3775 /* example-start wheelbarrow wheelbarrow.c */
3776
3777 #include <gtk/gtk.h>
3778
3779 /* XPM */
3780 static char * WheelbarrowFull_xpm[] = {
3781 "48 48 64 1",
3782 "       c None",
3783 ".      c #DF7DCF3CC71B",
3784 "X      c #965875D669A6",
3785 "o      c #71C671C671C6",
3786 "O      c #A699A289A699",
3787 "+      c #965892489658",
3788 "@      c #8E38410330C2",
3789 "#      c #D75C7DF769A6",
3790 "$      c #F7DECF3CC71B",
3791 "%      c #96588A288E38",
3792 "&amp;      c #A69992489E79",
3793 "*      c #8E3886178E38",
3794 "=      c #104008200820",
3795 "-      c #596510401040",
3796 ";      c #C71B30C230C2",
3797 ":      c #C71B9A699658",
3798 ">      c #618561856185",
3799 ",      c #20811C712081",
3800 "<      c #104000000000",
3801 "1      c #861720812081",
3802 "2      c #DF7D4D344103",
3803 "3      c #79E769A671C6",
3804 "4      c #861782078617",
3805 "5      c #41033CF34103",
3806 "6      c #000000000000",
3807 "7      c #49241C711040",
3808 "8      c #492445144924",
3809 "9      c #082008200820",
3810 "0      c #69A618611861",
3811 "q      c #B6DA71C65144",
3812 "w      c #410330C238E3",
3813 "e      c #CF3CBAEAB6DA",
3814 "r      c #71C6451430C2",
3815 "t      c #EFBEDB6CD75C",
3816 "y      c #28A208200820",
3817 "u      c #186110401040",
3818 "i      c #596528A21861",
3819 "p      c #71C661855965",
3820 "a      c #A69996589658",
3821 "s      c #30C228A230C2",
3822 "d      c #BEFBA289AEBA",
3823 "f      c #596545145144",
3824 "g      c #30C230C230C2",
3825 "h      c #8E3882078617",
3826 "j      c #208118612081",
3827 "k      c #38E30C300820",
3828 "l      c #30C2208128A2",
3829 "z      c #38E328A238E3",
3830 "x      c #514438E34924",
3831 "c      c #618555555965",
3832 "v      c #30C2208130C2",
3833 "b      c #38E328A230C2",
3834 "n      c #28A228A228A2",
3835 "m      c #41032CB228A2",
3836 "M      c #104010401040",
3837 "N      c #492438E34103",
3838 "B      c #28A2208128A2",
3839 "V      c #A699596538E3",
3840 "C      c #30C21C711040",
3841 "Z      c #30C218611040",
3842 "A      c #965865955965",
3843 "S      c #618534D32081",
3844 "D      c #38E31C711040",
3845 "F      c #082000000820",
3846 "                                                ",
3847 "          .XoO                                  ",
3848 "         +@#$%o&amp;                                ",
3849 "         *=-;#::o+                              ",
3850 "           >,<12#:34                            ",
3851 "             45671#:X3                          ",
3852 "               +89<02qwo                        ",
3853 "e*                >,67;ro                       ",
3854 "ty>                 459@>+&amp;&amp;                    ",
3855 "$2u+                  ><ipas8*                  ",
3856 "%$;=*                *3:.Xa.dfg>                ",
3857 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
3858 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
3859 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
3860 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
3861 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
3862 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
3863 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
3864 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
3865 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
3866 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
3867 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
3868 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
3869 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
3870 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
3871 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
3872 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
3873 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
3874 "              p;<69BvwwsszslllbBlllllllu<5+     ",
3875 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
3876 "               c1-699Blvlllllu7k96MMMg4         ",
3877 "               *10y8n6FjvllllB<166668           ",
3878 "                S-kg+>666<M<996-y6n<8*          ",
3879 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
3880 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
3881 "                 N-k-<>     >=01-kuu666>        ",
3882 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
3883 "                 Ou0<>       o66y<ulw<66&amp;       ",
3884 "                  *kk5       >66By7=xu664       ",
3885 "                   <<M4      466lj<Mxu66o       ",
3886 "                   *>>       +66uv,zN666*       ",
3887 "                              566,xxj669        ",
3888 "                              4666FF666>        ",
3889 "                               >966666M         ",
3890 "                                oM6668+         ",
3891 "                                  *4            ",
3892 "                                                ",
3893 "                                                "};
3894
3895
3896 /* When invoked (via signal delete_event), terminates the application */
3897 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
3898     gtk_main_quit();
3899 }
3900
3901 int main (int argc, char *argv[])
3902 {
3903     /* GtkWidget is the storage type for widgets */
3904     GtkWidget *window, *pixmap, *fixed;
3905     GdkPixmap *gdk_pixmap;
3906     GdkBitmap *mask;
3907     GtkStyle *style;
3908     GdkGC *gc;
3909     
3910     /* Create the main window, and attach delete_event signal to terminate
3911      * the application.  Note that the main window will not have a titlebar
3912      * since we're making it a popup. */
3913     gtk_init (&amp;argc, &amp;argv);
3914     window = gtk_window_new( GTK_WINDOW_POPUP );
3915     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
3916                         GTK_SIGNAL_FUNC (close_application), NULL);
3917     gtk_widget_show (window);
3918
3919     /* Now for the pixmap and the pixmap widget */
3920     style = gtk_widget_get_default_style();
3921     gc = style->black_gc;
3922     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
3923                                              &amp;style->bg[GTK_STATE_NORMAL],
3924                                              WheelbarrowFull_xpm );
3925     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
3926     gtk_widget_show( pixmap );
3927
3928     /* To display the pixmap, we use a fixed widget to place the pixmap */
3929     fixed = gtk_fixed_new();
3930     gtk_widget_set_usize( fixed, 200, 200 );
3931     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
3932     gtk_container_add( GTK_CONTAINER(window), fixed );
3933     gtk_widget_show( fixed );
3934
3935     /* This masks out everything except for the image itself */
3936     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
3937     
3938     /* show the window */
3939     gtk_widget_set_uposition( window, 20, 400 );
3940     gtk_widget_show( window );
3941     gtk_main ();
3942           
3943     return(0);
3944 }
3945 /* example-end */
3946 </verb></tscreen>
3947
3948 To make the wheelbarrow image sensitive, we could attach the button
3949 press event signal to make it do something. The following few lines
3950 would make the picture sensitive to a mouse button being pressed which
3951 makes the application terminate.
3952
3953 <tscreen><verb>
3954     gtk_widget_set_events( window,
3955                           gtk_widget_get_events( window ) |
3956                           GDK_BUTTON_PRESS_MASK );
3957
3958    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
3959                        GTK_SIGNAL_FUNC(close_application), NULL );
3960 </verb></tscreen>
3961
3962 <!-- ----------------------------------------------------------------- -->
3963 <sect1>Rulers
3964 <p>
3965 Ruler widgets are used to indicate the location of the mouse pointer
3966 in a given window. A window can have a vertical ruler spanning across
3967 the width and a horizontal ruler spanning down the height. A small
3968 triangular indicator on the ruler shows the exact location of the
3969 pointer relative to the ruler.
3970
3971 A ruler must first be created. Horizontal and vertical rulers are
3972 created using
3973
3974 <tscreen><verb>
3975 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
3976
3977 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
3978 </verb></tscreen>
3979
3980 Once a ruler is created, we can define the unit of measurement. Units
3981 of measure for rulers can be GTK_PIXELS, GTK_INCHES or
3982 GTK_CENTIMETERS. This is set using
3983
3984 <tscreen><verb>
3985 void gtk_ruler_set_metric( GtkRuler      *ruler,
3986                            GtkMetricType  metric );
3987 </verb></tscreen>
3988
3989 The default measure is GTK_PIXELS.
3990
3991 <tscreen><verb>
3992     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
3993 </verb></tscreen>
3994
3995 Other important characteristics of a ruler are how to mark the units
3996 of scale and where the position indicator is initially placed. These
3997 are set for a ruler using
3998
3999 <tscreen><verb>
4000 void gtk_ruler_set_range( GtkRuler *ruler,
4001                           gfloat    lower,
4002                           gfloat    upper,
4003                           gfloat    position,
4004                           gfloat    max_size );
4005 </verb></tscreen>
4006
4007 The lower and upper arguments define the extent of the ruler, and
4008 max_size is the largest possible number that will be displayed.
4009 Position defines the initial position of the pointer indicator within
4010 the ruler.
4011
4012 A vertical ruler can span an 800 pixel wide window thus
4013
4014 <tscreen><verb>
4015     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4016 </verb></tscreen>
4017
4018 The markings displayed on the ruler will be from 0 to 800, with a
4019 number for every 100 pixels. If instead we wanted the ruler to range
4020 from 7 to 16, we would code
4021
4022 <tscreen><verb>
4023     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4024 </verb></tscreen>
4025
4026 The indicator on the ruler is a small triangular mark that indicates
4027 the position of the pointer relative to the ruler. If the ruler is
4028 used to follow the mouse pointer, the motion_notify_event signal
4029 should be connected to the motion_notify_event method of the ruler.
4030 To follow all mouse movements within a window area, we would use
4031
4032 <tscreen><verb>
4033 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4034
4035     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4036            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4037            GTK_OBJECT(ruler) );
4038 </verb></tscreen>
4039
4040 The following example creates a drawing area with a horizontal ruler
4041 above it and a vertical ruler to the left of it. The size of the
4042 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4043 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4044 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4045 Placement of the drawing area and the rulers is done using a table.
4046
4047 <tscreen><verb>
4048 /* example-start rulers rulers.c */
4049
4050 #include <gtk/gtk.h>
4051
4052 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4053
4054 #define XSIZE  600
4055 #define YSIZE  400
4056
4057 /* This routine gets control when the close button is clicked */
4058 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4059     gtk_main_quit();
4060 }
4061
4062 /* The main routine */
4063 int main( int argc, char *argv[] ) {
4064     GtkWidget *window, *table, *area, *hrule, *vrule;
4065
4066     /* Initialize GTK and create the main window */
4067     gtk_init( &amp;argc, &amp;argv );
4068
4069     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4070     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4071             GTK_SIGNAL_FUNC( close_application ), NULL);
4072     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4073
4074     /* Create a table for placing the ruler and the drawing area */
4075     table = gtk_table_new( 3, 2, FALSE );
4076     gtk_container_add( GTK_CONTAINER(window), table );
4077
4078     area = gtk_drawing_area_new();
4079     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4080     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4081                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4082     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
4083
4084     /* The horizontal ruler goes on top. As the mouse moves across the drawing area,
4085      * a motion_notify_event is passed to the appropriate event handler for the ruler. */
4086     hrule = gtk_hruler_new();
4087     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4088     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4089     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4090                                (GtkSignalFunc)EVENT_METHOD(hrule, motion_notify_event),
4091                                GTK_OBJECT(hrule) );
4092     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4093     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4094                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4095     
4096     /* The vertical ruler goes on the left. As the mouse moves across the drawing area,
4097      * a motion_notify_event is passed to the appropriate event handler for the ruler. */
4098     vrule = gtk_vruler_new();
4099     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4100     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4101     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4102                                (GtkSignalFunc)
4103                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->motion_notify_event,
4104                                GTK_OBJECT(vrule) );
4105     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4106                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4107
4108     /* Now show everything */
4109     gtk_widget_show( area );
4110     gtk_widget_show( hrule );
4111     gtk_widget_show( vrule );
4112     gtk_widget_show( table );
4113     gtk_widget_show( window );
4114     gtk_main();
4115
4116     return(0);
4117 }
4118 /* example-end */
4119 </verb></tscreen>
4120
4121 <!-- ----------------------------------------------------------------- -->
4122 <sect1>Statusbars
4123 <p>
4124 Statusbars are simple widgets used to display a text message. They
4125 keep a stack of the messages pushed onto them, so that popping the
4126 current message will re-display the previous text message.
4127
4128 In order to allow different parts of an application to use the same
4129 statusbar to display messages, the statusbar widget issues Context
4130 Identifiers which are used to identify different 'users'. The message
4131 on top of the stack is the one displayed, no matter what context it is
4132 in. Messages are stacked in last-in-first-out order, not context
4133 identifier order.
4134
4135 A statusbar is created with a call to:
4136
4137 <tscreen><verb>
4138 GtkWidget *gtk_statusbar_new( void );
4139 </verb></tscreen>
4140
4141 A new Context Identifier is requested using a call to the following 
4142 function with a short textual description of the context:
4143
4144 <tscreen><verb>
4145 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4146                                     const gchar  *context_description );
4147 </verb></tscreen>
4148
4149 There are three functions that can operate on statusbars:
4150
4151 <tscreen><verb>
4152 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4153                           guint         context_id,
4154                           gchar        *text );
4155
4156 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4157                         guint         context_id );
4158
4159 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4160                            guint         context_id,
4161                            guint         message_id ); 
4162 </verb></tscreen>
4163
4164 The first, gtk_statusbar_push, is used to add a new message to the
4165 statusbar.  It returns a Message Identifier, which can be passed later
4166 to the function gtk_statusbar_remove to remove the message with the
4167 given Message and Context Identifiers from the statusbar's stack.
4168
4169 The function gtk_statusbar_pop removes the message highest in the
4170 stack with the given Context Identifier.
4171
4172 The following example creates a statusbar and two buttons, one for
4173 pushing items onto the statusbar, and one for popping the last item
4174 back off.
4175
4176 <tscreen><verb>
4177 /* example-start statusbar statusbar.c */
4178
4179 #include <gtk/gtk.h>
4180 #include <glib.h>
4181
4182 GtkWidget *status_bar;
4183
4184 void push_item (GtkWidget *widget, gpointer data)
4185 {
4186   static int count = 1;
4187   char buff[20];
4188
4189   g_snprintf(buff, 20, "Item %d", count++);
4190   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4191
4192   return;
4193 }
4194
4195 void pop_item (GtkWidget *widget, gpointer data)
4196 {
4197   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4198   return;
4199 }
4200
4201 int main (int argc, char *argv[])
4202 {
4203
4204     GtkWidget *window;
4205     GtkWidget *vbox;
4206     GtkWidget *button;
4207
4208     gint context_id;
4209
4210     gtk_init (&amp;argc, &amp;argv);
4211
4212     /* create a new window */
4213     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4214     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4215     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4216     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4217                        (GtkSignalFunc) gtk_exit, NULL);
4218  
4219     vbox = gtk_vbox_new(FALSE, 1);
4220     gtk_container_add(GTK_CONTAINER(window), vbox);
4221     gtk_widget_show(vbox);
4222           
4223     status_bar = gtk_statusbar_new();      
4224     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4225     gtk_widget_show (status_bar);
4226
4227     context_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(status_bar), "Statusbar example");
4228
4229     button = gtk_button_new_with_label("push item");
4230     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4231         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4232     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4233     gtk_widget_show(button);              
4234
4235     button = gtk_button_new_with_label("pop last item");
4236     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4237         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4238     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4239     gtk_widget_show(button);              
4240
4241     /* always display the window as the last step so it all splashes on
4242      * the screen at once. */
4243     gtk_widget_show(window);
4244
4245     gtk_main ();
4246
4247     return 0;
4248 }
4249 /* example-end */
4250 </verb></tscreen>
4251
4252 <!-- ----------------------------------------------------------------- -->
4253 <sect1>Text Entries
4254 <p>
4255 The Entry widget allows text to be typed and displayed in a single line
4256 text box. The text may be set with function calls that allow new text
4257 to replace, prepend or append the current contents of the Entry widget.
4258
4259 There are two functions for creating Entry widgets:
4260
4261 <tscreen><verb>
4262 GtkWidget *gtk_entry_new( void );
4263
4264 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4265 </verb></tscreen>
4266
4267 The first just creates a new Entry widget, whilst the second creates a
4268 new Entry and sets a limit on the length of the text within the Entry.
4269
4270 There are several functions for altering the text which is currently
4271 within the Entry widget.
4272
4273 <tscreen><verb>
4274 void gtk_entry_set_text( GtkEntry    *entry,
4275                          const gchar *text );
4276
4277 void gtk_entry_append_text( GtkEntry    *entry,
4278                             const gchar *text );
4279
4280 void gtk_entry_prepend_text( GtkEntry    *entry,
4281                              const gchar *text );
4282 </verb></tscreen>
4283
4284 The function gtk_entry_set_text sets the contents of the Entry widget,
4285 replacing the current contents. The functions gtk_entry_append_text
4286 and gtk_entry_prepend_text allow the current contents to be appended
4287 and prepended to.
4288
4289 The next function allows the current insertion point to be set.
4290
4291 <tscreen><verb>
4292 void gtk_entry_set_position( GtkEntry *entry,
4293                              gint      position );
4294 </verb></tscreen>
4295
4296 The contents of the Entry can be retrieved by using a call to the
4297 following function. This is useful in the callback functions described below.
4298
4299 <tscreen><verb>
4300 gchar *gtk_entry_get_text( GtkEntry *entry );
4301 </verb></tscreen>
4302
4303 If we don't want the contents of the Entry to be changed by someone typing
4304 into it, we can change its editable state.
4305
4306 <tscreen><verb>
4307 void gtk_entry_set_editable( GtkEntry *entry,
4308                              gboolean  editable );
4309 </verb></tscreen>
4310
4311 The function above allows us to toggle the editable state of the
4312 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4313 argument.
4314
4315 If we are using the Entry where we don't want the text entered to be
4316 visible, for example when a password is being entered, we can use the
4317 following function, which also takes a boolean flag.
4318
4319 <tscreen><verb>
4320 void gtk_entry_set_visibility( GtkEntry *entry,
4321                                gboolean  visible );
4322 </verb></tscreen>
4323
4324 A region of the text may be set as selected by using the following
4325 function. This would most often be used after setting some default
4326 text in an Entry, making it easy for the user to remove it.
4327
4328 <tscreen><verb>
4329 void gtk_entry_select_region( GtkEntry *entry,
4330                               gint      start,
4331                               gint      end );
4332 </verb></tscreen>
4333
4334 If we want to catch when the user has entered text, we can connect to
4335 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4336 user hits the enter key within the Entry widget. Changed is raised
4337 when the text changes at all, e.g. for every character entered or
4338 removed.
4339
4340 The following code is an example of using an Entry widget.
4341
4342 <tscreen><verb>
4343 /* example-start entry entry.c */
4344
4345 #include <gtk/gtk.h>
4346
4347 void enter_callback(GtkWidget *widget, GtkWidget *entry)
4348 {
4349   gchar *entry_text;
4350   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4351   printf("Entry contents: %s\n", entry_text);
4352 }
4353
4354 void entry_toggle_editable (GtkWidget *checkbutton,
4355                                    GtkWidget *entry)
4356 {
4357   gtk_entry_set_editable(GTK_ENTRY(entry),
4358                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4359 }
4360
4361 void entry_toggle_visibility (GtkWidget *checkbutton,
4362                                    GtkWidget *entry)
4363 {
4364   gtk_entry_set_visibility(GTK_ENTRY(entry),
4365                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4366 }
4367
4368 int main (int argc, char *argv[])
4369 {
4370
4371     GtkWidget *window;
4372     GtkWidget *vbox, *hbox;
4373     GtkWidget *entry;
4374     GtkWidget *button;
4375     GtkWidget *check;
4376
4377     gtk_init (&amp;argc, &amp;argv);
4378
4379     /* create a new window */
4380     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4381     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4382     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4383     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4384                        (GtkSignalFunc) gtk_exit, NULL);
4385
4386     vbox = gtk_vbox_new (FALSE, 0);
4387     gtk_container_add (GTK_CONTAINER (window), vbox);
4388     gtk_widget_show (vbox);
4389
4390     entry = gtk_entry_new_with_max_length (50);
4391     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4392                        GTK_SIGNAL_FUNC(enter_callback),
4393                        entry);
4394     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4395     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4396     gtk_entry_select_region (GTK_ENTRY (entry),
4397                              0, GTK_ENTRY(entry)->text_length);
4398     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4399     gtk_widget_show (entry);
4400
4401     hbox = gtk_hbox_new (FALSE, 0);
4402     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4403     gtk_widget_show (hbox);
4404                                   
4405     check = gtk_check_button_new_with_label("Editable");
4406     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4407     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4408                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4409     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4410     gtk_widget_show (check);
4411     
4412     check = gtk_check_button_new_with_label("Visible");
4413     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4414     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4415                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4416     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4417     gtk_widget_show (check);
4418                                    
4419     button = gtk_button_new_with_label ("Close");
4420     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4421                                GTK_SIGNAL_FUNC(gtk_exit),
4422                                GTK_OBJECT (window));
4423     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4424     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4425     gtk_widget_grab_default (button);
4426     gtk_widget_show (button);
4427     
4428     gtk_widget_show(window);
4429
4430     gtk_main();
4431     return(0);
4432 }
4433 /* example-end */
4434 </verb></tscreen>
4435
4436 <!-- ----------------------------------------------------------------- -->
4437 <sect1> Color Selection
4438 <p>
4439 The color selection widget is, not surprisingly, a widget for
4440 interactive selection of colors. This composite widget lets the user
4441 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
4442 Saturation, Value) triples.  This is done either by adjusting single
4443 values with sliders or entries, or by picking the desired color from a
4444 hue-saturation wheel/value bar.  Optionally, the opacity of the color
4445 can also be set.
4446
4447 The color selection widget currently emits only one signal,
4448 "color_changed", which is emitted whenever the current color in the
4449 widget changes, either when the user changes it or if it's set
4450 explicitly through gtk_color_selection_set_color().
4451
4452 Lets have a look at what the color selection widget has to offer
4453 us. The widget comes in two flavours: gtk_color_selection and
4454 gtk_color_selection_dialog.
4455
4456 <tscreen><verb>
4457 GtkWidget *gtk_color_selection_new( void );
4458 </verb></tscreen>
4459         
4460 You'll probably not be using this constructor directly. It creates an
4461 orphan GtkColorSelection widget which you'll have to parent
4462 yourself. The GtkColorSelection widget inherits from the GtkVBox
4463 widget.
4464
4465 <tscreen><verb> 
4466 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
4467 </verb></tscreen>
4468
4469 This is the most common color selection constructor. It creates a
4470 GtkColorSelectionDialog, which inherits from a GtkDialog. It consists
4471 of a GtkFrame containing a GtkColorSelection widget, a GtkHSeparator
4472 and a GtkHBox with three buttons, "Ok", "Cancel" and "Help". You can
4473 reach these buttons by accessing the "ok_button", "cancel_button" and
4474 "help_button" widgets in the GtkColorSelectionDialog structure,
4475 (i.e. GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
4476
4477 <tscreen><verb>
4478 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
4479                                             GtkUpdateType      policy );
4480 </verb></tscreen>
4481
4482 This function sets the update policy. The default policy is
4483 GTK_UPDATE_CONTINUOUS which means that the current color is updated
4484 continuously when the user drags the sliders or presses the mouse and
4485 drags in the hue-saturation wheel or value bar. If you experience
4486 performance problems, you may want to set the policy to
4487 GTK_UPDATE_DISCONTINUOUS or GTK_UPDATE_DELAYED.
4488
4489 <tscreen><verb>
4490 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
4491                                       gint               use_opacity );
4492 </verb></tscreen>
4493
4494 The color selection widget supports adjusting the opacity of a color
4495 (also known as the alpha channel). This is disabled by
4496 default. Calling this function with use_opacity set to TRUE enables
4497 opacity. Likewise, use_opacity set to FALSE will disable opacity.
4498
4499 <tscreen><verb>
4500 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
4501                                     gdouble           *color );
4502 </verb></tscreen>
4503
4504 You can set the current color explicitly by calling this function with
4505 a pointer to an array of colors (gdouble). The length of the array
4506 depends on whether opacity is enabled or not. Position 0 contains the
4507 red component, 1 is green, 2 is blue and opacity is at position 3
4508 (only if opacity is enabled, see
4509 gtk_color_selection_set_opacity()). All values are between 0.0 and
4510 1.0.
4511
4512 <tscreen><verb>
4513 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
4514                                     gdouble           *color );
4515 </verb></tscreen>
4516
4517 When you need to query the current color, typically when you've
4518 received a "color_changed" signal, you use this function. Color is a
4519 pointer to the array of colors to fill in. See the
4520 gtk_color_selection_set_color() function for the description of this
4521 array.
4522
4523 <!-- Need to do a whole section on DnD - TRG
4524 Drag and drop
4525 -------------
4526
4527 The color sample areas (right under the hue-saturation wheel) supports
4528 drag and drop. The type of drag and drop is "application/x-color". The
4529 message data consists of an array of 4 (or 5 if opacity is enabled)
4530 gdouble values, where the value at position 0 is 0.0 (opacity on) or
4531 1.0 (opacity off) followed by the red, green and blue values at
4532 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
4533 is passed in the value at position 4.
4534 -->
4535
4536 Here's a simple example demonstrating the use of the
4537 GtkColorSelectionDialog. The program displays a window containing a
4538 drawing area. Clicking on it opens a color selection dialog, and
4539 changing the color in the color selection dialog changes the
4540 background color.
4541
4542 <tscreen><verb>
4543 /* example-start colorsel colorsel.c */
4544
4545 #include <glib.h>
4546 #include <gdk/gdk.h>
4547 #include <gtk/gtk.h>
4548
4549 GtkWidget *colorseldlg = NULL;
4550 GtkWidget *drawingarea = NULL;
4551
4552 /* Color changed handler */
4553
4554 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
4555 {
4556   gdouble color[3];
4557   GdkColor gdk_color;
4558   GdkColormap *colormap;
4559
4560   /* Get drawingarea colormap */
4561
4562   colormap = gdk_window_get_colormap (drawingarea->window);
4563
4564   /* Get current color */
4565
4566   gtk_color_selection_get_color (colorsel,color);
4567
4568   /* Fit to a unsigned 16 bit integer (0..65535) and insert into the GdkColor structure */
4569
4570   gdk_color.red = (guint16)(color[0]*65535.0);
4571   gdk_color.green = (guint16)(color[1]*65535.0);
4572   gdk_color.blue = (guint16)(color[2]*65535.0);
4573
4574   /* Allocate color */
4575
4576   gdk_color_alloc (colormap, &amp;gdk_color);
4577
4578   /* Set window background color */
4579
4580   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
4581
4582   /* Clear window */
4583
4584   gdk_window_clear (drawingarea->window);
4585 }
4586
4587 /* Drawingarea event handler */
4588
4589 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
4590 {
4591   gint handled = FALSE;
4592   GtkWidget *colorsel;
4593
4594   /* Check if we've received a button pressed event */
4595
4596   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
4597     {
4598       /* Yes, we have an event and there's no colorseldlg yet! */
4599
4600       handled = TRUE;
4601
4602       /* Create color selection dialog */
4603
4604       colorseldlg = gtk_color_selection_dialog_new("Select background color");
4605
4606       /* Get the GtkColorSelection widget */
4607
4608       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
4609
4610       /* Connect to the "color_changed" signal, set the client-data to the colorsel widget */
4611
4612       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
4613         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
4614
4615       /* Show the dialog */
4616
4617       gtk_widget_show(colorseldlg);
4618     }
4619
4620   return handled;
4621 }
4622
4623 /* Close down and exit handler */
4624
4625 void destroy_window (GtkWidget *widget, gpointer client_data)
4626 {
4627   gtk_main_quit ();
4628 }
4629
4630 /* Main */
4631
4632 gint main (gint argc, gchar *argv[])
4633 {
4634   GtkWidget *window;
4635
4636   /* Initialize the toolkit, remove gtk-related commandline stuff */
4637
4638   gtk_init (&amp;argc,&amp;argv);
4639
4640   /* Create toplevel window, set title and policies */
4641
4642   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4643   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
4644   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
4645
4646   /* Attach to the "delete" and "destroy" events so we can exit */
4647
4648   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
4649     (GtkSignalFunc)destroy_window, (gpointer)window);
4650
4651   gtk_signal_connect (GTK_OBJECT(window), "destroy",
4652     (GtkSignalFunc)destroy_window, (gpointer)window);
4653   
4654   /* Create drawingarea, set size and catch button events */
4655
4656   drawingarea = gtk_drawing_area_new ();
4657
4658   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
4659
4660   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
4661
4662   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
4663     (GtkSignalFunc)area_event, (gpointer)drawingarea);
4664   
4665   /* Add drawingarea to window, then show them both */
4666
4667   gtk_container_add (GTK_CONTAINER(window), drawingarea);
4668
4669   gtk_widget_show (drawingarea);
4670   gtk_widget_show (window);
4671   
4672   /* Enter the gtk main loop (this never returns) */
4673
4674   gtk_main ();
4675
4676   /* Satisfy grumpy compilers */
4677
4678   return(0);
4679 }
4680 /* example-end */
4681 </verb></tscreen>
4682
4683 <!-- ----------------------------------------------------------------- -->
4684 <sect1> File Selections
4685 <p>
4686 The file selection widget is a quick and simple way to display a File
4687 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
4688 great way to cut down on programming time.
4689
4690 To create a new file selection box use:
4691
4692 <tscreen><verb>
4693 GtkWidget *gtk_file_selection_new( gchar *title );
4694 </verb></tscreen>
4695
4696 To set the filename, for example to bring up a specific directory, or
4697 give a default filename, use this function:
4698
4699 <tscreen><verb>
4700 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
4701                                       gchar            *filename );
4702 </verb></tscreen>
4703
4704 To grab the text that the user has entered or clicked on, use this 
4705 function:
4706
4707 <tscreen><verb>
4708 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
4709 </verb></tscreen>
4710
4711 There are also pointers to the widgets contained within the file 
4712 selection widget. These are:
4713
4714 <itemize>
4715 <item>dir_list
4716 <item>file_list
4717 <item>selection_entry
4718 <item>selection_text
4719 <item>main_vbox
4720 <item>ok_button
4721 <item>cancel_button
4722 <item>help_button
4723 </itemize>
4724
4725 Most likely you will want to use the ok_button, cancel_button, and
4726 help_button pointers in signaling their use.
4727
4728 Included here is an example stolen from testgtk.c, modified to run on
4729 its own. As you will see, there is nothing much to creating a file
4730 selection widget. While in this example the Help button appears on the
4731 screen, it does nothing as there is not a signal attached to it.
4732
4733 <tscreen><verb>
4734 /* example-start filesel filesel.c */
4735
4736 #include <gtk/gtk.h>
4737
4738 /* Get the selected filename and print it to the console */
4739 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
4740 {
4741     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
4742 }
4743
4744 void destroy (GtkWidget *widget, gpointer data)
4745 {
4746     gtk_main_quit ();
4747 }
4748
4749 int main (int argc, char *argv[])
4750 {
4751     GtkWidget *filew;
4752     
4753     gtk_init (&amp;argc, &amp;argv);
4754     
4755     /* Create a new file selection widget */
4756     filew = gtk_file_selection_new ("File selection");
4757     
4758     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
4759                         (GtkSignalFunc) destroy, &amp;filew);
4760     /* Connect the ok_button to file_ok_sel function */
4761     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
4762                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
4763     
4764     /* Connect the cancel_button to destroy the widget */
4765     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button),
4766                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
4767                                GTK_OBJECT (filew));
4768     
4769     /* Lets set the filename, as if this were a save dialog, and we are giving
4770      a default filename */
4771     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
4772                                      "penguin.png");
4773     
4774     gtk_widget_show(filew);
4775     gtk_main ();
4776     return 0;
4777 }
4778 /* example-end */
4779 </verb></tscreen>
4780
4781 <!-- ***************************************************************** -->
4782 <sect> Container Widgets
4783 <!-- ***************************************************************** -->
4784
4785 <!-- ----------------------------------------------------------------- -->
4786 <sect1> Notebooks
4787 <p>
4788 The NoteBook Widget is a collection of 'pages' that overlap each
4789 other, each page contains different information. This widget has
4790 become more common lately in GUI programming, and it is a good way to
4791 show blocks of similar information that warrant separation in their
4792 display.
4793
4794 The first function call you will need to know, as you can probably
4795 guess by now, is used to create a new notebook widget.
4796
4797 <tscreen><verb>
4798 GtkWidget *gtk_notebook_new( void );
4799 </verb></tscreen>
4800
4801 Once the notebook has been created, there are a number of functions
4802 that operate on the notebook widget. Let's look at them individually.
4803
4804 The first one we will look at is how to position the page indicators.
4805 These page indicators or 'tabs' as they are referred to, can be
4806 positioned in four ways: top, bottom, left, or right.
4807
4808 <tscreen><verb>
4809 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
4810                                GtkPositionType  pos );
4811 </verb></tscreen>
4812
4813 GtkPostionType will be one of the following, and they are pretty self explanatory:
4814 <itemize>
4815 <item> GTK_POS_LEFT
4816 <item> GTK_POS_RIGHT
4817 <item> GTK_POS_TOP
4818 <item> GTK_POS_BOTTOM
4819 </itemize>
4820
4821 GTK_POS_TOP is the default.
4822
4823 Next we will look at how to add pages to the notebook. There are three
4824 ways to add pages to the NoteBook. Let's look at the first two
4825 together as they are quite similar.
4826
4827 <tscreen><verb>
4828 void gtk_notebook_append_page( GtkNotebook *notebook,
4829                                GtkWidget   *child,
4830                                GtkWidget   *tab_label );
4831
4832 void gtk_notebook_prepend_page( GtkNotebook *notebook,
4833                                 GtkWidget   *child,
4834                                 GtkWidget   *tab_label );
4835 </verb></tscreen>
4836
4837 These functions add pages to the notebook by inserting them from the
4838 back of the notebook (append), or the front of the notebook (prepend).
4839 <tt/child/ is the widget that is placed within the notebook page, and
4840 <tt/tab_label/ is the label for the page being added. The <tt/child/
4841 widget must be created separately, and is typically a set of options
4842 setout witin one of the other container widgets, such as a table.
4843
4844 The final function for adding a page to the notebook contains all of
4845 the properties of the previous two, but it allows you to specify what
4846 position you want the page to be in the notebook.
4847
4848 <tscreen><verb>
4849 void gtk_notebook_insert_page( GtkNotebook *notebook,
4850                                GtkWidget   *child,
4851                                GtkWidget   *tab_label,
4852                                gint         position );
4853 </verb></tscreen>
4854
4855 The parameters are the same as _append_ and _prepend_ except it
4856 contains an extra parameter, <tt/position/.  This parameter is used to
4857 specify what place this page will be inserted into.
4858
4859 Now that we know how to add a page, lets see how we can remove a page
4860 from the notebook.
4861
4862 <tscreen><verb>
4863 void gtk_notebook_remove_page( GtkNotebook *notebook,
4864                                gint         page_num );
4865 </verb></tscreen>
4866
4867 This function takes the page specified by <tt/page_num/ and removes it
4868 from the widget pointed to by <tt/notebook/.
4869
4870 To find out what the current page is in a notebook use the function:
4871
4872 <tscreen><verb>
4873 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
4874 </verb></tscreen>
4875
4876 These next two functions are simple calls to move the notebook page
4877 forward or backward. Simply provide the respective function call with
4878 the notebook widget you wish to operate on. Note: when the NoteBook is
4879 currently on the last page, and gtk_notebook_next_page is called, the
4880 notebook will wrap back to the first page. Likewise, if the NoteBook
4881 is on the first page, and gtk_notebook_prev_page is called, the
4882 notebook will wrap to the last page.
4883
4884 <tscreen><verb>
4885 void gtk_notebook_next_page( GtkNoteBook *notebook );
4886
4887 void gtk_notebook_prev_page( GtkNoteBook *notebook );
4888 </verb></tscreen>
4889
4890 This next function sets the 'active' page. If you wish the notebook to
4891 be opened to page 5 for example, you would use this function.  Without
4892 using this function, the notebook defaults to the first page.
4893
4894 <tscreen><verb>
4895 void gtk_notebook_set_page( GtkNotebook *notebook,
4896                             gint         page_num );
4897 </verb></tscreen>
4898
4899 The next two functions add or remove the notebook page tabs and the
4900 notebook border respectively.
4901
4902 <tscreen><verb>
4903 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
4904                                  gboolean     show_tabs);
4905
4906 void gtk_notebook_set_show_border( GtkNotebook *notebook,
4907                                    gboolean     show_border );
4908 </verb></tscreen>
4909
4910 The next function is useful when the you have a large number of pages,
4911 and the tabs don't fit on the page. It allows the tabs to be scrolled
4912 through using two arrow buttons.
4913
4914 <tscreen><verb>
4915 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
4916                                   gboolean     scrollable );
4917 </verb></tscreen>
4918
4919 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
4920 TRUE or FALSE.
4921
4922 Now lets look at an example, it is expanded from the testgtk.c code
4923 that comes with the GTK distribution. This small program creates a
4924 window with a notebook and six buttons. The notebook contains 11
4925 pages, added in three different ways, appended, inserted, and
4926 prepended. The buttons allow you rotate the tab positions, add/remove
4927 the tabs and border, remove a page, change pages in both a forward and
4928 backward manner, and exit the program.
4929
4930 <tscreen><verb>
4931 /* example-start notebook notebook.c */
4932
4933 #include <gtk/gtk.h>
4934
4935 /* This function rotates the position of the tabs */
4936 void rotate_book (GtkButton *button, GtkNotebook *notebook)
4937 {
4938     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
4939 }
4940
4941 /* Add/Remove the page tabs and the borders */
4942 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
4943 {
4944     gint tval = FALSE;
4945     gint bval = FALSE;
4946     if (notebook->show_tabs == 0)
4947             tval = TRUE; 
4948     if (notebook->show_border == 0)
4949             bval = TRUE;
4950     
4951     gtk_notebook_set_show_tabs (notebook, tval);
4952     gtk_notebook_set_show_border (notebook, bval);
4953 }
4954
4955 /* Remove a page from the notebook */
4956 void remove_book (GtkButton *button, GtkNotebook *notebook)
4957 {
4958     gint page;
4959     
4960     page = gtk_notebook_get_current_page(notebook);
4961     gtk_notebook_remove_page (notebook, page);
4962     /* Need to refresh the widget -- 
4963      This forces the widget to redraw itself. */
4964     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
4965 }
4966
4967 void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
4968 {
4969     gtk_main_quit ();
4970 }
4971
4972 int main (int argc, char *argv[])
4973 {
4974     GtkWidget *window;
4975     GtkWidget *button;
4976     GtkWidget *table;
4977     GtkWidget *notebook;
4978     GtkWidget *frame;
4979     GtkWidget *label;
4980     GtkWidget *checkbutton;
4981     int i;
4982     char bufferf[32];
4983     char bufferl[32];
4984     
4985     gtk_init (&amp;argc, &amp;argv);
4986     
4987     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4988     
4989     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4990                         GTK_SIGNAL_FUNC (delete), NULL);
4991     
4992     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4993
4994     table = gtk_table_new(3,6,FALSE);
4995     gtk_container_add (GTK_CONTAINER (window), table);
4996     
4997     /* Create a new notebook, place the position of the tabs */
4998     notebook = gtk_notebook_new ();
4999     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
5000     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
5001     gtk_widget_show(notebook);
5002     
5003     /* Lets append a bunch of pages to the notebook */
5004     for (i=0; i < 5; i++) {
5005         sprintf(bufferf, "Append Frame %d", i+1);
5006         sprintf(bufferl, "Page %d", i+1);
5007         
5008         frame = gtk_frame_new (bufferf);
5009         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
5010         gtk_widget_set_usize (frame, 100, 75);
5011         gtk_widget_show (frame);
5012         
5013         label = gtk_label_new (bufferf);
5014         gtk_container_add (GTK_CONTAINER (frame), label);
5015         gtk_widget_show (label);
5016         
5017         label = gtk_label_new (bufferl);
5018         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
5019     }
5020       
5021     /* Now lets add a page to a specific spot */
5022     checkbutton = gtk_check_button_new_with_label ("Check me please!");
5023     gtk_widget_set_usize(checkbutton, 100, 75);
5024     gtk_widget_show (checkbutton);
5025    
5026     label = gtk_label_new ("Add page");
5027     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
5028     
5029     /* Now finally lets prepend pages to the notebook */
5030     for (i=0; i < 5; i++) {
5031         sprintf(bufferf, "Prepend Frame %d", i+1);
5032         sprintf(bufferl, "PPage %d", i+1);
5033         
5034         frame = gtk_frame_new (bufferf);
5035         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
5036         gtk_widget_set_usize (frame, 100, 75);
5037         gtk_widget_show (frame);
5038         
5039         label = gtk_label_new (bufferf);
5040         gtk_container_add (GTK_CONTAINER (frame), label);
5041         gtk_widget_show (label);
5042         
5043         label = gtk_label_new (bufferl);
5044         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
5045     }
5046     
5047     /* Set what page to start at (page 4) */
5048     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
5049
5050     /* Create a bunch of buttons */
5051     button = gtk_button_new_with_label ("close");
5052     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5053                                GTK_SIGNAL_FUNC (delete), NULL);
5054     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
5055     gtk_widget_show(button);
5056     
5057     button = gtk_button_new_with_label ("next page");
5058     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5059                                (GtkSignalFunc) gtk_notebook_next_page,
5060                                GTK_OBJECT (notebook));
5061     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
5062     gtk_widget_show(button);
5063     
5064     button = gtk_button_new_with_label ("prev page");
5065     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5066                                (GtkSignalFunc) gtk_notebook_prev_page,
5067                                GTK_OBJECT (notebook));
5068     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
5069     gtk_widget_show(button);
5070     
5071     button = gtk_button_new_with_label ("tab position");
5072     gtk_signal_connect (GTK_OBJECT (button), "clicked",
5073                         (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
5074     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
5075     gtk_widget_show(button);
5076     
5077     button = gtk_button_new_with_label ("tabs/border on/off");
5078     gtk_signal_connect (GTK_OBJECT (button), "clicked",
5079                         (GtkSignalFunc) tabsborder_book,
5080                         GTK_OBJECT (notebook));
5081     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
5082     gtk_widget_show(button);
5083     
5084     button = gtk_button_new_with_label ("remove page");
5085     gtk_signal_connect (GTK_OBJECT (button), "clicked",
5086                         (GtkSignalFunc) remove_book,
5087                         GTK_OBJECT(notebook));
5088     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
5089     gtk_widget_show(button);
5090     
5091     gtk_widget_show(table);
5092     gtk_widget_show(window);
5093     
5094     gtk_main ();
5095     
5096     return(0);
5097 }
5098 /* example-end */
5099 </verb></tscreen>
5100
5101 Hopefully this helps you on your way with creating notebooks for your
5102 GTK applications.
5103
5104 <!-- ----------------------------------------------------------------- -->
5105 <sect1>Scrolled Windows
5106 <p>
5107 Scrolled windows are used to create a scrollable area inside a real
5108 window.  You may insert any type of widget into a scrolled window, and
5109 it will be accessible regardless of the size by using the scrollbars.
5110
5111 The following function is used to create a new scrolled window.
5112
5113 <tscreen><verb>
5114 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
5115                                     GtkAdjustment *vadjustment );
5116 </verb></tscreen>
5117
5118 Where the first argument is the adjustment for the horizontal
5119 direction, and the second, the adjustment for the vertical direction.
5120 These are almost always set to NULL.
5121
5122 <tscreen><verb>
5123 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
5124                                      GtkPolicyType      hscrollbar_policy,
5125                                      GtkPolicyType      vscrollbar_policy );
5126 </verb></tscreen>
5127
5128 This sets the policy to be used with respect to the scrollbars.
5129 The first argument is the scrolled window you wish to change. The second
5130 sets the policy for the horizontal scrollbar, and the third the policy for 
5131 the vertical scrollbar.
5132
5133 The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
5134 GTK_POLICY_AUTOMATIC will automatically decide whether you need
5135 scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
5136 there.
5137
5138 You can then place your object into the scrolled window using the
5139 following function.
5140
5141 <tscreen><verb>
5142 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
5143                                             GtkWidget         *child);
5144 </verb></tscreen>
5145
5146 Here is a simple example that packs 100 toggle buttons into a scrolled
5147 window.  I've only commented on the parts that may be new to you.
5148
5149 <tscreen><verb>
5150 /* example-start scrolledwin scrolledwin.c */
5151
5152 #include <gtk/gtk.h>
5153
5154 void destroy(GtkWidget *widget, gpointer data)
5155 {
5156     gtk_main_quit();
5157 }
5158
5159 int main (int argc, char *argv[])
5160 {
5161     static GtkWidget *window;
5162     GtkWidget *scrolled_window;
5163     GtkWidget *table;
5164     GtkWidget *button;
5165     char buffer[32];
5166     int i, j;
5167     
5168     gtk_init (&amp;argc, &amp;argv);
5169     
5170     /* Create a new dialog window for the scrolled window to be
5171      * packed into. A dialog is just like a normal window except it has a 
5172      * vbox and a horizontal separator packed into it. It's just a shortcut
5173      * for creating dialogs */
5174     window = gtk_dialog_new ();
5175     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5176                         (GtkSignalFunc) destroy, NULL);
5177     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
5178     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5179     gtk_widget_set_usize(window, 300, 300);
5180     
5181     /* create a new scrolled window. */
5182     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
5183     
5184     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
5185     
5186     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
5187      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
5188      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
5189      * there.  The first one is the horizontal scrollbar, the second, 
5190      * the vertical. */
5191     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
5192                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
5193     /* The dialog window is created with a vbox packed into it. */                                                              
5194     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
5195                         TRUE, TRUE, 0);
5196     gtk_widget_show (scrolled_window);
5197     
5198     /* create a table of 10 by 10 squares. */
5199     table = gtk_table_new (10, 10, FALSE);
5200     
5201     /* set the spacing to 10 on x and 10 on y */
5202     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
5203     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
5204     
5205     /* pack the table into the scrolled window */
5206     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
5207                                            table);
5208     gtk_widget_show (table);
5209     
5210     /* this simply creates a grid of toggle buttons on the table
5211      * to demonstrate the scrolled window. */
5212     for (i = 0; i < 10; i++)
5213        for (j = 0; j < 10; j++) {
5214           sprintf (buffer, "button (%d,%d)\n", i, j);
5215           button = gtk_toggle_button_new_with_label (buffer);
5216           gtk_table_attach_defaults (GTK_TABLE (table), button,
5217                                      i, i+1, j, j+1);
5218           gtk_widget_show (button);
5219        }
5220     
5221     /* Add a "close" button to the bottom of the dialog */
5222     button = gtk_button_new_with_label ("close");
5223     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5224                                (GtkSignalFunc) gtk_widget_destroy,
5225                                GTK_OBJECT (window));
5226     
5227     /* this makes it so the button is the default. */
5228     
5229     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5230     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
5231     
5232     /* This grabs this button to be the default button. Simply hitting
5233      * the "Enter" key will cause this button to activate. */
5234     gtk_widget_grab_default (button);
5235     gtk_widget_show (button);
5236     
5237     gtk_widget_show (window);
5238     
5239     gtk_main();
5240     
5241     return(0);
5242 }
5243 /* example-end */
5244 </verb></tscreen>
5245
5246 Try playing with resizing the window. You'll notice how the scrollbars
5247 react. You may also wish to use the gtk_widget_set_usize() call to set
5248 the default size of the window or other widgets.
5249
5250 <!-- ----------------------------------------------------------------- -->   
5251 <sect1> Paned Window Widgets
5252 <p>
5253 The paned window widgets are useful when you want to divide an area
5254 into two parts, with the relative size of the two parts controlled by
5255 the user. A groove is drawn between the two portions with a handle
5256 that the user can drag to change the ratio. The division can either be
5257 horizontal (HPaned) or vertical (VPaned).
5258    
5259 To create a new paned window, call one of:
5260    
5261 <tscreen><verb>
5262 GtkWidget *gtk_hpaned_new (void);
5263
5264 GtkWidget *gtk_vpaned_new (void);
5265 </verb></tscreen>
5266
5267 After creating the paned window widget, you need to add child widgets
5268 to its two halves. To do this, use the functions:
5269    
5270 <tscreen><verb>
5271 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
5272
5273 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
5274 </verb></tscreen>
5275    
5276 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
5277 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
5278 right or bottom half of the paned window.
5279
5280 A paned widget can be changed visually using the following two
5281 functions.
5282
5283 <tscreen><verb>
5284 void gtk_paned_set_handle_size( GtkPaned *paned,
5285                                 guint16   size);
5286
5287 void gtk_paned_set_gutter_size( GtkPaned *paned,
5288                                 guint16   size);
5289 </verb></tscreen>
5290
5291 The first of these sets the size of the handle and the second sets the
5292 size of the gutter that is between the two parts of the paned window.
5293
5294 As an example, we will create part of the user interface of an
5295 imaginary email program. A window is divided into two portions
5296 vertically, with the top portion being a list of email messages and
5297 the bottom portion the text of the email message. Most of the program
5298 is pretty straightforward. A couple of points to note: text can't be
5299 added to a Text widget until it is realized. This could be done by
5300 calling <tt/gtk_widget_realize()/, but as a demonstration of an
5301 alternate technique, we connect a handler to the "realize" signal to
5302 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
5303 of the items in the table containing the text window and its
5304 scrollbars, so that when the bottom portion is made smaller, the
5305 correct portions shrink instead of being pushed off the bottom of the
5306 window.
5307
5308 <tscreen><verb>
5309 /* example-start paned paned.c */
5310
5311 #include <gtk/gtk.h>
5312    
5313 /* Create the list of "messages" */
5314 GtkWidget *
5315 create_list (void)
5316 {
5317
5318     GtkWidget *scrolled_window;
5319     GtkWidget *list;
5320     GtkWidget *list_item;
5321    
5322     int i;
5323     char buffer[16];
5324    
5325     /* Create a new scrolled window, with scrollbars only if needed */
5326     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
5327     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
5328                                     GTK_POLICY_AUTOMATIC, 
5329                                     GTK_POLICY_AUTOMATIC);
5330    
5331     /* Create a new list and put it in the scrolled window */
5332     list = gtk_list_new ();
5333     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
5334                                            list);
5335     gtk_widget_show (list);
5336    
5337     /* Add some messages to the window */
5338     for (i=0; i<10; i++) {
5339
5340         sprintf(buffer,"Message #%d",i);
5341         list_item = gtk_list_item_new_with_label (buffer);
5342         gtk_container_add (GTK_CONTAINER(list), list_item);
5343         gtk_widget_show (list_item);
5344
5345     }
5346    
5347     return scrolled_window;
5348 }
5349    
5350 /* Add some text to our text widget - this is a callback that is invoked
5351 when our window is realized. We could also force our window to be
5352 realized with gtk_widget_realize, but it would have to be part of
5353 a hierarchy first */
5354
5355 void
5356 realize_text (GtkWidget *text, gpointer data)
5357 {
5358     gtk_text_freeze (GTK_TEXT (text));
5359     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
5360     "From: pathfinder@nasa.gov\n"
5361     "To: mom@nasa.gov\n"
5362     "Subject: Made it!\n"
5363     "\n"
5364     "We just got in this morning. The weather has been\n"
5365     "great - clear but cold, and there are lots of fun sights.\n"
5366     "Sojourner says hi. See you soon.\n"
5367     " -Path\n", -1);
5368    
5369     gtk_text_thaw (GTK_TEXT (text));
5370 }
5371    
5372 /* Create a scrolled text area that displays a "message" */
5373 GtkWidget *
5374 create_text (void)
5375 {
5376     GtkWidget *table;
5377     GtkWidget *text;
5378     GtkWidget *hscrollbar;
5379     GtkWidget *vscrollbar;
5380    
5381     /* Create a table to hold the text widget and scrollbars */
5382     table = gtk_table_new (2, 2, FALSE);
5383    
5384     /* Put a text widget in the upper left hand corner. Note the use of
5385      * GTK_SHRINK in the y direction */
5386     text = gtk_text_new (NULL, NULL);
5387     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
5388                       GTK_FILL | GTK_EXPAND,
5389                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
5390     gtk_widget_show (text);
5391    
5392     /* Put a HScrollbar in the lower left hand corner */
5393     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
5394     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
5395                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
5396     gtk_widget_show (hscrollbar);
5397    
5398     /* And a VScrollbar in the upper right */
5399     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
5400     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
5401                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
5402     gtk_widget_show (vscrollbar);
5403    
5404     /* Add a handler to put a message in the text widget when it is realized */
5405     gtk_signal_connect (GTK_OBJECT (text), "realize",
5406                         GTK_SIGNAL_FUNC (realize_text), NULL);
5407    
5408     return table;
5409 }
5410    
5411 int
5412 main (int argc, char *argv[])
5413 {
5414     GtkWidget *window;
5415     GtkWidget *vpaned;
5416     GtkWidget *list;
5417     GtkWidget *text;
5418
5419     gtk_init (&amp;argc, &amp;argv);
5420    
5421     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5422     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
5423     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5424                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5425     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5426     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
5427
5428     /* create a vpaned widget and add it to our toplevel window */
5429    
5430     vpaned = gtk_vpaned_new ();
5431     gtk_container_add (GTK_CONTAINER(window), vpaned);
5432     gtk_paned_set_handle_size (GTK_PANED(vpaned),
5433                                10);
5434     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
5435                                15);                       
5436     gtk_widget_show (vpaned);
5437    
5438     /* Now create the contents of the two halves of the window */
5439    
5440     list = create_list ();
5441     gtk_paned_add1 (GTK_PANED(vpaned), list);
5442     gtk_widget_show (list);
5443    
5444     text = create_text ();
5445     gtk_paned_add2 (GTK_PANED(vpaned), text);
5446     gtk_widget_show (text);
5447     gtk_widget_show (window);
5448     gtk_main ();
5449     return 0;
5450 }
5451 /* example-end */
5452 </verb></tscreen>
5453
5454 <!-- ----------------------------------------------------------------- -->   
5455 <sect1>Toolbar
5456 <p>
5457 Toolbars are usually used to group some number of widgets in order to
5458 simplify customization of their look and layout. Typically a toolbar
5459 consists of buttons with icons, labels and tooltips, but any other
5460 widget can also be put inside a toolbar. Finally, items can be
5461 arranged horizontally or vertically and buttons can be displayed with
5462 icons, labels or both.
5463
5464 Creating a toolbar is (as one may already suspect) done with the
5465 following function:
5466
5467 <tscreen><verb>
5468 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
5469                             GtkToolbarStyle  style );
5470 </verb></tscreen>
5471
5472 where orientation may be one of:
5473
5474 <tscreen><verb>
5475   GTK_ORIENTATION_HORIZONTAL    
5476   GTK_ORIENTATION_VERTICAL
5477 </verb></tscreen>
5478
5479 and style one of:
5480
5481 <tscreen><verb>
5482   GTK_TOOLBAR_TEXT
5483   GTK_TOOLBAR_ICONS
5484   GTK_TOOLBAR_BOTH
5485 </verb></tscreen>
5486
5487 The style applies to all the buttons created with the `item' functions
5488 (not to buttons inserted into toolbar as separate widgets).
5489
5490 After creating a toolbar one can append, prepend and insert items
5491 (that means simple buttons) into the toolbar. To describe an item we
5492 need a label text, a tooltip text, a private tooltip text, an icon for
5493 the button and a callback function for it. For example, to append or
5494 prepend an item you may use the following functions:
5495
5496 <tscreen><verb>
5497 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
5498                                     const char    *text,
5499                                     const char    *tooltip_text,
5500                                     const char    *tooltip_private_text,
5501                                     GtkWidget     *icon,
5502                                     GtkSignalFunc  callback,
5503                                     gpointer       user_data );
5504
5505 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
5506                                      const char    *text,
5507                                      const char    *tooltip_text,
5508                                      const char    *tooltip_private_text,
5509                                      GtkWidget     *icon,
5510                                      GtkSignalFunc  callback,
5511                                      gpointer       user_data );
5512 </verb></tscreen>
5513
5514 If you want to use gtk_toolbar_insert_item, the only additional
5515 parameter which must be specified is the position in which the item
5516 should be inserted, thus:
5517
5518 <tscreen><verb>
5519 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
5520                                     const char    *text,
5521                                     const char    *tooltip_text,
5522                                     const char    *tooltip_private_text,
5523                                     GtkWidget     *icon,
5524                                     GtkSignalFunc  callback,
5525                                     gpointer       user_data,
5526                                     gint           position );
5527 </verb></tscreen>
5528
5529 To simplify adding spaces between toolbar items, you may use the
5530 following functions:
5531
5532 <tscreen><verb>
5533 void gtk_toolbar_append_space( GtkToolbar *toolbar );
5534
5535 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
5536
5537 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
5538                                gint        position );
5539  
5540 </verb></tscreen>
5541
5542 While the size of the added space can be set globally for a
5543 whole toolbar with the function:
5544
5545 <tscreen><verb>
5546 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
5547                                  gint        space_size) ;
5548 </verb></tscreen>
5549
5550 If it's required, the orientation of a toolbar and its style can be
5551 changed `on the fly' using the following functions:
5552
5553 <tscreen><verb>
5554 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
5555                                   GtkOrientation  orientation );
5556
5557 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
5558                             GtkToolbarStyle  style );
5559
5560 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
5561                                gint        enable );
5562 </verb></tscreen>
5563
5564 Where <tt/orientation/ is one of GTK_ORIENTATION_HORIZONTAL or
5565 GTK_ORIENTATION_VERTICAL. The <tt/style/ is used to set appearance of
5566 the toolbar items by using one of GTK_TOOLBAR_ICONS, GTK_TOOLBAR_TEXT
5567 or GTK_TOOLBAR_BOTH.
5568
5569 To show some other things that can be done with a toolbar, let's take
5570 the following program (we'll interrupt the listing with some
5571 additional explanations):
5572
5573 <tscreen><verb>
5574 #include <gtk/gtk.h>
5575
5576 #include "gtk.xpm"
5577
5578 /* This function is connected to the Close button or
5579  * closing the window from the WM */
5580 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
5581 {
5582   gtk_main_quit ();
5583 }
5584 </verb></tscreen>
5585
5586 The above beginning seems for sure familiar to you if it's not your first
5587 GTK program. There is one additional thing though, we include a nice XPM
5588 picture to serve as an icon for all of the buttons.
5589
5590 <tscreen><verb>
5591 GtkWidget* close_button; // this button will emit signal to close application
5592 GtkWidget* tooltips_button; // to enable/disable tooltips
5593 GtkWidget* text_button,
5594          * icon_button,
5595          * both_button; // radio buttons for toolbar style
5596 GtkWidget* entry; // a text entry to show packing any widget into toolbar
5597 </verb></tscreen>
5598
5599 In fact not all of the above widgets are needed here, but to make things
5600 clearer I put them all together.
5601
5602 <tscreen><verb>
5603 /* that's easy... when one of the buttons is toggled, we just
5604  * check which one is active and set the style of the toolbar
5605  * accordingly
5606  * ATTENTION: our toolbar is passed as data to callback ! */
5607 void radio_event (GtkWidget *widget, gpointer data)
5608 {
5609   if (GTK_TOGGLE_BUTTON (text_button)->active) 
5610     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
5611   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
5612     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
5613   else if (GTK_TOGGLE_BUTTON (both_button)->active)
5614     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
5615 }
5616
5617 /* even easier, just check given toggle button and enable/disable 
5618  * tooltips */
5619 void toggle_event (GtkWidget *widget, gpointer data)
5620 {
5621   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
5622                             GTK_TOGGLE_BUTTON (widget)->active );
5623 }
5624 </verb></tscreen>
5625
5626 The above are just two callback functions that will be called when
5627 one of the buttons on a toolbar is pressed. You should already be
5628 familiar with things like this if you've already used toggle buttons (and
5629 radio buttons).
5630
5631 <tscreen><verb>
5632 int main (int argc, char *argv[])
5633 {
5634   /* Here is our main window (a dialog) and a handle for the handlebox */
5635   GtkWidget* dialog;
5636   GtkWidget* handlebox;
5637
5638   /* Ok, we need a toolbar, an icon with a mask (one for all of 
5639      the buttons) and an icon widget to put this icon in (but 
5640      we'll create a separate widget for each button) */
5641   GtkWidget * toolbar;
5642   GdkPixmap * icon;
5643   GdkBitmap * mask;
5644   GtkWidget * iconw;
5645
5646   /* this is called in all GTK application. */
5647   gtk_init (&amp;argc, &amp;argv);
5648   
5649   /* create a new window with a given title, and nice size */
5650   dialog = gtk_dialog_new ();
5651   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
5652   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
5653   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
5654
5655   /* typically we quit if someone tries to close us */
5656   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
5657                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
5658
5659   /* we need to realize the window because we use pixmaps for 
5660    * items on the toolbar in the context of it */
5661   gtk_widget_realize ( dialog );
5662
5663   /* to make it nice we'll put the toolbar into the handle box, 
5664    * so that it can be detached from the main window */
5665   handlebox = gtk_handle_box_new ();
5666   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
5667                        handlebox, FALSE, FALSE, 5 );
5668 </verb></tscreen>
5669
5670 The above should be similar to any other GTK application. Just
5671 initialization of GTK, creating the window etc.. There is only one
5672 thing that probably needs some explanation: a handle box. A handle box
5673 is just another box that can be used to pack widgets in to. The
5674 difference between it and typical boxes is that it can be detached
5675 from a parent window (or, in fact, the handle box remains in the
5676 parent, but it is reduced to a very small rectangle, while all of its
5677 contents are reparented to a new freely floating window). It is
5678 usually nice to have a detachable toolbar, so these two widgets occur
5679 together quite often.
5680
5681 <tscreen><verb>
5682   /* toolbar will be horizontal, with both icons and text, and
5683    * with 5pxl spaces between items and finally, 
5684    * we'll also put it into our handlebox */
5685   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
5686                               GTK_TOOLBAR_BOTH );
5687   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
5688   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
5689   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
5690
5691   /* now we create icon with mask: we'll reuse it to create
5692    * icon widgets for toolbar items */
5693   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
5694       &amp;dialog->style->white, gtk_xpm );
5695 </verb></tscreen>
5696
5697 Well, what we do above is just a straight-forward initialization of
5698 the toolbar widget and creation of a GDK pixmap with its mask. If you
5699 want to know something more about using pixmaps, refer to GDK
5700 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
5701 earlier in this tutorial.
5702
5703 <tscreen><verb>
5704   /* our first item is <close> button */
5705   iconw = gtk_pixmap_new ( icon, mask ); // icon widget
5706   close_button = 
5707     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), // our toolbar
5708                               "Close",               // button label
5709                               "Closes this app",     // tooltip for this button
5710                               "Private",             // tooltip private string
5711                               iconw,                 // icon widget
5712                               GTK_SIGNAL_FUNC (delete_event), // a signal
5713                               NULL );
5714   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); // space after item
5715 </verb></tscreen>
5716
5717 In the above code you see the simplest case: adding a button to
5718 toolbar.  Just before appending a new item, we have to construct a
5719 pixmap widget to serve as an icon for this item; this step will have
5720 to be repeated for each new item. Just after the item we also add a
5721 space, so the following items will not touch each other. As you see
5722 gtk_toolbar_append_item returns a pointer to our newly created button
5723 widget, so that we can work with it in the normal way.
5724
5725 <tscreen><verb>
5726   /* now, let's make our radio buttons group... */
5727   iconw = gtk_pixmap_new ( icon, mask );
5728   icon_button = 
5729     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5730                                GTK_TOOLBAR_CHILD_RADIOBUTTON, // a type of element
5731                                NULL,                          // pointer to widget
5732                                "Icon",                        // label
5733                                "Only icons in toolbar",       // tooltip
5734                                "Private",                     // tooltip private string
5735                                iconw,                         // icon
5736                                GTK_SIGNAL_FUNC (radio_event), // signal
5737                                toolbar);                      // data for signal
5738   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5739 </verb></tscreen>
5740
5741 Here we begin creating a radio buttons group. To do this we use
5742 gtk_toolbar_append_element.  In fact, using this function one can also
5743 add simple items or even spaces (type = GTK_TOOLBAR_CHILD_SPACE or
5744 GTK_TOOLBAR_CHILD_BUTTON). In the above case we start creating a radio
5745 group. In creating other radio buttons for this group a pointer to the
5746 previous button in the group is required, so that a list of buttons
5747 can be easily constructed (see the section on <ref
5748 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
5749 tutorial).
5750
5751 <tscreen><verb>
5752   /* following radio buttons refer to previous ones */
5753   iconw = gtk_pixmap_new ( icon, mask );
5754   text_button = 
5755     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5756                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
5757                                icon_button,
5758                                "Text",
5759                                "Only texts in toolbar",
5760                                "Private",
5761                                iconw,
5762                                GTK_SIGNAL_FUNC (radio_event),
5763                                toolbar);
5764   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5765                                           
5766   iconw = gtk_pixmap_new ( icon, mask );
5767   both_button = 
5768     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5769                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
5770                                text_button,
5771                                "Both",
5772                                "Icons and text in toolbar",
5773                                "Private",
5774                                iconw,
5775                                GTK_SIGNAL_FUNC (radio_event),
5776                                toolbar);
5777   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5778   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
5779 </verb></tscreen>
5780
5781 In the end we have set the state of one of the buttons manually (otherwise
5782 they all stay in active state, preventing us from switching between them).
5783
5784 <tscreen><verb>
5785   /* here we have just a simple toggle button */
5786   iconw = gtk_pixmap_new ( icon, mask );
5787   tooltips_button = 
5788     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
5789                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
5790                                NULL,
5791                                "Tooltips",
5792                                "Toolbar with or without tips",
5793                                "Private",
5794                                iconw,
5795                                GTK_SIGNAL_FUNC (toggle_event),
5796                                toolbar);
5797   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
5798   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
5799 </verb></tscreen>
5800
5801 A toggle button can be created in the obvious way (if one knows how to create
5802 radio buttons already).
5803
5804 <tscreen><verb>
5805   /* to pack a widget into toolbar, we only have to 
5806    * create it and append it with an appropriate tooltip */
5807   entry = gtk_entry_new ();
5808   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
5809                              entry, 
5810                              "This is just an entry", 
5811                              "Private" );
5812
5813   /* well, it isn't created within thetoolbar, so we must still show it */
5814   gtk_widget_show ( entry );
5815 </verb></tscreen>
5816
5817 As you see, adding any kind of widget to a toolbar is simple. The
5818 one thing you have to remember is that this widget must be shown manually
5819 (contrary to other items which will be shown together with the toolbar).
5820
5821 <tscreen><verb>
5822   /* that's it ! let's show everything. */
5823   gtk_widget_show ( toolbar );
5824   gtk_widget_show (handlebox);
5825   gtk_widget_show ( dialog );
5826
5827   /* rest in gtk_main and wait for the fun to begin! */
5828   gtk_main ();
5829   
5830   return 0;
5831 }
5832 </verb></tscreen>
5833
5834 So, here we are at the end of toolbar tutorial. Of course, to appreciate
5835 it in full you need also this nice XPM icon, so here it is:
5836
5837 <tscreen><verb>
5838 /* XPM */
5839 static char * gtk_xpm[] = {
5840 "32 39 5 1",
5841 ".      c none",
5842 "+      c black",
5843 "@      c #3070E0",
5844 "#      c #F05050",
5845 "$      c #35E035",
5846 "................+...............",
5847 "..............+++++.............",
5848 "............+++++@@++...........",
5849 "..........+++++@@@@@@++.........",
5850 "........++++@@@@@@@@@@++........",
5851 "......++++@@++++++++@@@++.......",
5852 ".....+++@@@+++++++++++@@@++.....",
5853 "...+++@@@@+++@@@@@@++++@@@@+....",
5854 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
5855 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
5856 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
5857 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
5858 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
5859 ".+####+++@@@+++++++@@@@@+@$$$$@.",
5860 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
5861 ".+######++++@@@@@@@++@$$$$$$$$+.",
5862 ".+#######+##+@@@@+++$$$$$$@@$$+.",
5863 ".+###+++##+##+@@++@$$$$$$++$$$+.",
5864 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
5865 ".+###++++++#+++@$$@+@$$@++$$$@+.",
5866 ".+####+++++++#++$$@+@$$++$$$$+..",
5867 ".++####++++++#++$$@+@$++@$$$$+..",
5868 ".+#####+++++##++$$++@+++$$$$$+..",
5869 ".++####+++##+#++$$+++++@$$$$$+..",
5870 ".++####+++####++$$++++++@$$$@+..",
5871 ".+#####++#####++$$+++@++++@$@+..",
5872 ".+#####++#####++$$++@$$@+++$@@..",
5873 ".++####++#####++$$++$$$$$+@$@++.",
5874 ".++####++#####++$$++$$$$$$$$+++.",
5875 ".+++####+#####++$$++$$$$$$$@+++.",
5876 "..+++#########+@$$+@$$$$$$+++...",
5877 "...+++########+@$$$$$$$$@+++....",
5878 ".....+++######+@$$$$$$$+++......",
5879 "......+++#####+@$$$$$@++........",
5880 ".......+++####+@$$$$+++.........",
5881 ".........++###+$$$@++...........",
5882 "..........++##+$@+++............",
5883 "...........+++++++..............",
5884 ".............++++..............."};
5885 </verb></tscreen>
5886
5887 <!-- ----------------------------------------------------------------- -->   
5888 <sect1> Aspect Frames
5889 <p>
5890 The aspect frame widget is like a frame widget, except that it also
5891 enforces the aspect ratio (that is, the ratio of the width to the
5892 height) of the child widget to have a certain value, adding extra
5893 space if necessary. This is useful, for instance, if you want to
5894 preview a larger image. The size of the preview should vary when the
5895 user resizes the window, but the aspect ratio needs to always match
5896 the original image.
5897   
5898 To create a new aspect frame use:
5899    
5900 <tscreen><verb>
5901 GtkWidget *gtk_aspect_frame_new( const gchar *label,
5902                                  gfloat       xalign,
5903                                  gfloat       yalign,
5904                                  gfloat       ratio,
5905                                  gint         obey_child);
5906 </verb></tscreen>
5907    
5908 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
5909 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
5910 widget will match the aspect ratio of the ideal size it requests.
5911 Otherwise, it is given by <tt/ratio/.
5912    
5913 To change the options of an existing aspect frame, you can use:
5914    
5915 <tscreen><verb>
5916 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
5917                            gfloat          xalign,
5918                            gfloat          yalign,
5919                            gfloat          ratio,
5920                            gint            obey_child);
5921 </verb></tscreen>
5922    
5923 As an example, the following program uses an AspectFrame to present a
5924 drawing area whose aspect ratio will always be 2:1, no matter how the
5925 user resizes the top-level window.
5926    
5927 <tscreen><verb>
5928 /* example-start aspectframe aspectframe.c */
5929
5930 #include <gtk/gtk.h>
5931    
5932 int
5933 main (int argc, char *argv[])
5934 {
5935     GtkWidget *window;
5936     GtkWidget *aspect_frame;
5937     GtkWidget *drawing_area;
5938     gtk_init (&amp;argc, &amp;argv);
5939    
5940     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5941     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
5942     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5943                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5944     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5945    
5946     /* Create an aspect_frame and add it to our toplevel window */
5947    
5948     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
5949                                          0.5, /* center x */
5950                                          0.5, /* center y */
5951                                          2, /* xsize/ysize = 2 */
5952                                          FALSE /* ignore child's aspect */);
5953    
5954     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
5955     gtk_widget_show (aspect_frame);
5956    
5957     /* Now add a child widget to the aspect frame */
5958    
5959     drawing_area = gtk_drawing_area_new ();
5960    
5961     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
5962      * window since we are forcing a 2x1 aspect ratio */
5963     gtk_widget_set_usize (drawing_area, 200, 200);
5964     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
5965     gtk_widget_show (drawing_area);
5966    
5967     gtk_widget_show (window);
5968     gtk_main ();
5969     return 0;
5970 }
5971 /* example-end */
5972 </verb></tscreen>
5973
5974 <!-- ----------------------------------------------------------------- -->   
5975 <sect1>The EventBox <label id="sec_EventBox">
5976 <p> 
5977 Some gtk widgets don't have associated X windows, so they just draw on
5978 their parents. Because of this, they cannot receive events and if they
5979 are incorrectly sized, they don't clip so you can get messy
5980 overwriting etc. If you require more from these widgets, the EventBox
5981 is for you.
5982
5983 At first glance, the EventBox widget might appear to be totally
5984 useless. It draws nothing on the screen and responds to no
5985 events. However, it does serve a function - it provides an X window
5986 for its child widget. This is important as many GTK widgets do not
5987 have an associated X window. Not having an X window saves memory and
5988 improves performance, but also has some drawbacks. A widget without an
5989 X window cannot receive events, and does not perform any clipping on
5990 its contents. Although the name <em/EventBox/ emphasizes the
5991 event-handling function, the widget can also be used for clipping.
5992 (and more, see the example below).
5993
5994 To create a new EventBox widget, use:
5995
5996 <tscreen><verb>
5997 GtkWidget *gtk_event_box_new( void );
5998 </verb></tscreen>
5999
6000 A child widget can then be added to this EventBox:
6001
6002 <tscreen><verb>
6003 gtk_container_add( GTK_CONTAINER(event_box), widget );
6004 </verb></tscreen>
6005
6006 The following example demonstrates both uses of an EventBox - a label
6007 is created that is clipped to a small box, and set up so that a
6008 mouse-click on the label causes the program to exit. Resizing the
6009 window reveals varying amounts of the label.
6010
6011 <tscreen><verb>
6012 /* example-start eventbox eventbox.c */
6013
6014 #include <gtk/gtk.h>
6015
6016 int 
6017 main (int argc, char *argv[])
6018 {
6019     GtkWidget *window;
6020     GtkWidget *event_box;
6021     GtkWidget *label;
6022     
6023     gtk_init (&amp;argc, &amp;argv);
6024     
6025     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6026     
6027     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6028     
6029     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6030                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
6031     
6032     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6033     
6034     /* Create an EventBox and add it to our toplevel window */
6035     
6036     event_box = gtk_event_box_new ();
6037     gtk_container_add (GTK_CONTAINER(window), event_box);
6038     gtk_widget_show (event_box);
6039     
6040     /* Create a long label */
6041     
6042     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
6043     gtk_container_add (GTK_CONTAINER (event_box), label);
6044     gtk_widget_show (label);
6045     
6046     /* Clip it short. */
6047     gtk_widget_set_usize (label, 110, 20);
6048     
6049     /* And bind an action to it */
6050     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
6051     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
6052                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
6053     
6054     /* Yet one more thing you need an X window for ... */
6055     
6056     gtk_widget_realize (event_box);
6057     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
6058     
6059     gtk_widget_show (window);
6060     
6061     gtk_main ();
6062     
6063     return(0);
6064 }
6065 /* example-end */
6066 </verb></tscreen>
6067
6068 <!-- ***************************************************************** -->
6069 <sect>CList Widget
6070 <!-- ***************************************************************** -->
6071
6072 <!-- ----------------------------------------------------------------- -->
6073 <p>
6074 The GtkCList widget has replaced the GtkList widget (which is still
6075 available).
6076
6077 The GtkCList widget is a multi-column list widget that is capable of
6078 handling literally thousands of rows of information. Each column can
6079 optionally have a title, which itself is optionally active, allowing
6080 us to bind a function to its selection.
6081
6082 <!-- ----------------------------------------------------------------- -->
6083 <sect1>Creating a GtkCList widget
6084 <p>
6085 Creating a GtkCList is quite straightforward, once you have learned
6086 about widgets in general. It provides the almost standard two ways,
6087 that is the hard way, and the easy way. But before we create it, there
6088 is one thing we should figure out beforehand: how many columns should
6089 it have?
6090
6091 Not all columns have to be visible and can be used to store data that
6092 is related to a certain cell in the list.
6093
6094 <tscreen><verb>
6095 GtkWidget *gtk_clist_new ( gint columns );
6096
6097 GtkWidget *gtk_clist_new_with_titles( gint   columns,
6098                                       gchar *titles[] );
6099 </verb></tscreen>
6100
6101 The first form is very straight forward, the second might require some
6102 explanation. Each column can have a title associated with it, and this
6103 title can be a label or a button that reacts when we click on it. If
6104 we use the second form, we must provide pointers to the title texts,
6105 and the number of pointers should equal the number of columns
6106 specified. Of course we can always use the first form, and manually
6107 add titles later.
6108
6109 Note: the GtkCList widget does not have it's own scrollbars and should
6110 be placed within a GtkScrolledWindow widget if your require this
6111 functionality. This is a change from the GTK 1.0 implementation.
6112
6113 <!-- ----------------------------------------------------------------- -->
6114 <sect1>Modes of operation
6115 <p>
6116 There are several attributes that can be used to alter the behaviour of
6117 a GtkCList. First there is
6118
6119 <tscreen><verb>
6120 void gtk_clist_set_selection_mode( GtkCList         *clist,
6121                                    GtkSelectionMode  mode );
6122 </verb></tscreen>
6123
6124 which, as the name implies, sets the selection mode of the GtkCList. The first
6125 argument is the GtkCList widget, and the second specifies the cell selection
6126 mode (they are defined in gtkenums.h). At the time of this writing, the following
6127 modes are available to us:
6128
6129 <itemize>
6130 <item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
6131 pointer for a single selected item.
6132
6133 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list contains no
6134 widgets or insensitive ones only, otherwise it contains a GList pointer for
6135 one GList structure, and therefore exactly one list item.
6136
6137 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list items are
6138 selected or a GList pointer for the first selected item. That in turn points
6139 to a GList structure for the second selected item and so on. This is currently
6140 the <bf>default</bf> for the GtkCList widget.
6141
6142 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
6143 </itemize>
6144
6145 Others might be added in later revisions of GTK.
6146
6147 We can also define what the border of the GtkCList widget should look
6148 like. It is done through
6149
6150 <tscreen><verb>
6151 void gtk_clist_set_shadow_type( GtkCList      *clist,
6152                                 GtkShadowType  border );
6153 </verb></tscreen>
6154
6155 And the possible values for the second argument are
6156
6157 <itemize>
6158 <item> GTK_SHADOW_NONE
6159
6160 <item> GTK_SHADOW_IN
6161
6162 <item> GTK_SHADOW_OUT
6163
6164 <item> GTK_SHADOW_ETCHED_IN
6165
6166 <item> GTK_SHADOW_ETCHED_OUT
6167 </itemize>
6168
6169 <!-- ----------------------------------------------------------------- -->
6170 <sect1>Working with titles
6171 <p>
6172 When you create a GtkCList widget, you will also get a set of title
6173 buttons automatically. They live in the top of the CList window, and
6174 can act either as normal buttons that respond to being pressed, or
6175 they can be passive, in which case they are nothing more than a
6176 title. There are four different calls that aid us in setting the
6177 status of the title buttons.
6178
6179 <tscreen><verb>
6180 void gtk_clist_column_title_active( GtkCList *clist,
6181                                      gint     column );
6182
6183 void gtk_clist_column_title_passive( GtkCList *clist,
6184                                      gint      column );
6185
6186 void gtk_clist_column_titles_active( GtkCList *clist );
6187
6188 void gtk_clist_column_titles_passive( GtkCList *clist );
6189 </verb></tscreen>
6190
6191 An active title is one which acts as a normal button, a passive one is
6192 just a label. The first two calls above will activate/deactivate the
6193 title button above the specific column, while the last two calls
6194 activate/deactivate all title buttons in the supplied clist widget.
6195
6196 But of course there are those cases when we don't want them at all,
6197 and so they can be hidden and shown at will using the following two
6198 calls.
6199
6200 <tscreen><verb>
6201 void gtk_clist_column_titles_show( GtkCList *clist );
6202
6203 void gtk_clist_column_titles_hide( GtkCList *clist );
6204 </verb></tscreen>
6205
6206 For titles to be really useful we need a mechanism to set and change
6207 them, and this is done using
6208
6209 <tscreen><verb>
6210 void gtk_clist_set_column_title( GtkCList *clist,
6211                                  gint      column,
6212                                  gchar    *title );
6213 </verb></tscreen>
6214
6215 Note that only the title of one column can be set at a time, so if all
6216 the titles are known from the beginning, then I really suggest using
6217 gtk_clist_new_with_titles (as described above) to set them. Saves you
6218 coding time, and makes your program smaller. There are some cases
6219 where getting the job done the manual way is better, and that's when
6220 not all titles will be text. GtkCList provides us with title buttons
6221 that can in fact incorporate whole widgets, for example a pixmap. It's
6222 all done through
6223
6224 <tscreen><verb>
6225 void gtk_clist_set_column_widget( GtkCList  *clist,
6226                                   gint       column,
6227                                   GtkWidget *widget );
6228 </verb></tscreen>
6229
6230 which should require no special explanation.
6231
6232 <!-- ----------------------------------------------------------------- -->
6233 <sect1>Manipulating the list itself
6234 <p>
6235 It is possible to change the justification for a column, and it is
6236 done through
6237
6238 <tscreen><verb>
6239 void gtk_clist_set_column_justification( GtkCList         *clist,
6240                                          gint              column,
6241                                          GtkJustification  justification );
6242 </verb></tscreen>
6243
6244 The GtkJustification type can take the following values:
6245
6246 <itemize>
6247 <item>GTK_JUSTIFY_LEFT - The text in the column will begin from the
6248 left edge.
6249
6250 <item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the
6251 right edge.
6252
6253 <item>GTK_JUSTIFY_CENTER - The text is placed in the center of the
6254 column.
6255
6256 <item>GTK_JUSTIFY_FILL - The text will use up all available space in
6257 the column. It is normally done by inserting extra blank spaces
6258 between words (or between individual letters if it's a single
6259 word). Much in the same way as any ordinary WYSIWYG text editor.
6260 </itemize>
6261
6262 The next function is a very important one, and should be standard in
6263 the setup of all GtkCList widgets. When the list is created, the width
6264 of the various columns are chosen to match their titles, and since
6265 this is seldom the right width we have to set it using
6266
6267 <tscreen><verb>
6268 void gtk_clist_set_column_width( GtkCList *clist,
6269                                  gint      column,
6270                                  gint      width );
6271 </verb></tscreen>
6272
6273 Note that the width is given in pixels and not letters. The same goes
6274 for the height of the cells in the columns, but as the default value
6275 is the height of the current font this isn't as critical to the
6276 application. Still, it is done through
6277
6278 <tscreen><verb>
6279 void gtk_clist_set_row_height( GtkCList *clist,
6280                                gint      height );
6281 </verb></tscreen>
6282
6283 Again, note that the height is given in pixels.
6284
6285 We can also move the list around without user interaction, however, it
6286 does require that we know what we are looking for. Or in other words,
6287 we need the row and column of the item we want to scroll to.
6288
6289 <tscreen><verb>
6290 void gtk_clist_moveto( GtkCList *clist,
6291                        gint      row,
6292                        gint      column,
6293                        gfloat    row_align,
6294                        gfloat    col_align );
6295 </verb></tscreen>
6296
6297 The gfloat row_align is pretty important to understand. It's a value
6298 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
6299 the row appears at the top, while if the value of row_align is 1.0,
6300 the row will appear at the bottom instead. All other values between
6301 0.0 and 1.0 are also valid and will place the row between the top and
6302 the bottom. The last argument, gfloat col_align works in the same way,
6303 though 0.0 marks left and 1.0 marks right instead.
6304
6305 Depending on the application's needs, we don't have to scroll to an
6306 item that is already visible to us. So how do we know if it is
6307 visible? As usual, there is a function to find that out as well.
6308
6309 <tscreen><verb>
6310 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
6311                                         gint      row );
6312 </verb></tscreen>
6313
6314 The return value is is one of the following:
6315
6316 <itemize>
6317 <item>GTK_VISIBILITY_NONE
6318
6319 <item>GTK_VISIBILITY_PARTIAL
6320
6321 <item>GTK_VISIBILITY_FULL
6322 </itemize>
6323
6324 Note that it will only tell us if a row is visible. Currently there is
6325 no way to determine this for a column. We can get partial information
6326 though, because if the return is GTK_VISIBILITY_PARTIAL, then some of
6327 it is hidden, but we don't know if it is the row that is being cut by
6328 the lower edge of the listbox, or if the row has columns that are
6329 outside.
6330
6331 We can also change both the foreground and background colors of a
6332 particular row. This is useful for marking the row selected by the
6333 user, and the two functions that is used to do it are
6334
6335 <tscreen><verb>
6336 void gtk_clist_set_foreground( GtkCList *clist,
6337                                gint      row,
6338                                GdkColor *color );
6339
6340 void gtk_clist_set_background( GtkCList *clist,
6341                                gint      row,
6342                                GdkColor *color );
6343 </verb></tscreen>
6344
6345 Please note that the colors must have been previously allocated.
6346
6347 <!-- ----------------------------------------------------------------- -->
6348 <sect1>Adding rows to the list
6349 <p>
6350 We can add rows in three ways. They can be prepended or appended to
6351 the list using
6352
6353 <tscreen><verb>
6354 gint gtk_clist_prepend( GtkCList *clist,
6355                         gchar    *text[] );
6356
6357 gint gtk_clist_append( GtkCList *clist,
6358                        gchar    *text[] );
6359 </verb></tscreen>
6360
6361 The return value of these two functions indicate the index of the row
6362 that was just added. We can insert a row at a given place using
6363
6364 <tscreen><verb>
6365 void gtk_clist_insert( GtkCList *clist,
6366                        gint      row,
6367                        gchar    *text[] );
6368 </verb></tscreen>
6369
6370 In these calls we have to provide a collection of pointers that are
6371 the texts we want to put in the columns. The number of pointers should
6372 equal the number of columns in the list. If the text[] argument is
6373 NULL, then there will be no text in the columns of the row. This is
6374 useful, for example, if we want to add pixmaps instead (something that
6375 has to be done manually).
6376
6377 Also, please note that the numbering of both rows and columns start at 0.
6378
6379 To remove an individual row we use
6380
6381 <tscreen><verb>
6382 void gtk_clist_remove( GtkCList *clist,
6383                        gint      row );
6384 </verb></tscreen>
6385
6386 There is also a call that removes all rows in the list. This is a lot
6387 faster than calling gtk_clist_remove once for each row, which is the
6388 only alternative.
6389
6390 <tscreen><verb>
6391 void gtk_clist_clear( GtkCList *clist );
6392 </verb></tscreen>
6393
6394 There are also two convenience functions that should be used when a
6395 lot of changes have to be made to the list. This is to prevent the
6396 list flickering while being repeatedly updated, which may be highly
6397 annoying to the user. So instead it is a good idea to freeze the list,
6398 do the updates to it, and finally thaw it which causes the list to be
6399 updated on the screen.
6400
6401 <tscreen><verb>
6402 void gtk_clist_freeze( GtkCList * clist );
6403
6404 void gtk_clist_thaw( GtkCList * clist );
6405 </verb></tscreen>
6406
6407 <!-- ----------------------------------------------------------------- -->
6408 <sect1>Setting text and pixmaps in the cells
6409 <p>
6410 A cell can contain a pixmap, text or both. To set them the following
6411 functions are used.
6412
6413 <tscreen><verb>
6414 void gtk_clist_set_text( GtkCList *clist,
6415                          gint      row,
6416                          gint      column,
6417                          gchar    *text );
6418
6419 void gtk_clist_set_pixmap( GtkCList  *clist,
6420                            gint       row,
6421                            gint       column,
6422                            GdkPixmap *pixmap,
6423                            GdkBitmap *mask );
6424
6425 void gtk_clist_set_pixtext( GtkCList  *clist,
6426                             gint       row,
6427                             gint       column,
6428                             gchar     *text,
6429                             guint8     spacing,
6430                             GdkPixmap *pixmap,
6431                             GdkBitmap *mask );
6432 </verb></tscreen>
6433
6434 It's quite straightforward. All the calls have the GtkCList as the
6435 first argument, followed by the row and column of the cell, followed
6436 by the data to be set. The <tt/spacing/ argument in
6437 gtk_clist_set_pixtext is the number of pixels between the pixmap and
6438 the beginning of the text.
6439
6440 To read back the data, we instead use
6441
6442 <tscreen><verb>
6443 gint gtk_clist_get_text( GtkCList  *clist,
6444                          gint       row,
6445                          gint       column,
6446                          gchar    **text );
6447
6448 gint gtk_clist_get_pixmap( GtkCList   *clist,
6449                            gint        row,
6450                            gint        column,
6451                            GdkPixmap **pixmap,
6452                            GdkBitmap **mask );
6453
6454 gint gtk_clist_get_pixtext( GtkCList   *clist,
6455                             gint        row,
6456                             gint        column,
6457                             gchar     **text,
6458                             guint8     *spacing,
6459                             GdkPixmap **pixmap,
6460                             GdkBitmap **mask );
6461 </verb></tscreen>
6462
6463 It isn't necessary to read it all back in case you aren't
6464 interested. Any of the pointers that are meant for return values (all
6465 except the clist) can be NULL. So if we want to read back only the
6466 text from a cell that is of type pixtext, then we would do the
6467 following, assuming that clist, row and column already exist:
6468
6469 <tscreen><verb>
6470 gchar *mytext;
6471
6472 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
6473 </verb></tscreen>
6474
6475 There is one more call that is related to what's inside a cell in the
6476 clist, and that's
6477
6478 <tscreen><verb>
6479 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
6480                                      gint      row,
6481                                      gint      column );
6482 </verb></tscreen>
6483
6484 which returns the type of data in a cell. The return value is one of
6485
6486 <itemize>
6487 <item>GTK_CELL_EMPTY
6488
6489 <item>GTK_CELL_TEXT
6490
6491 <item>GTK_CELL_PIXMAP
6492
6493 <item>GTK_CELL_PIXTEXT
6494
6495 <item>GTK_CELL_WIDGET
6496 </itemize>
6497
6498 There is also a function that will let us set the indentation, both
6499 vertical and horizontal, of a cell. The indentation value is of type
6500 gint, given in pixels, and can be both positive and negative.
6501
6502 <tscreen><verb>
6503 void gtk_clist_set_shift( GtkCList *clist,
6504                           gint      row,
6505                           gint      column,
6506                           gint      vertical,
6507                           gint      horizontal );
6508 </verb></tscreen>
6509
6510 <!-- ----------------------------------------------------------------- -->
6511 <sect1>Storing data pointers
6512 <p>
6513 With a GtkCList it is possible to set a data pointer for a row. This
6514 pointer will not be visible for the user, but is merely a convenience
6515 for the programmer to associate a row with a pointer to some
6516 additional data.
6517
6518 The functions should be fairly self-explanatory by now
6519
6520 <tscreen><verb>
6521 void gtk_clist_set_row_data( GtkCList *clist,
6522                              gint      row,
6523                              gpointer  data );
6524
6525 void gtk_clist_set_row_data_full( GtkCList         *clist,
6526                                   gint              row,
6527                                   gpointer          data,
6528                                   GtkDestroyNotify  destroy );
6529
6530 gpointer gtk_clist_get_row_data( GtkCList *clist,
6531                                  gint      row );
6532
6533 gint gtk_clist_find_row_from_data( GtkCList *clist,
6534                                    gpointer  data );
6535 </verb></tscreen>
6536
6537 <!-- ----------------------------------------------------------------- -->
6538 <sect1>Working with selections
6539 <p>
6540 There are also functions available that let us force the (un)selection
6541 of a row. These are
6542
6543 <tscreen><verb>
6544 void gtk_clist_select_row( GtkCList *clist,
6545                            gint      row,
6546                            gint      column );
6547
6548 void gtk_clist_unselect_row( GtkCList *clist,
6549                              gint      row,
6550                              gint      column );
6551 </verb></tscreen>
6552
6553 And also a function that will take x and y coordinates (for example,
6554 read from the mousepointer), and map that onto the list, returning the
6555 corresponding row and column.
6556
6557 <tscreen><verb>
6558 gint gtk_clist_get_selection_info( GtkCList *clist,
6559                                    gint      x,
6560                                    gint      y,
6561                                    gint     *row,
6562                                    gint     *column );
6563 </verb></tscreen>
6564
6565 When we detect something of interest, it might be movement of the
6566 pointer, a click somewhere in the list, we can read the pointer
6567 coordinates and find out where in the list the pointer is. Cumbersome?
6568 Luckily, there is a simpler way...
6569
6570 <!-- ----------------------------------------------------------------- -->
6571 <sect1>The signals that bring it together
6572 <p>
6573 As with all other widgets, there are a few signals that can be used. The
6574 GtkCList widget is derived from the GtkContainer widget, and so has all the
6575 same signals, but also the adds following:
6576
6577 <itemize>
6578 <item>select_row - This signal will send the following information, in
6579 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
6580
6581 <item>unselect_row - When the user unselects a row, this signal is
6582 activated. It sends the same information as select_row
6583
6584 <item>click_column - Send GtkCList *clist, gint column
6585 </itemize>
6586
6587 So if we want to connect a callback to select_row, the callback
6588 function would be declared like this
6589
6590 <tscreen><verb>
6591 void select_row_callback(GtkWidget *widget,
6592                          gint row,
6593                          gint column,
6594                          GdkEventButton *event,
6595                          gpointer data);
6596 </verb></tscreen>
6597
6598 The callback is connected as usual with
6599
6600 <tscreen><verb>
6601 gtk_signal_connect(GTK_OBJECT( clist),
6602                    "select_row"
6603                    GTK_SIGNAL_FUNC(select_row_callback),
6604                    NULL);
6605 </verb></tscreen>
6606
6607 <!-- ----------------------------------------------------------------- -->
6608 <sect1>A GtkCList example
6609 <p>
6610
6611 <tscreen><verb>
6612 /* example-start clist clist.c */
6613
6614 #include        <gtk/gtk.h>
6615 #include        <glib.h>
6616
6617 /* These are just the prototypes of the various callbacks */
6618 void button_add_clicked( GtkWidget *button, gpointer data);
6619 void button_clear_clicked( GtkWidget *button, gpointer data);
6620 void button_hide_show_clicked( GtkWidget *button, gpointer data);
6621 void selection_made( GtkWidget *clist, gint row, gint column,
6622                      GdkEventButton *event, gpointer data);
6623
6624 gint main (int argc, gchar *argv[])
6625 {                                  
6626     GtkWidget       *window;
6627     GtkWidget       *vbox, *hbox;
6628     GtkWidget       *clist;
6629     GtkWidget       *button_add, *button_clear, *button_hide_show;    
6630     gchar           *titles[2] = {"Ingredients","Amount"};
6631
6632     gtk_init(&amp;argc, &amp;argv);
6633     
6634     
6635     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
6636     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
6637
6638     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
6639     gtk_signal_connect(GTK_OBJECT(window),
6640                        "destroy",
6641                        GTK_SIGNAL_FUNC(gtk_main_quit),
6642                        NULL);
6643     
6644     vbox=gtk_vbox_new(FALSE, 5);
6645     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
6646     gtk_container_add(GTK_CONTAINER(window), vbox);
6647     gtk_widget_show(vbox);
6648     
6649     /* Create the GtkCList. For this example we use 2 columns */
6650     clist = gtk_clist_new_with_titles( 2, titles);
6651
6652     /* When a selection is made, we want to know about it. The callback
6653      * used is selection_made, and its code can be found further down */
6654     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
6655                        GTK_SIGNAL_FUNC(selection_made),
6656                        NULL);
6657
6658     /* It isn't necessary to shadow the border, but it looks nice :) */
6659     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
6660
6661     /* What however is important, is that we set the column widths as
6662      * they will never be right otherwise. Note that the columns are
6663      * numbered from 0 and up (to 1 in this case).
6664      */
6665     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
6666
6667     /* Add the GtkCList widget to the vertical box and show it. */
6668     gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
6669     gtk_widget_show(clist);
6670
6671     /* Create the buttons and add them to the window. See the button
6672      * tutorial for more examples and comments on this.
6673      */
6674     hbox = gtk_hbox_new(FALSE, 0);
6675     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
6676     gtk_widget_show(hbox);
6677
6678     button_add = gtk_button_new_with_label("Add List");
6679     button_clear = gtk_button_new_with_label("Clear List");
6680     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
6681
6682     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
6683     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
6684     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
6685
6686     /* Connect our callbacks to the three buttons */
6687     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
6688                               GTK_SIGNAL_FUNC(button_add_clicked),
6689                               (gpointer) clist);
6690     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
6691                               GTK_SIGNAL_FUNC(button_clear_clicked),
6692                               (gpointer) clist);
6693     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
6694                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
6695                               (gpointer) clist);
6696
6697     gtk_widget_show(button_add);
6698     gtk_widget_show(button_clear);
6699     gtk_widget_show(button_hide_show);
6700
6701     /* The interface is completely set up so we show the window and
6702      * enter the gtk_main loop.
6703      */
6704     gtk_widget_show(window);
6705     gtk_main();
6706     
6707     return(0);
6708 }
6709
6710 /* User clicked the "Add List" button. */
6711 void button_add_clicked( GtkWidget *button, gpointer data)
6712 {
6713     int         indx;
6714
6715     /* Something silly to add to the list. 4 rows of 2 columns each */
6716     gchar      *drink[4][2] = {{"Milk", "3 Oz"},
6717                                {"Water", "6 l"},
6718                                {"Carrots", "2"},
6719                                {"Snakes", "55"}};
6720
6721     /* Here we do the actual adding of the text. It's done once for
6722      * each row.
6723      */
6724     for( indx=0; indx < 4; indx++)
6725         gtk_clist_append( (GtkCList*) data, drink[indx]);
6726
6727     return;
6728 }
6729
6730 /* User clicked the "Clear List" button. */
6731 void button_clear_clicked( GtkWidget *button, gpointer data)
6732 {
6733     /* Clear the list using gtk_clist_clear. This is much faster than
6734      * calling gtk_clist_remove once for each row.
6735      */
6736     gtk_clist_clear((GtkCList*) data);
6737
6738     return;
6739 }
6740
6741 /* The user clicked the "Hide/Show titles" button. */
6742 void button_hide_show_clicked( GtkWidget *button, gpointer data)
6743 {
6744     /* Just a flag to remember the status. 0 = currently visible */
6745     static short int flag = 0;
6746
6747     if (flag == 0)
6748     {
6749         /* Hide the titles and set the flag to 1 */
6750         gtk_clist_column_titles_hide((GtkCList*) data);
6751         flag++;
6752     }
6753     else
6754     {
6755         /* Show the titles and reset flag to 0 */
6756         gtk_clist_column_titles_show((GtkCList*) data);
6757         flag--;
6758     }
6759
6760     return;
6761 }
6762
6763 /* If we come here, then the user has selected a row in the list. */
6764 void selection_made( GtkWidget *clist, gint row, gint column,
6765                      GdkEventButton *event, gpointer data)
6766 {
6767     gchar       *text;
6768
6769     /* Get the text that is stored in the selected row and column
6770      * which was clicked in. We will receive it as a pointer in the
6771      * argument text.
6772      */
6773     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
6774
6775     /* Just prints some information about the selected row */
6776     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);
6777
6778     return;
6779 }
6780 /* example-end */
6781 </verb></tscreen>
6782                     
6783 <!-- ***************************************************************** -->
6784 <sect> List Widget
6785 <!-- ***************************************************************** -->
6786 <p>
6787 NOTE: The GtkList widget has been superseded by the GtkCList widget.
6788
6789 The GtkList widget is designed to act as a vertical container for
6790 widgets that should be of the type GtkListItem.
6791
6792 A GtkList widget has its own window to receive events and its own
6793 background color which is usually white. As it is directly derived
6794 from a GtkContainer it can be treated as such by using the
6795 GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
6796 this. One should already be familiar with the usage of a GList and
6797 its related functions g_list_*() to be able to use the GtkList widget
6798 to it full extent.
6799
6800 There is one field inside the structure definition of the GtkList
6801 widget that will be of greater interest to us, this is:
6802
6803 <tscreen><verb>
6804 struct _GtkList
6805 {
6806   ...
6807   GList *selection;
6808   guint selection_mode;
6809   ...
6810 }; 
6811 </verb></tscreen>
6812
6813 The selection field of a GtkList points to a linked list of all items
6814 that are currently selected, or NULL if the selection is empty.  So to
6815 learn about the current selection we read the GTK_LIST()->selection
6816 field, but do not modify it since the internal fields are maintained
6817 by the gtk_list_*() functions.
6818
6819 The selection_mode of the GtkList determines the selection facilities
6820 of a GtkList and therefore the contents of the GTK_LIST()->selection
6821 field. The selection_mode may be one of the following:
6822
6823 <itemize>
6824 <item> GTK_SELECTION_SINGLE - The selection is either NULL
6825                         or contains a GList pointer
6826                         for a single selected item.
6827
6828 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list
6829                         contains no widgets or insensitive
6830                         ones only, otherwise it contains
6831                         a GList pointer for one GList
6832                         structure, and therefore exactly
6833                         one list item.
6834
6835 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list
6836                         items are selected or a GList pointer
6837                         for the first selected item. That
6838                         in turn points to a GList structure
6839                         for the second selected item and so
6840                         on.
6841
6842 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
6843 </itemize>
6844
6845 The default is GTK_SELECTION_MULTIPLE.
6846
6847 <!-- ----------------------------------------------------------------- -->
6848 <sect1> Signals
6849 <p>
6850 <tscreen><verb>
6851 void selection_changed( GtkList *list );
6852 </verb></tscreen>
6853
6854 This signal will be invoked whenever the selection field of a GtkList
6855 has changed. This happens when a child of the GtkList got selected or
6856 deselected.
6857
6858 <tscreen><verb>
6859 void select_child( GtkList   *list,
6860                    GtkWidget *child);
6861 </verb></tscreen>
6862
6863 This signal is invoked when a child of the GtkList is about to get
6864 selected. This happens mainly on calls to gtk_list_select_item(),
6865 gtk_list_select_child(), button presses and sometimes indirectly
6866 triggered on some else occasions where children get added to or
6867 removed from the GtkList.
6868
6869 <tscreen><verb>
6870 void unselect_child( GtkList   *list,
6871                      GtkWidget *child );
6872 </verb></tscreen>
6873
6874 This signal is invoked when a child of the GtkList is about to get
6875 deselected. This happens mainly on calls to gtk_list_unselect_item(),
6876 gtk_list_unselect_child(), button presses and sometimes indirectly
6877 triggered on some else occasions where children get added to or
6878 removed from the GtkList.
6879
6880 <!-- ----------------------------------------------------------------- -->
6881 <sect1> Functions
6882 <p>
6883 <tscreen><verb>
6884 guint gtk_list_get_type( void );
6885 </verb></tscreen>
6886
6887 Returns the `GtkList' type identifier.
6888
6889 <tscreen><verb>
6890 GtkWidget *gtk_list_new( void );
6891 </verb></tscreen>
6892
6893 Create a new GtkList object. The new widget is returned as a pointer
6894 to a GtkWidget object. NULL is returned on failure.
6895
6896 <tscreen><verb>
6897 void gtk_list_insert_items( GtkList *list,
6898                             GList   *items,
6899                             gint     position );
6900 </verb></tscreen>
6901
6902 Insert list items into the list, starting at <tt/position/.
6903 <tt/items/ is a doubly linked list where each nodes data pointer is
6904 expected to point to a newly created GtkListItem.  The GList nodes of
6905 <tt/items/ are taken over by the list.
6906
6907 <tscreen><verb>
6908 void gtk_list_append_items( GtkList *list,
6909                             GList   *items);
6910 </verb></tscreen>
6911
6912 Insert list items just like gtk_list_insert_items() at the end of the
6913 list. The GList nodes of <tt/items/ are taken over by the list.
6914
6915 <tscreen><verb>
6916 void gtk_list_prepend_items( GtkList *list,
6917                              GList   *items);
6918 </verb></tscreen>
6919
6920 Insert list items just like gtk_list_insert_items() at the very
6921 beginning of the list. The GList nodes of <tt/items/ are taken over by
6922 the list.
6923
6924 <tscreen><verb>
6925 void gtk_list_remove_items( GtkList *list,
6926                             GList   *items);
6927 </verb></tscreen>
6928
6929 Remove list items from the list. <tt/items/ is a doubly linked list
6930 where each nodes data pointer is expected to point to a direct child
6931 of list. It is the callers responsibility to make a call to
6932 g_list_free(items) afterwards. Also the caller has to destroy the list
6933 items himself.
6934
6935 <tscreen><verb>
6936 void gtk_list_clear_items( GtkList *list,
6937                            gint start,
6938                            gint end );
6939 </verb></tscreen>
6940
6941 Remove and destroy list items from the list. A widget is affected if
6942 its current position within the list is in the range specified by
6943 <tt/start/ and <tt/end/.
6944
6945 <tscreen><verb>
6946 void gtk_list_select_item( GtkList *list,
6947                            gint     item );
6948 </verb></tscreen>
6949
6950 Invoke the select_child signal for a list item specified through its
6951 current position within the list.
6952
6953 <tscreen><verb>
6954 void gtk_list_unselect_item( GtkList *list,
6955                              gint     item);
6956 </verb></tscreen>
6957
6958 Invoke the unselect_child signal for a list item specified through its
6959 current position within the list.
6960
6961 <tscreen><verb>
6962 void gtk_list_select_child( GtkList *list,
6963                             GtkWidget *child);
6964 </verb></tscreen>
6965
6966 Invoke the select_child signal for the specified child.
6967
6968 <tscreen><verb>
6969 void gtk_list_unselect_child( GtkList   *list,
6970                               GtkWidget *child);
6971 </verb></tscreen>
6972
6973 Invoke the unselect_child signal for the specified child.
6974
6975 <tscreen><verb>
6976 gint gtk_list_child_position( GtkList *list,
6977                               GtkWidget *child);
6978 </verb></tscreen>
6979
6980 Return the position of <tt/child/ within the list. "-1" is returned on
6981 failure.
6982
6983 <tscreen><verb>
6984 void gtk_list_set_selection_mode( GtkList         *list,
6985                                   GtkSelectionMode mode );
6986 </verb></tscreen>
6987
6988 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
6989 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
6990 GTK_SELECTION_EXTENDED.
6991
6992 <tscreen><verb>
6993 GtkList *GTK_LIST( gpointer obj );
6994 </verb></tscreen>
6995
6996 Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
6997 more info.
6998
6999 <tscreen><verb>
7000 GtkListClass *GTK_LIST_CLASS( gpointer class);
7001 </verb></tscreen>
7002
7003 Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
7004 for more info.
7005
7006 <tscreen><verb>
7007 gint GTK_IS_LIST( gpointer obj);
7008 </verb></tscreen>
7009
7010 Determine if a generic pointer refers to a `GtkList' object. *Note
7011 Standard Macros::, for more info.
7012
7013 <!-- ----------------------------------------------------------------- -->
7014 <sect1> Example
7015 <p>
7016 Following is an example program that will print out the changes of the
7017 selection of a GtkList, and lets you "arrest" list items into a prison
7018 by selecting them with the rightmost mouse button.
7019
7020 <tscreen><verb>
7021 /* example-start list list.c */
7022
7023 /* Include the gtk+ header files
7024  * Include stdio.h, we need that for the printf() function
7025  */
7026 #include        <gtk/gtk.h>
7027 #include        <stdio.h>
7028
7029 /* This is our data identification string to store
7030  * data in list items
7031  */
7032 const gchar *list_item_data_key="list_item_data";
7033
7034
7035 /* prototypes for signal handler that we are going to connect
7036  * to the GtkList widget
7037  */
7038 static void  sigh_print_selection( GtkWidget *gtklist,
7039                                    gpointer   func_data);
7040
7041 static void  sigh_button_event( GtkWidget      *gtklist,
7042                                 GdkEventButton *event,
7043                                 GtkWidget      *frame );
7044
7045
7046 /* Main function to set up the user interface */
7047
7048 gint main (int    argc,
7049            gchar *argv[])
7050 {                                  
7051     GtkWidget *separator;
7052     GtkWidget *window;
7053     GtkWidget *vbox;
7054     GtkWidget *scrolled_window;
7055     GtkWidget *frame;
7056     GtkWidget *gtklist;
7057     GtkWidget *button;
7058     GtkWidget *list_item;
7059     GList *dlist;
7060     guint i;
7061     gchar buffer[64];
7062     
7063     
7064     /* Initialize gtk+ (and subsequently gdk) */
7065
7066     gtk_init(&amp;argc, &amp;argv);
7067     
7068     
7069     /* Create a window to put all the widgets in
7070      * connect gtk_main_quit() to the "destroy" event of
7071      * the window to handle window manager close-window-events
7072      */
7073     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
7074     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
7075     gtk_signal_connect(GTK_OBJECT(window),
7076                        "destroy",
7077                        GTK_SIGNAL_FUNC(gtk_main_quit),
7078                        NULL);
7079     
7080     
7081     /* Inside the window we need a box to arrange the widgets
7082      * vertically */
7083     vbox=gtk_vbox_new(FALSE, 5);
7084     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
7085     gtk_container_add(GTK_CONTAINER(window), vbox);
7086     gtk_widget_show(vbox);
7087     
7088     /* This is the scrolled window to put the GtkList widget inside */
7089     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
7090     gtk_widget_set_usize(scrolled_window, 250, 150);
7091     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
7092     gtk_widget_show(scrolled_window);
7093     
7094     /* Create the GtkList widget.
7095      * Connect the sigh_print_selection() signal handler
7096      * function to the "selection_changed" signal of the GtkList
7097      * to print out the selected items each time the selection
7098      * has changed */
7099     gtklist=gtk_list_new();
7100     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
7101                                            gtklist);
7102     gtk_widget_show(gtklist);
7103     gtk_signal_connect(GTK_OBJECT(gtklist),
7104                        "selection_changed",
7105                        GTK_SIGNAL_FUNC(sigh_print_selection),
7106                        NULL);
7107     
7108     /* We create a "Prison" to put a list item in ;) */
7109     frame=gtk_frame_new("Prison");
7110     gtk_widget_set_usize(frame, 200, 50);
7111     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
7112     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
7113     gtk_container_add(GTK_CONTAINER(vbox), frame);
7114     gtk_widget_show(frame);
7115     
7116     /* Connect the sigh_button_event() signal handler to the GtkList
7117      * which will handle the "arresting" of list items
7118      */
7119     gtk_signal_connect(GTK_OBJECT(gtklist),
7120                        "button_release_event",
7121                        GTK_SIGNAL_FUNC(sigh_button_event),
7122                        frame);
7123     
7124     /* Create a separator */
7125     separator=gtk_hseparator_new();
7126     gtk_container_add(GTK_CONTAINER(vbox), separator);
7127     gtk_widget_show(separator);
7128     
7129     /* Finally create a button and connect it's "clicked" signal
7130      * to the destruction of the window */
7131     button=gtk_button_new_with_label("Close");
7132     gtk_container_add(GTK_CONTAINER(vbox), button);
7133     gtk_widget_show(button);
7134     gtk_signal_connect_object(GTK_OBJECT(button),
7135                               "clicked",
7136                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
7137                               GTK_OBJECT(window));
7138     
7139     
7140     /* Now we create 5 list items, each having it's own
7141      * label and add them to the GtkList using gtk_container_add()
7142      * Also we query the text string from the label and
7143      * associate it with the list_item_data_key for each list item
7144      */
7145     for (i=0; i<5; i++) {
7146         GtkWidget       *label;
7147         gchar           *string;
7148         
7149         sprintf(buffer, "ListItemContainer with Label #%d", i);
7150         label=gtk_label_new(buffer);
7151         list_item=gtk_list_item_new();
7152         gtk_container_add(GTK_CONTAINER(list_item), label);
7153         gtk_widget_show(label);
7154         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
7155         gtk_widget_show(list_item);
7156         gtk_label_get(GTK_LABEL(label), &amp;string);
7157         gtk_object_set_data(GTK_OBJECT(list_item),
7158                             list_item_data_key,
7159                             string);
7160     }
7161     /* Here, we are creating another 5 labels, this time
7162      * we use gtk_list_item_new_with_label() for the creation
7163      * we can't query the text string from the label because
7164      * we don't have the labels pointer and therefore
7165      * we just associate the list_item_data_key of each
7166      * list item with the same text string.
7167      * For adding of the list items we put them all into a doubly
7168      * linked list (GList), and then add them by a single call to
7169      * gtk_list_append_items().
7170      * Because we use g_list_prepend() to put the items into the
7171      * doubly linked list, their order will be descending (instead
7172      * of ascending when using g_list_append())
7173      */
7174     dlist=NULL;
7175     for (; i<10; i++) {
7176         sprintf(buffer, "List Item with Label %d", i);
7177         list_item=gtk_list_item_new_with_label(buffer);
7178         dlist=g_list_prepend(dlist, list_item);
7179         gtk_widget_show(list_item);
7180         gtk_object_set_data(GTK_OBJECT(list_item),
7181                             list_item_data_key,
7182                             "ListItem with integrated Label");
7183     }
7184     gtk_list_append_items(GTK_LIST(gtklist), dlist);
7185     
7186     /* Finally we want to see the window, don't we? ;) */
7187     gtk_widget_show(window);
7188     
7189     /* Fire up the main event loop of gtk */
7190     gtk_main();
7191     
7192     /* We get here after gtk_main_quit() has been called which
7193      * happens if the main window gets destroyed
7194      */
7195     return(0);
7196 }
7197
7198 /* This is the signal handler that got connected to button
7199  * press/release events of the GtkList
7200  */
7201 void sigh_button_event( GtkWidget      *gtklist,
7202                         GdkEventButton *event,
7203                         GtkWidget      *frame )
7204 {
7205     /* We only do something if the third (rightmost mouse button
7206      * was released
7207      */
7208     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
7209         event->button==3) {
7210         GList           *dlist, *free_list;
7211         GtkWidget       *new_prisoner;
7212         
7213         /* Fetch the currently selected list item which
7214          * will be our next prisoner ;)
7215          */
7216         dlist=GTK_LIST(gtklist)->selection;
7217         if (dlist)
7218                 new_prisoner=GTK_WIDGET(dlist->data);
7219         else
7220                 new_prisoner=NULL;
7221         
7222         /* Look for already imprisoned list items, we
7223          * will put them back into the list.
7224          * Remember to free the doubly linked list that
7225          * gtk_container_children() returns
7226          */
7227         dlist=gtk_container_children(GTK_CONTAINER(frame));
7228         free_list=dlist;
7229         while (dlist) {
7230             GtkWidget       *list_item;
7231             
7232             list_item=dlist->data;
7233             
7234             gtk_widget_reparent(list_item, gtklist);
7235             
7236             dlist=dlist->next;
7237         }
7238         g_list_free(free_list);
7239         
7240         /* If we have a new prisoner, remove him from the
7241          * GtkList and put him into the frame "Prison".
7242          * We need to unselect the item first.
7243          */
7244         if (new_prisoner) {
7245             GList   static_dlist;
7246             
7247             static_dlist.data=new_prisoner;
7248             static_dlist.next=NULL;
7249             static_dlist.prev=NULL;
7250             
7251             gtk_list_unselect_child(GTK_LIST(gtklist),
7252                                     new_prisoner);
7253             gtk_widget_reparent(new_prisoner, frame);
7254         }
7255     }
7256 }
7257
7258 /* This is the signal handler that gets called if GtkList
7259  * emits the "selection_changed" signal
7260  */
7261 void sigh_print_selection( GtkWidget *gtklist,
7262                            gpointer   func_data)
7263 {
7264     GList   *dlist;
7265     
7266     /* Fetch the doubly linked list of selected items
7267      * of the GtkList, remember to treat this as read-only!
7268      */
7269     dlist=GTK_LIST(gtklist)->selection;
7270     
7271     /* If there are no selected items there is nothing more
7272      * to do than just telling the user so
7273      */
7274     if (!dlist) {
7275         g_print("Selection cleared\n");
7276         return;
7277     }
7278     /* Ok, we got a selection and so we print it
7279      */
7280     g_print("The selection is a ");
7281     
7282     /* Get the list item from the doubly linked list
7283      * and then query the data associated with list_item_data_key.
7284      * We then just print it */
7285     while (dlist) {
7286         GtkObject       *list_item;
7287         gchar           *item_data_string;
7288         
7289         list_item=GTK_OBJECT(dlist->data);
7290         item_data_string=gtk_object_get_data(list_item,
7291                                              list_item_data_key);
7292         g_print("%s ", item_data_string);
7293         
7294         dlist=dlist->next;
7295     }
7296     g_print("\n");
7297 }
7298 /* example-end */
7299 </verb></tscreen>
7300
7301 <!-- ----------------------------------------------------------------- -->
7302 <sect1> List Item Widget
7303 <p>
7304 The GtkListItem widget is designed to act as a container holding up to
7305 one child, providing functions for selection/deselection just like the
7306 GtkList widget requires them for its children.
7307
7308 A GtkListItem has its own window to receive events and has its own
7309 background color which is usually white.
7310
7311 As it is directly derived from a GtkItem it can be treated as such by
7312 using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
7313 this. Usually a GtkListItem just holds a label to identify e.g. a
7314 filename within a GtkList -- therefore the convenience function
7315 gtk_list_item_new_with_label() is provided. The same effect can be
7316 achieved by creating a GtkLabel on its own, setting its alignment to
7317 xalign=0 and yalign=0.5 with a subsequent container addition to the
7318 GtkListItem.
7319
7320 As one is not forced to add a GtkLabel to a GtkListItem, you could
7321 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
7322
7323 <!-- ----------------------------------------------------------------- -->
7324 <sect1> Signals
7325 <p>
7326 A GtkListItem does not create new signals on its own, but inherits
7327 the signals of a GtkItem. *Note GtkItem::, for more info.
7328
7329 <!-- ----------------------------------------------------------------- -->
7330 <sect1> Functions
7331 <p>
7332 <tscreen><verb>
7333 guint gtk_list_item_get_type( void );
7334 </verb></tscreen>
7335
7336 Returns the `GtkListItem' type identifier.
7337
7338 <tscreen><verb>
7339 GtkWidget *gtk_list_item_new( void );
7340 </verb></tscreen>
7341
7342 Create a new GtkListItem object. The new widget is returned as a
7343 pointer to a GtkWidget object. NULL is returned on failure.
7344
7345 <tscreen><verb>
7346 GtkWidget *gtk_list_item_new_with_label( gchar *label );
7347 </verb></tscreen>
7348
7349 Create a new GtkListItem object, having a single GtkLabel as the sole
7350 child. The new widget is returned as a pointer to a GtkWidget
7351 object. NULL is returned on failure.
7352
7353 <tscreen><verb>
7354 void gtk_list_item_select( GtkListItem *list_item );
7355 </verb></tscreen>
7356
7357 This function is basically a wrapper around a call to gtk_item_select
7358 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
7359 GtkItem::, for more info.
7360
7361 <tscreen><verb>
7362 void gtk_list_item_deselect( GtkListItem *list_item );
7363 </verb></tscreen>
7364
7365 This function is basically a wrapper around a call to
7366 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
7367 signal.  *Note GtkItem::, for more info.
7368
7369 <tscreen><verb>
7370 GtkListItem *GTK_LIST_ITEM( gpointer obj );
7371 </verb></tscreen>
7372
7373 Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
7374 more info.
7375
7376 <tscreen><verb>
7377 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
7378 </verb></tscreen>
7379
7380 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
7381 for more info.
7382
7383 <tscreen><verb>
7384 gint GTK_IS_LIST_ITEM( gpointer obj );
7385 </verb></tscreen>
7386
7387 Determine if a generic pointer refers to a `GtkListItem' object.
7388 *Note Standard Macros::, for more info.
7389  
7390 <!-- ----------------------------------------------------------------- -->
7391 <sect1> Example
7392 <p>
7393 Please see the GtkList example on this, which covers the usage of a
7394 GtkListItem as well.
7395
7396 <!-- ***************************************************************** -->
7397 <sect> Tree Widget<label id="sec_Tree_Widgets">
7398 <!-- ***************************************************************** -->
7399 <p>
7400 The purpose of tree widgets is to display hierarchically-organized
7401 data. The GtkTree widget itself is a vertical container for widgets of
7402 type GtkTreeItem. GtkTree itself is not terribly different from
7403 GtkList - both are derived directly from GtkContainer, and the
7404 GtkContainer methods work in the same way on GtkTree widgets as on
7405 GtkList widgets. The difference is that GtkTree widgets can be nested
7406 within other GtkTree widgets. We'll see how to do this shortly.
7407
7408 The GtkTree widget has its own window, and defaults to a white
7409 background, as does GtkList. Also, most of the GtkTree methods work in
7410 the same way as the corresponding GtkList ones. However, GtkTree is
7411 not derived from GtkList, so you cannot use them interchangeably.
7412
7413 <sect1> Creating a Tree
7414 <p>
7415 A GtkTree is created in the usual way, using:
7416
7417 <tscreen><verb>
7418 GtkWidget* gtk_tree_new( void );
7419 </verb></tscreen>
7420
7421 Like the GtkList widget, a GtkTree will simply keep growing as more
7422 items are added to it, as well as when subtrees are expanded.  For
7423 this reason, they are almost always packed into a
7424 GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
7425 scrolled window to ensure that it is big enough to see the tree's
7426 items, as the default size for GtkScrolledWindow is quite small.
7427
7428 Now that you have a tree, you'll probably want to add some items to
7429 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
7430 explains the gory details of GtkTreeItem. For now, it'll suffice to
7431 create one, using:
7432
7433 <tscreen><verb>
7434 GtkWidget* gtk_tree_item_new_with_label( gchar *label );
7435 </verb></tscreen>
7436
7437 You can then add it to the tree using one of the following (see
7438 <ref id="sec_GtkTree_Functions" name="Functions and Macros">
7439 below for more options):
7440
7441 <tscreen><verb>
7442 void gtk_tree_append( GtkTree    *tree,
7443                        GtkWidget *tree_item );
7444
7445 void gtk_tree_prepend( GtkTree   *tree,
7446                        GtkWidget *tree_item );
7447 </verb></tscreen>
7448
7449 Note that you must add items to a GtkTree one at a time - there is no
7450 equivalent to gtk_list_*_items().
7451
7452 <!-- ----------------------------------------------------------------- -->
7453 <sect1> Adding a Subtree
7454 <p>
7455 A subtree is created like any other GtkTree widget. A subtree is added
7456 to another tree beneath a tree item, using:
7457
7458 <tscreen><verb>
7459 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
7460                                 GtkWidget   *subtree );
7461 </verb></tscreen>
7462
7463 You do not need to call gtk_widget_show() on a subtree before or after
7464 adding it to a GtkTreeItem. However, you <em>must</em> have added the
7465 GtkTreeItem in question to a parent tree before calling
7466 gtk_tree_item_set_subtree(). This is because, technically, the parent
7467 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
7468 rather the GtkTree which holds that GtkTreeItem.
7469
7470 When you add a subtree to a GtkTreeItem, a plus or minus sign appears
7471 beside it, which the user can click on to "expand" or "collapse" it,
7472 meaning, to show or hide its subtree. GtkTreeItems are collapsed by
7473 default. Note that when you collapse a GtkTreeItem, any selected
7474 items in its subtree remain selected, which may not be what the user
7475 expects.
7476
7477 <!-- ----------------------------------------------------------------- -->
7478 <sect1> Handling the Selection List
7479 <p>
7480 As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
7481 it is possible to control the behaviour of the tree (somewhat) by
7482 setting the selection type using:
7483
7484 <tscreen><verb>
7485 void gtk_tree_set_selection_mode( GtkTree          *tree,
7486                                   GtkSelectionMode  mode );
7487 </verb></tscreen>
7488
7489 The semantics associated with the various selection modes are
7490 described in the section on the GtkList widget. As with the GtkList
7491 widget, the "select_child", "unselect_child" (not really - see <ref
7492 id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
7493 and "selection_changed" signals are emitted when list items are
7494 selected or unselected. However, in order to take advantage of these
7495 signals, you need to know <em>which</em> GtkTree widget they will be
7496 emitted by, and where to find the list of selected items.
7497
7498 This is a source of potential confusion. The best way to explain this
7499 is that though all GtkTree widgets are created equal, some are more
7500 equal than others. All GtkTree widgets have their own X window, and
7501 can therefore receive events such as mouse clicks (if their
7502 GtkTreeItems or their children don't catch them first!). However, to
7503 make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
7504 behave in a sane manner, the list of selected items is specific to the
7505 topmost GtkTree widget in a hierarchy, known as the "root tree".
7506
7507 Thus, accessing the <tt>selection</tt>field directly in an arbitrary
7508 GtkTree widget is not a good idea unless you <em>know</em> it's the
7509 root tree.  Instead, use the GTK_TREE_SELECTION (Tree) macro, which
7510 gives the root tree's selection list as a GList pointer. Of course,
7511 this list can include items that are not in the subtree in question if 
7512 the selection type is GTK_SELECTION_MULTIPLE.
7513
7514 Finally, the "select_child" (and "unselect_child", in theory) signals
7515 are emitted by all trees, but the "selection_changed" signal is only
7516 emitted by the root tree. Consequently, if you want to handle the
7517 "select_child" signal for a tree and all its subtrees, you will have
7518 to call gtk_signal_connect() for every subtree.
7519
7520 <sect1> Tree Widget Internals
7521 <p>
7522 The GtkTree's struct definition looks like this:
7523
7524 <tscreen><verb>
7525 struct _GtkTree
7526 {
7527   GtkContainer container;
7528
7529   GList *children;
7530   
7531   GtkTree* root_tree; /* owner of selection list */
7532   GtkWidget* tree_owner;
7533   GList *selection;
7534   guint level;
7535   guint indent_value;
7536   guint current_indent;
7537   guint selection_mode : 2;
7538   guint view_mode : 1;
7539   guint view_line : 1;
7540 };
7541 </verb></tscreen>
7542
7543 The perils associated with accessing the <tt>selection</tt> field
7544 directly have already been mentioned. The other important fields of
7545 the struct can also be accessed with handy macros or class functions.
7546 GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
7547 whether a tree is the root tree in a GtkTree hierarchy, while
7548 GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
7549 GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
7550 to use one of the gtk_widget_*() functions on it).
7551
7552 Instead of directly accessing the children field of a GtkTree widget,
7553 it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
7554 to the gtk_container_children() function. This creates a duplicate of
7555 the original list, so it's advisable to free it up using g_list_free()
7556 after you're done with it, or to iterate on it destructively, like
7557 this:
7558
7559 <tscreen><verb>
7560     children = gtk_container_children (GTK_CONTAINER (tree));
7561     while (children) {
7562       do_something_nice (GTK_TREE_ITEM (children->data));
7563       children = g_list_remove_link (children, children);
7564 }
7565 </verb></tscreen>
7566
7567 The <tt>tree_owner</tt> field is defined only in subtrees, where it
7568 points to the GtkTreeItem widget which holds the tree in question.
7569 The <tt>level</tt> field indicates how deeply nested a particular tree
7570 is; root trees have level 0, and each successive level of subtrees has
7571 a level one greater than the parent level. This field is set only
7572 after a GtkTree widget is actually mapped (i.e. drawn on the screen).
7573
7574 <sect2> Signals<label id="sec_GtkTree_Signals">
7575 <p>
7576 <tscreen><verb>
7577 void selection_changed( GtkTree *tree );
7578 </verb></tscreen>
7579
7580 This signal will be emitted whenever the <tt>selection</tt> field of a
7581 GtkTree has changed. This happens when a child of the GtkTree is
7582 selected or deselected.
7583
7584 <tscreen><verb>
7585 void select_child( GtkTree   *tree,
7586                    GtkWidget *child );
7587 </verb></tscreen>
7588
7589 This signal is emitted when a child of the GtkTree is about to get
7590 selected. This happens on calls to gtk_tree_select_item(),
7591 gtk_tree_select_child(), on <em>all</em> button presses and calls to
7592 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
7593 indirectly triggered on other occasions where children get added to or
7594 removed from the GtkTree.
7595
7596 <tscreen><verb>
7597 void unselect_child (GtkTree   *tree,
7598                      GtkWidget *child);
7599 </verb></tscreen>
7600
7601 This signal is emitted when a child of the GtkTree is about to get
7602 deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
7603 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
7604 other occasions, but <em>not</em> when a button press deselects a
7605 child, nor on emission of the "toggle" signal by gtk_item_toggle().
7606
7607 <sect2> Functions and Macros<label id="sec_GtkTree_Functions">
7608 <p>
7609 <tscreen><verb>
7610 guint gtk_tree_get_type( void );
7611 </verb></tscreen>
7612
7613 Returns the `GtkTree' type identifier.
7614
7615 <tscreen><verb>
7616 GtkWidget* gtk_tree_new( void );
7617 </verb></tscreen>
7618
7619 Create a new GtkTree object. The new widget is returned as a pointer
7620 to a GtkWidget object. NULL is returned on failure.
7621
7622 <tscreen><verb>
7623 void gtk_tree_append( GtkTree   *tree,
7624                       GtkWidget *tree_item );
7625 </verb></tscreen>
7626
7627 Append a tree item to a GtkTree.
7628
7629 <tscreen><verb>
7630 void gtk_tree_prepend( GtkTree   *tree,
7631                        GtkWidget *tree_item );
7632 </verb></tscreen>
7633
7634 Prepend a tree item to a GtkTree.
7635
7636 <tscreen><verb>
7637 void gtk_tree_insert( GtkTree   *tree,
7638                       GtkWidget *tree_item,
7639                       gint       position );
7640 </verb></tscreen>
7641
7642 Insert a tree item into a GtkTree at the position in the list
7643 specified by <tt>position.</tt>
7644
7645 <tscreen><verb>
7646 void gtk_tree_remove_items( GtkTree *tree,
7647                             GList   *items );
7648 </verb></tscreen>
7649
7650 Remove a list of items (in the form of a GList *) from a GtkTree.
7651 Note that removing an item from a tree dereferences (and thus usually)
7652 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
7653 subtrees in that subtree.  If you want to remove only one item, you
7654 can use gtk_container_remove().
7655
7656 <tscreen><verb>
7657 void gtk_tree_clear_items( GtkTree *tree,
7658                            gint     start,
7659                            gint     end );
7660 </verb></tscreen>
7661
7662 Remove the items from position <tt>start</tt> to position <tt>end</tt>
7663 from a GtkTree.  The same warning about dereferencing applies here, as
7664 gtk_tree_clear_items() simply constructs a list and passes it to
7665 gtk_tree_remove_items().
7666
7667 <tscreen><verb>
7668 void gtk_tree_select_item( GtkTree *tree,
7669                            gint     item );
7670 </verb></tscreen>
7671
7672 Emits the "select_item" signal for the child at position
7673 <tt>item</tt>, thus selecting the child (unless you unselect it in a
7674 signal handler).
7675
7676 <tscreen><verb>
7677 void gtk_tree_unselect_item( GtkTree *tree,
7678                              gint     item );
7679 </verb></tscreen>
7680
7681 Emits the "unselect_item" signal for the child at position
7682 <tt>item</tt>, thus unselecting the child.
7683
7684 <tscreen><verb>
7685 void gtk_tree_select_child( GtkTree   *tree,
7686                             GtkWidget *tree_item );
7687 </verb></tscreen>
7688
7689 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
7690 selecting it.
7691
7692 <tscreen><verb>
7693 void gtk_tree_unselect_child( GtkTree   *tree,
7694                               GtkWidget *tree_item );
7695 </verb></tscreen>
7696
7697 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
7698 thus unselecting it.
7699
7700 <tscreen><verb>
7701 gint gtk_tree_child_position( GtkTree   *tree,
7702                               GtkWidget *child );
7703 </verb></tscreen>
7704
7705 Returns the position in the tree of <tt>child</tt>, unless
7706 <tt>child</tt> is not in the tree, in which case it returns -1.
7707
7708 <tscreen><verb>
7709 void gtk_tree_set_selection_mode( GtkTree          *tree,
7710                                   GtkSelectionMode  mode );
7711 </verb></tscreen>
7712
7713 Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
7714 default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
7715 GTK_SELECTION_EXTENDED. This is only defined for root trees, which
7716 makes sense, since the root tree "owns" the selection. Setting it for
7717 subtrees has no effect at all; the value is simply ignored.
7718
7719 <tscreen><verb>
7720 void gtk_tree_set_view_mode( GtkTree         *tree,
7721                              GtkTreeViewMode  mode ); 
7722 </verb></tscreen>
7723
7724 Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
7725 default) or GTK_TREE_VIEW_ITEM.  The view mode propagates from a tree
7726 to its subtrees, and can't be set exclusively to a subtree (this is
7727 not exactly true - see the example code comments).
7728
7729 The term "view mode" is rather ambiguous - basically, it controls the
7730 way the highlight is drawn when one of a tree's children is selected.
7731 If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
7732 highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
7733 (i.e. usually the label) is highlighted.
7734
7735 <tscreen><verb>
7736 void gtk_tree_set_view_lines( GtkTree *tree,
7737                               guint    flag );
7738 </verb></tscreen>
7739
7740 Controls whether connecting lines between tree items are drawn.
7741 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
7742 which case they aren't.
7743
7744 <tscreen><verb>
7745 GtkTree *GTK_TREE (gpointer obj);
7746 </verb></tscreen>
7747
7748 Cast a generic pointer to `GtkTree *'.
7749
7750 <tscreen><verb>
7751 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
7752 </verb></tscreen>
7753
7754 Cast a generic pointer to `GtkTreeClass*'.
7755
7756 <tscreen><verb>
7757 gint GTK_IS_TREE (gpointer obj);
7758 </verb></tscreen>
7759
7760 Determine if a generic pointer refers to a `GtkTree' object.
7761
7762 <tscreen><verb>
7763 gint GTK_IS_ROOT_TREE (gpointer obj)
7764 </verb></tscreen>
7765
7766 Determine if a generic pointer refers to a `GtkTree' object
7767 <em>and</em> is a root tree. Though this will accept any pointer, the
7768 results of passing it a pointer that does not refer to a GtkTree are
7769 undefined and possibly harmful.
7770
7771 <tscreen><verb>
7772 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
7773 </verb></tscreen>
7774
7775 Return the root tree of a pointer to a `GtkTree' object. The above
7776 warning applies.
7777
7778 <tscreen><verb>
7779 GList *GTK_TREE_SELECTION( gpointer obj)
7780 </verb></tscreen>
7781
7782 Return the selection list of the root tree of a `GtkTree' object. The
7783 above warning applies here, too.
7784
7785 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
7786 <p>
7787 The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
7788 which in turn is derived from GtkBin.  Therefore, the item itself is a
7789 generic container holding exactly one child widget, which can be of
7790 any type.  The GtkTreeItem widget has a number of extra fields, but
7791 the only one we need be concerned with is the <tt>subtree</tt> field.
7792
7793 The definition for the GtkTreeItem struct looks like this:
7794
7795 <tscreen><verb>
7796 struct _GtkTreeItem
7797 {
7798   GtkItem item;
7799
7800   GtkWidget *subtree;
7801   GtkWidget *pixmaps_box;
7802   GtkWidget *plus_pix_widget, *minus_pix_widget;
7803
7804   GList *pixmaps;               /* pixmap node for this items color depth */
7805
7806   guint expanded : 1;
7807 };
7808 </verb></tscreen>
7809
7810 The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
7811 on the plus/minus symbol which controls expansion and collapsing.  The
7812 <tt>pixmaps</tt> field points to an internal data structure.  Since
7813 you can always obtain the subtree of a GtkTreeItem in a (relatively)
7814 type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
7815 probably advisable never to touch the insides of a GtkTreeItem unless
7816 you <em>really</em> know what you're doing.
7817
7818 Since it is directly derived from a GtkItem it can be treated as such
7819 by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
7820 label, so the convenience function gtk_list_item_new_with_label() is
7821 provided. The same effect can be achieved using code like the
7822 following, which is actually copied verbatim from
7823 gtk_tree_item_new_with_label():
7824
7825 <tscreen><verb>
7826 tree_item = gtk_tree_item_new ();
7827 label_widget = gtk_label_new (label);
7828 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
7829
7830 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
7831 gtk_widget_show (label_widget);
7832 </verb></tscreen>
7833
7834 As one is not forced to add a GtkLabel to a GtkTreeItem, you could
7835 also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
7836 app will likely be quite unpopular in this case) to the GtkTreeItem.
7837
7838 If you remove all the items from a subtree, it will be destroyed and
7839 unparented, unless you reference it beforehand, and the GtkTreeItem
7840 which owns it will be collapsed.  So, if you want it to stick around,
7841 do something like the following:
7842
7843 <tscreen><verb>
7844 gtk_widget_ref (tree);
7845 owner = GTK_TREE(tree)->tree_owner;
7846 gtk_container_remove (GTK_CONTAINER(tree), item);
7847 if (tree->parent == NULL){
7848   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
7849   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
7850 }
7851 else
7852   gtk_widget_unref (tree);
7853 </verb></tscreen>
7854
7855 Finally, drag-n-drop <em>does</em> work with GtkTreeItems.  You just
7856 have to make sure that the GtkTreeItem you want to make into a drag
7857 item or a drop site has not only been added to a GtkTree, but that
7858 each successive parent widget has a parent itself, all the way back to
7859 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
7860 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
7861
7862 <sect2> Signals
7863 <p>
7864 GtkTreeItem inherits the "select", "deselect", and "toggle" signals
7865 from GtkItem.  In addition, it adds two signals of its own, "expand"
7866 and "collapse".
7867
7868 <tscreen><verb>
7869 void select( GtkItem *tree_item );
7870 </verb></tscreen>
7871
7872 This signal is emitted when an item is about to be selected, either
7873 after it has been clicked on by the user, or when the program calls
7874 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
7875
7876 <tscreen><verb>
7877 void deselect( GtkItem *tree_item );
7878 </verb></tscreen>
7879
7880 This signal is emitted when an item is about to be unselected, either
7881 after it has been clicked on by the user, or when the program calls
7882 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
7883 GtkTreeItems, it is also emitted by gtk_tree_unselect_child(), and
7884 sometimes gtk_tree_select_child().
7885
7886 <tscreen><verb>
7887 void toggle( GtkItem *tree_item );
7888 </verb></tscreen>
7889
7890 This signal is emitted when the program calls gtk_item_toggle().  The
7891 effect it has when emitted on a GtkTreeItem is to call
7892 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
7893 item's parent tree, if the item has a parent tree.  If it doesn't,
7894 then the highlight is reversed on the item.
7895
7896 <tscreen><verb>
7897 void expand( GtkTreeItem *tree_item );
7898 </verb></tscreen>
7899
7900 This signal is emitted when the tree item's subtree is about to be
7901 expanded, that is, when the user clicks on the plus sign next to the
7902 item, or when the program calls gtk_tree_item_expand().
7903
7904 <tscreen><verb>
7905 void collapse( GtkTreeItem *tree_item );
7906 </verb></tscreen>
7907
7908 This signal is emitted when the tree item's subtree is about to be
7909 collapsed, that is, when the user clicks on the minus sign next to the
7910 item, or when the program calls gtk_tree_item_collapse().
7911
7912 <sect2> Functions and Macros
7913 <p>
7914 <tscreen><verb>
7915 guint gtk_tree_item_get_type( void );
7916 </verb></tscreen>
7917
7918 Returns the `GtkTreeItem' type identifier.
7919
7920 <tscreen><verb>
7921 GtkWidget* gtk_tree_item_new( void );
7922 </verb></tscreen>
7923
7924 Create a new GtkTreeItem object. The new widget is returned as a
7925 pointer to a GtkWidget object. NULL is returned on failure.
7926
7927 <tscreen><verb>
7928 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
7929 </verb></tscreen>
7930
7931 Create a new GtkTreeItem object, having a single GtkLabel as the sole
7932 child. The new widget is returned as a pointer to a GtkWidget
7933 object. NULL is returned on failure.
7934
7935 <tscreen><verb>
7936 void gtk_tree_item_select( GtkTreeItem *tree_item );
7937 </verb></tscreen>
7938
7939 This function is basically a wrapper around a call to gtk_item_select
7940 (GTK_ITEM (tree_item)) which will emit the select signal.
7941
7942 <tscreen><verb>
7943 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
7944 </verb></tscreen>
7945
7946 This function is basically a wrapper around a call to
7947 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
7948 signal.
7949
7950 <tscreen><verb>
7951 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
7952                                 GtkWidget   *subtree );
7953 </verb></tscreen>
7954
7955 This function adds subtree to tree_item, showing it if tree_item is
7956 expanded, or hiding it if tree_item is collapsed. Again, remember that
7957 the tree_item must have already been added to a tree for this to work.
7958
7959 <tscreen><verb>
7960 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
7961 </verb></tscreen>
7962
7963 This removes all of tree_item's subtree's children (thus unreferencing
7964 and destroying it, any of its children's subtrees, and so on...), then
7965 removes the subtree itself, and hides the plus/minus sign.
7966
7967 <tscreen><verb>
7968 void gtk_tree_item_expand( GtkTreeItem *tree_item );
7969 </verb></tscreen>
7970
7971 This emits the "expand" signal on tree_item, which expands it.
7972
7973 <tscreen><verb>
7974 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
7975 </verb></tscreen>
7976
7977 This emits the "collapse" signal on tree_item, which collapses it.
7978
7979 <tscreen><verb>
7980 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
7981 </verb></tscreen>
7982
7983 Cast a generic pointer to `GtkTreeItem*'.
7984
7985 <tscreen><verb>
7986 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
7987 </verb></tscreen>
7988
7989 Cast a generic pointer to `GtkTreeItemClass'.
7990
7991 <tscreen><verb>
7992 gint GTK_IS_TREE_ITEM (gpointer obj)
7993 </verb></tscreen>
7994
7995 Determine if a generic pointer refers to a `GtkTreeItem' object.
7996  
7997 <tscreen><verb>
7998 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
7999 </verb></tscreen>
8000
8001 Returns a tree item's subtree (obj should point to a `GtkTreeItem'
8002 object).
8003
8004 <sect1> Tree Example
8005 <p>
8006 This is somewhat like the tree example in testgtk.c, but a lot less
8007 complete (although much better commented).  It puts up a window with a
8008 tree, and connects all the signals for the relevant objects, so you
8009 can see when they are emitted.
8010
8011 <tscreen><verb>
8012 /* example-start tree tree.c */
8013
8014 #include <gtk/gtk.h>
8015
8016 /* for all the GtkItem:: and GtkTreeItem:: signals */
8017 static void cb_itemsignal (GtkWidget *item, gchar *signame)
8018 {
8019   gchar *name;
8020   GtkLabel *label;
8021
8022   /* It's a GtkBin, so it has one child, which we know to be a
8023      label, so get that */
8024   label = GTK_LABEL (GTK_BIN (item)->child);
8025   /* Get the text of the label */
8026   gtk_label_get (label, &amp;name);
8027   /* Get the level of the tree which the item is in */
8028   g_print ("%s called for item %s->%p, level %d\n", signame, name,
8029            item, GTK_TREE (item->parent)->level);
8030 }
8031
8032 /* Note that this is never called */
8033 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
8034                                GtkWidget *subtree)
8035 {
8036   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
8037            root_tree, subtree, child);
8038 }
8039
8040 /* Note that this is called every time the user clicks on an item,
8041    whether it is already selected or not. */
8042 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
8043                              GtkWidget *subtree)
8044 {
8045   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
8046            root_tree, subtree, child);
8047 }
8048
8049 static void cb_selection_changed (GtkWidget *tree)
8050 {
8051   GList *i;
8052   
8053   g_print ("selection_change called for tree %p\n", tree);
8054   g_print ("selected objects are:\n");
8055
8056   i = GTK_TREE_SELECTION(tree);
8057   while (i){
8058     gchar *name;
8059     GtkLabel *label;
8060     GtkWidget *item;
8061
8062     /* Get a GtkWidget pointer from the list node */
8063     item = GTK_WIDGET (i->data);
8064     label = GTK_LABEL (GTK_BIN (item)->child);
8065     gtk_label_get (label, &amp;name);
8066     g_print ("\t%s on level %d\n", name, GTK_TREE
8067              (item->parent)->level);
8068     i = i->next;
8069   }
8070 }
8071
8072 int main (int argc, char *argv[])
8073 {
8074   GtkWidget *window, *scrolled_win, *tree;
8075   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
8076                                "Maurice"};
8077   gint i;
8078
8079   gtk_init (&amp;argc, &amp;argv);
8080
8081   /* a generic toplevel window */
8082   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8083   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
8084                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
8085   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
8086
8087   /* A generic scrolled window */
8088   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8089   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8090                                   GTK_POLICY_AUTOMATIC,
8091                                   GTK_POLICY_AUTOMATIC);
8092   gtk_widget_set_usize (scrolled_win, 150, 200);
8093   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
8094   gtk_widget_show (scrolled_win);
8095   
8096   /* Create the root tree */
8097   tree = gtk_tree_new();
8098   g_print ("root tree is %p\n", tree);
8099   /* connect all GtkTree:: signals */
8100   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
8101                       GTK_SIGNAL_FUNC(cb_select_child), tree);
8102   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
8103                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
8104   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
8105                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
8106   /* Add it to the scrolled window */
8107   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
8108                                          tree);
8109   /* Set the selection mode */
8110   gtk_tree_set_selection_mode (GTK_TREE(tree),
8111                                GTK_SELECTION_MULTIPLE);
8112   /* Show it */
8113   gtk_widget_show (tree);
8114
8115   for (i = 0; i < 5; i++){
8116     GtkWidget *subtree, *item;
8117     gint j;
8118
8119     /* Create a tree item */
8120     item = gtk_tree_item_new_with_label (itemnames[i]);
8121     /* Connect all GtkItem:: and GtkTreeItem:: signals */
8122     gtk_signal_connect (GTK_OBJECT(item), "select",
8123                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
8124     gtk_signal_connect (GTK_OBJECT(item), "deselect",
8125                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
8126     gtk_signal_connect (GTK_OBJECT(item), "toggle",
8127                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
8128     gtk_signal_connect (GTK_OBJECT(item), "expand",
8129                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
8130     gtk_signal_connect (GTK_OBJECT(item), "collapse",
8131                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
8132     /* Add it to the parent tree */
8133     gtk_tree_append (GTK_TREE(tree), item);
8134     /* Show it - this can be done at any time */
8135     gtk_widget_show (item);
8136     /* Create this item's subtree */
8137     subtree = gtk_tree_new();
8138     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
8139              subtree);
8140
8141     /* This is still necessary if you want these signals to be called
8142        for the subtree's children.  Note that selection_change will be 
8143        signalled for the root tree regardless. */
8144     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
8145                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
8146     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
8147                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
8148     /* This has absolutely no effect, because it is completely ignored 
8149        in subtrees */
8150     gtk_tree_set_selection_mode (GTK_TREE(subtree),
8151                                  GTK_SELECTION_SINGLE);
8152     /* Neither does this, but for a rather different reason - the
8153        view_mode and view_line values of a tree are propagated to
8154        subtrees when they are mapped.  So, setting it later on would
8155        actually have a (somewhat unpredictable) effect */
8156     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
8157     /* Set this item's subtree - note that you cannot do this until
8158        AFTER the item has been added to its parent tree! */
8159     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
8160
8161     for (j = 0; j < 5; j++){
8162       GtkWidget *subitem;
8163
8164       /* Create a subtree item, in much the same way */
8165       subitem = gtk_tree_item_new_with_label (itemnames[j]);
8166       /* Connect all GtkItem:: and GtkTreeItem:: signals */
8167       gtk_signal_connect (GTK_OBJECT(subitem), "select",
8168                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
8169       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
8170                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
8171       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
8172                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
8173       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
8174                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
8175       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
8176                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
8177       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
8178       /* Add it to its parent tree */
8179       gtk_tree_append (GTK_TREE(subtree), subitem);
8180       /* Show it */
8181       gtk_widget_show (subitem);
8182     }
8183   }
8184
8185   /* Show the window and loop endlessly */
8186   gtk_widget_show (window);
8187   gtk_main();
8188   return 0;
8189 }
8190 /* example-end */
8191 </verb></tscreen>
8192
8193 <!-- ***************************************************************** -->
8194 <sect>Menu Widget
8195 <!-- ***************************************************************** -->
8196 <p>
8197 There are two ways to create menus, there's the easy way, and there's
8198 the hard way. Both have their uses, but you can usually use the
8199 itemfactory (the easy way). The "hard" way is to create all the menus
8200 using the calls directly. The easy way is to use the gtk_item_factory
8201 calls. This is much simpler, but there are advantages and
8202 disadvantages to each approach.
8203
8204 The itemfactory is much easier to use, and to add new menus to,
8205 although writing a few wrapper functions to create menus using the
8206 manual method could go a long way towards usability. With the
8207 menufactory, it is not possible to add images or the character '/' to
8208 the menus.
8209
8210 <!-- ----------------------------------------------------------------- -->
8211 <sect1>Manual Menu Creation
8212 <p>
8213 In the true tradition of teaching, we'll show you the hard way
8214 first. <tt>:)</>
8215
8216 There are three widgets that go into making a menubar and submenus:
8217 <itemize>
8218 <item>a menu item, which is what the user wants to select, e.g. 'Save'
8219 <item>a menu, which acts as a container for the menu items, and
8220 <item>a menubar, which is a container for each of the individual
8221 menus.
8222 </itemize>
8223
8224 This is slightly complicated by the fact that menu item widgets are
8225 used for two different things. They are both the widgets that are
8226 packed into the menu, and the widget that is packed into the menubar,
8227 which, when selected, activates the menu.
8228
8229 Let's look at the functions that are used to create menus and
8230 menubars.  This first function is used to create a new menubar.
8231
8232 <tscreen>
8233 <verb>
8234 GtkWidget *gtk_menu_bar_new( void );
8235 </verb>
8236 </tscreen>
8237
8238 This rather self explanatory function creates a new menubar. You use
8239 gtk_container_add to pack this into a window, or the box_pack
8240 functions to pack it into a box - the same as buttons.
8241
8242 <tscreen><verb>
8243 GtkWidget *gtk_menu_new( void );
8244 </verb></tscreen>
8245
8246 This function returns a pointer to a new menu, it is never actually
8247 shown (with gtk_widget_show), it is just a container for the menu
8248 items. Hopefully this will become more clear when you look at the
8249 example below.
8250
8251 The next two calls are used to create menu items that are packed into
8252 the menu (and menubar).
8253
8254 <tscreen><verb>
8255 GtkWidget *gtk_menu_item_new( void );
8256 </verb></tscreen>
8257
8258 and
8259
8260 <tscreen><verb>
8261 GtkWidget *gtk_menu_item_new_with_label( const char *label );
8262 </verb></tscreen>
8263
8264 These calls are used to create the menu items that are to be
8265 displayed.  Remember to differentiate between a "menu" as created with
8266 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
8267 functions. The menu item will be an actual button with an associated
8268 action, whereas a menu will be a container holding menu items.
8269
8270 The gtk_menu_new_with_label and gtk_menu_new functions are just as
8271 you'd expect after reading about the buttons. One creates a new menu
8272 item with a label already packed into it, and the other just creates a
8273 blank menu item.
8274
8275 Once you've created a menu item you have to put it into a menu. This
8276 is done using the function gtk_menu_append. In order to capture when
8277 the item is selected by the user, we need to connect to the
8278 <tt/activate/ signal in the usual way. So, if we wanted to create a
8279 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/ and
8280 <tt/Quit/ the code would look something like:
8281
8282 <tscreen><verb>
8283     file_menu = gtk_menu_new();    /* Don't need to show menus */
8284
8285     /* Create the menu items */
8286     open_item = gtk_menu_item_new_with_label("Open");
8287     save_item = gtk_menu_item_new_with_label("Save");
8288     quit_item = gtk_menu_item_new_with_label("Quit");
8289
8290     /* Add them to the menu */
8291     gtk_menu_append( GTK_MENU(file_menu), open_item);
8292     gtk_menu_append( GTK_MENU(file_menu), save_item);
8293     gtk_menu_append( GTK_MENU(file_menu), quit_item);
8294
8295     /* Attach the callback functions to the activate signal */
8296     gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
8297                                GTK_SIGNAL_FUNC(menuitem_response),
8298                                (gpointer) "file.open");
8299     gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
8300                                GTK_SIGNAL_FUNC(menuitem_response),
8301                                (gpointer) "file.save");
8302
8303     /* We can attach the Quit menu item to our exit function */
8304     gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
8305                                GTK_SIGNAL_FUNC(destroy),
8306                                (gpointer) "file.quit");
8307
8308     /* We do need to show menu items */
8309     gtk_widget_show( open_item );
8310     gtk_widget_show( save_item );
8311     gtk_widget_show( quit_item );
8312 </verb></tscreen>
8313
8314 At this point we have our menu. Now we need to create a menubar and a
8315 menu item for the <tt/File/ entry, to which we add our menu. The code
8316 looks like this:
8317
8318 <tscreen><verb>
8319     menu_bar = gtk_menu_bar_new();
8320     gtk_container_add( GTK_CONTAINER(window), menu_bar);
8321     gtk_widget_show( menu_bar );
8322
8323     file_item = gtk_menu_item_new_with_label("File");
8324     gtk_widget_show(file_item);
8325 </verb></tscreen>
8326
8327 Now we need to associate the menu with <tt/file_item/. This is done
8328 with the function
8329
8330 <tscreen>
8331 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
8332                                 GtkWidget   *submenu );
8333 </tscreen>
8334
8335 So, our example would continue with
8336
8337 <tscreen><verb>
8338     gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu );
8339 </verb></tscreen>
8340
8341 All that is left to do is to add the menu to the menubar, which is
8342 accomplished using the function
8343
8344 <tscreen>
8345 void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);
8346 </tscreen>
8347
8348 which in our case looks like this:
8349
8350 <tscreen><verb>
8351     gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );
8352 </verb></tscreen>
8353
8354 If we wanted the menu right justified on the menubar, such as help
8355 menus often are, we can use the following function (again on
8356 <tt/file_item/ in the current example) before attaching it to the
8357 menubar.
8358
8359 <tscreen><verb>
8360 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
8361 </verb></tscreen>
8362
8363 Here is a summary of the steps needed to create a menu bar with menus
8364 attached:
8365
8366 <itemize>
8367 <item> Create a new menu using gtk_menu_new()
8368 <item> Use multiple calls to gtk_menu_item_new() for each item you
8369 wish to have on your menu. And use gtk_menu_append() to put each of
8370 these new items on to the menu.
8371 <item> Create a menu item using gtk_menu_item_new(). This will be the
8372 root of the menu, the text appearing here will be on the menubar
8373 itself.
8374 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
8375 menu item (the one created in the above step).
8376 <item> Create a new menubar using gtk_menu_bar_new. This step only
8377 needs to be done once when creating a series of menus on one menu bar.
8378 <item> Use gtk_menu_bar_append to put the root menu onto the menubar.
8379 </itemize>
8380
8381 Creating a popup menu is nearly the same. The difference is that the
8382 menu is not posted `automatically' by a menubar, but explicitly by
8383 calling the function gtk_menu_popup() from a button-press event, for
8384 example.  Take these steps:
8385
8386 <itemize>
8387 <item>Create an event handling function. It needs to have the
8388 prototype
8389 <tscreen>
8390 static gint handler( GtkWidget *widget,
8391                      GdkEvent  *event );
8392 </tscreen>
8393 and it will use the event to find out where to pop up the menu.
8394 <item>In the event handler, if the event is a mouse button press,
8395 treat <tt>event</tt> as a button event (which it is) and use it as
8396 shown in the sample code to pass information to gtk_menu_popup().
8397 <item>Bind that event handler to a widget with
8398 <tscreen>
8399     gtk_signal_connect_object(GTK_OBJECT(widget), "event",
8400                               GTK_SIGNAL_FUNC (handler),
8401                               GTK_OBJECT(menu));
8402 </tscreen>
8403 where <tt>widget</tt> is the widget you are binding to,
8404 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
8405 created with gtk_menu_new(). This can be a menu which is also posted
8406 by a menu bar, as shown in the sample code.
8407 </itemize>
8408
8409 <!-- ----------------------------------------------------------------- -->
8410 <sect1>Manual Menu Example
8411 <p>
8412 That should about do it. Let's take a look at an example to help clarify.
8413
8414 <tscreen><verb>
8415 /* example-start menu menu.c */
8416
8417 #include <gtk/gtk.h>
8418
8419 static gint button_press (GtkWidget *, GdkEvent *);
8420 static void menuitem_response (gchar *);
8421
8422 int main (int argc, char *argv[])
8423 {
8424
8425     GtkWidget *window;
8426     GtkWidget *menu;
8427     GtkWidget *menu_bar;
8428     GtkWidget *root_menu;
8429     GtkWidget *menu_items;
8430     GtkWidget *vbox;
8431     GtkWidget *button;
8432     char buf[128];
8433     int i;
8434
8435     gtk_init (&amp;argc, &amp;argv);
8436
8437     /* create a new window */
8438     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
8439     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
8440     gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
8441     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
8442                        (GtkSignalFunc) gtk_main_quit, NULL);
8443
8444     /* Init the menu-widget, and remember -- never
8445      * gtk_show_widget() the menu widget!! 
8446      * This is the menu that holds the menu items, the one that
8447      * will pop up when you click on the "Root Menu" in the app */
8448     menu = gtk_menu_new();
8449
8450     /* Next we make a little loop that makes three menu-entries for "test-menu".
8451      * Notice the call to gtk_menu_append.  Here we are adding a list of
8452      * menu items to our menu.  Normally, we'd also catch the "clicked"
8453      * signal on each of the menu items and setup a callback for it,
8454      * but it's omitted here to save space. */
8455
8456     for(i = 0; i < 3; i++)
8457         {
8458             /* Copy the names to the buf. */
8459             sprintf(buf, "Test-undermenu - %d", i);
8460
8461             /* Create a new menu-item with a name... */
8462             menu_items = gtk_menu_item_new_with_label(buf);
8463
8464             /* ...and add it to the menu. */
8465             gtk_menu_append(GTK_MENU (menu), menu_items);
8466
8467             /* Do something interesting when the menuitem is selected */
8468             gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
8469                 GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf));
8470
8471             /* Show the widget */
8472             gtk_widget_show(menu_items);
8473         }
8474
8475     /* This is the root menu, and will be the label
8476      * displayed on the menu bar.  There won't be a signal handler attached,
8477      * as it only pops up the rest of the menu when pressed. */
8478     root_menu = gtk_menu_item_new_with_label("Root Menu");
8479
8480     gtk_widget_show(root_menu);
8481
8482     /* Now we specify that we want our newly created "menu" to be the menu
8483      * for the "root menu" */
8484     gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
8485
8486     /* A vbox to put a menu and a button in: */
8487     vbox = gtk_vbox_new(FALSE, 0);
8488     gtk_container_add(GTK_CONTAINER(window), vbox);
8489     gtk_widget_show(vbox);
8490
8491     /* Create a menu-bar to hold the menus and add it to our main window */
8492     menu_bar = gtk_menu_bar_new();
8493     gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
8494     gtk_widget_show(menu_bar);
8495
8496     /* Create a button to which to attach menu as a popup */
8497     button = gtk_button_new_with_label("press me");
8498     gtk_signal_connect_object(GTK_OBJECT(button), "event",
8499         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
8500     gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
8501     gtk_widget_show(button);
8502
8503     /* And finally we append the menu-item to the menu-bar -- this is the
8504      * "root" menu-item I have been raving about =) */
8505     gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
8506
8507     /* always display the window as the last step so it all splashes on
8508      * the screen at once. */
8509     gtk_widget_show(window);
8510
8511     gtk_main ();
8512
8513     return 0;
8514 }
8515
8516 /* Respond to a button-press by posting a menu passed in as widget.
8517  *
8518  * Note that the "widget" argument is the menu being posted, NOT
8519  * the button that was pressed.
8520  */
8521
8522 static gint button_press (GtkWidget *widget, GdkEvent *event)
8523 {
8524
8525     if (event->type == GDK_BUTTON_PRESS) {
8526         GdkEventButton *bevent = (GdkEventButton *) event; 
8527         gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
8528                         bevent->button, bevent->time);
8529         /* Tell calling code that we have handled this event; the buck
8530          * stops here. */
8531         return TRUE;
8532     }
8533
8534     /* Tell calling code that we have not handled this event; pass it on. */
8535     return FALSE;
8536 }
8537
8538
8539 /* Print a string when a menu item is selected */
8540
8541 static void menuitem_response (gchar *string)
8542 {
8543     printf("%s\n", string);
8544 }
8545 /* example-end */
8546 </verb></tscreen>
8547
8548 You may also set a menu item to be insensitive and, using an accelerator
8549 table, bind keys to menu functions.
8550
8551 <!-- ----------------------------------------------------------------- -->
8552 <sect1>Using GtkItemFactory
8553 <p>
8554 Now that we've shown you the hard way, here's how you do it using the
8555 gtk_item_factory calls.
8556
8557 <!-- ----------------------------------------------------------------- -->
8558 <sect1>Item Factory Example
8559 <p>
8560 Here is an example using the GTK item factory.
8561
8562 <tscreen><verb>
8563 /* example-start menu itemfactory.c */
8564
8565 #include <gtk/gtk.h>
8566 #include <strings.h>
8567
8568 /* Obligatory basic callback */
8569 static void print_hello(GtkWidget *w, gpointer data) {
8570   g_message("Hello, World!\n");
8571 }
8572
8573 /* This is the GtkItemFactoryEntry structure used to generate new menus.
8574    Item 1: The menu path. The letter after the underscore indicates an
8575            accelerator key once the menu is open.
8576    Item 2: The accelerator key for the entry
8577    Item 3: The callback function.
8578    Item 4: The callback action.  This changes the parameters with
8579            which the function is called.  The default is 0.
8580    Item 5: The item type, used to define what kind of an item it is.
8581            Here are the possible values:
8582
8583            NULL               -> "<Item>"
8584            ""                 -> "<Item>"
8585            "<Title>"          -> create a title item
8586            "<Item>"           -> create a simple item
8587            "<CheckItem>"      -> create a check item
8588            "<ToggleItem>"     -> create a toggle item
8589            "<RadioItem>"      -> create a radio item
8590            <path>             -> path of a radio item to link against
8591            "<Separator>"      -> create a separator
8592            "<Branch>"         -> create an item to hold sub items
8593            "<LastBranch>"     -> create a right justified branch 
8594 */
8595
8596 static GtkItemFactoryEntry menu_items[] = {
8597   {"/_File",         NULL,         NULL, 0, "<Branch>"},
8598   {"/File/_New",     "<control>N", print_hello, 0, NULL},
8599   {"/File/_Open",    "<control>O", print_hello, 0, NULL},
8600   {"/File/_Save",    "<control>S", print_hello, 0, NULL},
8601   {"/File/Save _As", NULL,         NULL, 0, NULL},
8602   {"/File/sep1",     NULL,         NULL, 0, "<Separator>"},
8603   {"/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL},
8604   {"/_Options",      NULL,         NULL, 0, "<Branch>"},
8605   {"/Options/Test",  NULL,         NULL, 0, NULL},
8606   {"/_Help",         NULL,         NULL, 0, "<LastBranch>"},
8607   {"/_Help/About",   NULL,         NULL, 0, NULL},
8608 };
8609
8610
8611 void get_main_menu(GtkWidget *window, GtkWidget ** menubar) {
8612   int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
8613   GtkItemFactory *item_factory;
8614   GtkAccelGroup *accel_group;
8615
8616   accel_group = gtk_accel_group_new();
8617
8618   /* This function initializes the item factory.
8619      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
8620               or GTK_TYPE_OPTION_MENU.
8621      Param 2: The path of the menu.
8622      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
8623               the accelerator table while generating menus.
8624   */
8625
8626   item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", 
8627                                        accel_group);
8628
8629   /* This function generates the menu items. Pass the item factory,
8630      the number of items in the array, the array itself, and any
8631      callback data for the the menu items. */
8632   gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
8633
8634   /* Attach the new accelerator group to the window. */
8635   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
8636
8637   if (menubar)
8638     /* Finally, return the actual menu bar created by the item factory. */ 
8639     *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
8640 }
8641
8642 int main(int argc, char *argv[]) {
8643   GtkWidget *window;
8644   GtkWidget *main_vbox;
8645   GtkWidget *menubar;
8646   
8647   gtk_init(&amp;argc, &amp;argv);
8648   
8649   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
8650   gtk_signal_connect(GTK_OBJECT(window), "destroy", 
8651                      GTK_SIGNAL_FUNC(gtk_main_quit), 
8652                      "WM destroy");
8653   gtk_window_set_title(GTK_WINDOW(window), "Item Factory");
8654   gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);
8655   
8656   main_vbox = gtk_vbox_new(FALSE, 1);
8657   gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
8658   gtk_container_add(GTK_CONTAINER(window), main_vbox);
8659   gtk_widget_show(main_vbox);
8660   
8661   get_main_menu(window, &amp;menubar);
8662   gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
8663   gtk_widget_show(menubar);
8664   
8665   gtk_widget_show(window);
8666   gtk_main();
8667   
8668   return(0);
8669 }
8670 /* example-end */
8671 </verb></tscreen>
8672
8673
8674 For now, there's only this example.  An explanation and lots 'o' comments
8675 will follow later.
8676
8677 <!-- ***************************************************************** -->
8678 <sect> Text Widget
8679 <!-- ***************************************************************** -->
8680 <p>
8681 The Text widget allows multiple lines of text to be displayed and
8682 edited.  It supports both multi-colored and multi-font text, allowing
8683 them to be mixed in any way we wish. It also has a wide set of key
8684 based text editing commands, which are compatible with Emacs.
8685
8686 The text widget supports full cut-and-paste facilities, including the
8687 use of double- and triple-click to select a word and a whole line,
8688 respectively.
8689
8690 <!-- ----------------------------------------------------------------- -->
8691 <sect1>Creating and Configuring a Text box
8692 <p>
8693 There is only one function for creating a new Text widget.
8694
8695 <tscreen><verb>
8696 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
8697                          GtkAdjustment *vadj );
8698 </verb></tscreen>
8699
8700 The arguments allow us to give the Text widget pointers to Adjustments
8701 that can be used to track the viewing position of the widget. Passing
8702 NULL values to either or both of these arguments will cause the
8703 gtk_text_new function to create its own.
8704
8705 <tscreen><verb>
8706 void gtk_text_set_adjustments( GtkText       *text,
8707                                GtkAdjustment *hadj,
8708                                GtkAdjustment *vadj );
8709 </verb></tscreen>
8710
8711 The above function allows the horizontal and vertical adjustments of a
8712 text widget to be changed at any time.
8713
8714 The text widget will not automatically create its own scrollbars when
8715 the amount of text to be displayed is too long for the display
8716 window. We therefore have to create and add them to the display layout
8717 ourselves.
8718
8719 <tscreen><verb>
8720   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
8721   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
8722   gtk_widget_show (vscrollbar);
8723 </verb></tscreen>
8724
8725 The above code snippet creates a new vertical scrollbar, and attaches
8726 it to the vertical adjustment of the text widget, <tt/text/. It then
8727 packs it into a box in the normal way.
8728
8729 Note, currently the GtkText widget does not support horizontal
8730 scrollbars.
8731
8732 There are two main ways in which a Text widget can be used: to allow
8733 the user to edit a body of text, or to allow us to display multiple
8734 lines of text to the user. In order for us to switch between these
8735 modes of operation, the text widget has the following function:
8736
8737 <tscreen><verb>
8738 void gtk_text_set_editable( GtkText *text,
8739                             gint     editable );
8740 </verb></tscreen>
8741
8742 The <tt/editable/ argument is a TRUE or FALSE value that specifies
8743 whether the user is permitted to edit the contents of the Text
8744 widget. When the text widget is editable, it will display a cursor at
8745 the current insertion point.
8746
8747 You are not, however, restricted to just using the text widget in
8748 these two modes. You can toggle the editable state of the text widget
8749 at any time, and can insert text at any time.
8750
8751 The text widget wraps lines of text that are too long to fit onto a
8752 single line of the display window. Its default behaviour is to break
8753 words across line breaks. This can be changed using the next function:
8754
8755 <tscreen><verb>
8756 void gtk_text_set_word_wrap( GtkText *text,
8757                              gint     word_wrap );
8758 </verb></tscreen>
8759
8760 Using this function allows us to specify that the text widget should
8761 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
8762 TRUE or FALSE value.
8763
8764 <!-- ----------------------------------------------------------------- -->
8765 <sect1>Text Manipulation
8766 <P>
8767 The current insertion point of a Text widget can be set using
8768 <tscreen><verb>
8769 void gtk_text_set_point( GtkText *text,
8770                          guint    index );
8771 </verb></tscreen>
8772
8773 where <tt/index/ is the position to set the insertion point.
8774
8775 Analogous to this is the function for getting the current insertion
8776 point:
8777
8778 <tscreen><verb>
8779 guint gtk_text_get_point( GtkText *text );
8780 </verb></tscreen>
8781
8782 A function that is useful in combination with the above two functions
8783 is
8784
8785 <tscreen><verb>
8786 guint gtk_text_get_length( GtkText *text );
8787 </verb></tscreen>
8788
8789 which returns the current length of the Text widget. The length is the
8790 number of characters that are within the text block of the widget,
8791 including characters such as carriage-return, which marks the end of
8792 lines.
8793
8794 In order to insert text at the current insertion point of a Text
8795 widget, the function gtk_text_insert is used, which also allows us to
8796 specify background and foreground colors and a font for the text.
8797
8798 <tscreen><verb>
8799 void gtk_text_insert( GtkText    *text,
8800                       GdkFont    *font,
8801                       GdkColor   *fore,
8802                       GdkColor   *back,
8803                       const char *chars,
8804                       gint        length );
8805 </verb></tscreen>
8806
8807 Passing a value of <tt/NULL/ in as the value for the foreground color,
8808 background colour or font will result in the values set within the
8809 widget style to be used. Using a value of <tt/-1/ for the length
8810 parameter will result in the whole of the text string given being
8811 inserted.
8812
8813 The text widget is one of the few within GTK that redraws itself
8814 dynamically, outside of the gtk_main function. This means that all
8815 changes to the contents of the text widget take effect
8816 immediately. This may be undesirable when performing multiple changes
8817 to the text widget. In order to allow us to perform multiple updates
8818 to the text widget without it continuously redrawing, we can freeze
8819 the widget, which temporarily stops it from automatically redrawing
8820 itself every time it is changed. We can then thaw the widget after our
8821 updates are complete.
8822
8823 The following two functions perform this freeze and thaw action:
8824
8825 <tscreen><verb>
8826 void gtk_text_freeze( GtkText *text );
8827
8828 void gtk_text_thaw( GtkText *text );         
8829 </verb></tscreen>
8830
8831 Text is deleted from the text widget relative to the current insertion
8832 point by the following two functions. The return value is a TRUE or
8833 FALSE indicator of whether the operation was successful.
8834
8835 <tscreen><verb>
8836 gint gtk_text_backward_delete( GtkText *text,
8837                                guint    nchars );
8838
8839 gint gtk_text_forward_delete ( GtkText *text,
8840                                guint    nchars );
8841 </verb></tscreen>
8842
8843 If you want to retrieve the contents of the text widget, then the
8844 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
8845 character at position <tt/index/ within the text widget <tt/t/.
8846
8847 To retrieve larger blocks of text, we can use the function
8848
8849 <tscreen><verb>
8850 gchar *gtk_editable_get_chars( GtkEditable *editable,
8851                                gint         start_pos,
8852                                gint         end_pos );   
8853 </verb></tscreen>
8854
8855 This is a function of the parent class of the text widget. A value of
8856 -1 as <tt/end_pos/ signifies the end of the text. The index of the
8857 text starts at 0.
8858
8859 The function allocates a new chunk of memory for the text block, so
8860 don't forget to free it with a call to g_free when you have finished
8861 with it.
8862  
8863 <!-- ----------------------------------------------------------------- -->
8864 <sect1>Keyboard Shortcuts
8865 <p>
8866 The text widget has a number of pre-installed keyboard shortcuts for
8867 common editing, motion and selection functions. These are accessed
8868 using Control and Alt key combinations.
8869
8870 In addition to these, holding down the Control key whilst using cursor
8871 key movement will move the cursor by words rather than
8872 characters. Holding down Shift whilst using cursor movement will
8873 extend the selection.
8874
8875 <sect2>Motion Shortcuts
8876 <p>
8877 <itemize>
8878 <item> Ctrl-A   Beginning of line
8879 <item> Ctrl-E   End of line
8880 <item> Ctrl-N   Next Line
8881 <item> Ctrl-P   Previous Line
8882 <item> Ctrl-B   Backward one character
8883 <item> Ctrl-F   Forward one character
8884 <item> Alt-B    Backward one word
8885 <item> Alt-F    Forward one word
8886 </itemize>
8887
8888 <sect2>Editing Shortcuts
8889 <p>
8890 <itemize>
8891 <item> Ctrl-H   Delete Backward Character (Backspace)
8892 <item> Ctrl-D   Delete Forward Character (Delete)
8893 <item> Ctrl-W   Delete Backward Word
8894 <item> Alt-D    Delete Forward Word
8895 <item> Ctrl-K   Delete to end of line
8896 <item> Ctrl-U   Delete line
8897 </itemize>
8898
8899 <sect2>Selection Shortcuts
8900 <p>
8901 <itemize>
8902 <item> Ctrl-X   Cut to clipboard
8903 <item> Ctrl-C   Copy to clipboard
8904 <item> Ctrl-V   Paste from clipboard
8905 </itemize>
8906
8907 <!-- ----------------------------------------------------------------- -->
8908 <sect1>A GtkText Example
8909 <p>
8910 <tscreen><verb>
8911 /* example-start text text.c */
8912
8913 /* text.c */
8914
8915 #include <stdio.h>
8916 #include <gtk/gtk.h>
8917
8918 void text_toggle_editable (GtkWidget *checkbutton,
8919                            GtkWidget *text)
8920 {
8921   gtk_text_set_editable(GTK_TEXT(text),
8922                         GTK_TOGGLE_BUTTON(checkbutton)->active);
8923 }
8924
8925 void text_toggle_word_wrap (GtkWidget *checkbutton,
8926                             GtkWidget *text)
8927 {
8928   gtk_text_set_word_wrap(GTK_TEXT(text),
8929                          GTK_TOGGLE_BUTTON(checkbutton)->active);
8930 }
8931
8932 void close_application( GtkWidget *widget, gpointer data )
8933 {
8934        gtk_main_quit();
8935 }
8936
8937 int main (int argc, char *argv[])
8938 {
8939   GtkWidget *window;
8940   GtkWidget *box1;
8941   GtkWidget *box2;
8942   GtkWidget *hbox;
8943   GtkWidget *button;
8944   GtkWidget *check;
8945   GtkWidget *separator;
8946   GtkWidget *table;
8947   GtkWidget *vscrollbar;
8948   GtkWidget *text;
8949   GdkColormap *cmap;
8950   GdkColor colour;
8951   GdkFont *fixed_font;
8952
8953   FILE *infile;
8954
8955   gtk_init (&amp;argc, &amp;argv);
8956  
8957   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8958   gtk_widget_set_usize (window, 600, 500);
8959   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
8960   gtk_signal_connect (GTK_OBJECT (window), "destroy",
8961                       GTK_SIGNAL_FUNC(close_application),
8962                       NULL);
8963   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
8964   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8965   
8966   
8967   box1 = gtk_vbox_new (FALSE, 0);
8968   gtk_container_add (GTK_CONTAINER (window), box1);
8969   gtk_widget_show (box1);
8970   
8971   
8972   box2 = gtk_vbox_new (FALSE, 10);
8973   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8974   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
8975   gtk_widget_show (box2);
8976   
8977   
8978   table = gtk_table_new (2, 2, FALSE);
8979   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
8980   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
8981   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
8982   gtk_widget_show (table);
8983   
8984   /* Create the GtkText widget */
8985   text = gtk_text_new (NULL, NULL);
8986   gtk_text_set_editable (GTK_TEXT (text), TRUE);
8987   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
8988                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
8989                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
8990   gtk_widget_show (text);
8991
8992   /* Add a vertical scrollbar to the GtkText widget */
8993   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
8994   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
8995                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
8996   gtk_widget_show (vscrollbar);
8997
8998   /* Get the system colour map and allocate the colour red */
8999   cmap = gdk_colormap_get_system();
9000   colour.red = 0xffff;
9001   colour.green = 0;
9002   colour.blue = 0;
9003   if (!gdk_color_alloc(cmap, &amp;colour)) {
9004     g_error("couldn't allocate colour");
9005   }
9006
9007   /* Load a fixed font */
9008   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
9009
9010   /* Realizing a widget creates a window for it, ready for us to insert some text */
9011   gtk_widget_realize (text);
9012
9013   /* Freeze the text widget, ready for multiple updates */
9014   gtk_text_freeze (GTK_TEXT (text));
9015   
9016   /* Insert some coloured text */
9017   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9018                    "Supports ", -1);
9019   gtk_text_insert (GTK_TEXT (text), NULL, &amp;colour, NULL,
9020                    "colored ", -1);
9021   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9022                    "text and different ", -1);
9023   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
9024                    "fonts\n\n", -1);
9025   
9026   /* Load the file text.c into the text window */
9027
9028   infile = fopen("text.c", "r");
9029   
9030   if (infile) {
9031     char buffer[1024];
9032     int nchars;
9033     
9034     while (1)
9035       {
9036         nchars = fread(buffer, 1, 1024, infile);
9037         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
9038                          NULL, buffer, nchars);
9039         
9040         if (nchars < 1024)
9041           break;
9042       }
9043     
9044     fclose (infile);
9045   }
9046
9047   /* Thaw the text widget, allowing the updates to become visible */  
9048   gtk_text_thaw (GTK_TEXT (text));
9049   
9050   hbox = gtk_hbutton_box_new ();
9051   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9052   gtk_widget_show (hbox);
9053
9054   check = gtk_check_button_new_with_label("Editable");
9055   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9056   gtk_signal_connect (GTK_OBJECT(check), "toggled",
9057                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
9058   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9059   gtk_widget_show (check);
9060   check = gtk_check_button_new_with_label("Wrap Words");
9061   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9062   gtk_signal_connect (GTK_OBJECT(check), "toggled",
9063                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
9064   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9065   gtk_widget_show (check);
9066
9067   separator = gtk_hseparator_new ();
9068   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9069   gtk_widget_show (separator);
9070
9071   box2 = gtk_vbox_new (FALSE, 10);
9072   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9073   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9074   gtk_widget_show (box2);
9075   
9076   button = gtk_button_new_with_label ("close");
9077   gtk_signal_connect (GTK_OBJECT (button), "clicked",
9078                       GTK_SIGNAL_FUNC(close_application),
9079                       NULL);
9080   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9081   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9082   gtk_widget_grab_default (button);
9083   gtk_widget_show (button);
9084
9085   gtk_widget_show (window);
9086
9087   gtk_main ();
9088   
9089   return(0);       
9090 }
9091 /* example-end */
9092 </verb></tscreen>
9093
9094
9095 <!-- ***************************************************************** -->
9096 <sect> Undocumented Widgets
9097 <!-- ***************************************************************** -->
9098 <p>
9099 These all require authors! :) Please consider contributing to our
9100 tutorial.
9101
9102 If you must use one of these widgets that are undocumented, I strongly
9103 suggest you take a look at their respective header files in the GTK
9104 distribution. GTK's function names are very descriptive. Once you
9105 have an understanding of how things work, it's not difficult to figure
9106 out how to use a widget simply by looking at its function
9107 declarations. This, along with a few examples from others' code, and
9108 it should be no problem.
9109
9110 When you do come to understand all the functions of a new undocumented
9111 widget, please consider writing a tutorial on it so others may benefit
9112 from your time.
9113
9114 <!-- ----------------------------------------------------------------- -->
9115 <sect1> Alignment
9116 <p>
9117 <!-- ----------------------------------------------------------------- -->
9118 <sect1> Arrows
9119 <p>
9120 <!-- ----------------------------------------------------------------- -->
9121 <sect1> Button Box(es)
9122 <p>
9123 <!-- ----------------------------------------------------------------- -->
9124 <sect1> Calendar
9125 <p>
9126 <!-- ----------------------------------------------------------------- -->
9127 <sect1> Combo box
9128 <p>
9129 <!-- ----------------------------------------------------------------- -->
9130 <sect1> CTree
9131 <p>
9132 <!-- ----------------------------------------------------------------- -->
9133 <sect1> Curves
9134 <p>
9135 <!-- ----------------------------------------------------------------- -->
9136 <sect1> Dialog boxes
9137 <p>
9138 <!-- ----------------------------------------------------------------- -->
9139 <sect1> Drawing Area
9140 <p>
9141 <!-- ----------------------------------------------------------------- -->
9142 <sect1> Fixed Container
9143 <p>
9144 <!-- ----------------------------------------------------------------- -->
9145 <sect1> Frame
9146 <p>
9147 <!-- ----------------------------------------------------------------- -->
9148 <sect1> Font Selection Dialog
9149 <p>
9150 <!-- ----------------------------------------------------------------- -->
9151 <sect1> Gamma Curve
9152 <p>
9153 <!-- ----------------------------------------------------------------- -->
9154 <sect1> Image
9155 <p>
9156 <!-- ----------------------------------------------------------------- -->
9157 <sect1> Layout
9158 <p>
9159 <!-- ----------------------------------------------------------------- -->
9160 <sect1> Packer
9161 <p>
9162 <!-- ----------------------------------------------------------------- -->
9163 <sect1> Plugs and Sockets
9164 <p>
9165 <!-- ----------------------------------------------------------------- -->
9166 <sect1> Preview
9167 <p>
9168 <!-- ----------------------------------------------------------------- -->
9169 <sect1> Spin Button
9170 <p>
9171 <!-- ----------------------------------------------------------------- -->
9172 <sect1> Viewport
9173 <p>
9174
9175 <!--
9176
9177 (This may need to be rewritten to follow the style of the rest of the tutorial)
9178
9179 <tscreen><verb>
9180
9181 Previews serve a number of purposes in GIMP/GTK. The most important one is
9182 this. High quality images may take up to tens of megabytes of memory - easy!
9183 Any operation on an image that big is bound to take a long time. If it takes
9184 you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after
9185 you make an error) to choose the desired modification, it make take you
9186 literally hours to make the right one - if you don't run out of memory
9187 first. People who have spent hours in color darkrooms know the feeling.
9188 Previews to the rescue!
9189
9190 But the annoyance of the delay is not the only issue. Oftentimes it is
9191 helpful to compare the Before and After versions side-by-side or at least
9192 back-to-back. If you're working with big images and 10 second delays,
9193 obtaining the Before and After impressions is, to say the least, difficult.
9194 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
9195 out for most people, while back-to-back is more like back-to-1001, 1002,
9196 ..., 1010-back! Previews to the rescue!
9197
9198 But there's more. Previews allow for side-by-side pre-previews. In other
9199 words, you write a plug-in (e.g. the filterpack simulation) which would have
9200 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
9201 An approach like this acts as a sort of a preview palette and is very
9202 effective for subtle changes. Let's go previews!
9203
9204 There's more. For certain plug-ins real-time image-specific human
9205 intervention maybe necessary. In the SuperNova plug-in, for example, the
9206 user is asked to enter the coordinates of the center of the future
9207 supernova. The easiest way to do this, really, is to present the user with a
9208 preview and ask him to interactively select the spot. Let's go previews!
9209
9210 Finally, a couple of misc uses. One can use previews even when not working
9211 with big images. For example, they are useful when rendering complicated
9212 patterns. (Just check out the venerable Diffraction plug-in + many other
9213 ones!) As another example, take a look at the colormap rotation plug-in
9214 (work in progress). You can also use previews for little logos inside you
9215 plug-ins and even for an image of yourself, The Author. Let's go previews!
9216
9217 When Not to Use Previews
9218
9219 Don't use previews for graphs, drawing etc. GDK is much faster for that. Use
9220 previews only for rendered images!
9221
9222 Let's go previews!
9223
9224 You can stick a preview into just about anything. In a vbox, an hbox, a
9225 table, a button, etc. But they look their best in tight frames around them.
9226 Previews by themselves do not have borders and look flat without them. (Of
9227 course, if the flat look is what you want...) Tight frames provide the
9228 necessary borders.
9229
9230                                [Image][Image]
9231
9232 Previews in many ways are like any other widgets in GTK (whatever that
9233 means) except they possess an additional feature: they need to be filled with
9234 some sort of an image! First, we will deal exclusively with the GTK aspect
9235 of previews and then we'll discuss how to fill them.
9236
9237 GtkWidget *preview!
9238
9239 Without any ado:
9240
9241                               /* Create a preview widget,
9242                               set its size, an show it */
9243 GtkWidget *preview;
9244 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
9245                               /*Other option:
9246                               GTK_PREVIEW_GRAYSCALE);*/
9247 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
9248 gtk_widget_show(preview);
9249 my_preview_rendering_function(preview);
9250
9251 Oh yeah, like I said, previews look good inside frames, so how about:
9252
9253 GtkWidget *create_a_preview(int        Width,
9254                             int        Height,
9255                             int        Colorfulness)
9256 {
9257   GtkWidget *preview;
9258   GtkWidget *frame;
9259   
9260   frame = gtk_frame_new(NULL);
9261   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
9262   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
9263   gtk_widget_show(frame);
9264
9265   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
9266                                        :GTK_PREVIEW_GRAYSCALE);
9267   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
9268   gtk_container_add(GTK_CONTAINER(frame),preview);
9269   gtk_widget_show(preview);
9270
9271   my_preview_rendering_function(preview);
9272   return frame;
9273 }
9274
9275 That's my basic preview. This routine returns the "parent" frame so you can
9276 place it somewhere else in your interface. Of course, you can pass the
9277 parent frame to this routine as a parameter. In many situations, however,
9278 the contents of the preview are changed continually by your application. In
9279 this case you may want to pass a pointer to the preview to a
9280 "create_a_preview()" and thus have control of it later.
9281
9282 One more important note that may one day save you a lot of time. Sometimes
9283 it is desirable to label you preview. For example, you may label the preview
9284 containing the original image as "Original" and the one containing the
9285 modified image as "Less Original". It might occur to you to pack the
9286 preview along with the appropriate label into a vbox. The unexpected caveat
9287 is that if the label is wider than the preview (which may happen for a
9288 variety of reasons unforseeable to you, from the dynamic decision on the
9289 size of the preview to the size of the font) the frame expands and no longer
9290 fits tightly over the preview. The same problem can probably arise in other
9291 situations as well.
9292
9293                                    [Image]
9294
9295 The solution is to place the preview and the label into a 2x1 table and by
9296 attaching them with the following parameters (this is one possible variations
9297 of course. The key is no GTK_FILL in the second attachment):
9298
9299 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
9300                  0,
9301                  GTK_EXPAND|GTK_FILL,
9302                  0,0);
9303 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
9304                  GTK_EXPAND,
9305                  GTK_EXPAND,
9306                  0,0);
9307
9308
9309 And here's the result:
9310
9311                                    [Image]
9312
9313 Misc
9314
9315 Making a preview clickable is achieved most easily by placing it in a
9316 button. It also adds a nice border around the preview and you may not even
9317 need to place it in a frame. See the Filter Pack Simulation plug-in for an
9318 example.
9319
9320 This is pretty much it as far as GTK is concerned.
9321
9322 Filling In a Preview
9323
9324 In order to familiarize ourselves with the basics of filling in previews,
9325 let's create the following pattern (contrived by trial and error):
9326
9327                                    [Image]
9328
9329 void
9330 my_preview_rendering_function(GtkWidget     *preview)
9331 {
9332 #define SIZE 100
9333 #define HALF (SIZE/2)
9334
9335   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
9336   gint i, j;                             /* Coordinates    */
9337   double r, alpha, x, y;
9338
9339   if (preview==NULL) return; /* I usually add this when I want */
9340                              /* to avoid silly crashes. You    */
9341                              /* should probably make sure that */
9342                              /* everything has been nicely     */
9343                              /* initialized!                   */
9344   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
9345                                          /* glib.h contains ABS(x).   */
9346         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
9347         row[i*3+1] = 128;                /* Define Green              */
9348         row[i*3+2] = 224;                /* Define Blue               */
9349       }                                  /* "+0" is for alignment!    */
9350       else {
9351         row[i*3+0] = r*255;
9352         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
9353         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
9354       }
9355     }
9356     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
9357     /* Insert "row" into "preview" starting at the point with  */
9358     /* coordinates (0,j) first column, j_th row extending SIZE */
9359     /* pixels to the right */
9360   }
9361
9362   free(row); /* save some space */
9363   gtk_widget_draw(preview,NULL); /* what does this do? */
9364   gdk_flush(); /* or this? */
9365 }
9366
9367 Non-GIMP users can have probably seen enough to do a lot of things already.
9368 For the GIMP users I have a few pointers to add.
9369
9370 Image Preview
9371
9372 It is probably wise to keep a reduced version of the image around with just
9373 enough pixels to fill the preview. This is done by selecting every n'th
9374 pixel where n is the ratio of the size of the image to the size of the
9375 preview. All further operations (including filling in the previews) are then
9376 performed on the reduced number of pixels only. The following is my
9377 implementation of reducing the image. (Keep in mind that I've had only basic
9378 C!)
9379
9380 (UNTESTED CODE ALERT!!!)
9381
9382 typedef struct {
9383   gint      width;
9384   gint      height;
9385   gint      bbp;
9386   guchar    *rgb;
9387   guchar    *mask;
9388 } ReducedImage;
9389
9390 enum {
9391   SELECTION_ONLY,
9392   SELECTION_IN_CONTEXT,
9393   ENTIRE_IMAGE
9394 };
9395
9396 ReducedImage *Reduce_The_Image(GDrawable *drawable,
9397                                GDrawable *mask,
9398                                gint LongerSize,
9399                                gint Selection)
9400 {
9401   /* This function reduced the image down to the the selected preview size */
9402   /* The preview size is determine by LongerSize, i.e. the greater of the  */
9403   /* two dimensions. Works for RGB images only!                            */
9404   gint RH, RW;          /* Reduced height and reduced width                */
9405   gint width, height;   /* Width and Height of the area being reduced      */
9406   gint bytes=drawable->bpp;
9407   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
9408
9409   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
9410   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
9411   GPixelRgn srcPR, srcMask;
9412   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
9413                              /* image.                                     */
9414
9415   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
9416   width  = x2-x1;
9417   height = y2-y1;
9418   /* If there's a SELECTION, we got its bounds!)
9419
9420   if (width != drawable->width &amp;&amp; height != drawable->height)
9421     NoSelectionMade=FALSE;
9422   /* Become aware of whether the user has made an active selection   */
9423   /* This will become important later, when creating a reduced mask. */
9424
9425   /* If we want to preview the entire image, overrule the above!  */
9426   /* Of course, if no selection has been made, this does nothing! */
9427   if (Selection==ENTIRE_IMAGE) {
9428     x1=0;
9429     x2=drawable->width;
9430     y1=0;
9431     y2=drawable->height;
9432   }
9433
9434   /* If we want to preview a selection with some surrounding area we */
9435   /* have to expand it a little bit. Consider it a bit of a riddle. */
9436   if (Selection==SELECTION_IN_CONTEXT) {
9437     x1=MAX(0,                x1-width/2.0);
9438     x2=MIN(drawable->width,  x2+width/2.0);
9439     y1=MAX(0,                y1-height/2.0);
9440     y2=MIN(drawable->height, y2+height/2.0);
9441   }
9442
9443   /* How we can determine the width and the height of the area being */
9444   /* reduced.                                                        */
9445   width  = x2-x1;
9446   height = y2-y1;
9447
9448   /* The lines below determine which dimension is to be the longer   */
9449   /* side. The idea borrowed from the supernova plug-in. I suspect I */
9450   /* could've thought of it myself, but the truth must be told.      */
9451   /* Plagiarism stinks!                                               */
9452   if (width>height) {
9453     RW=LongerSize;
9454     RH=(float) height * (float) LongerSize/ (float) width;
9455   }
9456   else {
9457     RH=LongerSize;
9458     RW=(float)width * (float) LongerSize/ (float) height;
9459   }
9460
9461   /* The entire image is stretched into a string! */
9462   tempRGB   = (guchar *) malloc(RW*RH*bytes);
9463   tempmask  = (guchar *) malloc(RW*RH);
9464
9465   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height, FALSE, FALSE);
9466   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height, FALSE, FALSE);
9467
9468   /* Grab enough to save a row of image and a row of mask. */
9469   src_row       = (guchar *) malloc (width*bytes);
9470   src_mask_row  = (guchar *) malloc (width);
9471
9472   for (i=0; i < RH; i++) {
9473     whichrow=(float)i*(float)height/(float)RH;
9474     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
9475     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
9476
9477     for (j=0; j < RW; j++) {
9478       whichcol=(float)j*(float)width/(float)RW;
9479
9480       /* No selection made = each point is completely selected! */
9481       if (NoSelectionMade)
9482         tempmask[i*RW+j]=255;
9483       else
9484         tempmask[i*RW+j]=src_mask_row[whichcol];
9485
9486       /* Add the row to the one long string which now contains the image! */
9487       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
9488       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
9489       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
9490
9491       /* Hold on to the alpha as well */
9492       if (bytes==4)
9493         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
9494     }
9495   }
9496   temp->bpp=bytes;
9497   temp->width=RW;
9498   temp->height=RH;
9499   temp->rgb=tempRGB;
9500   temp->mask=tempmask;
9501   return temp;
9502 }
9503
9504 The following is a preview function which used the same ReducedImage type!
9505 Note that it uses fakes transparency (if one is present by means of
9506 fake_transparency which is defined as follows:
9507
9508 gint fake_transparency(gint i, gint j)
9509 {
9510   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
9511     return 64;
9512   else
9513     return 196;
9514 }
9515
9516 Now here's the preview function:
9517
9518 void
9519 my_preview_render_function(GtkWidget     *preview,
9520                            gint          changewhat,
9521                            gint          changewhich)
9522 {
9523   gint Inten, bytes=drawable->bpp;
9524   gint i, j, k;
9525   float partial;
9526   gint RW=reduced->width;
9527   gint RH=reduced->height;
9528   guchar *row=malloc(bytes*RW);;
9529
9530
9531   for (i=0; i < RH; i++) {
9532     for (j=0; j < RW; j++) {
9533
9534       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
9535       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
9536       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
9537
9538       if (bytes==4)
9539         for (k=0; k<3; k++) {
9540           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
9541           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
9542         }
9543     }
9544     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
9545   }
9546
9547   free(a);
9548   gtk_widget_draw(preview,NULL);
9549   gdk_flush();
9550 }
9551
9552 Applicable Routines
9553
9554 guint           gtk_preview_get_type           (void);
9555 /* No idea */
9556 void            gtk_preview_uninit             (void);
9557 /* No idea */
9558 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
9559 /* Described above */
9560 void            gtk_preview_size               (GtkPreview      *preview,
9561                                                 gint             width,
9562                                                 gint             height);
9563 /* Allows you to resize an existing preview.    */
9564 /* Apparently there's a bug in GTK which makes  */
9565 /* this process messy. A way to clean up a mess */
9566 /* is to manually resize the window containing  */
9567 /* the preview after resizing the preview.      */
9568
9569 void            gtk_preview_put                (GtkPreview      *preview,
9570                                                 GdkWindow       *window,
9571                                                 GdkGC           *gc,
9572                                                 gint             srcx,
9573                                                 gint             srcy,
9574                                                 gint             destx,
9575                                                 gint             desty,
9576                                                 gint             width,
9577                                                 gint             height);
9578 /* No idea */
9579
9580 void            gtk_preview_put_row            (GtkPreview      *preview,
9581                                                 guchar          *src,
9582                                                 guchar          *dest,
9583                                                 gint             x,
9584                                                 gint             y,
9585                                                 gint             w);
9586 /* No idea */
9587
9588 void            gtk_preview_draw_row           (GtkPreview      *preview,
9589                                                 guchar          *data,
9590                                                 gint             x,
9591                                                 gint             y,
9592                                                 gint             w);
9593 /* Described in the text */
9594
9595 void            gtk_preview_set_expand         (GtkPreview      *preview,
9596                                                 gint             expand);
9597 /* No idea */
9598
9599 /* No clue for any of the below but    */
9600 /* should be standard for most widgets */
9601 void            gtk_preview_set_gamma          (double           gamma);
9602 void            gtk_preview_set_color_cube     (guint            nred_shades,
9603                                                 guint            ngreen_shades,
9604                                                 guint            nblue_shades,
9605                                                 guint            ngray_shades);
9606 void            gtk_preview_set_install_cmap   (gint             install_cmap);
9607 void            gtk_preview_set_reserved       (gint             nreserved);
9608 GdkVisual*      gtk_preview_get_visual         (void);
9609 GdkColormap*    gtk_preview_get_cmap           (void);
9610 GtkPreviewInfo* gtk_preview_get_info           (void);
9611
9612 That's all, folks!
9613
9614 </verb></tscreen>
9615
9616 -->
9617
9618 <!-- ***************************************************************** -->
9619 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
9620 <!-- ***************************************************************** -->
9621 <p>
9622 This describes the functions used to operate on widgets.  These can be
9623 used to set style, padding, size etc.
9624
9625 (Maybe I should make a whole section on accelerators.)
9626
9627 <tscreen><verb>
9628 void gtk_widget_install_accelerator( GtkWidget           *widget,
9629                                      GtkAcceleratorTable *table,
9630                                      gchar               *signal_name,
9631                                      gchar                key,
9632                                      guint8               modifiers );
9633
9634 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
9635                                      GtkAcceleratorTable *table,
9636                                      gchar               *signal_name);
9637
9638 void gtk_widget_activate( GtkWidget *widget );
9639
9640 void gtk_widget_set_name( GtkWidget *widget,
9641                           gchar     *name );
9642
9643 gchar *gtk_widget_get_name( GtkWidget *widget );
9644
9645 void gtk_widget_set_sensitive( GtkWidget *widget,
9646                                gint       sensitive );
9647
9648 void gtk_widget_set_style( GtkWidget *widget,
9649                            GtkStyle  *style );
9650                                            
9651 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
9652
9653 GtkStyle *gtk_widget_get_default_style( void );
9654
9655 void gtk_widget_set_uposition( GtkWidget *widget,
9656                                gint       x,
9657                                gint       y );
9658
9659 void gtk_widget_set_usize( GtkWidget *widget,
9660                            gint       width,
9661                            gint       height );
9662
9663 void gtk_widget_grab_focus( GtkWidget *widget );
9664
9665 void gtk_widget_show( GtkWidget *widget );
9666
9667 void gtk_widget_hide( GtkWidget *widget );
9668 </verb></tscreen>
9669
9670 <!-- ***************************************************************** -->
9671 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
9672 <!-- ***************************************************************** -->
9673
9674 <!-- ----------------------------------------------------------------- -->
9675 <sect1>Timeouts
9676 <p>
9677 You may be wondering how you make GTK do useful work when in gtk_main.
9678 Well, you have several options. Using the following functions you can
9679 create a timeout function that will be called every "interval"
9680 milliseconds.
9681
9682 <tscreen><verb>
9683 gint gtk_timeout_add( guint32     interval,
9684                       GtkFunction function,
9685                       gpointer    data );
9686 </verb></tscreen>
9687
9688 The first argument is the number of milliseconds between calls to your
9689 function. The second argument is the function you wish to have called,
9690 and the third, the data passed to this callback function. The return
9691 value is an integer "tag" which may be used to stop the timeout by
9692 calling:
9693
9694 <tscreen><verb>
9695 void gtk_timeout_remove( gint tag );
9696 </verb></tscreen>
9697
9698 You may also stop the timeout function by returning zero or FALSE from
9699 your callback function. Obviously this means if you want your function
9700 to continue to be called, it should return a non-zero value,
9701 i.e. TRUE.
9702
9703 The declaration of your callback should look something like this:
9704
9705 <tscreen><verb>
9706 gint timeout_callback( gpointer data );
9707 </verb></tscreen>
9708
9709 <!-- ----------------------------------------------------------------- -->
9710 <sect1>Monitoring IO
9711 <p>
9712 A nifty feature of GDK (the library that underlies GTK), is the
9713 ability to have it check for data on a file descriptor for you (as
9714 returned by open(2) or socket(2)). This is especially useful for
9715 networking applications. The function:
9716
9717 <tscreen><verb>
9718 gint gdk_input_add( gint              source,
9719                     GdkInputCondition condition,
9720                     GdkInputFunction  function,
9721                     gpointer          data );
9722 </verb></tscreen>
9723
9724 Where the first argument is the file descriptor you wish to have
9725 watched, and the second specifies what you want GDK to look for. This
9726 may be one of:
9727
9728 <itemize>
9729 <item>GDK_INPUT_READ - Call your function when there is data ready for
9730 reading on your file descriptor.
9731
9732 <item>GDK_INPUT_WRITE - Call your function when the file descriptor is
9733 ready for writing.
9734 </itemize>
9735
9736 As I'm sure you've figured out already, the third argument is the
9737 function you wish to have called when the above conditions are
9738 satisfied, and the fourth is the data to pass to this function.
9739
9740 The return value is a tag that may be used to stop GDK from monitoring
9741 this file descriptor using the following function.
9742
9743 <tscreen><verb>
9744 void gdk_input_remove( gint tag );
9745 </verb></tscreen>
9746
9747 The callback function should be declared as:
9748
9749 <tscreen><verb>
9750 void input_callback( gpointer          data,
9751                      gint              source, 
9752                      GdkInputCondition condition );
9753 </verb></tscreen>
9754
9755 Where <tt/source/ and <tt/condition/ are as specified above.
9756
9757 <!-- ----------------------------------------------------------------- -->
9758 <sect1>Idle Functions
9759 <p>
9760 <!-- TODO: Need to check on idle priorities - TRG -->
9761 What if you have a function you want called when nothing else is
9762 happening ?
9763
9764 <tscreen><verb>
9765 gint gtk_idle_add( GtkFunction function,
9766                    gpointer    data );
9767 </verb></tscreen>
9768
9769 This causes GTK to call the specified function whenever nothing else
9770 is happening.
9771
9772 <tscreen><verb>
9773 void gtk_idle_remove( gint tag );
9774 </verb></tscreen>
9775
9776 I won't explain the meaning of the arguments as they follow very much
9777 like the ones above. The function pointed to by the first argument to
9778 gtk_idle_add will be called whenever the opportunity arises. As with
9779 the others, returning FALSE will stop the idle function from being
9780 called.
9781
9782 <!-- ***************************************************************** -->
9783 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
9784 <!-- ***************************************************************** -->
9785
9786 <!-- ----------------------------------------------------------------- -->
9787 <sect1>Signal Functions
9788
9789 <!-- ----------------------------------------------------------------- -->
9790 <sect2>Connecting and Disconnecting Signal Handlers
9791 <p>
9792
9793 <tscreen><verb>
9794 guint gtk_signal_connect( GtkObject     *object,
9795                           const gchar   *name,
9796                           GtkSignalFunc  func,
9797                           gpointer       func_data );
9798
9799 guint gtk_signal_connect_after( GtkObject     *object,
9800                                 const gchar   *name,
9801                                 GtkSignalFunc  func,
9802                                 gpointer       func_data );
9803
9804 guint gtk_signal_connect_object( GtkObject     *object,
9805                                  const gchar   *name,
9806                                  GtkSignalFunc  func,
9807                                  GtkObject     *slot_object );
9808
9809 guint gtk_signal_connect_object_after( GtkObject     *object,
9810                                        const gchar   *name,
9811                                        GtkSignalFunc  func,
9812                                        GtkObject     *slot_object );
9813
9814 guint gtk_signal_connect_full( GtkObject          *object,
9815                                const gchar        *name,
9816                                GtkSignalFunc       func,
9817                                GtkCallbackMarshal  marshal,
9818                                gpointer            data,
9819                                GtkDestroyNotify    destroy_func,
9820                                gint                object_signal,
9821                                gint                after );
9822
9823 guint gtk_signal_connect_interp( GtkObject          *object,
9824                                  const gchar        *name,
9825                                  GtkCallbackMarshal  func,
9826                                  gpointer            data,
9827                                  GtkDestroyNotify    destroy_func,
9828                                  gint                after );
9829
9830 void gtk_signal_connect_object_while_alive( GtkObject     *object,
9831                                             const gchar   *signal,
9832                                             GtkSignalFunc  func,
9833                                             GtkObject     *alive_object );
9834
9835 void gtk_signal_connect_while_alive( GtkObject     *object,
9836                                      const gchar   *signal,
9837                                      GtkSignalFunc  func,
9838                                      gpointer       func_data,
9839                                      GtkObject     *alive_object );
9840
9841 void gtk_signal_disconnect( GtkObject *object,
9842                             guint      handler_id );
9843
9844 void gtk_signal_disconnect_by_func( GtkObject     *object,
9845                                     GtkSignalFunc  func,
9846                                     gpointer       data );
9847 </verb></tscreen>
9848
9849 <!-- ----------------------------------------------------------------- -->
9850 <sect2>Blocking and Unblocking Signal Handlers
9851 <p>
9852 <tscreen><verb>
9853 void gtk_signal_handler_block( GtkObject *object,
9854                                guint      handler_id);
9855
9856 void gtk_signal_handler_block_by_func( GtkObject     *object,
9857                                        GtkSignalFunc  func,
9858                                        gpointer       data );
9859
9860 void gtk_signal_handler_block_by_data( GtkObject *object,
9861                                        gpointer   data );
9862
9863 void gtk_signal_handler_unblock( GtkObject *object,
9864                                  guint      handler_id );
9865
9866 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
9867                                          GtkSignalFunc  func,
9868                                          gpointer       data );
9869
9870 void gtk_signal_handler_unblock_by_data( GtkObject *object,
9871                                          gpointer   data );
9872 </verb></tscreen>
9873
9874 <!-- ----------------------------------------------------------------- -->
9875 <sect2>Emitting and Stopping Signals
9876 <p>
9877 <tscreen><verb>
9878 void gtk_signal_emit( GtkObject *object,
9879                       guint      signal_id,
9880                       ... );
9881
9882 void gtk_signal_emit_by_name( GtkObject   *object,
9883                               const gchar *name,
9884                               ... );
9885
9886 void gtk_signal_emitv( GtkObject *object,
9887                        guint      signal_id,
9888                        GtkArg    *params );
9889
9890 void gtk_signal_emitv_by_name( GtkObject   *object,
9891                                const gchar *name,
9892                                GtkArg      *params );
9893
9894 guint gtk_signal_n_emissions( GtkObject *object,
9895                               guint      signal_id );
9896
9897 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
9898                                       const gchar *name );
9899
9900 void gtk_signal_emit_stop( GtkObject *object,
9901                            guint      signal_id );
9902
9903 void gtk_signal_emit_stop_by_name( GtkObject   *object,
9904                                    const gchar *name );
9905 </verb></tscreen>
9906
9907 <!-- ----------------------------------------------------------------- -->
9908 <sect1>Signal Emission and Propagation
9909 <p>
9910 Signal emission is the process wherby GTK runs all handlers for a
9911 specific object and signal.
9912
9913 First, note that the return value from a signal emission is the return
9914 value of the <em>last</em> handler executed. Since event signals are
9915 all of type GTK_RUN_LAST, this will be the default (GTK supplied)
9916 default handler, unless you connect with gtk_signal_connect_after().
9917
9918 The way an event (say GTK_BUTTON_PRESS) is handled, is:
9919 <itemize>
9920 <item>Start with the widget where the event occured.
9921
9922 <item>Emit the generic "event" signal. If that signal handler returns
9923 a value of TRUE, stop all processing.
9924
9925 <item>Otherwise, emit a specific, "button_press_event" signal. If that
9926 returns TRUE, stop all processing.
9927
9928 <item>Otherwise, go to the widget's parent, and repeat the above steps.
9929
9930 <item>Contimue until some signal handler returns TRUE, or until the
9931 top-level widget is reached.
9932 </itemize>
9933
9934 Some consequences of the above are:
9935 <itemize>
9936 <item>Your handler's return value will have no effect if there is a
9937 default handler, unless you connect with gtk_signal_connect_after().
9938
9939 <item>To prevent the default handler from being run, you need to
9940 connect with gtk_signal_connect() and use
9941 gtk_signal_emit_stop_by_name() - the return value only affects whether
9942 the signal is propagated, not the current emission.
9943 </itemize>
9944
9945 <!-- ***************************************************************** -->
9946 <sect>Managing Selections
9947 <!-- ***************************************************************** -->
9948
9949 <!-- ----------------------------------------------------------------- -->
9950 <sect1> Overview
9951 <p>
9952 One type of interprocess communication supported by GTK is
9953 <em>selections</em>. A selection identifies a chunk of data, for
9954 instance, a portion of text, selected by the user in some fashion, for
9955 instance, by dragging with the mouse. Only one application on a
9956 display, (the <em>owner</em>) can own a particular selection at one
9957 time, so when a selection is claimed by one application, the previous
9958 owner must indicate to the user that selection has been
9959 relinquished. Other applications can request the contents of a
9960 selection in different forms, called <em>targets</em>. There can be
9961 any number of selections, but most X applications only handle one, the
9962 <em>primary selection</em>.
9963
9964 In most cases, it isn't necessary for a GTK application to deal with
9965 selections itself. The standard widgets, such as the Entry widget,
9966 already have the capability to claim the selection when appropriate
9967 (e.g., when the user drags over text), and to retrieve the contents of
9968 the selection owned by another widget, or another application (e.g.,
9969 when the user clicks the second mouse button). However, there may be
9970 cases in which you want to give other widgets the ability to supply
9971 the selection, or you wish to retrieve targets not supported by
9972 default.
9973
9974 A fundamental concept needed to understand selection handling is that
9975 of the <em>atom</em>. An atom is an integer that uniquely identifies a
9976 string (on a certain display). Certain atoms are predefined by the X
9977 server, and in some cases there are constants in <tt>gtk.h</tt>
9978 corresponding to these atoms. For instance the constant
9979 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
9980 In other cases, you should use the functions
9981 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
9982 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
9983 selections and targets are identified by atoms.
9984
9985 <!-- ----------------------------------------------------------------- -->
9986 <sect1> Retrieving the selection
9987 <p>
9988 Retrieving the selection is an asynchronous process. To start the
9989 process, you call:
9990
9991 <tscreen><verb>
9992 gint gtk_selection_convert( GtkWidget *widget, 
9993                             GdkAtom    selection, 
9994                             GdkAtom    target,
9995                             guint32    time );
9996 </verb</tscreen>
9997
9998 This <em>converts</em> the selection into the form specified by
9999 <tt/target/. If at all possible, the time field should be the time
10000 from the event that triggered the selection. This helps make sure that
10001 events occur in the order that the user requested them. However, if it
10002 is not available (for instance, if the conversion was triggered by a
10003 "clicked" signal), then you can use the constant
10004 <tt>GDK_CURRENT_TIME</tt>.
10005
10006 When the selection owner responds to the request, a
10007 "selection_received" signal is sent to your application. The handler
10008 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
10009 structure, which is defined as:
10010
10011 <tscreen><verb>
10012 struct _GtkSelectionData
10013 {
10014   GdkAtom selection;
10015   GdkAtom target;
10016   GdkAtom type;
10017   gint    format;
10018   guchar *data;
10019   gint    length;
10020 };
10021 </verb></tscreen>
10022
10023 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
10024 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
10025 identifies the type of data returned by the selection owner. Some
10026 possible values are "STRING", a string of latin-1 characters, "ATOM",
10027 a series of atoms, "INTEGER", an integer, etc. Most targets can only
10028 return one type. <tt/format/ gives the length of the units (for
10029 instance characters) in bits. Usually, you don't care about this when
10030 receiving data. <tt>data</tt> is a pointer to the returned data, and
10031 <tt>length</tt> gives the length of the returned data, in bytes. If
10032 <tt>length</tt> is negative, then an error occurred and the selection
10033 could not be retrieved. This might happen if no application owned the
10034 selection, or if you requested a target that the application didn't
10035 support. The buffer is actually guaranteed to be one byte longer than
10036 <tt>length</tt>; the extra byte will always be zero, so it isn't
10037 necessary to make a copy of strings just to null terminate them.
10038
10039 In the following example, we retrieve the special target "TARGETS",
10040 which is a list of all targets into which the selection can be
10041 converted.
10042
10043 <tscreen><verb>
10044 /* example-start selection gettargets.c */
10045
10046 #include <gtk/gtk.h>
10047
10048 void selection_received (GtkWidget *widget, 
10049                          GtkSelectionData *selection_data, 
10050                          gpointer data);
10051
10052 /* Signal handler invoked when user clicks on the "Get Targets" button */
10053 void
10054 get_targets (GtkWidget *widget, gpointer data)
10055 {
10056   static GdkAtom targets_atom = GDK_NONE;
10057
10058   /* Get the atom corresponding to the string "TARGETS" */
10059   if (targets_atom == GDK_NONE)
10060     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
10061
10062   /* And request the "TARGETS" target for the primary selection */
10063   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
10064                          GDK_CURRENT_TIME);
10065 }
10066
10067 /* Signal handler called when the selections owner returns the data */
10068 void
10069 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
10070                     gpointer data)
10071 {
10072   GdkAtom *atoms;
10073   GList *item_list;
10074   int i;
10075
10076   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
10077   if (selection_data->length < 0)
10078     {
10079       g_print ("Selection retrieval failed\n");
10080       return;
10081     }
10082   /* Make sure we got the data in the expected form */
10083   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
10084     {
10085       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
10086       return;
10087     }
10088   
10089   /* Print out the atoms we received */
10090   atoms = (GdkAtom *)selection_data->data;
10091
10092   item_list = NULL;
10093   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
10094     {
10095       char *name;
10096       name = gdk_atom_name (atoms[i]);
10097       if (name != NULL)
10098         g_print ("%s\n",name);
10099       else
10100         g_print ("(bad atom)\n");
10101     }
10102
10103   return;
10104 }
10105
10106 int 
10107 main (int argc, char *argv[])
10108 {
10109   GtkWidget *window;
10110   GtkWidget *button;
10111   
10112   gtk_init (&amp;argc, &amp;argv);
10113
10114   /* Create the toplevel window */
10115
10116   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10117   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
10118   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10119
10120   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10121                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
10122
10123   /* Create a button the user can click to get targets */
10124
10125   button = gtk_button_new_with_label ("Get Targets");
10126   gtk_container_add (GTK_CONTAINER (window), button);
10127
10128   gtk_signal_connect (GTK_OBJECT(button), "clicked",
10129                       GTK_SIGNAL_FUNC (get_targets), NULL);
10130   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
10131                       GTK_SIGNAL_FUNC (selection_received), NULL);
10132
10133   gtk_widget_show (button);
10134   gtk_widget_show (window);
10135   
10136   gtk_main ();
10137   
10138   return 0;
10139 }
10140 /* example-end */
10141 </verb></tscreen>
10142
10143 <!-- ----------------------------------------------------------------- -->
10144 <sect1> Supplying the selection 
10145 <p>
10146 Supplying the selection is a bit more complicated. You must register 
10147 handlers that will be called when your selection is requested. For
10148 each selection/target pair you will handle, you make a call to:
10149
10150 <tscreen><verb>
10151 void gtk_selection_add_handler( GtkWidget            *widget, 
10152                                 GdkAtom               selection,
10153                                 GdkAtom               target,
10154                                 GtkSelectionFunction  function,
10155                                 GtkRemoveFunction     remove_func,
10156                                 gpointer              data );
10157 </verb></tscreen>
10158
10159 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
10160 this handler will manage.  <tt/remove_func/, if not
10161 NULL, will be called when the signal handler is removed. This is
10162 useful, for instance, for interpreted languages which need to
10163 keep track of a reference count for <tt/data/.
10164
10165 The callback function has the signature:
10166
10167 <tscreen><verb>
10168 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
10169                                       GtkSelectionData *selection_data,
10170                                       gpointer          data );
10171
10172 </verb></tscreen>
10173
10174 The GtkSelectionData is the same as above, but this time, we're
10175 responsible for filling in the fields <tt/type/, <tt/format/,
10176 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
10177 important here - the X server uses it to figure out whether the data
10178 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
10179 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
10180 function:
10181
10182 <tscreen><verb>
10183 void gtk_selection_data_set( GtkSelectionData *selection_data,
10184                              GdkAtom           type,
10185                              gint              format,
10186                              guchar           *data,
10187                              gint              length );
10188 </verb></tscreen>
10189
10190 This function takes care of properly making a copy of the data so that
10191 you don't have to worry about keeping it around. (You should not fill
10192 in the fields of the GtkSelectionData structure by hand.)
10193
10194 When prompted by the user, you claim ownership of the selection by
10195 calling:
10196
10197 <tscreen><verb>
10198 gint gtk_selection_owner_set( GtkWidget *widget,
10199                               GdkAtom    selection,
10200                               guint32    time );
10201 </verb></tscreen>
10202
10203 If another application claims ownership of the selection, you will
10204 receive a "selection_clear_event".
10205
10206 As an example of supplying the selection, the following program adds
10207 selection functionality to a toggle button. When the toggle button is
10208 depressed, the program claims the primary selection. The only target
10209 supported (aside from certain targets like "TARGETS" supplied by GTK
10210 itself), is the "STRING" target. When this target is requested, a
10211 string representation of the time is returned.
10212
10213 <tscreen><verb>
10214 /* example-start selection setselection.c */
10215
10216 #include <gtk/gtk.h>
10217 #include <time.h>
10218
10219 /* Callback when the user toggles the selection */
10220 void
10221 selection_toggled (GtkWidget *widget, gint *have_selection)
10222 {
10223   if (GTK_TOGGLE_BUTTON(widget)->active)
10224     {
10225       *have_selection = gtk_selection_owner_set (widget,
10226                                                  GDK_SELECTION_PRIMARY,
10227                                                  GDK_CURRENT_TIME);
10228       /* if claiming the selection failed, we return the button to
10229          the out state */
10230       if (!*have_selection)
10231         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
10232     }
10233   else
10234     {
10235       if (*have_selection)
10236         {
10237           /* Before clearing the selection by setting the owner to NULL,
10238              we check if we are the actual owner */
10239           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
10240             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
10241                                      GDK_CURRENT_TIME);
10242           *have_selection = FALSE;
10243         }
10244     }
10245 }
10246
10247 /* Called when another application claims the selection */
10248 gint
10249 selection_clear (GtkWidget *widget, GdkEventSelection *event,
10250                  gint *have_selection)
10251 {
10252   *have_selection = FALSE;
10253   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
10254
10255   return TRUE;
10256 }
10257
10258 /* Supplies the current time as the selection. */
10259 void
10260 selection_handle (GtkWidget *widget, 
10261                   GtkSelectionData *selection_data,
10262                   gpointer data)
10263 {
10264   gchar *timestr;
10265   time_t current_time;
10266
10267   current_time = time (NULL);
10268   timestr = asctime (localtime(&amp;current_time)); 
10269   /* When we return a single string, it should not be null terminated.
10270      That will be done for us */
10271
10272   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
10273                           8, timestr, strlen(timestr));
10274 }
10275
10276 int
10277 main (int argc, char *argv[])
10278 {
10279   GtkWidget *window;
10280
10281   GtkWidget *selection_button;
10282
10283   static int have_selection = FALSE;
10284   
10285   gtk_init (&amp;argc, &amp;argv);
10286
10287   /* Create the toplevel window */
10288
10289   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10290   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
10291   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10292
10293   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10294                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
10295
10296   /* Create a toggle button to act as the selection */
10297
10298   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
10299   gtk_container_add (GTK_CONTAINER (window), selection_button);
10300   gtk_widget_show (selection_button);
10301
10302   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
10303                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
10304   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
10305                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
10306
10307   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
10308                              GDK_SELECTION_TYPE_STRING,
10309                              selection_handle, NULL);
10310
10311   gtk_widget_show (selection_button);
10312   gtk_widget_show (window);
10313   
10314   gtk_main ();
10315   
10316   return 0;
10317 }
10318 /* example-end */
10319 </verb></tscreen>
10320
10321
10322 <!-- ***************************************************************** -->
10323 <sect>glib<label id="sec_glib">
10324 <!-- ***************************************************************** -->
10325 <p>
10326 glib provides many useful functions and definitions available for use
10327 when creating GDK and GTK applications. I will list them all here with
10328 a brief explanation. Many are duplicates of standard libc functions so
10329 I won't go into detail on those. This is mostly to be used as a reference,
10330 so you know what is available for use.
10331
10332 <!-- ----------------------------------------------------------------- -->
10333 <sect1>Definitions
10334 <p>
10335 Definitions for the extremes of many of the standard types are:
10336
10337 <tscreen><verb>
10338 G_MINFLOAT
10339 G_MAXFLOAT
10340 G_MINDOUBLE
10341 G_MAXDOUBLE
10342 G_MINSHORT
10343 G_MAXSHORT
10344 G_MININT
10345 G_MAXINT
10346 G_MINLONG
10347 G_MAXLONG
10348 </verb></tscreen>
10349
10350 Also, the following typedefs. The ones left unspecified are dynamically set
10351 depending on the architecture. Remember to avoid counting on the size of a
10352 pointer if you want to be portable! E.g., a pointer on an Alpha is 8 bytes, but 4
10353 on Intel.
10354
10355 <tscreen><verb>
10356 char   gchar;
10357 short  gshort;
10358 long   glong;
10359 int    gint;
10360 char   gboolean;
10361
10362 unsigned char   guchar;
10363 unsigned short  gushort;
10364 unsigned long   gulong;
10365 unsigned int    guint;
10366
10367 float   gfloat;
10368 double  gdouble;
10369 long double gldouble;
10370
10371 void* gpointer;
10372
10373 gint8
10374 guint8
10375 gint16
10376 guint16
10377 gint32
10378 guint32
10379 </verb></tscreen>
10380
10381 <!-- ----------------------------------------------------------------- -->
10382 <sect1>Doubly Linked Lists
10383 <p>
10384 The following functions are used to create, manage, and destroy doubly
10385 linked lists.  I assume you know what linked lists are, as it is beyond the scope
10386 of this document to explain them.  Of course, it's not required that you
10387 know these for general use of GTK, but they are nice to know.
10388
10389 <tscreen><verb>
10390 GList *g_list_alloc( void );
10391
10392 void g_list_free( GList *list );
10393
10394 void g_list_free_1( GList *list );
10395
10396 GList *g_list_append( GList     *list,
10397                       gpointer   data );
10398                            
10399 GList *g_list_prepend( GList    *list,
10400                        gpointer  data );
10401                         
10402 GList *g_list_insert( GList    *list,
10403                       gpointer  data,
10404                             gint      position );
10405
10406 GList *g_list_remove( GList    *list,
10407                       gpointer  data );
10408                            
10409 GList *g_list_remove_link( GList *list,
10410                            GList *link );
10411
10412 GList *g_list_reverse( GList *list );
10413
10414 GList *g_list_nth( GList *list,
10415                    gint   n );
10416                            
10417 GList *g_list_find( GList    *list,
10418                     gpointer  data );
10419
10420 GList *g_list_last( GList *list );
10421
10422 GList *g_list_first( GList *list );
10423
10424 gint g_list_length( GList *list );
10425
10426 void g_list_foreach( GList    *list,
10427                      GFunc     func,
10428                      gpointer  user_data );
10429 </verb></tscreen>                                             
10430
10431 <!-- ----------------------------------------------------------------- -->
10432 <sect1>Singly Linked Lists
10433 <p>
10434 Many of the above functions for singly linked lists are identical to the
10435 above. Here is a complete list:
10436 <tscreen><verb>
10437 GSList *g_slist_alloc( void );
10438
10439 void g_slist_free( GSList *list );
10440
10441 void g_slist_free_1( GSList *list );
10442
10443 GSList *g_slist_append( GSList   *list,
10444                         gpointer  data );
10445                 
10446 GSList *g_slist_prepend( GSList   *list,
10447                          gpointer  data );
10448                              
10449 GSList *g_slist_insert( GSList   *list,
10450                         gpointer  data,
10451                             gint      position );
10452                              
10453 GSList *g_slist_remove( GSList   *list,
10454                         gpointer  data );
10455                              
10456 GSList *g_slist_remove_link( GSList *list,
10457                              GSList *link );
10458                              
10459 GSList *g_slist_reverse( GSList *list );
10460
10461 GSList *g_slist_nth( GSList *list,
10462                      gint    n );
10463                              
10464 GSList *g_slist_find( GSList   *list,
10465                       gpointer  data );
10466                              
10467 GSList *g_slist_last( GSList *list );
10468
10469 gint g_slist_length( GSList *list );
10470
10471 void g_slist_foreach( GSList   *list,
10472                       GFunc     func,
10473                             gpointer  user_data );
10474         
10475 </verb></tscreen>
10476
10477 <!-- ----------------------------------------------------------------- -->
10478 <sect1>Memory Management
10479 <p>
10480 <tscreen><verb>
10481 gpointer g_malloc( gulong size );
10482 </verb></tscreen>
10483
10484 This is a replacement for malloc(). You do not need to check the return
10485 value as it is done for you in this function.
10486
10487 <tscreen><verb>
10488 gpointer g_malloc0( gulong size );
10489 </verb></tscreen>
10490
10491 Same as above, but zeroes the memory before returning a pointer to it.
10492
10493 <tscreen><verb>
10494 gpointer g_realloc( gpointer mem,
10495                     gulong   size );
10496 </verb></tscreen>
10497
10498 Relocates "size" bytes of memory starting at "mem".  Obviously, the
10499 memory should have been previously allocated.
10500
10501 <tscreen><verb>
10502 void g_free( gpointer mem );
10503 </verb></tscreen>
10504
10505 Frees memory. Easy one.
10506
10507 <tscreen><verb>
10508 void g_mem_profile( void );
10509 </verb></tscreen>
10510
10511 Dumps a profile of used memory, but requires that you add #define
10512 MEM_PROFILE to the top of glib/gmem.c and re-make and make install.
10513
10514 <tscreen><verb>
10515 void g_mem_check( gpointer mem );
10516 </verb></tscreen>
10517
10518 Checks that a memory location is valid.  Requires you add #define
10519 MEM_CHECK to the top of gmem.c and re-make and make install.
10520
10521 <!-- ----------------------------------------------------------------- -->
10522 <sect1>Timers
10523 <p>
10524 Timer functions..
10525
10526 <tscreen><verb>
10527 GTimer *g_timer_new( void );
10528
10529 void g_timer_destroy( GTimer *timer );
10530
10531 void g_timer_start( GTimer  *timer );
10532
10533 void g_timer_stop( GTimer  *timer );
10534
10535 void g_timer_reset( GTimer  *timer );
10536
10537 gdouble g_timer_elapsed( GTimer *timer,
10538                          gulong *microseconds );
10539 </verb></tscreen>                        
10540
10541 <!-- ----------------------------------------------------------------- -->
10542 <sect1>String Handling
10543 <p>
10544 A whole mess of string handling functions. They all look very interesting, and
10545 probably better for many purposes than the standard C string functions, but
10546 require documentation.
10547
10548 <tscreen><verb>
10549 GString *g_string_new( gchar *init );
10550
10551 void g_string_free( GString *string,
10552                     gint     free_segment );
10553                              
10554 GString *g_string_assign( GString *lval,
10555                           gchar   *rval );
10556                              
10557 GString *g_string_truncate( GString *string,
10558                             gint     len );
10559                              
10560 GString *g_string_append( GString *string,
10561                           gchar   *val );
10562                             
10563 GString *g_string_append_c( GString *string,
10564                             gchar    c );
10565         
10566 GString *g_string_prepend( GString *string,
10567                            gchar   *val );
10568                              
10569 GString *g_string_prepend_c( GString *string,
10570                              gchar    c );
10571         
10572 void g_string_sprintf( GString *string,
10573                        gchar   *fmt,
10574                        ...);
10575         
10576 void g_string_sprintfa ( GString *string,
10577                          gchar   *fmt,
10578                          ... );
10579 </verb></tscreen>                                                         
10580
10581 <!-- ----------------------------------------------------------------- -->
10582 <sect1>Utility and Error Functions
10583 <p>
10584 <tscreen><verb>
10585 gchar *g_strdup( const gchar *str );
10586 </verb></tscreen>
10587
10588 Replacement strdup function.  Copies the original strings contents to
10589 newly allocated memory, and returns a pointer to it.
10590
10591 <tscreen><verb>
10592 gchar *g_strerror( gint errnum );
10593 </verb></tscreen>
10594
10595 I recommend using this for all error messages.  It's much nicer, and more
10596 portable than perror() or others.  The output is usually of the form:
10597
10598 <tscreen><verb>
10599 program name:function that failed:file or further description:strerror
10600 </verb></tscreen>
10601
10602 Here's an example of one such call used in our hello_world program:
10603
10604 <tscreen><verb>
10605 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
10606 </verb></tscreen>
10607
10608 <tscreen><verb>
10609 void g_error( gchar *format, ... );
10610 </verb></tscreen>
10611
10612 Prints an error message. The format is just like printf, but it
10613 prepends "** ERROR **: " to your message, and exits the program.  
10614 Use only for fatal errors.
10615
10616 <tscreen><verb>
10617 void g_warning( gchar *format, ... );
10618 </verb></tscreen>
10619
10620 Same as above, but prepends "** WARNING **: ", and does not exit the
10621 program.
10622
10623 <tscreen><verb>
10624 void g_message( gchar *format, ... );
10625 </verb></tscreen>
10626
10627 Prints "message: " prepended to the string you pass in.
10628
10629 <tscreen><verb>
10630 void g_print( gchar *format, ... );
10631 </verb></tscreen>
10632
10633 Replacement for printf().
10634
10635 And our last function:
10636
10637 <tscreen><verb>
10638 gchar *g_strsignal( gint signum );
10639 </verb></tscreen>
10640
10641 Prints out the name of the Unix system signal given the signal number.
10642 Useful in generic signal handling functions.
10643
10644 All of the above are more or less just stolen from glib.h.  If anyone cares
10645 to document any function, just send me an email!
10646
10647 <!-- ***************************************************************** -->
10648 <sect>GTK's rc Files
10649 <!-- ***************************************************************** -->
10650 <p>
10651 GTK has its own way of dealing with application defaults, by using rc
10652 files. These can be used to set the colors of just about any widget, and
10653 can also be used to tile pixmaps onto the background of some widgets.  
10654
10655 <!-- ----------------------------------------------------------------- -->
10656 <sect1>Functions For rc Files 
10657 <p>
10658 When your application starts, you should include a call to:
10659
10660 <tscreen><verb>
10661 void gtk_rc_parse( char *filename );
10662 </verb></tscreen>
10663
10664 Passing in the filename of your rc file. This will cause GTK to parse
10665 this file, and use the style settings for the widget types defined
10666 there.
10667
10668 If you wish to have a special set of widgets that can take on a
10669 different style from others, or any other logical division of widgets,
10670 use a call to:
10671
10672 <tscreen><verb>
10673 void gtk_widget_set_name( GtkWidget *widget,
10674                           gchar     *name );
10675 </verb></tscreen>
10676
10677 Passing your newly created widget as the first argument, and the name
10678 you wish to give it as the second. This will allow you to change the
10679 attributes of this widget by name through the rc file.
10680
10681 If we use a call something like this:
10682
10683 <tscreen><verb>
10684 button = gtk_button_new_with_label ("Special Button");
10685 gtk_widget_set_name (button, "special button");
10686 </verb></tscreen>
10687
10688 Then this button is given the name "special button" and may be addressed by
10689 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
10690
10691 The example rc file below, sets the properties of the main window, and lets
10692 all children of that main window inherit the style described by the "main
10693 button" style.  The code used in the application is:
10694
10695 <tscreen><verb>
10696 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10697 gtk_widget_set_name (window, "main window");
10698 </verb></tscreen>
10699
10700 And then the style is defined in the rc file using:
10701
10702 <tscreen><verb>
10703 widget "main window.*GtkButton*" style "main_button"
10704 </verb></tscreen>
10705
10706 Which sets all the GtkButton widgets in the "main window" to the
10707 "main_buttons" style as defined in the rc file.
10708
10709 As you can see, this is a fairly powerful and flexible system.  Use your
10710 imagination as to how best to take advantage of this.
10711
10712 <!-- ----------------------------------------------------------------- -->
10713 <sect1>GTK's rc File Format
10714 <p>
10715 The format of the GTK file is illustrated in the example below. This is
10716 the testgtkrc file from the GTK distribution, but I've added a
10717 few comments and things. You may wish to include this explanation
10718 your application to allow the user to fine tune his application.
10719
10720 There are several directives to change the attributes of a widget.
10721
10722 <itemize>
10723 <item>fg - Sets the foreground color of a widget.
10724 <item>bg - Sets the background color of a widget.
10725 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
10726 <item>font - Sets the font to be used with the given widget.
10727 </itemize>
10728
10729 In addition to this, there are several states a widget can be in, and you
10730 can set different colors, pixmaps and fonts for each state. These states are:
10731
10732 <itemize>
10733 <item>NORMAL - The normal state of a widget, without the mouse over top of
10734 it, and not being pressed etc.
10735 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
10736 using this state will be in effect.
10737 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
10738 the attributes assigned by this tag will be in effect.
10739 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
10740 activated, it will take these attributes.
10741 <item>SELECTED - When an object is selected, it takes these attributes.
10742 </itemize>
10743
10744 When using the "fg" and "bg" keywords to set the colors of widgets, the
10745 format is:
10746
10747 <tscreen><verb>
10748 fg[<STATE>] = { Red, Green, Blue }
10749 </verb></tscreen>
10750
10751 Where STATE is one of the above states (PRELIGHT, ACTIVE etc), and the Red,
10752 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
10753 white. They must be in float form, or they will register as 0, so a straight 
10754 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
10755 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
10756
10757 bg_pixmap is very similar to the above, except the colors are replaced by a
10758 filename.
10759
10760 pixmap_path is a list of paths separated by ":"'s.  These paths will be
10761 searched for any pixmap you specify.
10762
10763 The font directive is simply:
10764 <tscreen><verb>
10765 font = "<font name>"
10766 </verb></tscreen>
10767
10768 Where the only hard part is figuring out the font string. Using xfontsel or
10769 similar utility should help.
10770
10771 The "widget_class" sets the style of a class of widgets. These classes are
10772 listed in the widget overview on the class hierarchy.
10773
10774 The "widget" directive sets a specifically named set of widgets to a
10775 given style, overriding any style set for the given widget class.
10776 These widgets are registered inside the application using the
10777 gtk_widget_set_name() call. This allows you to specify the attributes of a
10778 widget on a per widget basis, rather than setting the attributes of an
10779 entire widget class. I urge you to document any of these special widgets so
10780 users may customize them.
10781
10782 When the keyword <tt>parent</> is used as an attribute, the widget will take on
10783 the attributes of its parent in the application.
10784
10785 When defining a style, you may assign the attributes of a previously defined
10786 style to this new one.
10787
10788 <tscreen><verb>
10789 style "main_button" = "button"
10790 {
10791   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10792   bg[PRELIGHT] = { 0.75, 0, 0 }
10793 }
10794 </verb></tscreen>
10795
10796 This example takes the "button" style, and creates a new "main_button" style
10797 simply by changing the font and prelight background color of the "button"
10798 style.
10799
10800 Of course, many of these attributes don't apply to all widgets. It's a
10801 simple matter of common sense really. Anything that could apply, should.
10802
10803 <!-- ----------------------------------------------------------------- -->
10804 <sect1>Example rc file
10805 <p>
10806
10807 <tscreen><verb>
10808 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
10809 #
10810 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
10811 #
10812 # style <name> [= <name>]
10813 # {
10814 #   <option>
10815 # }
10816 #
10817 # widget <widget_set> style <style_name>
10818 # widget_class <widget_class_set> style <style_name>
10819
10820
10821 # Here is a list of all the possible states.  Note that some do not apply to
10822 # certain widgets.
10823 #
10824 # NORMAL - The normal state of a widget, without the mouse over top of
10825 # it, and not being pressed etc.
10826 #
10827 # PRELIGHT - When the mouse is over top of the widget, colors defined
10828 # using this state will be in effect.
10829 #
10830 # ACTIVE - When the widget is pressed or clicked it will be active, and
10831 # the attributes assigned by this tag will be in effect.
10832 #
10833 # INSENSITIVE - When a widget is set insensitive, and cannot be
10834 # activated, it will take these attributes.
10835 #
10836 # SELECTED - When an object is selected, it takes these attributes.
10837 #
10838 # Given these states, we can set the attributes of the widgets in each of
10839 # these states using the following directives.
10840 #
10841 # fg - Sets the foreground color of a widget.
10842 # fg - Sets the background color of a widget.
10843 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
10844 # font - Sets the font to be used with the given widget.
10845 #
10846
10847 # This sets a style called "button".  The name is not really important, as
10848 # it is assigned to the actual widgets at the bottom of the file.
10849
10850 style "window"
10851 {
10852   #This sets the padding around the window to the pixmap specified.
10853   #bg_pixmap[<STATE>] = "<pixmap filename>"
10854   bg_pixmap[NORMAL] = "warning.xpm"
10855 }
10856
10857 style "scale"
10858 {
10859   #Sets the foreground color (font color) to red when in the "NORMAL"
10860   #state.
10861   
10862   fg[NORMAL] = { 1.0, 0, 0 }
10863   
10864   #Sets the background pixmap of this widget to that of its parent.
10865   bg_pixmap[NORMAL] = "<parent>"
10866 }
10867
10868 style "button"
10869 {
10870   # This shows all the possible states for a button.  The only one that
10871   # doesn't apply is the SELECTED state.
10872   
10873   fg[PRELIGHT] = { 0, 1.0, 1.0 }
10874   bg[PRELIGHT] = { 0, 0, 1.0 }
10875   bg[ACTIVE] = { 1.0, 0, 0 }
10876   fg[ACTIVE] = { 0, 1.0, 0 }
10877   bg[NORMAL] = { 1.0, 1.0, 0 }
10878   fg[NORMAL] = { .99, 0, .99 }
10879   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
10880   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
10881 }
10882
10883 # In this example, we inherit the attributes of the "button" style and then
10884 # override the font and background color when prelit to create a new
10885 # "main_button" style.
10886
10887 style "main_button" = "button"
10888 {
10889   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10890   bg[PRELIGHT] = { 0.75, 0, 0 }
10891 }
10892
10893 style "toggle_button" = "button"
10894 {
10895   fg[NORMAL] = { 1.0, 0, 0 }
10896   fg[ACTIVE] = { 1.0, 0, 0 }
10897   
10898   # This sets the background pixmap of the toggle_button to that of its
10899   # parent widget (as defined in the application).
10900   bg_pixmap[NORMAL] = "<parent>"
10901 }
10902
10903 style "text"
10904 {
10905   bg_pixmap[NORMAL] = "marble.xpm"
10906   fg[NORMAL] = { 1.0, 1.0, 1.0 }
10907 }
10908
10909 style "ruler"
10910 {
10911   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
10912 }
10913
10914 # pixmap_path "~/.pixmaps"
10915
10916 # These set the widget types to use the styles defined above.
10917 # The widget types are listed in the class hierarchy, but could probably be
10918 # just listed in this document for the users reference.
10919
10920 widget_class "GtkWindow" style "window"
10921 widget_class "GtkDialog" style "window"
10922 widget_class "GtkFileSelection" style "window"
10923 widget_class "*Gtk*Scale" style "scale"
10924 widget_class "*GtkCheckButton*" style "toggle_button"
10925 widget_class "*GtkRadioButton*" style "toggle_button"
10926 widget_class "*GtkButton*" style "button"
10927 widget_class "*Ruler" style "ruler"
10928 widget_class "*GtkText" style "text"
10929
10930 # This sets all the buttons that are children of the "main window" to
10931 # the main_button style.  These must be documented to be taken advantage of.
10932 widget "main window.*GtkButton*" style "main_button"
10933 </verb></tscreen>
10934
10935 <!-- ***************************************************************** -->
10936 <sect>Writing Your Own Widgets 
10937 <!-- ***************************************************************** -->
10938
10939 <!-- ----------------------------------------------------------------- -->
10940 <sect1> Overview
10941 <p>
10942 Although the GTK distribution comes with many types of widgets that
10943 should cover most basic needs, there may come a time when you need to
10944 create your own new widget type. Since GTK uses widget inheritance
10945 extensively, and there is already a widget that is close to what you want,
10946 it is often possible to make a useful new widget type in
10947 just a few lines of code. But before starting work on a new widget, check
10948 around first to make sure that someone has not already written
10949 it. This will prevent duplication of effort and keep the number of
10950 GTK widgets out there to a minimum, which will help keep both the code
10951 and the interface of different applications consistent. As a flip side
10952 to this, once you finish your widget, announce it to the world so
10953 other people can benefit. The best place to do this is probably the
10954 <tt>gtk-list</tt>.
10955
10956 Complete sources for the example widgets are available at the place you 
10957 got this tutorial, or from:
10958
10959 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
10960 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
10961
10962
10963 <!-- ----------------------------------------------------------------- -->
10964 <sect1> The Anatomy Of A Widget
10965 <p>
10966 In order to create a new widget, it is important to have an
10967 understanding of how GTK objects work. This section is just meant as a
10968 brief overview. See the reference documentation for the details. 
10969
10970 GTK widgets are implemented in an object oriented fashion. However,
10971 they are implemented in standard C. This greatly improves portability
10972 and stability over using current generation C++ compilers; however,
10973 it does mean that the widget writer has to pay attention to some of
10974 the implementation details. The information common to all instances of
10975 one class of widgets (e.g., to all Button widgets) is stored in the 
10976 <em>class structure</em>. There is only one copy of this in
10977 which is stored information about the class's signals
10978 (which act like virtual functions in C). To support inheritance, the
10979 first field in the class structure must be a copy of the parent's
10980 class structure. The declaration of the class structure of GtkButtton
10981 looks like:
10982
10983 <tscreen><verb>
10984 struct _GtkButtonClass
10985 {
10986   GtkContainerClass parent_class;
10987
10988   void (* pressed)  (GtkButton *button);
10989   void (* released) (GtkButton *button);
10990   void (* clicked)  (GtkButton *button);
10991   void (* enter)    (GtkButton *button);
10992   void (* leave)    (GtkButton *button);
10993 };
10994 </verb></tscreen>
10995
10996 When a button is treated as a container (for instance, when it is
10997 resized), its class structure can be cast to GtkContainerClass, and
10998 the relevant fields used to handle the signals.
10999
11000 There is also a structure for each widget that is created on a
11001 per-instance basis. This structure has fields to store information that
11002 is different for each instance of the widget. We'll call this
11003 structure the <em>object structure</em>. For the Button class, it looks
11004 like:
11005
11006 <tscreen><verb>
11007 struct _GtkButton
11008 {
11009   GtkContainer container;
11010
11011   GtkWidget *child;
11012
11013   guint in_button : 1;
11014   guint button_down : 1;
11015 };
11016 </verb></tscreen>
11017
11018 Note that, similar to the class structure, the first field is the
11019 object structure of the parent class, so that this structure can be
11020 cast to the parent class's object structure as needed.
11021
11022 <!-- ----------------------------------------------------------------- -->
11023 <sect1> Creating a Composite widget
11024
11025 <!-- ----------------------------------------------------------------- -->
11026 <sect2> Introduction
11027 <p>
11028 One type of widget that you may be interested in creating is a
11029 widget that is merely an aggregate of other GTK widgets. This type of
11030 widget does nothing that couldn't be done without creating new
11031 widgets, but provides a convenient way of packaging user interface
11032 elements for reuse. The FileSelection and ColorSelection widgets in
11033 the standard distribution are examples of this type of widget.
11034
11035 The example widget that we'll create in this section is the Tictactoe
11036 widget, a 3x3 array of toggle buttons which triggers a signal when all
11037 three buttons in a row, column, or on one of the diagonals are
11038 depressed. 
11039
11040 <!-- ----------------------------------------------------------------- -->
11041 <sect2> Choosing a parent class
11042 <p>
11043 The parent class for a composite widget is typically the container
11044 class that holds all of the elements of the composite widget. For
11045 example, the parent class of the FileSelection widget is the
11046 Dialog class. Since our buttons will be arranged in a table, it
11047 might seem natural to make our parent class the GtkTable
11048 class. Unfortunately, this turns out not to work. The creation of a
11049 widget is divided among two functions - a <tt/WIDGETNAME_new()/
11050 function that the user calls, and a <tt/WIDGETNAME_init()/ function
11051 which does the basic work of initializing the widget which is
11052 independent of the arguments passed to the <tt/_new()/
11053 function. Descendent widgets only call the <tt/_init/ function of
11054 their parent widget. But this division of labor doesn't work well for
11055 tables, which when created, need to know the number of rows and
11056 columns in the table. Unless we want to duplicate most of the
11057 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
11058 best avoid deriving it from GtkTable. For that reason, we derive it
11059 from GtkVBox instead, and stick our table inside the VBox.
11060
11061 <!-- ----------------------------------------------------------------- -->
11062 <sect2> The header file
11063 <p>
11064 Each widget class has a header file which declares the object and
11065 class structures for that widget, along with public functions. 
11066 A couple of features are worth pointing out. To prevent duplicate
11067 definitions, we wrap the entire header file in:
11068
11069 <tscreen><verb>
11070 #ifndef __TICTACTOE_H__
11071 #define __TICTACTOE_H__
11072 .
11073 .
11074 .
11075 #endif /* __TICTACTOE_H__ */
11076 </verb></tscreen>
11077
11078 And to keep C++ programs that include the header file happy, in:
11079
11080 <tscreen><verb>
11081 #ifdef __cplusplus
11082 extern "C" {
11083 #endif /* __cplusplus */
11084 .
11085 .
11086 .
11087 #ifdef __cplusplus
11088 }
11089 #endif /* __cplusplus */
11090 </verb></tscreen>
11091
11092 Along with the functions and structures, we declare three standard
11093 macros in our header file, <tt/TICTACTOE(obj)/,
11094 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
11095 pointer into a pointer to the object or class structure, and check
11096 if an object is a Tictactoe widget respectively.
11097
11098 Here is the complete header file:
11099
11100 <tscreen><verb>
11101 /* tictactoe.h */
11102
11103 #ifndef __TICTACTOE_H__
11104 #define __TICTACTOE_H__
11105
11106 #include <gdk/gdk.h>
11107 #include <gtk/gtkvbox.h>
11108
11109 #ifdef __cplusplus
11110 extern "C" {
11111 #endif /* __cplusplus */
11112
11113 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
11114 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
11115 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
11116
11117
11118 typedef struct _Tictactoe       Tictactoe;
11119 typedef struct _TictactoeClass  TictactoeClass;
11120
11121 struct _Tictactoe
11122 {
11123   GtkVBox vbox;
11124   
11125   GtkWidget *buttons[3][3];
11126 };
11127
11128 struct _TictactoeClass
11129 {
11130   GtkVBoxClass parent_class;
11131
11132   void (* tictactoe) (Tictactoe *ttt);
11133 };
11134
11135 guint          tictactoe_get_type        (void);
11136 GtkWidget*     tictactoe_new             (void);
11137 void           tictactoe_clear           (Tictactoe *ttt);
11138
11139 #ifdef __cplusplus
11140 }
11141 #endif /* __cplusplus */
11142
11143 #endif /* __TICTACTOE_H__ */
11144
11145 </verb></tscreen>
11146
11147 <!-- ----------------------------------------------------------------- -->
11148 <sect2> The <tt/_get_type()/ function.
11149 <p>
11150 We now continue on to the implementation of our widget. A core
11151 function for every widget is the function
11152 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
11153 GTK about the widget class, and gets an ID that uniquely identifies
11154 the widget class. Upon subsequent calls, it just returns the ID.
11155
11156 <tscreen><verb>
11157 guint
11158 tictactoe_get_type ()
11159 {
11160   static guint ttt_type = 0;
11161
11162   if (!ttt_type)
11163     {
11164       GtkTypeInfo ttt_info =
11165       {
11166         "Tictactoe",
11167         sizeof (Tictactoe),
11168         sizeof (TictactoeClass),
11169         (GtkClassInitFunc) tictactoe_class_init,
11170         (GtkObjectInitFunc) tictactoe_init,
11171         (GtkArgSetFunc) NULL,
11172         (GtkArgGetFunc) NULL
11173       };
11174
11175       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
11176     }
11177
11178   return ttt_type;
11179 }
11180 </verb></tscreen>
11181
11182 The GtkTypeInfo structure has the following definition:
11183
11184 <tscreen><verb>
11185 struct _GtkTypeInfo
11186 {
11187   gchar *type_name;
11188   guint object_size;
11189   guint class_size;
11190   GtkClassInitFunc class_init_func;
11191   GtkObjectInitFunc object_init_func;
11192   GtkArgSetFunc arg_set_func;
11193   GtkArgGetFunc arg_get_func;
11194 };
11195 </verb></tscreen>
11196
11197 The fields of this structure are pretty self-explanatory. We'll ignore
11198 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
11199 but as yet largely
11200 unimplemented, role in allowing widget options to be conveniently set
11201 from interpreted languages. Once GTK has a correctly filled in copy of
11202 this structure, it knows how to create objects of a particular widget
11203 type. 
11204
11205 <!-- ----------------------------------------------------------------- -->
11206 <sect2> The <tt/_class_init()/ function
11207 <p>
11208 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
11209 the widget's class structure, and sets up any signals for the
11210 class. For our Tictactoe widget it looks like:
11211
11212 <tscreen><verb>
11213
11214 enum {
11215   TICTACTOE_SIGNAL,
11216   LAST_SIGNAL
11217 };
11218
11219 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
11220
11221 static void
11222 tictactoe_class_init (TictactoeClass *class)
11223 {
11224   GtkObjectClass *object_class;
11225
11226   object_class = (GtkObjectClass*) class;
11227   
11228   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
11229                                          GTK_RUN_FIRST,
11230                                          object_class->type,
11231                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
11232                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
11233
11234
11235   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
11236
11237   class->tictactoe = NULL;
11238 }
11239 </verb></tscreen>
11240
11241 Our widget has just one signal, the <tt/tictactoe/ signal that is
11242 invoked when a row, column, or diagonal is completely filled in. Not
11243 every composite widget needs signals, so if you are reading this for
11244 the first time, you may want to skip to the next section now, as
11245 things are going to get a bit complicated.
11246
11247 The function:
11248
11249 <tscreen><verb>
11250 gint gtk_signal_new( const gchar         *name,
11251                      GtkSignalRunType     run_type,
11252                      GtkType              object_type,
11253                      gint                 function_offset,
11254                      GtkSignalMarshaller  marshaller,
11255                      GtkType              return_val,
11256                      guint                nparams,
11257                      ...);
11258 </verb></tscreen>
11259
11260 Creates a new signal. The parameters are:
11261
11262 <itemize>
11263 <item> <tt/name/: The name of the signal.
11264 <item> <tt/run_type/: Whether the default handler runs before or after
11265 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
11266 although there are other possibilities.
11267 <item> <tt/object_type/: The ID of the object that this signal applies
11268 to. (It will also apply to that objects descendents)
11269 <item> <tt/function_offset/: The offset within the class structure of
11270 a pointer to the default handler.
11271 <item> <tt/marshaller/: A function that is used to invoke the signal
11272 handler. For signal handlers that have no arguments other than the
11273 object that emitted the signal and user data, we can use the
11274 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
11275 <item> <tt/return_val/: The type of the return val.
11276 <item> <tt/nparams/: The number of parameters of the signal handler
11277 (other than the two default ones mentioned above)
11278 <item> <tt/.../: The types of the parameters.
11279 </itemize>
11280
11281 When specifying types, the <tt/GtkType/ enumeration is used:
11282
11283 <tscreen><verb>
11284 typedef enum
11285 {
11286   GTK_TYPE_INVALID,
11287   GTK_TYPE_NONE,
11288   GTK_TYPE_CHAR,
11289   GTK_TYPE_BOOL,
11290   GTK_TYPE_INT,
11291   GTK_TYPE_UINT,
11292   GTK_TYPE_LONG,
11293   GTK_TYPE_ULONG,
11294   GTK_TYPE_FLOAT,
11295   GTK_TYPE_DOUBLE,
11296   GTK_TYPE_STRING,
11297   GTK_TYPE_ENUM,
11298   GTK_TYPE_FLAGS,
11299   GTK_TYPE_BOXED,
11300   GTK_TYPE_FOREIGN,
11301   GTK_TYPE_CALLBACK,
11302   GTK_TYPE_ARGS,
11303
11304   GTK_TYPE_POINTER,
11305
11306   /* it'd be great if the next two could be removed eventually */
11307   GTK_TYPE_SIGNAL,
11308   GTK_TYPE_C_CALLBACK,
11309
11310   GTK_TYPE_OBJECT
11311
11312 } GtkFundamentalType;
11313 </verb></tscreen>
11314
11315 <tt/gtk_signal_new()/ returns a unique integer identifier for the
11316 signal, that we store in the <tt/tictactoe_signals/ array, which we
11317 index using an enumeration. (Conventionally, the enumeration elements
11318 are the signal name, uppercased, but here there would be a conflict
11319 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
11320 instead.
11321
11322 After creating our signals, we need to tell GTK to associate our
11323 signals with the Tictactoe class. We do that by calling
11324 <tt/gtk_object_class_add_signals()/. We then set the pointer which
11325 points to the default handler for the `tictactoe' signal to NULL,
11326 indicating that there is no default action.
11327
11328 <!-- ----------------------------------------------------------------- -->
11329 <sect2> The <tt/_init()/ function.
11330 <p>
11331 Each widget class also needs a function to initialize the object
11332 structure. Usually, this function has the fairly limited role of
11333 setting the fields of the structure to default values. For composite
11334 widgets, however, this function also creates the component widgets.
11335
11336 <tscreen><verb>
11337 static void
11338 tictactoe_init (Tictactoe *ttt)
11339 {
11340   GtkWidget *table;
11341   gint i,j;
11342   
11343   table = gtk_table_new (3, 3, TRUE);
11344   gtk_container_add (GTK_CONTAINER(ttt), table);
11345   gtk_widget_show (table);
11346
11347   for (i=0;i<3; i++)
11348     for (j=0;j<3; j++)
11349       {
11350         ttt->buttons[i][j] = gtk_toggle_button_new ();
11351         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
11352                                    i, i+1, j, j+1);
11353         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
11354                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
11355         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
11356         gtk_widget_show (ttt->buttons[i][j]);
11357       }
11358 }
11359 </verb></tscreen>
11360
11361 <!-- ----------------------------------------------------------------- -->
11362 <sect2> And the rest...
11363 <p>
11364 There is one more function that every widget (except for base widget
11365 types like GtkBin that cannot be instantiated) needs to have - the
11366 function that the user calls to create an object of that type. This is
11367 conventionally called <tt/WIDGETNAME_new()/. In some
11368 widgets, though not for the Tictactoe widgets, this function takes
11369 arguments, and does some setup based on the arguments. The other two
11370 functions are specific to the Tictactoe widget. 
11371
11372 <tt/tictactoe_clear()/ is a public function that resets all the
11373 buttons in the widget to the up position. Note the use of
11374 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
11375 button toggles from being triggered unnecessarily.
11376
11377 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
11378 user clicks on a button. It checks to see if there are any winning
11379 combinations that involve the toggled button, and if so, emits
11380 the "tictactoe" signal.
11381
11382 <tscreen><verb>  
11383 GtkWidget*
11384 tictactoe_new ()
11385 {
11386   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
11387 }
11388
11389 void           
11390 tictactoe_clear (Tictactoe *ttt)
11391 {
11392   int i,j;
11393
11394   for (i=0;i<3;i++)
11395     for (j=0;j<3;j++)
11396       {
11397         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
11398         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
11399                                      FALSE);
11400         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
11401       }
11402 }
11403
11404 static void
11405 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
11406 {
11407   int i,k;
11408
11409   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11410                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11411                              { 0, 1, 2 }, { 0, 1, 2 } };
11412   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11413                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11414                              { 0, 1, 2 }, { 2, 1, 0 } };
11415
11416   int success, found;
11417
11418   for (k=0; k<8; k++)
11419     {
11420       success = TRUE;
11421       found = FALSE;
11422
11423       for (i=0;i<3;i++)
11424         {
11425           success = success &amp;&amp; 
11426             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
11427           found = found ||
11428             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
11429         }
11430       
11431       if (success &amp;&amp; found)
11432         {
11433           gtk_signal_emit (GTK_OBJECT (ttt), 
11434                            tictactoe_signals[TICTACTOE_SIGNAL]);
11435           break;
11436         }
11437     }
11438 }
11439 </verb></tscreen>
11440
11441 And finally, an example program using our Tictactoe widget:
11442
11443 <tscreen><verb>
11444 #include <gtk/gtk.h>
11445 #include "tictactoe.h"
11446
11447 /* Invoked when a row, column or diagonal is completed */
11448 void
11449 win (GtkWidget *widget, gpointer data)
11450 {
11451   g_print ("Yay!\n");
11452   tictactoe_clear (TICTACTOE (widget));
11453 }
11454
11455 int 
11456 main (int argc, char *argv[])
11457 {
11458   GtkWidget *window;
11459   GtkWidget *ttt;
11460   
11461   gtk_init (&amp;argc, &amp;argv);
11462
11463   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11464   
11465   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
11466   
11467   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11468                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11469   
11470   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11471
11472   /* Create a new Tictactoe widget */
11473   ttt = tictactoe_new ();
11474   gtk_container_add (GTK_CONTAINER (window), ttt);
11475   gtk_widget_show (ttt);
11476
11477   /* And attach to its "tictactoe" signal */
11478   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
11479                       GTK_SIGNAL_FUNC (win), NULL);
11480
11481   gtk_widget_show (window);
11482   
11483   gtk_main ();
11484   
11485   return 0;
11486 }
11487
11488 </verb></tscreen>
11489
11490 <!-- ----------------------------------------------------------------- -->
11491 <sect1> Creating a widget from scratch.
11492
11493 <!-- ----------------------------------------------------------------- -->
11494 <sect2> Introduction
11495 <p>
11496 In this section, we'll learn more about how widgets display themselves
11497 on the screen and interact with events. As an example of this, we'll
11498 create an analog dial widget with a pointer that the user can drag to
11499 set the value.
11500
11501 <!-- ----------------------------------------------------------------- -->
11502 <sect2> Displaying a widget on the screen
11503 <p>
11504 There are several steps that are involved in displaying on the screen.
11505 After the widget is created with a call to <tt/WIDGETNAME_new()/,
11506 several more functions are needed:
11507
11508 <itemize>
11509 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
11510 window for the widget if it has one.
11511 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
11512 <tt/gtk_widget_show()/. It is responsible for making sure the widget
11513 is actually drawn on the screen (<em/mapped/). For a container class,
11514 it must also make calls to <tt/map()/> functions of any child widgets.
11515 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
11516 is called for the widget or one of its ancestors. It makes the actual
11517 calls to the drawing functions to draw the widget on the screen. For
11518 container widgets, this function must make calls to
11519 <tt/gtk_widget_draw()/ for its child widgets.
11520 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
11521 widget. It makes the necessary calls to the drawing functions to draw
11522 the exposed portion on the screen. For container widgets, this
11523 function must generate expose events for its child widgets which don't
11524 have their own windows. (If they have their own windows, then X will
11525 generate the necessary expose events)
11526 </itemize>
11527
11528 You might notice that the last two functions are quite similar - each
11529 is responsible for drawing the widget on the screen. In fact many
11530 types of widgets don't really care about the difference between the
11531 two. The default <tt/draw()/ function in the widget class simply
11532 generates a synthetic expose event for the redrawn area. However, some
11533 types of widgets can save work by distinguishing between the two
11534 functions. For instance, if a widget has multiple X windows, then
11535 since expose events identify the exposed window, it can redraw only
11536 the affected window, which is not possible for calls to <tt/draw()/.
11537
11538 Container widgets, even if they don't care about the difference for
11539 themselves, can't simply use the default <tt/draw()/ function because
11540 their child widgets might care about the difference. However,
11541 it would be wasteful to duplicate the drawing code between the two
11542 functions. The convention is that such widgets have a function called
11543 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
11544 widget, that is then called by the <tt/draw()/ and <tt/expose()/
11545 functions.
11546
11547 In our example approach, since the dial widget is not a container
11548 widget, and only has a single window, we can take the simplest
11549 approach and use the default <tt/draw()/ function and only implement
11550 an <tt/expose()/ function.
11551
11552 <!-- ----------------------------------------------------------------- -->
11553 <sect2> The origins of the Dial Widget
11554 <p>
11555 Just as all land animals are just variants on the first amphibian that
11556 crawled up out of the mud, Gtk widgets tend to start off as variants
11557 of some other, previously written widget.  Thus, although this section
11558 is entitled `Creating a Widget from Scratch', the Dial widget really
11559 began with the source code for the Range widget. This was picked as a
11560 starting point because it would be nice if our Dial had the same
11561 interface as the Scale widgets which are just specialized descendents
11562 of the Range widget. So, though the source code is presented below in
11563 finished form, it should not be implied that it was written, <em>deus
11564 ex machina</em> in this fashion. Also, if you aren't yet familiar with
11565 how scale widgets work from the application writer's point of view, it
11566 would be a good idea to look them over before continuing.
11567
11568 <!-- ----------------------------------------------------------------- -->
11569 <sect2> The Basics
11570 <p>
11571 Quite a bit of our widget should look pretty familiar from the
11572 Tictactoe widget. First, we have a header file:
11573
11574 <tscreen><verb>
11575 /* GTK - The GIMP Toolkit
11576  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
11577  *
11578  * This library is free software; you can redistribute it and/or
11579  * modify it under the terms of the GNU Library General Public
11580  * License as published by the Free Software Foundation; either
11581  * version 2 of the License, or (at your option) any later version.
11582  *
11583  * This library is distributed in the hope that it will be useful,
11584  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11585  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11586  * Library General Public License for more details.
11587  *
11588  * You should have received a copy of the GNU Library General Public
11589  * License along with this library; if not, write to the Free
11590  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11591  */
11592
11593 #ifndef __GTK_DIAL_H__
11594 #define __GTK_DIAL_H__
11595
11596 #include <gdk/gdk.h>
11597 #include <gtk/gtkadjustment.h>
11598 #include <gtk/gtkwidget.h>
11599
11600
11601 #ifdef __cplusplus
11602 extern "C" {
11603 #endif /* __cplusplus */
11604
11605
11606 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
11607 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
11608 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
11609
11610
11611 typedef struct _GtkDial        GtkDial;
11612 typedef struct _GtkDialClass   GtkDialClass;
11613
11614 struct _GtkDial
11615 {
11616   GtkWidget widget;
11617
11618   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
11619   guint policy : 2;
11620
11621   /* Button currently pressed or 0 if none */
11622   guint8 button;
11623
11624   /* Dimensions of dial components */
11625   gint radius;
11626   gint pointer_width;
11627
11628   /* ID of update timer, or 0 if none */
11629   guint32 timer;
11630
11631   /* Current angle */
11632   gfloat angle;
11633
11634   /* Old values from adjustment stored so we know when something changes */
11635   gfloat old_value;
11636   gfloat old_lower;
11637   gfloat old_upper;
11638
11639   /* The adjustment object that stores the data for this dial */
11640   GtkAdjustment *adjustment;
11641 };
11642
11643 struct _GtkDialClass
11644 {
11645   GtkWidgetClass parent_class;
11646 };
11647
11648
11649 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
11650 guint          gtk_dial_get_type               (void);
11651 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
11652 void           gtk_dial_set_update_policy      (GtkDial      *dial,
11653                                                 GtkUpdateType  policy);
11654
11655 void           gtk_dial_set_adjustment         (GtkDial      *dial,
11656                                                 GtkAdjustment *adjustment);
11657 #ifdef __cplusplus
11658 }
11659 #endif /* __cplusplus */
11660
11661
11662 #endif /* __GTK_DIAL_H__ */
11663 </verb></tscreen>
11664
11665 Since there is quite a bit more going on in this widget, than the last
11666 one, we have more fields in the data structure, but otherwise things
11667 are pretty similar.
11668
11669 Next, after including header files, and declaring a few constants,
11670 we have some functions to provide information about the widget
11671 and initialize it:
11672
11673 <tscreen><verb>
11674 #include <math.h>
11675 #include <stdio.h>
11676 #include <gtk/gtkmain.h>
11677 #include <gtk/gtksignal.h>
11678
11679 #include "gtkdial.h"
11680
11681 #define SCROLL_DELAY_LENGTH  300
11682 #define DIAL_DEFAULT_SIZE 100
11683
11684 /* Forward declarations */
11685
11686 [ omitted to save space ]
11687
11688 /* Local data */
11689
11690 static GtkWidgetClass *parent_class = NULL;
11691
11692 guint
11693 gtk_dial_get_type ()
11694 {
11695   static guint dial_type = 0;
11696
11697   if (!dial_type)
11698     {
11699       GtkTypeInfo dial_info =
11700       {
11701         "GtkDial",
11702         sizeof (GtkDial),
11703         sizeof (GtkDialClass),
11704         (GtkClassInitFunc) gtk_dial_class_init,
11705         (GtkObjectInitFunc) gtk_dial_init,
11706         (GtkArgSetFunc) NULL,
11707         (GtkArgGetFunc) NULL,
11708       };
11709
11710       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
11711     }
11712
11713   return dial_type;
11714 }
11715
11716 static void
11717 gtk_dial_class_init (GtkDialClass *class)
11718 {
11719   GtkObjectClass *object_class;
11720   GtkWidgetClass *widget_class;
11721
11722   object_class = (GtkObjectClass*) class;
11723   widget_class = (GtkWidgetClass*) class;
11724
11725   parent_class = gtk_type_class (gtk_widget_get_type ());
11726
11727   object_class->destroy = gtk_dial_destroy;
11728
11729   widget_class->realize = gtk_dial_realize;
11730   widget_class->expose_event = gtk_dial_expose;
11731   widget_class->size_request = gtk_dial_size_request;
11732   widget_class->size_allocate = gtk_dial_size_allocate;
11733   widget_class->button_press_event = gtk_dial_button_press;
11734   widget_class->button_release_event = gtk_dial_button_release;
11735   widget_class->motion_notify_event = gtk_dial_motion_notify;
11736 }
11737
11738 static void
11739 gtk_dial_init (GtkDial *dial)
11740 {
11741   dial->button = 0;
11742   dial->policy = GTK_UPDATE_CONTINUOUS;
11743   dial->timer = 0;
11744   dial->radius = 0;
11745   dial->pointer_width = 0;
11746   dial->angle = 0.0;
11747   dial->old_value = 0.0;
11748   dial->old_lower = 0.0;
11749   dial->old_upper = 0.0;
11750   dial->adjustment = NULL;
11751 }
11752
11753 GtkWidget*
11754 gtk_dial_new (GtkAdjustment *adjustment)
11755 {
11756   GtkDial *dial;
11757
11758   dial = gtk_type_new (gtk_dial_get_type ());
11759
11760   if (!adjustment)
11761     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
11762
11763   gtk_dial_set_adjustment (dial, adjustment);
11764
11765   return GTK_WIDGET (dial);
11766 }
11767
11768 static void
11769 gtk_dial_destroy (GtkObject *object)
11770 {
11771   GtkDial *dial;
11772
11773   g_return_if_fail (object != NULL);
11774   g_return_if_fail (GTK_IS_DIAL (object));
11775
11776   dial = GTK_DIAL (object);
11777
11778   if (dial->adjustment)
11779     gtk_object_unref (GTK_OBJECT (dial->adjustment));
11780
11781   if (GTK_OBJECT_CLASS (parent_class)->destroy)
11782     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
11783 }
11784 </verb></tscreen>
11785
11786 Note that this <tt/init()/ function does less than for the Tictactoe
11787 widget, since this is not a composite widget, and the <tt/new()/
11788 function does more, since it now has an argument. Also, note that when
11789 we store a pointer to the Adjustment object, we increment its
11790 reference count, (and correspondingly decrement when we no longer use
11791 it) so that GTK can keep track of when it can be safely destroyed.
11792
11793 <p>
11794 Also, there are a few function to manipulate the widget's options:
11795
11796 <tscreen><verb>
11797 GtkAdjustment*
11798 gtk_dial_get_adjustment (GtkDial *dial)
11799 {
11800   g_return_val_if_fail (dial != NULL, NULL);
11801   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
11802
11803   return dial->adjustment;
11804 }
11805
11806 void
11807 gtk_dial_set_update_policy (GtkDial      *dial,
11808                              GtkUpdateType  policy)
11809 {
11810   g_return_if_fail (dial != NULL);
11811   g_return_if_fail (GTK_IS_DIAL (dial));
11812
11813   dial->policy = policy;
11814 }
11815
11816 void
11817 gtk_dial_set_adjustment (GtkDial      *dial,
11818                           GtkAdjustment *adjustment)
11819 {
11820   g_return_if_fail (dial != NULL);
11821   g_return_if_fail (GTK_IS_DIAL (dial));
11822
11823   if (dial->adjustment)
11824     {
11825       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
11826       gtk_object_unref (GTK_OBJECT (dial->adjustment));
11827     }
11828
11829   dial->adjustment = adjustment;
11830   gtk_object_ref (GTK_OBJECT (dial->adjustment));
11831
11832   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
11833                       (GtkSignalFunc) gtk_dial_adjustment_changed,
11834                       (gpointer) dial);
11835   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
11836                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
11837                       (gpointer) dial);
11838
11839   dial->old_value = adjustment->value;
11840   dial->old_lower = adjustment->lower;
11841   dial->old_upper = adjustment->upper;
11842
11843   gtk_dial_update (dial);
11844 }
11845 </verb></tscreen>
11846
11847 <sect2> <tt/gtk_dial_realize()/
11848
11849 <p>
11850 Now we come to some new types of functions. First, we have a function
11851 that does the work of creating the X window. Notice that a mask is
11852 passed to the function <tt/gdk_window_new()/ which specifies which fields of
11853 the GdkWindowAttr structure actually have data in them (the remaining
11854 fields will be given default values). Also worth noting is the way the
11855 event mask of the widget is created. We call
11856 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
11857 has specified for this widget (with <tt/gtk_widget_set_events()/, and
11858 add the events that we are interested in ourselves.
11859
11860 <p>
11861 After creating the window, we set its style and background, and put a
11862 pointer to the widget in the user data field of the GdkWindow. This
11863 last step allows GTK to dispatch events for this window to the correct
11864 widget.
11865
11866 <tscreen><verb>
11867 static void
11868 gtk_dial_realize (GtkWidget *widget)
11869 {
11870   GtkDial *dial;
11871   GdkWindowAttr attributes;
11872   gint attributes_mask;
11873
11874   g_return_if_fail (widget != NULL);
11875   g_return_if_fail (GTK_IS_DIAL (widget));
11876
11877   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
11878   dial = GTK_DIAL (widget);
11879
11880   attributes.x = widget->allocation.x;
11881   attributes.y = widget->allocation.y;
11882   attributes.width = widget->allocation.width;
11883   attributes.height = widget->allocation.height;
11884   attributes.wclass = GDK_INPUT_OUTPUT;
11885   attributes.window_type = GDK_WINDOW_CHILD;
11886   attributes.event_mask = gtk_widget_get_events (widget) | 
11887     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
11888     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
11889     GDK_POINTER_MOTION_HINT_MASK;
11890   attributes.visual = gtk_widget_get_visual (widget);
11891   attributes.colormap = gtk_widget_get_colormap (widget);
11892
11893   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
11894   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
11895
11896   widget->style = gtk_style_attach (widget->style, widget->window);
11897
11898   gdk_window_set_user_data (widget->window, widget);
11899
11900   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
11901 }
11902 </verb></tscreen>
11903
11904 <sect2> Size negotiation
11905
11906 <p>
11907 Before the first time that the window containing a widget is
11908 displayed, and whenever the layout of the window changes, GTK asks
11909 each child widget for its desired size. This request is handled by the
11910 function, <tt/gtk_dial_size_request()/. Since our widget isn't a
11911 container widget, and has no real constraints on its size, we just
11912 return a reasonable default value.
11913
11914 <tscreen><verb>
11915 static void 
11916 gtk_dial_size_request (GtkWidget      *widget,
11917                        GtkRequisition *requisition)
11918 {
11919   requisition->width = DIAL_DEFAULT_SIZE;
11920   requisition->height = DIAL_DEFAULT_SIZE;
11921 }
11922 </verb></tscreen>
11923
11924 <p>
11925 After all the widgets have requested an ideal size, the layout of the
11926 window is computed and each child widget is notified of its actual
11927 size. Usually, this will at least as large as the requested size, but
11928 if for instance, the user has resized the window, it may occasionally
11929 be smaller than the requested size. The size notification is handled
11930 by the function <tt/gtk_dial_size_allocate()/. Notice that as well as
11931 computing the sizes of some component pieces for future use, this
11932 routine also does the grunt work of moving the widgets X window into
11933 the new position and size.
11934
11935 <tscreen><verb>
11936 static void
11937 gtk_dial_size_allocate (GtkWidget     *widget,
11938                         GtkAllocation *allocation)
11939 {
11940   GtkDial *dial;
11941
11942   g_return_if_fail (widget != NULL);
11943   g_return_if_fail (GTK_IS_DIAL (widget));
11944   g_return_if_fail (allocation != NULL);
11945
11946   widget->allocation = *allocation;
11947   if (GTK_WIDGET_REALIZED (widget))
11948     {
11949       dial = GTK_DIAL (widget);
11950
11951       gdk_window_move_resize (widget->window,
11952                               allocation->x, allocation->y,
11953                               allocation->width, allocation->height);
11954
11955       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
11956       dial->pointer_width = dial->radius / 5;
11957     }
11958 }
11959 </verb></tscreen>.
11960
11961 <!-- ----------------------------------------------------------------- -->
11962 <sect2> <tt/gtk_dial_expose()/
11963
11964 <p>
11965 As mentioned above, all the drawing of this widget is done in the
11966 handler for expose events. There's not much to remark on here except
11967 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
11968 three dimensional shading according to the colors stored in the
11969 widget's style.
11970
11971 <tscreen><verb>
11972 static gint
11973 gtk_dial_expose (GtkWidget      *widget,
11974                  GdkEventExpose *event)
11975 {
11976   GtkDial *dial;
11977   GdkPoint points[3];
11978   gdouble s,c;
11979   gdouble theta;
11980   gint xc, yc;
11981   gint tick_length;
11982   gint i;
11983
11984   g_return_val_if_fail (widget != NULL, FALSE);
11985   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
11986   g_return_val_if_fail (event != NULL, FALSE);
11987
11988   if (event->count > 0)
11989     return FALSE;
11990   
11991   dial = GTK_DIAL (widget);
11992
11993   gdk_window_clear_area (widget->window,
11994                          0, 0,
11995                          widget->allocation.width,
11996                          widget->allocation.height);
11997
11998   xc = widget->allocation.width/2;
11999   yc = widget->allocation.height/2;
12000
12001   /* Draw ticks */
12002
12003   for (i=0; i<25; i++)
12004     {
12005       theta = (i*M_PI/18. - M_PI/6.);
12006       s = sin(theta);
12007       c = cos(theta);
12008
12009       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
12010       
12011       gdk_draw_line (widget->window,
12012                      widget->style->fg_gc[widget->state],
12013                      xc + c*(dial->radius - tick_length),
12014                      yc - s*(dial->radius - tick_length),
12015                      xc + c*dial->radius,
12016                      yc - s*dial->radius);
12017     }
12018
12019   /* Draw pointer */
12020
12021   s = sin(dial->angle);
12022   c = cos(dial->angle);
12023
12024
12025   points[0].x = xc + s*dial->pointer_width/2;
12026   points[0].y = yc + c*dial->pointer_width/2;
12027   points[1].x = xc + c*dial->radius;
12028   points[1].y = yc - s*dial->radius;
12029   points[2].x = xc - s*dial->pointer_width/2;
12030   points[2].y = yc - c*dial->pointer_width/2;
12031
12032   gtk_draw_polygon (widget->style,
12033                     widget->window,
12034                     GTK_STATE_NORMAL,
12035                     GTK_SHADOW_OUT,
12036                     points, 3,
12037                     TRUE);
12038   
12039   return FALSE;
12040 }
12041 </verb></tscreen>
12042
12043 <!-- ----------------------------------------------------------------- -->
12044 <sect2> Event handling
12045
12046 <p>
12047
12048 The rest of the widget's code handles various types of events, and
12049 isn't too different from what would be found in many GTK
12050 applications. Two types of events can occur - either the user can
12051 click on the widget with the mouse and drag to move the pointer, or
12052 the value of the Adjustment object can change due to some external
12053 circumstance. 
12054
12055 <p>
12056 When the user clicks on the widget, we check to see if the click was
12057 appropriately near the pointer, and if so, store then button that the
12058 user clicked with in the <tt/button/ field of the widget
12059 structure, and grab all mouse events with a call to
12060 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
12061 value of the control to be recomputed (by the function
12062 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
12063 set, "value_changed" events are either generated instantly
12064 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
12065 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
12066 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
12067
12068 <tscreen><verb>
12069 static gint
12070 gtk_dial_button_press (GtkWidget      *widget,
12071                        GdkEventButton *event)
12072 {
12073   GtkDial *dial;
12074   gint dx, dy;
12075   double s, c;
12076   double d_parallel;
12077   double d_perpendicular;
12078
12079   g_return_val_if_fail (widget != NULL, FALSE);
12080   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12081   g_return_val_if_fail (event != NULL, FALSE);
12082
12083   dial = GTK_DIAL (widget);
12084
12085   /* Determine if button press was within pointer region - we 
12086      do this by computing the parallel and perpendicular distance of
12087      the point where the mouse was pressed from the line passing through
12088      the pointer */
12089   
12090   dx = event->x - widget->allocation.width / 2;
12091   dy = widget->allocation.height / 2 - event->y;
12092   
12093   s = sin(dial->angle);
12094   c = cos(dial->angle);
12095   
12096   d_parallel = s*dy + c*dx;
12097   d_perpendicular = fabs(s*dx - c*dy);
12098   
12099   if (!dial->button &&
12100       (d_perpendicular < dial->pointer_width/2) &&
12101       (d_parallel > - dial->pointer_width))
12102     {
12103       gtk_grab_add (widget);
12104
12105       dial->button = event->button;
12106
12107       gtk_dial_update_mouse (dial, event->x, event->y);
12108     }
12109
12110   return FALSE;
12111 }
12112
12113 static gint
12114 gtk_dial_button_release (GtkWidget      *widget,
12115                           GdkEventButton *event)
12116 {
12117   GtkDial *dial;
12118
12119   g_return_val_if_fail (widget != NULL, FALSE);
12120   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12121   g_return_val_if_fail (event != NULL, FALSE);
12122
12123   dial = GTK_DIAL (widget);
12124
12125   if (dial->button == event->button)
12126     {
12127       gtk_grab_remove (widget);
12128
12129       dial->button = 0;
12130
12131       if (dial->policy == GTK_UPDATE_DELAYED)
12132         gtk_timeout_remove (dial->timer);
12133       
12134       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
12135           (dial->old_value != dial->adjustment->value))
12136         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12137     }
12138
12139   return FALSE;
12140 }
12141
12142 static gint
12143 gtk_dial_motion_notify (GtkWidget      *widget,
12144                          GdkEventMotion *event)
12145 {
12146   GtkDial *dial;
12147   GdkModifierType mods;
12148   gint x, y, mask;
12149
12150   g_return_val_if_fail (widget != NULL, FALSE);
12151   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12152   g_return_val_if_fail (event != NULL, FALSE);
12153
12154   dial = GTK_DIAL (widget);
12155
12156   if (dial->button != 0)
12157     {
12158       x = event->x;
12159       y = event->y;
12160
12161       if (event->is_hint || (event->window != widget->window))
12162         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
12163
12164       switch (dial->button)
12165         {
12166         case 1:
12167           mask = GDK_BUTTON1_MASK;
12168           break;
12169         case 2:
12170           mask = GDK_BUTTON2_MASK;
12171           break;
12172         case 3:
12173           mask = GDK_BUTTON3_MASK;
12174           break;
12175         default:
12176           mask = 0;
12177           break;
12178         }
12179
12180       if (mods & mask)
12181         gtk_dial_update_mouse (dial, x,y);
12182     }
12183
12184   return FALSE;
12185 }
12186
12187 static gint
12188 gtk_dial_timer (GtkDial *dial)
12189 {
12190   g_return_val_if_fail (dial != NULL, FALSE);
12191   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
12192
12193   if (dial->policy == GTK_UPDATE_DELAYED)
12194     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12195
12196   return FALSE;
12197 }
12198
12199 static void
12200 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
12201 {
12202   gint xc, yc;
12203   gfloat old_value;
12204
12205   g_return_if_fail (dial != NULL);
12206   g_return_if_fail (GTK_IS_DIAL (dial));
12207
12208   xc = GTK_WIDGET(dial)->allocation.width / 2;
12209   yc = GTK_WIDGET(dial)->allocation.height / 2;
12210
12211   old_value = dial->adjustment->value;
12212   dial->angle = atan2(yc-y, x-xc);
12213
12214   if (dial->angle < -M_PI/2.)
12215     dial->angle += 2*M_PI;
12216
12217   if (dial->angle < -M_PI/6)
12218     dial->angle = -M_PI/6;
12219
12220   if (dial->angle > 7.*M_PI/6.)
12221     dial->angle = 7.*M_PI/6.;
12222
12223   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
12224     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
12225
12226   if (dial->adjustment->value != old_value)
12227     {
12228       if (dial->policy == GTK_UPDATE_CONTINUOUS)
12229         {
12230           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12231         }
12232       else
12233         {
12234           gtk_widget_draw (GTK_WIDGET(dial), NULL);
12235
12236           if (dial->policy == GTK_UPDATE_DELAYED)
12237             {
12238               if (dial->timer)
12239                 gtk_timeout_remove (dial->timer);
12240
12241               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
12242                                              (GtkFunction) gtk_dial_timer,
12243                                              (gpointer) dial);
12244             }
12245         }
12246     }
12247 }
12248 </verb></tscreen>
12249
12250 <p>
12251 Changes to the Adjustment by external means are communicated to our
12252 widget by the `changed' and `value_changed' signals. The handlers
12253 for these functions call <tt/gtk_dial_update()/ to validate the
12254 arguments, compute the new pointer angle, and redraw the widget (by
12255 calling <tt/gtk_widget_draw()/).
12256
12257 <tscreen><verb>
12258 static void
12259 gtk_dial_update (GtkDial *dial)
12260 {
12261   gfloat new_value;
12262   
12263   g_return_if_fail (dial != NULL);
12264   g_return_if_fail (GTK_IS_DIAL (dial));
12265
12266   new_value = dial->adjustment->value;
12267   
12268   if (new_value < dial->adjustment->lower)
12269     new_value = dial->adjustment->lower;
12270
12271   if (new_value > dial->adjustment->upper)
12272     new_value = dial->adjustment->upper;
12273
12274   if (new_value != dial->adjustment->value)
12275     {
12276       dial->adjustment->value = new_value;
12277       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12278     }
12279
12280   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
12281     (dial->adjustment->upper - dial->adjustment->lower);
12282
12283   gtk_widget_draw (GTK_WIDGET(dial), NULL);
12284 }
12285
12286 static void
12287 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
12288                               gpointer       data)
12289 {
12290   GtkDial *dial;
12291
12292   g_return_if_fail (adjustment != NULL);
12293   g_return_if_fail (data != NULL);
12294
12295   dial = GTK_DIAL (data);
12296
12297   if ((dial->old_value != adjustment->value) ||
12298       (dial->old_lower != adjustment->lower) ||
12299       (dial->old_upper != adjustment->upper))
12300     {
12301       gtk_dial_update (dial);
12302
12303       dial->old_value = adjustment->value;
12304       dial->old_lower = adjustment->lower;
12305       dial->old_upper = adjustment->upper;
12306     }
12307 }
12308
12309 static void
12310 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
12311                                     gpointer       data)
12312 {
12313   GtkDial *dial;
12314
12315   g_return_if_fail (adjustment != NULL);
12316   g_return_if_fail (data != NULL);
12317
12318   dial = GTK_DIAL (data);
12319
12320   if (dial->old_value != adjustment->value)
12321     {
12322       gtk_dial_update (dial);
12323
12324       dial->old_value = adjustment->value;
12325     }
12326 }
12327 </verb></tscreen>
12328
12329 <!-- ----------------------------------------------------------------- -->
12330 <sect2> Possible Enhancements
12331 <p>
12332
12333 The Dial widget as we've described it so far runs about 670 lines of
12334 code. Although that might sound like a fair bit, we've really
12335 accomplished quite a bit with that much code, especially since much of
12336 that length is headers and boilerplate. However, there are quite a few
12337 more enhancements that could be made to this widget:
12338
12339 <itemize>
12340 <item> If you try this widget out, you'll find that there is some
12341 flashing as the pointer is dragged around. This is because the entire
12342 widget is erased every time the pointer is moved before being
12343 redrawn. Often, the best way to handle this problem is to draw to an
12344 offscreen pixmap, then copy the final results onto the screen in one
12345 step. (The ProgressBar widget draws itself in this fashion.)
12346
12347 <item> The user should be able to use the up and down arrow keys to
12348 increase and decrease the value.
12349
12350 <item> It would be nice if the widget had buttons to increase and
12351 decrease the value in small or large steps. Although it would be
12352 possible to use embedded Button widgets for this, we would also like
12353 the buttons to auto-repeat when held down, as the arrows on a
12354 scrollbar do. Most of the code to implement this type of behavior can
12355 be found in the GtkRange widget.
12356
12357 <item> The Dial widget could be made into a container widget with a
12358 single child widget positioned at the bottom between the buttons
12359 mentioned above. The user could then add their choice of a label or
12360 entry widget to display the current value of the dial.
12361
12362 </itemize>
12363
12364 <!-- ----------------------------------------------------------------- -->
12365 <sect1> Learning More
12366
12367 <p>
12368 Only a small part of the many details involved in creating widgets
12369 could be described above. If you want to write your own widgets, the
12370 best source of examples is the GTK source itself. Ask yourself some
12371 questions about the widget you want to write: is it a Container
12372 widget? does it have its own window? is it a modification of an
12373 existing widget? Then find a similar widget, and start making changes.
12374 Good luck!
12375
12376 <!-- ***************************************************************** -->
12377 <sect>Scribble, A Simple Example Drawing Program
12378 <!-- ***************************************************************** -->
12379
12380 <!-- ----------------------------------------------------------------- -->
12381 <sect1> Overview
12382
12383 <p>
12384 In this section, we will build a simple drawing program. In the
12385 process, we will examine how to handle mouse events, how to draw in a
12386 window, and how to do drawing better by using a backing pixmap. After
12387 creating the simple drawing program, we will extend it by adding
12388 support for XInput devices, such as drawing tablets. GTK provides
12389 support routines which makes getting extended information, such as
12390 pressure and tilt, from such devices quite easy.
12391
12392 <!-- ----------------------------------------------------------------- -->
12393 <sect1> Event Handling
12394
12395 <p>
12396 The GTK signals we have already discussed are for high-level actions,
12397 such as a menu item being selected. However, sometimes it is useful to
12398 learn about lower-level occurrences, such as the mouse being moved, or
12399 a key being pressed. There are also GTK signals corresponding to these
12400 low-level <em>events</em>. The handlers for these signals have an
12401 extra parameter which is a pointer to a structure containing
12402 information about the event. For instance, motion events handlers are
12403 passed a pointer to a GdkEventMotion structure which looks (in part)
12404 like:
12405
12406 <tscreen><verb>
12407 struct _GdkEventMotion
12408 {
12409   GdkEventType type;
12410   GdkWindow *window;
12411   guint32 time;
12412   gdouble x;
12413   gdouble y;
12414   ...
12415   guint state;
12416   ...
12417 };
12418 </verb></tscreen>
12419
12420 <tt/type/ will be set to the event type, in this case
12421 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
12422 occurred. <tt/x/ and <tt/y/ give the coordinates of the event,
12423 and <tt/state/ specifies the modifier state when the event
12424 occurred (that is, it specifies which modifier keys and mouse buttons
12425 were pressed.) It is the bitwise OR of some of the following:
12426
12427 <tscreen><verb>
12428 GDK_SHIFT_MASK  
12429 GDK_LOCK_MASK   
12430 GDK_CONTROL_MASK
12431 GDK_MOD1_MASK   
12432 GDK_MOD2_MASK   
12433 GDK_MOD3_MASK   
12434 GDK_MOD4_MASK   
12435 GDK_MOD5_MASK   
12436 GDK_BUTTON1_MASK
12437 GDK_BUTTON2_MASK
12438 GDK_BUTTON3_MASK
12439 GDK_BUTTON4_MASK
12440 GDK_BUTTON5_MASK
12441 </verb></tscreen>
12442
12443 <p>
12444 As for other signals, to determine what happens when an event occurs
12445 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
12446 know which events we want to be notified about. To do this, we call
12447 the function:
12448
12449 <tscreen><verb>
12450 void gtk_widget_set_events (GtkWidget *widget,
12451                             gint      events);
12452 </verb></tscreen>
12453
12454 The second field specifies the events we are interested in. It
12455 is the bitwise OR of constants that specify different types
12456 of events. For future reference the event types are:
12457
12458 <tscreen><verb>
12459 GDK_EXPOSURE_MASK
12460 GDK_POINTER_MOTION_MASK
12461 GDK_POINTER_MOTION_HINT_MASK
12462 GDK_BUTTON_MOTION_MASK     
12463 GDK_BUTTON1_MOTION_MASK    
12464 GDK_BUTTON2_MOTION_MASK    
12465 GDK_BUTTON3_MOTION_MASK    
12466 GDK_BUTTON_PRESS_MASK      
12467 GDK_BUTTON_RELEASE_MASK    
12468 GDK_KEY_PRESS_MASK         
12469 GDK_KEY_RELEASE_MASK       
12470 GDK_ENTER_NOTIFY_MASK      
12471 GDK_LEAVE_NOTIFY_MASK      
12472 GDK_FOCUS_CHANGE_MASK      
12473 GDK_STRUCTURE_MASK         
12474 GDK_PROPERTY_CHANGE_MASK   
12475 GDK_PROXIMITY_IN_MASK      
12476 GDK_PROXIMITY_OUT_MASK     
12477 </verb></tscreen>
12478
12479 There are a few subtle points that have to be observed when calling
12480 <tt/gtk_widget_set_events()/. First, it must be called before the X window
12481 for a GTK widget is created. In practical terms, this means you
12482 should call it immediately after creating the widget. Second, the
12483 widget must have an associated X window. For efficiency, many widget
12484 types do not have their own window, but draw in their parent's window.
12485 These widgets are:
12486
12487 <tscreen><verb>
12488 GtkAlignment
12489 GtkArrow
12490 GtkBin
12491 GtkBox
12492 GtkImage
12493 GtkItem
12494 GtkLabel
12495 GtkPixmap
12496 GtkScrolledWindow
12497 GtkSeparator
12498 GtkTable
12499 GtkAspectFrame
12500 GtkFrame
12501 GtkVBox
12502 GtkHBox
12503 GtkVSeparator
12504 GtkHSeparator
12505 </verb></tscreen>
12506
12507 To capture events for these widgets, you need to use an EventBox
12508 widget. See the section on the <ref id="sec_EventBox"
12509 name="EventBox"> widget for details.
12510
12511 <p>
12512 For our drawing program, we want to know when the mouse button is
12513 pressed and when the mouse is moved, so we specify
12514 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
12515 want to know when we need to redraw our window, so we specify
12516 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
12517 Configure event when our window size changes, we don't have to specify
12518 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
12519 automatically specified for all windows.
12520
12521 <p>
12522 It turns out, however, that there is a problem with just specifying
12523 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
12524 motion event to the event queue every time the user moves the mouse.
12525 Imagine that it takes us 0.1 seconds to handle a motion event, but the
12526 X server queues a new motion event every 0.05 seconds. We will soon
12527 get way behind the users drawing. If the user draws for 5 seconds,
12528 it will take us another 5 seconds to catch up after they release 
12529 the mouse button! What we would like is to only get one motion
12530 event for each event we process. The way to do this is to 
12531 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
12532
12533 <p>
12534 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
12535 us a motion event the first time the pointer moves after entering
12536 our window, or after a button press or release event. Subsequent 
12537 motion events will be suppressed until we explicitly ask for
12538 the position of the pointer using the function:
12539
12540 <tscreen><verb>
12541 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
12542                                           gint            *x,
12543                                           gint            *y,
12544                                           GdkModifierType *mask);
12545 </verb></tscreen>
12546
12547 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
12548 has a simpler interface, but turns out not to be very useful, since
12549 it only retrieves the position of the mouse, not whether the buttons
12550 are pressed.)
12551
12552 <p>
12553 The code to set the events for our window then looks like:
12554
12555 <tscreen><verb>
12556   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
12557                       (GtkSignalFunc) expose_event, NULL);
12558   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
12559                       (GtkSignalFunc) configure_event, NULL);
12560   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
12561                       (GtkSignalFunc) motion_notify_event, NULL);
12562   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
12563                       (GtkSignalFunc) button_press_event, NULL);
12564
12565   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
12566                          | GDK_LEAVE_NOTIFY_MASK
12567                          | GDK_BUTTON_PRESS_MASK
12568                          | GDK_POINTER_MOTION_MASK
12569                          | GDK_POINTER_MOTION_HINT_MASK);
12570 </verb></tscreen>
12571
12572 We'll save the "expose_event" and "configure_event" handlers for
12573 later. The "motion_notify_event" and "button_press_event" handlers
12574 pretty simple:
12575
12576 <tscreen><verb>
12577 static gint
12578 button_press_event (GtkWidget *widget, GdkEventButton *event)
12579 {
12580   if (event->button == 1 &amp;&amp; pixmap != NULL)
12581       draw_brush (widget, event->x, event->y);
12582
12583   return TRUE;
12584 }
12585
12586 static gint
12587 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
12588 {
12589   int x, y;
12590   GdkModifierType state;
12591
12592   if (event->is_hint)
12593     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
12594   else
12595     {
12596       x = event->x;
12597       y = event->y;
12598       state = event->state;
12599     }
12600     
12601   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
12602     draw_brush (widget, x, y);
12603   
12604   return TRUE;
12605 }
12606 </verb></tscreen>
12607
12608 <!-- ----------------------------------------------------------------- -->
12609 <sect1> The DrawingArea Widget, And Drawing
12610
12611 <p>
12612 We know turn to the process of drawing on the screen. The 
12613 widget we use for this is the DrawingArea widget. A drawing area
12614 widget is essentially an X window and nothing more. It is a blank
12615 canvas in which we can draw whatever we like. A drawing area
12616 is created using the call:
12617
12618 <tscreen><verb>
12619 GtkWidget* gtk_drawing_area_new        (void);
12620 </verb></tscreen>
12621
12622 A default size for the widget can be specified by calling:
12623
12624 <tscreen><verb>
12625 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
12626                                         gint                 width,
12627                                         gint                 height);
12628 </verb></tscreen>
12629
12630 This default size can be overridden, as is true for all widgets,
12631 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
12632 be overridden if the user manually resizes the the window containing
12633 the drawing area.
12634
12635 <p>
12636 It should be noted that when we create a DrawingArea widget, we are,
12637 <em>completely</em> responsible for drawing the contents. If our
12638 window is obscured then uncovered, we get an exposure event and must
12639 redraw what was previously hidden.
12640
12641 <p>
12642 Having to remember everything that was drawn on the screen so we
12643 can properly redraw it can, to say the least, be a nuisance. In
12644 addition, it can be visually distracting if portions of the
12645 window are cleared, then redrawn step by step. The solution to
12646 this problem is to use an offscreen <em>backing pixmap</em>.
12647 Instead of drawing directly to the screen, we draw to an image
12648 stored in server memory but not displayed, then when the image
12649 changes or new portions of the image are displayed, we copy the
12650 relevant portions onto the screen.
12651
12652 <p>
12653 To create an offscreen pixmap, we call the function:
12654
12655 <tscreen><verb>
12656 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
12657                                          gint        width,
12658                                          gint        height,
12659                                          gint        depth);
12660 </verb></tscreen>
12661
12662 The <tt>window</tt> parameter specifies a GDK window that this pixmap
12663 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
12664 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
12665 depth</em>, that is the number of bits per pixel, for the new window.
12666 If the depth is specified as <tt>-1</tt>, it will match the depth
12667 of <tt>window</tt>.
12668
12669 <p>
12670 We create the pixmap in our "configure_event" handler. This event
12671 is generated whenever the window changes size, including when it
12672 is originally created.
12673
12674 <tscreen><verb>
12675 /* Backing pixmap for drawing area */
12676 static GdkPixmap *pixmap = NULL;
12677
12678 /* Create a new backing pixmap of the appropriate size */
12679 static gint
12680 configure_event (GtkWidget *widget, GdkEventConfigure *event)
12681 {
12682   if (pixmap)
12683     gdk_pixmap_unref(pixmap);
12684
12685   pixmap = gdk_pixmap_new(widget->window,
12686                           widget->allocation.width,
12687                           widget->allocation.height,
12688                           -1);
12689   gdk_draw_rectangle (pixmap,
12690                       widget->style->white_gc,
12691                       TRUE,
12692                       0, 0,
12693                       widget->allocation.width,
12694                       widget->allocation.height);
12695
12696   return TRUE;
12697 }
12698 </verb></tscreen>
12699
12700 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
12701 initially to white. We'll say more about that in a moment.
12702
12703 <p>
12704 Our exposure event handler then simply copies the relevant portion
12705 of the pixmap onto the screen (we determine the area we need
12706 to redraw by using the event->area field of the exposure event):
12707
12708 <tscreen><verb>
12709 /* Redraw the screen from the backing pixmap */
12710 static gint
12711 expose_event (GtkWidget *widget, GdkEventExpose *event)
12712 {
12713   gdk_draw_pixmap(widget->window,
12714                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
12715                   pixmap,
12716                   event->area.x, event->area.y,
12717                   event->area.x, event->area.y,
12718                   event->area.width, event->area.height);
12719
12720   return FALSE;
12721 }
12722 </verb></tscreen>
12723
12724 We've now seen how to keep the screen up to date with our pixmap, but
12725 how do we actually draw interesting stuff on our pixmap?  There are a
12726 large number of calls in GTK's GDK library for drawing on
12727 <em>drawables</em>. A drawable is simply something that can be drawn
12728 upon. It can be a window, a pixmap, or a bitmap (a black and white
12729 image).  We've already seen two such calls above,
12730 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
12731 complete list is:
12732
12733 <tscreen><verb>
12734 gdk_draw_line ()
12735 gdk_draw_rectangle ()
12736 gdk_draw_arc ()
12737 gdk_draw_polygon ()
12738 gdk_draw_string ()
12739 gdk_draw_text ()
12740 gdk_draw_pixmap ()
12741 gdk_draw_bitmap ()
12742 gdk_draw_image ()
12743 gdk_draw_points ()
12744 gdk_draw_segments ()
12745 </verb></tscreen>
12746
12747 See the reference documentation or the header file
12748 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
12749 These functions all share the same first two arguments. The first
12750 argument is the drawable to draw upon, the second argument is a
12751 <em>graphics context</em> (GC). 
12752
12753 <p>
12754 A graphics context encapsulates information about things such as
12755 foreground and background color and line width. GDK has a full set of
12756 functions for creating and modifying graphics contexts, but to keep
12757 things simple we'll just use predefined graphics contexts. Each widget
12758 has an associated style. (Which can be modified in a gtkrc file, see
12759 the section GTK's rc file.) This, among other things, stores a number
12760 of graphics contexts. Some examples of accessing these graphics
12761 contexts are:
12762
12763 <tscreen><verb>
12764 widget->style->white_gc
12765 widget->style->black_gc
12766 widget->style->fg_gc[GTK_STATE_NORMAL]
12767 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
12768 </verb></tscreen>
12769
12770 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
12771 <tt>light_gc</tt> are indexed by a parameter of type
12772 <tt>GtkStateType</tt> which can take on the values:
12773
12774 <tscreen><verb>
12775 GTK_STATE_NORMAL,
12776 GTK_STATE_ACTIVE,
12777 GTK_STATE_PRELIGHT,
12778 GTK_STATE_SELECTED,
12779 GTK_STATE_INSENSITIVE
12780 </verb></tscreen>
12781
12782 For instance, the for <tt/GTK_STATE_SELECTED/ the default foreground
12783 color is white and the default background color, dark blue.
12784
12785 <p>
12786 Our function <tt>draw_brush()</tt>, which does the actual drawing
12787 on the screen, is then:
12788
12789 <tscreen><verb>
12790 /* Draw a rectangle on the screen */
12791 static void
12792 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
12793 {
12794   GdkRectangle update_rect;
12795
12796   update_rect.x = x - 5;
12797   update_rect.y = y - 5;
12798   update_rect.width = 10;
12799   update_rect.height = 10;
12800   gdk_draw_rectangle (pixmap,
12801                       widget->style->black_gc,
12802                       TRUE,
12803                       update_rect.x, update_rect.y,
12804                       update_rect.width, update_rect.height);
12805   gtk_widget_draw (widget, &amp;update_rect);
12806 }
12807 </verb></tscreen>
12808
12809 After we draw the rectangle representing the brush onto the pixmap,
12810 we call the function:
12811
12812 <tscreen><verb>
12813 void       gtk_widget_draw                (GtkWidget           *widget,
12814                                            GdkRectangle        *area);
12815 </verb></tscreen>
12816
12817 which notifies X that the area given by the <tt>area</tt> parameter
12818 needs to be updated. X will eventually generate an expose event
12819 (possibly combining the areas passed in several calls to
12820 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
12821 to copy the relevant portions to the screen.
12822
12823 <p>
12824 We have now covered the entire drawing program except for a few
12825 mundane details like creating the main window. The complete
12826 source code is available from the location from which you got
12827 this tutorial, or from:
12828
12829 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12830 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12831
12832
12833 <!-- ----------------------------------------------------------------- -->
12834 <sect1> Adding XInput support
12835
12836 <p>
12837
12838 It is now possible to buy quite inexpensive input devices such 
12839 as drawing tablets, which allow drawing with a much greater
12840 ease of artistic expression than does a mouse. The simplest way
12841 to use such devices is simply as a replacement for the mouse,
12842 but that misses out many of the advantages of these devices,
12843 such as:
12844
12845 <itemize>
12846 <item> Pressure sensitivity
12847 <item> Tilt reporting
12848 <item> Sub-pixel positioning
12849 <item> Multiple inputs (for example, a stylus with a point and eraser)
12850 </itemize>
12851
12852 For information about the XInput extension, see the <htmlurl
12853 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
12854 name="XInput-HOWTO">.
12855
12856 <p>
12857 If we examine the full definition of, for example, the GdkEventMotion
12858 structure, we see that it has fields to support extended device
12859 information.
12860
12861 <tscreen><verb>
12862 struct _GdkEventMotion
12863 {
12864   GdkEventType type;
12865   GdkWindow *window;
12866   guint32 time;
12867   gdouble x;
12868   gdouble y;
12869   gdouble pressure;
12870   gdouble xtilt;
12871   gdouble ytilt;
12872   guint state;
12873   gint16 is_hint;
12874   GdkInputSource source;
12875   guint32 deviceid;
12876 };
12877 </verb></tscreen>
12878
12879 <tt/pressure/ gives the pressure as a floating point number between
12880 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
12881 -1 and 1, corresponding to the degree of tilt in each direction.
12882 <tt/source/ and <tt/deviceid/ specify the device for which the
12883 event occurred in two different ways. <tt/source/ gives some simple
12884 information about the type of device. It can take the enumeration
12885 values.
12886
12887 <tscreen><verb>
12888 GDK_SOURCE_MOUSE
12889 GDK_SOURCE_PEN
12890 GDK_SOURCE_ERASER
12891 GDK_SOURCE_CURSOR
12892 </verb></tscreen>
12893
12894 <tt/deviceid/ specifies a unique numeric ID for the device. This can
12895 be used to find out further information about the device using the
12896 <tt/gdk_input_list_devices()/ call (see below). The special value
12897 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
12898 the mouse.)
12899
12900 <sect2> Enabling extended device information
12901
12902 <p>
12903 To let GTK know about our interest in the extended device information,
12904 we merely have to add a single line to our program:
12905
12906 <tscreen><verb>
12907 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
12908 </verb></tscreen>
12909
12910 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
12911 we are interested in extension events, but only if we don't have
12912 to draw our own cursor. See the section <ref
12913 id="sec_Further_Sophistications" name="Further Sophistications"> below
12914 for more information about drawing the cursor. We could also 
12915 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
12916 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
12917 back to the default condition.
12918
12919 <p>
12920 This is not completely the end of the story however. By default,
12921 no extension devices are enabled. We need a mechanism to allow
12922 users to enable and configure their extension devices. GTK provides
12923 the InputDialog widget to automate this process. The following
12924 procedure manages an InputDialog widget. It creates the dialog if
12925 it isn't present, and raises it to the top otherwise.
12926
12927 <tscreen><verb>
12928 void
12929 input_dialog_destroy (GtkWidget *w, gpointer data)
12930 {
12931   *((GtkWidget **)data) = NULL;
12932 }
12933
12934 void
12935 create_input_dialog ()
12936 {
12937   static GtkWidget *inputd = NULL;
12938
12939   if (!inputd)
12940     {
12941       inputd = gtk_input_dialog_new();
12942
12943       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
12944                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
12945       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
12946                                  "clicked",
12947                                  (GtkSignalFunc)gtk_widget_hide,
12948                                  GTK_OBJECT(inputd));
12949       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
12950
12951       gtk_widget_show (inputd);
12952     }
12953   else
12954     {
12955       if (!GTK_WIDGET_MAPPED(inputd))
12956         gtk_widget_show(inputd);
12957       else
12958         gdk_window_raise(inputd->window);
12959     }
12960 }
12961 </verb></tscreen>
12962
12963 (You might want to take note of the way we handle this dialog.  By
12964 connecting to the "destroy" signal, we make sure that we don't keep a
12965 pointer to dialog around after it is destroyed - that could lead to a
12966 segfault.)
12967
12968 <p>
12969 The InputDialog has two buttons "Close" and "Save", which by default
12970 have no actions assigned to them. In the above function we make
12971 "Close" hide the dialog, hide the "Save" button, since we don't
12972 implement saving of XInput options in this program.
12973
12974 <sect2> Using extended device information
12975
12976 <p>
12977 Once we've enabled the device, we can just use the extended 
12978 device information in the extra fields of the event structures.
12979 In fact, it is always safe to use this information since these
12980 fields will have reasonable default values even when extended
12981 events are not enabled.
12982
12983 <p>
12984 Once change we do have to make is to call
12985 <tt/gdk_input_window_get_pointer()/ instead of
12986 <tt/gdk_window_get_pointer/. This is necessary because
12987 <tt/gdk_window_get_pointer/ doesn't return the extended device
12988 information.
12989
12990 <tscreen><verb>
12991 void gdk_input_window_get_pointer     (GdkWindow       *window,
12992                                        guint32         deviceid,
12993                                        gdouble         *x,
12994                                        gdouble         *y,
12995                                        gdouble         *pressure,
12996                                        gdouble         *xtilt,
12997                                        gdouble         *ytilt,
12998                                        GdkModifierType *mask);
12999 </verb></tscreen>
13000
13001 When calling this function, we need to specify the device ID as
13002 well as the window. Usually, we'll get the device ID from the
13003 <tt/deviceid/ field of an event structure. Again, this function
13004 will return reasonable values when extension events are not
13005 enabled. (In this case, <tt/event->deviceid/ will have the value
13006 <tt/GDK_CORE_POINTER/).
13007
13008 So the basic structure of our button-press and motion event handlers,
13009 doesn't change much - we just need to add code to deal with the
13010 extended information.
13011
13012 <tscreen><verb>
13013 static gint
13014 button_press_event (GtkWidget *widget, GdkEventButton *event)
13015 {
13016   print_button_press (event->deviceid);
13017   
13018   if (event->button == 1 &amp;&amp; pixmap != NULL)
13019     draw_brush (widget, event->source, event->x, event->y, event->pressure);
13020
13021   return TRUE;
13022 }
13023
13024 static gint
13025 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13026 {
13027   gdouble x, y;
13028   gdouble pressure;
13029   GdkModifierType state;
13030
13031   if (event->is_hint)
13032     gdk_input_window_get_pointer (event->window, event->deviceid,
13033                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
13034   else
13035     {
13036       x = event->x;
13037       y = event->y;
13038       pressure = event->pressure;
13039       state = event->state;
13040     }
13041     
13042   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13043     draw_brush (widget, event->source, x, y, pressure);
13044   
13045   return TRUE;
13046 }
13047 </verb></tscreen>
13048
13049 We also need to do something with the new information. Our new
13050 <tt/draw_brush()/ function draws with a different color for
13051 each <tt/event->source/ and changes the brush size depending
13052 on the pressure.
13053
13054 <tscreen><verb>
13055 /* Draw a rectangle on the screen, size depending on pressure,
13056    and color on the type of device */
13057 static void
13058 draw_brush (GtkWidget *widget, GdkInputSource source,
13059             gdouble x, gdouble y, gdouble pressure)
13060 {
13061   GdkGC *gc;
13062   GdkRectangle update_rect;
13063
13064   switch (source)
13065     {
13066     case GDK_SOURCE_MOUSE:
13067       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
13068       break;
13069     case GDK_SOURCE_PEN:
13070       gc = widget->style->black_gc;
13071       break;
13072     case GDK_SOURCE_ERASER:
13073       gc = widget->style->white_gc;
13074       break;
13075     default:
13076       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
13077     }
13078
13079   update_rect.x = x - 10 * pressure;
13080   update_rect.y = y - 10 * pressure;
13081   update_rect.width = 20 * pressure;
13082   update_rect.height = 20 * pressure;
13083   gdk_draw_rectangle (pixmap, gc, TRUE,
13084                       update_rect.x, update_rect.y,
13085                       update_rect.width, update_rect.height);
13086   gtk_widget_draw (widget, &amp;update_rect);
13087 }
13088 </verb></tscreen>
13089
13090 <sect2> Finding out more about a device
13091
13092 <p>
13093 As an example of how to find out more about a device, our program
13094 will print the name of the device that generates each button
13095 press. To find out the name of a device, we call the function:
13096
13097 <tscreen><verb>
13098 GList *gdk_input_list_devices               (void);
13099 </verb></tscreen>
13100
13101 which returns a GList (a linked list type from the glib library)
13102 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
13103 as:
13104
13105 <tscreen><verb>
13106 struct _GdkDeviceInfo
13107 {
13108   guint32 deviceid;
13109   gchar *name;
13110   GdkInputSource source;
13111   GdkInputMode mode;
13112   gint has_cursor;
13113   gint num_axes;
13114   GdkAxisUse *axes;
13115   gint num_keys;
13116   GdkDeviceKey *keys;
13117 };
13118 </verb></tscreen>
13119
13120 Most of these fields are configuration information that you
13121 can ignore unless you are implemented XInput configuration
13122 saving. The we are interested in here is <tt/name/ which is
13123 simply the name that X assigns to the device. The other field
13124 that isn't configuration information is <tt/has_cursor/. If
13125 <tt/has_cursor/ is false, then we we need to draw our own
13126 cursor. But since we've specified <tt/GDK_EXTENSION_EVENTS_CURSOR/,
13127 we don't have to worry about this.
13128
13129 <p>
13130 Our <tt/print_button_press()/ function simply iterates through
13131 the returned list until it finds a match, then prints out
13132 the name of the device.
13133
13134 <tscreen><verb>
13135 static void
13136 print_button_press (guint32 deviceid)
13137 {
13138   GList *tmp_list;
13139
13140   /* gdk_input_list_devices returns an internal list, so we shouldn't
13141      free it afterwards */
13142   tmp_list = gdk_input_list_devices();
13143
13144   while (tmp_list)
13145     {
13146       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
13147
13148       if (info->deviceid == deviceid)
13149         {
13150           printf("Button press on device '%s'\n", info->name);
13151           return;
13152         }
13153
13154       tmp_list = tmp_list->next;
13155     }
13156 }
13157 </verb></tscreen>
13158
13159 That completes the changes to `XInputize' our program. As with
13160 the first version, the complete source is available at the location
13161 from which you got this tutorial, or from:
13162
13163 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13164 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13165
13166
13167 <sect2> Further sophistications <label id="sec_Further_Sophistications">
13168
13169 <p>
13170 Although our program now supports XInput quite well, it lacks some
13171 features we would want in a full-featured application. First, the user
13172 probably doesn't want to have to configure their device each time they
13173 run the program, so we should allow them to save the device
13174 configuration. This is done by iterating through the return of
13175 <tt/gdk_input_list_devices()/ and writing out the configuration to a
13176 file.
13177
13178 <p>
13179 To restore the state next time the program is run, GDK provides
13180 functions to change device configuration:
13181
13182 <tscreen><verb>
13183 gdk_input_set_extension_events()
13184 gdk_input_set_source()
13185 gdk_input_set_mode()
13186 gdk_input_set_axes()
13187 gdk_input_set_key()
13188 </verb></tscreen>
13189
13190 (The list returned from <tt/gdk_input_list_devices()/ should not be
13191 modified directly.) An example of doing this can be found in the
13192 drawing program gsumi. (Available from <htmlurl
13193 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
13194 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
13195 would be nice to have a standard way of doing this for all
13196 applications. This probably belongs at a slightly higher level than
13197 GTK, perhaps in the GNOME library.
13198
13199 <p>
13200 Another major omission that we have mentioned above is the lack of
13201 cursor drawing. Platforms other than XFree86 currently do not allow
13202 simultaneously using a device as both the core pointer and directly by
13203 an application. See the <url
13204 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13205 name="XInput-HOWTO"> for more information about this. This means that
13206 applications that want to support the widest audience need to draw
13207 their own cursor.
13208
13209 <p>
13210 An application that draws its own cursor needs to do two things:
13211 determine if the current device needs a cursor drawn or not, and
13212 determine if the current device is in proximity. (If the current
13213 device is a drawing tablet, it's a nice touch to make the cursor 
13214 disappear when the stylus is lifted from the tablet. When the
13215 device is touching the stylus, that is called "in proximity.")
13216 The first is done by searching the device list, as we did
13217 to find out the device name. The second is achieved by selecting
13218 "proximity_out" events. An example of drawing one's own cursor is
13219 found in the 'testinput' program found in the GTK distribution.
13220
13221 <!-- ***************************************************************** -->
13222 <sect>Tips For Writing GTK Applications
13223 <!-- ***************************************************************** -->
13224
13225 <p>
13226 This section is simply a gathering of wisdom, general style guidelines
13227 and hints to creating good GTK applications. It is totally useless
13228 right now cause its only a topic sentence :)
13229
13230 Use GNU autoconf and automake!  They are your friends :) I am planning
13231 to make a quick intro on them here.
13232
13233 <!-- ***************************************************************** -->
13234 <sect>Contributing <label id="sec_Contributing">
13235 <!-- ***************************************************************** -->
13236
13237 <p>
13238 This document, like so much other great software out there, was
13239 created for free by volunteers.  If you are at all knowledgeable about
13240 any aspect of GTK that does not already have documentation, please
13241 consider contributing to this document.
13242 <p>
13243 If you do decide to contribute, please mail your text to Tony Gale,
13244 <tt><htmlurl url="mailto:gale@gtk.org"
13245 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
13246 document is free, and any addition by you provide must also be
13247 free. That is, people may use any portion of your examples in their
13248 programs, and copies of this document may be distributed at will etc.
13249 <p>
13250 Thank you.
13251
13252 <!-- ***************************************************************** -->
13253 <sect>Credits
13254 <!-- ***************************************************************** -->
13255 <p>
13256 I would like to thank the following for their contributions to this text.
13257
13258 <itemize>
13259 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
13260 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
13261
13262 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
13263 name="raph@acm.org"></tt>
13264 for hello world ala GTK, widget packing, and general all around wisdom.
13265 He's also generously donated a home for this tutorial.
13266
13267 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
13268 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
13269 and the ability to make it :)
13270
13271 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
13272 name="werner.koch@guug.de"></tt> for converting the original plain text to
13273 SGML, and the widget class hierarchy.
13274
13275 <item>Mark Crichton <tt><htmlurl
13276 url="mailto:crichton@expert.cc.purdue.edu"
13277 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
13278 and the table packing tutorial.
13279
13280 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
13281 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
13282 patch to the distro).  He's also responsible for the selections code
13283 and tutorial, as well as the sections on writing your own GTK widgets,
13284 and the example application. Thanks a lot Owen for all you help!
13285
13286 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
13287 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
13288 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
13289 lot Mark!  You've been a great help.
13290
13291 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
13292 name="timj@psynet.net"></tt> for his great job on the Lists
13293 Widget. His excellent work on automatically extracting the widget tree
13294 and signal information from GTK. Thanks Tim :)
13295
13296 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
13297 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
13298 tutorial.
13299
13300 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
13301 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
13302
13303 <item>David Huggins-Daines <tt><htmlurl
13304 url="mailto:bn711@freenet.carleton.ca"
13305 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
13306 Widget sections.
13307
13308 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
13309 name="mars@lysator.liu.se"></tt> for the GtkCList section
13310 </itemize>
13311
13312 And to all of you who commented and helped refine this document.
13313
13314 Thanks.
13315
13316 <!-- ***************************************************************** -->
13317 <sect> Tutorial Copyright and Permissions Notice
13318 <!-- ***************************************************************** -->
13319
13320 <p>
13321 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
13322
13323 Copyright (C) 1998-1999 Tony Gale.
13324
13325 Permission is granted to make and distribute verbatim copies of this 
13326 manual provided the copyright notice and this permission notice are 
13327 preserved on all copies.
13328
13329 Permission is granted to copy and distribute modified versions of 
13330 this document under the conditions for verbatim copying, provided that 
13331 this copyright notice is included exactly as in the original,
13332 and that the entire resulting derived work is distributed under 
13333 the terms of a permission notice identical to this one.
13334 <P>Permission is granted to copy and distribute translations of this 
13335 document into another language, under the above conditions for modified 
13336 versions.
13337
13338 If you are intending to incorporate this document into a published 
13339 work, please contact the maintainer, and we will make an effort 
13340 to ensure that you have the most up to date information available.
13341
13342 There is no guarantee that this document lives up to its intended
13343 purpose.  This is simply provided as a free resource.  As such,
13344 the authors and maintainers of the information provided within can
13345 not make any guarantee that the information is even accurate.
13346
13347 <!-- ***************************************************************** -->
13348 <appendix>
13349 <!-- ***************************************************************** -->
13350
13351 <!-- ***************************************************************** -->
13352 <sect> GTK Signals <label id="sec_GTK_Signals">
13353 <!-- ***************************************************************** -->
13354 <p>
13355 As GTK is an object oriented widget set, it has a hierarchy of
13356 inheritance. This inheritance mechanism applies for
13357 signals. Therefore, you should refer to the widget hierarchy tree when
13358 using the signals listed in this section.
13359
13360 <!-- ----------------------------------------------------------------- -->
13361 <sect1>GtkObject
13362 <!-- ----------------------------------------------------------------- -->
13363 <p>
13364 <tscreen><verb>
13365 void GtkObject::destroy (GtkObject *,
13366                          gpointer);
13367 </verb></tscreen>
13368
13369 <!-- ----------------------------------------------------------------- -->
13370 <sect1>GtkWidget
13371 <!-- ----------------------------------------------------------------- -->
13372 <p>
13373 <tscreen><verb>
13374
13375 void GtkWidget::show    (GtkWidget *,
13376                          gpointer);
13377 void GtkWidget::hide    (GtkWidget *,
13378                          gpointer);
13379 void GtkWidget::map     (GtkWidget *,
13380                          gpointer);
13381 void GtkWidget::unmap   (GtkWidget *,
13382                          gpointer);
13383 void GtkWidget::realize (GtkWidget *,
13384                          gpointer);
13385 void GtkWidget::unrealize       (GtkWidget *,
13386                                  gpointer);
13387 void GtkWidget::draw    (GtkWidget *,
13388                          ggpointer,
13389                          gpointer);
13390 void GtkWidget::draw-focus      (GtkWidget *,
13391                                  gpointer);
13392 void GtkWidget::draw-default    (GtkWidget *,
13393                                  gpointer);
13394 void GtkWidget::size-request    (GtkWidget *,
13395                                  ggpointer,
13396                                  gpointer);
13397 void GtkWidget::size-allocate   (GtkWidget *,
13398                                  ggpointer,
13399                                  gpointer);
13400 void GtkWidget::state-changed   (GtkWidget *,
13401                                  GtkStateType,
13402                                  gpointer);
13403 void GtkWidget::parent-set      (GtkWidget *,
13404                                  GtkObject *,
13405                                  gpointer);
13406 void GtkWidget::style-set       (GtkWidget *,
13407                                  GtkStyle *,
13408                                  gpointer);
13409 void GtkWidget::add-accelerator (GtkWidget *,
13410                                  gguint,
13411                                  GtkAccelGroup *,
13412                                  gguint,
13413                                  GdkModifierType,
13414                                  GtkAccelFlags,
13415                                  gpointer);
13416 void GtkWidget::remove-accelerator      (GtkWidget *,
13417                                          GtkAccelGroup *,
13418                                          gguint,
13419                                          GdkModifierType,
13420                                          gpointer);
13421 gboolean GtkWidget::event       (GtkWidget *,
13422                                  GdkEvent *,
13423                                  gpointer);
13424 gboolean GtkWidget::button-press-event  (GtkWidget *,
13425                                          GdkEvent *,
13426                                          gpointer);
13427 gboolean GtkWidget::button-release-event        (GtkWidget *,
13428                                                  GdkEvent *,
13429                                                  gpointer);
13430 gboolean GtkWidget::motion-notify-event (GtkWidget *,
13431                                          GdkEvent *,
13432                                          gpointer);
13433 gboolean GtkWidget::delete-event        (GtkWidget *,
13434                                          GdkEvent *,
13435                                          gpointer);
13436 gboolean GtkWidget::destroy-event       (GtkWidget *,
13437                                          GdkEvent *,
13438                                          gpointer);
13439 gboolean GtkWidget::expose-event        (GtkWidget *,
13440                                          GdkEvent *,
13441                                          gpointer);
13442 gboolean GtkWidget::key-press-event     (GtkWidget *,
13443                                          GdkEvent *,
13444                                          gpointer);
13445 gboolean GtkWidget::key-release-event   (GtkWidget *,
13446                                          GdkEvent *,
13447                                          gpointer);
13448 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
13449                                          GdkEvent *,
13450                                          gpointer);
13451 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
13452                                          GdkEvent *,
13453                                          gpointer);
13454 gboolean GtkWidget::configure-event     (GtkWidget *,
13455                                          GdkEvent *,
13456                                          gpointer);
13457 gboolean GtkWidget::focus-in-event      (GtkWidget *,
13458                                          GdkEvent *,
13459                                          gpointer);
13460 gboolean GtkWidget::focus-out-event     (GtkWidget *,
13461                                          GdkEvent *,
13462                                          gpointer);
13463 gboolean GtkWidget::map-event   (GtkWidget *,
13464                                  GdkEvent *,
13465                                  gpointer);
13466 gboolean GtkWidget::unmap-event (GtkWidget *,
13467                                  GdkEvent *,
13468                                  gpointer);
13469 gboolean GtkWidget::property-notify-event       (GtkWidget *,
13470                                                  GdkEvent *,
13471                                                  gpointer);
13472 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
13473                                                  GdkEvent *,
13474                                                  gpointer);
13475 gboolean GtkWidget::selection-request-event     (GtkWidget *,
13476                                                  GdkEvent *,
13477                                                  gpointer);
13478 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
13479                                                  GdkEvent *,
13480                                                  gpointer);
13481 void GtkWidget::selection-get   (GtkWidget *,
13482                                  GtkSelectionData *,
13483                                  gguint,
13484                                  gpointer);
13485 void GtkWidget::selection-received      (GtkWidget *,
13486                                          GtkSelectionData *,
13487                                          gguint,
13488                                          gpointer);
13489 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
13490                                          GdkEvent *,
13491                                          gpointer);
13492 gboolean GtkWidget::proximity-out-event (GtkWidget *,
13493                                          GdkEvent *,
13494                                          gpointer);
13495 void GtkWidget::drag-begin      (GtkWidget *,
13496                                  GdkDragContext *,
13497                                  gpointer);
13498 void GtkWidget::drag-end        (GtkWidget *,
13499                                  GdkDragContext *,
13500                                  gpointer);
13501 void GtkWidget::drag-data-delete        (GtkWidget *,
13502                                          GdkDragContext *,
13503                                          gpointer);
13504 void GtkWidget::drag-leave      (GtkWidget *,
13505                                  GdkDragContext *,
13506                                  gguint,
13507                                  gpointer);
13508 gboolean GtkWidget::drag-motion (GtkWidget *,
13509                                  GdkDragContext *,
13510                                  ggint,
13511                                  ggint,
13512                                  gguint,
13513                                  gpointer);
13514 gboolean GtkWidget::drag-drop   (GtkWidget *,
13515                                  GdkDragContext *,
13516                                  ggint,
13517                                  ggint,
13518                                  gguint,
13519                                  gpointer);
13520 void GtkWidget::drag-data-get   (GtkWidget *,
13521                                  GdkDragContext *,
13522                                  GtkSelectionData *,
13523                                  gguint,
13524                                  gguint,
13525                                  gpointer);
13526 void GtkWidget::drag-data-received      (GtkWidget *,
13527                                          GdkDragContext *,
13528                                          ggint,
13529                                          ggint,
13530                                          GtkSelectionData *,
13531                                          gguint,
13532                                          gguint,
13533                                          gpointer);
13534 gboolean GtkWidget::client-event        (GtkWidget *,
13535                                          GdkEvent *,
13536                                          gpointer);
13537 gboolean GtkWidget::no-expose-event     (GtkWidget *,
13538                                          GdkEvent *,
13539                                          gpointer);
13540 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
13541                                                  GdkEvent *,
13542                                                  gpointer);
13543 void GtkWidget::debug-msg       (GtkWidget *,
13544                                  GtkString *,
13545                                  gpointer);
13546 </verb></tscreen>
13547
13548 <!-- ----------------------------------------------------------------- -->
13549 <sect1>GtkData
13550 <!-- ----------------------------------------------------------------- -->
13551 <p>
13552 <tscreen><verb>
13553 void GtkData::disconnect        (GtkData *,
13554                                  gpointer);
13555 </verb></tscreen>
13556
13557 <!-- ----------------------------------------------------------------- -->
13558 <sect1>GtkContainer
13559 <!-- ----------------------------------------------------------------- -->
13560 <p>
13561 <tscreen><verb>
13562 void GtkContainer::add  (GtkContainer *,
13563                          GtkWidget *,
13564                          gpointer);
13565 void GtkContainer::remove       (GtkContainer *,
13566                                  GtkWidget *,
13567                                  gpointer);
13568 void GtkContainer::check-resize (GtkContainer *,
13569                                  gpointer);
13570 GtkDirectionType GtkContainer::focus    (GtkContainer *,
13571                                          GtkDirectionType,
13572                                          gpointer);
13573 void GtkContainer::set-focus-child      (GtkContainer *,
13574                                          GtkWidget *,
13575                                          gpointer);
13576 </verb></tscreen>
13577
13578 <!-- ----------------------------------------------------------------- -->
13579 <sect1>GtkCalendar
13580 <!-- ----------------------------------------------------------------- -->
13581 <p>
13582 <tscreen><verb>
13583 void GtkCalendar::month-changed (GtkCalendar *,
13584                                  gpointer);
13585 void GtkCalendar::day-selected  (GtkCalendar *,
13586                                  gpointer);
13587 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
13588                                                  gpointer);
13589 void GtkCalendar::prev-month    (GtkCalendar *,
13590                                  gpointer);
13591 void GtkCalendar::next-month    (GtkCalendar *,
13592                                  gpointer);
13593 void GtkCalendar::prev-year     (GtkCalendar *,
13594                                  gpointer);
13595 void GtkCalendar::next-year     (GtkCalendar *,
13596                                  gpointer);
13597 </verb></tscreen>
13598
13599 <!-- ----------------------------------------------------------------- -->
13600 <sect1>GtkEditable
13601 <!-- ----------------------------------------------------------------- -->
13602 <p>
13603 <tscreen><verb>
13604 void GtkEditable::changed       (GtkEditable *,
13605                                  gpointer);
13606 void GtkEditable::insert-text   (GtkEditable *,
13607                                  GtkString *,
13608                                  ggint,
13609                                  ggpointer,
13610                                  gpointer);
13611 void GtkEditable::delete-text   (GtkEditable *,
13612                                  ggint,
13613                                  ggint,
13614                                  gpointer);
13615 void GtkEditable::activate      (GtkEditable *,
13616                                  gpointer);
13617 void GtkEditable::set-editable  (GtkEditable *,
13618                                  gboolean,
13619                                  gpointer);
13620 void GtkEditable::move-cursor   (GtkEditable *,
13621                                  ggint,
13622                                  ggint,
13623                                  gpointer);
13624 void GtkEditable::move-word     (GtkEditable *,
13625                                  ggint,
13626                                  gpointer);
13627 void GtkEditable::move-page     (GtkEditable *,
13628                                  ggint,
13629                                  ggint,
13630                                  gpointer);
13631 void GtkEditable::move-to-row   (GtkEditable *,
13632                                  ggint,
13633                                  gpointer);
13634 void GtkEditable::move-to-column        (GtkEditable *,
13635                                          ggint,
13636                                          gpointer);
13637 void GtkEditable::kill-char     (GtkEditable *,
13638                                  ggint,
13639                                  gpointer);
13640 void GtkEditable::kill-word     (GtkEditable *,
13641                                  ggint,
13642                                  gpointer);
13643 void GtkEditable::kill-line     (GtkEditable *,
13644                                  ggint,
13645                                  gpointer);
13646 void GtkEditable::cut-clipboard (GtkEditable *,
13647                                  gpointer);
13648 void GtkEditable::copy-clipboard        (GtkEditable *,
13649                                          gpointer);
13650 void GtkEditable::paste-clipboard       (GtkEditable *,
13651                                          gpointer);
13652 </verb></tscreen>
13653
13654 <!-- ----------------------------------------------------------------- -->
13655 <sect1>GtkTipsQuery
13656 <!-- ----------------------------------------------------------------- -->
13657 <p>
13658 <tscreen><verb>
13659 void GtkTipsQuery::start-query  (GtkTipsQuery *,
13660                                  gpointer);
13661 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
13662                                  gpointer);
13663 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
13664                                          GtkWidget *,
13665                                          GtkString *,
13666                                          GtkString *,
13667                                          gpointer);
13668 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
13669                                          GtkWidget *,
13670                                          GtkString *,
13671                                          GtkString *,
13672                                          GdkEvent *,
13673                                          gpointer);
13674 </verb></tscreen>
13675
13676 <!-- ----------------------------------------------------------------- -->
13677 <sect1>GtkCList
13678 <!-- ----------------------------------------------------------------- -->
13679 <p>
13680 <tscreen><verb>
13681 void GtkCList::select-row       (GtkCList *,
13682                                  ggint,
13683                                  ggint,
13684                                  GdkEvent *,
13685                                  gpointer);
13686 void GtkCList::unselect-row     (GtkCList *,
13687                                  ggint,
13688                                  ggint,
13689                                  GdkEvent *,
13690                                  gpointer);
13691 void GtkCList::row-move (GtkCList *,
13692                          ggint,
13693                          ggint,
13694                          gpointer);
13695 void GtkCList::click-column     (GtkCList *,
13696                                  ggint,
13697                                  gpointer);
13698 void GtkCList::resize-column    (GtkCList *,
13699                                  ggint,
13700                                  ggint,
13701                                  gpointer);
13702 void GtkCList::toggle-focus-row (GtkCList *,
13703                                  gpointer);
13704 void GtkCList::select-all       (GtkCList *,
13705                                  gpointer);
13706 void GtkCList::unselect-all     (GtkCList *,
13707                                  gpointer);
13708 void GtkCList::undo-selection   (GtkCList *,
13709                                  gpointer);
13710 void GtkCList::start-selection  (GtkCList *,
13711                                  gpointer);
13712 void GtkCList::end-selection    (GtkCList *,
13713                                  gpointer);
13714 void GtkCList::toggle-add-mode  (GtkCList *,
13715                                  gpointer);
13716 void GtkCList::extend-selection (GtkCList *,
13717                                  GtkScrollType,
13718                                  ggfloat,
13719                                  gboolean,
13720                                  gpointer);
13721 void GtkCList::scroll-vertical  (GtkCList *,
13722                                  GtkScrollType,
13723                                  ggfloat,
13724                                  gpointer);
13725 void GtkCList::scroll-horizontal        (GtkCList *,
13726                                          GtkScrollType,
13727                                          ggfloat,
13728                                          gpointer);
13729 void GtkCList::abort-column-resize      (GtkCList *,
13730                                          gpointer);
13731 </verb></tscreen>
13732
13733 <!-- ----------------------------------------------------------------- -->
13734 <sect1>GtkNotebook
13735 <!-- ----------------------------------------------------------------- -->
13736 <p>
13737 <tscreen><verb>
13738 void GtkNotebook::switch-page   (GtkNotebook *,
13739                                  ggpointer,
13740                                  gguint,
13741                                  gpointer);
13742
13743 </verb></tscreen>
13744
13745 <!-- ----------------------------------------------------------------- -->
13746 <sect1>GtkList
13747 <!-- ----------------------------------------------------------------- -->
13748 <p>
13749 <tscreen><verb>
13750 void GtkList::selection-changed (GtkList *,
13751                                  gpointer);
13752 void GtkList::select-child      (GtkList *,
13753                                  GtkWidget *,
13754                                  gpointer);
13755 void GtkList::unselect-child    (GtkList *,
13756                                  GtkWidget *,
13757                                  gpointer);
13758 </verb></tscreen>
13759
13760 <!-- ----------------------------------------------------------------- -->
13761 <sect1>GtkMenuShell
13762 <!-- ----------------------------------------------------------------- -->
13763 <p>
13764 <tscreen><verb>
13765 void GtkMenuShell::deactivate   (GtkMenuShell *,
13766                                  gpointer);
13767 void GtkMenuShell::selection-done       (GtkMenuShell *,
13768                                          gpointer);
13769 void GtkMenuShell::move-current (GtkMenuShell *,
13770                                  GtkMenuDirectionType,
13771                                  gpointer);
13772 void GtkMenuShell::activate-current     (GtkMenuShell *,
13773                                          gboolean,
13774                                          gpointer);
13775 void GtkMenuShell::cancel       (GtkMenuShell *,
13776                                  gpointer);
13777 </verb></tscreen>
13778
13779 <!-- ----------------------------------------------------------------- -->
13780 <sect1>GtkToolbar
13781 <!-- ----------------------------------------------------------------- -->
13782 <p>
13783 <tscreen><verb>
13784 void GtkToolbar::orientation-changed    (GtkToolbar *,
13785                                          ggint,
13786                                          gpointer);
13787 void GtkToolbar::style-changed  (GtkToolbar *,
13788                                  ggint,
13789                                  gpointer);
13790 </verb></tscreen>
13791
13792 <!-- ----------------------------------------------------------------- -->
13793 <sect1>GtkTree
13794 <!-- ----------------------------------------------------------------- -->
13795 <p>
13796 <tscreen><verb>
13797 void GtkTree::selection-changed (GtkTree *,
13798                                  gpointer);
13799 void GtkTree::select-child      (GtkTree *,
13800                                  GtkWidget *,
13801                                  gpointer);
13802 void GtkTree::unselect-child    (GtkTree *,
13803                                  GtkWidget *,
13804                                  gpointer);
13805 </verb></tscreen>
13806
13807 <!-- ----------------------------------------------------------------- -->
13808 <sect1>GtkButton
13809 <!-- ----------------------------------------------------------------- -->
13810 <p>
13811 <tscreen><verb>
13812 void GtkButton::pressed (GtkButton *,
13813                          gpointer);
13814 void GtkButton::released        (GtkButton *,
13815                                  gpointer);
13816 void GtkButton::clicked (GtkButton *,
13817                          gpointer);
13818 void GtkButton::enter   (GtkButton *,
13819                          gpointer);
13820 void GtkButton::leave   (GtkButton *,
13821                          gpointer);
13822 </verb></tscreen>
13823
13824 <!-- ----------------------------------------------------------------- -->
13825 <sect1>GtkItem
13826 <!-- ----------------------------------------------------------------- -->
13827 <p>
13828 <tscreen><verb>
13829 void GtkItem::select    (GtkItem *,
13830                          gpointer);
13831 void GtkItem::deselect  (GtkItem *,
13832                          gpointer);
13833 void GtkItem::toggle    (GtkItem *,
13834                          gpointer);
13835 </verb></tscreen>
13836
13837 <!-- ----------------------------------------------------------------- -->
13838 <sect1>GtkWindow
13839 <!-- ----------------------------------------------------------------- -->
13840 <p>
13841 <tscreen><verb>
13842 void GtkWindow::set-focus       (GtkWindow *,
13843                                  ggpointer,
13844                                  gpointer);
13845 </verb></tscreen>
13846
13847 <!-- ----------------------------------------------------------------- -->
13848 <sect1>GtkHandleBox
13849 <!-- ----------------------------------------------------------------- -->
13850 <p>
13851 <tscreen><verb>
13852 void GtkHandleBox::child-attached       (GtkHandleBox *,
13853                                          GtkWidget *,
13854                                          gpointer);
13855 void GtkHandleBox::child-detached       (GtkHandleBox *,
13856                                          GtkWidget *,
13857                                          gpointer);
13858 </verb></tscreen>
13859
13860 <!-- ----------------------------------------------------------------- -->
13861 <sect1>GtkToggleButton
13862 <!-- ----------------------------------------------------------------- -->
13863 <p>
13864 <tscreen><verb>
13865 void GtkToggleButton::toggled   (GtkToggleButton *,
13866                                  gpointer);
13867
13868 </verb></tscreen>
13869
13870 <!-- ----------------------------------------------------------------- -->
13871 <sect1>GtkMenuItem
13872 <!-- ----------------------------------------------------------------- -->
13873 <p>
13874 <tscreen><verb>
13875 void GtkMenuItem::activate      (GtkMenuItem *,
13876                                  gpointer);
13877 void GtkMenuItem::activate-item (GtkMenuItem *,
13878                                  gpointer);
13879 </verb></tscreen>
13880
13881 <!-- ----------------------------------------------------------------- -->
13882 <sect1>GtkListItem
13883 <!-- ----------------------------------------------------------------- -->
13884 <p>
13885 <tscreen><verb>
13886 void GtkListItem::toggle-focus-row      (GtkListItem *,
13887                                          gpointer);
13888 void GtkListItem::select-all    (GtkListItem *,
13889                                  gpointer);
13890 void GtkListItem::unselect-all  (GtkListItem *,
13891                                  gpointer);
13892 void GtkListItem::undo-selection        (GtkListItem *,
13893                                          gpointer);
13894 void GtkListItem::start-selection       (GtkListItem *,
13895                                          gpointer);
13896 void GtkListItem::end-selection (GtkListItem *,
13897                                  gpointer);
13898 void GtkListItem::toggle-add-mode       (GtkListItem *,
13899                                          gpointer);
13900 void GtkListItem::extend-selection      (GtkListItem *,
13901                                          GtkEnum,
13902                                          ggfloat,
13903                                          gboolean,
13904                                          gpointer);
13905 void GtkListItem::scroll-vertical       (GtkListItem *,
13906                                          GtkEnum,
13907                                          ggfloat,
13908                                          gpointer);
13909 void GtkListItem::scroll-horizontal     (GtkListItem *,
13910                                          GtkEnum,
13911                                          ggfloat,
13912                                          gpointer);
13913 </verb></tscreen>
13914
13915 <!-- ----------------------------------------------------------------- -->
13916 <sect1>GtkTreeItem
13917 <!-- ----------------------------------------------------------------- -->
13918 <p>
13919 <tscreen><verb>
13920 void GtkTreeItem::collapse      (GtkTreeItem *,
13921                                  gpointer);
13922 void GtkTreeItem::expand        (GtkTreeItem *,
13923                                  gpointer);
13924 </verb></tscreen>
13925
13926 <!-- ----------------------------------------------------------------- -->
13927 <sect1>GtkCheckMenuItem
13928 <!-- ----------------------------------------------------------------- -->
13929 <p>
13930 <tscreen><verb>
13931 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
13932                                  gpointer);
13933 </verb></tscreen>
13934
13935 <!-- ----------------------------------------------------------------- -->
13936 <sect1>GtkInputDialog
13937 <!-- ----------------------------------------------------------------- -->
13938 <p>
13939 <tscreen><verb>
13940 void GtkInputDialog::enable-device      (GtkInputDialog *,
13941                                          ggint,
13942                                          gpointer);
13943 void GtkInputDialog::disable-device     (GtkInputDialog *,
13944                                          ggint,
13945                                          gpointer);
13946 </verb></tscreen>
13947
13948 <!-- ----------------------------------------------------------------- -->
13949 <sect1>GtkColorSelection
13950 <!-- ----------------------------------------------------------------- -->
13951 <p>
13952 <tscreen><verb>
13953 void GtkColorSelection::color-changed   (GtkColorSelection *,
13954                                          gpointer);
13955 </verb></tscreen>
13956
13957 <!-- ----------------------------------------------------------------- -->
13958 <sect1>GtkStatusBar
13959 <!-- ----------------------------------------------------------------- -->
13960 <p>
13961 <tscreen><verb>
13962 void GtkStatusbar::text-pushed  (GtkStatusbar *,
13963                                  gguint,
13964                                  GtkString *,
13965                                  gpointer);
13966 void GtkStatusbar::text-popped  (GtkStatusbar *,
13967                                  gguint,
13968                                  GtkString *,
13969                                  gpointer);
13970 </verb></tscreen>
13971
13972 <!-- ----------------------------------------------------------------- -->
13973 <sect1>GtkCTree
13974 <!-- ----------------------------------------------------------------- -->
13975 <p>
13976 <tscreen><verb>
13977 void GtkCTree::tree-select-row  (GtkCTree *,
13978                                  GtkCTreeNode *,
13979                                  ggint,
13980                                  gpointer);
13981 void GtkCTree::tree-unselect-row        (GtkCTree *,
13982                                          GtkCTreeNode *,
13983                                          ggint,
13984                                          gpointer);
13985 void GtkCTree::tree-expand      (GtkCTree *,
13986                                  GtkCTreeNode *,
13987                                  gpointer);
13988 void GtkCTree::tree-collapse    (GtkCTree *,
13989                                  ggpointer,
13990                                  gpointer);
13991 void GtkCTree::tree-move        (GtkCTree *,
13992                                  GtkCTreeNode *,
13993                                  GtkCTreeNode *,
13994                                  GtkCTreeNode *,
13995                                  gpointer);
13996 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
13997                                                  GtkCTreeExpansionType,
13998                                                  gpointer);
13999 </verb></tscreen>
14000
14001 <!-- ----------------------------------------------------------------- -->
14002 <sect1>GtkCurve
14003 <!-- ----------------------------------------------------------------- -->
14004 <p>
14005 <tscreen><verb>
14006 void GtkCurve::curve-type-changed       (GtkCurve *,
14007                                          gpointer);
14008 </verb></tscreen>
14009
14010 <!-- ----------------------------------------------------------------- -->
14011 <sect1>GtkAdjustment
14012 <!-- ----------------------------------------------------------------- -->
14013 <p>
14014 <tscreen><verb>
14015 void GtkAdjustment::changed     (GtkAdjustment *,
14016                                  gpointer);
14017 void GtkAdjustment::value-changed       (GtkAdjustment *,
14018                                          gpointer);
14019 </verb></tscreen>
14020
14021 <!-- ***************************************************************** -->
14022 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
14023 <!-- ***************************************************************** -->
14024 <p>
14025 The follwing data types are passed into event handlers by GTK+. For
14026 each data type listed, the signals that use this data type are listed.
14027
14028 <itemize>
14029 <item>  GdkEvent
14030           <itemize>
14031           <item>drag_end_event
14032           </itemize>
14033
14034 <item>  GdkEventType
14035
14036 <item>  GdkEventAny
14037           <itemize>
14038           <item>delete_event
14039           <item>destroy_event
14040           <item>map_event
14041           <item>unmap_event
14042           <item>no_expose_event
14043           </itemize>
14044
14045 <item>  GdkEventExpose
14046           <itemize>
14047           <item>expose_event
14048           </itemize>
14049
14050 <item>  GdkEventNoExpose
14051
14052 <item>  GdkEventVisibility
14053
14054 <item>  GdkEventMotion
14055           <itemize>
14056           <item>motion_notify_event
14057           </itemize>
14058
14059 <item>  GdkEventButton
14060           <itemize>
14061           <item>button_press_event
14062           <item>button_release_event
14063           </itemize>
14064
14065 <item>  GdkEventKey
14066           <itemize>
14067           <item>key_press_event
14068           <item>key_release_event
14069           </itemize>
14070
14071 <item>  GdkEventCrossing
14072           <itemize>
14073           <item>enter_notify_event
14074           <item>leave_notify_event
14075           </itemize>
14076
14077 <item>  GdkEventFocus
14078           <itemize>
14079           <item>focus_in_event
14080           <item>focus_out_event
14081           </itemize>
14082
14083 <item>  GdkEventConfigure
14084           <itemize>
14085           <item>configure_event
14086           </itemize>
14087
14088 <item>  GdkEventProperty
14089           <itemize>
14090           <item>property_notify_event
14091           </itemize>
14092
14093 <item>  GdkEventSelection
14094           <itemize>
14095           <item>selection_clear_event
14096           <item>selection_request_event
14097           <item>selection_notify_event
14098           </itemize>
14099
14100 <item>  GdkEventProximity
14101           <itemize>
14102           <item>proximity_in_event
14103           <item>proximity_out_event
14104           </itemize>
14105
14106 <item>  GdkEventDragBegin
14107           <itemize>
14108           <item>drag_begin_event
14109           </itemize>
14110
14111 <item>  GdkEventDragRequest
14112           <itemize>
14113           <item>drag_request_event
14114           </itemize>
14115
14116 <item>  GdkEventDropEnter
14117           <itemize>
14118           <item>drop_enter_event
14119           </itemize>
14120
14121 <item>  GdkEventDropLeave
14122           <itemize>
14123           <item>drop_leave_event
14124           </itemize>
14125
14126 <item>  GdkEventDropDataAvailable
14127           <itemize>
14128           <item>drop_data_available_event
14129           </itemize>
14130
14131 <item>  GdkEventClient
14132           <itemize>
14133           <item>client_event
14134           </itemize>
14135
14136 <item>  GdkEventOther
14137           <itemize>
14138           <item>other_event
14139           </itemize>
14140 </itemize>
14141
14142 The data type <tt/GdkEventType/ is a special data type that is used by
14143 all the other data types as an indicator of the data type being passed
14144 to the signal handler. As you will see below, each of the event data
14145 structures has a member of this type. It is defined as an enumeration
14146 type as follows:
14147
14148 <tscreen><verb>
14149 typedef enum
14150 {
14151   GDK_NOTHING           = -1,
14152   GDK_DELETE            = 0,
14153   GDK_DESTROY           = 1,
14154   GDK_EXPOSE            = 2,
14155   GDK_MOTION_NOTIFY     = 3,
14156   GDK_BUTTON_PRESS      = 4,
14157   GDK_2BUTTON_PRESS     = 5,
14158   GDK_3BUTTON_PRESS     = 6,
14159   GDK_BUTTON_RELEASE    = 7,
14160   GDK_KEY_PRESS         = 8,
14161   GDK_KEY_RELEASE       = 9,
14162   GDK_ENTER_NOTIFY      = 10,
14163   GDK_LEAVE_NOTIFY      = 11,
14164   GDK_FOCUS_CHANGE      = 12,
14165   GDK_CONFIGURE         = 13,
14166   GDK_MAP               = 14,
14167   GDK_UNMAP             = 15,
14168   GDK_PROPERTY_NOTIFY   = 16,
14169   GDK_SELECTION_CLEAR   = 17,
14170   GDK_SELECTION_REQUEST = 18,
14171   GDK_SELECTION_NOTIFY  = 19,
14172   GDK_PROXIMITY_IN      = 20,
14173   GDK_PROXIMITY_OUT     = 21,
14174   GDK_DRAG_BEGIN        = 22,
14175   GDK_DRAG_REQUEST      = 23,
14176   GDK_DROP_ENTER        = 24,
14177   GDK_DROP_LEAVE        = 25,
14178   GDK_DROP_DATA_AVAIL   = 26,
14179   GDK_CLIENT_EVENT      = 27,
14180   GDK_VISIBILITY_NOTIFY = 28,
14181   GDK_NO_EXPOSE         = 29,
14182   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
14183 } GdkEventType;
14184 </verb></tscreen>
14185
14186 The other event type that is different from the others is
14187 <tt/GdkEvent/ itself. This is a union of all the other
14188 data types, which allows it to be cast to a specific
14189 event data type within a signal handler.
14190
14191 <!-- Just a big list for now, needs expanding upon - TRG -->
14192 So, the event data types are defined as follows:
14193
14194 <tscreen><verb>
14195 struct _GdkEventAny
14196 {
14197   GdkEventType type;
14198   GdkWindow *window;
14199   gint8 send_event;
14200 };
14201
14202 struct _GdkEventExpose
14203 {
14204   GdkEventType type;
14205   GdkWindow *window;
14206   gint8 send_event;
14207   GdkRectangle area;
14208   gint count; /* If non-zero, how many more events follow. */
14209 };
14210
14211 struct _GdkEventNoExpose
14212 {
14213   GdkEventType type;
14214   GdkWindow *window;
14215   gint8 send_event;
14216   /* XXX: does anyone need the X major_code or minor_code fields? */
14217 };
14218
14219 struct _GdkEventVisibility
14220 {
14221   GdkEventType type;
14222   GdkWindow *window;
14223   gint8 send_event;
14224   GdkVisibilityState state;
14225 };
14226
14227 struct _GdkEventMotion
14228 {
14229   GdkEventType type;
14230   GdkWindow *window;
14231   gint8 send_event;
14232   guint32 time;
14233   gdouble x;
14234   gdouble y;
14235   gdouble pressure;
14236   gdouble xtilt;
14237   gdouble ytilt;
14238   guint state;
14239   gint16 is_hint;
14240   GdkInputSource source;
14241   guint32 deviceid;
14242   gdouble x_root, y_root;
14243 };
14244
14245 struct _GdkEventButton
14246 {
14247   GdkEventType type;
14248   GdkWindow *window;
14249   gint8 send_event;
14250   guint32 time;
14251   gdouble x;
14252   gdouble y;
14253   gdouble pressure;
14254   gdouble xtilt;
14255   gdouble ytilt;
14256   guint state;
14257   guint button;
14258   GdkInputSource source;
14259   guint32 deviceid;
14260   gdouble x_root, y_root;
14261 };
14262
14263 struct _GdkEventKey
14264 {
14265   GdkEventType type;
14266   GdkWindow *window;
14267   gint8 send_event;
14268   guint32 time;
14269   guint state;
14270   guint keyval;
14271   gint length;
14272   gchar *string;
14273 };
14274
14275 struct _GdkEventCrossing
14276 {
14277   GdkEventType type;
14278   GdkWindow *window;
14279   gint8 send_event;
14280   GdkWindow *subwindow;
14281   GdkNotifyType detail;
14282 };
14283
14284 struct _GdkEventFocus
14285 {
14286   GdkEventType type;
14287   GdkWindow *window;
14288   gint8 send_event;
14289   gint16 in;
14290 };
14291
14292 struct _GdkEventConfigure
14293 {
14294   GdkEventType type;
14295   GdkWindow *window;
14296   gint8 send_event;
14297   gint16 x, y;
14298   gint16 width;
14299   gint16 height;
14300 };
14301
14302 struct _GdkEventProperty
14303 {
14304   GdkEventType type;
14305   GdkWindow *window;
14306   gint8 send_event;
14307   GdkAtom atom;
14308   guint32 time;
14309   guint state;
14310 };
14311
14312 struct _GdkEventSelection
14313 {
14314   GdkEventType type;
14315   GdkWindow *window;
14316   gint8 send_event;
14317   GdkAtom selection;
14318   GdkAtom target;
14319   GdkAtom property;
14320   guint32 requestor;
14321   guint32 time;
14322 };
14323
14324 /* This event type will be used pretty rarely. It only is important
14325    for XInput aware programs that are drawing their own cursor */
14326
14327 struct _GdkEventProximity
14328 {
14329   GdkEventType type;
14330   GdkWindow *window;
14331   gint8 send_event;
14332   guint32 time;
14333   GdkInputSource source;
14334   guint32 deviceid;
14335 };
14336
14337 struct _GdkEventDragRequest
14338 {
14339   GdkEventType type;
14340   GdkWindow *window;
14341   gint8 send_event;
14342   guint32 requestor;
14343   union {
14344     struct {
14345       guint protocol_version:4;
14346       guint sendreply:1;
14347       guint willaccept:1;
14348       guint delete_data:1; /* Do *not* delete if link is sent, only
14349                               if data is sent */
14350       guint senddata:1;
14351       guint reserved:22;
14352     } flags;
14353     glong allflags;
14354   } u;
14355   guint8 isdrop; /* This gdk event can be generated by a couple of
14356                     X events - this lets the app know whether the
14357                     drop really occurred or we just set the data */
14358
14359   GdkPoint drop_coords;
14360   gchar *data_type;
14361   guint32 timestamp;
14362 };
14363
14364 struct _GdkEventDragBegin
14365 {
14366   GdkEventType type;
14367   GdkWindow *window;
14368   gint8 send_event;
14369   union {
14370     struct {
14371       guint protocol_version:4;
14372       guint reserved:28;
14373     } flags;
14374     glong allflags;
14375   } u;
14376 };
14377
14378 struct _GdkEventDropEnter
14379 {
14380   GdkEventType type;
14381   GdkWindow *window;
14382   gint8 send_event;
14383   guint32 requestor;
14384   union {
14385     struct {
14386       guint protocol_version:4;
14387       guint sendreply:1;
14388       guint extended_typelist:1;
14389       guint reserved:26;
14390     } flags;
14391     glong allflags;
14392   } u;
14393 };
14394
14395 struct _GdkEventDropLeave
14396 {
14397   GdkEventType type;
14398   GdkWindow *window;
14399   gint8 send_event;
14400   guint32 requestor;
14401   union {
14402     struct {
14403       guint protocol_version:4;
14404       guint reserved:28;
14405     } flags;
14406     glong allflags;
14407   } u;
14408 };
14409
14410 struct _GdkEventDropDataAvailable
14411 {
14412   GdkEventType type;
14413   GdkWindow *window;
14414   gint8 send_event;
14415   guint32 requestor;
14416   union {
14417     struct {
14418       guint protocol_version:4;
14419       guint isdrop:1;
14420       guint reserved:25;
14421     } flags;
14422     glong allflags;
14423   } u;
14424   gchar *data_type; /* MIME type */
14425   gulong data_numbytes;
14426   gpointer data;
14427   guint32 timestamp;
14428   GdkPoint coords;
14429 };
14430
14431 struct _GdkEventClient
14432 {
14433   GdkEventType type;
14434   GdkWindow *window;
14435   gint8 send_event;
14436   GdkAtom message_type;
14437   gushort data_format;
14438   union {
14439     char b[20];
14440     short s[10];
14441     long l[5];
14442   } data;
14443 };
14444
14445 struct _GdkEventOther
14446 {
14447   GdkEventType type;
14448   GdkWindow *window;
14449   gint8 send_event;
14450   GdkXEvent *xevent;
14451 };
14452 </verb></tscreen>
14453
14454 <!-- ***************************************************************** -->
14455 <sect> Code Examples
14456 <!-- ***************************************************************** -->
14457 <p>
14458 Below are the code examples that are used in the above text
14459 which are not included in complete form elsewhere.
14460
14461 <!-- ----------------------------------------------------------------- -->
14462 <sect1>Tictactoe
14463 <!-- ----------------------------------------------------------------- -->
14464 <sect2>tictactoe.h
14465 <p>
14466 <tscreen><verb>
14467 /* example-start tictactoe tictactoe.h */
14468
14469 /* GTK - The GIMP Toolkit
14470  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14471  *
14472  * This library is free software; you can redistribute it and/or
14473  * modify it under the terms of the GNU Library General Public
14474  * License as published by the Free Software Foundation; either
14475  * version 2 of the License, or (at your option) any later version.
14476  *
14477  * This library is distributed in the hope that it will be useful,
14478  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14479  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14480  * Library General Public License for more details.
14481  *
14482  * You should have received a copy of the GNU Library General Public
14483  * License along with this library; if not, write to the
14484  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14485  * Boston, MA 02111-1307, USA.
14486  */
14487 #ifndef __TICTACTOE_H__
14488 #define __TICTACTOE_H__
14489
14490
14491 #include <gdk/gdk.h>
14492 #include <gtk/gtkvbox.h>
14493
14494
14495 #ifdef __cplusplus
14496 extern "C" {
14497 #endif /* __cplusplus */
14498
14499 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
14500 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
14501 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
14502
14503
14504 typedef struct _Tictactoe       Tictactoe;
14505 typedef struct _TictactoeClass  TictactoeClass;
14506
14507 struct _Tictactoe
14508 {
14509   GtkVBox vbox;
14510   
14511   GtkWidget *buttons[3][3];
14512 };
14513
14514 struct _TictactoeClass
14515 {
14516   GtkVBoxClass parent_class;
14517
14518   void (* tictactoe) (Tictactoe *ttt);
14519 };
14520
14521 guint          tictactoe_get_type        (void);
14522 GtkWidget*     tictactoe_new             (void);
14523 void           tictactoe_clear           (Tictactoe *ttt);
14524
14525 #ifdef __cplusplus
14526 }
14527 #endif /* __cplusplus */
14528
14529 #endif /* __TICTACTOE_H__ */
14530
14531 /* example-end */
14532 </verb></tscreen>
14533
14534 <!-- ----------------------------------------------------------------- -->
14535 <sect2>tictactoe.c
14536 <p>
14537 <tscreen><verb>
14538 /* example-start tictactoe tictactoe.c */
14539
14540 /* GTK - The GIMP Toolkit
14541  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14542  *
14543  * This library is free software; you can redistribute it and/or
14544  * modify it under the terms of the GNU Library General Public
14545  * License as published by the Free Software Foundation; either
14546  * version 2 of the License, or (at your option) any later version.
14547  *
14548  * This library is distributed in the hope that it will be useful,
14549  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14550  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14551  * Library General Public License for more details.
14552  *
14553  * You should have received a copy of the GNU Library General Public
14554  * License along with this library; if not, write to the
14555  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14556  * Boston, MA 02111-1307, USA.
14557  */
14558 #include "gtk/gtksignal.h"
14559 #include "gtk/gtktable.h"
14560 #include "gtk/gtktogglebutton.h"
14561 #include "tictactoe.h"
14562
14563 enum {
14564   TICTACTOE_SIGNAL,
14565   LAST_SIGNAL
14566 };
14567
14568 static void tictactoe_class_init          (TictactoeClass *klass);
14569 static void tictactoe_init                (Tictactoe      *ttt);
14570 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
14571
14572 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
14573
14574 guint
14575 tictactoe_get_type ()
14576 {
14577   static guint ttt_type = 0;
14578
14579   if (!ttt_type)
14580     {
14581       GtkTypeInfo ttt_info =
14582       {
14583         "Tictactoe",
14584         sizeof (Tictactoe),
14585         sizeof (TictactoeClass),
14586         (GtkClassInitFunc) tictactoe_class_init,
14587         (GtkObjectInitFunc) tictactoe_init,
14588         (GtkArgSetFunc) NULL,
14589         (GtkArgGetFunc) NULL
14590       };
14591
14592       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
14593     }
14594
14595   return ttt_type;
14596 }
14597
14598 static void
14599 tictactoe_class_init (TictactoeClass *class)
14600 {
14601   GtkObjectClass *object_class;
14602
14603   object_class = (GtkObjectClass*) class;
14604   
14605   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
14606                                          GTK_RUN_FIRST,
14607                                          object_class->type,
14608                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
14609                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
14610
14611
14612   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
14613
14614   class->tictactoe = NULL;
14615 }
14616
14617 static void
14618 tictactoe_init (Tictactoe *ttt)
14619 {
14620   GtkWidget *table;
14621   gint i,j;
14622   
14623   table = gtk_table_new (3, 3, TRUE);
14624   gtk_container_add (GTK_CONTAINER(ttt), table);
14625   gtk_widget_show (table);
14626
14627   for (i=0;i<3; i++)
14628     for (j=0;j<3; j++)
14629       {
14630         ttt->buttons[i][j] = gtk_toggle_button_new ();
14631         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
14632                                    i, i+1, j, j+1);
14633         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
14634                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
14635         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
14636         gtk_widget_show (ttt->buttons[i][j]);
14637       }
14638 }
14639
14640 GtkWidget*
14641 tictactoe_new ()
14642 {
14643   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
14644 }
14645
14646 void           
14647 tictactoe_clear (Tictactoe *ttt)
14648 {
14649   int i,j;
14650
14651   for (i=0;i<3;i++)
14652     for (j=0;j<3;j++)
14653       {
14654         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
14655         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
14656                                      FALSE);
14657         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
14658       }
14659 }
14660
14661 static void
14662 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
14663 {
14664   int i,k;
14665
14666   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14667                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14668                              { 0, 1, 2 }, { 0, 1, 2 } };
14669   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14670                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14671                              { 0, 1, 2 }, { 2, 1, 0 } };
14672
14673   int success, found;
14674
14675   for (k=0; k<8; k++)
14676     {
14677       success = TRUE;
14678       found = FALSE;
14679
14680       for (i=0;i<3;i++)
14681         {
14682           success = success &amp;&amp; 
14683             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
14684           found = found ||
14685             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
14686         }
14687       
14688       if (success &amp;&amp; found)
14689         {
14690           gtk_signal_emit (GTK_OBJECT (ttt), 
14691                            tictactoe_signals[TICTACTOE_SIGNAL]);
14692           break;
14693         }
14694     }
14695 }
14696
14697 /* example-end */
14698 </verb></tscreen>
14699
14700 <!-- ----------------------------------------------------------------- -->
14701 <sect2>ttt_test.c
14702 <p>
14703 <tscreen><verb>
14704 /* example-start tictactoe ttt_test.c */
14705
14706 #include <gtk/gtk.h>
14707 #include "tictactoe.h"
14708
14709 void
14710 win (GtkWidget *widget, gpointer data)
14711 {
14712   g_print ("Yay!\n");
14713   tictactoe_clear (TICTACTOE (widget));
14714 }
14715
14716 int 
14717 main (int argc, char *argv[])
14718 {
14719   GtkWidget *window;
14720   GtkWidget *ttt;
14721   
14722   gtk_init (&amp;argc, &amp;argv);
14723
14724   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14725   
14726   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
14727   
14728   gtk_signal_connect (GTK_OBJECT (window), "destroy",
14729                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
14730   
14731   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
14732
14733   ttt = tictactoe_new ();
14734   
14735   gtk_container_add (GTK_CONTAINER (window), ttt);
14736   gtk_widget_show (ttt);
14737
14738   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
14739                       GTK_SIGNAL_FUNC (win), NULL);
14740
14741   gtk_widget_show (window);
14742   
14743   gtk_main ();
14744   
14745   return 0;
14746 }
14747
14748 /* example-end */
14749 </verb></tscreen>
14750
14751 <!-- ----------------------------------------------------------------- -->
14752 <sect1> GtkDial
14753
14754 <!-- ----------------------------------------------------------------- -->
14755 <sect2> gtkdial.h
14756 <p>
14757 <tscreen><verb>
14758 /* example-start gtkdial gtkdial.h */
14759
14760 /* GTK - The GIMP Toolkit
14761  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14762  *
14763  * This library is free software; you can redistribute it and/or
14764  * modify it under the terms of the GNU Library General Public
14765  * License as published by the Free Software Foundation; either
14766  * version 2 of the License, or (at your option) any later version.
14767  *
14768  * This library is distributed in the hope that it will be useful,
14769  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14770  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14771  * Library General Public License for more details.
14772  *
14773  * You should have received a copy of the GNU Library General Public
14774  * License along with this library; if not, write to the
14775  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14776  * Boston, MA 02111-1307, USA.
14777  */
14778 #ifndef __GTK_DIAL_H__
14779 #define __GTK_DIAL_H__
14780
14781
14782 #include <gdk/gdk.h>
14783 #include <gtk/gtkadjustment.h>
14784 #include <gtk/gtkwidget.h>
14785
14786
14787 #ifdef __cplusplus
14788 extern "C" {
14789 #endif /* __cplusplus */
14790
14791
14792 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
14793 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
14794 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
14795
14796
14797 typedef struct _GtkDial        GtkDial;
14798 typedef struct _GtkDialClass   GtkDialClass;
14799
14800 struct _GtkDial
14801 {
14802   GtkWidget widget;
14803
14804   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
14805   guint policy : 2;
14806
14807   /* Button currently pressed or 0 if none */
14808   guint8 button;
14809
14810   /* Dimensions of dial components */
14811   gint radius;
14812   gint pointer_width;
14813
14814   /* ID of update timer, or 0 if none */
14815   guint32 timer;
14816
14817   /* Current angle */
14818   gfloat angle;
14819
14820   /* Old values from adjustment stored so we know when something changes */
14821   gfloat old_value;
14822   gfloat old_lower;
14823   gfloat old_upper;
14824
14825   /* The adjustment object that stores the data for this dial */
14826   GtkAdjustment *adjustment;
14827 };
14828
14829 struct _GtkDialClass
14830 {
14831   GtkWidgetClass parent_class;
14832 };
14833
14834
14835 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
14836 guint          gtk_dial_get_type               (void);
14837 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
14838 void           gtk_dial_set_update_policy      (GtkDial      *dial,
14839                                                 GtkUpdateType  policy);
14840
14841 void           gtk_dial_set_adjustment         (GtkDial      *dial,
14842                                                 GtkAdjustment *adjustment);
14843 #ifdef __cplusplus
14844 }
14845 #endif /* __cplusplus */
14846
14847
14848 #endif /* __GTK_DIAL_H__ */
14849 /* example-end */
14850 </verb></tscreen>
14851
14852 <!-- ----------------------------------------------------------------- -->
14853 <sect2> gtkdial.c
14854 <p>
14855 <tscreen><verb>
14856 /* example-start gtkdial gtkdial.c */
14857
14858 /* GTK - The GIMP Toolkit
14859  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14860  *
14861  * This library is free software; you can redistribute it and/or
14862  * modify it under the terms of the GNU Library General Public
14863  * License as published by the Free Software Foundation; either
14864  * version 2 of the License, or (at your option) any later version.
14865  *
14866  * This library is distributed in the hope that it will be useful,
14867  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14868  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14869  * Library General Public License for more details.
14870  *
14871  * You should have received a copy of the GNU Library General Public
14872  * License along with this library; if not, write to the
14873  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14874  * Boston, MA 02111-1307, USA.
14875  */
14876 #include <math.h>
14877 #include <stdio.h>
14878 #include <gtk/gtkmain.h>
14879 #include <gtk/gtksignal.h>
14880
14881 #include "gtkdial.h"
14882
14883 #define SCROLL_DELAY_LENGTH  300
14884 #define DIAL_DEFAULT_SIZE 100
14885
14886 /* Forward declarations */
14887
14888 static void gtk_dial_class_init               (GtkDialClass    *klass);
14889 static void gtk_dial_init                     (GtkDial         *dial);
14890 static void gtk_dial_destroy                  (GtkObject        *object);
14891 static void gtk_dial_realize                  (GtkWidget        *widget);
14892 static void gtk_dial_size_request             (GtkWidget      *widget,
14893                                                GtkRequisition *requisition);
14894 static void gtk_dial_size_allocate            (GtkWidget     *widget,
14895                                                GtkAllocation *allocation);
14896 static gint gtk_dial_expose                   (GtkWidget        *widget,
14897                                                 GdkEventExpose   *event);
14898 static gint gtk_dial_button_press             (GtkWidget        *widget,
14899                                                 GdkEventButton   *event);
14900 static gint gtk_dial_button_release           (GtkWidget        *widget,
14901                                                 GdkEventButton   *event);
14902 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
14903                                                 GdkEventMotion   *event);
14904 static gint gtk_dial_timer                    (GtkDial         *dial);
14905
14906 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
14907 static void gtk_dial_update                   (GtkDial *dial);
14908 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
14909                                                 gpointer          data);
14910 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
14911                                                 gpointer          data);
14912
14913 /* Local data */
14914
14915 static GtkWidgetClass *parent_class = NULL;
14916
14917 guint
14918 gtk_dial_get_type ()
14919 {
14920   static guint dial_type = 0;
14921
14922   if (!dial_type)
14923     {
14924       GtkTypeInfo dial_info =
14925       {
14926         "GtkDial",
14927         sizeof (GtkDial),
14928         sizeof (GtkDialClass),
14929         (GtkClassInitFunc) gtk_dial_class_init,
14930         (GtkObjectInitFunc) gtk_dial_init,
14931         (GtkArgSetFunc) NULL,
14932         (GtkArgGetFunc) NULL,
14933       };
14934
14935       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
14936     }
14937
14938   return dial_type;
14939 }
14940
14941 static void
14942 gtk_dial_class_init (GtkDialClass *class)
14943 {
14944   GtkObjectClass *object_class;
14945   GtkWidgetClass *widget_class;
14946
14947   object_class = (GtkObjectClass*) class;
14948   widget_class = (GtkWidgetClass*) class;
14949
14950   parent_class = gtk_type_class (gtk_widget_get_type ());
14951
14952   object_class->destroy = gtk_dial_destroy;
14953
14954   widget_class->realize = gtk_dial_realize;
14955   widget_class->expose_event = gtk_dial_expose;
14956   widget_class->size_request = gtk_dial_size_request;
14957   widget_class->size_allocate = gtk_dial_size_allocate;
14958   widget_class->button_press_event = gtk_dial_button_press;
14959   widget_class->button_release_event = gtk_dial_button_release;
14960   widget_class->motion_notify_event = gtk_dial_motion_notify;
14961 }
14962
14963 static void
14964 gtk_dial_init (GtkDial *dial)
14965 {
14966   dial->button = 0;
14967   dial->policy = GTK_UPDATE_CONTINUOUS;
14968   dial->timer = 0;
14969   dial->radius = 0;
14970   dial->pointer_width = 0;
14971   dial->angle = 0.0;
14972   dial->old_value = 0.0;
14973   dial->old_lower = 0.0;
14974   dial->old_upper = 0.0;
14975   dial->adjustment = NULL;
14976 }
14977
14978 GtkWidget*
14979 gtk_dial_new (GtkAdjustment *adjustment)
14980 {
14981   GtkDial *dial;
14982
14983   dial = gtk_type_new (gtk_dial_get_type ());
14984
14985   if (!adjustment)
14986     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
14987
14988   gtk_dial_set_adjustment (dial, adjustment);
14989
14990   return GTK_WIDGET (dial);
14991 }
14992
14993 static void
14994 gtk_dial_destroy (GtkObject *object)
14995 {
14996   GtkDial *dial;
14997
14998   g_return_if_fail (object != NULL);
14999   g_return_if_fail (GTK_IS_DIAL (object));
15000
15001   dial = GTK_DIAL (object);
15002
15003   if (dial->adjustment)
15004     gtk_object_unref (GTK_OBJECT (dial->adjustment));
15005
15006   if (GTK_OBJECT_CLASS (parent_class)->destroy)
15007     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
15008 }
15009
15010 GtkAdjustment*
15011 gtk_dial_get_adjustment (GtkDial *dial)
15012 {
15013   g_return_val_if_fail (dial != NULL, NULL);
15014   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
15015
15016   return dial->adjustment;
15017 }
15018
15019 void
15020 gtk_dial_set_update_policy (GtkDial      *dial,
15021                              GtkUpdateType  policy)
15022 {
15023   g_return_if_fail (dial != NULL);
15024   g_return_if_fail (GTK_IS_DIAL (dial));
15025
15026   dial->policy = policy;
15027 }
15028
15029 void
15030 gtk_dial_set_adjustment (GtkDial      *dial,
15031                           GtkAdjustment *adjustment)
15032 {
15033   g_return_if_fail (dial != NULL);
15034   g_return_if_fail (GTK_IS_DIAL (dial));
15035
15036   if (dial->adjustment)
15037     {
15038       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
15039       gtk_object_unref (GTK_OBJECT (dial->adjustment));
15040     }
15041
15042   dial->adjustment = adjustment;
15043   gtk_object_ref (GTK_OBJECT (dial->adjustment));
15044
15045   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
15046                       (GtkSignalFunc) gtk_dial_adjustment_changed,
15047                       (gpointer) dial);
15048   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
15049                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
15050                       (gpointer) dial);
15051
15052   dial->old_value = adjustment->value;
15053   dial->old_lower = adjustment->lower;
15054   dial->old_upper = adjustment->upper;
15055
15056   gtk_dial_update (dial);
15057 }
15058
15059 static void
15060 gtk_dial_realize (GtkWidget *widget)
15061 {
15062   GtkDial *dial;
15063   GdkWindowAttr attributes;
15064   gint attributes_mask;
15065
15066   g_return_if_fail (widget != NULL);
15067   g_return_if_fail (GTK_IS_DIAL (widget));
15068
15069   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
15070   dial = GTK_DIAL (widget);
15071
15072   attributes.x = widget->allocation.x;
15073   attributes.y = widget->allocation.y;
15074   attributes.width = widget->allocation.width;
15075   attributes.height = widget->allocation.height;
15076   attributes.wclass = GDK_INPUT_OUTPUT;
15077   attributes.window_type = GDK_WINDOW_CHILD;
15078   attributes.event_mask = gtk_widget_get_events (widget) | 
15079     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
15080     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
15081     GDK_POINTER_MOTION_HINT_MASK;
15082   attributes.visual = gtk_widget_get_visual (widget);
15083   attributes.colormap = gtk_widget_get_colormap (widget);
15084
15085   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
15086   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
15087
15088   widget->style = gtk_style_attach (widget->style, widget->window);
15089
15090   gdk_window_set_user_data (widget->window, widget);
15091
15092   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
15093 }
15094
15095 static void 
15096 gtk_dial_size_request (GtkWidget      *widget,
15097                        GtkRequisition *requisition)
15098 {
15099   requisition->width = DIAL_DEFAULT_SIZE;
15100   requisition->height = DIAL_DEFAULT_SIZE;
15101 }
15102
15103 static void
15104 gtk_dial_size_allocate (GtkWidget     *widget,
15105                         GtkAllocation *allocation)
15106 {
15107   GtkDial *dial;
15108
15109   g_return_if_fail (widget != NULL);
15110   g_return_if_fail (GTK_IS_DIAL (widget));
15111   g_return_if_fail (allocation != NULL);
15112
15113   widget->allocation = *allocation;
15114   dial = GTK_DIAL (widget);
15115
15116   if (GTK_WIDGET_REALIZED (widget))
15117     {
15118
15119       gdk_window_move_resize (widget->window,
15120                               allocation->x, allocation->y,
15121                               allocation->width, allocation->height);
15122
15123     }
15124   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
15125   dial->pointer_width = dial->radius / 5;
15126 }
15127
15128 static gint
15129 gtk_dial_expose (GtkWidget      *widget,
15130                  GdkEventExpose *event)
15131 {
15132   GtkDial *dial;
15133   GdkPoint points[3];
15134   gdouble s,c;
15135   gdouble theta;
15136   gint xc, yc;
15137   gint tick_length;
15138   gint i;
15139
15140   g_return_val_if_fail (widget != NULL, FALSE);
15141   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15142   g_return_val_if_fail (event != NULL, FALSE);
15143
15144   if (event->count > 0)
15145     return FALSE;
15146   
15147   dial = GTK_DIAL (widget);
15148
15149   gdk_window_clear_area (widget->window,
15150                          0, 0,
15151                          widget->allocation.width,
15152                          widget->allocation.height);
15153
15154   xc = widget->allocation.width/2;
15155   yc = widget->allocation.height/2;
15156
15157   /* Draw ticks */
15158
15159   for (i=0; i<25; i++)
15160     {
15161       theta = (i*M_PI/18. - M_PI/6.);
15162       s = sin(theta);
15163       c = cos(theta);
15164
15165       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
15166       
15167       gdk_draw_line (widget->window,
15168                      widget->style->fg_gc[widget->state],
15169                      xc + c*(dial->radius - tick_length),
15170                      yc - s*(dial->radius - tick_length),
15171                      xc + c*dial->radius,
15172                      yc - s*dial->radius);
15173     }
15174
15175   /* Draw pointer */
15176
15177   s = sin(dial->angle);
15178   c = cos(dial->angle);
15179
15180
15181   points[0].x = xc + s*dial->pointer_width/2;
15182   points[0].y = yc + c*dial->pointer_width/2;
15183   points[1].x = xc + c*dial->radius;
15184   points[1].y = yc - s*dial->radius;
15185   points[2].x = xc - s*dial->pointer_width/2;
15186   points[2].y = yc - c*dial->pointer_width/2;
15187
15188   gtk_draw_polygon (widget->style,
15189                     widget->window,
15190                     GTK_STATE_NORMAL,
15191                     GTK_SHADOW_OUT,
15192                     points, 3,
15193                     TRUE);
15194   
15195   return FALSE;
15196 }
15197
15198 static gint
15199 gtk_dial_button_press (GtkWidget      *widget,
15200                        GdkEventButton *event)
15201 {
15202   GtkDial *dial;
15203   gint dx, dy;
15204   double s, c;
15205   double d_parallel;
15206   double d_perpendicular;
15207
15208   g_return_val_if_fail (widget != NULL, FALSE);
15209   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15210   g_return_val_if_fail (event != NULL, FALSE);
15211
15212   dial = GTK_DIAL (widget);
15213
15214   /* Determine if button press was within pointer region - we 
15215      do this by computing the parallel and perpendicular distance of
15216      the point where the mouse was pressed from the line passing through
15217      the pointer */
15218   
15219   dx = event->x - widget->allocation.width / 2;
15220   dy = widget->allocation.height / 2 - event->y;
15221   
15222   s = sin(dial->angle);
15223   c = cos(dial->angle);
15224   
15225   d_parallel = s*dy + c*dx;
15226   d_perpendicular = fabs(s*dx - c*dy);
15227   
15228   if (!dial->button &amp;&amp;
15229       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
15230       (d_parallel > - dial->pointer_width))
15231     {
15232       gtk_grab_add (widget);
15233
15234       dial->button = event->button;
15235
15236       gtk_dial_update_mouse (dial, event->x, event->y);
15237     }
15238
15239   return FALSE;
15240 }
15241
15242 static gint
15243 gtk_dial_button_release (GtkWidget      *widget,
15244                           GdkEventButton *event)
15245 {
15246   GtkDial *dial;
15247
15248   g_return_val_if_fail (widget != NULL, FALSE);
15249   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15250   g_return_val_if_fail (event != NULL, FALSE);
15251
15252   dial = GTK_DIAL (widget);
15253
15254   if (dial->button == event->button)
15255     {
15256       gtk_grab_remove (widget);
15257
15258       dial->button = 0;
15259
15260       if (dial->policy == GTK_UPDATE_DELAYED)
15261         gtk_timeout_remove (dial->timer);
15262       
15263       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
15264           (dial->old_value != dial->adjustment->value))
15265         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15266     }
15267
15268   return FALSE;
15269 }
15270
15271 static gint
15272 gtk_dial_motion_notify (GtkWidget      *widget,
15273                          GdkEventMotion *event)
15274 {
15275   GtkDial *dial;
15276   GdkModifierType mods;
15277   gint x, y, mask;
15278
15279   g_return_val_if_fail (widget != NULL, FALSE);
15280   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15281   g_return_val_if_fail (event != NULL, FALSE);
15282
15283   dial = GTK_DIAL (widget);
15284
15285   if (dial->button != 0)
15286     {
15287       x = event->x;
15288       y = event->y;
15289
15290       if (event->is_hint || (event->window != widget->window))
15291         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
15292
15293       switch (dial->button)
15294         {
15295         case 1:
15296           mask = GDK_BUTTON1_MASK;
15297           break;
15298         case 2:
15299           mask = GDK_BUTTON2_MASK;
15300           break;
15301         case 3:
15302           mask = GDK_BUTTON3_MASK;
15303           break;
15304         default:
15305           mask = 0;
15306           break;
15307         }
15308
15309       if (mods &amp; mask)
15310         gtk_dial_update_mouse (dial, x,y);
15311     }
15312
15313   return FALSE;
15314 }
15315
15316 static gint
15317 gtk_dial_timer (GtkDial *dial)
15318 {
15319   g_return_val_if_fail (dial != NULL, FALSE);
15320   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
15321
15322   if (dial->policy == GTK_UPDATE_DELAYED)
15323     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15324
15325   return FALSE;
15326 }
15327
15328 static void
15329 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
15330 {
15331   gint xc, yc;
15332   gfloat old_value;
15333
15334   g_return_if_fail (dial != NULL);
15335   g_return_if_fail (GTK_IS_DIAL (dial));
15336
15337   xc = GTK_WIDGET(dial)->allocation.width / 2;
15338   yc = GTK_WIDGET(dial)->allocation.height / 2;
15339
15340   old_value = dial->adjustment->value;
15341   dial->angle = atan2(yc-y, x-xc);
15342
15343   if (dial->angle < -M_PI/2.)
15344     dial->angle += 2*M_PI;
15345
15346   if (dial->angle < -M_PI/6)
15347     dial->angle = -M_PI/6;
15348
15349   if (dial->angle > 7.*M_PI/6.)
15350     dial->angle = 7.*M_PI/6.;
15351
15352   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
15353     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
15354
15355   if (dial->adjustment->value != old_value)
15356     {
15357       if (dial->policy == GTK_UPDATE_CONTINUOUS)
15358         {
15359           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15360         }
15361       else
15362         {
15363           gtk_widget_draw (GTK_WIDGET(dial), NULL);
15364
15365           if (dial->policy == GTK_UPDATE_DELAYED)
15366             {
15367               if (dial->timer)
15368                 gtk_timeout_remove (dial->timer);
15369
15370               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
15371                                              (GtkFunction) gtk_dial_timer,
15372                                              (gpointer) dial);
15373             }
15374         }
15375     }
15376 }
15377
15378 static void
15379 gtk_dial_update (GtkDial *dial)
15380 {
15381   gfloat new_value;
15382   
15383   g_return_if_fail (dial != NULL);
15384   g_return_if_fail (GTK_IS_DIAL (dial));
15385
15386   new_value = dial->adjustment->value;
15387   
15388   if (new_value < dial->adjustment->lower)
15389     new_value = dial->adjustment->lower;
15390
15391   if (new_value > dial->adjustment->upper)
15392     new_value = dial->adjustment->upper;
15393
15394   if (new_value != dial->adjustment->value)
15395     {
15396       dial->adjustment->value = new_value;
15397       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15398     }
15399
15400   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
15401     (dial->adjustment->upper - dial->adjustment->lower);
15402
15403   gtk_widget_draw (GTK_WIDGET(dial), NULL);
15404 }
15405
15406 static void
15407 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
15408                               gpointer       data)
15409 {
15410   GtkDial *dial;
15411
15412   g_return_if_fail (adjustment != NULL);
15413   g_return_if_fail (data != NULL);
15414
15415   dial = GTK_DIAL (data);
15416
15417   if ((dial->old_value != adjustment->value) ||
15418       (dial->old_lower != adjustment->lower) ||
15419       (dial->old_upper != adjustment->upper))
15420     {
15421       gtk_dial_update (dial);
15422
15423       dial->old_value = adjustment->value;
15424       dial->old_lower = adjustment->lower;
15425       dial->old_upper = adjustment->upper;
15426     }
15427 }
15428
15429 static void
15430 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
15431                                     gpointer       data)
15432 {
15433   GtkDial *dial;
15434
15435   g_return_if_fail (adjustment != NULL);
15436   g_return_if_fail (data != NULL);
15437
15438   dial = GTK_DIAL (data);
15439
15440   if (dial->old_value != adjustment->value)
15441     {
15442       gtk_dial_update (dial);
15443
15444       dial->old_value = adjustment->value;
15445     }
15446 }
15447 /* example-end */
15448 </verb></tscreen>
15449
15450 <!-- ----------------------------------------------------------------- -->
15451 <sect1> Scribble
15452 <p>
15453 <tscreen><verb>
15454 /* example-start scribble-simple scribble-simple.c */
15455
15456 /* GTK - The GIMP Toolkit
15457  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15458  *
15459  * This library is free software; you can redistribute it and/or
15460  * modify it under the terms of the GNU Library General Public
15461  * License as published by the Free Software Foundation; either
15462  * version 2 of the License, or (at your option) any later version.
15463  *
15464  * This library is distributed in the hope that it will be useful,
15465  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15466  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15467  * Library General Public License for more details.
15468  *
15469  * You should have received a copy of the GNU Library General Public
15470  * License along with this library; if not, write to the
15471  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15472  * Boston, MA 02111-1307, USA.
15473  */
15474
15475 #include <gtk/gtk.h>
15476
15477 /* Backing pixmap for drawing area */
15478 static GdkPixmap *pixmap = NULL;
15479
15480 /* Create a new backing pixmap of the appropriate size */
15481 static gint
15482 configure_event (GtkWidget *widget, GdkEventConfigure *event)
15483 {
15484   if (pixmap)
15485     gdk_pixmap_unref(pixmap);
15486
15487   pixmap = gdk_pixmap_new(widget->window,
15488                           widget->allocation.width,
15489                           widget->allocation.height,
15490                           -1);
15491   gdk_draw_rectangle (pixmap,
15492                       widget->style->white_gc,
15493                       TRUE,
15494                       0, 0,
15495                       widget->allocation.width,
15496                       widget->allocation.height);
15497
15498   return TRUE;
15499 }
15500
15501 /* Redraw the screen from the backing pixmap */
15502 static gint
15503 expose_event (GtkWidget *widget, GdkEventExpose *event)
15504 {
15505   gdk_draw_pixmap(widget->window,
15506                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
15507                   pixmap,
15508                   event->area.x, event->area.y,
15509                   event->area.x, event->area.y,
15510                   event->area.width, event->area.height);
15511
15512   return FALSE;
15513 }
15514
15515 /* Draw a rectangle on the screen */
15516 static void
15517 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
15518 {
15519   GdkRectangle update_rect;
15520
15521   update_rect.x = x - 5;
15522   update_rect.y = y - 5;
15523   update_rect.width = 10;
15524   update_rect.height = 10;
15525   gdk_draw_rectangle (pixmap,
15526                       widget->style->black_gc,
15527                       TRUE,
15528                       update_rect.x, update_rect.y,
15529                       update_rect.width, update_rect.height);
15530   gtk_widget_draw (widget, &amp;update_rect);
15531 }
15532
15533 static gint
15534 button_press_event (GtkWidget *widget, GdkEventButton *event)
15535 {
15536   if (event->button == 1 &amp;&amp; pixmap != NULL)
15537     draw_brush (widget, event->x, event->y);
15538
15539   return TRUE;
15540 }
15541
15542 static gint
15543 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
15544 {
15545   int x, y;
15546   GdkModifierType state;
15547
15548   if (event->is_hint)
15549     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
15550   else
15551     {
15552       x = event->x;
15553       y = event->y;
15554       state = event->state;
15555     }
15556     
15557   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15558     draw_brush (widget, x, y);
15559   
15560   return TRUE;
15561 }
15562
15563 void
15564 quit ()
15565 {
15566   gtk_exit (0);
15567 }
15568
15569 int
15570 main (int argc, char *argv[])
15571 {
15572   GtkWidget *window;
15573   GtkWidget *drawing_area;
15574   GtkWidget *vbox;
15575
15576   GtkWidget *button;
15577
15578   gtk_init (&amp;argc, &amp;argv);
15579
15580   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15581   gtk_widget_set_name (window, "Test Input");
15582
15583   vbox = gtk_vbox_new (FALSE, 0);
15584   gtk_container_add (GTK_CONTAINER (window), vbox);
15585   gtk_widget_show (vbox);
15586
15587   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15588                       GTK_SIGNAL_FUNC (quit), NULL);
15589
15590   /* Create the drawing area */
15591
15592   drawing_area = gtk_drawing_area_new ();
15593   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
15594   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
15595
15596   gtk_widget_show (drawing_area);
15597
15598   /* Signals used to handle backing pixmap */
15599
15600   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
15601                       (GtkSignalFunc) expose_event, NULL);
15602   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
15603                       (GtkSignalFunc) configure_event, NULL);
15604
15605   /* Event signals */
15606
15607   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
15608                       (GtkSignalFunc) motion_notify_event, NULL);
15609   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
15610                       (GtkSignalFunc) button_press_event, NULL);
15611
15612   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
15613                          | GDK_LEAVE_NOTIFY_MASK
15614                          | GDK_BUTTON_PRESS_MASK
15615                          | GDK_POINTER_MOTION_MASK
15616                          | GDK_POINTER_MOTION_HINT_MASK);
15617
15618   /* .. And a quit button */
15619   button = gtk_button_new_with_label ("Quit");
15620   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
15621
15622   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
15623                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
15624                              GTK_OBJECT (window));
15625   gtk_widget_show (button);
15626
15627   gtk_widget_show (window);
15628
15629   gtk_main ();
15630
15631   return 0;
15632 }
15633 /* example-end */
15634 </verb></tscreen>
15635
15636 </article>