]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
Changed a remaining "menufactory" to "itemfactory"
[~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>February 1st, 1999
15
16 <!-- ***************************************************************** -->
17 <sect>Introduction
18 <!-- ***************************************************************** -->
19 <p>
20 GTK (GIMP Toolkit) was originally developed as a toolkit for the GIMP
21 (General Image Manipulation Program). GTK is built on top of GDK
22 (GIMP Drawing Kit) which is basically a wrapper around the Xlib
23 functions. It's called the GIMP toolkit because it was originally
24 written for developing the GIMP, but has now been used in several free
25 software projects.  The authors are:
26 <itemize>
27 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
28                            name="petm@xcf.berkeley.edu"></tt>
29 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
30                            name="spencer@xcf.berkeley.edu"></tt>
31 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
32                            name="jmacd@xcf.berkeley.edu"></tt>
33 </itemize>
34
35 GTK is essentially an object oriented application programmers
36 interface (API). Although written completely in C, it is implemented
37 using the idea of classes and callback functions (pointers to
38 functions).
39
40 There is also a third component called glib which contains a few
41 replacements for some standard calls, as well as some additional
42 functions for handling linked lists etc. The replacement functions are
43 used to increase GTK's portability, as some of the functions
44 implemented here are not available or are nonstandard on other unixes
45 such as g_strerror(). Some also contain enhancements to the libc
46 versions, such as g_malloc that has enhanced debugging utilities.
47
48 This tutorial is an attempt to document as much as possible of GTK, it
49 is by no means complete. This tutorial assumes a good understanding of
50 C, and how to create C programs. It would be a great benefit for the
51 reader to have previous X programming experience, but it shouldn't be
52 necessary. If you are learning GTK as your first widget set, please
53 comment on how you found this tutorial, and what you had trouble
54 with. Note that there is also a C++ API for GTK (GTK--) in the works,
55 so if you prefer to use C++, you should look into this
56 instead. There are also Objective C, ADA, Guile and other language
57 bindings available, but I don't follow these.
58
59 This document is a 'work in progress'. Please look for updates on 
60 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
61 name="http://www.gtk.org/">.
62
63 I would very much like to hear of any problems you have learning GTK
64 from this document, and would appreciate input as to how it may be
65 improved. Please see the section on <ref id="sec_Contributing"
66 name="Contributing"> for further information.
67
68 <!-- ***************************************************************** -->
69 <sect>Getting Started
70 <!-- ***************************************************************** -->
71
72 <p>
73 The first thing to do of course, is download the GTK source and
74 install it. You can always get the latest version from ftp.gtk.org in
75 /pub/gtk. You can also view other sources of GTK information on
76 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
77 name="http://www.gtk.org/">. GTK uses GNU autoconf for configuration.
78 Once untar'd, type ./configure --help to see a list of options.
79
80 Th GTK source distribution also contains the complete source to all of
81 the examples used in this tutorial, along with Makefiles to aid
82 compilation.
83
84 To begin our introduction to GTK, we'll start with the simplest
85 program possible. This program will create a 200x200 pixel window and
86 has no way of exiting except to be killed using the shell.
87
88 <tscreen><verb>
89 /* example-start base base.c */
90
91 #include <gtk/gtk.h>
92
93 int main( int   argc,
94           char *argv[] )
95 {
96     GtkWidget *window;
97     
98     gtk_init (&amp;argc, &amp;argv);
99     
100     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
101     gtk_widget_show  (window);
102     
103     gtk_main ();
104     
105     return(0);
106 }
107 /* example-end */
108 </verb></tscreen>
109
110 You can compile the above program with gcc using:
111 <tscreen><verb>
112 gcc base.c -o base `gtk-config --cflags --libs`
113 </verb></tscreen>
114
115 The meaning of the unusual compilation options is explained below.
116
117 All programs will of course include gtk/gtk.h which declares the
118 variables, functions, structures etc. that will be used in your GTK
119 application.
120
121 The next line:
122
123 <tscreen><verb>
124 gtk_init (&amp;argc, &amp;argv);
125 </verb></tscreen>
126
127 calls the function gtk_init(gint *argc, gchar ***argv) which will be
128 called in all GTK applications. This sets up a few things for us such
129 as the default visual and color map and then proceeds to call
130 gdk_init(gint *argc, gchar ***argv). This function initializes the
131 library for use, sets up default signal handlers, and checks the
132 arguments passed to your application on the command line, looking for
133 one of the following:
134
135 <itemize>
136 <item> <tt/--gtk-module/
137 <item> <tt/--g-fatal-warnings/
138 <item> <tt/--gtk-debug/
139 <item> <tt/--gtk-no-debug/
140 <item> <tt/--gdk-debug/
141 <item> <tt/--gdk-no-debug/
142 <item> <tt/--display/
143 <item> <tt/--sync/
144 <item> <tt/--no-xshm/
145 <item> <tt/--name/
146 <item> <tt/--class/
147 </itemize>
148
149 It removes these from the argument list, leaving anything it does not
150 recognize for your application to parse or ignore. This creates a set
151 of standard arguments accepted by all GTK applications.
152
153 The next two lines of code create and display a window.
154
155 <tscreen><verb>
156   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
157   gtk_widget_show (window);
158 </verb></tscreen>
159
160 The GTK_WINDOW_TOPLEVEL argument specifies that we want the window to
161 undergo window manager decoration and placement. Rather than create a
162 window of 0x0 size, a window without children is set to 200x200 by
163 default so you can still manipulate it.
164
165 The gtk_widget_show() function lets GTK know that we are done setting
166 the attributes of this widget, and that it can display it.
167
168 The last line enters the GTK main processing loop.
169
170 <tscreen><verb>
171   gtk_main ();
172 </verb></tscreen>
173
174 gtk_main() is another call you will see in every GTK application.
175 When control reaches this point, GTK will sleep waiting for X events
176 (such as button or key presses), timeouts, or file IO notifications to
177 occur. In our simple example however, events are ignored.
178
179 <!-- ----------------------------------------------------------------- -->
180 <sect1>Hello World in GTK
181 <p>
182 Now for a program with a widget (a button).  It's the classic
183 hello world a la GTK.
184
185 <tscreen><verb>
186 /* example-start helloworld helloworld.c */
187
188 #include <gtk/gtk.h>
189
190 /* This is a callback function. The data arguments are ignored
191  * in this example. More on callbacks below. */
192 void hello( GtkWidget *widget,
193             gpointer   data )
194 {
195     g_print ("Hello World\n");
196 }
197
198 gint delete_event( GtkWidget *widget,
199                    GdkEvent  *event,
200                    gpointer   data )
201 {
202     /* If you return FALSE in the "delete_event" signal handler,
203      * GTK will emit the "destroy" signal. Returning TRUE means
204      * you don't want the window to be destroyed.
205      * This is useful for popping up 'are you sure you want to quit?'
206      * type dialogs. */
207
208     g_print ("delete event occurred\n");
209
210     /* Change TRUE to FALSE and the main window will be destroyed with
211      * a "delete_event". */
212
213     return(TRUE);
214 }
215
216 /* Another callback */
217 void destroy( GtkWidget *widget,
218               gpointer   data )
219 {
220     gtk_main_quit();
221 }
222
223 int main( int   argc,
224           char *argv[] )
225 {
226     /* GtkWidget is the storage type for widgets */
227     GtkWidget *window;
228     GtkWidget *button;
229     
230     /* This is called in all GTK applications. Arguments are parsed
231      * from the command line and are returned to the application. */
232     gtk_init(&amp;argc, &amp;argv);
233     
234     /* create a new window */
235     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
236     
237     /* When the window is given the "delete_event" signal (this is given
238      * by the window manager, usually by the 'close' option, or on the
239      * titlebar), we ask it to call the delete_event () function
240      * as defined above. The data passed to the callback
241      * function is NULL and is ignored in the callback function. */
242     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
243                         GTK_SIGNAL_FUNC (delete_event), NULL);
244     
245     /* Here we connect the "destroy" event to a signal handler.  
246      * This event occurs when we call gtk_widget_destroy() on the window,
247      * or if we return 'FALSE' in the "delete_event" callback. */
248     gtk_signal_connect (GTK_OBJECT (window), "destroy",
249                         GTK_SIGNAL_FUNC (destroy), NULL);
250     
251     /* Sets the border width of the window. */
252     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
253     
254     /* Creates a new button with the label "Hello World". */
255     button = gtk_button_new_with_label ("Hello World");
256     
257     /* When the button receives the "clicked" signal, it will call the
258      * function hello() passing it NULL as its argument.  The hello()
259      * function is defined above. */
260     gtk_signal_connect (GTK_OBJECT (button), "clicked",
261                         GTK_SIGNAL_FUNC (hello), NULL);
262     
263     /* This will cause the window to be destroyed by calling
264      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
265      * signal could come from here, or the window manager. */
266     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
267                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
268                                GTK_OBJECT (window));
269     
270     /* This packs the button into the window (a gtk container). */
271     gtk_container_add (GTK_CONTAINER (window), button);
272     
273     /* The final step is to display this newly created widget. */
274     gtk_widget_show (button);
275     
276     /* and the window */
277     gtk_widget_show (window);
278     
279     /* All GTK applications must have a gtk_main(). Control ends here
280      * and waits for an event to occur (like a key press or
281      * mouse event). */
282     gtk_main ();
283     
284     return(0);
285 }
286 /* example-end */
287 </verb></tscreen>
288
289 <!-- ----------------------------------------------------------------- -->
290 <sect1>Compiling Hello World
291 <p>
292 To compile use:
293
294 <tscreen><verb>
295 gcc -Wall -g helloworld.c -o helloworld `gtk-config --cflags` \
296     `gtk-config --libs`
297 </verb></tscreen>
298
299 This uses the program <tt>gtk-config</>, which comes with gtk. This
300 program 'knows' what compiler switches are needed to compile programs
301 that use gtk. <tt>gtk-config --cflags</> will output a list of include
302 directories for the compiler to look in, and <tt>gtk-config --libs</>
303 will output the list of libraries for the compiler to link with and
304 the directories to find them in. In the aboce example they could have
305 been combined into a single instance, such as
306 `gtk-config --cflags --libs`.
307
308 Note that the type of single quote used in the compile command above
309 is significant.
310
311 The libraries that are usually linked in are:
312 <itemize>
313 <item>The GTK library (-lgtk), the widget library, based on top of GDK.
314 <item>The GDK library (-lgdk), the Xlib wrapper.
315 <item>The gmodule library (-lgmodule), which is used to load run time
316 extensions.
317 <item>The glib library (-lglib), containing miscellaneous functions, only
318 g_print() is used in this particular example. GTK is built on top
319 of glib so you will always require this library. See the section on 
320 <ref id="sec_glib" name="glib"> for details.
321 <item>The Xlib library (-lX11) which is used by GDK.
322 <item>The Xext library (-lXext). This contains code for shared memory
323 pixmaps and other X extensions.
324 <item>The math library (-lm). This is used by GTK for various purposes.
325 </itemize>
326
327 <!-- ----------------------------------------------------------------- -->
328 <sect1>Theory of Signals and Callbacks
329 <p>
330 Before we look in detail at <em>helloworld</em>, we'll discuss signals
331 and callbacks. GTK is an event driven toolkit, which means it will
332 sleep in gtk_main until an event occurs and control is passed to the
333 appropriate function.
334
335 This passing of control is done using the idea of "signals". When an
336 event occurs, such as the press of a mouse button, the appropriate
337 signal will be "emitted" by the widget that was pressed.  This is how
338 GTK does most of its useful work. There are a set of signals that all
339 widgets inherit, such as "destroy", and there are signals that are
340 widget specific, such as "toggled" on a toggle button.
341
342 To make a button perform an action, we set up a signal handler to
343 catch these signals and call the appropriate function. This is done by
344 using a function such as:
345
346 <tscreen><verb>
347 gint gtk_signal_connect( GtkObject     *object,
348                          gchar         *name,
349                          GtkSignalFunc  func,
350                          gpointer       func_data );
351 </verb></tscreen>
352
353 Where the first argument is the widget which will be emitting the
354 signal, and the second, the name of the signal you wish to catch. The
355 third is the function you wish to be called when it is caught, and the
356 fourth, the data you wish to have passed to this function.
357
358 The function specified in the third argument is called a "callback
359 function", and should generally be of the form:
360
361 <tscreen><verb>
362 void callback_func( GtkWidget *widget,
363                     gpointer   callback_data );
364 </verb></tscreen>
365
366 Where the first argument will be a pointer to the widget that emitted
367 the signal, and the second, a pointer to the data given as the last
368 argument to the gtk_signal_connect() function as shown above.
369
370 Note that the above form for a signal callback function declaration is
371 only a general guide, as some widget specific signals generate
372 different calling parameters. For example, the GtkCList "select_row"
373 signal provides both row and column parameters.
374
375 Another call used in the <em>helloworld</em> example, is:
376
377 <tscreen><verb>
378 gint gtk_signal_connect_object( GtkObject     *object,
379                                 gchar         *name,
380                                 GtkSignalFunc  func,
381                                 GtkObject     *slot_object );
382 </verb></tscreen>
383
384 gtk_signal_connect_object() is the same as gtk_signal_connect() except
385 that the callback function only uses one argument, a pointer to a GTK
386 object. So when using this function to connect signals, the callback
387 should be of the form:
388
389 <tscreen><verb>
390 void callback_func( GtkObject *object );
391 </verb></tscreen>
392
393 Where the object is usually a widget. We usually don't setup callbacks
394 for gtk_signal_connect_object however. They are usually used to call a
395 GTK function that accepts a single widget or object as an argument, as
396 is the case in our <em>helloworld</em> example.
397
398 The purpose of having two functions to connect signals is simply to
399 allow the callbacks to have a different number of arguments. Many
400 functions in the GTK library accept only a single GtkWidget pointer as
401 an argument, so you want to use the gtk_signal_connect_object() for
402 these, whereas for your functions, you may need to have additional
403 data supplied to the callbacks.
404
405 <!-- ----------------------------------------------------------------- -->
406 <sect1>Events
407 <p>
408 In addition to the signal mechanism described above, there are a set
409 of <em>events</em> that reflect the X event mechanism. Callbacks may
410 also be attached to these events. These events are:
411
412 <itemize>
413 <item> event
414 <item> button_press_event
415 <item> button_release_event
416 <item> motion_notify_event
417 <item> delete_event
418 <item> destroy_event
419 <item> expose_event
420 <item> key_press_event
421 <item> key_release_event
422 <item> enter_notify_event
423 <item> leave_notify_event
424 <item> configure_event
425 <item> focus_in_event
426 <item> focus_out_event
427 <item> map_event
428 <item> unmap_event
429 <item> property_notify_event
430 <item> selection_clear_event
431 <item> selection_request_event
432 <item> selection_notify_event
433 <item> proximity_in_event
434 <item> proximity_out_event
435 <item> drag_begin_event
436 <item> drag_request_event
437 <item> drag_end_event
438 <item> drop_enter_event
439 <item> drop_leave_event
440 <item> drop_data_available_event
441 <item> other_event
442 </itemize>
443
444 In order to connect a callback function to one of these events, you
445 use the function gtk_signal_connect, as described above, using one of
446 the above event names as the <tt/name/ parameter. The callback
447 function for events has a slightly different form than that for
448 signals:
449
450 <tscreen><verb>
451 void callback_func( GtkWidget *widget,
452                     GdkEvent  *event,
453                     gpointer   callback_data );
454 </verb></tscreen>
455
456 GdkEvent is a C <tt/union/ structure whose type will depend upon which
457 of the above events has occurred. In order for us to tell which event
458 has been issued each of the possible alternatives has a <tt/type/
459 parameter which reflects the event being issued. The other components
460 of the event structure will depend upon the type of the
461 event. Possible values for the type are:
462
463 <tscreen><verb>
464   GDK_NOTHING
465   GDK_DELETE
466   GDK_DESTROY
467   GDK_EXPOSE
468   GDK_MOTION_NOTIFY
469   GDK_BUTTON_PRESS
470   GDK_2BUTTON_PRESS
471   GDK_3BUTTON_PRESS
472   GDK_BUTTON_RELEASE
473   GDK_KEY_PRESS
474   GDK_KEY_RELEASE
475   GDK_ENTER_NOTIFY
476   GDK_LEAVE_NOTIFY
477   GDK_FOCUS_CHANGE
478   GDK_CONFIGURE
479   GDK_MAP
480   GDK_UNMAP
481   GDK_PROPERTY_NOTIFY
482   GDK_SELECTION_CLEAR
483   GDK_SELECTION_REQUEST
484   GDK_SELECTION_NOTIFY
485   GDK_PROXIMITY_IN
486   GDK_PROXIMITY_OUT
487   GDK_DRAG_BEGIN
488   GDK_DRAG_REQUEST
489   GDK_DROP_ENTER
490   GDK_DROP_LEAVE
491   GDK_DROP_DATA_AVAIL
492   GDK_CLIENT_EVENT
493   GDK_VISIBILITY_NOTIFY
494   GDK_NO_EXPOSE
495   GDK_OTHER_EVENT       /* Deprecated, use filters instead */
496 </verb></tscreen>
497
498 So, to connect a callback function to one of these events we would use
499 something like:
500
501 <tscreen><verb>
502 gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
503                     GTK_SIGNAL_FUNC(button_press_callback), 
504                         NULL);
505 </verb></tscreen>
506
507 This assumes that <tt/button/ is a GtkButton widget. Now, when the
508 mouse is over the button and a mouse button is pressed, the function
509 <tt/button_press_callback/ will be called. This function may be
510 declared as:
511
512 <tscreen><verb>
513 static gint button_press_event (GtkWidget      *widget, 
514                                 GdkEventButton *event,
515                                 gpointer        data);
516 </verb></tscreen>
517
518 Note that we can declare the second argument as type
519 <tt/GdkEventButton/ as we know what type of event will occur for this
520 function to be called.
521
522 The value returned from this function indicates whether the event
523 should be propagated further by the GTK event handling
524 mechanism. Returning TRUE indicates that the event has been handled,
525 and that it should not propagate further. Returning FALSE continues
526 the normal event handling.  See the section on
527 <ref id="sec_Adv_Events_and_Signals"
528 name="Advanced Event and Signal Handling"> for more details on this
529 propagation process.
530
531 For details on the GdkEvent data types, see the appendix entitled
532 <ref id="sec_GDK_Event_Types" name="GDK Event Types">.
533
534 <!-- ----------------------------------------------------------------- -->
535 <sect1>Stepping Through Hello World
536 <p>
537 Now that we know the theory behind this, lets clarify by walking through 
538 the example <em>helloworld</em> program.
539
540 Here is the callback function that will be called when the button is
541 "clicked". We ignore both the widget and the data in this example, but
542 it is not hard to do things with them. The next example will use the
543 data argument to tell us which button was pressed.
544
545 <tscreen><verb>
546 void hello( GtkWidget *widget,
547             gpointer   data )
548 {
549     g_print ("Hello World\n");
550 }
551 </verb></tscreen>
552
553 The next callback is a bit special. The "delete_event" occurs when the
554 window manager sends this event to the application. We have a choice
555 here as to what to do about these events. We can ignore them, make
556 some sort of response, or simply quit the application.
557
558 The value you return in this callback lets GTK know what action to
559 take.  By returning TRUE, we let it know that we don't want to have
560 the "destroy" signal emitted, keeping our application running. By
561 returning FALSE, we ask that "destroy" is emitted, which in turn will
562 call our "destroy" signal handler.
563
564 <tscreen><verb>
565 gint delete_event( GtkWidget *widget,
566                    GdkEvent  *event,
567                    gpointer   data )
568 {
569     g_print ("delete event occurred\n");
570
571     return (TRUE); 
572 }
573 </verb></tscreen>
574
575 Here is another callback function which causes the program to quit by
576 calling gtk_main_quit(). This function tells GTK that it is to exit
577 from gtk_main when control is returned to it.
578
579 <tscreen><verb>
580 void destroy( GtkWidget *widget,
581               gpointer   data )
582 {
583     gtk_main_quit ();
584 }
585 </verb></tscreen>
586
587 I assume you know about the main() function... yes, as with other
588 applications, all GTK applications will also have one of these.
589
590 <tscreen><verb>
591 int main( int   argc,
592           char *argv[] )
593 {
594 </verb></tscreen>
595
596 This next part, declares a pointer to a structure of type
597 GtkWidget. These are used below to create a window and a button.
598
599 <tscreen><verb>
600     GtkWidget *window;
601     GtkWidget *button;
602 </verb></tscreen>
603
604 Here is our gtk_init again. As before, this initializes the toolkit,
605 and parses the arguments found on the command line. Any argument it
606 recognizes from the command line, it removes from the list, and
607 modifies argc and argv to make it look like they never existed,
608 allowing your application to parse the remaining arguments.
609
610 <tscreen><verb>
611     gtk_init (&amp;argc, &amp;argv);
612 </verb></tscreen>
613
614 Create a new window. This is fairly straight forward. Memory is
615 allocated for the GtkWidget *window structure so it now points to a
616 valid structure. It sets up a new window, but it is not displayed
617 until we call gtk_widget_show(window) near the end of our program.
618
619 <tscreen><verb>
620     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
621 </verb></tscreen>
622
623 Here is an example of connecting a signal handler to an object, in
624 this case, the window. Here, the "destroy" signal is caught. This is
625 emitted when we use the window manager to kill the window (and we
626 return FALSE in the "delete_event" handler), or when we use the
627 gtk_widget_destroy() call passing in the window widget as the object
628 to destroy. By setting this up, we handle both cases with a single
629 call. Here, it just calls the destroy() function defined above with a
630 NULL argument, which quits GTK for us.
631
632 The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform type
633 casting and checking for us, as well as aid the readability of the
634 code.
635
636 <tscreen><verb>
637     gtk_signal_connect (GTK_OBJECT (window), "destroy",
638                         GTK_SIGNAL_FUNC (destroy), NULL);
639 </verb></tscreen>
640
641 This next function is used to set an attribute of a container object.
642 This just sets the window so it has a blank area along the inside of
643 it 10 pixels wide where no widgets will go. There are other similar
644 functions which we will look at in the section on
645 <ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
646
647 And again, GTK_CONTAINER is a macro to perform type casting.
648
649 <tscreen><verb>
650     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
651 </verb></tscreen>
652
653 This call creates a new button. It allocates space for a new GtkWidget
654 structure in memory, initializes it, and makes the button pointer
655 point to it. It will have the label "Hello World" on it when
656 displayed.
657
658 <tscreen><verb>
659     button = gtk_button_new_with_label ("Hello World");
660 </verb></tscreen>
661
662 Here, we take this button, and make it do something useful. We attach
663 a signal handler to it so when it emits the "clicked" signal, our
664 hello() function is called. The data is ignored, so we simply pass in
665 NULL to the hello() callback function. Obviously, the "clicked" signal
666 is emitted when we click the button with our mouse pointer.
667
668 <tscreen><verb>
669     gtk_signal_connect (GTK_OBJECT (button), "clicked",
670                         GTK_SIGNAL_FUNC (hello), NULL);
671 </verb></tscreen>
672
673 We are also going to use this button to exit our program. This will
674 illustrate how the "destroy" signal may come from either the window
675 manager, or our program. When the button is "clicked", same as above,
676 it calls the first hello() callback function, and then this one in the
677 order they are set up. You may have as many callback functions as you
678 need, and all will be executed in the order you connected
679 them. Because the gtk_widget_destroy() function accepts only a
680 GtkWidget *widget as an argument, we use the
681 gtk_signal_connect_object() function here instead of straight
682 gtk_signal_connect().
683
684 <tscreen><verb>
685     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
686                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
687                                GTK_OBJECT (window));
688 </verb></tscreen>
689
690 This is a packing call, which will be explained in depth later on. But
691 it is fairly easy to understand. It simply tells GTK that the button
692 is to be placed in the window where it will be displayed. Note that a
693 GTK container can only contain one widget. There are other widgets,
694 that are described later, which are designed to layout multiple
695 widgets in various ways.
696  
697 <tscreen><verb>
698     gtk_container_add (GTK_CONTAINER (window), button);
699 </verb></tscreen>
700
701 Now we have everything set up the way we want it to be. With all the
702 signal handlers in place, and the button placed in the window where it
703 should be, we ask GTK to "show" the widgets on the screen. The window
704 widget is shown last so the whole window will pop up at once rather
705 than seeing the window pop up, and then the button form inside of
706 it. Although with such a simple example, you'd never notice.
707
708 <tscreen><verb>
709     gtk_widget_show (button);
710
711     gtk_widget_show (window);
712 </verb></tscreen>
713
714 And of course, we call gtk_main() which waits for events to come from
715 the X server and will call on the widgets to emit signals when these
716 events come.
717
718 <tscreen><verb>
719     gtk_main ();
720 </verb></tscreen>
721
722 And the final return. Control returns here after gtk_quit() is called.
723
724 <tscreen><verb>
725     return 0;
726 </verb></tscreen>
727
728 Now, when we click the mouse button on a GTK button, the widget emits
729 a "clicked" signal. In order for us to use this information, our
730 program sets up a signal handler to catch that signal, which
731 dispatches the function of our choice. In our example, when the button
732 we created is "clicked", the hello() function is called with a NULL
733 argument, and then the next handler for this signal is called. This
734 calls the gtk_widget_destroy() function, passing it the window widget
735 as its argument, destroying the window widget. This causes the window
736 to emit the "destroy" signal, which is caught, and calls our destroy()
737 callback function, which simply exits GTK.
738
739 Another course of events, is to use the window manager to kill the
740 window. This will cause the "delete_event" to be emitted. This will
741 call our "delete_event" handler. If we return TRUE here, the window
742 will be left as is and nothing will happen. Returning FALSE will cause
743 GTK to emit the "destroy" signal which of course, calls the "destroy"
744 callback, exiting GTK.
745
746 Note that these signals are not the same as the Unix system signals,
747 and are not implemented using them, although the terminology is almost
748 identical.
749
750 <!-- ***************************************************************** -->
751 <sect>Moving On
752 <!-- ***************************************************************** -->
753
754 <!-- ----------------------------------------------------------------- -->
755 <sect1>Data Types
756 <p>
757 There are a few things you probably noticed in the previous examples
758 that need explaining. The gint, gchar etc. that you see are typedefs
759 to int and char respectively. This is done to get around that nasty
760 dependency on the size of simple data types when doing calculations.
761
762 A good example is "gint32" which will be typedef'd to a 32 bit integer
763 for any given platform, whether it be the 64 bit alpha, or the 32 bit
764 i386. The typedefs are very straight forward and intuitive. They are
765 all defined in glib/glib.h (which gets included from gtk.h).
766
767 You'll also notice the ability to use GtkWidget when the function
768 calls for a GtkObject. GTK is an object oriented design, and a widget
769 is an object.
770
771 <!-- ----------------------------------------------------------------- -->
772 <sect1>More on Signal Handlers
773 <p>
774 Lets take another look at the gtk_signal_connect declaration.
775
776 <tscreen><verb>
777 gint gtk_signal_connect( GtkObject *object,
778                          gchar *name,
779                          GtkSignalFunc func,
780                          gpointer func_data );
781 </verb></tscreen>
782
783 Notice the gint return value? This is a tag that identifies your
784 callback function. As stated above, you may have as many callbacks per
785 signal and per object as you need, and each will be executed in turn,
786 in the order they were attached.
787
788 This tag allows you to remove this callback from the list by using:
789
790 <tscreen><verb>
791 void gtk_signal_disconnect( GtkObject *object,
792                             gint id );
793 </verb></tscreen>
794
795 So, by passing in the widget you wish to remove the handler from, and
796 the tag returned by one of the signal_connect functions, you can
797 disconnect a signal handler.
798
799 Another function to remove all the signal handers from an object is:
800
801 <tscreen><verb>
802 void gtk_signal_handlers_destroy( GtkObject *object );
803 </verb></tscreen>
804
805 This call is fairly self explanatory. It simply removes all the
806 current signal handlers from the object passed in as the first
807 argument.
808
809 <!-- ----------------------------------------------------------------- -->
810 <sect1>An Upgraded Hello World
811 <p>
812 Let's take a look at a slightly improved <em>helloworld</em> with
813 better examples of callbacks. This will also introduce us to our next
814 topic, packing widgets.
815
816 <tscreen><verb>
817 /* example-start helloworld2 helloworld2.c */
818
819 #include <gtk/gtk.h>
820
821 /* Our new improved callback.  The data passed to this function
822  * is printed to stdout. */
823 void callback( GtkWidget *widget,
824                gpointer   data )
825 {
826     g_print ("Hello again - %s was pressed\n", (char *) data);
827 }
828
829 /* another callback */
830 void delete_event( GtkWidget *widget,
831                    GdkEvent  *event,
832                    gpointer   data )
833 {
834     gtk_main_quit ();
835 }
836
837 int main( int   argc,
838           char *argv[] )
839 {
840     /* GtkWidget is the storage type for widgets */
841     GtkWidget *window;
842     GtkWidget *button;
843     GtkWidget *box1;
844
845     /* This is called in all GTK applications. Arguments are parsed
846      * from the command line and are returned to the application. */
847     gtk_init (&amp;argc, &amp;argv);
848
849     /* Create a new window */
850     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
851
852     /* This is a new call, this just sets the title of our
853      * new window to "Hello Buttons!" */
854     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
855
856     /* Here we just set a handler for delete_event that immediately
857      * exits GTK. */
858     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
859                         GTK_SIGNAL_FUNC (delete_event), NULL);
860
861     /* Sets the border width of the window. */
862     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
863
864     /* We create a box to pack widgets into.  This is described in detail
865      * in the "packing" section. The box is not really visible, it
866      * is just used as a tool to arrange widgets. */
867     box1 = gtk_hbox_new(FALSE, 0);
868
869     /* Put the box into the main window. */
870     gtk_container_add (GTK_CONTAINER (window), box1);
871
872     /* Creates a new button with the label "Button 1". */
873     button = gtk_button_new_with_label ("Button 1");
874
875     /* Now when the button is clicked, we call the "callback" function
876      * with a pointer to "button 1" as its argument */
877     gtk_signal_connect (GTK_OBJECT (button), "clicked",
878                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
879
880     /* Instead of gtk_container_add, we pack this button into the invisible
881      * box, which has been packed into the window. */
882     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
883
884     /* Always remember this step, this tells GTK that our preparation for
885      * this button is complete, and it can now be displayed. */
886     gtk_widget_show(button);
887
888     /* Do these same steps again to create a second button */
889     button = gtk_button_new_with_label ("Button 2");
890
891     /* Call the same callback function with a different argument,
892      * passing a pointer to "button 2" instead. */
893     gtk_signal_connect (GTK_OBJECT (button), "clicked",
894                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
895
896     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
897
898     /* The order in which we show the buttons is not really important, but I
899      * recommend showing the window last, so it all pops up at once. */
900     gtk_widget_show(button);
901
902     gtk_widget_show(box1);
903
904     gtk_widget_show (window);
905
906     /* Rest in gtk_main and wait for the fun to begin! */
907     gtk_main ();
908
909     return(0);
910 }
911 /* example-end */
912 </verb></tscreen>
913
914 Compile this program using the same linking arguments as our first
915 example.  You'll notice this time there is no easy way to exit the
916 program, you have to use your window manager or command line to kill
917 it. A good exercise for the reader would be to insert a third "Quit"
918 button that will exit the program. You may also wish to play with the
919 options to gtk_box_pack_start() while reading the next section.  Try
920 resizing the window, and observe the behavior.
921
922 Just as a side note, there is another useful define for
923 gtk_window_new() - GTK_WINDOW_DIALOG. This interacts with the window
924 manager a little differently and should be used for transient windows.
925
926 <!-- ***************************************************************** -->
927 <sect>Packing Widgets
928 <!-- ***************************************************************** -->
929 <p>
930 When creating an application, you'll want to put more than one widget
931 inside a window. Our first <em>helloworld</em> example only used one
932 widget so we could simply use a gtk_container_add call to "pack" the
933 widget into the window. But when you want to put more than one widget
934 into a window, how do you control where that widget is positioned?
935 This is where packing comes in.
936
937 <!-- ----------------------------------------------------------------- -->
938 <sect1>Theory of Packing Boxes
939 <p>
940 Most packing is done by creating boxes as in the example above. These
941 are invisible widget containers that we can pack our widgets into
942 which come in two forms, a horizontal box, and a vertical box. When
943 packing widgets into a horizontal box, the objects are inserted
944 horizontally from left to right or right to left depending on the call
945 used. In a vertical box, widgets are packed from top to bottom or vice
946 versa. You may use any combination of boxes inside or beside other
947 boxes to create the desired effect.
948
949 To create a new horizontal box, we use a call to gtk_hbox_new(), and
950 for vertical boxes, gtk_vbox_new().The gtk_box_pack_start() and
951 gtk_box_pack_end() functions are used to place objects inside of these
952 containers. The gtk_box_pack_start() function will start at the top
953 and work its way down in a vbox, and pack left to right in an hbox.
954 gtk_box_pack_end() will do the opposite, packing from bottom to top in
955 a vbox, and right to left in an hbox. Using these functions allow us
956 to right justify or left justify our widgets and may be mixed in any
957 way to achieve the desired effect. We will use gtk_box_pack_start() in
958 most of our examples. An object may be another container or a
959 widget. In fact, many widgets are actually containers themselves,
960 including the button, but we usually only use a label inside a button.
961
962 By using these calls, GTK knows where you want to place your widgets
963 so it can do automatic resizing and other nifty things. There's also a
964 number of options as to how your widgets should be packed. As you can
965 imagine, this method gives us a quite a bit of flexibility when
966 placing and creating widgets.
967
968 <!-- ----------------------------------------------------------------- -->
969 <sect1>Details of Boxes
970 <p>
971 Because of this flexibility, packing boxes in GTK can be confusing at
972 first. There are a lot of options, and it's not immediately obvious how
973 they all fit together. In the end however, there are basically five
974 different styles.
975
976 <? <CENTER> >
977 <?
978 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
979 HEIGHT="235" ALT="Box Packing Example Image">
980 >
981 <? </CENTER> >
982
983 Each line contains one horizontal box (hbox) with several buttons. The
984 call to gtk_box_pack is shorthand for the call to pack each of the
985 buttons into the hbox. Each of the buttons is packed into the hbox the
986 same way (i.e. same arguments to the gtk_box_pack_start() function).
987
988 This is the declaration of the gtk_box_pack_start function.
989
990 <tscreen><verb>
991 void gtk_box_pack_start( GtkBox    *box,
992                          GtkWidget *child,
993                          gint       expand,
994                          gint       fill,
995                          gint       padding );
996 </verb></tscreen>
997
998 The first argument is the box you are packing the object into, the
999 second is the object. The objects will all be buttons for now, so
1000 we'll be packing buttons into boxes.
1001
1002 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1003 controls whether the widgets are laid out in the box to fill in all
1004 the extra space in the box so the box is expanded to fill the area
1005 alloted to it (TRUE).  Or the box is shrunk to just fit the widgets
1006 (FALSE). Setting expand to FALSE will allow you to do right and left
1007 justification of your widgets.  Otherwise, they will all expand to fit
1008 into the box, and the same effect could be achieved by using only one
1009 of gtk_box_pack_start or gtk_box_pack_end.
1010
1011 The fill argument to the gtk_box_pack functions control whether the
1012 extra space is allocated to the objects themselves (TRUE), or as extra
1013 padding in the box around these objects (FALSE). It only has an effect
1014 if the expand argument is also TRUE.
1015
1016 When creating a new box, the function looks like this:
1017
1018 <tscreen><verb>
1019 GtkWidget *gtk_hbox_new (gint homogeneous,
1020                          gint spacing);
1021 </verb></tscreen>
1022
1023 The homogeneous argument to gtk_hbox_new (and the same for
1024 gtk_vbox_new) controls whether each object in the box has the same
1025 size (i.e. the same width in an hbox, or the same height in a
1026 vbox). If it is set, the expand argument to the gtk_box_pack routines
1027 is always turned on.
1028
1029 What's the difference between spacing (set when the box is created)
1030 and padding (set when elements are packed)? Spacing is added between
1031 objects, and padding is added on either side of an object. The
1032 following figure should make it clearer:
1033
1034 <? <CENTER> >
1035 <?
1036 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1037 HEIGHT="213" VSPACE="15" HSPACE="10"
1038 ALT="Box Packing Example Image">
1039 >
1040 <? </CENTER> >
1041
1042 Here is the code used to create the above images. I've commented it
1043 fairly heavily so hopefully you won't have any problems following
1044 it. Compile it yourself and play with it.
1045
1046 <!-- ----------------------------------------------------------------- -->
1047 <sect1>Packing Demonstration Program
1048 <p>
1049 <tscreen><verb>
1050 /* example-start packbox packbox.c */
1051
1052 #include <stdio.h>
1053 #include "gtk/gtk.h"
1054
1055 void delete_event( GtkWidget *widget,
1056                    GdkEvent  *event,
1057                    gpointer   data )
1058 {
1059     gtk_main_quit ();
1060 }
1061
1062 /* Make a new hbox filled with button-labels. Arguments for the 
1063  * variables we're interested are passed in to this function. 
1064  * We do not show the box, but do show everything inside. */
1065 GtkWidget *make_box( gint homogeneous,
1066                      gint spacing,
1067                      gint expand,
1068                      gint fill,
1069                      gint padding ) 
1070 {
1071     GtkWidget *box;
1072     GtkWidget *button;
1073     char padstr[80];
1074     
1075     /* Create a new hbox with the appropriate homogeneous
1076      * and spacing settings */
1077     box = gtk_hbox_new (homogeneous, spacing);
1078     
1079     /* Create a series of buttons with the appropriate settings */
1080     button = gtk_button_new_with_label ("gtk_box_pack");
1081     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1082     gtk_widget_show (button);
1083     
1084     button = gtk_button_new_with_label ("(box,");
1085     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1086     gtk_widget_show (button);
1087     
1088     button = gtk_button_new_with_label ("button,");
1089     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1090     gtk_widget_show (button);
1091     
1092     /* Create a button with the label depending on the value of
1093      * expand. */
1094     if (expand == TRUE)
1095             button = gtk_button_new_with_label ("TRUE,");
1096     else
1097             button = gtk_button_new_with_label ("FALSE,");
1098     
1099     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1100     gtk_widget_show (button);
1101     
1102     /* This is the same as the button creation for "expand"
1103      * above, but uses the shorthand form. */
1104     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1105     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1106     gtk_widget_show (button);
1107     
1108     sprintf (padstr, "%d);", padding);
1109     
1110     button = gtk_button_new_with_label (padstr);
1111     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1112     gtk_widget_show (button);
1113     
1114     return box;
1115 }
1116
1117 int main( int   argc,
1118           char *argv[]) 
1119 {
1120     GtkWidget *window;
1121     GtkWidget *button;
1122     GtkWidget *box1;
1123     GtkWidget *box2;
1124     GtkWidget *separator;
1125     GtkWidget *label;
1126     GtkWidget *quitbox;
1127     int which;
1128     
1129     /* Our init, don't forget this! :) */
1130     gtk_init (&amp;argc, &amp;argv);
1131     
1132     if (argc != 2) {
1133         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1134         /* this just does cleanup in GTK, and exits with an exit status of 1. */
1135         gtk_exit (1);
1136     }
1137     
1138     which = atoi (argv[1]);
1139
1140     /* Create our window */
1141     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1142
1143     /* You should always remember to connect the destroy signal to the
1144      * main window. This is very important for proper intuitive
1145      * behavior */
1146     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1147                         GTK_SIGNAL_FUNC (delete_event), NULL);
1148     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1149     
1150     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1151      * This allows us to stack the horizontal boxes filled with buttons one
1152      * on top of the other in this vbox. */
1153     box1 = gtk_vbox_new (FALSE, 0);
1154     
1155     /* which example to show. These correspond to the pictures above. */
1156     switch (which) {
1157     case 1:
1158         /* create a new label. */
1159         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1160         
1161         /* Align the label to the left side.  We'll discuss this function and 
1162          * others in the section on Widget Attributes. */
1163         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1164
1165         /* Pack the label into the vertical box (vbox box1).  Remember that 
1166          * widgets added to a vbox will be packed one on top of the other in
1167          * order. */
1168         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1169         
1170         /* Show the label */
1171         gtk_widget_show (label);
1172         
1173         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1174          * expand = FALSE, fill = FALSE, padding = 0 */
1175         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1176         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1177         gtk_widget_show (box2);
1178
1179         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1180          * expand = FALSE, fill = FALSE, padding = 0 */
1181         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1182         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1183         gtk_widget_show (box2);
1184         
1185         /* Args are: homogeneous, spacing, expand, fill, padding */
1186         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1187         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1188         gtk_widget_show (box2);
1189         
1190         /* Creates a separator, we'll learn more about these later, 
1191          * but they are quite simple. */
1192         separator = gtk_hseparator_new ();
1193         
1194         /* Cack the separator into the vbox. Remember each of these
1195          * widgets are being packed into a vbox, so they'll be stacked
1196          * vertically. */
1197         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1198         gtk_widget_show (separator);
1199         
1200         /* Create another new label, and show it. */
1201         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1202         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1203         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1204         gtk_widget_show (label);
1205         
1206         /* Args are: homogeneous, spacing, expand, fill, padding */
1207         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1208         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1209         gtk_widget_show (box2);
1210         
1211         /* Args are: homogeneous, spacing, expand, fill, padding */
1212         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1213         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1214         gtk_widget_show (box2);
1215         
1216         /* Another new separator. */
1217         separator = gtk_hseparator_new ();
1218         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1219         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1220         gtk_widget_show (separator);
1221         
1222         break;
1223
1224     case 2:
1225
1226         /* Create a new label, remember box1 is a vbox as created 
1227          * near the beginning of main() */
1228         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1229         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1230         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1231         gtk_widget_show (label);
1232         
1233         /* Args are: homogeneous, spacing, expand, fill, padding */
1234         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1235         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1236         gtk_widget_show (box2);
1237         
1238         /* Args are: homogeneous, spacing, expand, fill, padding */
1239         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1240         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1241         gtk_widget_show (box2);
1242         
1243         separator = gtk_hseparator_new ();
1244         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1245         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1246         gtk_widget_show (separator);
1247         
1248         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1249         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1250         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1251         gtk_widget_show (label);
1252         
1253         /* Args are: homogeneous, spacing, expand, fill, padding */
1254         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1255         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1256         gtk_widget_show (box2);
1257         
1258         /* Args are: homogeneous, spacing, expand, fill, padding */
1259         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1260         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1261         gtk_widget_show (box2);
1262         
1263         separator = gtk_hseparator_new ();
1264         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1265         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1266         gtk_widget_show (separator);
1267         break;
1268     
1269     case 3:
1270
1271         /* This demonstrates the ability to use gtk_box_pack_end() to
1272          * right justify widgets. First, we create a new box as before. */
1273         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1274
1275         /* Create the label that will be put at the end. */
1276         label = gtk_label_new ("end");
1277         /* Pack it using gtk_box_pack_end(), so it is put on the right
1278          * side of the hbox created in the make_box() call. */
1279         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1280         /* Show the label. */
1281         gtk_widget_show (label);
1282         
1283         /* Pack box2 into box1 (the vbox remember ? :) */
1284         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1285         gtk_widget_show (box2);
1286         
1287         /* A separator for the bottom. */
1288         separator = gtk_hseparator_new ();
1289         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1290          * high. This is so the hbox we created will also be 400 pixels wide,
1291          * and the "end" label will be separated from the other labels in the
1292          * hbox. Otherwise, all the widgets in the hbox would be packed as
1293          * close together as possible. */
1294         gtk_widget_set_usize (separator, 400, 5);
1295         /* pack the separator into the vbox (box1) created near the start 
1296          * of main() */
1297         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1298         gtk_widget_show (separator);    
1299     }
1300     
1301     /* Create another new hbox.. remember we can use as many as we need! */
1302     quitbox = gtk_hbox_new (FALSE, 0);
1303     
1304     /* Our quit button. */
1305     button = gtk_button_new_with_label ("Quit");
1306     
1307     /* Setup the signal to destroy the window. Remember that this will send
1308      * the "destroy" signal to the window which will be caught by our signal
1309      * handler as defined above. */
1310     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1311                                GTK_SIGNAL_FUNC (gtk_main_quit),
1312                                GTK_OBJECT (window));
1313     /* Pack the button into the quitbox.
1314      * The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1315     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1316     /* pack the quitbox into the vbox (box1) */
1317     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1318     
1319     /* Pack the vbox (box1) which now contains all our widgets, into the
1320      * main window. */
1321     gtk_container_add (GTK_CONTAINER (window), box1);
1322     
1323     /* And show everything left */
1324     gtk_widget_show (button);
1325     gtk_widget_show (quitbox);
1326     
1327     gtk_widget_show (box1);
1328     /* Showing the window last so everything pops up at once. */
1329     gtk_widget_show (window);
1330     
1331     /* And of course, our main function. */
1332     gtk_main ();
1333
1334     /* Control returns here when gtk_main_quit() is called, but not when 
1335      * gtk_exit is used. */
1336     
1337     return(0);
1338 }
1339 /* example-end */
1340 </verb></tscreen>
1341
1342 <!-- ----------------------------------------------------------------- -->
1343 <sect1>Packing Using Tables
1344 <p>
1345 Let's take a look at another way of packing - Tables. These can be
1346 extremely useful in certain situations.
1347
1348 Using tables, we create a grid that we can place widgets in. The
1349 widgets may take up as many spaces as we specify.
1350
1351 The first thing to look at of course, is the gtk_table_new function:
1352
1353 <tscreen><verb>
1354 GtkWidget *gtk_table_new( gint rows,
1355                           gint columns,
1356                           gint homogeneous );
1357 </verb></tscreen>
1358
1359 The first argument is the number of rows to make in the table, while
1360 the second, obviously, is the number of columns.
1361
1362 The homogeneous argument has to do with how the table's boxes are
1363 sized. If homogeneous is TRUE, the table boxes are resized to the size
1364 of the largest widget in the table. If homogeneous is FALSE, the size
1365 of a table boxes is dictated by the tallest widget in its same row,
1366 and the widest widget in its column.
1367
1368 The rows and columns are laid out from 0 to n, where n was the number
1369 specified in the call to gtk_table_new. So, if you specify rows = 2
1370 and columns = 2, the layout would look something like this:
1371
1372 <tscreen><verb>
1373  0          1          2
1374 0+----------+----------+
1375  |          |          |
1376 1+----------+----------+
1377  |          |          |
1378 2+----------+----------+
1379 </verb></tscreen>
1380
1381 Note that the coordinate system starts in the upper left hand corner.
1382 To place a widget into a box, use the following function:
1383
1384 <tscreen><verb>
1385 void gtk_table_attach( GtkTable  *table,
1386                        GtkWidget *child,
1387                        gint       left_attach,
1388                        gint       right_attach,
1389                        gint       top_attach,
1390                        gint       bottom_attach,
1391                        gint       xoptions,
1392                        gint       yoptions,
1393                        gint       xpadding,
1394                        gint       ypadding );
1395 </verb></tscreen>                                      
1396
1397 Where the first argument ("table") is the table you've created and the
1398 second ("child") the widget you wish to place in the table.
1399
1400 The left and right attach arguments specify where to place the widget,
1401 and how many boxes to use. If you want a button in the lower right
1402 table entry of our 2x2 table, and want it to fill that entry ONLY,
1403 left_attach would be = 1, right_attach = 2, top_attach = 1,
1404 bottom_attach = 2.
1405
1406 Now, if you wanted a widget to take up the whole top row of our 2x2
1407 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1408 bottom_attach = 1.
1409
1410 The xoptions and yoptions are used to specify packing options and may
1411 be bitwise OR'ed together to allow multiple options.
1412
1413 These options are:
1414 <itemize>
1415 <item>GTK_FILL - If the table box is larger than the widget, and
1416 GTK_FILL is specified, the widget will expand to use all the room
1417 available.
1418
1419 <item>GTK_SHRINK - If the table widget was allocated less space then
1420 was requested (usually by the user resizing the window), then the
1421 widgets would normally just be pushed off the bottom of the window and
1422 disappear. If GTK_SHRINK is specified, the widgets will shrink with
1423 the table.
1424
1425 <item>GTK_EXPAND - This will cause the table to expand to use up any
1426 remaining space in the window.
1427 </itemize>
1428
1429 Padding is just like in boxes, creating a clear area around the widget
1430 specified in pixels.
1431
1432 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1433
1434 <tscreen><verb>
1435 void gtk_table_attach_defaults( GtkTable  *table,
1436                                 GtkWidget *widget,
1437                                 gint       left_attach,
1438                                 gint       right_attach,
1439                                 gint       top_attach,
1440                                 gint       bottom_attach );
1441 </verb></tscreen>
1442
1443 The X and Y options default to GTK_FILL | GTK_EXPAND, and X and Y
1444 padding are set to 0. The rest of the arguments are identical to the
1445 previous function.
1446
1447 We also have gtk_table_set_row_spacing() and
1448 gtk_table_set_col_spacing().  This places spacing between the rows at
1449 the specified row or column.
1450
1451 <tscreen><verb>
1452 void gtk_table_set_row_spacing( GtkTable *table,
1453                                 gint      row,
1454                                 gint      spacing );
1455 </verb></tscreen>
1456
1457 and
1458
1459 <tscreen><verb>
1460 void gtk_table_set_col_spacing ( GtkTable *table,
1461                                  gint      column,
1462                                  gint      spacing );
1463 </verb></tscreen>
1464
1465 Note that for columns, the space goes to the right of the column, and
1466 for rows, the space goes below the row.
1467
1468 You can also set a consistent spacing of all rows and/or columns with:
1469
1470 <tscreen><verb>
1471 void gtk_table_set_row_spacings( GtkTable *table,
1472                                  gint      spacing );
1473 </verb></tscreen>
1474
1475 And,
1476
1477 <tscreen><verb>
1478 void gtk_table_set_col_spacings( GtkTable *table,
1479                                  gint      spacing );
1480 </verb></tscreen>
1481
1482 Note that with these calls, the last row and last column do not get
1483 any spacing.
1484
1485 <!-- ----------------------------------------------------------------- -->
1486 <sect1>Table Packing Example
1487 <p>
1488 Here we make a window with three buttons in a 2x2 table.
1489 The first two buttons will be placed in the upper row.
1490 A third, quit button, is placed in the lower row, spanning both columns.
1491 Which means it should look something like this:
1492
1493 <? <CENTER> >
1494 <?
1495 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1496 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1497 >
1498 <? </CENTER> >
1499
1500 Here's the source code:
1501
1502 <tscreen><verb>
1503 /* example-start table table.c */
1504
1505 #include <gtk/gtk.h>
1506
1507 /* Our callback.
1508  * The data passed to this function is printed to stdout */
1509 void callback( GtkWidget *widget,
1510                gpointer   data )
1511 {
1512     g_print ("Hello again - %s was pressed\n", (char *) data);
1513 }
1514
1515 /* This callback quits the program */
1516 void delete_event( GtkWidget *widget,
1517                    GdkEvent  *event,
1518                    gpointer   data )
1519 {
1520     gtk_main_quit ();
1521 }
1522
1523 int main( int   argc,
1524           char *argv[] )
1525 {
1526     GtkWidget *window;
1527     GtkWidget *button;
1528     GtkWidget *table;
1529
1530     gtk_init (&amp;argc, &amp;argv);
1531
1532     /* Create a new window */
1533     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1534
1535     /* Set the window title */
1536     gtk_window_set_title (GTK_WINDOW (window), "Table");
1537
1538     /* Set a handler for delete_event that immediately
1539      * exits GTK. */
1540     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1541                         GTK_SIGNAL_FUNC (delete_event), NULL);
1542
1543     /* Sets the border width of the window. */
1544     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1545
1546     /* Create a 2x2 table */
1547     table = gtk_table_new (2, 2, TRUE);
1548
1549     /* Put the table in the main window */
1550     gtk_container_add (GTK_CONTAINER (window), table);
1551
1552     /* Create first button */
1553     button = gtk_button_new_with_label ("button 1");
1554
1555     /* When the button is clicked, we call the "callback" function
1556      * with a pointer to "button 1" as its argument */
1557     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1558               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1559
1560
1561     /* Insert button 1 into the upper left quadrant of the table */
1562     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1563
1564     gtk_widget_show (button);
1565
1566     /* Create second button */
1567
1568     button = gtk_button_new_with_label ("button 2");
1569
1570     /* When the button is clicked, we call the "callback" function
1571      * with a pointer to "button 2" as its argument */
1572     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1573               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1574     /* Insert button 2 into the upper right quadrant of the table */
1575     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1576
1577     gtk_widget_show (button);
1578
1579     /* Create "Quit" button */
1580     button = gtk_button_new_with_label ("Quit");
1581
1582     /* When the button is clicked, we call the "delete_event" function
1583      * and the program exits */
1584     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1585                         GTK_SIGNAL_FUNC (delete_event), NULL);
1586
1587     /* Insert the quit button into the both 
1588      * lower quadrants of the table */
1589     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1590
1591     gtk_widget_show (button);
1592
1593     gtk_widget_show (table);
1594     gtk_widget_show (window);
1595
1596     gtk_main ();
1597
1598     return 0;
1599 }
1600 /* example-end */
1601 </verb></tscreen>
1602
1603 <!-- ***************************************************************** -->
1604 <sect>Widget Overview
1605 <!-- ***************************************************************** -->
1606 <p>
1607 The general steps to creating a widget in GTK are:
1608 <enum>
1609 <item> gtk_*_new - one of various functions to create a new widget.
1610 These are all detailed in this section.
1611
1612 <item> Connect all signals and events we wish to use to the
1613 appropriate handlers.
1614
1615 <item> Set the attributes of the widget.
1616
1617 <item> Pack the widget into a container using the appropriate call
1618 such as gtk_container_add() or gtk_box_pack_start().
1619
1620 <item> gtk_widget_show() the widget.
1621 </enum>
1622
1623 gtk_widget_show() lets GTK know that we are done setting the
1624 attributes of the widget, and it is ready to be displayed. You may
1625 also use gtk_widget_hide to make it disappear again. The order in
1626 which you show the widgets is not important, but I suggest showing the
1627 window last so the whole window pops up at once rather than seeing the
1628 individual widgets come up on the screen as they're formed. The
1629 children of a widget (a window is a widget too) will not be displayed
1630 until the window itself is shown using the gtk_widget_show() function.
1631
1632 <!-- ----------------------------------------------------------------- -->
1633 <sect1> Casting
1634 <p>
1635 You'll notice as you go on, that GTK uses a type casting system. This
1636 is always done using macros that both test the ability to cast the
1637 given item, and perform the cast. Some common ones you will see are:
1638
1639 <itemize>
1640 <item> GTK_WIDGET(widget)
1641 <item> GTK_OBJECT(object)
1642 <item> GTK_SIGNAL_FUNC(function)
1643 <item> GTK_CONTAINER(container)
1644 <item> GTK_WINDOW(window)
1645 <item> GTK_BOX(box)
1646 </itemize>
1647
1648 These are all used to cast arguments in functions. You'll see them in the
1649 examples, and can usually tell when to use them simply by looking at the
1650 function's declaration.
1651
1652 As you can see below in the class hierarchy, all GtkWidgets are
1653 derived from the GtkObject base class. This means you can use a widget
1654 in any place the function asks for an object - simply use the
1655 GTK_OBJECT() macro.
1656
1657 For example:
1658
1659 <tscreen><verb>
1660 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1661                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1662 </verb></tscreen> 
1663
1664 This casts the button into an object, and provides a cast for the
1665 function pointer to the callback.
1666
1667 Many widgets are also containers. If you look in the class hierarchy
1668 below, you'll notice that many widgets derive from the GtkContainer
1669 class. Any one of these widgets may be used with the GTK_CONTAINER
1670 macro to pass them to functions that ask for containers.
1671
1672 Unfortunately, these macros are not extensively covered in the
1673 tutorial, but I recommend taking a look through the GTK header
1674 files. It can be very educational. In fact, it's not difficult to
1675 learn how a widget works just by looking at the function declarations.
1676
1677 <!-- ----------------------------------------------------------------- -->
1678 <sect1>Widget Hierarchy
1679 <p>
1680 For your reference, here is the class hierarchy tree used to implement widgets.
1681
1682 <tscreen><verb>
1683  GtkObject
1684   +GtkWidget
1685   | +GtkMisc
1686   | | +GtkLabel
1687   | | | +GtkAccelLabel
1688   | | | `GtkTipsQuery
1689   | | +GtkArrow
1690   | | +GtkImage
1691   | | `GtkPixmap
1692   | +GtkContainer
1693   | | +GtkBin
1694   | | | +GtkAlignment
1695   | | | +GtkFrame
1696   | | | | `GtkAspectFrame
1697   | | | +GtkButton
1698   | | | | +GtkToggleButton
1699   | | | | | `GtkCheckButton
1700   | | | | |   `GtkRadioButton
1701   | | | | `GtkOptionMenu
1702   | | | +GtkItem
1703   | | | | +GtkMenuItem
1704   | | | | | +GtkCheckMenuItem
1705   | | | | | | `GtkRadioMenuItem
1706   | | | | | `GtkTearoffMenuItem
1707   | | | | +GtkListItem
1708   | | | | `GtkTreeItem
1709   | | | +GtkWindow
1710   | | | | +GtkColorSelectionDialog
1711   | | | | +GtkDialog
1712   | | | | | `GtkInputDialog
1713   | | | | +GtkDrawWindow
1714   | | | | +GtkFileSelection
1715   | | | | +GtkFontSelectionDialog
1716   | | | | `GtkPlug
1717   | | | +GtkEventBox
1718   | | | +GtkHandleBox
1719   | | | +GtkScrolledWindow
1720   | | | `GtkViewport
1721   | | +GtkBox
1722   | | | +GtkButtonBox
1723   | | | | +GtkHButtonBox
1724   | | | | `GtkVButtonBox
1725   | | | +GtkVBox
1726   | | | | +GtkColorSelection
1727   | | | | `GtkGammaCurve
1728   | | | `GtkHBox
1729   | | |   +GtkCombo
1730   | | |   `GtkStatusbar
1731   | | +GtkCList
1732   | | | `GtkCTree
1733   | | +GtkFixed
1734   | | +GtkNotebook
1735   | | | `GtkFontSelection
1736   | | +GtkPaned
1737   | | | +GtkHPaned
1738   | | | `GtkVPaned
1739   | | +GtkLayout
1740   | | +GtkList
1741   | | +GtkMenuShell
1742   | | | +GtkMenuBar
1743   | | | `GtkMenu
1744   | | +GtkPacker
1745   | | +GtkSocket
1746   | | +GtkTable
1747   | | +GtkToolbar
1748   | | `GtkTree
1749   | +GtkCalendar
1750   | +GtkDrawingArea
1751   | | `GtkCurve
1752   | +GtkEditable
1753   | | +GtkEntry
1754   | | | `GtkSpinButton
1755   | | `GtkText
1756   | +GtkRuler
1757   | | +GtkHRuler
1758   | | `GtkVRuler
1759   | +GtkRange
1760   | | +GtkScale
1761   | | | +GtkHScale
1762   | | | `GtkVScale
1763   | | `GtkScrollbar
1764   | |   +GtkHScrollbar
1765   | |   `GtkVScrollbar
1766   | +GtkSeparator
1767   | | +GtkHSeparator
1768   | | `GtkVSeparator
1769   | +GtkPreview
1770   | `GtkProgress
1771   |   `GtkProgressBar
1772   +GtkData
1773   | +GtkAdjustment
1774   | `GtkTooltips
1775   `GtkItemFactory
1776 </verb></tscreen>
1777
1778 <!-- ----------------------------------------------------------------- -->
1779 <sect1>Widgets Without Windows
1780 <p>
1781 The following widgets do not have an associated window. If you want to
1782 capture events, you'll have to use the GtkEventBox. See the section on
1783 the <ref id="sec_EventBox" name="EventBox"> widget.
1784
1785 <tscreen><verb>
1786 GtkAlignment
1787 GtkArrow
1788 GtkBin
1789 GtkBox
1790 GtkImage
1791 GtkItem
1792 GtkLabel
1793 GtkPixmap
1794 GtkScrolledWindow
1795 GtkSeparator
1796 GtkTable
1797 GtkAspectFrame
1798 GtkFrame
1799 GtkVBox
1800 GtkHBox
1801 GtkVSeparator
1802 GtkHSeparator
1803 </verb></tscreen>
1804
1805 We'll further our exploration of GTK by examining each widget in turn,
1806 creating a few simple functions to display them. Another good source
1807 is the testgtk.c program that comes with GTK. It can be found in
1808 gtk/testgtk.c.
1809
1810 <!-- ***************************************************************** -->
1811 <sect>The Button Widget
1812 <!-- ***************************************************************** -->
1813
1814 <!-- ----------------------------------------------------------------- -->
1815 <sect1>Normal Buttons
1816 <p>
1817 We've almost seen all there is to see of the button widget. It's
1818 pretty simple. There are however two ways to create a button. You can
1819 use the gtk_button_new_with_label() to create a button with a label,
1820 or use gtk_button_new() to create a blank button. It's then up to you
1821 to pack a label or pixmap into this new button. To do this, create a
1822 new box, and then pack your objects into this box using the usual
1823 gtk_box_pack_start, and then use gtk_container_add to pack the box
1824 into the button.
1825
1826 Here's an example of using gtk_button_new to create a button with a
1827 picture and a label in it. I've broken up the code to create a box
1828 from the rest so you can use it in your programs. There are further
1829 examples of using pixmaps later in the tutorial.
1830
1831 <tscreen><verb>
1832 /* example-start buttons buttons.c */
1833
1834 #include <gtk/gtk.h>
1835
1836 /* Create a new hbox with an image and a label packed into it
1837  * and return the box. */
1838
1839 GtkWidget *xpm_label_box( GtkWidget *parent,
1840                           gchar     *xpm_filename,
1841                           gchar     *label_text )
1842 {
1843     GtkWidget *box1;
1844     GtkWidget *label;
1845     GtkWidget *pixmapwid;
1846     GdkPixmap *pixmap;
1847     GdkBitmap *mask;
1848     GtkStyle *style;
1849
1850     /* Create box for xpm and label */
1851     box1 = gtk_hbox_new (FALSE, 0);
1852     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1853
1854     /* Get the style of the button to get the
1855      * background color. */
1856     style = gtk_widget_get_style(parent);
1857
1858     /* Now on to the xpm stuff */
1859     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1860                                          &amp;style->bg[GTK_STATE_NORMAL],
1861                                          xpm_filename);
1862     pixmapwid = gtk_pixmap_new (pixmap, mask);
1863
1864     /* Create a label for the button */
1865     label = gtk_label_new (label_text);
1866
1867     /* Pack the pixmap and label into the box */
1868     gtk_box_pack_start (GTK_BOX (box1),
1869                         pixmapwid, FALSE, FALSE, 3);
1870
1871     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1872
1873     gtk_widget_show(pixmapwid);
1874     gtk_widget_show(label);
1875
1876     return(box1);
1877 }
1878
1879 /* Our usual callback function */
1880 void callback( GtkWidget *widget,
1881                gpointer   data )
1882 {
1883     g_print ("Hello again - %s was pressed\n", (char *) data);
1884 }
1885
1886
1887 int main( int   argc,
1888           char *argv[] )
1889 {
1890     /* GtkWidget is the storage type for widgets */
1891     GtkWidget *window;
1892     GtkWidget *button;
1893     GtkWidget *box1;
1894
1895     gtk_init (&amp;argc, &amp;argv);
1896
1897     /* Create a new window */
1898     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1899
1900     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1901
1902     /* It's a good idea to do this for all windows. */
1903     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1904                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1905
1906     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1907                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1908
1909
1910     /* Sets the border width of the window. */
1911     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1912     gtk_widget_realize(window);
1913
1914     /* Create a new button */
1915     button = gtk_button_new ();
1916
1917     /* Connect the "clicked" signal of the button to our callback */
1918     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1919                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1920
1921     /* This calls our box creating function */
1922     box1 = xpm_label_box(window, "info.xpm", "cool button");
1923
1924     /* Pack and show all our widgets */
1925     gtk_widget_show(box1);
1926
1927     gtk_container_add (GTK_CONTAINER (button), box1);
1928
1929     gtk_widget_show(button);
1930
1931     gtk_container_add (GTK_CONTAINER (window), button);
1932
1933     gtk_widget_show (window);
1934
1935     /* Rest in gtk_main and wait for the fun to begin! */
1936     gtk_main ();
1937
1938     return(0);
1939 }
1940 /* example-end */
1941 </verb></tscreen>
1942
1943 The xpm_label_box function could be used to pack xpm's and labels into
1944 any widget that can be a container.
1945
1946 The Button widget has the following signals:
1947
1948 <itemize>
1949 <item> pressed
1950 <item> released
1951 <item> clicked
1952 <item> enter
1953 <item> leave
1954 </itemize>
1955
1956 <!-- ----------------------------------------------------------------- -->
1957 <sect1> Toggle Buttons
1958 <p>
1959 Toggle buttons are derived from normal buttons and are very similar,
1960 except they will always be in one of two states, alternated by a
1961 click. They may be depressed, and when you click again, they will pop
1962 back up. Click again, and they will pop back down.
1963
1964 Toggle buttons are the basis for check buttons and radio buttons, as
1965 such, many of the calls used for toggle buttons are inherited by radio
1966 and check buttons. I will point these out when we come to them.
1967
1968 Creating a new toggle button:
1969
1970 <tscreen><verb>
1971 GtkWidget *gtk_toggle_button_new( void );
1972
1973 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
1974 </verb></tscreen>
1975
1976 As you can imagine, these work identically to the normal button widget
1977 calls. The first creates a blank toggle button, and the second, a
1978 button with a label widget already packed into it.
1979
1980 To retrieve the state of the toggle widget, including radio and check
1981 buttons, we use a GTK macro as shown in our example below. This tests
1982 the state of the toggle in a callback. The signal of interest emitted
1983 to us by toggle buttons (the toggle button, check button, and radio
1984 button widgets), is the "toggled" signal. To check the state of these
1985 buttons, set up a signal handler to catch the toggled signal, and use
1986 the macro to determine its state. The callback will look something
1987 like:
1988
1989 <tscreen><verb>
1990 void toggle_button_callback (GtkWidget *widget, gpointer data)
1991 {
1992     if (GTK_TOGGLE_BUTTON (widget)->active) 
1993     {
1994         /* If control reaches here, the toggle button is down */
1995     
1996     } else {
1997     
1998         /* If control reaches here, the toggle button is up */
1999     }
2000 }
2001 </verb></tscreen>
2002
2003 <tscreen><verb>
2004 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2005                                   gint             state );
2006 </verb></tscreen>
2007
2008 The above call can be used to set the state of the toggle button, and
2009 its children the radio and check buttons. Passing in your created
2010 button as the first argument, and a TRUE or FALSE for the second state
2011 argument to specify whether it should be down (depressed) or up
2012 (released). Default is up, or FALSE.
2013
2014 Note that when you use the gtk_toggle_button_set_active() function, and
2015 the state is actually changed, it causes the "clicked" signal to be
2016 emitted from the button.
2017
2018 <tscreen><verb>
2019 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2020 </verb></tscreen>
2021
2022 This simply toggles the button, and emits the "toggled" signal.
2023
2024 <!-- ----------------------------------------------------------------- -->
2025 <sect1> Check Buttons
2026 <p>
2027 Check buttons inherent many properties and functions from the the
2028 toggle buttons above, but look a little different. Rather than being
2029 buttons with text inside them, they are small squares with the text to
2030 the right of them. These are often used for toggling options on and
2031 off in applications.
2032
2033 The two creation functions are similar to those of the normal button.
2034
2035 <tscreen><verb>
2036 GtkWidget *gtk_check_button_new( void );
2037
2038 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2039 </verb></tscreen>
2040
2041 The new_with_label function creates a check button with a label beside
2042 it.
2043
2044 Checking the state of the check button is identical to that of the
2045 toggle button.
2046
2047 <!-- ----------------------------------------------------------------- -->
2048 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2049 <p>
2050 Radio buttons are similar to check buttons except they are grouped so
2051 that only one may be selected/depressed at a time. This is good for
2052 places in your application where you need to select from a short list
2053 of options.
2054
2055 Creating a new radio button is done with one of these calls:
2056
2057 <tscreen><verb>
2058 GtkWidget *gtk_radio_button_new( GSList *group );
2059
2060 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2061                                             gchar  *label );
2062 </verb></tscreen>
2063
2064 You'll notice the extra argument to these calls. They require a group
2065 to perform their duty properly. The first call to
2066 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2067 should pass NULL as the first argument. Then create a group using:
2068
2069 <tscreen><verb>
2070 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2071 </verb></tscreen>
2072
2073 The important thing to remember is that gtk_radio_button_group must be
2074 called for each new button added to the group, with the previous
2075 button passed in as an argument. The result is then passed into the
2076 call to gtk_radio_button_new or gtk_radio_button_new_with_label. This
2077 allows a chain of buttons to be established. The example below should
2078 make this clear.
2079
2080 You can shorten this slightly by using the following syntax, which
2081 removes the need for a variable to hold the list of buttons. This form
2082 is used in the example to create the third button:
2083
2084 <tscreen><verb>
2085      button2 = gtk_radio_button_new_with_label(
2086                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2087                  "button2");
2088 </verb></tscreen>
2089
2090 It is also a good idea to explicitly set which button should be the
2091 default depressed button with:
2092
2093 <tscreen><verb>
2094 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2095                                   gint             state );
2096 </verb></tscreen>
2097
2098 This is described in the section on toggle buttons, and works in
2099 exactly the same way.
2100
2101 The following example creates a radio button group with three buttons.
2102
2103 <tscreen><verb>
2104 /* example-start radiobuttons radiobuttons.c */
2105
2106 #include <gtk/gtk.h>
2107 #include <glib.h>
2108
2109 void close_application( GtkWidget *widget,
2110                         GdkEvent  *event,
2111                         gpointer   data )
2112 {
2113   gtk_main_quit();
2114 }
2115
2116 int main( int   argc,
2117           char *argv[] )
2118 {
2119     GtkWidget *window = NULL;
2120     GtkWidget *box1;
2121     GtkWidget *box2;
2122     GtkWidget *button;
2123     GtkWidget *separator;
2124     GSList *group;
2125   
2126     gtk_init(&amp;argc,&amp;argv);    
2127       
2128     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2129   
2130     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2131                         GTK_SIGNAL_FUNC(close_application),
2132                         NULL);
2133
2134     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2135     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2136
2137     box1 = gtk_vbox_new (FALSE, 0);
2138     gtk_container_add (GTK_CONTAINER (window), box1);
2139     gtk_widget_show (box1);
2140
2141     box2 = gtk_vbox_new (FALSE, 10);
2142     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2143     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2144     gtk_widget_show (box2);
2145
2146     button = gtk_radio_button_new_with_label (NULL, "button1");
2147     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2148     gtk_widget_show (button);
2149
2150     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2151     button = gtk_radio_button_new_with_label(group, "button2");
2152     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2153     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2154     gtk_widget_show (button);
2155
2156     button = gtk_radio_button_new_with_label(
2157                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2158                  "button3");
2159     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2160     gtk_widget_show (button);
2161
2162     separator = gtk_hseparator_new ();
2163     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2164     gtk_widget_show (separator);
2165
2166     box2 = gtk_vbox_new (FALSE, 10);
2167     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2168     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2169     gtk_widget_show (box2);
2170
2171     button = gtk_button_new_with_label ("close");
2172     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2173                                GTK_SIGNAL_FUNC(close_application),
2174                                GTK_OBJECT (window));
2175     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2176     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2177     gtk_widget_grab_default (button);
2178     gtk_widget_show (button);
2179     gtk_widget_show (window);
2180      
2181     gtk_main();
2182
2183     return(0);
2184 }
2185 /* example-end */
2186 </verb></tscreen>
2187
2188 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2189
2190 <!-- ***************************************************************** -->
2191 <sect> Adjustments <label id="sec_Adjustment">
2192 <!-- ***************************************************************** -->
2193 <p>
2194 GTK+ has various widgets that can be visually adjusted by the user
2195 using the mouse or the keyboard, such as the range widgets, described
2196 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2197 section. There are also a few widgets that display some adjustable
2198 portion of a larger area of data, such as the text widget and the
2199 viewport widget.
2200
2201 Obviously, an application needs to be able to react to changes the
2202 user makes in range widgets. One way to do this would be to have each
2203 widget emit its own type of signal when its adjustment changes, and
2204 either pass the new value to the signal handler, or require it to look
2205 inside the widget's data structure in order to ascertain the value.
2206 But you may also want to connect the adjustments of several widgets
2207 together, so that adjusting one adjusts the others. The most obvious
2208 example of this is connecting a scrollbar to a panning viewport or a
2209 scrolling text area. If each widget has its own way of setting or
2210 getting the adjustment value, then the programmer may have to write
2211 their own signal handlers to translate between the output of one
2212 widget's signal and the "input" of another's adjustment setting
2213 function.
2214
2215 GTK+ solves this problem using the GtkAdjustment object, which is a
2216 way for widgets to store and pass adjustment information in an
2217 abstract and flexible form. The most obvious use of GtkAdjustment is
2218 to store the configuration parameters and values of range widgets,
2219 such as scrollbars and scale controls. However, since GtkAdjustments
2220 are derived from GtkObject, they have some special powers beyond those
2221 of normal data structures. Most importantly, they can emit signals,
2222 just like widgets, and these signals can be used not only to allow
2223 your program to react to user input on adjustable widgets, but also to
2224 propagate adjustment values transparently between adjustable widgets.
2225
2226 <sect1> Creating an Adjustment
2227 <p>
2228 You create an adjustment using:
2229
2230 <tscreen><verb>
2231 GtkObject *gtk_adjustment_new( gfloat value,
2232                                gfloat lower,
2233                                gfloat upper,
2234                                gfloat step_increment,
2235                                gfloat page_increment,
2236                                gfloat page_size );
2237 </verb></tscreen>
2238
2239 The <tt/value/ argument is the initial value you want to give to the
2240 adjustment, usually corresponding to the topmost or leftmost position
2241 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2242 value which the adjustment can hold. The <tt/step_increment/ argument
2243 specifies the "smaller" of the two increments by which the user can
2244 change the value, while the <tt/page_increment/ is the "larger" one.
2245 The <tt/page_size/ argument usually corresponds somehow to the visible
2246 area of a panning widget. The <tt/upper/ argument is used to represent
2247 the bottom most or right most coordinate in a panning widget's
2248 child. Therefore it is <em/not/ always the largest number that
2249 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2250 usually non-zero.
2251
2252 <!-- ----------------------------------------------------------------- -->
2253 <sect1> Using Adjustments the Easy Way
2254 <p>
2255 The adjustable widgets can be roughly divided into those which use and
2256 require specific units for these values and those which treat them as
2257 arbitrary numbers. The group which treats the values as arbitrary
2258 numbers includes the range widgets (scrollbars and scales, the
2259 progress bar widget, and the spin button widget). These widgets are
2260 all the widgets which are typically "adjusted" directly by the user
2261 with the mouse or keyboard. They will treat the <tt/lower/ and
2262 <tt/upper/ values of an adjustment as a range within which the user
2263 can manipulate the adjustment's <tt/value/. By default, they will only
2264 modify the <tt/value/ of an adjustment.
2265
2266 The other group includes the text widget, the viewport widget, the
2267 compound list widget, and the scrolled window widget. All of these
2268 widgets use pixel values for their adjustments. These are also all
2269 widgets which are typically "adjusted" indirectly using scrollbars.
2270 While all widgets which use adjustments can either create their own
2271 adjustments or use ones you supply, you'll generally want to let this
2272 particular category of widgets create its own adjustments. Usually,
2273 they will eventually override all the values except the <tt/value/
2274 itself in whatever adjustments you give them, but the results are, in
2275 general, undefined (meaning, you'll have to read the source code to
2276 find out, and it may be different from widget to widget).
2277
2278 Now, you're probably thinking, since text widgets and viewports insist
2279 on setting everything except the <tt/value/ of their adjustments,
2280 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2281 you <em/share/ an adjustment object between a scrollbar and a text
2282 widget, manipulating the scrollbar will automagically adjust the text
2283 widget?  Of course it will! Just like this:
2284
2285 <tscreen><verb>
2286   /* creates its own adjustments */
2287   text = gtk_text_new (NULL, NULL);
2288   /* uses the newly-created adjustment for the scrollbar as well */
2289   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2290 </verb></tscreen>
2291
2292 </sect1>
2293 <!-- ----------------------------------------------------------------- -->
2294 <sect1> Adjustment Internals
2295 <p>
2296 Ok, you say, that's nice, but what if I want to create my own handlers
2297 to respond when the user adjusts a range widget or a spin button, and
2298 how do I get at the value of the adjustment in these handlers?  To
2299 answer these questions and more, let's start by taking a look at
2300 <tt>struct _GtkAdjustment</tt> itself:
2301
2302 <tscreen><verb>
2303 struct _GtkAdjustment
2304 {
2305   GtkData data;
2306   
2307   gfloat lower;
2308   gfloat upper;
2309   gfloat value;
2310   gfloat step_increment;
2311   gfloat page_increment;
2312   gfloat page_size;
2313 };     
2314 </verb></tscreen>
2315
2316 The first thing you should know is that there aren't any handy-dandy
2317 macros or accessor functions for getting the <tt/value/ out of a
2318 GtkAdjustment, so you'll have to (horror of horrors) do it like a
2319 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2320 (Object)</tt> macro does run-time type checking (as do all the GTK+
2321 type-casting macros, actually).
2322
2323 Since, when you set the <tt/value/ of an adjustment, you generally
2324 want the change to be reflected by every widget that uses this
2325 adjustment, GTK+ provides this convenience function to do this:
2326
2327 <tscreen><verb>
2328 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2329                                gfloat         value );
2330 </verb></tscreen>
2331
2332 As mentioned earlier, GtkAdjustment is a subclass of GtkObject just
2333 like all the various widgets, and thus it is able to emit signals.
2334 This is, of course, why updates happen automagically when you share an
2335 adjustment object between a scrollbar and another adjustable widget;
2336 all adjustable widgets connect signal handlers to their adjustment's
2337 <tt/value_changed/ signal, as can your program. Here's the definition
2338 of this signal in <tt/struct _GtkAdjustmentClass/:
2339
2340 <tscreen><verb>
2341   void (* value_changed) (GtkAdjustment *adjustment);
2342 </verb></tscreen>
2343
2344 The various widgets that use the GtkAdjustment object will emit this
2345 signal on an adjustment whenever they change its value. This happens
2346 both when user input causes the slider to move on a range widget, as
2347 well as when the program explicitly changes the value with
2348 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2349 widget, and you want to change the rotation of a picture whenever its
2350 value changes, you would create a callback like this:
2351
2352 <tscreen><verb>
2353 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2354 {
2355   set_picture_rotation (picture, adj->value);
2356 ...
2357 </verb></tscreen>
2358
2359 and connect it to the scale widget's adjustment like this:
2360
2361 <tscreen><verb>
2362 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2363                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2364 </verb></tscreen>
2365
2366 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2367 fields of its adjustment, such as when a user adds more text to a text
2368 widget?  In this case, it emits the <tt/changed/ signal, which looks
2369 like this:
2370
2371 <tscreen><verb>
2372   void (* changed)       (GtkAdjustment *adjustment);
2373 </verb></tscreen>
2374
2375 Range widgets typically connect a handler to this signal, which
2376 changes their appearance to reflect the change - for example, the size
2377 of the slider in a scrollbar will grow or shrink in inverse proportion
2378 to the difference between the <tt/lower/ and <tt/upper/ values of its
2379 adjustment.
2380
2381 You probably won't ever need to attach a handler to this signal,
2382 unless you're writing a new type of range widget.  However, if you
2383 change any of the values in a GtkAdjustment directly, you should emit
2384 this signal on it to reconfigure whatever widgets are using it, like
2385 this:
2386
2387 <tscreen><verb>
2388 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2389 </verb></tscreen>
2390
2391 Now go forth and adjust!
2392 </sect1>
2393 </sect>
2394
2395 <!-- ***************************************************************** -->
2396 <sect> Range Widgets<label id="sec_Range_Widgets">
2397 <!-- ***************************************************************** -->
2398
2399 <p>
2400 The category of range widgets includes the ubiquitous scrollbar widget
2401 and the less common "scale" widget. Though these two types of widgets
2402 are generally used for different purposes, they are quite similar in
2403 function and implementation. All range widgets share a set of common
2404 graphic elements, each of which has its own X window and receives
2405 events. They all contain a "trough" and a "slider" (what is sometimes
2406 called a "thumbwheel" in other GUI environments). Dragging the slider
2407 with the pointer moves it back and forth within the trough, while
2408 clicking in the trough advances the slider towards the location of the
2409 click, either completely, or by a designated amount, depending on
2410 which mouse button is used.
2411
2412 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2413 all range widgets are associated with an adjustment object, from which
2414 they calculate the length of the slider and it's position within the
2415 trough. When the user manipulates the slider, the range widget will
2416 change the value of the adjustment.
2417
2418 <!-- ----------------------------------------------------------------- -->
2419 <sect1> Scrollbar Widgets
2420 <p>
2421 These are your standard, run-of-the-mill scrollbars. These should be
2422 used only for scrolling some other widget, such as a list, a text box,
2423 or a viewport (and it's generally easier to use the scrolled window
2424 widget in most cases).  For other purposes, you should use scale
2425 widgets, as they are friendlier and more featureful.
2426
2427 There are separate types for horizontal and vertical scrollbars.
2428 There really isn't much to say about these. You create them with the
2429 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2430 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2431
2432 <tscreen><verb>
2433 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2434
2435 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2436 </verb></tscreen>
2437
2438 and that's about it (if you don't believe me, look in the header
2439 files!).  The <tt/adjustment/ argument can either be a pointer to an
2440 existing GtkAdjustment, or NULL, in which case one will be created for
2441 you. Specifying NULL might actually be useful in this case, if you
2442 wish to pass the newly-created adjustment to the constructor function
2443 of some other widget which will configure it for you, such as a text
2444 widget.
2445 </sect1>
2446
2447 <!-- ----------------------------------------------------------------- -->
2448 <sect1> Scale Widgets
2449 <p>
2450 Scale widgets are used to allow the user to visually select and
2451 manipulate a value within a specific range. You might want to use a
2452 scale widget, for example, to adjust the magnification level on a
2453 zoomed preview of a picture, or to control the brightness of a colour,
2454 or to specify the number of minutes of inactivity before a screensaver
2455 takes over the screen.
2456
2457 <!-- ----------------------------------------------------------------- -->
2458 <sect2>Creating a Scale Widget
2459 <p>
2460 As with scrollbars, there are separate widget types for horizontal and
2461 vertical scale widgets. (Most programmers seem to favour horizontal
2462 scale widgets). Since they work essentially the same way, there's no
2463 need to treat them separately here. The following functions, defined
2464 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2465 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2466 widgets, respectively:
2467
2468 <tscreen>
2469 <verb>
2470 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2471
2472 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2473 </verb>
2474 </tscreen>
2475
2476 The <tt/adjustment/ argument can either be an adjustment which has
2477 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2478 which case, an anonymous GtkAdjustment is created with all of its
2479 values set to <tt/0.0/ (which isn't very useful in this case). In
2480 order to avoid confusing yourself, you probably want to create your
2481 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2482 value actually corresponds to the highest value the user can select.
2483 (If you're <em/already/ thoroughly confused, read the section on <ref
2484 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2485 what exactly adjustments do and how to create and manipulate them).
2486
2487 <!-- ----------------------------------------------------------------- -->
2488 <sect2> Functions and Signals (well, functions, at least)
2489 <p>
2490 Scale widgets can display their current value as a number beside the
2491 trough. The default behaviour is to show the value, but you can change
2492 this with this function:
2493
2494 <tscreen><verb>
2495 void gtk_scale_set_draw_value( GtkScale *scale,
2496                                gint      draw_value );
2497 </verb></tscreen>
2498
2499 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2500 <tt/FALSE/, with predictable consequences for either one.
2501
2502 The value displayed by a scale widget is rounded to one decimal point
2503 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2504 change this with:
2505
2506 <tscreen>
2507 <verb>
2508 void gtk_scale_set_digits( GtkScale *scale,
2509                             gint     digits );
2510 </verb>
2511 </tscreen>
2512
2513 where <tt/digits/ is the number of decimal places you want. You can
2514 set <tt/digits/ to anything you like, but no more than 13 decimal
2515 places will actually be drawn on screen.
2516
2517 Finally, the value can be drawn in different positions
2518 relative to the trough:
2519
2520 <tscreen>
2521 <verb>
2522 void gtk_scale_set_value_pos( GtkScale        *scale,
2523                               GtkPositionType  pos );
2524 </verb>
2525 </tscreen>
2526
2527 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2528 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2529 following values:
2530
2531 <itemize>
2532 <item> GTK_POS_LEFT
2533 <item> GTK_POS_RIGHT
2534 <item> GTK_POS_TOP
2535 <item> GTK_POS_BOTTOM
2536 </itemize>
2537
2538 If you position the value on the "side" of the trough (e.g. on the top
2539 or bottom of a horizontal scale widget), then it will follow the
2540 slider up and down the trough.
2541
2542 All the preceding functions are defined in
2543 <tt>&lt;gtk/gtkscale.h&gt;</tt>.
2544 </sect2>
2545 </sect1>
2546
2547 <!-- ----------------------------------------------------------------- -->
2548 <sect1> Common Functions <label id="sec_Range_Functions">
2549 <p>
2550 The GtkRange widget class is fairly complicated internally, but, like
2551 all the "base class" widgets, most of its complexity is only
2552 interesting if you want to hack on it. Also, almost all of the
2553 functions and signals it defines are only really used in writing
2554 derived widgets. There are, however, a few useful functions that are
2555 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2556 widgets.
2557
2558 <!-- ----------------------------------------------------------------- -->
2559 <sect2> Setting the Update Policy
2560 <p>
2561 The "update policy" of a range widget defines at what points during
2562 user interaction it will change the <tt/value/ field of its
2563 GtkAdjustment and emit the "value_changed" signal on this
2564 GtkAdjustment. The update policies, defined in
2565 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2566 are:
2567
2568 <itemize>
2569 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2570 "value_changed" signal is emitted continuously, i.e. whenever the
2571 slider is moved by even the tiniest amount.
2572 </item>
2573 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2574 only emitted once the slider has stopped moving and the user has
2575 released the mouse button.
2576 </item>
2577 <item>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emitted
2578 when the user releases the mouse button, or if the slider stops moving
2579 for a short period of time.
2580 </item>
2581 </itemize>
2582
2583 The update policy of a range widget can be set by casting it using the
2584 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2585
2586 <tscreen><verb>
2587 void gtk_range_set_update_policy( GtkRange      *range,
2588                                   GtkUpdateType  policy) ;
2589 </verb></tscreen>
2590
2591 <!-- ----------------------------------------------------------------- -->
2592 <sect2>Getting and Setting Adjustments
2593 <p>
2594 Getting and setting the adjustment for a range widget "on the fly" is
2595 done, predictably, with:
2596
2597 <tscreen><verb>
2598 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2599
2600 void gtk_range_set_adjustment( GtkRange      *range,
2601                                GtkAdjustment *adjustment );
2602 </verb></tscreen>
2603
2604 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2605 which <tt/range/ is connected.
2606
2607 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2608 the adjustment that <tt/range/ is already using, regardless of whether
2609 you changed any of its fields or not. If you pass it a new
2610 GtkAdjustment, it will unreference the old one if it exists (possibly
2611 destroying it), connect the appropriate signals to the new one, and
2612 call the private function <tt/gtk_range_adjustment_changed()/, which
2613 will (or at least, is supposed to...) recalculate the size and/or
2614 position of the slider and redraw if necessary. As mentioned in the
2615 section on adjustments, if you wish to reuse the same GtkAdjustment,
2616 when you modify its values directly, you should emit the "changed"
2617 signal on it, like this:
2618
2619 <tscreen><verb>
2620 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2621 </verb></tscreen>
2622 </sect2>
2623 </sect1>
2624
2625 <!-- ----------------------------------------------------------------- -->
2626 <sect1> Key and Mouse bindings
2627 <p>
2628 All of the GTK+ range widgets react to mouse clicks in more or less
2629 the same way. Clicking button-1 in the trough will cause its
2630 adjustment's <tt/page_increment/ to be added or subtracted from its
2631 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2632 button-2 in the trough will jump the slider to the point at which the
2633 button was clicked. Clicking any button on a scrollbar's arrows will
2634 cause its adjustment's value to change <tt/step_increment/ at a time.
2635
2636 It may take a little while to get used to, but by default, scrollbars
2637 as well as scale widgets can take the keyboard focus in GTK+. If you
2638 think your users will find this too confusing, you can always disable
2639 this by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:
2640
2641 <tscreen><verb>
2642 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2643 </verb></tscreen>
2644
2645 The key bindings (which are, of course, only active when the widget
2646 has focus) are slightly different between horizontal and vertical
2647 range widgets, for obvious reasons. They are also not quite the same
2648 for scale widgets as they are for scrollbars, for somewhat less
2649 obvious reasons (possibly to avoid confusion between the keys for
2650 horizontal and vertical scrollbars in scrolled windows, where both
2651 operate on the same area).
2652
2653 <sect2> Vertical Range Widgets
2654 <p>
2655 All vertical range widgets can be operated with the up and down arrow
2656 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2657 arrows move the slider up and down by <tt/step_increment/, while
2658 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2659
2660 The user can also move the slider all the way to one end or the other
2661 of the trough using the keyboard. With the GtkVScale widget, this is
2662 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2663 GtkVScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2664 and <tt>Control-Page Down</tt>.
2665
2666 <!-- ----------------------------------------------------------------- -->
2667 <sect2> Horizontal Range Widgets
2668 <p>
2669 The left and right arrow keys work as you might expect in these
2670 widgets, moving the slider back and forth by <tt/step_increment/. The
2671 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2672 For the GtkHScale widget, moving the slider by <tt/page_increment/ is
2673 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2674 while for GtkHScrollbar, it's done with <tt>Control-Home</tt> and
2675 <tt>Control-End</tt>.
2676 </sect2>
2677 </sect1>
2678
2679 <!-- ----------------------------------------------------------------- -->
2680 <sect1> Example<label id="sec_Range_Example">
2681 <p>
2682 This example is a somewhat modified version of the "range controls"
2683 test from <tt/testgtk.c/. It basically puts up a window with three
2684 range widgets all connected to the same adjustment, and a couple of
2685 controls for adjusting some of the parameters mentioned above and in
2686 the seciton on adjustments, so you can see how they affect the way
2687 these widgets work for the user.
2688
2689 <tscreen><verb>
2690 /* example-start rangewidgets rangewidgets.c */
2691
2692 #include <gtk/gtk.h>
2693
2694 GtkWidget *hscale, *vscale;
2695
2696 void cb_pos_menu_select( GtkWidget       *item,
2697                          GtkPositionType  pos )
2698 {
2699     /* Set the value position on both scale widgets */
2700     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2701     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2702 }
2703
2704 void cb_update_menu_select( GtkWidget     *item,
2705                             GtkUpdateType  policy )
2706 {
2707     /* Set the update policy for both scale widgets */
2708     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2709     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2710 }
2711
2712 void cb_digits_scale( GtkAdjustment *adj )
2713 {
2714     /* Set the number of decimal places to which adj->value is rounded */
2715     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2716     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2717 }
2718
2719 void cb_page_size( GtkAdjustment *get,
2720                    GtkAdjustment *set )
2721 {
2722     /* Set the page size and page increment size of the sample
2723      * adjustment to the value specified by the "Page Size" scale */
2724     set->page_size = get->value;
2725     set->page_increment = get->value;
2726     /* Now emit the "changed" signal to reconfigure all the widgets that
2727      * are attached to this adjustment */
2728     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2729 }
2730
2731 void cb_draw_value( GtkToggleButton *button )
2732 {
2733     /* Turn the value display on the scale widgets off or on depending
2734      *  on the state of the checkbutton */
2735     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2736     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2737 }
2738
2739 /* Convenience functions */
2740
2741 GtkWidget *make_menu_item( gchar         *name,
2742                            GtkSignalFunc  callback,
2743                            gpointer       data )
2744 {
2745     GtkWidget *item;
2746   
2747     item = gtk_menu_item_new_with_label (name);
2748     gtk_signal_connect (GTK_OBJECT (item), "activate",
2749                         callback, data);
2750     gtk_widget_show (item);
2751
2752     return(item);
2753 }
2754
2755 void scale_set_default_values( GtkScale *scale )
2756 {
2757     gtk_range_set_update_policy (GTK_RANGE (scale),
2758                                  GTK_UPDATE_CONTINUOUS);
2759     gtk_scale_set_digits (scale, 1);
2760     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2761     gtk_scale_set_draw_value (scale, TRUE);
2762 }
2763
2764 /* makes the sample window */
2765
2766 void create_range_controls( void )
2767 {
2768     GtkWidget *window;
2769     GtkWidget *box1, *box2, *box3;
2770     GtkWidget *button;
2771     GtkWidget *scrollbar;
2772     GtkWidget *separator;
2773     GtkWidget *opt, *menu, *item;
2774     GtkWidget *label;
2775     GtkWidget *scale;
2776     GtkObject *adj1, *adj2;
2777
2778     /* Standard window-creating stuff */
2779     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2780     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2781                         GTK_SIGNAL_FUNC(gtk_main_quit),
2782                         NULL);
2783     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2784
2785     box1 = gtk_vbox_new (FALSE, 0);
2786     gtk_container_add (GTK_CONTAINER (window), box1);
2787     gtk_widget_show (box1);
2788
2789     box2 = gtk_hbox_new (FALSE, 10);
2790     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2791     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2792     gtk_widget_show (box2);
2793
2794     /* calue, lower, upper, step_increment, page_increment, page_size */
2795     /* Note that the page_size value only makes a difference for
2796      * scrollbar widgets, and the highest value you'll get is actually
2797      * (upper - page_size). */
2798     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2799   
2800     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2801     scale_set_default_values (GTK_SCALE (vscale));
2802     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2803     gtk_widget_show (vscale);
2804
2805     box3 = gtk_vbox_new (FALSE, 10);
2806     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2807     gtk_widget_show (box3);
2808
2809     /* Reuse the same adjustment */
2810     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2811     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2812     scale_set_default_values (GTK_SCALE (hscale));
2813     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2814     gtk_widget_show (hscale);
2815
2816     /* Reuse the same adjustment again */
2817     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2818     /* Notice how this causes the scales to always be updated
2819      * continuously when the scrollbar is moved */
2820     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2821                                  GTK_UPDATE_CONTINUOUS);
2822     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2823     gtk_widget_show (scrollbar);
2824
2825     box2 = gtk_hbox_new (FALSE, 10);
2826     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2827     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2828     gtk_widget_show (box2);
2829
2830     /* A checkbutton to control whether the value is displayed or not */
2831     button = gtk_check_button_new_with_label("Display value on scale widgets");
2832     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2833     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2834                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2835     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2836     gtk_widget_show (button);
2837   
2838     box2 = gtk_hbox_new (FALSE, 10);
2839     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2840
2841     /* An option menu to change the position of the value */
2842     label = gtk_label_new ("Scale Value Position:");
2843     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2844     gtk_widget_show (label);
2845   
2846     opt = gtk_option_menu_new();
2847     menu = gtk_menu_new();
2848
2849     item = make_menu_item ("Top",
2850                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2851                            GINT_TO_POINTER (GTK_POS_TOP));
2852     gtk_menu_append (GTK_MENU (menu), item);
2853   
2854     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2855                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2856     gtk_menu_append (GTK_MENU (menu), item);
2857   
2858     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2859                            GINT_TO_POINTER (GTK_POS_LEFT));
2860     gtk_menu_append (GTK_MENU (menu), item);
2861   
2862     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2863                             GINT_TO_POINTER (GTK_POS_RIGHT));
2864     gtk_menu_append (GTK_MENU (menu), item);
2865   
2866     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2867     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2868     gtk_widget_show (opt);
2869
2870     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2871     gtk_widget_show (box2);
2872
2873     box2 = gtk_hbox_new (FALSE, 10);
2874     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2875
2876     /* Yet another option menu, this time for the update policy of the
2877      * scale widgets */
2878     label = gtk_label_new ("Scale Update Policy:");
2879     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2880     gtk_widget_show (label);
2881   
2882     opt = gtk_option_menu_new();
2883     menu = gtk_menu_new();
2884   
2885     item = make_menu_item ("Continuous",
2886                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2887                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2888     gtk_menu_append (GTK_MENU (menu), item);
2889   
2890     item = make_menu_item ("Discontinuous",
2891                             GTK_SIGNAL_FUNC (cb_update_menu_select),
2892                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2893     gtk_menu_append (GTK_MENU (menu), item);
2894   
2895     item = make_menu_item ("Delayed",
2896                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2897                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2898     gtk_menu_append (GTK_MENU (menu), item);
2899   
2900     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2901     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2902     gtk_widget_show (opt);
2903   
2904     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2905     gtk_widget_show (box2);
2906
2907     box2 = gtk_hbox_new (FALSE, 10);
2908     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2909   
2910     /* A GtkHScale widget for adjusting the number of digits on the
2911      * sample scales. */
2912     label = gtk_label_new ("Scale Digits:");
2913     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2914     gtk_widget_show (label);
2915
2916     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
2917     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2918                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
2919     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2920     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2921     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2922     gtk_widget_show (scale);
2923
2924     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2925     gtk_widget_show (box2);
2926   
2927     box2 = gtk_hbox_new (FALSE, 10);
2928     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2929   
2930     /* And, one last GtkHScale widget for adjusting the page size of the
2931      * scrollbar. */
2932     label = gtk_label_new ("Scrollbar Page Size:");
2933     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2934     gtk_widget_show (label);
2935
2936     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
2937     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2938                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
2939     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2940     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2941     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2942     gtk_widget_show (scale);
2943
2944     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2945     gtk_widget_show (box2);
2946
2947     separator = gtk_hseparator_new ();
2948     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2949     gtk_widget_show (separator);
2950
2951     box2 = gtk_vbox_new (FALSE, 10);
2952     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2953     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2954     gtk_widget_show (box2);
2955
2956     button = gtk_button_new_with_label ("Quit");
2957     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2958                                GTK_SIGNAL_FUNC(gtk_main_quit),
2959                                NULL);
2960     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2961     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2962     gtk_widget_grab_default (button);
2963     gtk_widget_show (button);
2964
2965     gtk_widget_show (window);
2966 }
2967
2968 int main( int   argc,
2969           char *argv[] )
2970 {
2971     gtk_init(&amp;argc, &amp;argv);
2972
2973     create_range_controls();
2974
2975     gtk_main();
2976
2977     return(0);
2978 }
2979
2980 /* example-end */
2981 </verb></tscreen>
2982 </sect1>
2983 </sect>
2984
2985 <!-- ***************************************************************** -->
2986 <sect> Miscellaneous Widgets
2987 <!-- ***************************************************************** -->
2988
2989 <!-- ----------------------------------------------------------------- -->
2990 <sect1> Labels
2991 <p>
2992 Labels are used a lot in GTK, and are relatively simple. Labels emit
2993 no signals as they do not have an associated X window. If you need to
2994 catch signals, or do clipping, use the <ref id="sec_EventBox"
2995 name="EventBox"> widget.
2996
2997 To create a new label, use:
2998
2999 <tscreen><verb>
3000 GtkWidget *gtk_label_new( char *str );
3001 </verb></tscreen>
3002
3003 Where the sole argument is the string you wish the label to display.
3004
3005 To change the label's text after creation, use the function:
3006
3007 <tscreen><verb>
3008 void gtk_label_set_text( GtkLabel *label,
3009                          char     *str );
3010 </verb></tscreen>
3011
3012 Where the first argument is the label you created previously (cast
3013 using the GTK_LABEL() macro), and the second is the new string.
3014
3015 The space needed for the new string will be automatically adjusted if
3016 needed. You can produce multi-line labels by putting line breaks in
3017 the label string.
3018
3019 To retrieve the current string, use:
3020
3021 <tscreen><verb>
3022 void gtk_label_get( GtkLabel  *label,
3023                     char     **str );
3024 </verb></tscreen>
3025
3026 Where the first argument is the label you've created, and the second,
3027 the return for the string. Do not free the return string, as it is
3028 used internally by GTK.
3029
3030 The label text can be justified using:
3031
3032 <tscreen><verb>
3033 void gtk_label_set_justify( GtkLabel         *label,
3034                             GtkJustification  jtype );
3035 </verb></tscreen>
3036
3037 Values for <tt/jtype/ are:
3038 <itemize>
3039 <item> GTK_JUSTIFY_LEFT
3040 <item> GTK_JUSTIFY_RIGHT
3041 <item> GTK_JUSTIFY_CENTER (the default)
3042 <item> GTK_JUSTIFY_FILL
3043 </itemize>
3044
3045 The label widget is also capable of line wrapping the text
3046 automatically. This can be activated using:
3047
3048 <tscreen><verb>
3049 void gtk_label_set_line_wrap (GtkLabel *label,
3050                               gboolean  wrap);
3051 </verb></tscreen>
3052
3053 The <//wrap/ argument takes a TRUE or FALSE value.
3054
3055 If you want your label underlined, then you can set a pattern on the
3056 label:
3057
3058 <tscreen><verb>
3059 void       gtk_label_set_pattern   (GtkLabel          *label,
3060                                     const gchar       *pattern);
3061 </verb></tscreen>
3062
3063 The pattern argument indicates how the underlining should look. It
3064 consists of a string of underscore and space characters. An underscore
3065 indicates that the corresponding character in the label should be
3066 underlined. For example, the string <verb/"__     __"/ would underline the
3067 first two characters and eigth and ninth characters.
3068
3069 Below is a short example to illustrate these functions. This example
3070 makes use of the Frame widget to better demonstrate the label
3071 styles. You can ignore this for now as the <ref id="sec_Frames"
3072 name="Frame"> widget is explained later on.
3073
3074 <tscreen><verb>
3075 /* example-start label label.c */
3076
3077 #include <gtk/gtk.h>
3078
3079 int main( int   argc,
3080           char *argv[] )
3081 {
3082   static GtkWidget *window = NULL;
3083   GtkWidget *hbox;
3084   GtkWidget *vbox;
3085   GtkWidget *frame;
3086   GtkWidget *label;
3087
3088   /* Initialise GTK */
3089   gtk_init(&amp;argc, &amp;argv);
3090
3091   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3092   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3093                       GTK_SIGNAL_FUNC(gtk_main_quit),
3094                       NULL);
3095
3096   gtk_window_set_title (GTK_WINDOW (window), "Label");
3097   vbox = gtk_vbox_new (FALSE, 5);
3098   hbox = gtk_hbox_new (FALSE, 5);
3099   gtk_container_add (GTK_CONTAINER (window), hbox);
3100   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3101   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3102   
3103   frame = gtk_frame_new ("Normal Label");
3104   label = gtk_label_new ("This is a Normal label");
3105   gtk_container_add (GTK_CONTAINER (frame), label);
3106   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3107   
3108   frame = gtk_frame_new ("Multi-line Label");
3109   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3110                          "Third line");
3111   gtk_container_add (GTK_CONTAINER (frame), label);
3112   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3113   
3114   frame = gtk_frame_new ("Left Justified Label");
3115   label = gtk_label_new ("This is a Left-Justified\n" \
3116                          "Multi-line label.\nThird      line");
3117   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3118   gtk_container_add (GTK_CONTAINER (frame), label);
3119   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3120   
3121   frame = gtk_frame_new ("Right Justified Label");
3122   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3123                          "Fourth line, (j/k)");
3124   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3125   gtk_container_add (GTK_CONTAINER (frame), label);
3126   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3127
3128   vbox = gtk_vbox_new (FALSE, 5);
3129   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3130   frame = gtk_frame_new ("Line wrapped label");
3131   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3132                          "should not be taking up the entire             " /* big space to test spacing */\
3133                          "width allocated to it, but automatically " \
3134                          "wraps the words to fit.  " \
3135                          "The time has come, for all good men, to come to " \
3136                          "the aid of their party.  " \
3137                          "The sixth sheik's six sheep's sick.\n" \
3138                          "     It supports multiple paragraphs correctly, " \
3139                          "and  correctly   adds "\
3140                          "many          extra  spaces. ");
3141   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3142   gtk_container_add (GTK_CONTAINER (frame), label);
3143   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3144   
3145   frame = gtk_frame_new ("Filled, wrapped label");
3146   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3147                          "It should be taking "\
3148                          "up the entire              width allocated to it.  " \
3149                          "Here is a seneance to prove "\
3150                          "my point.  Here is another sentence. "\
3151                          "Here comes the sun, do de do de do.\n"\
3152                          "    This is a new paragraph.\n"\
3153                          "    This is another newer, longer, better " \
3154                          "paragraph.  It is coming to an end, "\
3155                          "unfortunately.");
3156   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3157   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3158   gtk_container_add (GTK_CONTAINER (frame), label);
3159   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3160   
3161   frame = gtk_frame_new ("Underlined label");
3162   label = gtk_label_new ("This label is underlined!\n"
3163                          "This one is underlined in quite a funky fashion");
3164   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3165   gtk_label_set_pattern (GTK_LABEL (label),
3166                          "_________________________ _ _________ _ ______     __ _______ ___");
3167   gtk_container_add (GTK_CONTAINER (frame), label);
3168   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3169   
3170   gtk_widget_show_all (window);
3171
3172   gtk_main ();
3173   
3174   return(0);
3175 }
3176 /* example-end */
3177 </verb></tscreen>
3178
3179 <!-- ----------------------------------------------------------------- -->
3180 <sect1> Arrows
3181 <p>
3182 The Arrow widget draws an arrowhead, facing in a number of possible
3183 directions and having a number of possible styles. It can be very
3184 useful when placed on a button in many applications.
3185
3186 There are only two functions for manipulating an Arrow widget:
3187
3188 <tscreen><verb>
3189 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3190                           GtkShadowType  shadow_type );
3191
3192 void gtk_arrow_set( GtkArrow      *arrow,
3193                     GtkArrowType   arrow_type,
3194                     GtkShadowType  shadow_type );
3195 </verb></tscreen>
3196
3197 The first creates a new arrow widget with the indicated type and
3198 appearance. The second allows these values to be altered
3199 retrospectively. The <tt/arrow_type/ argument may take one of the
3200 following values:
3201
3202 <itemize>
3203 <item> GTK_ARROW_UP
3204 <item> GTK_ARROW_DOWN
3205 <item> GTK_ARROW_LEFT
3206 <item> GTK_ARROW_RIGHT
3207 </itemize>
3208
3209 These values obviously indicate the direction in which the arrow will
3210 point. The <tt/shadow_type/ argument may take one of these values:
3211
3212 <itemize>
3213 <item> GTK_SHADOW_IN
3214 <item> GTK_SHADOW_OUT (the default)
3215 <item> GTK_SHADOW_ETCHED_IN
3216 <item> GTK_SHADOW_ETCHED_OUT
3217 </itemize>
3218
3219 Here's a brief example to illustrate their use.
3220
3221 <tscreen><verb>
3222 /* example-start arrow arrow.c */
3223
3224 #include <gtk/gtk.h>
3225
3226 /* Create an Arrow widget with the specified parameters
3227  * and pack it into a button */
3228 GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3229                                 GtkShadowType shadow_type )
3230 {
3231   GtkWidget *button;
3232   GtkWidget *arrow;
3233
3234   button = gtk_button_new();
3235   arrow = gtk_arrow_new (arrow_type, shadow_type);
3236
3237   gtk_container_add (GTK_CONTAINER (button), arrow);
3238   
3239   gtk_widget_show(button);
3240   gtk_widget_show(arrow);
3241
3242   return(button);
3243 }
3244
3245 int main( int   argc,
3246           char *argv[] )
3247 {
3248   /* GtkWidget is the storage type for widgets */
3249   GtkWidget *window;
3250   GtkWidget *button;
3251   GtkWidget *box;
3252
3253   /* Initialize the toolkit */
3254   gtk_init (&amp;argc, &amp;argv);
3255
3256   /* Create a new window */
3257   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3258
3259   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3260
3261   /* It's a good idea to do this for all windows. */
3262   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3263                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3264
3265   /* Sets the border width of the window. */
3266   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3267
3268   /* Create a box to hold the arrows/buttons */
3269   box = gtk_hbox_new (FALSE, 0);
3270   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3271   gtk_container_add (GTK_CONTAINER (window), box);
3272
3273   /* Pack and show all our widgets */
3274   gtk_widget_show(box);
3275
3276   button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN);
3277   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3278
3279   button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3280   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3281   
3282   button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3283   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3284   
3285   button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3286   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3287   
3288   gtk_widget_show (window);
3289   
3290   /* Rest in gtk_main and wait for the fun to begin! */
3291   gtk_main ();
3292   
3293   return(0);
3294 }
3295 /* example-end */
3296 </verb></tscreen>
3297
3298 <!-- ----------------------------------------------------------------- -->
3299 <sect1>The Tooltips Widget
3300 <p>
3301 These are the little text strings that pop up when you leave your
3302 pointer over a button or other widget for a few seconds. They are easy
3303 to use, so I will just explain them without giving an example. If you
3304 want to see some code, take a look at the testgtk.c program
3305 distributed with GTK.
3306
3307 Widgets that do not receieve events (widgets that do not have their
3308 own window) will not work with tooltips.
3309
3310 The first call you will use creates a new tooltip. You only need to do
3311 this once for a set of tooltips as the <tt/GtkTooltip/ object this
3312 function returns can be used to create multiple tooltips.
3313
3314 <tscreen><verb>
3315 GtkTooltips *gtk_tooltips_new( void );
3316 </verb></tscreen>
3317
3318 Once you have created a new tooltip, and the widget you wish to use it
3319 on, simply use this call to set it:
3320
3321 <tscreen><verb>
3322 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3323                            GtkWidget   *widget,
3324                            const gchar *tip_text,
3325                            const gchar *tip_private );
3326 </verb></tscreen>
3327
3328 The first argument is the tooltip you've already created, followed by
3329 the widget you wish to have this tooltip pop up for, and the text you
3330 wish it to say. The last argument is a text string that can be used as
3331 an identifier when using GtkTipsQuery to implement context sensitive
3332 help. For now, you can set it to NULL.
3333
3334 <!-- TODO: sort out what how to do the context sensitive help -->
3335
3336 Here's a short example:
3337
3338 <tscreen><verb>
3339 GtkTooltips *tooltips;
3340 GtkWidget *button;
3341 .
3342 .
3343 .
3344 tooltips = gtk_tooltips_new ();
3345 button = gtk_button_new_with_label ("button 1");
3346 .
3347 .
3348 .
3349 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3350 </verb></tscreen>
3351
3352 There are other calls that can be used with tooltips. I will just list
3353 them with a brief description of what they do.
3354
3355 <tscreen><verb>
3356 void gtk_tooltips_enable( GtkTooltips *tooltips );
3357 </verb></tscreen>
3358
3359 Enable a disabled set of tooltips.
3360
3361 <tscreen><verb>
3362 void gtk_tooltips_disable( GtkTooltips *tooltips );
3363 </verb></tscreen>
3364
3365 Disable an enabled set of tooltips.
3366
3367 <tscreen><verb>
3368 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3369                              gint         delay );
3370
3371 </verb></tscreen>
3372
3373 Sets how many milliseconds you have to hold your pointer over the
3374 widget before the tooltip will pop up. The default is 500
3375 milliseconds (half a second).
3376
3377 <tscreen><verb>
3378 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3379                               GdkColor    *background,
3380                               GdkColor    *foreground );
3381 </verb></tscreen>
3382
3383 Set the foreground and background color of the tooltips.
3384
3385 And that's all the functions associated with tooltips. More than
3386 you'll ever want to know :-)
3387
3388 <!-- ----------------------------------------------------------------- -->
3389 <sect1> Progress Bars <label id="sec_ProgressBar">
3390 <p>
3391 Progress bars are used to show the status of an operation. They are
3392 pretty easy to use, as you will see with the code below. But first
3393 lets start out with the calls to create a new progress bar.
3394
3395 There are two ways to create a progress bar, one simple one takes
3396 no arguments, and one that takes a GtkAdjustment object as an
3397 argument. If the former is used, the progress bar creates it's own
3398 adjustment object.
3399
3400 <tscreen><verb>
3401 GtkWidget *gtk_progress_bar_new( void );
3402
3403 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3404 </verb></tscreen>
3405
3406 The second method has the advantage that we can use the adjustment
3407 object to specify our own range parameters for the progress bar.
3408
3409 Now that the progress bar has been created we can use it.
3410
3411 <tscreen><verb>
3412 void gtk_progress_bar_update( GtkProgressBar *pbar,
3413                               gfloat          percentage );
3414 </verb></tscreen>
3415
3416 The first argument is the progress bar you wish to operate on, and the
3417 second argument is the amount 'completed', meaning the amount the
3418 progress bar has been filled from 0-100%. This is passed to the
3419 function as a real number ranging from 0 to 1.
3420
3421 GTK v1.1 has added new functionality to the progress bar that enables
3422 it to display it's value in different ways, and to inform the user of
3423 its current value and its range.
3424
3425 A progress bar may be set to one of a number of orientations using the
3426 function
3427
3428 <tscreen><verb>
3429 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3430                                        GtkProgressBarOrientation orientation );
3431 </verb></tscreen>
3432
3433 Where the <tt/orientation/ argument may take one of the following
3434 values to indicate the direction in which the progress bar moves:
3435
3436 <itemize>
3437 <item> GTK_PROGRESS_LEFT_TO_RIGHT
3438 <item> GTK_PROGRESS_RIGHT_TO_LEFT
3439 <item> GTK_PROGRESS_BOTTOM_TO_TOP
3440 <item> GTK_PROGRESS_TOP_TO_BOTTOM
3441 </itemize>
3442
3443 When used as a measure of how far a process has progressed, the
3444 GtkProgressBar can be set to display it's value in either a continuous
3445 or discrete mode. In continuous mode, the progress bar is updated for
3446 each value. In discrete mode, the progress bar is updated in a number
3447 of discrete blocks. The number of blocks is also configurable.
3448
3449 The style of a progress bar can be set using the following function.
3450
3451 <tscreen><verb>
3452 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3453                                      GtkProgressBarStyle  style );
3454 </verb></tscreen>
3455
3456 The <tt/style/ parameter can take one of two values:
3457
3458 <itemize>
3459 <item>GTK_PROGRESS_CONTINUOUS
3460 <item>GTK_PROGRESS_DISCRETE
3461 </itemize>
3462
3463 The number of discrete blocks can be set by calling
3464
3465 <tscreen><verb>
3466 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3467                                            guint           blocks );
3468 </verb></tscreen>
3469
3470 As well as indicating the amount of progress that has occured, the
3471 progress bar may be set to just indicate that there is some
3472 activity. This can be useful in situations where progress cannot be
3473 measured against a value range. Activity mode is not effected by the
3474 bar style that is described above, and overrides it.This mode is
3475 selected by the following function.
3476
3477 <tscreen><verb>
3478 void gtk_progress_set_activity_mode( GtkProgress *progress,
3479                                      guint        activity_mode );
3480 </verb></tscreen>
3481
3482 The step size of the activity indicator, and the number of blocks are
3483 set using the following functions.
3484
3485 <tscreen><verb>
3486 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3487                                          guint           step );
3488
3489 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3490                                            guint           blocks );
3491 </verb></tscreen>
3492
3493 When in continuous mode, the progress bar can also display a
3494 configurable text string within it's trough, using the following
3495 function.
3496
3497 <tscreen><verb>
3498 void gtk_progress_set_format_string( GtkProgress *progress,
3499                                      gchar       *format);
3500 </verb></tscreen>
3501
3502 The <tt/format/ argument is similiar to one that would be used in a C
3503 <tt/printf/ statement. The following directives may be used within the
3504 format string:
3505
3506 <itemize>
3507 <item> %p - percentage
3508 <item> %v - value
3509 <item> %l - lower range value
3510 <item> %u - upper range value
3511 </itemize>
3512  
3513 Progress Bars are usually used with timeouts or other such functions
3514 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3515 Functions">) to give the illusion of multitasking. All will employ the
3516 gtk_progress_bar_update function in the same manner.
3517
3518 Here is an example of the progress bar, updated using timeouts.  This
3519 code also shows you how to reset the Progress Bar.
3520
3521 <tscreen><verb>
3522 /* example-start progressbar progressbar.c */
3523
3524 #include <gtk/gtk.h>
3525
3526 typedef struct _ProgressData {
3527     GtkWidget *window;
3528     GtkWidget *pbar;
3529     int timer;
3530 } ProgressData;
3531
3532 /* Update the value of the progress bar so that we get
3533  * some movement */
3534 gint progress_timeout( gpointer data )
3535 {
3536     gfloat new_val;
3537     GtkAdjustment *adj;
3538
3539     adj = GTK_PROGRESS (data)->adjustment;
3540
3541     /* Calculate the value of the progress bar using the
3542      * value range set in the adjustment object */
3543     new_val = adj->value + 1;
3544     if (new_val > adj->upper)
3545       new_val = adj->lower;
3546
3547     /* Set the new value */
3548     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3549
3550     /* As this is a timeout function, return TRUE so that it
3551      * continues to get called */
3552     return(TRUE);
3553
3554
3555 /* Callback that toggles the text display within the progress
3556  * bar trough */
3557 void toggle_show_text( GtkWidget    *widget,
3558                        ProgressData *pdata )
3559 {
3560     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3561                                 GTK_TOGGLE_BUTTON (widget)->active);
3562 }
3563
3564 /* Callback that toggles the activity mode of the progress
3565  * bar */
3566 void toggle_activity_mode( GtkWidget    *widget,
3567                            ProgressData *pdata )
3568 {
3569     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3570                                     GTK_TOGGLE_BUTTON (widget)->active);
3571 }
3572
3573 /* Callback that toggles the continuous mode of the progress
3574  * bar */
3575 void set_continuous_mode( GtkWidget    *widget,
3576                           ProgressData *pdata )
3577 {
3578     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3579                                     GTK_PROGRESS_CONTINUOUS);
3580 }
3581
3582 /* Callback that toggles the discrete mode of the progress
3583  * bar */
3584 void set_discrete_mode( GtkWidget    *widget,
3585                         ProgressData *pdata )
3586 {
3587     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3588                                     GTK_PROGRESS_DISCRETE);
3589 }
3590  
3591 /* Clean up allocated memory and remove the timer */
3592 void destroy_progress( GtkWidget     *widget,
3593                        ProgressData *pdata)
3594 {
3595     gtk_timeout_remove (pdata->timer);
3596     pdata->timer = 0;
3597     pdata->window = NULL;
3598     g_free(pdata);
3599     gtk_main_quit();
3600 }
3601
3602 int main( int   argc,
3603           char *argv[])
3604 {
3605     ProgressData *pdata;
3606     GtkWidget *align;
3607     GtkWidget *separator;
3608     GtkWidget *table;
3609     GtkAdjustment *adj;
3610     GtkWidget *button;
3611     GtkWidget *check;
3612     GtkWidget *vbox;
3613
3614     gtk_init (&amp;argc, &amp;argv);
3615
3616     /* Allocate memory for the data that is passwd to the callbacks */
3617     pdata = g_malloc( sizeof(ProgressData) );
3618   
3619     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3620     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3621
3622     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3623                         GTK_SIGNAL_FUNC (destroy_progress),
3624                         pdata);
3625     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3626     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3627
3628     vbox = gtk_vbox_new (FALSE, 5);
3629     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3630     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3631     gtk_widget_show(vbox);
3632   
3633     /* Create a centering alignment object */
3634     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3635     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3636     gtk_widget_show(align);
3637
3638     /* Create a GtkAdjusment object to hold the range of the
3639      * progress bar */
3640     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3641
3642     /* Create the GtkProgressBar using the adjustment */
3643     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3644
3645     /* Set the format of the string that can be displayed in the
3646      * trough of the progress bar:
3647      * %p - percentage
3648      * %v - value
3649      * %l - lower range value
3650      * %u - upper range value */
3651     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3652                                     "%v from [%l-%u] (=%p%%)");
3653     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3654     gtk_widget_show(pdata->pbar);
3655
3656     /* Add a timer callback to update the value of the progress bar */
3657     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3658
3659     separator = gtk_hseparator_new ();
3660     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3661     gtk_widget_show(separator);
3662
3663     /* rows, columns, homogeneous */
3664     table = gtk_table_new (2, 3, FALSE);
3665     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3666     gtk_widget_show(table);
3667
3668     /* Add a check button to select displaying of the trough text */
3669     check = gtk_check_button_new_with_label ("Show text");
3670     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3671                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3672                       5, 5);
3673     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3674                         GTK_SIGNAL_FUNC (toggle_show_text),
3675                         pdata);
3676     gtk_widget_show(check);
3677
3678     /* Add a check button to toggle activity mode */
3679     check = gtk_check_button_new_with_label ("Activity mode");
3680     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3681                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3682                       5, 5);
3683     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3684                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3685                         pdata);
3686     gtk_widget_show(check);
3687
3688     separator = gtk_vseparator_new ();
3689     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3690                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3691                       5, 5);
3692     gtk_widget_show(separator);
3693
3694     /* Add a radio button to select continuous display mode */
3695     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3696     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3697                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3698                       5, 5);
3699     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3700                         GTK_SIGNAL_FUNC (set_continuous_mode),
3701                         pdata);
3702     gtk_widget_show (button);
3703
3704     /* Add a radio button to select discrete display mode */
3705     button = gtk_radio_button_new_with_label(
3706                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3707                "Discrete");
3708     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3709                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3710                       5, 5);
3711     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3712                         GTK_SIGNAL_FUNC (set_discrete_mode),
3713                         pdata);
3714     gtk_widget_show (button);
3715
3716     separator = gtk_hseparator_new ();
3717     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3718     gtk_widget_show(separator);
3719
3720     /* Add a button to exit the program */
3721     button = gtk_button_new_with_label ("close");
3722     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3723                                (GtkSignalFunc) gtk_widget_destroy,
3724                                GTK_OBJECT (pdata->window));
3725     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3726
3727     /* This makes it so the button is the default. */
3728     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3729
3730     /* This grabs this button to be the default button. Simply hitting
3731      * the "Enter" key will cause this button to activate. */
3732     gtk_widget_grab_default (button);
3733     gtk_widget_show(button);
3734
3735     gtk_widget_show (pdata->window);
3736
3737     gtk_main ();
3738     
3739     return(0);
3740 }
3741 /* example-end */
3742 </verb></tscreen>
3743
3744 <!-- ----------------------------------------------------------------- -->
3745 <sect1> Dialogs
3746 <p>
3747 The Dialog widget is very simple, and is actually just a window with a
3748 few things pre-packed into it for you. The structure for a Dialog is:
3749
3750 <tscreen><verb>
3751 struct GtkDialog
3752 {
3753       GtkWindow window;
3754     
3755       GtkWidget *vbox;
3756       GtkWidget *action_area;
3757 };
3758 </verb></tscreen>
3759
3760 So you see, it simply creates a window, and then packs a vbox into the
3761 top, then a separator, and then an hbox for the "action_area".
3762
3763 The Dialog widget can be used for pop-up messages to the user, and
3764 other similar tasks. It is really basic, and there is only one
3765 function for the dialog box, which is:
3766
3767 <tscreen><verb>
3768 GtkWidget *gtk_dialog_new( void );
3769 </verb></tscreen>
3770
3771 So to create a new dialog box, use,
3772
3773 <tscreen><verb>
3774     GtkWidget *window;
3775     window = gtk_dialog_new ();
3776 </verb></tscreen>
3777
3778 This will create the dialog box, and it is now up to you to use it.
3779 you could pack a button in the action_area by doing something like this:
3780
3781 <tscreen><verb>
3782     button = ...
3783     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3784                         button, TRUE, TRUE, 0);
3785     gtk_widget_show (button);
3786 </verb></tscreen>
3787
3788 And you could add to the vbox area by packing, for instance, a label 
3789 in it, try something like this:
3790
3791 <tscreen><verb>
3792     label = gtk_label_new ("Dialogs are groovy");
3793     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3794                         label, TRUE, TRUE, 0);
3795     gtk_widget_show (label);
3796 </verb></tscreen>
3797
3798 As an example in using the dialog box, you could put two buttons in
3799 the action_area, a Cancel button and an Ok button, and a label in the
3800 vbox area, asking the user a question or giving an error etc. Then
3801 you could attach a different signal to each of the buttons and perform
3802 the operation the user selects.
3803
3804 If the simple functionality provided by the default vertical and
3805 horizontal boxes in the two areas does't give you enough control for
3806 your application, then you can simply pack another layout widget into
3807 the boxes provided. For example, you could pack a table into the
3808 vertical box.
3809
3810 <!-- ----------------------------------------------------------------- -->
3811 <sect1> Pixmaps <label id="sec_Pixmaps">
3812 <p>
3813 Pixmaps are data structures that contain pictures. These pictures can
3814 be used in various places, but most visibly as icons on the X-Windows
3815 desktop, or as cursors. A bitmap is a 2-color pixmap.
3816
3817 To use pixmaps in GTK, we must first build a GdkPixmap structure using
3818 routines from the GDK layer. Pixmaps can either be created from
3819 in-memory data, or from data read from a file. We'll go through each
3820 of the calls to create a pixmap.
3821
3822 <tscreen><verb>
3823 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
3824                                         gchar     *data,
3825                                         gint       width,
3826                                         gint       height );
3827 </verb></tscreen>
3828
3829 This routine is used to create a single-plane pixmap (2 colors) from
3830 data in memory. Each bit of the data represents whether that pixel is
3831 off or on. Width and height are in pixels. The GdkWindow pointer is
3832 to the current window, since a pixmap resources are meaningful only in
3833 the context of the screen where it is to be displayed.
3834
3835 <tscreen><verb>
3836 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
3837                                         gchar     *data,
3838                                         gint       width,
3839                                         gint       height,
3840                                         gint       depth,
3841                                         GdkColor  *fg,
3842                                         GdkColor  *bg );
3843 </verb></tscreen>
3844
3845 This is used to create a pixmap of the given depth (number of colors) from
3846 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
3847 background color to use.
3848
3849 <tscreen><verb>
3850 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
3851                                        GdkBitmap  **mask,
3852                                        GdkColor    *transparent_color,
3853                                        const gchar *filename );
3854 </verb></tscreen>
3855
3856 XPM format is a readable pixmap representation for the X Window
3857 System. It is widely used and many different utilities are available
3858 for creating image files in this format. The file specified by
3859 filename must contain an image in that format and it is loaded into
3860 the pixmap structure. The mask specifies which bits of the pixmap are
3861 opaque. All other bits are colored using the color specified by
3862 transparent_color. An example using this follows below.
3863
3864 <tscreen><verb>
3865 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
3866                                          GdkBitmap **mask,
3867                                          GdkColor   *transparent_color,
3868                                          gchar     **data );
3869 </verb></tscreen>
3870
3871 Small images can be incorporated into a program as data in the XPM
3872 format.  A pixmap is created using this data, instead of reading it
3873 from a file.  An example of such data is
3874
3875 <tscreen><verb>
3876 /* XPM */
3877 static const char * xpm_data[] = {
3878 "16 16 3 1",
3879 "       c None",
3880 ".      c #000000000000",
3881 "X      c #FFFFFFFFFFFF",
3882 "                ",
3883 "   ......       ",
3884 "   .XXX.X.      ",
3885 "   .XXX.XX.     ",
3886 "   .XXX.XXX.    ",
3887 "   .XXX.....    ",
3888 "   .XXXXXXX.    ",
3889 "   .XXXXXXX.    ",
3890 "   .XXXXXXX.    ",
3891 "   .XXXXXXX.    ",
3892 "   .XXXXXXX.    ",
3893 "   .XXXXXXX.    ",
3894 "   .XXXXXXX.    ",
3895 "   .........    ",
3896 "                ",
3897 "                "};
3898 </verb></tscreen>
3899
3900 When we're done using a pixmap and not likely to reuse it again soon,
3901 it is a good idea to release the resource using
3902 gdk_pixmap_unref(). Pixmaps should be considered a precious resource.
3903
3904 Once we've created a pixmap, we can display it as a GTK widget. We
3905 must create a GTK pixmap widget to contain the GDK pixmap. This is
3906 done using
3907
3908 <tscreen><verb>
3909 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
3910                            GdkBitmap *mask );
3911 </verb></tscreen>
3912
3913 The other pixmap widget calls are
3914
3915 <tscreen><verb>
3916 guint gtk_pixmap_get_type( void );
3917
3918 void  gtk_pixmap_set( GtkPixmap  *pixmap,
3919                       GdkPixmap  *val,
3920                       GdkBitmap  *mask );
3921
3922 void  gtk_pixmap_get( GtkPixmap  *pixmap,
3923                       GdkPixmap **val,
3924                       GdkBitmap **mask);
3925 </verb></tscreen>
3926
3927 gtk_pixmap_set is used to change the pixmap that the widget is currently
3928 managing. Val is the pixmap created using GDK.
3929
3930 The following is an example of using a pixmap in a button.
3931
3932 <tscreen><verb>
3933 /* example-start pixmap pixmap.c */
3934
3935 #include <gtk/gtk.h>
3936
3937
3938 /* XPM data of Open-File icon */
3939 static const char * xpm_data[] = {
3940 "16 16 3 1",
3941 "       c None",
3942 ".      c #000000000000",
3943 "X      c #FFFFFFFFFFFF",
3944 "                ",
3945 "   ......       ",
3946 "   .XXX.X.      ",
3947 "   .XXX.XX.     ",
3948 "   .XXX.XXX.    ",
3949 "   .XXX.....    ",
3950 "   .XXXXXXX.    ",
3951 "   .XXXXXXX.    ",
3952 "   .XXXXXXX.    ",
3953 "   .XXXXXXX.    ",
3954 "   .XXXXXXX.    ",
3955 "   .XXXXXXX.    ",
3956 "   .XXXXXXX.    ",
3957 "   .........    ",
3958 "                ",
3959 "                "};
3960
3961
3962 /* when invoked (via signal delete_event), terminates the application.
3963  */
3964 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
3965     gtk_main_quit();
3966 }
3967
3968
3969 /* is invoked when the button is clicked.  It just prints a message.
3970  */
3971 void button_clicked( GtkWidget *widget, gpointer data ) {
3972     printf( "button clicked\n" );
3973 }
3974
3975 int main( int argc, char *argv[] )
3976 {
3977     /* GtkWidget is the storage type for widgets */
3978     GtkWidget *window, *pixmapwid, *button;
3979     GdkPixmap *pixmap;
3980     GdkBitmap *mask;
3981     GtkStyle *style;
3982     
3983     /* create the main window, and attach delete_event signal to terminating
3984        the application */
3985     gtk_init( &amp;argc, &amp;argv );
3986     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
3987     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
3988                         GTK_SIGNAL_FUNC (close_application), NULL );
3989     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
3990     gtk_widget_show( window );
3991
3992     /* now for the pixmap from gdk */
3993     style = gtk_widget_get_style( window );
3994     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
3995                                            &amp;style->bg[GTK_STATE_NORMAL],
3996                                            (gchar **)xpm_data );
3997
3998     /* a pixmap widget to contain the pixmap */
3999     pixmapwid = gtk_pixmap_new( pixmap, mask );
4000     gtk_widget_show( pixmapwid );
4001
4002     /* a button to contain the pixmap widget */
4003     button = gtk_button_new();
4004     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
4005     gtk_container_add( GTK_CONTAINER(window), button );
4006     gtk_widget_show( button );
4007
4008     gtk_signal_connect( GTK_OBJECT(button), "clicked",
4009                         GTK_SIGNAL_FUNC(button_clicked), NULL );
4010
4011     /* show the window */
4012     gtk_main ();
4013           
4014     return 0;
4015 }
4016 /* example-end */
4017 </verb></tscreen>
4018
4019 To load a file from an XPM data file called icon0.xpm in the current
4020 directory, we would have created the pixmap thus
4021
4022 <tscreen><verb>
4023     /* load a pixmap from a file */
4024     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
4025                                          &amp;style->bg[GTK_STATE_NORMAL],
4026                                          "./icon0.xpm" );
4027     pixmapwid = gtk_pixmap_new( pixmap, mask );
4028     gtk_widget_show( pixmapwid );
4029     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
4030 </verb></tscreen>
4031
4032 A disadvantage of using pixmaps is that the displayed object is always
4033 rectangular, regardless of the image. We would like to create desktops
4034 and applications with icons that have more natural shapes. For
4035 example, for a game interface, we would like to have round buttons to
4036 push. The way to do this is using shaped windows.
4037
4038 A shaped window is simply a pixmap where the background pixels are
4039 transparent. This way, when the background image is multi-colored, we
4040 don't overwrite it with a rectangular, non-matching border around our
4041 icon. The following example displays a full wheelbarrow image on the
4042 desktop.
4043
4044 <tscreen><verb>
4045 /* example-start wheelbarrow wheelbarrow.c */
4046
4047 #include <gtk/gtk.h>
4048
4049 /* XPM */
4050 static char * WheelbarrowFull_xpm[] = {
4051 "48 48 64 1",
4052 "       c None",
4053 ".      c #DF7DCF3CC71B",
4054 "X      c #965875D669A6",
4055 "o      c #71C671C671C6",
4056 "O      c #A699A289A699",
4057 "+      c #965892489658",
4058 "@      c #8E38410330C2",
4059 "#      c #D75C7DF769A6",
4060 "$      c #F7DECF3CC71B",
4061 "%      c #96588A288E38",
4062 "&amp;      c #A69992489E79",
4063 "*      c #8E3886178E38",
4064 "=      c #104008200820",
4065 "-      c #596510401040",
4066 ";      c #C71B30C230C2",
4067 ":      c #C71B9A699658",
4068 ">      c #618561856185",
4069 ",      c #20811C712081",
4070 "<      c #104000000000",
4071 "1      c #861720812081",
4072 "2      c #DF7D4D344103",
4073 "3      c #79E769A671C6",
4074 "4      c #861782078617",
4075 "5      c #41033CF34103",
4076 "6      c #000000000000",
4077 "7      c #49241C711040",
4078 "8      c #492445144924",
4079 "9      c #082008200820",
4080 "0      c #69A618611861",
4081 "q      c #B6DA71C65144",
4082 "w      c #410330C238E3",
4083 "e      c #CF3CBAEAB6DA",
4084 "r      c #71C6451430C2",
4085 "t      c #EFBEDB6CD75C",
4086 "y      c #28A208200820",
4087 "u      c #186110401040",
4088 "i      c #596528A21861",
4089 "p      c #71C661855965",
4090 "a      c #A69996589658",
4091 "s      c #30C228A230C2",
4092 "d      c #BEFBA289AEBA",
4093 "f      c #596545145144",
4094 "g      c #30C230C230C2",
4095 "h      c #8E3882078617",
4096 "j      c #208118612081",
4097 "k      c #38E30C300820",
4098 "l      c #30C2208128A2",
4099 "z      c #38E328A238E3",
4100 "x      c #514438E34924",
4101 "c      c #618555555965",
4102 "v      c #30C2208130C2",
4103 "b      c #38E328A230C2",
4104 "n      c #28A228A228A2",
4105 "m      c #41032CB228A2",
4106 "M      c #104010401040",
4107 "N      c #492438E34103",
4108 "B      c #28A2208128A2",
4109 "V      c #A699596538E3",
4110 "C      c #30C21C711040",
4111 "Z      c #30C218611040",
4112 "A      c #965865955965",
4113 "S      c #618534D32081",
4114 "D      c #38E31C711040",
4115 "F      c #082000000820",
4116 "                                                ",
4117 "          .XoO                                  ",
4118 "         +@#$%o&amp;                                ",
4119 "         *=-;#::o+                              ",
4120 "           >,<12#:34                            ",
4121 "             45671#:X3                          ",
4122 "               +89<02qwo                        ",
4123 "e*                >,67;ro                       ",
4124 "ty>                 459@>+&amp;&amp;                    ",
4125 "$2u+                  ><ipas8*                  ",
4126 "%$;=*                *3:.Xa.dfg>                ",
4127 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
4128 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
4129 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
4130 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
4131 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
4132 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
4133 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
4134 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
4135 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
4136 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
4137 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
4138 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
4139 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
4140 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
4141 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
4142 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
4143 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
4144 "              p;<69BvwwsszslllbBlllllllu<5+     ",
4145 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
4146 "               c1-699Blvlllllu7k96MMMg4         ",
4147 "               *10y8n6FjvllllB<166668           ",
4148 "                S-kg+>666<M<996-y6n<8*          ",
4149 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
4150 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
4151 "                 N-k-<>     >=01-kuu666>        ",
4152 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
4153 "                 Ou0<>       o66y<ulw<66&amp;       ",
4154 "                  *kk5       >66By7=xu664       ",
4155 "                   <<M4      466lj<Mxu66o       ",
4156 "                   *>>       +66uv,zN666*       ",
4157 "                              566,xxj669        ",
4158 "                              4666FF666>        ",
4159 "                               >966666M         ",
4160 "                                oM6668+         ",
4161 "                                  *4            ",
4162 "                                                ",
4163 "                                                "};
4164
4165
4166 /* When invoked (via signal delete_event), terminates the application */
4167 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4168     gtk_main_quit();
4169 }
4170
4171 int main (int argc, char *argv[])
4172 {
4173     /* GtkWidget is the storage type for widgets */
4174     GtkWidget *window, *pixmap, *fixed;
4175     GdkPixmap *gdk_pixmap;
4176     GdkBitmap *mask;
4177     GtkStyle *style;
4178     GdkGC *gc;
4179     
4180     /* Create the main window, and attach delete_event signal to terminate
4181      * the application.  Note that the main window will not have a titlebar
4182      * since we're making it a popup. */
4183     gtk_init (&amp;argc, &amp;argv);
4184     window = gtk_window_new( GTK_WINDOW_POPUP );
4185     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4186                         GTK_SIGNAL_FUNC (close_application), NULL);
4187     gtk_widget_show (window);
4188
4189     /* Now for the pixmap and the pixmap widget */
4190     style = gtk_widget_get_default_style();
4191     gc = style->black_gc;
4192     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
4193                                              &amp;style->bg[GTK_STATE_NORMAL],
4194                                              WheelbarrowFull_xpm );
4195     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
4196     gtk_widget_show( pixmap );
4197
4198     /* To display the pixmap, we use a fixed widget to place the pixmap */
4199     fixed = gtk_fixed_new();
4200     gtk_widget_set_usize( fixed, 200, 200 );
4201     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
4202     gtk_container_add( GTK_CONTAINER(window), fixed );
4203     gtk_widget_show( fixed );
4204
4205     /* This masks out everything except for the image itself */
4206     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
4207     
4208     /* show the window */
4209     gtk_widget_set_uposition( window, 20, 400 );
4210     gtk_widget_show( window );
4211     gtk_main ();
4212           
4213     return(0);
4214 }
4215 /* example-end */
4216 </verb></tscreen>
4217
4218 To make the wheelbarrow image sensitive, we could attach the button
4219 press event signal to make it do something. The following few lines
4220 would make the picture sensitive to a mouse button being pressed which
4221 makes the application terminate.
4222
4223 <tscreen><verb>
4224     gtk_widget_set_events( window,
4225                           gtk_widget_get_events( window ) |
4226                           GDK_BUTTON_PRESS_MASK );
4227
4228    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
4229                        GTK_SIGNAL_FUNC(close_application), NULL );
4230 </verb></tscreen>
4231
4232 <!-- ----------------------------------------------------------------- -->
4233 <sect1>Rulers
4234 <p>
4235 Ruler widgets are used to indicate the location of the mouse pointer
4236 in a given window. A window can have a vertical ruler spanning across
4237 the width and a horizontal ruler spanning down the height. A small
4238 triangular indicator on the ruler shows the exact location of the
4239 pointer relative to the ruler.
4240
4241 A ruler must first be created. Horizontal and vertical rulers are
4242 created using
4243
4244 <tscreen><verb>
4245 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4246
4247 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4248 </verb></tscreen>
4249
4250 Once a ruler is created, we can define the unit of measurement. Units
4251 of measure for rulers can be GTK_PIXELS, GTK_INCHES or
4252 GTK_CENTIMETERS. This is set using
4253
4254 <tscreen><verb>
4255 void gtk_ruler_set_metric( GtkRuler      *ruler,
4256                            GtkMetricType  metric );
4257 </verb></tscreen>
4258
4259 The default measure is GTK_PIXELS.
4260
4261 <tscreen><verb>
4262     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4263 </verb></tscreen>
4264
4265 Other important characteristics of a ruler are how to mark the units
4266 of scale and where the position indicator is initially placed. These
4267 are set for a ruler using
4268
4269 <tscreen><verb>
4270 void gtk_ruler_set_range( GtkRuler *ruler,
4271                           gfloat    lower,
4272                           gfloat    upper,
4273                           gfloat    position,
4274                           gfloat    max_size );
4275 </verb></tscreen>
4276
4277 The lower and upper arguments define the extent of the ruler, and
4278 max_size is the largest possible number that will be displayed.
4279 Position defines the initial position of the pointer indicator within
4280 the ruler.
4281
4282 A vertical ruler can span an 800 pixel wide window thus
4283
4284 <tscreen><verb>
4285     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4286 </verb></tscreen>
4287
4288 The markings displayed on the ruler will be from 0 to 800, with a
4289 number for every 100 pixels. If instead we wanted the ruler to range
4290 from 7 to 16, we would code
4291
4292 <tscreen><verb>
4293     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4294 </verb></tscreen>
4295
4296 The indicator on the ruler is a small triangular mark that indicates
4297 the position of the pointer relative to the ruler. If the ruler is
4298 used to follow the mouse pointer, the motion_notify_event signal
4299 should be connected to the motion_notify_event method of the ruler.
4300 To follow all mouse movements within a window area, we would use
4301
4302 <tscreen><verb>
4303 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4304
4305     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4306            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4307            GTK_OBJECT(ruler) );
4308 </verb></tscreen>
4309
4310 The following example creates a drawing area with a horizontal ruler
4311 above it and a vertical ruler to the left of it. The size of the
4312 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4313 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4314 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4315 Placement of the drawing area and the rulers is done using a table.
4316
4317 <tscreen><verb>
4318 /* example-start rulers rulers.c */
4319
4320 #include <gtk/gtk.h>
4321
4322 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4323
4324 #define XSIZE  600
4325 #define YSIZE  400
4326
4327 /* This routine gets control when the close button is clicked */
4328 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4329     gtk_main_quit();
4330 }
4331
4332 /* The main routine */
4333 int main( int argc, char *argv[] ) {
4334     GtkWidget *window, *table, *area, *hrule, *vrule;
4335
4336     /* Initialize GTK and create the main window */
4337     gtk_init( &amp;argc, &amp;argv );
4338
4339     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4340     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4341             GTK_SIGNAL_FUNC( close_application ), NULL);
4342     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4343
4344     /* Create a table for placing the ruler and the drawing area */
4345     table = gtk_table_new( 3, 2, FALSE );
4346     gtk_container_add( GTK_CONTAINER(window), table );
4347
4348     area = gtk_drawing_area_new();
4349     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4350     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4351                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4352     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK );
4353
4354     /* The horizontal ruler goes on top. As the mouse moves across the drawing area,
4355      * a motion_notify_event is passed to the appropriate event handler for the ruler. */
4356     hrule = gtk_hruler_new();
4357     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4358     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4359     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4360                                (GtkSignalFunc)EVENT_METHOD(hrule, motion_notify_event),
4361                                GTK_OBJECT(hrule) );
4362     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4363     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4364                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4365     
4366     /* The vertical ruler goes on the left. As the mouse moves across the drawing area,
4367      * a motion_notify_event is passed to the appropriate event handler for the ruler. */
4368     vrule = gtk_vruler_new();
4369     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4370     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4371     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4372                                (GtkSignalFunc)
4373                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->motion_notify_event,
4374                                GTK_OBJECT(vrule) );
4375     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4376                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4377
4378     /* Now show everything */
4379     gtk_widget_show( area );
4380     gtk_widget_show( hrule );
4381     gtk_widget_show( vrule );
4382     gtk_widget_show( table );
4383     gtk_widget_show( window );
4384     gtk_main();
4385
4386     return(0);
4387 }
4388 /* example-end */
4389 </verb></tscreen>
4390
4391 <!-- ----------------------------------------------------------------- -->
4392 <sect1>Statusbars
4393 <p>
4394 Statusbars are simple widgets used to display a text message. They
4395 keep a stack of the messages pushed onto them, so that popping the
4396 current message will re-display the previous text message.
4397
4398 In order to allow different parts of an application to use the same
4399 statusbar to display messages, the statusbar widget issues Context
4400 Identifiers which are used to identify different 'users'. The message
4401 on top of the stack is the one displayed, no matter what context it is
4402 in. Messages are stacked in last-in-first-out order, not context
4403 identifier order.
4404
4405 A statusbar is created with a call to:
4406
4407 <tscreen><verb>
4408 GtkWidget *gtk_statusbar_new( void );
4409 </verb></tscreen>
4410
4411 A new Context Identifier is requested using a call to the following 
4412 function with a short textual description of the context:
4413
4414 <tscreen><verb>
4415 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4416                                     const gchar  *context_description );
4417 </verb></tscreen>
4418
4419 There are three functions that can operate on statusbars:
4420
4421 <tscreen><verb>
4422 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4423                           guint         context_id,
4424                           gchar        *text );
4425
4426 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4427                         guint         context_id );
4428
4429 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4430                            guint         context_id,
4431                            guint         message_id ); 
4432 </verb></tscreen>
4433
4434 The first, gtk_statusbar_push, is used to add a new message to the
4435 statusbar.  It returns a Message Identifier, which can be passed later
4436 to the function gtk_statusbar_remove to remove the message with the
4437 given Message and Context Identifiers from the statusbar's stack.
4438
4439 The function gtk_statusbar_pop removes the message highest in the
4440 stack with the given Context Identifier.
4441
4442 The following example creates a statusbar and two buttons, one for
4443 pushing items onto the statusbar, and one for popping the last item
4444 back off.
4445
4446 <tscreen><verb>
4447 /* example-start statusbar statusbar.c */
4448
4449 #include <gtk/gtk.h>
4450 #include <glib.h>
4451
4452 GtkWidget *status_bar;
4453
4454 void push_item (GtkWidget *widget, gpointer data)
4455 {
4456   static int count = 1;
4457   char buff[20];
4458
4459   g_snprintf(buff, 20, "Item %d", count++);
4460   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4461
4462   return;
4463 }
4464
4465 void pop_item (GtkWidget *widget, gpointer data)
4466 {
4467   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4468   return;
4469 }
4470
4471 int main (int argc, char *argv[])
4472 {
4473
4474     GtkWidget *window;
4475     GtkWidget *vbox;
4476     GtkWidget *button;
4477
4478     gint context_id;
4479
4480     gtk_init (&amp;argc, &amp;argv);
4481
4482     /* create a new window */
4483     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4484     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4485     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4486     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4487                        (GtkSignalFunc) gtk_exit, NULL);
4488  
4489     vbox = gtk_vbox_new(FALSE, 1);
4490     gtk_container_add(GTK_CONTAINER(window), vbox);
4491     gtk_widget_show(vbox);
4492           
4493     status_bar = gtk_statusbar_new();      
4494     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4495     gtk_widget_show (status_bar);
4496
4497     context_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(status_bar), "Statusbar example");
4498
4499     button = gtk_button_new_with_label("push item");
4500     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4501         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4502     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4503     gtk_widget_show(button);              
4504
4505     button = gtk_button_new_with_label("pop last item");
4506     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4507         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4508     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4509     gtk_widget_show(button);              
4510
4511     /* always display the window as the last step so it all splashes on
4512      * the screen at once. */
4513     gtk_widget_show(window);
4514
4515     gtk_main ();
4516
4517     return 0;
4518 }
4519 /* example-end */
4520 </verb></tscreen>
4521
4522 <!-- ----------------------------------------------------------------- -->
4523 <sect1>Text Entries
4524 <p>
4525 The Entry widget allows text to be typed and displayed in a single line
4526 text box. The text may be set with function calls that allow new text
4527 to replace, prepend or append the current contents of the Entry widget.
4528
4529 There are two functions for creating Entry widgets:
4530
4531 <tscreen><verb>
4532 GtkWidget *gtk_entry_new( void );
4533
4534 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4535 </verb></tscreen>
4536
4537 The first just creates a new Entry widget, whilst the second creates a
4538 new Entry and sets a limit on the length of the text within the Entry.
4539
4540 There are several functions for altering the text which is currently
4541 within the Entry widget.
4542
4543 <tscreen><verb>
4544 void gtk_entry_set_text( GtkEntry    *entry,
4545                          const gchar *text );
4546
4547 void gtk_entry_append_text( GtkEntry    *entry,
4548                             const gchar *text );
4549
4550 void gtk_entry_prepend_text( GtkEntry    *entry,
4551                              const gchar *text );
4552 </verb></tscreen>
4553
4554 The function gtk_entry_set_text sets the contents of the Entry widget,
4555 replacing the current contents. The functions gtk_entry_append_text
4556 and gtk_entry_prepend_text allow the current contents to be appended
4557 and prepended to.
4558
4559 The next function allows the current insertion point to be set.
4560
4561 <tscreen><verb>
4562 void gtk_entry_set_position( GtkEntry *entry,
4563                              gint      position );
4564 </verb></tscreen>
4565
4566 The contents of the Entry can be retrieved by using a call to the
4567 following function. This is useful in the callback functions described below.
4568
4569 <tscreen><verb>
4570 gchar *gtk_entry_get_text( GtkEntry *entry );
4571 </verb></tscreen>
4572
4573 If we don't want the contents of the Entry to be changed by someone typing
4574 into it, we can change its editable state.
4575
4576 <tscreen><verb>
4577 void gtk_entry_set_editable( GtkEntry *entry,
4578                              gboolean  editable );
4579 </verb></tscreen>
4580
4581 The function above allows us to toggle the editable state of the
4582 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4583 argument.
4584
4585 If we are using the Entry where we don't want the text entered to be
4586 visible, for example when a password is being entered, we can use the
4587 following function, which also takes a boolean flag.
4588
4589 <tscreen><verb>
4590 void gtk_entry_set_visibility( GtkEntry *entry,
4591                                gboolean  visible );
4592 </verb></tscreen>
4593
4594 A region of the text may be set as selected by using the following
4595 function. This would most often be used after setting some default
4596 text in an Entry, making it easy for the user to remove it.
4597
4598 <tscreen><verb>
4599 void gtk_entry_select_region( GtkEntry *entry,
4600                               gint      start,
4601                               gint      end );
4602 </verb></tscreen>
4603
4604 If we want to catch when the user has entered text, we can connect to
4605 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4606 user hits the enter key within the Entry widget. Changed is raised
4607 when the text changes at all, e.g. for every character entered or
4608 removed.
4609
4610 The following code is an example of using an Entry widget.
4611
4612 <tscreen><verb>
4613 /* example-start entry entry.c */
4614
4615 #include <gtk/gtk.h>
4616
4617 void enter_callback(GtkWidget *widget, GtkWidget *entry)
4618 {
4619   gchar *entry_text;
4620   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4621   printf("Entry contents: %s\n", entry_text);
4622 }
4623
4624 void entry_toggle_editable (GtkWidget *checkbutton,
4625                                    GtkWidget *entry)
4626 {
4627   gtk_entry_set_editable(GTK_ENTRY(entry),
4628                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4629 }
4630
4631 void entry_toggle_visibility (GtkWidget *checkbutton,
4632                                    GtkWidget *entry)
4633 {
4634   gtk_entry_set_visibility(GTK_ENTRY(entry),
4635                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4636 }
4637
4638 int main (int argc, char *argv[])
4639 {
4640
4641     GtkWidget *window;
4642     GtkWidget *vbox, *hbox;
4643     GtkWidget *entry;
4644     GtkWidget *button;
4645     GtkWidget *check;
4646
4647     gtk_init (&amp;argc, &amp;argv);
4648
4649     /* create a new window */
4650     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4651     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4652     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4653     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4654                        (GtkSignalFunc) gtk_exit, NULL);
4655
4656     vbox = gtk_vbox_new (FALSE, 0);
4657     gtk_container_add (GTK_CONTAINER (window), vbox);
4658     gtk_widget_show (vbox);
4659
4660     entry = gtk_entry_new_with_max_length (50);
4661     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4662                        GTK_SIGNAL_FUNC(enter_callback),
4663                        entry);
4664     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4665     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4666     gtk_entry_select_region (GTK_ENTRY (entry),
4667                              0, GTK_ENTRY(entry)->text_length);
4668     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4669     gtk_widget_show (entry);
4670
4671     hbox = gtk_hbox_new (FALSE, 0);
4672     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4673     gtk_widget_show (hbox);
4674                                   
4675     check = gtk_check_button_new_with_label("Editable");
4676     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4677     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4678                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4679     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4680     gtk_widget_show (check);
4681     
4682     check = gtk_check_button_new_with_label("Visible");
4683     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4684     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4685                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4686     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4687     gtk_widget_show (check);
4688                                    
4689     button = gtk_button_new_with_label ("Close");
4690     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4691                                GTK_SIGNAL_FUNC(gtk_exit),
4692                                GTK_OBJECT (window));
4693     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4694     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4695     gtk_widget_grab_default (button);
4696     gtk_widget_show (button);
4697     
4698     gtk_widget_show(window);
4699
4700     gtk_main();
4701     return(0);
4702 }
4703 /* example-end */
4704 </verb></tscreen>
4705
4706 <!-- ----------------------------------------------------------------- -->
4707 <sect1>Spin Buttons
4708 <p>
4709 The Spin Button widget is generally used to allow the user to select a
4710 value from a range of numeric values. It consists of a text
4711 entry box with up and down arrow buttons attached to the
4712 side. Selecting one of the buttons causes the value to 'spin' up and
4713 down the range of possible values. The entry box may also be edited
4714 directly to enter a specific value.
4715
4716 The Spin Button allows the value to have zero or a number of decimal
4717 places and to be incremented/decremented in configurable steps. The
4718 action of holding down one of the buttons optionally result in an
4719 acceleration of change in the value according to how long it is
4720 depressed.
4721
4722 The Spin Button uses an <ref id="sec_Adjustment" name="Adjustment">
4723 object to hold information about the range of values that the spin
4724 button can take. This makes for a powerful Spin Button widget.
4725
4726 Recall that an adjustment widget is created with the following
4727 function, which illustrates the information that it holds:
4728
4729 <tscreen><verb>
4730 GtkObject *gtk_adjustment_new( gfloat value,
4731                                gfloat lower,
4732                                gfloat upper,
4733                                gfloat step_increment,
4734                                gfloat page_increment,
4735                                gfloat page_size );
4736 </verb></tscreen>
4737
4738 These attributes of an Adjustment are used by the Spin Button in the
4739 following way:
4740
4741 <itemize>
4742 <item> <tt/value/: initial value for the Spin Button
4743 <item> <tt/lower/: lower range value
4744 <item> <tt/upper/: upper range value
4745 <item> <tt/step_increment/: value to increment/decrement when pressing
4746 mouse button 1 on a button
4747 <item> <tt/page_increment/: value to increment/decrement when pressing
4748 mouse button 2 on a button
4749 <item> <tt/page_size/: unused
4750 </itemize>
4751
4752 Additionally, mouse button 3 can be used to jump directly to the
4753 <tt/upper/ or <tt/lower/ values when used to select one of the
4754 buttons. Lets look at how to create a Spin Button:
4755
4756 <tscreen><verb>
4757 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4758                                 gfloat         climb_rate,
4759                                 guint          digits );
4760 </verb></tscreen>
4761
4762 The <tt/climb_rate/ argument take a value between 0.0 and 1.0 and
4763 indicates the amount of acceleration that the Spin Button has. The
4764 <tt/digits/ argument specifies the number of decimal places to which
4765 the value will be displayed.
4766
4767 A Spin Button can be reconfigured after creation using the following
4768 function:
4769
4770 <tscreen><verb>
4771 void gtk_spin_button_configure( GtkSpinButton *spin_button,
4772                                 GtkAdjustment *adjustment,
4773                                 gfloat         climb_rate,
4774                                 guint          digits );
4775 </verb></tscreen>
4776
4777 The <tt/spin_button/ argument specifies the Spin Button widget that is
4778 to be reconfigured. The other arguments are as specified above.
4779
4780 The adjustment can be set and retrieved independantly using the
4781 following two functions:
4782
4783 <tscreen><verb>
4784 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
4785                                      GtkAdjustment  *adjustment );
4786
4787 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
4788 </verb></tscreen>
4789
4790 The number of decimal places can also be altered using:
4791
4792 <tscreen><verb>
4793 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
4794                                  guint          digits) ;
4795 </verb></tscreen>
4796
4797 The value that a Spin Button is currently displaying can be changed
4798 using the following function:
4799
4800 <tscreen><verb>
4801 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
4802                                 gfloat         value );
4803 </verb></tscreen>
4804
4805 The current value of a Spin Button can be retrieved as either a
4806 floating point or integer value with the following functions:
4807
4808 <tscreen><verb>
4809 gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *spin_button );
4810
4811 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
4812 </verb></tscreen>
4813
4814 If you want to alter the value of a Spin Value relative to its current
4815 value, then the following function can be used:
4816
4817 <tscreen><verb>
4818 void gtk_spin_button_spin( GtkSpinButton *spin_button,
4819                            GtkSpinType    direction,
4820                            gfloat         increment );
4821 </verb></tscreen>
4822
4823 The <tt/direction/ parameter can take one of the following values:
4824
4825 <itemize>
4826 <item> GTK_SPIN_STEP_FORWARD
4827 <item> GTK_SPIN_STEP_BACKWARD
4828 <item> GTK_SPIN_PAGE_FORWARD
4829 <item> GTK_SPIN_PAGE_BACKWARD
4830 <item> GTK_SPIN_HOME
4831 <item> GTK_SPIN_END
4832 <item> GTK_SPIN_USER_DEFINED
4833 </itemize>
4834
4835 This function packs in quite a bit of functionality, which I will
4836 attempt to clearly explain. Many of these settings use values from the
4837 Adjustment object that is associated with a Spin Button.
4838
4839 GTK_SPIN_STEP_FORWARD and GTK_SPIN_STEP_BACKWARD change the value of
4840 the Spin Button by the amount specified by <tt/increment/, unless
4841 <tt/increment/ is equal to 0, in which case the value is changed by
4842 the value of <tt/step_increment/ in theAdjustment.
4843
4844 GTK_SPIN_PAGE_FORWARD and GTK_SPIN_PAGE_BACKWARD simply alter the value of
4845 the Spin Button by <tt/increment/.
4846
4847 GTK_SPIN_HOME sets the value of the Spin Button to the bottom of the
4848 Adjustments range.
4849
4850 GTK_SPIN_END sets the value of the Spin Button to the top of the
4851 Adjustments range.
4852
4853 GTK_SPIN_USER_DEFINED simply alters the value of the Spin Button by
4854 the specified amount.
4855
4856 We move away from functions for setting and retreving the range attributes
4857 of the Spin Button now, and move onto functions that effect the
4858 appearance and behaviour of the Spin Button widget itself.
4859
4860 The first of these functions is used to constrain the text box of the
4861 Spin Button such that it may only contain a numric value. This
4862 prevents a user from typing anything other than numeric values into
4863 the text box of a Spin Button:
4864
4865 <tscreen><verb>
4866 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
4867                                   gboolean       numeric );
4868 </verb></tscreen>
4869
4870 You can set whether a Spin Button will wrap around between the upper
4871 and lower range values with the following function:
4872
4873 <tscreen><verb>
4874 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
4875                                gboolean       wrap );
4876 </verb></tscreen>
4877
4878 You can set a Spin Button to round the value to the nearest
4879 <tt/step_increment/, which is set within the Adjustment object used
4880 with the Spin Button. This is accomplished with the following
4881 function:
4882
4883 <tscreen><verb>
4884 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
4885                                         gboolean        snap_to_ticks );
4886 </verb></tscreen>
4887
4888 The update policy of a Spin Button can be changed with the following
4889 function:
4890
4891 <tscreen><verb>
4892 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
4893                                     GtkSpinButtonUpdatePolicy policy );
4894 </verb></tscreen>
4895
4896 <!-- TODO: find out what this does - TRG -->
4897
4898 The possible values of <tt/policy/ are either GTK_UPDATE_ALWAYS or
4899 GTK_UPDATE_IF_VALID.
4900
4901 The appearance of the buttons used in a Spin Button can be changed
4902 using the following function:
4903
4904 <tscreen><verb>
4905 void gtk_spin_button_set_shadow_type( GtkSpinButton *spin_button,
4906                                       GtkShadowType  shadow_type );
4907 </verb></tscreen>
4908
4909 As usual, the <tt/shadow_type/ can be one of:
4910
4911 <itemize>
4912 <item> GTK_SHADOW_IN
4913 <item> GTK_SHADOW_OUT
4914 <item> GTK_SHADOW_ETCHED_IN
4915 <item> GTK_SHADOW_ETCHED_OUT
4916 </itemize>
4917
4918 Finally, you can explicitly request that a Spin Button update itself:
4919
4920 <tscreen><verb>
4921 void gtk_spin_button_update( GtkSpinButton  *spin_button );
4922 </verb></tscreen>
4923
4924 It's example time again.
4925
4926 <tscreen><verb>
4927 /* example-start spinbutton spinbutton.c */
4928
4929 #include <gtk/gtk.h>
4930
4931 static GtkWidget *spinner1;
4932
4933 void toggle_snap( GtkWidget     *widget,
4934                   GtkSpinButton *spin )
4935 {
4936   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
4937 }
4938
4939 void toggle_numeric( GtkWidget *widget,
4940                      GtkSpinButton *spin )
4941 {
4942   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
4943 }
4944
4945 void change_digits( GtkWidget *widget,
4946                     GtkSpinButton *spin )
4947 {
4948   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
4949                               gtk_spin_button_get_value_as_int (spin));
4950 }
4951
4952 void get_value( GtkWidget *widget,
4953                 gpointer data )
4954 {
4955   gchar buf[32];
4956   GtkLabel *label;
4957   GtkSpinButton *spin;
4958
4959   spin = GTK_SPIN_BUTTON (spinner1);
4960   label = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget)));
4961   if (GPOINTER_TO_INT (data) == 1)
4962     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
4963   else
4964     sprintf (buf, "%0.*f", spin->digits,
4965              gtk_spin_button_get_value_as_float (spin));
4966   gtk_label_set_text (label, buf);
4967 }
4968
4969
4970 int main( int   argc,
4971           char *argv[] )
4972 {
4973   GtkWidget *window;
4974   GtkWidget *frame;
4975   GtkWidget *hbox;
4976   GtkWidget *main_vbox;
4977   GtkWidget *vbox;
4978   GtkWidget *vbox2;
4979   GtkWidget *spinner2;
4980   GtkWidget *spinner;
4981   GtkWidget *button;
4982   GtkWidget *label;
4983   GtkWidget *val_label;
4984   GtkAdjustment *adj;
4985
4986   /* Initialise GTK */
4987   gtk_init(&amp;argc, &amp;argv);
4988
4989   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4990
4991   gtk_signal_connect (GTK_OBJECT (window), "destroy",
4992                       GTK_SIGNAL_FUNC (gtk_main_quit),
4993                       NULL);
4994
4995   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
4996
4997   main_vbox = gtk_vbox_new (FALSE, 5);
4998   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
4999   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5000   
5001   frame = gtk_frame_new ("Not accelerated");
5002   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5003   
5004   vbox = gtk_vbox_new (FALSE, 0);
5005   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5006   gtk_container_add (GTK_CONTAINER (frame), vbox);
5007   
5008   /* Day, month, year spinners */
5009   
5010   hbox = gtk_hbox_new (FALSE, 0);
5011   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5012   
5013   vbox2 = gtk_vbox_new (FALSE, 0);
5014   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5015   
5016   label = gtk_label_new ("Day :");
5017   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5018   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5019   
5020   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5021                                               5.0, 0.0);
5022   spinner = gtk_spin_button_new (adj, 0, 0);
5023   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5024   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5025                                    GTK_SHADOW_OUT);
5026   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5027   
5028   vbox2 = gtk_vbox_new (FALSE, 0);
5029   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5030   
5031   label = gtk_label_new ("Month :");
5032   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5033   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5034   
5035   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5036                                               5.0, 0.0);
5037   spinner = gtk_spin_button_new (adj, 0, 0);
5038   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5039   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5040                                    GTK_SHADOW_ETCHED_IN);
5041   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5042   
5043   vbox2 = gtk_vbox_new (FALSE, 0);
5044   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5045   
5046   label = gtk_label_new ("Year :");
5047   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5048   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5049   
5050   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5051                                               1.0, 100.0, 0.0);
5052   spinner = gtk_spin_button_new (adj, 0, 0);
5053   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5054   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5055                                    GTK_SHADOW_IN);
5056   gtk_widget_set_usize (spinner, 55, 0);
5057   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5058   
5059   frame = gtk_frame_new ("Accelerated");
5060   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5061   
5062   vbox = gtk_vbox_new (FALSE, 0);
5063   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5064   gtk_container_add (GTK_CONTAINER (frame), vbox);
5065   
5066   hbox = gtk_hbox_new (FALSE, 0);
5067   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5068   
5069   vbox2 = gtk_vbox_new (FALSE, 0);
5070   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5071   
5072   label = gtk_label_new ("Value :");
5073   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5074   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5075   
5076   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5077                                               0.5, 100.0, 0.0);
5078   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5079   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5080   gtk_widget_set_usize (spinner1, 100, 0);
5081   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5082   
5083   vbox2 = gtk_vbox_new (FALSE, 0);
5084   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5085   
5086   label = gtk_label_new ("Digits :");
5087   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5088   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5089   
5090   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5091   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5092   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5093   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
5094                       GTK_SIGNAL_FUNC (change_digits),
5095                       (gpointer) spinner2);
5096   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5097   
5098   hbox = gtk_hbox_new (FALSE, 0);
5099   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5100   
5101   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5102   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5103                       GTK_SIGNAL_FUNC (toggle_snap),
5104                       spinner1);
5105   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5106   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5107   
5108   button = gtk_check_button_new_with_label ("Numeric only input mode");
5109   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5110                       GTK_SIGNAL_FUNC (toggle_numeric),
5111                       spinner1);
5112   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5113   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5114   
5115   val_label = gtk_label_new ("");
5116   
5117   hbox = gtk_hbox_new (FALSE, 0);
5118   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5119   button = gtk_button_new_with_label ("Value as Int");
5120   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5121   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5122                       GTK_SIGNAL_FUNC (get_value),
5123                       GINT_TO_POINTER (1));
5124   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5125   
5126   button = gtk_button_new_with_label ("Value as Float");
5127   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5128   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5129                       GTK_SIGNAL_FUNC (get_value),
5130                       GINT_TO_POINTER (2));
5131   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5132   
5133   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5134   gtk_label_set_text (GTK_LABEL (val_label), "0");
5135   
5136   hbox = gtk_hbox_new (FALSE, 0);
5137   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5138   
5139   button = gtk_button_new_with_label ("Close");
5140   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5141                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
5142                              GTK_OBJECT (window));
5143   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5144
5145   gtk_widget_show_all (window);
5146
5147   /* Enter the event loop */
5148   gtk_main ();
5149     
5150   return(0);
5151 }
5152 /* example-end */
5153 </verb></tscreen>
5154
5155 <!-- ----------------------------------------------------------------- -->
5156 <sect1> Color Selection
5157 <p>
5158 The color selection widget is, not surprisingly, a widget for
5159 interactive selection of colors. This composite widget lets the user
5160 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5161 Saturation, Value) triples.  This is done either by adjusting single
5162 values with sliders or entries, or by picking the desired color from a
5163 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5164 can also be set.
5165
5166 The color selection widget currently emits only one signal,
5167 "color_changed", which is emitted whenever the current color in the
5168 widget changes, either when the user changes it or if it's set
5169 explicitly through gtk_color_selection_set_color().
5170
5171 Lets have a look at what the color selection widget has to offer
5172 us. The widget comes in two flavours: gtk_color_selection and
5173 gtk_color_selection_dialog.
5174
5175 <tscreen><verb>
5176 GtkWidget *gtk_color_selection_new( void );
5177 </verb></tscreen>
5178         
5179 You'll probably not be using this constructor directly. It creates an
5180 orphan GtkColorSelection widget which you'll have to parent
5181 yourself. The GtkColorSelection widget inherits from the GtkVBox
5182 widget.
5183
5184 <tscreen><verb> 
5185 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5186 </verb></tscreen>
5187
5188 This is the most common color selection constructor. It creates a
5189 GtkColorSelectionDialog, which inherits from a GtkDialog. It consists
5190 of a GtkFrame containing a GtkColorSelection widget, a GtkHSeparator
5191 and a GtkHBox with three buttons, "Ok", "Cancel" and "Help". You can
5192 reach these buttons by accessing the "ok_button", "cancel_button" and
5193 "help_button" widgets in the GtkColorSelectionDialog structure,
5194 (i.e. GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
5195
5196 <tscreen><verb>
5197 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
5198                                             GtkUpdateType      policy );
5199 </verb></tscreen>
5200
5201 This function sets the update policy. The default policy is
5202 GTK_UPDATE_CONTINUOUS which means that the current color is updated
5203 continuously when the user drags the sliders or presses the mouse and
5204 drags in the hue-saturation wheel or value bar. If you experience
5205 performance problems, you may want to set the policy to
5206 GTK_UPDATE_DISCONTINUOUS or GTK_UPDATE_DELAYED.
5207
5208 <tscreen><verb>
5209 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
5210                                       gint               use_opacity );
5211 </verb></tscreen>
5212
5213 The color selection widget supports adjusting the opacity of a color
5214 (also known as the alpha channel). This is disabled by
5215 default. Calling this function with use_opacity set to TRUE enables
5216 opacity. Likewise, use_opacity set to FALSE will disable opacity.
5217
5218 <tscreen><verb>
5219 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
5220                                     gdouble           *color );
5221 </verb></tscreen>
5222
5223 You can set the current color explicitly by calling this function with
5224 a pointer to an array of colors (gdouble). The length of the array
5225 depends on whether opacity is enabled or not. Position 0 contains the
5226 red component, 1 is green, 2 is blue and opacity is at position 3
5227 (only if opacity is enabled, see
5228 gtk_color_selection_set_opacity()). All values are between 0.0 and
5229 1.0.
5230
5231 <tscreen><verb>
5232 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
5233                                     gdouble           *color );
5234 </verb></tscreen>
5235
5236 When you need to query the current color, typically when you've
5237 received a "color_changed" signal, you use this function. Color is a
5238 pointer to the array of colors to fill in. See the
5239 gtk_color_selection_set_color() function for the description of this
5240 array.
5241
5242 <!-- Need to do a whole section on DnD - TRG
5243 Drag and drop
5244 -------------
5245
5246 The color sample areas (right under the hue-saturation wheel) supports
5247 drag and drop. The type of drag and drop is "application/x-color". The
5248 message data consists of an array of 4 (or 5 if opacity is enabled)
5249 gdouble values, where the value at position 0 is 0.0 (opacity on) or
5250 1.0 (opacity off) followed by the red, green and blue values at
5251 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
5252 is passed in the value at position 4.
5253 -->
5254
5255 Here's a simple example demonstrating the use of the
5256 GtkColorSelectionDialog. The program displays a window containing a
5257 drawing area. Clicking on it opens a color selection dialog, and
5258 changing the color in the color selection dialog changes the
5259 background color.
5260
5261 <tscreen><verb>
5262 /* example-start colorsel colorsel.c */
5263
5264 #include <glib.h>
5265 #include <gdk/gdk.h>
5266 #include <gtk/gtk.h>
5267
5268 GtkWidget *colorseldlg = NULL;
5269 GtkWidget *drawingarea = NULL;
5270
5271 /* Color changed handler */
5272
5273 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
5274 {
5275   gdouble color[3];
5276   GdkColor gdk_color;
5277   GdkColormap *colormap;
5278
5279   /* Get drawingarea colormap */
5280
5281   colormap = gdk_window_get_colormap (drawingarea->window);
5282
5283   /* Get current color */
5284
5285   gtk_color_selection_get_color (colorsel,color);
5286
5287   /* Fit to a unsigned 16 bit integer (0..65535) and insert into the GdkColor structure */
5288
5289   gdk_color.red = (guint16)(color[0]*65535.0);
5290   gdk_color.green = (guint16)(color[1]*65535.0);
5291   gdk_color.blue = (guint16)(color[2]*65535.0);
5292
5293   /* Allocate color */
5294
5295   gdk_color_alloc (colormap, &amp;gdk_color);
5296
5297   /* Set window background color */
5298
5299   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
5300
5301   /* Clear window */
5302
5303   gdk_window_clear (drawingarea->window);
5304 }
5305
5306 /* Drawingarea event handler */
5307
5308 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
5309 {
5310   gint handled = FALSE;
5311   GtkWidget *colorsel;
5312
5313   /* Check if we've received a button pressed event */
5314
5315   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
5316     {
5317       /* Yes, we have an event and there's no colorseldlg yet! */
5318
5319       handled = TRUE;
5320
5321       /* Create color selection dialog */
5322
5323       colorseldlg = gtk_color_selection_dialog_new("Select background color");
5324
5325       /* Get the GtkColorSelection widget */
5326
5327       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
5328
5329       /* Connect to the "color_changed" signal, set the client-data to the colorsel widget */
5330
5331       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
5332         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
5333
5334       /* Show the dialog */
5335
5336       gtk_widget_show(colorseldlg);
5337     }
5338
5339   return handled;
5340 }
5341
5342 /* Close down and exit handler */
5343
5344 void destroy_window (GtkWidget *widget, gpointer client_data)
5345 {
5346   gtk_main_quit ();
5347 }
5348
5349 /* Main */
5350
5351 gint main (gint argc, gchar *argv[])
5352 {
5353   GtkWidget *window;
5354
5355   /* Initialize the toolkit, remove gtk-related commandline stuff */
5356
5357   gtk_init (&amp;argc,&amp;argv);
5358
5359   /* Create toplevel window, set title and policies */
5360
5361   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5362   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
5363   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
5364
5365   /* Attach to the "delete" and "destroy" events so we can exit */
5366
5367   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
5368     (GtkSignalFunc)destroy_window, (gpointer)window);
5369
5370   gtk_signal_connect (GTK_OBJECT(window), "destroy",
5371     (GtkSignalFunc)destroy_window, (gpointer)window);
5372   
5373   /* Create drawingarea, set size and catch button events */
5374
5375   drawingarea = gtk_drawing_area_new ();
5376
5377   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
5378
5379   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
5380
5381   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
5382     (GtkSignalFunc)area_event, (gpointer)drawingarea);
5383   
5384   /* Add drawingarea to window, then show them both */
5385
5386   gtk_container_add (GTK_CONTAINER(window), drawingarea);
5387
5388   gtk_widget_show (drawingarea);
5389   gtk_widget_show (window);
5390   
5391   /* Enter the gtk main loop (this never returns) */
5392
5393   gtk_main ();
5394
5395   /* Satisfy grumpy compilers */
5396
5397   return(0);
5398 }
5399 /* example-end */
5400 </verb></tscreen>
5401
5402 <!-- ----------------------------------------------------------------- -->
5403 <sect1> File Selections
5404 <p>
5405 The file selection widget is a quick and simple way to display a File
5406 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
5407 great way to cut down on programming time.
5408
5409 To create a new file selection box use:
5410
5411 <tscreen><verb>
5412 GtkWidget *gtk_file_selection_new( gchar *title );
5413 </verb></tscreen>
5414
5415 To set the filename, for example to bring up a specific directory, or
5416 give a default filename, use this function:
5417
5418 <tscreen><verb>
5419 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
5420                                       gchar            *filename );
5421 </verb></tscreen>
5422
5423 To grab the text that the user has entered or clicked on, use this 
5424 function:
5425
5426 <tscreen><verb>
5427 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
5428 </verb></tscreen>
5429
5430 There are also pointers to the widgets contained within the file 
5431 selection widget. These are:
5432
5433 <itemize>
5434 <item>dir_list
5435 <item>file_list
5436 <item>selection_entry
5437 <item>selection_text
5438 <item>main_vbox
5439 <item>ok_button
5440 <item>cancel_button
5441 <item>help_button
5442 </itemize>
5443
5444 Most likely you will want to use the ok_button, cancel_button, and
5445 help_button pointers in signaling their use.
5446
5447 Included here is an example stolen from testgtk.c, modified to run on
5448 its own. As you will see, there is nothing much to creating a file
5449 selection widget. While in this example the Help button appears on the
5450 screen, it does nothing as there is not a signal attached to it.
5451
5452 <tscreen><verb>
5453 /* example-start filesel filesel.c */
5454
5455 #include <gtk/gtk.h>
5456
5457 /* Get the selected filename and print it to the console */
5458 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
5459 {
5460     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
5461 }
5462
5463 void destroy (GtkWidget *widget, gpointer data)
5464 {
5465     gtk_main_quit ();
5466 }
5467
5468 int main (int argc, char *argv[])
5469 {
5470     GtkWidget *filew;
5471     
5472     gtk_init (&amp;argc, &amp;argv);
5473     
5474     /* Create a new file selection widget */
5475     filew = gtk_file_selection_new ("File selection");
5476     
5477     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
5478                         (GtkSignalFunc) destroy, &amp;filew);
5479     /* Connect the ok_button to file_ok_sel function */
5480     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
5481                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
5482     
5483     /* Connect the cancel_button to destroy the widget */
5484     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filew)->cancel_button),
5485                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
5486                                GTK_OBJECT (filew));
5487     
5488     /* Lets set the filename, as if this were a save dialog, and we are giving
5489      a default filename */
5490     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
5491                                      "penguin.png");
5492     
5493     gtk_widget_show(filew);
5494     gtk_main ();
5495     return 0;
5496 }
5497 /* example-end */
5498 </verb></tscreen>
5499
5500 <!-- ***************************************************************** -->
5501 <sect> Container Widgets
5502 <!-- ***************************************************************** -->
5503
5504 <!-- ----------------------------------------------------------------- -->   
5505 <sect1>The EventBox <label id="sec_EventBox">
5506 <p> 
5507 Some GTK widgets don't have associated X windows, so they just draw on
5508 their parents. Because of this, they cannot receive events and if they
5509 are incorrectly sized, they don't clip so you can get messy
5510 overwriting etc. If you require more from these widgets, the EventBox
5511 is for you.
5512
5513 At first glance, the EventBox widget might appear to be totally
5514 useless. It draws nothing on the screen and responds to no
5515 events. However, it does serve a function - it provides an X window
5516 for its child widget. This is important as many GTK widgets do not
5517 have an associated X window. Not having an X window saves memory and
5518 improves performance, but also has some drawbacks. A widget without an
5519 X window cannot receive events, and does not perform any clipping on
5520 its contents. Although the name <em/EventBox/ emphasizes the
5521 event-handling function, the widget can also be used for clipping.
5522 (and more, see the example below).
5523
5524 To create a new EventBox widget, use:
5525
5526 <tscreen><verb>
5527 GtkWidget *gtk_event_box_new( void );
5528 </verb></tscreen>
5529
5530 A child widget can then be added to this EventBox:
5531
5532 <tscreen><verb>
5533     gtk_container_add( GTK_CONTAINER(event_box), child_widget );
5534 </verb></tscreen>
5535
5536 The following example demonstrates both uses of an EventBox - a label
5537 is created that is clipped to a small box, and set up so that a
5538 mouse-click on the label causes the program to exit. Resizing the
5539 window reveals varying amounts of the label.
5540
5541 <tscreen><verb>
5542 /* example-start eventbox eventbox.c */
5543
5544 #include <gtk/gtk.h>
5545
5546 int 
5547 main (int argc, char *argv[])
5548 {
5549     GtkWidget *window;
5550     GtkWidget *event_box;
5551     GtkWidget *label;
5552     
5553     gtk_init (&amp;argc, &amp;argv);
5554     
5555     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5556     
5557     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
5558     
5559     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5560                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5561     
5562     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5563     
5564     /* Create an EventBox and add it to our toplevel window */
5565     
5566     event_box = gtk_event_box_new ();
5567     gtk_container_add (GTK_CONTAINER(window), event_box);
5568     gtk_widget_show (event_box);
5569     
5570     /* Create a long label */
5571     
5572     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
5573     gtk_container_add (GTK_CONTAINER (event_box), label);
5574     gtk_widget_show (label);
5575     
5576     /* Clip it short. */
5577     gtk_widget_set_usize (label, 110, 20);
5578     
5579     /* And bind an action to it */
5580     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
5581     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
5582                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5583     
5584     /* Yet one more thing you need an X window for ... */
5585     
5586     gtk_widget_realize (event_box);
5587     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
5588     
5589     gtk_widget_show (window);
5590     
5591     gtk_main ();
5592     
5593     return(0);
5594 }
5595 /* example-end */
5596 </verb></tscreen>
5597
5598 <!-- ----------------------------------------------------------------- -->   
5599 <sect1>The Alignment widget <label id="sec_Alignment">
5600 <p>
5601 The alignment widget allows you to place a widget within its window at
5602 a position and size relative to the size of the Alignment widget
5603 itself. For example, it can be very useful for centering a widget
5604 within the window.
5605
5606 There are only two functions associated with the Alignment widget:
5607
5608 <tscreen><verb>
5609 GtkWidget* gtk_alignment_new( gfloat xalign,
5610                               gfloat yalign,
5611                               gfloat xscale,
5612                               gfloat yscale );
5613
5614 void gtk_alignment_set( GtkAlignment *alignment,
5615                         gfloat        xalign,
5616                         gfloat        yalign,
5617                         gfloat        xscale,
5618                         gfloat        yscale );
5619 </verb></tscreen>
5620
5621 The first function creates a new Alignment widget with the specified
5622 parameters. The second function allows the alignment paramters of an
5623 exisiting Alignment widget to be altered.
5624
5625 All four alignment parameters are floating point numbers which can
5626 range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
5627 affect the position of the widget placed within the Alignment
5628 widget. The <tt/xscale/ and <tt/yscale/ arguments effect the amount of
5629 space allocated to the widget.
5630
5631 A child widget can be added to this Alignment widget using:
5632
5633 <tscreen><verb>
5634     gtk_container_add( GTK_CONTAINER(alignment), child_widget );
5635 </verb></tscreen>
5636
5637 For an example of using an Alignment widget, refer to the example for
5638 the <ref id="sec_ProgressBar" name="Progress Bar"> widget.
5639
5640 <!-- ----------------------------------------------------------------- -->
5641 <sect1> Fixed Container
5642 <p>
5643 The Fixed container allows you to place widgets at a fixed position
5644 within it's window, relative to it's upper left hand corner. The
5645 position of the widgets can be changed dynamically.
5646
5647 There are only three functions associated with the fixed widget:
5648
5649 <tscreen><verb>
5650 GtkWidget* gtk_fixed_new( void );
5651
5652 void gtk_fixed_put( GtkFixed  *fixed,
5653                     GtkWidget *widget,
5654                     gint16     x,
5655                     gint16     y );
5656
5657 void gtk_fixed_move( GtkFixed  *fixed,
5658                      GtkWidget *widget,
5659                      gint16     x,
5660                      gint16     y );
5661 </verb></tscreen>
5662
5663 The function <tt/gtk_fixed_new/ allows you to create a new Fixed
5664 container.
5665
5666 <tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
5667 the position specified by <tt/x/ and <tt/y/.
5668
5669 <tt/gtk_fixed_move/ allows the specified widget to be moved to a new
5670 position.
5671
5672 The following example illustrates how to use the Fixed Container.
5673
5674 <tscreen><verb>
5675 /* example-start fixed fixed.c */
5676
5677 #include <gtk/gtk.h>
5678
5679 /* I'm going to be lazy and use some global variables to
5680  * store the position of the widget within the fixed
5681  * container */
5682 gint x=50;
5683 gint y=50;
5684
5685 /* This callback function moves the button to a new position
5686  * in the Fixed container. */
5687 void move_button( GtkWidget *widget,
5688                   GtkWidget *fixed )
5689 {
5690   x = (x+30)%300;
5691   y = (y+50)%300;
5692   gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); 
5693 }
5694
5695 int main( int   argc,
5696           char *argv[] )
5697 {
5698   /* GtkWidget is the storage type for widgets */
5699   GtkWidget *window;
5700   GtkWidget *fixed;
5701   GtkWidget *button;
5702   gint i;
5703
5704   /* Initialise GTK */
5705   gtk_init(&amp;argc, &amp;argv);
5706     
5707   /* Create a new window */
5708   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5709   gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
5710
5711   /* Here we connect the "destroy" event to a signal handler */ 
5712   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5713                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5714  
5715   /* Sets the border width of the window. */
5716   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5717
5718   /* Create a Fixed Container */
5719   fixed = gtk_fixed_new();
5720   gtk_container_add(GTK_CONTAINER(window), fixed);
5721   gtk_widget_show(fixed);
5722   
5723   for (i = 1 ; i <= 3 ; i++) {
5724     /* Creates a new button with the label "Press me" */
5725     button = gtk_button_new_with_label ("Press me");
5726   
5727     /* When the button receives the "clicked" signal, it will call the
5728      * function move_button() passing it the Fixed Containter as its
5729      * argument. */
5730     gtk_signal_connect (GTK_OBJECT (button), "clicked",
5731                         GTK_SIGNAL_FUNC (move_button), fixed);
5732   
5733     /* This packs the button into the fixed containers window. */
5734     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
5735   
5736     /* The final step is to display this newly created widget. */
5737     gtk_widget_show (button);
5738   }
5739
5740   /* Display the window */
5741   gtk_widget_show (window);
5742     
5743   /* Enter the event loop */
5744   gtk_main ();
5745     
5746   return(0);
5747 }
5748 /* example-end */
5749 </verb></tscreen>
5750
5751 <!-- ----------------------------------------------------------------- -->
5752 <sect1> Layout Container
5753 <p>
5754 The Layout container is similar to the Fixed container except that it
5755 implements an infinite (where infinity is less than 2^32) scrolling
5756 area. Xwindows has a limitation where windows can be at most 32767
5757 pixels wide or tall. The Layout container gets around this limitation
5758 by doing some exotic stuff using window and bit gravities, so that you
5759 can have smooth scrolling even when you have many child widgets in
5760 your scrolling area.
5761
5762 A Layout container is created using:
5763
5764 <tscreen><verb>
5765 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
5766                            GtkAdjustment *vadjustment );
5767 </verb></tscreen>
5768
5769 As you can see, you can optionally specify the Adjustment objects that
5770 the Layout widget will use for it's scrolling.
5771
5772 You can add and move widgets in the Layout container using the
5773 following two functions:
5774
5775 <tscreen><verb>
5776 void gtk_layout_put( GtkLayout *layout,
5777                      GtkWidget *widget,
5778                      gint       x,
5779                      gint       y );
5780
5781 void gtk_layout_move( GtkLayout *layout,
5782                       GtkWidget *widget,
5783                       gint       x,
5784                       gint       y );
5785 </verb></tscreen>
5786
5787 The size of the Layout container can be set using the next function:
5788
5789 <tscreen><verb>
5790 void gtk_layout_set_size( GtkLayout *layout,
5791                           guint      width,
5792                           guint      height );
5793 </verb></tscreen>
5794
5795 Layout containers are one of the very few widgets in the GTK widget
5796 set that actively repaint themselves on screen as they are changed
5797 using the above functions (the vast majority of widgets queue
5798 requests which are then processed when control returns to the
5799 <tt/gtk_main()/ function).
5800
5801 When you want to make a large number of changes to a Layout container,
5802 you can use the following two functions to disable and re-enable this
5803 repainting functionality:
5804
5805 <tscreen><verb>
5806 void gtk_layout_freeze( GtkLayout *layout );
5807
5808 void gtk_layout_thaw( GtkLayout *layout );
5809 </verb></tscreen>
5810
5811 The final four functions for use with Layout widgets are for
5812 manipulating the horizontal and vertical adjustment widgets:
5813
5814 <tscreen><verb>
5815 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
5816
5817 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
5818
5819 void gtk_layout_set_hadjustment( GtkLayout     *layout,
5820                                  GtkAdjustment *adjustment );
5821
5822 void gtk_layout_set_vadjustment( GtkLayout     *layout,
5823                                  GtkAdjustment *adjustment);
5824 </verb></tscreen>
5825
5826 <!-- ----------------------------------------------------------------- -->
5827 <sect1> Frames <label id="sec_Frames">
5828 <p>
5829 Frames can be used to enclose one or a group of widgets with a box
5830 which can optionally be labelled. The position of the label and the
5831 style of the box can be altered to suit.
5832
5833 A Frame can be created with the following function:
5834
5835 <tscreen><verb>
5836 GtkWidget *gtk_frame_new( const gchar *label );
5837 </verb></tscreen>
5838
5839 The label is by default placed in the upper left hand corner of the
5840 frame. A value of NULL for the <tt/label/ argument will result in no
5841 label being displayed. The text of the label can be changed using the
5842 next function.
5843
5844 <tscreen><verb>
5845 void gtk_frame_set_label( GtkFrame    *frame,
5846                           const gchar *label );
5847 </verb></tscreen>
5848
5849 The position of the label can be changed using this function:
5850
5851 <tscreen><verb>
5852 void gtk_frame_set_label_align( GtkFrame *frame,
5853                                 gfloat    xalign,
5854                                 gfloat    yalign );
5855 </verb></tscreen>
5856
5857 <tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
5858 indicates the position of the label along the top horizontal of the
5859 frame. <tt/yalign/ is not currently used. The default value of xalign
5860 is 0.0 which places the label at the left hand end of the frame.
5861
5862 The next function alters the style of the box that is used to outline
5863 the frame.
5864
5865 <tscreen><verb>
5866 void gtk_frame_set_shadow_type( GtkFrame      *frame,
5867                                 GtkShadowType  type);
5868 </verb></tscreen>
5869
5870 The <tt/type/ argument can take one of the following values:
5871 <itemize>
5872 <item> GTK_SHADOW_NONE
5873 <item> GTK_SHADOW_IN
5874 <item> GTK_SHADOW_OUT
5875 <item> GTK_SHADOW_ETCHED_IN (the default)
5876 <item> GTK_SHADOW_ETCHED_OUT
5877 </itemize>
5878
5879 The following code example illustrates the use of the Frame widget.
5880
5881 <tscreen><verb>
5882 /* example-start frame frame.c */
5883
5884 #include <gtk/gtk.h>
5885
5886 int main( int   argc,
5887           char *argv[] )
5888 {
5889   /* GtkWidget is the storage type for widgets */
5890   GtkWidget *window;
5891   GtkWidget *frame;
5892   GtkWidget *button;
5893   gint i;
5894
5895   /* Initialise GTK */
5896   gtk_init(&amp;argc, &amp;argv);
5897     
5898   /* Create a new window */
5899   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5900   gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
5901
5902   /* Here we connect the "destroy" event to a signal handler */ 
5903   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5904                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5905
5906   gtk_widget_set_usize(window, 300, 300);
5907   /* Sets the border width of the window. */
5908   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5909
5910   /* Create a Frame */
5911   frame = gtk_frame_new(NULL);
5912   gtk_container_add(GTK_CONTAINER(window), frame);
5913
5914   /* Set the frames label */
5915   gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
5916
5917   /* Align the label at the right of the frame */
5918   gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
5919
5920   /* Set the style of the frame */
5921   gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
5922
5923   gtk_widget_show(frame);
5924   
5925   /* Display the window */
5926   gtk_widget_show (window);
5927     
5928   /* Enter the event loop */
5929   gtk_main ();
5930     
5931   return(0);
5932 }
5933 /* example-end */
5934
5935 </verb></tscreen>
5936
5937 <!-- ----------------------------------------------------------------- -->   
5938 <sect1> Aspect Frames
5939 <p>
5940 The aspect frame widget is like a frame widget, except that it also
5941 enforces the aspect ratio (that is, the ratio of the width to the
5942 height) of the child widget to have a certain value, adding extra
5943 space if necessary. This is useful, for instance, if you want to
5944 preview a larger image. The size of the preview should vary when the
5945 user resizes the window, but the aspect ratio needs to always match
5946 the original image.
5947   
5948 To create a new aspect frame use:
5949    
5950 <tscreen><verb>
5951 GtkWidget *gtk_aspect_frame_new( const gchar *label,
5952                                  gfloat       xalign,
5953                                  gfloat       yalign,
5954                                  gfloat       ratio,
5955                                  gint         obey_child);
5956 </verb></tscreen>
5957    
5958 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
5959 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
5960 widget will match the aspect ratio of the ideal size it requests.
5961 Otherwise, it is given by <tt/ratio/.
5962    
5963 To change the options of an existing aspect frame, you can use:
5964    
5965 <tscreen><verb>
5966 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
5967                            gfloat          xalign,
5968                            gfloat          yalign,
5969                            gfloat          ratio,
5970                            gint            obey_child);
5971 </verb></tscreen>
5972    
5973 As an example, the following program uses an AspectFrame to present a
5974 drawing area whose aspect ratio will always be 2:1, no matter how the
5975 user resizes the top-level window.
5976    
5977 <tscreen><verb>
5978 /* example-start aspectframe aspectframe.c */
5979
5980 #include <gtk/gtk.h>
5981    
5982 int
5983 main (int argc, char *argv[])
5984 {
5985     GtkWidget *window;
5986     GtkWidget *aspect_frame;
5987     GtkWidget *drawing_area;
5988     gtk_init (&amp;argc, &amp;argv);
5989    
5990     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5991     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
5992     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5993                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5994     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5995    
5996     /* Create an aspect_frame and add it to our toplevel window */
5997    
5998     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
5999                                          0.5, /* center x */
6000                                          0.5, /* center y */
6001                                          2, /* xsize/ysize = 2 */
6002                                          FALSE /* ignore child's aspect */);
6003    
6004     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
6005     gtk_widget_show (aspect_frame);
6006    
6007     /* Now add a child widget to the aspect frame */
6008    
6009     drawing_area = gtk_drawing_area_new ();
6010    
6011     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6012      * window since we are forcing a 2x1 aspect ratio */
6013     gtk_widget_set_usize (drawing_area, 200, 200);
6014     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
6015     gtk_widget_show (drawing_area);
6016    
6017     gtk_widget_show (window);
6018     gtk_main ();
6019     return 0;
6020 }
6021 /* example-end */
6022 </verb></tscreen>
6023
6024 <!-- ----------------------------------------------------------------- -->   
6025 <sect1> Paned Window Widgets
6026 <p>
6027 The paned window widgets are useful when you want to divide an area
6028 into two parts, with the relative size of the two parts controlled by
6029 the user. A groove is drawn between the two portions with a handle
6030 that the user can drag to change the ratio. The division can either be
6031 horizontal (HPaned) or vertical (VPaned).
6032    
6033 To create a new paned window, call one of:
6034    
6035 <tscreen><verb>
6036 GtkWidget *gtk_hpaned_new (void);
6037
6038 GtkWidget *gtk_vpaned_new (void);
6039 </verb></tscreen>
6040
6041 After creating the paned window widget, you need to add child widgets
6042 to its two halves. To do this, use the functions:
6043    
6044 <tscreen><verb>
6045 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6046
6047 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6048 </verb></tscreen>
6049    
6050 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
6051 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
6052 right or bottom half of the paned window.
6053
6054 A paned widget can be changed visually using the following two
6055 functions.
6056
6057 <tscreen><verb>
6058 void gtk_paned_set_handle_size( GtkPaned *paned,
6059                                 guint16   size);
6060
6061 void gtk_paned_set_gutter_size( GtkPaned *paned,
6062                                 guint16   size);
6063 </verb></tscreen>
6064
6065 The first of these sets the size of the handle and the second sets the
6066 size of the gutter that is between the two parts of the paned window.
6067
6068 As an example, we will create part of the user interface of an
6069 imaginary email program. A window is divided into two portions
6070 vertically, with the top portion being a list of email messages and
6071 the bottom portion the text of the email message. Most of the program
6072 is pretty straightforward. A couple of points to note: text can't be
6073 added to a Text widget until it is realized. This could be done by
6074 calling <tt/gtk_widget_realize()/, but as a demonstration of an
6075 alternate technique, we connect a handler to the "realize" signal to
6076 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
6077 of the items in the table containing the text window and its
6078 scrollbars, so that when the bottom portion is made smaller, the
6079 correct portions shrink instead of being pushed off the bottom of the
6080 window.
6081
6082 <tscreen><verb>
6083 /* example-start paned paned.c */
6084
6085 #include <gtk/gtk.h>
6086    
6087 /* Create the list of "messages" */
6088 GtkWidget *
6089 create_list (void)
6090 {
6091
6092     GtkWidget *scrolled_window;
6093     GtkWidget *list;
6094     GtkWidget *list_item;
6095    
6096     int i;
6097     char buffer[16];
6098    
6099     /* Create a new scrolled window, with scrollbars only if needed */
6100     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6101     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6102                                     GTK_POLICY_AUTOMATIC, 
6103                                     GTK_POLICY_AUTOMATIC);
6104    
6105     /* Create a new list and put it in the scrolled window */
6106     list = gtk_list_new ();
6107     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
6108                                            list);
6109     gtk_widget_show (list);
6110    
6111     /* Add some messages to the window */
6112     for (i=0; i<10; i++) {
6113
6114         sprintf(buffer,"Message #%d",i);
6115         list_item = gtk_list_item_new_with_label (buffer);
6116         gtk_container_add (GTK_CONTAINER(list), list_item);
6117         gtk_widget_show (list_item);
6118
6119     }
6120    
6121     return scrolled_window;
6122 }
6123    
6124 /* Add some text to our text widget - this is a callback that is invoked
6125 when our window is realized. We could also force our window to be
6126 realized with gtk_widget_realize, but it would have to be part of
6127 a hierarchy first */
6128
6129 void
6130 realize_text (GtkWidget *text, gpointer data)
6131 {
6132     gtk_text_freeze (GTK_TEXT (text));
6133     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
6134     "From: pathfinder@nasa.gov\n"
6135     "To: mom@nasa.gov\n"
6136     "Subject: Made it!\n"
6137     "\n"
6138     "We just got in this morning. The weather has been\n"
6139     "great - clear but cold, and there are lots of fun sights.\n"
6140     "Sojourner says hi. See you soon.\n"
6141     " -Path\n", -1);
6142    
6143     gtk_text_thaw (GTK_TEXT (text));
6144 }
6145    
6146 /* Create a scrolled text area that displays a "message" */
6147 GtkWidget *
6148 create_text (void)
6149 {
6150     GtkWidget *table;
6151     GtkWidget *text;
6152     GtkWidget *hscrollbar;
6153     GtkWidget *vscrollbar;
6154    
6155     /* Create a table to hold the text widget and scrollbars */
6156     table = gtk_table_new (2, 2, FALSE);
6157    
6158     /* Put a text widget in the upper left hand corner. Note the use of
6159      * GTK_SHRINK in the y direction */
6160     text = gtk_text_new (NULL, NULL);
6161     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
6162                       GTK_FILL | GTK_EXPAND,
6163                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
6164     gtk_widget_show (text);
6165    
6166     /* Put a HScrollbar in the lower left hand corner */
6167     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
6168     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
6169                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6170     gtk_widget_show (hscrollbar);
6171    
6172     /* And a VScrollbar in the upper right */
6173     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
6174     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
6175                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
6176     gtk_widget_show (vscrollbar);
6177    
6178     /* Add a handler to put a message in the text widget when it is realized */
6179     gtk_signal_connect (GTK_OBJECT (text), "realize",
6180                         GTK_SIGNAL_FUNC (realize_text), NULL);
6181    
6182     return table;
6183 }
6184    
6185 int
6186 main (int argc, char *argv[])
6187 {
6188     GtkWidget *window;
6189     GtkWidget *vpaned;
6190     GtkWidget *list;
6191     GtkWidget *text;
6192
6193     gtk_init (&amp;argc, &amp;argv);
6194    
6195     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6196     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
6197     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6198                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6199     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6200     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
6201
6202     /* create a vpaned widget and add it to our toplevel window */
6203    
6204     vpaned = gtk_vpaned_new ();
6205     gtk_container_add (GTK_CONTAINER(window), vpaned);
6206     gtk_paned_set_handle_size (GTK_PANED(vpaned),
6207                                10);
6208     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
6209                                15);                       
6210     gtk_widget_show (vpaned);
6211    
6212     /* Now create the contents of the two halves of the window */
6213    
6214     list = create_list ();
6215     gtk_paned_add1 (GTK_PANED(vpaned), list);
6216     gtk_widget_show (list);
6217    
6218     text = create_text ();
6219     gtk_paned_add2 (GTK_PANED(vpaned), text);
6220     gtk_widget_show (text);
6221     gtk_widget_show (window);
6222     gtk_main ();
6223     return 0;
6224 }
6225 /* example-end */
6226 </verb></tscreen>
6227
6228 <!-- ----------------------------------------------------------------- -->
6229 <sect1>Viewports <label id="sec_Viewports">
6230 <p>
6231 It is unlikely that you will ever need to use the Viewport widget
6232 directly. You are much more likely to use the
6233 <ref id="sec_ScrolledWindows" name="Scrolled Windows"> widget which
6234 itself uses the Viewport.
6235
6236 A viewport widget allows you to place a larger widget within it such
6237 that you can view a part of it at a time. It uses
6238 <ref id="sec_Adjustment" name="Adjustments"> to define the area that
6239 is currently in view.
6240
6241 A Viewport is created with the function
6242
6243 <tscreen><verb>
6244 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
6245                              GtkAdjustment *vadjustment );
6246 </verb></tscreen>
6247
6248 As you can see you can specify the horizontal and vertical Adjustments
6249 that the widget is to use when you create the widget. It will create
6250 it's own if you pass NULL as the value of the arguments.
6251
6252 You can get and set the adjustments after the widget has been created
6253 using the following four functions:
6254
6255 <tscreen><verb>
6256 GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
6257
6258 GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
6259
6260 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
6261                                    GtkAdjustment *adjustment );
6262
6263 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
6264                                    GtkAdjustment *adjustment );
6265 </verb></tscreen>
6266
6267 The only other viewport function is used to alter its appearance:
6268
6269 <tscreen><verb>
6270 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
6271                                    GtkShadowType  type );
6272 </verb></tscreen>
6273
6274 Possible values for the <tt/type/ parameter are:
6275 <itemize>
6276 <item> GTK_SHADOW_NONE,
6277 <item> GTK_SHADOW_IN,
6278 <item> GTK_SHADOW_OUT,
6279 <item> GTK_SHADOW_ETCHED_IN,
6280 <item> GTK_SHADOW_ETCHED_OUT
6281 </itemize>
6282
6283 <!-- ----------------------------------------------------------------- -->
6284 <sect1>Scrolled Windows <label id="sec_ScrolledWindows">
6285 <p>
6286 Scrolled windows are used to create a scrollable area inside a real
6287 window.  You may insert any type of widget into a scrolled window, and
6288 it will be accessible regardless of the size by using the scrollbars.
6289
6290 The following function is used to create a new scrolled window.
6291
6292 <tscreen><verb>
6293 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
6294                                     GtkAdjustment *vadjustment );
6295 </verb></tscreen>
6296
6297 Where the first argument is the adjustment for the horizontal
6298 direction, and the second, the adjustment for the vertical direction.
6299 These are almost always set to NULL.
6300
6301 <tscreen><verb>
6302 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
6303                                      GtkPolicyType      hscrollbar_policy,
6304                                      GtkPolicyType      vscrollbar_policy );
6305 </verb></tscreen>
6306
6307 This sets the policy to be used with respect to the scrollbars.
6308 The first argument is the scrolled window you wish to change. The second
6309 sets the policy for the horizontal scrollbar, and the third the policy for 
6310 the vertical scrollbar.
6311
6312 The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
6313 GTK_POLICY_AUTOMATIC will automatically decide whether you need
6314 scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6315 there.
6316
6317 You can then place your object into the scrolled window using the
6318 following function.
6319
6320 <tscreen><verb>
6321 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
6322                                             GtkWidget         *child);
6323 </verb></tscreen>
6324
6325 Here is a simple example that packs 100 toggle buttons into a scrolled
6326 window.  I've only commented on the parts that may be new to you.
6327
6328 <tscreen><verb>
6329 /* example-start scrolledwin scrolledwin.c */
6330
6331 #include <gtk/gtk.h>
6332
6333 void destroy(GtkWidget *widget, gpointer data)
6334 {
6335     gtk_main_quit();
6336 }
6337
6338 int main (int argc, char *argv[])
6339 {
6340     static GtkWidget *window;
6341     GtkWidget *scrolled_window;
6342     GtkWidget *table;
6343     GtkWidget *button;
6344     char buffer[32];
6345     int i, j;
6346     
6347     gtk_init (&amp;argc, &amp;argv);
6348     
6349     /* Create a new dialog window for the scrolled window to be
6350      * packed into. A dialog is just like a normal window except it has a 
6351      * vbox and a horizontal separator packed into it. It's just a shortcut
6352      * for creating dialogs */
6353     window = gtk_dialog_new ();
6354     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6355                         (GtkSignalFunc) destroy, NULL);
6356     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
6357     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6358     gtk_widget_set_usize(window, 300, 300);
6359     
6360     /* create a new scrolled window. */
6361     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6362     
6363     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
6364     
6365     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
6366      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
6367      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6368      * there.  The first one is the horizontal scrollbar, the second, 
6369      * the vertical. */
6370     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6371                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
6372     /* The dialog window is created with a vbox packed into it. */                                                              
6373     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
6374                         TRUE, TRUE, 0);
6375     gtk_widget_show (scrolled_window);
6376     
6377     /* create a table of 10 by 10 squares. */
6378     table = gtk_table_new (10, 10, FALSE);
6379     
6380     /* set the spacing to 10 on x and 10 on y */
6381     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
6382     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
6383     
6384     /* pack the table into the scrolled window */
6385     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
6386                                            table);
6387     gtk_widget_show (table);
6388     
6389     /* this simply creates a grid of toggle buttons on the table
6390      * to demonstrate the scrolled window. */
6391     for (i = 0; i < 10; i++)
6392        for (j = 0; j < 10; j++) {
6393           sprintf (buffer, "button (%d,%d)\n", i, j);
6394           button = gtk_toggle_button_new_with_label (buffer);
6395           gtk_table_attach_defaults (GTK_TABLE (table), button,
6396                                      i, i+1, j, j+1);
6397           gtk_widget_show (button);
6398        }
6399     
6400     /* Add a "close" button to the bottom of the dialog */
6401     button = gtk_button_new_with_label ("close");
6402     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6403                                (GtkSignalFunc) gtk_widget_destroy,
6404                                GTK_OBJECT (window));
6405     
6406     /* this makes it so the button is the default. */
6407     
6408     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6409     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
6410     
6411     /* This grabs this button to be the default button. Simply hitting
6412      * the "Enter" key will cause this button to activate. */
6413     gtk_widget_grab_default (button);
6414     gtk_widget_show (button);
6415     
6416     gtk_widget_show (window);
6417     
6418     gtk_main();
6419     
6420     return(0);
6421 }
6422 /* example-end */
6423 </verb></tscreen>
6424
6425 Try playing with resizing the window. You'll notice how the scrollbars
6426 react. You may also wish to use the gtk_widget_set_usize() call to set
6427 the default size of the window or other widgets.
6428
6429 <!-- ----------------------------------------------------------------- -->   
6430 <sect1>Button Boxes
6431 <p>
6432 Button Boxes are a convenient way to quickly layout a group of
6433 buttons. They come in both horizontal and vertical flavours. You
6434 create a new Button Box with one of the following calls, which create
6435 a horizontal or vertical box, respectively:
6436
6437 <tscreen><verb>
6438 GtkWidget *gtk_hbutton_box_new( void );
6439
6440 GtkWidget *gtk_vbutton_box_new( void );
6441 </verb></tscreen>
6442
6443 The only attributes pertaining to button boxes effect how the buttons
6444 are layed out. You can change the spacing between the buttons with:
6445
6446 <tscreen><verb>
6447 void gtk_hbutton_box_set_spacing_default( gint spacing );
6448
6449 void gtk_vbutton_box_set_spacing_default( gint spacing );
6450 </verb></tscreen>
6451
6452 Similarly, the current spacing values can be queried using:
6453
6454 <tscreen><verb>
6455 gint gtk_hbutton_box_get_spacing_default( void );
6456
6457 gint gtk_vbutton_box_get_spacing_default( void );
6458 </verb></tscreen>
6459
6460 The second attribute that we can access effects the layour of the
6461 buttons within the box. It is set using one of:
6462
6463 <tscreen><verb>
6464 void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6465
6466 void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6467 </verb></tscreen>
6468
6469 The <tt/layout/ argument can take one of the following values:
6470
6471 <itemize>
6472 <item> GTK_BUTTONBOX_DEFAULT_STYLE
6473 <item> GTK_BUTTONBOX_SPREAD
6474 <item> GTK_BUTTONBOX_EDGE
6475 <item> GTK_BUTTONBOX_START
6476 <item> GTK_BUTTONBOX_END
6477 </itemize>
6478
6479 The current layout setting can be retrieved using:
6480
6481 <tscreen><verb>
6482 GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
6483
6484 GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
6485 </verb></tscreen>
6486
6487 Buttons are added to a Button Box using the usual function:
6488
6489 <tscreen><verb>
6490     gtk_container_add( GTK_CONTAINER(button_box), child_widget );
6491 </verb></tscreen>
6492
6493 Here's an example that illustrates all the different layout settings
6494 for Button Boxes.
6495
6496 <tscreen><verb>
6497 /* example-start buttonbox buttonbox.c */
6498
6499 #include <gtk/gtk.h>
6500
6501 /* Create a Button Box with the specified parameters */
6502 GtkWidget *create_bbox (gint  horizontal,
6503                         char* title,
6504                         gint  spacing,
6505                         gint  child_w,
6506                         gint  child_h,
6507                         gint  layout)
6508 {
6509   GtkWidget *frame;
6510   GtkWidget *bbox;
6511   GtkWidget *button;
6512
6513   frame = gtk_frame_new (title);
6514
6515   if (horizontal)
6516     bbox = gtk_hbutton_box_new ();
6517   else
6518     bbox = gtk_vbutton_box_new ();
6519
6520   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
6521   gtk_container_add (GTK_CONTAINER (frame), bbox);
6522
6523   /* Set the appearance of the Button Box */
6524   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
6525   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
6526   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
6527
6528   button = gtk_button_new_with_label ("OK");
6529   gtk_container_add (GTK_CONTAINER (bbox), button);
6530
6531   button = gtk_button_new_with_label ("Cancel");
6532   gtk_container_add (GTK_CONTAINER (bbox), button);
6533
6534   button = gtk_button_new_with_label ("Help");
6535   gtk_container_add (GTK_CONTAINER (bbox), button);
6536
6537   return(frame);
6538 }
6539
6540 int main( int   argc,
6541           char *argv[] )
6542 {
6543   static GtkWidget* window = NULL;
6544   GtkWidget *main_vbox;
6545   GtkWidget *vbox;
6546   GtkWidget *hbox;
6547   GtkWidget *frame_horz;
6548   GtkWidget *frame_vert;
6549
6550   /* Initialize GTK */
6551   gtk_init( &amp;argc, &amp;argv );
6552
6553   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6554   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
6555
6556   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6557                       GTK_SIGNAL_FUNC(gtk_main_quit),
6558                       NULL);
6559
6560   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6561
6562   main_vbox = gtk_vbox_new (FALSE, 0);
6563   gtk_container_add (GTK_CONTAINER (window), main_vbox);
6564
6565   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
6566   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
6567
6568   vbox = gtk_vbox_new (FALSE, 0);
6569   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6570   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
6571
6572   gtk_box_pack_start (GTK_BOX (vbox),
6573            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
6574                       TRUE, TRUE, 0);
6575
6576   gtk_box_pack_start (GTK_BOX (vbox),
6577            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6578                       TRUE, TRUE, 5);
6579
6580   gtk_box_pack_start (GTK_BOX (vbox),
6581            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6582                       TRUE, TRUE, 5);
6583
6584   gtk_box_pack_start (GTK_BOX (vbox),
6585            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
6586                       TRUE, TRUE, 5);
6587
6588   frame_vert = gtk_frame_new ("Vertical Button Boxes");
6589   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
6590
6591   hbox = gtk_hbox_new (FALSE, 0);
6592   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6593   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
6594
6595   gtk_box_pack_start (GTK_BOX (hbox),
6596            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
6597                       TRUE, TRUE, 0);
6598
6599   gtk_box_pack_start (GTK_BOX (hbox),
6600            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6601                       TRUE, TRUE, 5);
6602
6603   gtk_box_pack_start (GTK_BOX (hbox),
6604            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6605                       TRUE, TRUE, 5);
6606
6607   gtk_box_pack_start (GTK_BOX (hbox),
6608            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
6609                       TRUE, TRUE, 5);
6610
6611   gtk_widget_show_all (window);
6612
6613   /* Enter the event loop */
6614   gtk_main ();
6615     
6616   return(0);
6617 }
6618 /* example-end */
6619 </verb></tscreen>
6620
6621 <!-- ----------------------------------------------------------------- -->   
6622 <sect1>Toolbar
6623 <p>
6624 Toolbars are usually used to group some number of widgets in order to
6625 simplify customization of their look and layout. Typically a toolbar
6626 consists of buttons with icons, labels and tooltips, but any other
6627 widget can also be put inside a toolbar. Finally, items can be
6628 arranged horizontally or vertically and buttons can be displayed with
6629 icons, labels or both.
6630
6631 Creating a toolbar is (as one may already suspect) done with the
6632 following function:
6633
6634 <tscreen><verb>
6635 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
6636                             GtkToolbarStyle  style );
6637 </verb></tscreen>
6638
6639 where orientation may be one of:
6640
6641 <tscreen><verb>
6642   GTK_ORIENTATION_HORIZONTAL    
6643   GTK_ORIENTATION_VERTICAL
6644 </verb></tscreen>
6645
6646 and style one of:
6647
6648 <tscreen><verb>
6649   GTK_TOOLBAR_TEXT
6650   GTK_TOOLBAR_ICONS
6651   GTK_TOOLBAR_BOTH
6652 </verb></tscreen>
6653
6654 The style applies to all the buttons created with the `item' functions
6655 (not to buttons inserted into toolbar as separate widgets).
6656
6657 After creating a toolbar one can append, prepend and insert items
6658 (that means simple buttons) into the toolbar. To describe an item we
6659 need a label text, a tooltip text, a private tooltip text, an icon for
6660 the button and a callback function for it. For example, to append or
6661 prepend an item you may use the following functions:
6662
6663 <tscreen><verb>
6664 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
6665                                     const char    *text,
6666                                     const char    *tooltip_text,
6667                                     const char    *tooltip_private_text,
6668                                     GtkWidget     *icon,
6669                                     GtkSignalFunc  callback,
6670                                     gpointer       user_data );
6671
6672 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
6673                                      const char    *text,
6674                                      const char    *tooltip_text,
6675                                      const char    *tooltip_private_text,
6676                                      GtkWidget     *icon,
6677                                      GtkSignalFunc  callback,
6678                                      gpointer       user_data );
6679 </verb></tscreen>
6680
6681 If you want to use gtk_toolbar_insert_item, the only additional
6682 parameter which must be specified is the position in which the item
6683 should be inserted, thus:
6684
6685 <tscreen><verb>
6686 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
6687                                     const char    *text,
6688                                     const char    *tooltip_text,
6689                                     const char    *tooltip_private_text,
6690                                     GtkWidget     *icon,
6691                                     GtkSignalFunc  callback,
6692                                     gpointer       user_data,
6693                                     gint           position );
6694 </verb></tscreen>
6695
6696 To simplify adding spaces between toolbar items, you may use the
6697 following functions:
6698
6699 <tscreen><verb>
6700 void gtk_toolbar_append_space( GtkToolbar *toolbar );
6701
6702 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
6703
6704 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
6705                                gint        position );
6706  
6707 </verb></tscreen>
6708
6709 While the size of the added space can be set globally for a
6710 whole toolbar with the function:
6711
6712 <tscreen><verb>
6713 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
6714                                  gint        space_size) ;
6715 </verb></tscreen>
6716
6717 If it's required, the orientation of a toolbar and its style can be
6718 changed `on the fly' using the following functions:
6719
6720 <tscreen><verb>
6721 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
6722                                   GtkOrientation  orientation );
6723
6724 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
6725                             GtkToolbarStyle  style );
6726
6727 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
6728                                gint        enable );
6729 </verb></tscreen>
6730
6731 Where <tt/orientation/ is one of GTK_ORIENTATION_HORIZONTAL or
6732 GTK_ORIENTATION_VERTICAL. The <tt/style/ is used to set appearance of
6733 the toolbar items by using one of GTK_TOOLBAR_ICONS, GTK_TOOLBAR_TEXT
6734 or GTK_TOOLBAR_BOTH.
6735
6736 To show some other things that can be done with a toolbar, let's take
6737 the following program (we'll interrupt the listing with some
6738 additional explanations):
6739
6740 <tscreen><verb>
6741 #include <gtk/gtk.h>
6742
6743 #include "gtk.xpm"
6744
6745 /* This function is connected to the Close button or
6746  * closing the window from the WM */
6747 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
6748 {
6749   gtk_main_quit ();
6750 }
6751 </verb></tscreen>
6752
6753 The above beginning seems for sure familiar to you if it's not your first
6754 GTK program. There is one additional thing though, we include a nice XPM
6755 picture to serve as an icon for all of the buttons.
6756
6757 <tscreen><verb>
6758 GtkWidget* close_button; // this button will emit signal to close application
6759 GtkWidget* tooltips_button; // to enable/disable tooltips
6760 GtkWidget* text_button,
6761          * icon_button,
6762          * both_button; // radio buttons for toolbar style
6763 GtkWidget* entry; // a text entry to show packing any widget into toolbar
6764 </verb></tscreen>
6765
6766 In fact not all of the above widgets are needed here, but to make things
6767 clearer I put them all together.
6768
6769 <tscreen><verb>
6770 /* that's easy... when one of the buttons is toggled, we just
6771  * check which one is active and set the style of the toolbar
6772  * accordingly
6773  * ATTENTION: our toolbar is passed as data to callback ! */
6774 void radio_event (GtkWidget *widget, gpointer data)
6775 {
6776   if (GTK_TOGGLE_BUTTON (text_button)->active) 
6777     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
6778   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
6779     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
6780   else if (GTK_TOGGLE_BUTTON (both_button)->active)
6781     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
6782 }
6783
6784 /* even easier, just check given toggle button and enable/disable 
6785  * tooltips */
6786 void toggle_event (GtkWidget *widget, gpointer data)
6787 {
6788   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
6789                             GTK_TOGGLE_BUTTON (widget)->active );
6790 }
6791 </verb></tscreen>
6792
6793 The above are just two callback functions that will be called when
6794 one of the buttons on a toolbar is pressed. You should already be
6795 familiar with things like this if you've already used toggle buttons (and
6796 radio buttons).
6797
6798 <tscreen><verb>
6799 int main (int argc, char *argv[])
6800 {
6801   /* Here is our main window (a dialog) and a handle for the handlebox */
6802   GtkWidget* dialog;
6803   GtkWidget* handlebox;
6804
6805   /* Ok, we need a toolbar, an icon with a mask (one for all of 
6806      the buttons) and an icon widget to put this icon in (but 
6807      we'll create a separate widget for each button) */
6808   GtkWidget * toolbar;
6809   GdkPixmap * icon;
6810   GdkBitmap * mask;
6811   GtkWidget * iconw;
6812
6813   /* this is called in all GTK application. */
6814   gtk_init (&amp;argc, &amp;argv);
6815   
6816   /* create a new window with a given title, and nice size */
6817   dialog = gtk_dialog_new ();
6818   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
6819   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
6820   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
6821
6822   /* typically we quit if someone tries to close us */
6823   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
6824                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
6825
6826   /* we need to realize the window because we use pixmaps for 
6827    * items on the toolbar in the context of it */
6828   gtk_widget_realize ( dialog );
6829
6830   /* to make it nice we'll put the toolbar into the handle box, 
6831    * so that it can be detached from the main window */
6832   handlebox = gtk_handle_box_new ();
6833   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
6834                        handlebox, FALSE, FALSE, 5 );
6835 </verb></tscreen>
6836
6837 The above should be similar to any other GTK application. Just
6838 initialization of GTK, creating the window etc.. There is only one
6839 thing that probably needs some explanation: a handle box. A handle box
6840 is just another box that can be used to pack widgets in to. The
6841 difference between it and typical boxes is that it can be detached
6842 from a parent window (or, in fact, the handle box remains in the
6843 parent, but it is reduced to a very small rectangle, while all of its
6844 contents are reparented to a new freely floating window). It is
6845 usually nice to have a detachable toolbar, so these two widgets occur
6846 together quite often.
6847
6848 <tscreen><verb>
6849   /* toolbar will be horizontal, with both icons and text, and
6850    * with 5pxl spaces between items and finally, 
6851    * we'll also put it into our handlebox */
6852   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
6853                               GTK_TOOLBAR_BOTH );
6854   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
6855   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
6856   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
6857
6858   /* now we create icon with mask: we'll reuse it to create
6859    * icon widgets for toolbar items */
6860   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
6861       &amp;dialog->style->white, gtk_xpm );
6862 </verb></tscreen>
6863
6864 Well, what we do above is just a straight-forward initialization of
6865 the toolbar widget and creation of a GDK pixmap with its mask. If you
6866 want to know something more about using pixmaps, refer to GDK
6867 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
6868 earlier in this tutorial.
6869
6870 <tscreen><verb>
6871   /* our first item is <close> button */
6872   iconw = gtk_pixmap_new ( icon, mask ); // icon widget
6873   close_button = 
6874     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), // our toolbar
6875                               "Close",               // button label
6876                               "Closes this app",     // tooltip for this button
6877                               "Private",             // tooltip private string
6878                               iconw,                 // icon widget
6879                               GTK_SIGNAL_FUNC (delete_event), // a signal
6880                               NULL );
6881   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); // space after item
6882 </verb></tscreen>
6883
6884 In the above code you see the simplest case: adding a button to
6885 toolbar.  Just before appending a new item, we have to construct a
6886 pixmap widget to serve as an icon for this item; this step will have
6887 to be repeated for each new item. Just after the item we also add a
6888 space, so the following items will not touch each other. As you see
6889 gtk_toolbar_append_item returns a pointer to our newly created button
6890 widget, so that we can work with it in the normal way.
6891
6892 <tscreen><verb>
6893   /* now, let's make our radio buttons group... */
6894   iconw = gtk_pixmap_new ( icon, mask );
6895   icon_button = 
6896     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6897                                GTK_TOOLBAR_CHILD_RADIOBUTTON, // a type of element
6898                                NULL,                          // pointer to widget
6899                                "Icon",                        // label
6900                                "Only icons in toolbar",       // tooltip
6901                                "Private",                     // tooltip private string
6902                                iconw,                         // icon
6903                                GTK_SIGNAL_FUNC (radio_event), // signal
6904                                toolbar);                      // data for signal
6905   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6906 </verb></tscreen>
6907
6908 Here we begin creating a radio buttons group. To do this we use
6909 gtk_toolbar_append_element.  In fact, using this function one can also
6910 add simple items or even spaces (type = GTK_TOOLBAR_CHILD_SPACE or
6911 GTK_TOOLBAR_CHILD_BUTTON). In the above case we start creating a radio
6912 group. In creating other radio buttons for this group a pointer to the
6913 previous button in the group is required, so that a list of buttons
6914 can be easily constructed (see the section on <ref
6915 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
6916 tutorial).
6917
6918 <tscreen><verb>
6919   /* following radio buttons refer to previous ones */
6920   iconw = gtk_pixmap_new ( icon, mask );
6921   text_button = 
6922     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6923                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
6924                                icon_button,
6925                                "Text",
6926                                "Only texts in toolbar",
6927                                "Private",
6928                                iconw,
6929                                GTK_SIGNAL_FUNC (radio_event),
6930                                toolbar);
6931   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6932                                           
6933   iconw = gtk_pixmap_new ( icon, mask );
6934   both_button = 
6935     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6936                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
6937                                text_button,
6938                                "Both",
6939                                "Icons and text in toolbar",
6940                                "Private",
6941                                iconw,
6942                                GTK_SIGNAL_FUNC (radio_event),
6943                                toolbar);
6944   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6945   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
6946 </verb></tscreen>
6947
6948 In the end we have set the state of one of the buttons manually (otherwise
6949 they all stay in active state, preventing us from switching between them).
6950
6951 <tscreen><verb>
6952   /* here we have just a simple toggle button */
6953   iconw = gtk_pixmap_new ( icon, mask );
6954   tooltips_button = 
6955     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
6956                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
6957                                NULL,
6958                                "Tooltips",
6959                                "Toolbar with or without tips",
6960                                "Private",
6961                                iconw,
6962                                GTK_SIGNAL_FUNC (toggle_event),
6963                                toolbar);
6964   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
6965   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
6966 </verb></tscreen>
6967
6968 A toggle button can be created in the obvious way (if one knows how to create
6969 radio buttons already).
6970
6971 <tscreen><verb>
6972   /* to pack a widget into toolbar, we only have to 
6973    * create it and append it with an appropriate tooltip */
6974   entry = gtk_entry_new ();
6975   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
6976                              entry, 
6977                              "This is just an entry", 
6978                              "Private" );
6979
6980   /* well, it isn't created within thetoolbar, so we must still show it */
6981   gtk_widget_show ( entry );
6982 </verb></tscreen>
6983
6984 As you see, adding any kind of widget to a toolbar is simple. The
6985 one thing you have to remember is that this widget must be shown manually
6986 (contrary to other items which will be shown together with the toolbar).
6987
6988 <tscreen><verb>
6989   /* that's it ! let's show everything. */
6990   gtk_widget_show ( toolbar );
6991   gtk_widget_show (handlebox);
6992   gtk_widget_show ( dialog );
6993
6994   /* rest in gtk_main and wait for the fun to begin! */
6995   gtk_main ();
6996   
6997   return 0;
6998 }
6999 </verb></tscreen>
7000
7001 So, here we are at the end of toolbar tutorial. Of course, to appreciate
7002 it in full you need also this nice XPM icon, so here it is:
7003
7004 <tscreen><verb>
7005 /* XPM */
7006 static char * gtk_xpm[] = {
7007 "32 39 5 1",
7008 ".      c none",
7009 "+      c black",
7010 "@      c #3070E0",
7011 "#      c #F05050",
7012 "$      c #35E035",
7013 "................+...............",
7014 "..............+++++.............",
7015 "............+++++@@++...........",
7016 "..........+++++@@@@@@++.........",
7017 "........++++@@@@@@@@@@++........",
7018 "......++++@@++++++++@@@++.......",
7019 ".....+++@@@+++++++++++@@@++.....",
7020 "...+++@@@@+++@@@@@@++++@@@@+....",
7021 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7022 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7023 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7024 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7025 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7026 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7027 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7028 ".+######++++@@@@@@@++@$$$$$$$$+.",
7029 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7030 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7031 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7032 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7033 ".+####+++++++#++$$@+@$$++$$$$+..",
7034 ".++####++++++#++$$@+@$++@$$$$+..",
7035 ".+#####+++++##++$$++@+++$$$$$+..",
7036 ".++####+++##+#++$$+++++@$$$$$+..",
7037 ".++####+++####++$$++++++@$$$@+..",
7038 ".+#####++#####++$$+++@++++@$@+..",
7039 ".+#####++#####++$$++@$$@+++$@@..",
7040 ".++####++#####++$$++$$$$$+@$@++.",
7041 ".++####++#####++$$++$$$$$$$$+++.",
7042 ".+++####+#####++$$++$$$$$$$@+++.",
7043 "..+++#########+@$$+@$$$$$$+++...",
7044 "...+++########+@$$$$$$$$@+++....",
7045 ".....+++######+@$$$$$$$+++......",
7046 "......+++#####+@$$$$$@++........",
7047 ".......+++####+@$$$$+++.........",
7048 ".........++###+$$$@++...........",
7049 "..........++##+$@+++............",
7050 "...........+++++++..............",
7051 ".............++++..............."};
7052 </verb></tscreen>
7053
7054 <!-- ----------------------------------------------------------------- -->
7055 <sect1> Notebooks
7056 <p>
7057 The NoteBook Widget is a collection of 'pages' that overlap each
7058 other, each page contains different information. This widget has
7059 become more common lately in GUI programming, and it is a good way to
7060 show blocks of similar information that warrant separation in their
7061 display.
7062
7063 The first function call you will need to know, as you can probably
7064 guess by now, is used to create a new notebook widget.
7065
7066 <tscreen><verb>
7067 GtkWidget *gtk_notebook_new( void );
7068 </verb></tscreen>
7069
7070 Once the notebook has been created, there are a number of functions
7071 that operate on the notebook widget. Let's look at them individually.
7072
7073 The first one we will look at is how to position the page indicators.
7074 These page indicators or 'tabs' as they are referred to, can be
7075 positioned in four ways: top, bottom, left, or right.
7076
7077 <tscreen><verb>
7078 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7079                                GtkPositionType  pos );
7080 </verb></tscreen>
7081
7082 GtkPostionType will be one of the following, and they are pretty self explanatory:
7083 <itemize>
7084 <item> GTK_POS_LEFT
7085 <item> GTK_POS_RIGHT
7086 <item> GTK_POS_TOP
7087 <item> GTK_POS_BOTTOM
7088 </itemize>
7089
7090 GTK_POS_TOP is the default.
7091
7092 Next we will look at how to add pages to the notebook. There are three
7093 ways to add pages to the NoteBook. Let's look at the first two
7094 together as they are quite similar.
7095
7096 <tscreen><verb>
7097 void gtk_notebook_append_page( GtkNotebook *notebook,
7098                                GtkWidget   *child,
7099                                GtkWidget   *tab_label );
7100
7101 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7102                                 GtkWidget   *child,
7103                                 GtkWidget   *tab_label );
7104 </verb></tscreen>
7105
7106 These functions add pages to the notebook by inserting them from the
7107 back of the notebook (append), or the front of the notebook (prepend).
7108 <tt/child/ is the widget that is placed within the notebook page, and
7109 <tt/tab_label/ is the label for the page being added. The <tt/child/
7110 widget must be created separately, and is typically a set of options
7111 setout witin one of the other container widgets, such as a table.
7112
7113 The final function for adding a page to the notebook contains all of
7114 the properties of the previous two, but it allows you to specify what
7115 position you want the page to be in the notebook.
7116
7117 <tscreen><verb>
7118 void gtk_notebook_insert_page( GtkNotebook *notebook,
7119                                GtkWidget   *child,
7120                                GtkWidget   *tab_label,
7121                                gint         position );
7122 </verb></tscreen>
7123
7124 The parameters are the same as _append_ and _prepend_ except it
7125 contains an extra parameter, <tt/position/.  This parameter is used to
7126 specify what place this page will be inserted into.
7127
7128 Now that we know how to add a page, lets see how we can remove a page
7129 from the notebook.
7130
7131 <tscreen><verb>
7132 void gtk_notebook_remove_page( GtkNotebook *notebook,
7133                                gint         page_num );
7134 </verb></tscreen>
7135
7136 This function takes the page specified by <tt/page_num/ and removes it
7137 from the widget pointed to by <tt/notebook/.
7138
7139 To find out what the current page is in a notebook use the function:
7140
7141 <tscreen><verb>
7142 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7143 </verb></tscreen>
7144
7145 These next two functions are simple calls to move the notebook page
7146 forward or backward. Simply provide the respective function call with
7147 the notebook widget you wish to operate on. Note: when the NoteBook is
7148 currently on the last page, and gtk_notebook_next_page is called, the
7149 notebook will wrap back to the first page. Likewise, if the NoteBook
7150 is on the first page, and gtk_notebook_prev_page is called, the
7151 notebook will wrap to the last page.
7152
7153 <tscreen><verb>
7154 void gtk_notebook_next_page( GtkNoteBook *notebook );
7155
7156 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7157 </verb></tscreen>
7158
7159 This next function sets the 'active' page. If you wish the notebook to
7160 be opened to page 5 for example, you would use this function.  Without
7161 using this function, the notebook defaults to the first page.
7162
7163 <tscreen><verb>
7164 void gtk_notebook_set_page( GtkNotebook *notebook,
7165                             gint         page_num );
7166 </verb></tscreen>
7167
7168 The next two functions add or remove the notebook page tabs and the
7169 notebook border respectively.
7170
7171 <tscreen><verb>
7172 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7173                                  gboolean     show_tabs);
7174
7175 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7176                                    gboolean     show_border );
7177 </verb></tscreen>
7178
7179 The next function is useful when the you have a large number of pages,
7180 and the tabs don't fit on the page. It allows the tabs to be scrolled
7181 through using two arrow buttons.
7182
7183 <tscreen><verb>
7184 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7185                                   gboolean     scrollable );
7186 </verb></tscreen>
7187
7188 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
7189 TRUE or FALSE.
7190
7191 Now lets look at an example, it is expanded from the testgtk.c code
7192 that comes with the GTK distribution. This small program creates a
7193 window with a notebook and six buttons. The notebook contains 11
7194 pages, added in three different ways, appended, inserted, and
7195 prepended. The buttons allow you rotate the tab positions, add/remove
7196 the tabs and border, remove a page, change pages in both a forward and
7197 backward manner, and exit the program.
7198
7199 <tscreen><verb>
7200 /* example-start notebook notebook.c */
7201
7202 #include <gtk/gtk.h>
7203
7204 /* This function rotates the position of the tabs */
7205 void rotate_book (GtkButton *button, GtkNotebook *notebook)
7206 {
7207     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
7208 }
7209
7210 /* Add/Remove the page tabs and the borders */
7211 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
7212 {
7213     gint tval = FALSE;
7214     gint bval = FALSE;
7215     if (notebook->show_tabs == 0)
7216             tval = TRUE; 
7217     if (notebook->show_border == 0)
7218             bval = TRUE;
7219     
7220     gtk_notebook_set_show_tabs (notebook, tval);
7221     gtk_notebook_set_show_border (notebook, bval);
7222 }
7223
7224 /* Remove a page from the notebook */
7225 void remove_book (GtkButton *button, GtkNotebook *notebook)
7226 {
7227     gint page;
7228     
7229     page = gtk_notebook_get_current_page(notebook);
7230     gtk_notebook_remove_page (notebook, page);
7231     /* Need to refresh the widget -- 
7232      This forces the widget to redraw itself. */
7233     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
7234 }
7235
7236 void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
7237 {
7238     gtk_main_quit ();
7239 }
7240
7241 int main (int argc, char *argv[])
7242 {
7243     GtkWidget *window;
7244     GtkWidget *button;
7245     GtkWidget *table;
7246     GtkWidget *notebook;
7247     GtkWidget *frame;
7248     GtkWidget *label;
7249     GtkWidget *checkbutton;
7250     int i;
7251     char bufferf[32];
7252     char bufferl[32];
7253     
7254     gtk_init (&amp;argc, &amp;argv);
7255     
7256     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7257     
7258     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
7259                         GTK_SIGNAL_FUNC (delete), NULL);
7260     
7261     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7262
7263     table = gtk_table_new(3,6,FALSE);
7264     gtk_container_add (GTK_CONTAINER (window), table);
7265     
7266     /* Create a new notebook, place the position of the tabs */
7267     notebook = gtk_notebook_new ();
7268     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
7269     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
7270     gtk_widget_show(notebook);
7271     
7272     /* Lets append a bunch of pages to the notebook */
7273     for (i=0; i < 5; i++) {
7274         sprintf(bufferf, "Append Frame %d", i+1);
7275         sprintf(bufferl, "Page %d", i+1);
7276         
7277         frame = gtk_frame_new (bufferf);
7278         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7279         gtk_widget_set_usize (frame, 100, 75);
7280         gtk_widget_show (frame);
7281         
7282         label = gtk_label_new (bufferf);
7283         gtk_container_add (GTK_CONTAINER (frame), label);
7284         gtk_widget_show (label);
7285         
7286         label = gtk_label_new (bufferl);
7287         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
7288     }
7289       
7290     /* Now lets add a page to a specific spot */
7291     checkbutton = gtk_check_button_new_with_label ("Check me please!");
7292     gtk_widget_set_usize(checkbutton, 100, 75);
7293     gtk_widget_show (checkbutton);
7294    
7295     label = gtk_label_new ("Add page");
7296     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
7297     
7298     /* Now finally lets prepend pages to the notebook */
7299     for (i=0; i < 5; i++) {
7300         sprintf(bufferf, "Prepend Frame %d", i+1);
7301         sprintf(bufferl, "PPage %d", i+1);
7302         
7303         frame = gtk_frame_new (bufferf);
7304         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7305         gtk_widget_set_usize (frame, 100, 75);
7306         gtk_widget_show (frame);
7307         
7308         label = gtk_label_new (bufferf);
7309         gtk_container_add (GTK_CONTAINER (frame), label);
7310         gtk_widget_show (label);
7311         
7312         label = gtk_label_new (bufferl);
7313         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
7314     }
7315     
7316     /* Set what page to start at (page 4) */
7317     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
7318
7319     /* Create a bunch of buttons */
7320     button = gtk_button_new_with_label ("close");
7321     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7322                                GTK_SIGNAL_FUNC (delete), NULL);
7323     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
7324     gtk_widget_show(button);
7325     
7326     button = gtk_button_new_with_label ("next page");
7327     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7328                                (GtkSignalFunc) gtk_notebook_next_page,
7329                                GTK_OBJECT (notebook));
7330     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
7331     gtk_widget_show(button);
7332     
7333     button = gtk_button_new_with_label ("prev page");
7334     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7335                                (GtkSignalFunc) gtk_notebook_prev_page,
7336                                GTK_OBJECT (notebook));
7337     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
7338     gtk_widget_show(button);
7339     
7340     button = gtk_button_new_with_label ("tab position");
7341     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7342                         (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
7343     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
7344     gtk_widget_show(button);
7345     
7346     button = gtk_button_new_with_label ("tabs/border on/off");
7347     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7348                         (GtkSignalFunc) tabsborder_book,
7349                         GTK_OBJECT (notebook));
7350     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
7351     gtk_widget_show(button);
7352     
7353     button = gtk_button_new_with_label ("remove page");
7354     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7355                         (GtkSignalFunc) remove_book,
7356                         GTK_OBJECT(notebook));
7357     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
7358     gtk_widget_show(button);
7359     
7360     gtk_widget_show(table);
7361     gtk_widget_show(window);
7362     
7363     gtk_main ();
7364     
7365     return(0);
7366 }
7367 /* example-end */
7368 </verb></tscreen>
7369
7370 Hopefully this helps you on your way with creating notebooks for your
7371 GTK applications.
7372
7373 <!-- ***************************************************************** -->
7374 <sect>CList Widget
7375 <!-- ***************************************************************** -->
7376
7377 <!-- ----------------------------------------------------------------- -->
7378 <p>
7379 The GtkCList widget has replaced the GtkList widget (which is still
7380 available).
7381
7382 The GtkCList widget is a multi-column list widget that is capable of
7383 handling literally thousands of rows of information. Each column can
7384 optionally have a title, which itself is optionally active, allowing
7385 us to bind a function to its selection.
7386
7387 <!-- ----------------------------------------------------------------- -->
7388 <sect1>Creating a GtkCList widget
7389 <p>
7390 Creating a GtkCList is quite straightforward, once you have learned
7391 about widgets in general. It provides the almost standard two ways,
7392 that is the hard way, and the easy way. But before we create it, there
7393 is one thing we should figure out beforehand: how many columns should
7394 it have?
7395
7396 Not all columns have to be visible and can be used to store data that
7397 is related to a certain cell in the list.
7398
7399 <tscreen><verb>
7400 GtkWidget *gtk_clist_new ( gint columns );
7401
7402 GtkWidget *gtk_clist_new_with_titles( gint   columns,
7403                                       gchar *titles[] );
7404 </verb></tscreen>
7405
7406 The first form is very straight forward, the second might require some
7407 explanation. Each column can have a title associated with it, and this
7408 title can be a label or a button that reacts when we click on it. If
7409 we use the second form, we must provide pointers to the title texts,
7410 and the number of pointers should equal the number of columns
7411 specified. Of course we can always use the first form, and manually
7412 add titles later.
7413
7414 Note: the GtkCList widget does not have it's own scrollbars and should
7415 be placed within a GtkScrolledWindow widget if your require this
7416 functionality. This is a change from the GTK 1.0 implementation.
7417
7418 <!-- ----------------------------------------------------------------- -->
7419 <sect1>Modes of operation
7420 <p>
7421 There are several attributes that can be used to alter the behaviour of
7422 a GtkCList. First there is
7423
7424 <tscreen><verb>
7425 void gtk_clist_set_selection_mode( GtkCList         *clist,
7426                                    GtkSelectionMode  mode );
7427 </verb></tscreen>
7428
7429 which, as the name implies, sets the selection mode of the GtkCList. The first
7430 argument is the GtkCList widget, and the second specifies the cell selection
7431 mode (they are defined in gtkenums.h). At the time of this writing, the following
7432 modes are available to us:
7433
7434 <itemize>
7435 <item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
7436 pointer for a single selected item.
7437
7438 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list contains no
7439 widgets or insensitive ones only, otherwise it contains a GList pointer for
7440 one GList structure, and therefore exactly one list item.
7441
7442 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list items are
7443 selected or a GList pointer for the first selected item. That in turn points
7444 to a GList structure for the second selected item and so on. This is currently
7445 the <bf>default</bf> for the GtkCList widget.
7446
7447 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
7448 </itemize>
7449
7450 Others might be added in later revisions of GTK.
7451
7452 We can also define what the border of the GtkCList widget should look
7453 like. It is done through
7454
7455 <tscreen><verb>
7456 void gtk_clist_set_shadow_type( GtkCList      *clist,
7457                                 GtkShadowType  border );
7458 </verb></tscreen>
7459
7460 And the possible values for the second argument are
7461
7462 <itemize>
7463 <item> GTK_SHADOW_NONE
7464
7465 <item> GTK_SHADOW_IN
7466
7467 <item> GTK_SHADOW_OUT
7468
7469 <item> GTK_SHADOW_ETCHED_IN
7470
7471 <item> GTK_SHADOW_ETCHED_OUT
7472 </itemize>
7473
7474 <!-- ----------------------------------------------------------------- -->
7475 <sect1>Working with titles
7476 <p>
7477 When you create a GtkCList widget, you will also get a set of title
7478 buttons automatically. They live in the top of the CList window, and
7479 can act either as normal buttons that respond to being pressed, or
7480 they can be passive, in which case they are nothing more than a
7481 title. There are four different calls that aid us in setting the
7482 status of the title buttons.
7483
7484 <tscreen><verb>
7485 void gtk_clist_column_title_active( GtkCList *clist,
7486                                      gint     column );
7487
7488 void gtk_clist_column_title_passive( GtkCList *clist,
7489                                      gint      column );
7490
7491 void gtk_clist_column_titles_active( GtkCList *clist );
7492
7493 void gtk_clist_column_titles_passive( GtkCList *clist );
7494 </verb></tscreen>
7495
7496 An active title is one which acts as a normal button, a passive one is
7497 just a label. The first two calls above will activate/deactivate the
7498 title button above the specific column, while the last two calls
7499 activate/deactivate all title buttons in the supplied clist widget.
7500
7501 But of course there are those cases when we don't want them at all,
7502 and so they can be hidden and shown at will using the following two
7503 calls.
7504
7505 <tscreen><verb>
7506 void gtk_clist_column_titles_show( GtkCList *clist );
7507
7508 void gtk_clist_column_titles_hide( GtkCList *clist );
7509 </verb></tscreen>
7510
7511 For titles to be really useful we need a mechanism to set and change
7512 them, and this is done using
7513
7514 <tscreen><verb>
7515 void gtk_clist_set_column_title( GtkCList *clist,
7516                                  gint      column,
7517                                  gchar    *title );
7518 </verb></tscreen>
7519
7520 Note that only the title of one column can be set at a time, so if all
7521 the titles are known from the beginning, then I really suggest using
7522 gtk_clist_new_with_titles (as described above) to set them. Saves you
7523 coding time, and makes your program smaller. There are some cases
7524 where getting the job done the manual way is better, and that's when
7525 not all titles will be text. GtkCList provides us with title buttons
7526 that can in fact incorporate whole widgets, for example a pixmap. It's
7527 all done through
7528
7529 <tscreen><verb>
7530 void gtk_clist_set_column_widget( GtkCList  *clist,
7531                                   gint       column,
7532                                   GtkWidget *widget );
7533 </verb></tscreen>
7534
7535 which should require no special explanation.
7536
7537 <!-- ----------------------------------------------------------------- -->
7538 <sect1>Manipulating the list itself
7539 <p>
7540 It is possible to change the justification for a column, and it is
7541 done through
7542
7543 <tscreen><verb>
7544 void gtk_clist_set_column_justification( GtkCList         *clist,
7545                                          gint              column,
7546                                          GtkJustification  justification );
7547 </verb></tscreen>
7548
7549 The GtkJustification type can take the following values:
7550
7551 <itemize>
7552 <item>GTK_JUSTIFY_LEFT - The text in the column will begin from the
7553 left edge.
7554
7555 <item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the
7556 right edge.
7557
7558 <item>GTK_JUSTIFY_CENTER - The text is placed in the center of the
7559 column.
7560
7561 <item>GTK_JUSTIFY_FILL - The text will use up all available space in
7562 the column. It is normally done by inserting extra blank spaces
7563 between words (or between individual letters if it's a single
7564 word). Much in the same way as any ordinary WYSIWYG text editor.
7565 </itemize>
7566
7567 The next function is a very important one, and should be standard in
7568 the setup of all GtkCList widgets. When the list is created, the width
7569 of the various columns are chosen to match their titles, and since
7570 this is seldom the right width we have to set it using
7571
7572 <tscreen><verb>
7573 void gtk_clist_set_column_width( GtkCList *clist,
7574                                  gint      column,
7575                                  gint      width );
7576 </verb></tscreen>
7577
7578 Note that the width is given in pixels and not letters. The same goes
7579 for the height of the cells in the columns, but as the default value
7580 is the height of the current font this isn't as critical to the
7581 application. Still, it is done through
7582
7583 <tscreen><verb>
7584 void gtk_clist_set_row_height( GtkCList *clist,
7585                                gint      height );
7586 </verb></tscreen>
7587
7588 Again, note that the height is given in pixels.
7589
7590 We can also move the list around without user interaction, however, it
7591 does require that we know what we are looking for. Or in other words,
7592 we need the row and column of the item we want to scroll to.
7593
7594 <tscreen><verb>
7595 void gtk_clist_moveto( GtkCList *clist,
7596                        gint      row,
7597                        gint      column,
7598                        gfloat    row_align,
7599                        gfloat    col_align );
7600 </verb></tscreen>
7601
7602 The gfloat row_align is pretty important to understand. It's a value
7603 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
7604 the row appears at the top, while if the value of row_align is 1.0,
7605 the row will appear at the bottom instead. All other values between
7606 0.0 and 1.0 are also valid and will place the row between the top and
7607 the bottom. The last argument, gfloat col_align works in the same way,
7608 though 0.0 marks left and 1.0 marks right instead.
7609
7610 Depending on the application's needs, we don't have to scroll to an
7611 item that is already visible to us. So how do we know if it is
7612 visible? As usual, there is a function to find that out as well.
7613
7614 <tscreen><verb>
7615 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
7616                                         gint      row );
7617 </verb></tscreen>
7618
7619 The return value is is one of the following:
7620
7621 <itemize>
7622 <item>GTK_VISIBILITY_NONE
7623
7624 <item>GTK_VISIBILITY_PARTIAL
7625
7626 <item>GTK_VISIBILITY_FULL
7627 </itemize>
7628
7629 Note that it will only tell us if a row is visible. Currently there is
7630 no way to determine this for a column. We can get partial information
7631 though, because if the return is GTK_VISIBILITY_PARTIAL, then some of
7632 it is hidden, but we don't know if it is the row that is being cut by
7633 the lower edge of the listbox, or if the row has columns that are
7634 outside.
7635
7636 We can also change both the foreground and background colors of a
7637 particular row. This is useful for marking the row selected by the
7638 user, and the two functions that is used to do it are
7639
7640 <tscreen><verb>
7641 void gtk_clist_set_foreground( GtkCList *clist,
7642                                gint      row,
7643                                GdkColor *color );
7644
7645 void gtk_clist_set_background( GtkCList *clist,
7646                                gint      row,
7647                                GdkColor *color );
7648 </verb></tscreen>
7649
7650 Please note that the colors must have been previously allocated.
7651
7652 <!-- ----------------------------------------------------------------- -->
7653 <sect1>Adding rows to the list
7654 <p>
7655 We can add rows in three ways. They can be prepended or appended to
7656 the list using
7657
7658 <tscreen><verb>
7659 gint gtk_clist_prepend( GtkCList *clist,
7660                         gchar    *text[] );
7661
7662 gint gtk_clist_append( GtkCList *clist,
7663                        gchar    *text[] );
7664 </verb></tscreen>
7665
7666 The return value of these two functions indicate the index of the row
7667 that was just added. We can insert a row at a given place using
7668
7669 <tscreen><verb>
7670 void gtk_clist_insert( GtkCList *clist,
7671                        gint      row,
7672                        gchar    *text[] );
7673 </verb></tscreen>
7674
7675 In these calls we have to provide a collection of pointers that are
7676 the texts we want to put in the columns. The number of pointers should
7677 equal the number of columns in the list. If the text[] argument is
7678 NULL, then there will be no text in the columns of the row. This is
7679 useful, for example, if we want to add pixmaps instead (something that
7680 has to be done manually).
7681
7682 Also, please note that the numbering of both rows and columns start at 0.
7683
7684 To remove an individual row we use
7685
7686 <tscreen><verb>
7687 void gtk_clist_remove( GtkCList *clist,
7688                        gint      row );
7689 </verb></tscreen>
7690
7691 There is also a call that removes all rows in the list. This is a lot
7692 faster than calling gtk_clist_remove once for each row, which is the
7693 only alternative.
7694
7695 <tscreen><verb>
7696 void gtk_clist_clear( GtkCList *clist );
7697 </verb></tscreen>
7698
7699 There are also two convenience functions that should be used when a
7700 lot of changes have to be made to the list. This is to prevent the
7701 list flickering while being repeatedly updated, which may be highly
7702 annoying to the user. So instead it is a good idea to freeze the list,
7703 do the updates to it, and finally thaw it which causes the list to be
7704 updated on the screen.
7705
7706 <tscreen><verb>
7707 void gtk_clist_freeze( GtkCList * clist );
7708
7709 void gtk_clist_thaw( GtkCList * clist );
7710 </verb></tscreen>
7711
7712 <!-- ----------------------------------------------------------------- -->
7713 <sect1>Setting text and pixmaps in the cells
7714 <p>
7715 A cell can contain a pixmap, text or both. To set them the following
7716 functions are used.
7717
7718 <tscreen><verb>
7719 void gtk_clist_set_text( GtkCList *clist,
7720                          gint      row,
7721                          gint      column,
7722                          gchar    *text );
7723
7724 void gtk_clist_set_pixmap( GtkCList  *clist,
7725                            gint       row,
7726                            gint       column,
7727                            GdkPixmap *pixmap,
7728                            GdkBitmap *mask );
7729
7730 void gtk_clist_set_pixtext( GtkCList  *clist,
7731                             gint       row,
7732                             gint       column,
7733                             gchar     *text,
7734                             guint8     spacing,
7735                             GdkPixmap *pixmap,
7736                             GdkBitmap *mask );
7737 </verb></tscreen>
7738
7739 It's quite straightforward. All the calls have the GtkCList as the
7740 first argument, followed by the row and column of the cell, followed
7741 by the data to be set. The <tt/spacing/ argument in
7742 gtk_clist_set_pixtext is the number of pixels between the pixmap and
7743 the beginning of the text.
7744
7745 To read back the data, we instead use
7746
7747 <tscreen><verb>
7748 gint gtk_clist_get_text( GtkCList  *clist,
7749                          gint       row,
7750                          gint       column,
7751                          gchar    **text );
7752
7753 gint gtk_clist_get_pixmap( GtkCList   *clist,
7754                            gint        row,
7755                            gint        column,
7756                            GdkPixmap **pixmap,
7757                            GdkBitmap **mask );
7758
7759 gint gtk_clist_get_pixtext( GtkCList   *clist,
7760                             gint        row,
7761                             gint        column,
7762                             gchar     **text,
7763                             guint8     *spacing,
7764                             GdkPixmap **pixmap,
7765                             GdkBitmap **mask );
7766 </verb></tscreen>
7767
7768 It isn't necessary to read it all back in case you aren't
7769 interested. Any of the pointers that are meant for return values (all
7770 except the clist) can be NULL. So if we want to read back only the
7771 text from a cell that is of type pixtext, then we would do the
7772 following, assuming that clist, row and column already exist:
7773
7774 <tscreen><verb>
7775 gchar *mytext;
7776
7777 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
7778 </verb></tscreen>
7779
7780 There is one more call that is related to what's inside a cell in the
7781 clist, and that's
7782
7783 <tscreen><verb>
7784 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
7785                                      gint      row,
7786                                      gint      column );
7787 </verb></tscreen>
7788
7789 which returns the type of data in a cell. The return value is one of
7790
7791 <itemize>
7792 <item>GTK_CELL_EMPTY
7793
7794 <item>GTK_CELL_TEXT
7795
7796 <item>GTK_CELL_PIXMAP
7797
7798 <item>GTK_CELL_PIXTEXT
7799
7800 <item>GTK_CELL_WIDGET
7801 </itemize>
7802
7803 There is also a function that will let us set the indentation, both
7804 vertical and horizontal, of a cell. The indentation value is of type
7805 gint, given in pixels, and can be both positive and negative.
7806
7807 <tscreen><verb>
7808 void gtk_clist_set_shift( GtkCList *clist,
7809                           gint      row,
7810                           gint      column,
7811                           gint      vertical,
7812                           gint      horizontal );
7813 </verb></tscreen>
7814
7815 <!-- ----------------------------------------------------------------- -->
7816 <sect1>Storing data pointers
7817 <p>
7818 With a GtkCList it is possible to set a data pointer for a row. This
7819 pointer will not be visible for the user, but is merely a convenience
7820 for the programmer to associate a row with a pointer to some
7821 additional data.
7822
7823 The functions should be fairly self-explanatory by now
7824
7825 <tscreen><verb>
7826 void gtk_clist_set_row_data( GtkCList *clist,
7827                              gint      row,
7828                              gpointer  data );
7829
7830 void gtk_clist_set_row_data_full( GtkCList         *clist,
7831                                   gint              row,
7832                                   gpointer          data,
7833                                   GtkDestroyNotify  destroy );
7834
7835 gpointer gtk_clist_get_row_data( GtkCList *clist,
7836                                  gint      row );
7837
7838 gint gtk_clist_find_row_from_data( GtkCList *clist,
7839                                    gpointer  data );
7840 </verb></tscreen>
7841
7842 <!-- ----------------------------------------------------------------- -->
7843 <sect1>Working with selections
7844 <p>
7845 There are also functions available that let us force the (un)selection
7846 of a row. These are
7847
7848 <tscreen><verb>
7849 void gtk_clist_select_row( GtkCList *clist,
7850                            gint      row,
7851                            gint      column );
7852
7853 void gtk_clist_unselect_row( GtkCList *clist,
7854                              gint      row,
7855                              gint      column );
7856 </verb></tscreen>
7857
7858 And also a function that will take x and y coordinates (for example,
7859 read from the mousepointer), and map that onto the list, returning the
7860 corresponding row and column.
7861
7862 <tscreen><verb>
7863 gint gtk_clist_get_selection_info( GtkCList *clist,
7864                                    gint      x,
7865                                    gint      y,
7866                                    gint     *row,
7867                                    gint     *column );
7868 </verb></tscreen>
7869
7870 When we detect something of interest, it might be movement of the
7871 pointer, a click somewhere in the list, we can read the pointer
7872 coordinates and find out where in the list the pointer is. Cumbersome?
7873 Luckily, there is a simpler way...
7874
7875 <!-- ----------------------------------------------------------------- -->
7876 <sect1>The signals that bring it together
7877 <p>
7878 As with all other widgets, there are a few signals that can be used. The
7879 GtkCList widget is derived from the GtkContainer widget, and so has all the
7880 same signals, but also the adds following:
7881
7882 <itemize>
7883 <item>select_row - This signal will send the following information, in
7884 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
7885
7886 <item>unselect_row - When the user unselects a row, this signal is
7887 activated. It sends the same information as select_row
7888
7889 <item>click_column - Send GtkCList *clist, gint column
7890 </itemize>
7891
7892 So if we want to connect a callback to select_row, the callback
7893 function would be declared like this
7894
7895 <tscreen><verb>
7896 void select_row_callback(GtkWidget *widget,
7897                          gint row,
7898                          gint column,
7899                          GdkEventButton *event,
7900                          gpointer data);
7901 </verb></tscreen>
7902
7903 The callback is connected as usual with
7904
7905 <tscreen><verb>
7906 gtk_signal_connect(GTK_OBJECT( clist),
7907                    "select_row"
7908                    GTK_SIGNAL_FUNC(select_row_callback),
7909                    NULL);
7910 </verb></tscreen>
7911
7912 <!-- ----------------------------------------------------------------- -->
7913 <sect1>A GtkCList example
7914 <p>
7915
7916 <tscreen><verb>
7917 /* example-start clist clist.c */
7918
7919 #include        <gtk/gtk.h>
7920 #include        <glib.h>
7921
7922 /* These are just the prototypes of the various callbacks */
7923 void button_add_clicked( GtkWidget *button, gpointer data);
7924 void button_clear_clicked( GtkWidget *button, gpointer data);
7925 void button_hide_show_clicked( GtkWidget *button, gpointer data);
7926 void selection_made( GtkWidget *clist, gint row, gint column,
7927                      GdkEventButton *event, gpointer data);
7928
7929 gint main (int argc, gchar *argv[])
7930 {                                  
7931     GtkWidget       *window;
7932     GtkWidget       *vbox, *hbox;
7933     GtkWidget       *clist;
7934     GtkWidget       *button_add, *button_clear, *button_hide_show;    
7935     gchar           *titles[2] = {"Ingredients","Amount"};
7936
7937     gtk_init(&amp;argc, &amp;argv);
7938     
7939     
7940     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
7941     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
7942
7943     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
7944     gtk_signal_connect(GTK_OBJECT(window),
7945                        "destroy",
7946                        GTK_SIGNAL_FUNC(gtk_main_quit),
7947                        NULL);
7948     
7949     vbox=gtk_vbox_new(FALSE, 5);
7950     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
7951     gtk_container_add(GTK_CONTAINER(window), vbox);
7952     gtk_widget_show(vbox);
7953     
7954     /* Create the GtkCList. For this example we use 2 columns */
7955     clist = gtk_clist_new_with_titles( 2, titles);
7956
7957     /* When a selection is made, we want to know about it. The callback
7958      * used is selection_made, and its code can be found further down */
7959     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
7960                        GTK_SIGNAL_FUNC(selection_made),
7961                        NULL);
7962
7963     /* It isn't necessary to shadow the border, but it looks nice :) */
7964     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
7965
7966     /* What however is important, is that we set the column widths as
7967      * they will never be right otherwise. Note that the columns are
7968      * numbered from 0 and up (to 1 in this case).
7969      */
7970     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
7971
7972     /* Add the GtkCList widget to the vertical box and show it. */
7973     gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
7974     gtk_widget_show(clist);
7975
7976     /* Create the buttons and add them to the window. See the button
7977      * tutorial for more examples and comments on this.
7978      */
7979     hbox = gtk_hbox_new(FALSE, 0);
7980     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
7981     gtk_widget_show(hbox);
7982
7983     button_add = gtk_button_new_with_label("Add List");
7984     button_clear = gtk_button_new_with_label("Clear List");
7985     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
7986
7987     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
7988     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
7989     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
7990
7991     /* Connect our callbacks to the three buttons */
7992     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
7993                               GTK_SIGNAL_FUNC(button_add_clicked),
7994                               (gpointer) clist);
7995     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
7996                               GTK_SIGNAL_FUNC(button_clear_clicked),
7997                               (gpointer) clist);
7998     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
7999                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
8000                               (gpointer) clist);
8001
8002     gtk_widget_show(button_add);
8003     gtk_widget_show(button_clear);
8004     gtk_widget_show(button_hide_show);
8005
8006     /* The interface is completely set up so we show the window and
8007      * enter the gtk_main loop.
8008      */
8009     gtk_widget_show(window);
8010     gtk_main();
8011     
8012     return(0);
8013 }
8014
8015 /* User clicked the "Add List" button. */
8016 void button_add_clicked( GtkWidget *button, gpointer data)
8017 {
8018     int         indx;
8019
8020     /* Something silly to add to the list. 4 rows of 2 columns each */
8021     gchar      *drink[4][2] = {{"Milk", "3 Oz"},
8022                                {"Water", "6 l"},
8023                                {"Carrots", "2"},
8024                                {"Snakes", "55"}};
8025
8026     /* Here we do the actual adding of the text. It's done once for
8027      * each row.
8028      */
8029     for( indx=0; indx < 4; indx++)
8030         gtk_clist_append( (GtkCList*) data, drink[indx]);
8031
8032     return;
8033 }
8034
8035 /* User clicked the "Clear List" button. */
8036 void button_clear_clicked( GtkWidget *button, gpointer data)
8037 {
8038     /* Clear the list using gtk_clist_clear. This is much faster than
8039      * calling gtk_clist_remove once for each row.
8040      */
8041     gtk_clist_clear((GtkCList*) data);
8042
8043     return;
8044 }
8045
8046 /* The user clicked the "Hide/Show titles" button. */
8047 void button_hide_show_clicked( GtkWidget *button, gpointer data)
8048 {
8049     /* Just a flag to remember the status. 0 = currently visible */
8050     static short int flag = 0;
8051
8052     if (flag == 0)
8053     {
8054         /* Hide the titles and set the flag to 1 */
8055         gtk_clist_column_titles_hide((GtkCList*) data);
8056         flag++;
8057     }
8058     else
8059     {
8060         /* Show the titles and reset flag to 0 */
8061         gtk_clist_column_titles_show((GtkCList*) data);
8062         flag--;
8063     }
8064
8065     return;
8066 }
8067
8068 /* If we come here, then the user has selected a row in the list. */
8069 void selection_made( GtkWidget *clist, gint row, gint column,
8070                      GdkEventButton *event, gpointer data)
8071 {
8072     gchar       *text;
8073
8074     /* Get the text that is stored in the selected row and column
8075      * which was clicked in. We will receive it as a pointer in the
8076      * argument text.
8077      */
8078     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
8079
8080     /* Just prints some information about the selected row */
8081     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);
8082
8083     return;
8084 }
8085 /* example-end */
8086 </verb></tscreen>
8087                     
8088 <!-- ***************************************************************** -->
8089 <sect> Tree Widget <label id="sec_Tree_Widgets">
8090 <!-- ***************************************************************** -->
8091 <p>
8092 The purpose of tree widgets is to display hierarchically-organized
8093 data. The GtkTree widget itself is a vertical container for widgets of
8094 type GtkTreeItem. GtkTree itself is not terribly different from
8095 GtkList - both are derived directly from GtkContainer, and the
8096 GtkContainer methods work in the same way on GtkTree widgets as on
8097 GtkList widgets. The difference is that GtkTree widgets can be nested
8098 within other GtkTree widgets. We'll see how to do this shortly.
8099
8100 The GtkTree widget has its own window, and defaults to a white
8101 background, as does GtkList. Also, most of the GtkTree methods work in
8102 the same way as the corresponding GtkList ones. However, GtkTree is
8103 not derived from GtkList, so you cannot use them interchangeably.
8104
8105 <sect1> Creating a Tree
8106 <p>
8107 A GtkTree is created in the usual way, using:
8108
8109 <tscreen><verb>
8110 GtkWidget* gtk_tree_new( void );
8111 </verb></tscreen>
8112
8113 Like the GtkList widget, a GtkTree will simply keep growing as more
8114 items are added to it, as well as when subtrees are expanded.  For
8115 this reason, they are almost always packed into a
8116 GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
8117 scrolled window to ensure that it is big enough to see the tree's
8118 items, as the default size for GtkScrolledWindow is quite small.
8119
8120 Now that you have a tree, you'll probably want to add some items to
8121 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
8122 explains the gory details of GtkTreeItem. For now, it'll suffice to
8123 create one, using:
8124
8125 <tscreen><verb>
8126 GtkWidget* gtk_tree_item_new_with_label( gchar *label );
8127 </verb></tscreen>
8128
8129 You can then add it to the tree using one of the following (see
8130 <ref id="sec_GtkTree_Functions" name="Functions and Macros">
8131 below for more options):
8132
8133 <tscreen><verb>
8134 void gtk_tree_append( GtkTree    *tree,
8135                        GtkWidget *tree_item );
8136
8137 void gtk_tree_prepend( GtkTree   *tree,
8138                        GtkWidget *tree_item );
8139 </verb></tscreen>
8140
8141 Note that you must add items to a GtkTree one at a time - there is no
8142 equivalent to gtk_list_*_items().
8143
8144 <!-- ----------------------------------------------------------------- -->
8145 <sect1> Adding a Subtree
8146 <p>
8147 A subtree is created like any other GtkTree widget. A subtree is added
8148 to another tree beneath a tree item, using:
8149
8150 <tscreen><verb>
8151 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8152                                 GtkWidget   *subtree );
8153 </verb></tscreen>
8154
8155 You do not need to call gtk_widget_show() on a subtree before or after
8156 adding it to a GtkTreeItem. However, you <em>must</em> have added the
8157 GtkTreeItem in question to a parent tree before calling
8158 gtk_tree_item_set_subtree(). This is because, technically, the parent
8159 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
8160 rather the GtkTree which holds that GtkTreeItem.
8161
8162 When you add a subtree to a GtkTreeItem, a plus or minus sign appears
8163 beside it, which the user can click on to "expand" or "collapse" it,
8164 meaning, to show or hide its subtree. GtkTreeItems are collapsed by
8165 default. Note that when you collapse a GtkTreeItem, any selected
8166 items in its subtree remain selected, which may not be what the user
8167 expects.
8168
8169 <!-- ----------------------------------------------------------------- -->
8170 <sect1> Handling the Selection List
8171 <p>
8172 As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
8173 it is possible to control the behaviour of the tree (somewhat) by
8174 setting the selection type using:
8175
8176 <tscreen><verb>
8177 void gtk_tree_set_selection_mode( GtkTree          *tree,
8178                                   GtkSelectionMode  mode );
8179 </verb></tscreen>
8180
8181 The semantics associated with the various selection modes are
8182 described in the section on the GtkList widget. As with the GtkList
8183 widget, the "select_child", "unselect_child" (not really - see <ref
8184 id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
8185 and "selection_changed" signals are emitted when list items are
8186 selected or unselected. However, in order to take advantage of these
8187 signals, you need to know <em>which</em> GtkTree widget they will be
8188 emitted by, and where to find the list of selected items.
8189
8190 This is a source of potential confusion. The best way to explain this
8191 is that though all GtkTree widgets are created equal, some are more
8192 equal than others. All GtkTree widgets have their own X window, and
8193 can therefore receive events such as mouse clicks (if their
8194 GtkTreeItems or their children don't catch them first!). However, to
8195 make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
8196 behave in a sane manner, the list of selected items is specific to the
8197 topmost GtkTree widget in a hierarchy, known as the "root tree".
8198
8199 Thus, accessing the <tt>selection</tt>field directly in an arbitrary
8200 GtkTree widget is not a good idea unless you <em>know</em> it's the
8201 root tree.  Instead, use the GTK_TREE_SELECTION (Tree) macro, which
8202 gives the root tree's selection list as a GList pointer. Of course,
8203 this list can include items that are not in the subtree in question if 
8204 the selection type is GTK_SELECTION_MULTIPLE.
8205
8206 Finally, the "select_child" (and "unselect_child", in theory) signals
8207 are emitted by all trees, but the "selection_changed" signal is only
8208 emitted by the root tree. Consequently, if you want to handle the
8209 "select_child" signal for a tree and all its subtrees, you will have
8210 to call gtk_signal_connect() for every subtree.
8211
8212 <sect1> Tree Widget Internals
8213 <p>
8214 The GtkTree's struct definition looks like this:
8215
8216 <tscreen><verb>
8217 struct _GtkTree
8218 {
8219   GtkContainer container;
8220
8221   GList *children;
8222   
8223   GtkTree* root_tree; /* owner of selection list */
8224   GtkWidget* tree_owner;
8225   GList *selection;
8226   guint level;
8227   guint indent_value;
8228   guint current_indent;
8229   guint selection_mode : 2;
8230   guint view_mode : 1;
8231   guint view_line : 1;
8232 };
8233 </verb></tscreen>
8234
8235 The perils associated with accessing the <tt>selection</tt> field
8236 directly have already been mentioned. The other important fields of
8237 the struct can also be accessed with handy macros or class functions.
8238 GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
8239 whether a tree is the root tree in a GtkTree hierarchy, while
8240 GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
8241 GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
8242 to use one of the gtk_widget_*() functions on it).
8243
8244 Instead of directly accessing the children field of a GtkTree widget,
8245 it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
8246 to the gtk_container_children() function. This creates a duplicate of
8247 the original list, so it's advisable to free it up using g_list_free()
8248 after you're done with it, or to iterate on it destructively, like
8249 this:
8250
8251 <tscreen><verb>
8252     children = gtk_container_children (GTK_CONTAINER (tree));
8253     while (children) {
8254       do_something_nice (GTK_TREE_ITEM (children->data));
8255       children = g_list_remove_link (children, children);
8256 }
8257 </verb></tscreen>
8258
8259 The <tt>tree_owner</tt> field is defined only in subtrees, where it
8260 points to the GtkTreeItem widget which holds the tree in question.
8261 The <tt>level</tt> field indicates how deeply nested a particular tree
8262 is; root trees have level 0, and each successive level of subtrees has
8263 a level one greater than the parent level. This field is set only
8264 after a GtkTree widget is actually mapped (i.e. drawn on the screen).
8265
8266 <sect2> Signals<label id="sec_GtkTree_Signals">
8267 <p>
8268 <tscreen><verb>
8269 void selection_changed( GtkTree *tree );
8270 </verb></tscreen>
8271
8272 This signal will be emitted whenever the <tt>selection</tt> field of a
8273 GtkTree has changed. This happens when a child of the GtkTree is
8274 selected or deselected.
8275
8276 <tscreen><verb>
8277 void select_child( GtkTree   *tree,
8278                    GtkWidget *child );
8279 </verb></tscreen>
8280
8281 This signal is emitted when a child of the GtkTree is about to get
8282 selected. This happens on calls to gtk_tree_select_item(),
8283 gtk_tree_select_child(), on <em>all</em> button presses and calls to
8284 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
8285 indirectly triggered on other occasions where children get added to or
8286 removed from the GtkTree.
8287
8288 <tscreen><verb>
8289 void unselect_child (GtkTree   *tree,
8290                      GtkWidget *child);
8291 </verb></tscreen>
8292
8293 This signal is emitted when a child of the GtkTree is about to get
8294 deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
8295 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
8296 other occasions, but <em>not</em> when a button press deselects a
8297 child, nor on emission of the "toggle" signal by gtk_item_toggle().
8298
8299 <sect2> Functions and Macros<label id="sec_GtkTree_Functions">
8300 <p>
8301 <tscreen><verb>
8302 guint gtk_tree_get_type( void );
8303 </verb></tscreen>
8304
8305 Returns the `GtkTree' type identifier.
8306
8307 <tscreen><verb>
8308 GtkWidget* gtk_tree_new( void );
8309 </verb></tscreen>
8310
8311 Create a new GtkTree object. The new widget is returned as a pointer
8312 to a GtkWidget object. NULL is returned on failure.
8313
8314 <tscreen><verb>
8315 void gtk_tree_append( GtkTree   *tree,
8316                       GtkWidget *tree_item );
8317 </verb></tscreen>
8318
8319 Append a tree item to a GtkTree.
8320
8321 <tscreen><verb>
8322 void gtk_tree_prepend( GtkTree   *tree,
8323                        GtkWidget *tree_item );
8324 </verb></tscreen>
8325
8326 Prepend a tree item to a GtkTree.
8327
8328 <tscreen><verb>
8329 void gtk_tree_insert( GtkTree   *tree,
8330                       GtkWidget *tree_item,
8331                       gint       position );
8332 </verb></tscreen>
8333
8334 Insert a tree item into a GtkTree at the position in the list
8335 specified by <tt>position.</tt>
8336
8337 <tscreen><verb>
8338 void gtk_tree_remove_items( GtkTree *tree,
8339                             GList   *items );
8340 </verb></tscreen>
8341
8342 Remove a list of items (in the form of a GList *) from a GtkTree.
8343 Note that removing an item from a tree dereferences (and thus usually)
8344 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
8345 subtrees in that subtree.  If you want to remove only one item, you
8346 can use gtk_container_remove().
8347
8348 <tscreen><verb>
8349 void gtk_tree_clear_items( GtkTree *tree,
8350                            gint     start,
8351                            gint     end );
8352 </verb></tscreen>
8353
8354 Remove the items from position <tt>start</tt> to position <tt>end</tt>
8355 from a GtkTree.  The same warning about dereferencing applies here, as
8356 gtk_tree_clear_items() simply constructs a list and passes it to
8357 gtk_tree_remove_items().
8358
8359 <tscreen><verb>
8360 void gtk_tree_select_item( GtkTree *tree,
8361                            gint     item );
8362 </verb></tscreen>
8363
8364 Emits the "select_item" signal for the child at position
8365 <tt>item</tt>, thus selecting the child (unless you unselect it in a
8366 signal handler).
8367
8368 <tscreen><verb>
8369 void gtk_tree_unselect_item( GtkTree *tree,
8370                              gint     item );
8371 </verb></tscreen>
8372
8373 Emits the "unselect_item" signal for the child at position
8374 <tt>item</tt>, thus unselecting the child.
8375
8376 <tscreen><verb>
8377 void gtk_tree_select_child( GtkTree   *tree,
8378                             GtkWidget *tree_item );
8379 </verb></tscreen>
8380
8381 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
8382 selecting it.
8383
8384 <tscreen><verb>
8385 void gtk_tree_unselect_child( GtkTree   *tree,
8386                               GtkWidget *tree_item );
8387 </verb></tscreen>
8388
8389 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
8390 thus unselecting it.
8391
8392 <tscreen><verb>
8393 gint gtk_tree_child_position( GtkTree   *tree,
8394                               GtkWidget *child );
8395 </verb></tscreen>
8396
8397 Returns the position in the tree of <tt>child</tt>, unless
8398 <tt>child</tt> is not in the tree, in which case it returns -1.
8399
8400 <tscreen><verb>
8401 void gtk_tree_set_selection_mode( GtkTree          *tree,
8402                                   GtkSelectionMode  mode );
8403 </verb></tscreen>
8404
8405 Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
8406 default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
8407 GTK_SELECTION_EXTENDED. This is only defined for root trees, which
8408 makes sense, since the root tree "owns" the selection. Setting it for
8409 subtrees has no effect at all; the value is simply ignored.
8410
8411 <tscreen><verb>
8412 void gtk_tree_set_view_mode( GtkTree         *tree,
8413                              GtkTreeViewMode  mode ); 
8414 </verb></tscreen>
8415
8416 Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
8417 default) or GTK_TREE_VIEW_ITEM.  The view mode propagates from a tree
8418 to its subtrees, and can't be set exclusively to a subtree (this is
8419 not exactly true - see the example code comments).
8420
8421 The term "view mode" is rather ambiguous - basically, it controls the
8422 way the highlight is drawn when one of a tree's children is selected.
8423 If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
8424 highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
8425 (i.e. usually the label) is highlighted.
8426
8427 <tscreen><verb>
8428 void gtk_tree_set_view_lines( GtkTree *tree,
8429                               guint    flag );
8430 </verb></tscreen>
8431
8432 Controls whether connecting lines between tree items are drawn.
8433 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
8434 which case they aren't.
8435
8436 <tscreen><verb>
8437 GtkTree *GTK_TREE (gpointer obj);
8438 </verb></tscreen>
8439
8440 Cast a generic pointer to `GtkTree *'.
8441
8442 <tscreen><verb>
8443 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
8444 </verb></tscreen>
8445
8446 Cast a generic pointer to `GtkTreeClass*'.
8447
8448 <tscreen><verb>
8449 gint GTK_IS_TREE (gpointer obj);
8450 </verb></tscreen>
8451
8452 Determine if a generic pointer refers to a `GtkTree' object.
8453
8454 <tscreen><verb>
8455 gint GTK_IS_ROOT_TREE (gpointer obj)
8456 </verb></tscreen>
8457
8458 Determine if a generic pointer refers to a `GtkTree' object
8459 <em>and</em> is a root tree. Though this will accept any pointer, the
8460 results of passing it a pointer that does not refer to a GtkTree are
8461 undefined and possibly harmful.
8462
8463 <tscreen><verb>
8464 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
8465 </verb></tscreen>
8466
8467 Return the root tree of a pointer to a `GtkTree' object. The above
8468 warning applies.
8469
8470 <tscreen><verb>
8471 GList *GTK_TREE_SELECTION( gpointer obj)
8472 </verb></tscreen>
8473
8474 Return the selection list of the root tree of a `GtkTree' object. The
8475 above warning applies here, too.
8476
8477 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
8478 <p>
8479 The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
8480 which in turn is derived from GtkBin.  Therefore, the item itself is a
8481 generic container holding exactly one child widget, which can be of
8482 any type.  The GtkTreeItem widget has a number of extra fields, but
8483 the only one we need be concerned with is the <tt>subtree</tt> field.
8484
8485 The definition for the GtkTreeItem struct looks like this:
8486
8487 <tscreen><verb>
8488 struct _GtkTreeItem
8489 {
8490   GtkItem item;
8491
8492   GtkWidget *subtree;
8493   GtkWidget *pixmaps_box;
8494   GtkWidget *plus_pix_widget, *minus_pix_widget;
8495
8496   GList *pixmaps;               /* pixmap node for this items color depth */
8497
8498   guint expanded : 1;
8499 };
8500 </verb></tscreen>
8501
8502 The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
8503 on the plus/minus symbol which controls expansion and collapsing.  The
8504 <tt>pixmaps</tt> field points to an internal data structure.  Since
8505 you can always obtain the subtree of a GtkTreeItem in a (relatively)
8506 type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
8507 probably advisable never to touch the insides of a GtkTreeItem unless
8508 you <em>really</em> know what you're doing.
8509
8510 Since it is directly derived from a GtkItem it can be treated as such
8511 by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
8512 label, so the convenience function gtk_list_item_new_with_label() is
8513 provided. The same effect can be achieved using code like the
8514 following, which is actually copied verbatim from
8515 gtk_tree_item_new_with_label():
8516
8517 <tscreen><verb>
8518 tree_item = gtk_tree_item_new ();
8519 label_widget = gtk_label_new (label);
8520 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
8521
8522 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
8523 gtk_widget_show (label_widget);
8524 </verb></tscreen>
8525
8526 As one is not forced to add a GtkLabel to a GtkTreeItem, you could
8527 also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
8528 app will likely be quite unpopular in this case) to the GtkTreeItem.
8529
8530 If you remove all the items from a subtree, it will be destroyed and
8531 unparented, unless you reference it beforehand, and the GtkTreeItem
8532 which owns it will be collapsed.  So, if you want it to stick around,
8533 do something like the following:
8534
8535 <tscreen><verb>
8536 gtk_widget_ref (tree);
8537 owner = GTK_TREE(tree)->tree_owner;
8538 gtk_container_remove (GTK_CONTAINER(tree), item);
8539 if (tree->parent == NULL){
8540   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
8541   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
8542 }
8543 else
8544   gtk_widget_unref (tree);
8545 </verb></tscreen>
8546
8547 Finally, drag-n-drop <em>does</em> work with GtkTreeItems.  You just
8548 have to make sure that the GtkTreeItem you want to make into a drag
8549 item or a drop site has not only been added to a GtkTree, but that
8550 each successive parent widget has a parent itself, all the way back to
8551 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
8552 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
8553
8554 <sect2> Signals
8555 <p>
8556 GtkTreeItem inherits the "select", "deselect", and "toggle" signals
8557 from GtkItem.  In addition, it adds two signals of its own, "expand"
8558 and "collapse".
8559
8560 <tscreen><verb>
8561 void select( GtkItem *tree_item );
8562 </verb></tscreen>
8563
8564 This signal is emitted when an item is about to be selected, either
8565 after it has been clicked on by the user, or when the program calls
8566 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
8567
8568 <tscreen><verb>
8569 void deselect( GtkItem *tree_item );
8570 </verb></tscreen>
8571
8572 This signal is emitted when an item is about to be unselected, either
8573 after it has been clicked on by the user, or when the program calls
8574 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
8575 GtkTreeItems, it is also emitted by gtk_tree_unselect_child(), and
8576 sometimes gtk_tree_select_child().
8577
8578 <tscreen><verb>
8579 void toggle( GtkItem *tree_item );
8580 </verb></tscreen>
8581
8582 This signal is emitted when the program calls gtk_item_toggle().  The
8583 effect it has when emitted on a GtkTreeItem is to call
8584 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
8585 item's parent tree, if the item has a parent tree.  If it doesn't,
8586 then the highlight is reversed on the item.
8587
8588 <tscreen><verb>
8589 void expand( GtkTreeItem *tree_item );
8590 </verb></tscreen>
8591
8592 This signal is emitted when the tree item's subtree is about to be
8593 expanded, that is, when the user clicks on the plus sign next to the
8594 item, or when the program calls gtk_tree_item_expand().
8595
8596 <tscreen><verb>
8597 void collapse( GtkTreeItem *tree_item );
8598 </verb></tscreen>
8599
8600 This signal is emitted when the tree item's subtree is about to be
8601 collapsed, that is, when the user clicks on the minus sign next to the
8602 item, or when the program calls gtk_tree_item_collapse().
8603
8604 <sect2> Functions and Macros
8605 <p>
8606 <tscreen><verb>
8607 guint gtk_tree_item_get_type( void );
8608 </verb></tscreen>
8609
8610 Returns the `GtkTreeItem' type identifier.
8611
8612 <tscreen><verb>
8613 GtkWidget* gtk_tree_item_new( void );
8614 </verb></tscreen>
8615
8616 Create a new GtkTreeItem object. The new widget is returned as a
8617 pointer to a GtkWidget object. NULL is returned on failure.
8618
8619 <tscreen><verb>
8620 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
8621 </verb></tscreen>
8622
8623 Create a new GtkTreeItem object, having a single GtkLabel as the sole
8624 child. The new widget is returned as a pointer to a GtkWidget
8625 object. NULL is returned on failure.
8626
8627 <tscreen><verb>
8628 void gtk_tree_item_select( GtkTreeItem *tree_item );
8629 </verb></tscreen>
8630
8631 This function is basically a wrapper around a call to gtk_item_select
8632 (GTK_ITEM (tree_item)) which will emit the select signal.
8633
8634 <tscreen><verb>
8635 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
8636 </verb></tscreen>
8637
8638 This function is basically a wrapper around a call to
8639 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
8640 signal.
8641
8642 <tscreen><verb>
8643 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8644                                 GtkWidget   *subtree );
8645 </verb></tscreen>
8646
8647 This function adds subtree to tree_item, showing it if tree_item is
8648 expanded, or hiding it if tree_item is collapsed. Again, remember that
8649 the tree_item must have already been added to a tree for this to work.
8650
8651 <tscreen><verb>
8652 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
8653 </verb></tscreen>
8654
8655 This removes all of tree_item's subtree's children (thus unreferencing
8656 and destroying it, any of its children's subtrees, and so on...), then
8657 removes the subtree itself, and hides the plus/minus sign.
8658
8659 <tscreen><verb>
8660 void gtk_tree_item_expand( GtkTreeItem *tree_item );
8661 </verb></tscreen>
8662
8663 This emits the "expand" signal on tree_item, which expands it.
8664
8665 <tscreen><verb>
8666 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
8667 </verb></tscreen>
8668
8669 This emits the "collapse" signal on tree_item, which collapses it.
8670
8671 <tscreen><verb>
8672 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
8673 </verb></tscreen>
8674
8675 Cast a generic pointer to `GtkTreeItem*'.
8676
8677 <tscreen><verb>
8678 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
8679 </verb></tscreen>
8680
8681 Cast a generic pointer to `GtkTreeItemClass'.
8682
8683 <tscreen><verb>
8684 gint GTK_IS_TREE_ITEM (gpointer obj)
8685 </verb></tscreen>
8686
8687 Determine if a generic pointer refers to a `GtkTreeItem' object.
8688  
8689 <tscreen><verb>
8690 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
8691 </verb></tscreen>
8692
8693 Returns a tree item's subtree (obj should point to a `GtkTreeItem'
8694 object).
8695
8696 <sect1> Tree Example
8697 <p>
8698 This is somewhat like the tree example in testgtk.c, but a lot less
8699 complete (although much better commented).  It puts up a window with a
8700 tree, and connects all the signals for the relevant objects, so you
8701 can see when they are emitted.
8702
8703 <tscreen><verb>
8704 /* example-start tree tree.c */
8705
8706 #include <gtk/gtk.h>
8707
8708 /* for all the GtkItem:: and GtkTreeItem:: signals */
8709 static void cb_itemsignal (GtkWidget *item, gchar *signame)
8710 {
8711   gchar *name;
8712   GtkLabel *label;
8713
8714   /* It's a GtkBin, so it has one child, which we know to be a
8715      label, so get that */
8716   label = GTK_LABEL (GTK_BIN (item)->child);
8717   /* Get the text of the label */
8718   gtk_label_get (label, &amp;name);
8719   /* Get the level of the tree which the item is in */
8720   g_print ("%s called for item %s->%p, level %d\n", signame, name,
8721            item, GTK_TREE (item->parent)->level);
8722 }
8723
8724 /* Note that this is never called */
8725 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
8726                                GtkWidget *subtree)
8727 {
8728   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
8729            root_tree, subtree, child);
8730 }
8731
8732 /* Note that this is called every time the user clicks on an item,
8733    whether it is already selected or not. */
8734 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
8735                              GtkWidget *subtree)
8736 {
8737   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
8738            root_tree, subtree, child);
8739 }
8740
8741 static void cb_selection_changed (GtkWidget *tree)
8742 {
8743   GList *i;
8744   
8745   g_print ("selection_change called for tree %p\n", tree);
8746   g_print ("selected objects are:\n");
8747
8748   i = GTK_TREE_SELECTION(tree);
8749   while (i){
8750     gchar *name;
8751     GtkLabel *label;
8752     GtkWidget *item;
8753
8754     /* Get a GtkWidget pointer from the list node */
8755     item = GTK_WIDGET (i->data);
8756     label = GTK_LABEL (GTK_BIN (item)->child);
8757     gtk_label_get (label, &amp;name);
8758     g_print ("\t%s on level %d\n", name, GTK_TREE
8759              (item->parent)->level);
8760     i = i->next;
8761   }
8762 }
8763
8764 int main (int argc, char *argv[])
8765 {
8766   GtkWidget *window, *scrolled_win, *tree;
8767   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
8768                                "Maurice"};
8769   gint i;
8770
8771   gtk_init (&amp;argc, &amp;argv);
8772
8773   /* a generic toplevel window */
8774   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8775   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
8776                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
8777   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
8778
8779   /* A generic scrolled window */
8780   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8781   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8782                                   GTK_POLICY_AUTOMATIC,
8783                                   GTK_POLICY_AUTOMATIC);
8784   gtk_widget_set_usize (scrolled_win, 150, 200);
8785   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
8786   gtk_widget_show (scrolled_win);
8787   
8788   /* Create the root tree */
8789   tree = gtk_tree_new();
8790   g_print ("root tree is %p\n", tree);
8791   /* connect all GtkTree:: signals */
8792   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
8793                       GTK_SIGNAL_FUNC(cb_select_child), tree);
8794   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
8795                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
8796   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
8797                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
8798   /* Add it to the scrolled window */
8799   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
8800                                          tree);
8801   /* Set the selection mode */
8802   gtk_tree_set_selection_mode (GTK_TREE(tree),
8803                                GTK_SELECTION_MULTIPLE);
8804   /* Show it */
8805   gtk_widget_show (tree);
8806
8807   for (i = 0; i < 5; i++){
8808     GtkWidget *subtree, *item;
8809     gint j;
8810
8811     /* Create a tree item */
8812     item = gtk_tree_item_new_with_label (itemnames[i]);
8813     /* Connect all GtkItem:: and GtkTreeItem:: signals */
8814     gtk_signal_connect (GTK_OBJECT(item), "select",
8815                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
8816     gtk_signal_connect (GTK_OBJECT(item), "deselect",
8817                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
8818     gtk_signal_connect (GTK_OBJECT(item), "toggle",
8819                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
8820     gtk_signal_connect (GTK_OBJECT(item), "expand",
8821                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
8822     gtk_signal_connect (GTK_OBJECT(item), "collapse",
8823                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
8824     /* Add it to the parent tree */
8825     gtk_tree_append (GTK_TREE(tree), item);
8826     /* Show it - this can be done at any time */
8827     gtk_widget_show (item);
8828     /* Create this item's subtree */
8829     subtree = gtk_tree_new();
8830     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
8831              subtree);
8832
8833     /* This is still necessary if you want these signals to be called
8834        for the subtree's children.  Note that selection_change will be 
8835        signalled for the root tree regardless. */
8836     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
8837                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
8838     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
8839                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
8840     /* This has absolutely no effect, because it is completely ignored 
8841        in subtrees */
8842     gtk_tree_set_selection_mode (GTK_TREE(subtree),
8843                                  GTK_SELECTION_SINGLE);
8844     /* Neither does this, but for a rather different reason - the
8845        view_mode and view_line values of a tree are propagated to
8846        subtrees when they are mapped.  So, setting it later on would
8847        actually have a (somewhat unpredictable) effect */
8848     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
8849     /* Set this item's subtree - note that you cannot do this until
8850        AFTER the item has been added to its parent tree! */
8851     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
8852
8853     for (j = 0; j < 5; j++){
8854       GtkWidget *subitem;
8855
8856       /* Create a subtree item, in much the same way */
8857       subitem = gtk_tree_item_new_with_label (itemnames[j]);
8858       /* Connect all GtkItem:: and GtkTreeItem:: signals */
8859       gtk_signal_connect (GTK_OBJECT(subitem), "select",
8860                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
8861       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
8862                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
8863       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
8864                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
8865       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
8866                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
8867       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
8868                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
8869       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
8870       /* Add it to its parent tree */
8871       gtk_tree_append (GTK_TREE(subtree), subitem);
8872       /* Show it */
8873       gtk_widget_show (subitem);
8874     }
8875   }
8876
8877   /* Show the window and loop endlessly */
8878   gtk_widget_show (window);
8879   gtk_main();
8880   return 0;
8881 }
8882 /* example-end */
8883 </verb></tscreen>
8884
8885 <!-- ***************************************************************** -->
8886 <sect>Menu Widget
8887 <!-- ***************************************************************** -->
8888 <p>
8889 There are two ways to create menus, there's the easy way, and there's
8890 the hard way. Both have their uses, but you can usually use the
8891 itemfactory (the easy way). The "hard" way is to create all the menus
8892 using the calls directly. The easy way is to use the gtk_item_factory
8893 calls. This is much simpler, but there are advantages and
8894 disadvantages to each approach.
8895
8896 The itemfactory is much easier to use, and to add new menus to,
8897 although writing a few wrapper functions to create menus using the
8898 manual method could go a long way towards usability. With the
8899 itemfactory, it is not possible to add images or the character '/' to
8900 the menus.
8901
8902 <!-- ----------------------------------------------------------------- -->
8903 <sect1>Manual Menu Creation
8904 <p>
8905 In the true tradition of teaching, we'll show you the hard way
8906 first. <tt>:)</>
8907
8908 There are three widgets that go into making a menubar and submenus:
8909 <itemize>
8910 <item>a menu item, which is what the user wants to select, e.g. 'Save'
8911 <item>a menu, which acts as a container for the menu items, and
8912 <item>a menubar, which is a container for each of the individual
8913 menus.
8914 </itemize>
8915
8916 This is slightly complicated by the fact that menu item widgets are
8917 used for two different things. They are both the widgets that are
8918 packed into the menu, and the widget that is packed into the menubar,
8919 which, when selected, activates the menu.
8920
8921 Let's look at the functions that are used to create menus and
8922 menubars.  This first function is used to create a new menubar.
8923
8924 <tscreen>
8925 <verb>
8926 GtkWidget *gtk_menu_bar_new( void );
8927 </verb>
8928 </tscreen>
8929
8930 This rather self explanatory function creates a new menubar. You use
8931 gtk_container_add to pack this into a window, or the box_pack
8932 functions to pack it into a box - the same as buttons.
8933
8934 <tscreen><verb>
8935 GtkWidget *gtk_menu_new( void );
8936 </verb></tscreen>
8937
8938 This function returns a pointer to a new menu, it is never actually
8939 shown (with gtk_widget_show), it is just a container for the menu
8940 items. Hopefully this will become more clear when you look at the
8941 example below.
8942
8943 The next two calls are used to create menu items that are packed into
8944 the menu (and menubar).
8945
8946 <tscreen><verb>
8947 GtkWidget *gtk_menu_item_new( void );
8948 </verb></tscreen>
8949
8950 and
8951
8952 <tscreen><verb>
8953 GtkWidget *gtk_menu_item_new_with_label( const char *label );
8954 </verb></tscreen>
8955
8956 These calls are used to create the menu items that are to be
8957 displayed.  Remember to differentiate between a "menu" as created with
8958 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
8959 functions. The menu item will be an actual button with an associated
8960 action, whereas a menu will be a container holding menu items.
8961
8962 The gtk_menu_new_with_label and gtk_menu_new functions are just as
8963 you'd expect after reading about the buttons. One creates a new menu
8964 item with a label already packed into it, and the other just creates a
8965 blank menu item.
8966
8967 Once you've created a menu item you have to put it into a menu. This
8968 is done using the function gtk_menu_append. In order to capture when
8969 the item is selected by the user, we need to connect to the
8970 <tt/activate/ signal in the usual way. So, if we wanted to create a
8971 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/ and
8972 <tt/Quit/ the code would look something like:
8973
8974 <tscreen><verb>
8975     file_menu = gtk_menu_new();    /* Don't need to show menus */
8976
8977     /* Create the menu items */
8978     open_item = gtk_menu_item_new_with_label("Open");
8979     save_item = gtk_menu_item_new_with_label("Save");
8980     quit_item = gtk_menu_item_new_with_label("Quit");
8981
8982     /* Add them to the menu */
8983     gtk_menu_append( GTK_MENU(file_menu), open_item);
8984     gtk_menu_append( GTK_MENU(file_menu), save_item);
8985     gtk_menu_append( GTK_MENU(file_menu), quit_item);
8986
8987     /* Attach the callback functions to the activate signal */
8988     gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
8989                                GTK_SIGNAL_FUNC(menuitem_response),
8990                                (gpointer) "file.open");
8991     gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
8992                                GTK_SIGNAL_FUNC(menuitem_response),
8993                                (gpointer) "file.save");
8994
8995     /* We can attach the Quit menu item to our exit function */
8996     gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
8997                                GTK_SIGNAL_FUNC(destroy),
8998                                (gpointer) "file.quit");
8999
9000     /* We do need to show menu items */
9001     gtk_widget_show( open_item );
9002     gtk_widget_show( save_item );
9003     gtk_widget_show( quit_item );
9004 </verb></tscreen>
9005
9006 At this point we have our menu. Now we need to create a menubar and a
9007 menu item for the <tt/File/ entry, to which we add our menu. The code
9008 looks like this:
9009
9010 <tscreen><verb>
9011     menu_bar = gtk_menu_bar_new();
9012     gtk_container_add( GTK_CONTAINER(window), menu_bar);
9013     gtk_widget_show( menu_bar );
9014
9015     file_item = gtk_menu_item_new_with_label("File");
9016     gtk_widget_show(file_item);
9017 </verb></tscreen>
9018
9019 Now we need to associate the menu with <tt/file_item/. This is done
9020 with the function
9021
9022 <tscreen>
9023 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
9024                                 GtkWidget   *submenu );
9025 </tscreen>
9026
9027 So, our example would continue with
9028
9029 <tscreen><verb>
9030     gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu );
9031 </verb></tscreen>
9032
9033 All that is left to do is to add the menu to the menubar, which is
9034 accomplished using the function
9035
9036 <tscreen>
9037 void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);
9038 </tscreen>
9039
9040 which in our case looks like this:
9041
9042 <tscreen><verb>
9043     gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );
9044 </verb></tscreen>
9045
9046 If we wanted the menu right justified on the menubar, such as help
9047 menus often are, we can use the following function (again on
9048 <tt/file_item/ in the current example) before attaching it to the
9049 menubar.
9050
9051 <tscreen><verb>
9052 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
9053 </verb></tscreen>
9054
9055 Here is a summary of the steps needed to create a menu bar with menus
9056 attached:
9057
9058 <itemize>
9059 <item> Create a new menu using gtk_menu_new()
9060 <item> Use multiple calls to gtk_menu_item_new() for each item you
9061 wish to have on your menu. And use gtk_menu_append() to put each of
9062 these new items on to the menu.
9063 <item> Create a menu item using gtk_menu_item_new(). This will be the
9064 root of the menu, the text appearing here will be on the menubar
9065 itself.
9066 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
9067 menu item (the one created in the above step).
9068 <item> Create a new menubar using gtk_menu_bar_new. This step only
9069 needs to be done once when creating a series of menus on one menu bar.
9070 <item> Use gtk_menu_bar_append to put the root menu onto the menubar.
9071 </itemize>
9072
9073 Creating a popup menu is nearly the same. The difference is that the
9074 menu is not posted `automatically' by a menubar, but explicitly by
9075 calling the function gtk_menu_popup() from a button-press event, for
9076 example.  Take these steps:
9077
9078 <itemize>
9079 <item>Create an event handling function. It needs to have the
9080 prototype
9081 <tscreen>
9082 static gint handler( GtkWidget *widget,
9083                      GdkEvent  *event );
9084 </tscreen>
9085 and it will use the event to find out where to pop up the menu.
9086 <item>In the event handler, if the event is a mouse button press,
9087 treat <tt>event</tt> as a button event (which it is) and use it as
9088 shown in the sample code to pass information to gtk_menu_popup().
9089 <item>Bind that event handler to a widget with
9090 <tscreen>
9091     gtk_signal_connect_object(GTK_OBJECT(widget), "event",
9092                               GTK_SIGNAL_FUNC (handler),
9093                               GTK_OBJECT(menu));
9094 </tscreen>
9095 where <tt>widget</tt> is the widget you are binding to,
9096 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
9097 created with gtk_menu_new(). This can be a menu which is also posted
9098 by a menu bar, as shown in the sample code.
9099 </itemize>
9100
9101 <!-- ----------------------------------------------------------------- -->
9102 <sect1>Manual Menu Example
9103 <p>
9104 That should about do it. Let's take a look at an example to help clarify.
9105
9106 <tscreen><verb>
9107 /* example-start menu menu.c */
9108
9109 #include <gtk/gtk.h>
9110
9111 static gint button_press (GtkWidget *, GdkEvent *);
9112 static void menuitem_response (gchar *);
9113
9114 int main (int argc, char *argv[])
9115 {
9116
9117     GtkWidget *window;
9118     GtkWidget *menu;
9119     GtkWidget *menu_bar;
9120     GtkWidget *root_menu;
9121     GtkWidget *menu_items;
9122     GtkWidget *vbox;
9123     GtkWidget *button;
9124     char buf[128];
9125     int i;
9126
9127     gtk_init (&amp;argc, &amp;argv);
9128
9129     /* create a new window */
9130     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9131     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
9132     gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
9133     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
9134                        (GtkSignalFunc) gtk_main_quit, NULL);
9135
9136     /* Init the menu-widget, and remember -- never
9137      * gtk_show_widget() the menu widget!! 
9138      * This is the menu that holds the menu items, the one that
9139      * will pop up when you click on the "Root Menu" in the app */
9140     menu = gtk_menu_new();
9141
9142     /* Next we make a little loop that makes three menu-entries for "test-menu".
9143      * Notice the call to gtk_menu_append.  Here we are adding a list of
9144      * menu items to our menu.  Normally, we'd also catch the "clicked"
9145      * signal on each of the menu items and setup a callback for it,
9146      * but it's omitted here to save space. */
9147
9148     for(i = 0; i < 3; i++)
9149         {
9150             /* Copy the names to the buf. */
9151             sprintf(buf, "Test-undermenu - %d", i);
9152
9153             /* Create a new menu-item with a name... */
9154             menu_items = gtk_menu_item_new_with_label(buf);
9155
9156             /* ...and add it to the menu. */
9157             gtk_menu_append(GTK_MENU (menu), menu_items);
9158
9159             /* Do something interesting when the menuitem is selected */
9160             gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
9161                 GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf));
9162
9163             /* Show the widget */
9164             gtk_widget_show(menu_items);
9165         }
9166
9167     /* This is the root menu, and will be the label
9168      * displayed on the menu bar.  There won't be a signal handler attached,
9169      * as it only pops up the rest of the menu when pressed. */
9170     root_menu = gtk_menu_item_new_with_label("Root Menu");
9171
9172     gtk_widget_show(root_menu);
9173
9174     /* Now we specify that we want our newly created "menu" to be the menu
9175      * for the "root menu" */
9176     gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
9177
9178     /* A vbox to put a menu and a button in: */
9179     vbox = gtk_vbox_new(FALSE, 0);
9180     gtk_container_add(GTK_CONTAINER(window), vbox);
9181     gtk_widget_show(vbox);
9182
9183     /* Create a menu-bar to hold the menus and add it to our main window */
9184     menu_bar = gtk_menu_bar_new();
9185     gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
9186     gtk_widget_show(menu_bar);
9187
9188     /* Create a button to which to attach menu as a popup */
9189     button = gtk_button_new_with_label("press me");
9190     gtk_signal_connect_object(GTK_OBJECT(button), "event",
9191         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
9192     gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
9193     gtk_widget_show(button);
9194
9195     /* And finally we append the menu-item to the menu-bar -- this is the
9196      * "root" menu-item I have been raving about =) */
9197     gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
9198
9199     /* always display the window as the last step so it all splashes on
9200      * the screen at once. */
9201     gtk_widget_show(window);
9202
9203     gtk_main ();
9204
9205     return 0;
9206 }
9207
9208 /* Respond to a button-press by posting a menu passed in as widget.
9209  *
9210  * Note that the "widget" argument is the menu being posted, NOT
9211  * the button that was pressed.
9212  */
9213
9214 static gint button_press (GtkWidget *widget, GdkEvent *event)
9215 {
9216
9217     if (event->type == GDK_BUTTON_PRESS) {
9218         GdkEventButton *bevent = (GdkEventButton *) event; 
9219         gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
9220                         bevent->button, bevent->time);
9221         /* Tell calling code that we have handled this event; the buck
9222          * stops here. */
9223         return TRUE;
9224     }
9225
9226     /* Tell calling code that we have not handled this event; pass it on. */
9227     return FALSE;
9228 }
9229
9230
9231 /* Print a string when a menu item is selected */
9232
9233 static void menuitem_response (gchar *string)
9234 {
9235     printf("%s\n", string);
9236 }
9237 /* example-end */
9238 </verb></tscreen>
9239
9240 You may also set a menu item to be insensitive and, using an accelerator
9241 table, bind keys to menu functions.
9242
9243 <!-- ----------------------------------------------------------------- -->
9244 <sect1>Using GtkItemFactory
9245 <p>
9246 Now that we've shown you the hard way, here's how you do it using the
9247 gtk_item_factory calls.
9248
9249 <!-- ----------------------------------------------------------------- -->
9250 <sect1>Item Factory Example
9251 <p>
9252 Here is an example using the GTK item factory.
9253
9254 <tscreen><verb>
9255 /* example-start menu itemfactory.c */
9256
9257 #include <gtk/gtk.h>
9258 #include <strings.h>
9259
9260 /* Obligatory basic callback */
9261 static void print_hello(GtkWidget *w, gpointer data) {
9262   g_message("Hello, World!\n");
9263 }
9264
9265 /* This is the GtkItemFactoryEntry structure used to generate new menus.
9266    Item 1: The menu path. The letter after the underscore indicates an
9267            accelerator key once the menu is open.
9268    Item 2: The accelerator key for the entry
9269    Item 3: The callback function.
9270    Item 4: The callback action.  This changes the parameters with
9271            which the function is called.  The default is 0.
9272    Item 5: The item type, used to define what kind of an item it is.
9273            Here are the possible values:
9274
9275            NULL               -> "<Item>"
9276            ""                 -> "<Item>"
9277            "<Title>"          -> create a title item
9278            "<Item>"           -> create a simple item
9279            "<CheckItem>"      -> create a check item
9280            "<ToggleItem>"     -> create a toggle item
9281            "<RadioItem>"      -> create a radio item
9282            <path>             -> path of a radio item to link against
9283            "<Separator>"      -> create a separator
9284            "<Branch>"         -> create an item to hold sub items
9285            "<LastBranch>"     -> create a right justified branch 
9286 */
9287
9288 static GtkItemFactoryEntry menu_items[] = {
9289   {"/_File",         NULL,         NULL, 0, "<Branch>"},
9290   {"/File/_New",     "<control>N", print_hello, 0, NULL},
9291   {"/File/_Open",    "<control>O", print_hello, 0, NULL},
9292   {"/File/_Save",    "<control>S", print_hello, 0, NULL},
9293   {"/File/Save _As", NULL,         NULL, 0, NULL},
9294   {"/File/sep1",     NULL,         NULL, 0, "<Separator>"},
9295   {"/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL},
9296   {"/_Options",      NULL,         NULL, 0, "<Branch>"},
9297   {"/Options/Test",  NULL,         NULL, 0, NULL},
9298   {"/_Help",         NULL,         NULL, 0, "<LastBranch>"},
9299   {"/_Help/About",   NULL,         NULL, 0, NULL},
9300 };
9301
9302
9303 void get_main_menu(GtkWidget *window, GtkWidget ** menubar) {
9304   int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
9305   GtkItemFactory *item_factory;
9306   GtkAccelGroup *accel_group;
9307
9308   accel_group = gtk_accel_group_new();
9309
9310   /* This function initializes the item factory.
9311      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
9312               or GTK_TYPE_OPTION_MENU.
9313      Param 2: The path of the menu.
9314      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
9315               the accelerator table while generating menus.
9316   */
9317
9318   item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", 
9319                                        accel_group);
9320
9321   /* This function generates the menu items. Pass the item factory,
9322      the number of items in the array, the array itself, and any
9323      callback data for the the menu items. */
9324   gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
9325
9326   /* Attach the new accelerator group to the window. */
9327   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
9328
9329   if (menubar)
9330     /* Finally, return the actual menu bar created by the item factory. */ 
9331     *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
9332 }
9333
9334 int main(int argc, char *argv[]) {
9335   GtkWidget *window;
9336   GtkWidget *main_vbox;
9337   GtkWidget *menubar;
9338   
9339   gtk_init(&amp;argc, &amp;argv);
9340   
9341   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9342   gtk_signal_connect(GTK_OBJECT(window), "destroy", 
9343                      GTK_SIGNAL_FUNC(gtk_main_quit), 
9344                      "WM destroy");
9345   gtk_window_set_title(GTK_WINDOW(window), "Item Factory");
9346   gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);
9347   
9348   main_vbox = gtk_vbox_new(FALSE, 1);
9349   gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
9350   gtk_container_add(GTK_CONTAINER(window), main_vbox);
9351   gtk_widget_show(main_vbox);
9352   
9353   get_main_menu(window, &amp;menubar);
9354   gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
9355   gtk_widget_show(menubar);
9356   
9357   gtk_widget_show(window);
9358   gtk_main();
9359   
9360   return(0);
9361 }
9362 /* example-end */
9363 </verb></tscreen>
9364
9365
9366 For now, there's only this example.  An explanation and lots 'o' comments
9367 will follow later.
9368
9369 <!-- ***************************************************************** -->
9370 <sect> Text Widget
9371 <!-- ***************************************************************** -->
9372 <p>
9373 The Text widget allows multiple lines of text to be displayed and
9374 edited.  It supports both multi-colored and multi-font text, allowing
9375 them to be mixed in any way we wish. It also has a wide set of key
9376 based text editing commands, which are compatible with Emacs.
9377
9378 The text widget supports full cut-and-paste facilities, including the
9379 use of double- and triple-click to select a word and a whole line,
9380 respectively.
9381
9382 <!-- ----------------------------------------------------------------- -->
9383 <sect1>Creating and Configuring a Text box
9384 <p>
9385 There is only one function for creating a new Text widget.
9386
9387 <tscreen><verb>
9388 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
9389                          GtkAdjustment *vadj );
9390 </verb></tscreen>
9391
9392 The arguments allow us to give the Text widget pointers to Adjustments
9393 that can be used to track the viewing position of the widget. Passing
9394 NULL values to either or both of these arguments will cause the
9395 gtk_text_new function to create its own.
9396
9397 <tscreen><verb>
9398 void gtk_text_set_adjustments( GtkText       *text,
9399                                GtkAdjustment *hadj,
9400                                GtkAdjustment *vadj );
9401 </verb></tscreen>
9402
9403 The above function allows the horizontal and vertical adjustments of a
9404 text widget to be changed at any time.
9405
9406 The text widget will not automatically create its own scrollbars when
9407 the amount of text to be displayed is too long for the display
9408 window. We therefore have to create and add them to the display layout
9409 ourselves.
9410
9411 <tscreen><verb>
9412   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
9413   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
9414   gtk_widget_show (vscrollbar);
9415 </verb></tscreen>
9416
9417 The above code snippet creates a new vertical scrollbar, and attaches
9418 it to the vertical adjustment of the text widget, <tt/text/. It then
9419 packs it into a box in the normal way.
9420
9421 Note, currently the GtkText widget does not support horizontal
9422 scrollbars.
9423
9424 There are two main ways in which a Text widget can be used: to allow
9425 the user to edit a body of text, or to allow us to display multiple
9426 lines of text to the user. In order for us to switch between these
9427 modes of operation, the text widget has the following function:
9428
9429 <tscreen><verb>
9430 void gtk_text_set_editable( GtkText *text,
9431                             gint     editable );
9432 </verb></tscreen>
9433
9434 The <tt/editable/ argument is a TRUE or FALSE value that specifies
9435 whether the user is permitted to edit the contents of the Text
9436 widget. When the text widget is editable, it will display a cursor at
9437 the current insertion point.
9438
9439 You are not, however, restricted to just using the text widget in
9440 these two modes. You can toggle the editable state of the text widget
9441 at any time, and can insert text at any time.
9442
9443 The text widget wraps lines of text that are too long to fit onto a
9444 single line of the display window. Its default behaviour is to break
9445 words across line breaks. This can be changed using the next function:
9446
9447 <tscreen><verb>
9448 void gtk_text_set_word_wrap( GtkText *text,
9449                              gint     word_wrap );
9450 </verb></tscreen>
9451
9452 Using this function allows us to specify that the text widget should
9453 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
9454 TRUE or FALSE value.
9455
9456 <!-- ----------------------------------------------------------------- -->
9457 <sect1>Text Manipulation
9458 <P>
9459 The current insertion point of a Text widget can be set using
9460 <tscreen><verb>
9461 void gtk_text_set_point( GtkText *text,
9462                          guint    index );
9463 </verb></tscreen>
9464
9465 where <tt/index/ is the position to set the insertion point.
9466
9467 Analogous to this is the function for getting the current insertion
9468 point:
9469
9470 <tscreen><verb>
9471 guint gtk_text_get_point( GtkText *text );
9472 </verb></tscreen>
9473
9474 A function that is useful in combination with the above two functions
9475 is
9476
9477 <tscreen><verb>
9478 guint gtk_text_get_length( GtkText *text );
9479 </verb></tscreen>
9480
9481 which returns the current length of the Text widget. The length is the
9482 number of characters that are within the text block of the widget,
9483 including characters such as carriage-return, which marks the end of
9484 lines.
9485
9486 In order to insert text at the current insertion point of a Text
9487 widget, the function gtk_text_insert is used, which also allows us to
9488 specify background and foreground colors and a font for the text.
9489
9490 <tscreen><verb>
9491 void gtk_text_insert( GtkText    *text,
9492                       GdkFont    *font,
9493                       GdkColor   *fore,
9494                       GdkColor   *back,
9495                       const char *chars,
9496                       gint        length );
9497 </verb></tscreen>
9498
9499 Passing a value of <tt/NULL/ in as the value for the foreground color,
9500 background colour or font will result in the values set within the
9501 widget style to be used. Using a value of <tt/-1/ for the length
9502 parameter will result in the whole of the text string given being
9503 inserted.
9504
9505 The text widget is one of the few within GTK that redraws itself
9506 dynamically, outside of the gtk_main function. This means that all
9507 changes to the contents of the text widget take effect
9508 immediately. This may be undesirable when performing multiple changes
9509 to the text widget. In order to allow us to perform multiple updates
9510 to the text widget without it continuously redrawing, we can freeze
9511 the widget, which temporarily stops it from automatically redrawing
9512 itself every time it is changed. We can then thaw the widget after our
9513 updates are complete.
9514
9515 The following two functions perform this freeze and thaw action:
9516
9517 <tscreen><verb>
9518 void gtk_text_freeze( GtkText *text );
9519
9520 void gtk_text_thaw( GtkText *text );         
9521 </verb></tscreen>
9522
9523 Text is deleted from the text widget relative to the current insertion
9524 point by the following two functions. The return value is a TRUE or
9525 FALSE indicator of whether the operation was successful.
9526
9527 <tscreen><verb>
9528 gint gtk_text_backward_delete( GtkText *text,
9529                                guint    nchars );
9530
9531 gint gtk_text_forward_delete ( GtkText *text,
9532                                guint    nchars );
9533 </verb></tscreen>
9534
9535 If you want to retrieve the contents of the text widget, then the
9536 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
9537 character at position <tt/index/ within the text widget <tt/t/.
9538
9539 To retrieve larger blocks of text, we can use the function
9540
9541 <tscreen><verb>
9542 gchar *gtk_editable_get_chars( GtkEditable *editable,
9543                                gint         start_pos,
9544                                gint         end_pos );   
9545 </verb></tscreen>
9546
9547 This is a function of the parent class of the text widget. A value of
9548 -1 as <tt/end_pos/ signifies the end of the text. The index of the
9549 text starts at 0.
9550
9551 The function allocates a new chunk of memory for the text block, so
9552 don't forget to free it with a call to g_free when you have finished
9553 with it.
9554  
9555 <!-- ----------------------------------------------------------------- -->
9556 <sect1>Keyboard Shortcuts
9557 <p>
9558 The text widget has a number of pre-installed keyboard shortcuts for
9559 common editing, motion and selection functions. These are accessed
9560 using Control and Alt key combinations.
9561
9562 In addition to these, holding down the Control key whilst using cursor
9563 key movement will move the cursor by words rather than
9564 characters. Holding down Shift whilst using cursor movement will
9565 extend the selection.
9566
9567 <sect2>Motion Shortcuts
9568 <p>
9569 <itemize>
9570 <item> Ctrl-A   Beginning of line
9571 <item> Ctrl-E   End of line
9572 <item> Ctrl-N   Next Line
9573 <item> Ctrl-P   Previous Line
9574 <item> Ctrl-B   Backward one character
9575 <item> Ctrl-F   Forward one character
9576 <item> Alt-B    Backward one word
9577 <item> Alt-F    Forward one word
9578 </itemize>
9579
9580 <sect2>Editing Shortcuts
9581 <p>
9582 <itemize>
9583 <item> Ctrl-H   Delete Backward Character (Backspace)
9584 <item> Ctrl-D   Delete Forward Character (Delete)
9585 <item> Ctrl-W   Delete Backward Word
9586 <item> Alt-D    Delete Forward Word
9587 <item> Ctrl-K   Delete to end of line
9588 <item> Ctrl-U   Delete line
9589 </itemize>
9590
9591 <sect2>Selection Shortcuts
9592 <p>
9593 <itemize>
9594 <item> Ctrl-X   Cut to clipboard
9595 <item> Ctrl-C   Copy to clipboard
9596 <item> Ctrl-V   Paste from clipboard
9597 </itemize>
9598
9599 <!-- ----------------------------------------------------------------- -->
9600 <sect1>A GtkText Example
9601 <p>
9602 <tscreen><verb>
9603 /* example-start text text.c */
9604
9605 /* text.c */
9606
9607 #include <stdio.h>
9608 #include <gtk/gtk.h>
9609
9610 void text_toggle_editable (GtkWidget *checkbutton,
9611                            GtkWidget *text)
9612 {
9613   gtk_text_set_editable(GTK_TEXT(text),
9614                         GTK_TOGGLE_BUTTON(checkbutton)->active);
9615 }
9616
9617 void text_toggle_word_wrap (GtkWidget *checkbutton,
9618                             GtkWidget *text)
9619 {
9620   gtk_text_set_word_wrap(GTK_TEXT(text),
9621                          GTK_TOGGLE_BUTTON(checkbutton)->active);
9622 }
9623
9624 void close_application( GtkWidget *widget, gpointer data )
9625 {
9626        gtk_main_quit();
9627 }
9628
9629 int main (int argc, char *argv[])
9630 {
9631   GtkWidget *window;
9632   GtkWidget *box1;
9633   GtkWidget *box2;
9634   GtkWidget *hbox;
9635   GtkWidget *button;
9636   GtkWidget *check;
9637   GtkWidget *separator;
9638   GtkWidget *table;
9639   GtkWidget *vscrollbar;
9640   GtkWidget *text;
9641   GdkColormap *cmap;
9642   GdkColor colour;
9643   GdkFont *fixed_font;
9644
9645   FILE *infile;
9646
9647   gtk_init (&amp;argc, &amp;argv);
9648  
9649   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9650   gtk_widget_set_usize (window, 600, 500);
9651   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
9652   gtk_signal_connect (GTK_OBJECT (window), "destroy",
9653                       GTK_SIGNAL_FUNC(close_application),
9654                       NULL);
9655   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
9656   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9657   
9658   
9659   box1 = gtk_vbox_new (FALSE, 0);
9660   gtk_container_add (GTK_CONTAINER (window), box1);
9661   gtk_widget_show (box1);
9662   
9663   
9664   box2 = gtk_vbox_new (FALSE, 10);
9665   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9666   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9667   gtk_widget_show (box2);
9668   
9669   
9670   table = gtk_table_new (2, 2, FALSE);
9671   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
9672   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
9673   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
9674   gtk_widget_show (table);
9675   
9676   /* Create the GtkText widget */
9677   text = gtk_text_new (NULL, NULL);
9678   gtk_text_set_editable (GTK_TEXT (text), TRUE);
9679   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
9680                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
9681                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
9682   gtk_widget_show (text);
9683
9684   /* Add a vertical scrollbar to the GtkText widget */
9685   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
9686   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
9687                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
9688   gtk_widget_show (vscrollbar);
9689
9690   /* Get the system colour map and allocate the colour red */
9691   cmap = gdk_colormap_get_system();
9692   colour.red = 0xffff;
9693   colour.green = 0;
9694   colour.blue = 0;
9695   if (!gdk_color_alloc(cmap, &amp;colour)) {
9696     g_error("couldn't allocate colour");
9697   }
9698
9699   /* Load a fixed font */
9700   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
9701
9702   /* Realizing a widget creates a window for it, ready for us to insert some text */
9703   gtk_widget_realize (text);
9704
9705   /* Freeze the text widget, ready for multiple updates */
9706   gtk_text_freeze (GTK_TEXT (text));
9707   
9708   /* Insert some coloured text */
9709   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9710                    "Supports ", -1);
9711   gtk_text_insert (GTK_TEXT (text), NULL, &amp;colour, NULL,
9712                    "colored ", -1);
9713   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9714                    "text and different ", -1);
9715   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
9716                    "fonts\n\n", -1);
9717   
9718   /* Load the file text.c into the text window */
9719
9720   infile = fopen("text.c", "r");
9721   
9722   if (infile) {
9723     char buffer[1024];
9724     int nchars;
9725     
9726     while (1)
9727       {
9728         nchars = fread(buffer, 1, 1024, infile);
9729         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
9730                          NULL, buffer, nchars);
9731         
9732         if (nchars < 1024)
9733           break;
9734       }
9735     
9736     fclose (infile);
9737   }
9738
9739   /* Thaw the text widget, allowing the updates to become visible */  
9740   gtk_text_thaw (GTK_TEXT (text));
9741   
9742   hbox = gtk_hbutton_box_new ();
9743   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9744   gtk_widget_show (hbox);
9745
9746   check = gtk_check_button_new_with_label("Editable");
9747   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9748   gtk_signal_connect (GTK_OBJECT(check), "toggled",
9749                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
9750   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9751   gtk_widget_show (check);
9752   check = gtk_check_button_new_with_label("Wrap Words");
9753   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9754   gtk_signal_connect (GTK_OBJECT(check), "toggled",
9755                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
9756   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9757   gtk_widget_show (check);
9758
9759   separator = gtk_hseparator_new ();
9760   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9761   gtk_widget_show (separator);
9762
9763   box2 = gtk_vbox_new (FALSE, 10);
9764   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9765   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9766   gtk_widget_show (box2);
9767   
9768   button = gtk_button_new_with_label ("close");
9769   gtk_signal_connect (GTK_OBJECT (button), "clicked",
9770                       GTK_SIGNAL_FUNC(close_application),
9771                       NULL);
9772   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9773   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9774   gtk_widget_grab_default (button);
9775   gtk_widget_show (button);
9776
9777   gtk_widget_show (window);
9778
9779   gtk_main ();
9780   
9781   return(0);       
9782 }
9783 /* example-end */
9784 </verb></tscreen>
9785
9786
9787 <!-- ***************************************************************** -->
9788 <sect> Undocumented Widgets
9789 <!-- ***************************************************************** -->
9790 <p>
9791 These all require authors! :) Please consider contributing to our
9792 tutorial.
9793
9794 If you must use one of these widgets that are undocumented, I strongly
9795 suggest you take a look at their respective header files in the GTK
9796 distribution. GTK's function names are very descriptive. Once you
9797 have an understanding of how things work, it's not difficult to figure
9798 out how to use a widget simply by looking at its function
9799 declarations. This, along with a few examples from others' code, and
9800 it should be no problem.
9801
9802 When you do come to understand all the functions of a new undocumented
9803 widget, please consider writing a tutorial on it so others may benefit
9804 from your time.
9805
9806 <!-- ----------------------------------------------------------------- -->
9807 <sect1> Calendar
9808 <p>
9809 <!-- ----------------------------------------------------------------- -->
9810 <sect1> Combo box
9811 <p>
9812 <!-- ----------------------------------------------------------------- -->
9813 <sect1> CTree
9814 <p>
9815 <!-- ----------------------------------------------------------------- -->
9816 <sect1> Curves
9817 <p>
9818 <!-- ----------------------------------------------------------------- -->
9819 <sect1> Drawing Area
9820 <p>
9821 <!-- ----------------------------------------------------------------- -->
9822 <sect1> Font Selection Dialog
9823 <p>
9824 <!-- ----------------------------------------------------------------- -->
9825 <sect1> Gamma Curve
9826 <p>
9827 <!-- ----------------------------------------------------------------- -->
9828 <sect1> Image
9829 <p>
9830 <!-- ----------------------------------------------------------------- -->
9831 <sect1> Packer
9832 <p>
9833 <!-- ----------------------------------------------------------------- -->
9834 <sect1> Plugs and Sockets
9835 <p>
9836 <!-- ----------------------------------------------------------------- -->
9837 <sect1> Preview
9838 <p>
9839
9840 <!--
9841
9842 (This may need to be rewritten to follow the style of the rest of the tutorial)
9843
9844 <tscreen><verb>
9845
9846 Previews serve a number of purposes in GIMP/GTK. The most important one is
9847 this. High quality images may take up to tens of megabytes of memory - easy!
9848 Any operation on an image that big is bound to take a long time. If it takes
9849 you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after
9850 you make an error) to choose the desired modification, it make take you
9851 literally hours to make the right one - if you don't run out of memory
9852 first. People who have spent hours in color darkrooms know the feeling.
9853 Previews to the rescue!
9854
9855 But the annoyance of the delay is not the only issue. Oftentimes it is
9856 helpful to compare the Before and After versions side-by-side or at least
9857 back-to-back. If you're working with big images and 10 second delays,
9858 obtaining the Before and After impressions is, to say the least, difficult.
9859 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
9860 out for most people, while back-to-back is more like back-to-1001, 1002,
9861 ..., 1010-back! Previews to the rescue!
9862
9863 But there's more. Previews allow for side-by-side pre-previews. In other
9864 words, you write a plug-in (e.g. the filterpack simulation) which would have
9865 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
9866 An approach like this acts as a sort of a preview palette and is very
9867 effective for subtle changes. Let's go previews!
9868
9869 There's more. For certain plug-ins real-time image-specific human
9870 intervention maybe necessary. In the SuperNova plug-in, for example, the
9871 user is asked to enter the coordinates of the center of the future
9872 supernova. The easiest way to do this, really, is to present the user with a
9873 preview and ask him to interactively select the spot. Let's go previews!
9874
9875 Finally, a couple of misc uses. One can use previews even when not working
9876 with big images. For example, they are useful when rendering complicated
9877 patterns. (Just check out the venerable Diffraction plug-in + many other
9878 ones!) As another example, take a look at the colormap rotation plug-in
9879 (work in progress). You can also use previews for little logos inside you
9880 plug-ins and even for an image of yourself, The Author. Let's go previews!
9881
9882 When Not to Use Previews
9883
9884 Don't use previews for graphs, drawing etc. GDK is much faster for that. Use
9885 previews only for rendered images!
9886
9887 Let's go previews!
9888
9889 You can stick a preview into just about anything. In a vbox, an hbox, a
9890 table, a button, etc. But they look their best in tight frames around them.
9891 Previews by themselves do not have borders and look flat without them. (Of
9892 course, if the flat look is what you want...) Tight frames provide the
9893 necessary borders.
9894
9895                                [Image][Image]
9896
9897 Previews in many ways are like any other widgets in GTK (whatever that
9898 means) except they possess an additional feature: they need to be filled with
9899 some sort of an image! First, we will deal exclusively with the GTK aspect
9900 of previews and then we'll discuss how to fill them.
9901
9902 GtkWidget *preview!
9903
9904 Without any ado:
9905
9906                               /* Create a preview widget,
9907                               set its size, an show it */
9908 GtkWidget *preview;
9909 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
9910                               /*Other option:
9911                               GTK_PREVIEW_GRAYSCALE);*/
9912 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
9913 gtk_widget_show(preview);
9914 my_preview_rendering_function(preview);
9915
9916 Oh yeah, like I said, previews look good inside frames, so how about:
9917
9918 GtkWidget *create_a_preview(int        Width,
9919                             int        Height,
9920                             int        Colorfulness)
9921 {
9922   GtkWidget *preview;
9923   GtkWidget *frame;
9924   
9925   frame = gtk_frame_new(NULL);
9926   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
9927   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
9928   gtk_widget_show(frame);
9929
9930   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
9931                                        :GTK_PREVIEW_GRAYSCALE);
9932   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
9933   gtk_container_add(GTK_CONTAINER(frame),preview);
9934   gtk_widget_show(preview);
9935
9936   my_preview_rendering_function(preview);
9937   return frame;
9938 }
9939
9940 That's my basic preview. This routine returns the "parent" frame so you can
9941 place it somewhere else in your interface. Of course, you can pass the
9942 parent frame to this routine as a parameter. In many situations, however,
9943 the contents of the preview are changed continually by your application. In
9944 this case you may want to pass a pointer to the preview to a
9945 "create_a_preview()" and thus have control of it later.
9946
9947 One more important note that may one day save you a lot of time. Sometimes
9948 it is desirable to label you preview. For example, you may label the preview
9949 containing the original image as "Original" and the one containing the
9950 modified image as "Less Original". It might occur to you to pack the
9951 preview along with the appropriate label into a vbox. The unexpected caveat
9952 is that if the label is wider than the preview (which may happen for a
9953 variety of reasons unforseeable to you, from the dynamic decision on the
9954 size of the preview to the size of the font) the frame expands and no longer
9955 fits tightly over the preview. The same problem can probably arise in other
9956 situations as well.
9957
9958                                    [Image]
9959
9960 The solution is to place the preview and the label into a 2x1 table and by
9961 attaching them with the following parameters (this is one possible variations
9962 of course. The key is no GTK_FILL in the second attachment):
9963
9964 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
9965                  0,
9966                  GTK_EXPAND|GTK_FILL,
9967                  0,0);
9968 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
9969                  GTK_EXPAND,
9970                  GTK_EXPAND,
9971                  0,0);
9972
9973
9974 And here's the result:
9975
9976                                    [Image]
9977
9978 Misc
9979
9980 Making a preview clickable is achieved most easily by placing it in a
9981 button. It also adds a nice border around the preview and you may not even
9982 need to place it in a frame. See the Filter Pack Simulation plug-in for an
9983 example.
9984
9985 This is pretty much it as far as GTK is concerned.
9986
9987 Filling In a Preview
9988
9989 In order to familiarize ourselves with the basics of filling in previews,
9990 let's create the following pattern (contrived by trial and error):
9991
9992                                    [Image]
9993
9994 void
9995 my_preview_rendering_function(GtkWidget     *preview)
9996 {
9997 #define SIZE 100
9998 #define HALF (SIZE/2)
9999
10000   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
10001   gint i, j;                             /* Coordinates    */
10002   double r, alpha, x, y;
10003
10004   if (preview==NULL) return; /* I usually add this when I want */
10005                              /* to avoid silly crashes. You    */
10006                              /* should probably make sure that */
10007                              /* everything has been nicely     */
10008                              /* initialized!                   */
10009   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
10010                                          /* glib.h contains ABS(x).   */
10011         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
10012         row[i*3+1] = 128;                /* Define Green              */
10013         row[i*3+2] = 224;                /* Define Blue               */
10014       }                                  /* "+0" is for alignment!    */
10015       else {
10016         row[i*3+0] = r*255;
10017         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
10018         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
10019       }
10020     }
10021     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
10022     /* Insert "row" into "preview" starting at the point with  */
10023     /* coordinates (0,j) first column, j_th row extending SIZE */
10024     /* pixels to the right */
10025   }
10026
10027   free(row); /* save some space */
10028   gtk_widget_draw(preview,NULL); /* what does this do? */
10029   gdk_flush(); /* or this? */
10030 }
10031
10032 Non-GIMP users can have probably seen enough to do a lot of things already.
10033 For the GIMP users I have a few pointers to add.
10034
10035 Image Preview
10036
10037 It is probably wise to keep a reduced version of the image around with just
10038 enough pixels to fill the preview. This is done by selecting every n'th
10039 pixel where n is the ratio of the size of the image to the size of the
10040 preview. All further operations (including filling in the previews) are then
10041 performed on the reduced number of pixels only. The following is my
10042 implementation of reducing the image. (Keep in mind that I've had only basic
10043 C!)
10044
10045 (UNTESTED CODE ALERT!!!)
10046
10047 typedef struct {
10048   gint      width;
10049   gint      height;
10050   gint      bbp;
10051   guchar    *rgb;
10052   guchar    *mask;
10053 } ReducedImage;
10054
10055 enum {
10056   SELECTION_ONLY,
10057   SELECTION_IN_CONTEXT,
10058   ENTIRE_IMAGE
10059 };
10060
10061 ReducedImage *Reduce_The_Image(GDrawable *drawable,
10062                                GDrawable *mask,
10063                                gint LongerSize,
10064                                gint Selection)
10065 {
10066   /* This function reduced the image down to the the selected preview size */
10067   /* The preview size is determine by LongerSize, i.e. the greater of the  */
10068   /* two dimensions. Works for RGB images only!                            */
10069   gint RH, RW;          /* Reduced height and reduced width                */
10070   gint width, height;   /* Width and Height of the area being reduced      */
10071   gint bytes=drawable->bpp;
10072   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
10073
10074   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
10075   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
10076   GPixelRgn srcPR, srcMask;
10077   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
10078                              /* image.                                     */
10079
10080   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
10081   width  = x2-x1;
10082   height = y2-y1;
10083   /* If there's a SELECTION, we got its bounds!)
10084
10085   if (width != drawable->width &amp;&amp; height != drawable->height)
10086     NoSelectionMade=FALSE;
10087   /* Become aware of whether the user has made an active selection   */
10088   /* This will become important later, when creating a reduced mask. */
10089
10090   /* If we want to preview the entire image, overrule the above!  */
10091   /* Of course, if no selection has been made, this does nothing! */
10092   if (Selection==ENTIRE_IMAGE) {
10093     x1=0;
10094     x2=drawable->width;
10095     y1=0;
10096     y2=drawable->height;
10097   }
10098
10099   /* If we want to preview a selection with some surrounding area we */
10100   /* have to expand it a little bit. Consider it a bit of a riddle. */
10101   if (Selection==SELECTION_IN_CONTEXT) {
10102     x1=MAX(0,                x1-width/2.0);
10103     x2=MIN(drawable->width,  x2+width/2.0);
10104     y1=MAX(0,                y1-height/2.0);
10105     y2=MIN(drawable->height, y2+height/2.0);
10106   }
10107
10108   /* How we can determine the width and the height of the area being */
10109   /* reduced.                                                        */
10110   width  = x2-x1;
10111   height = y2-y1;
10112
10113   /* The lines below determine which dimension is to be the longer   */
10114   /* side. The idea borrowed from the supernova plug-in. I suspect I */
10115   /* could've thought of it myself, but the truth must be told.      */
10116   /* Plagiarism stinks!                                               */
10117   if (width>height) {
10118     RW=LongerSize;
10119     RH=(float) height * (float) LongerSize/ (float) width;
10120   }
10121   else {
10122     RH=LongerSize;
10123     RW=(float)width * (float) LongerSize/ (float) height;
10124   }
10125
10126   /* The entire image is stretched into a string! */
10127   tempRGB   = (guchar *) malloc(RW*RH*bytes);
10128   tempmask  = (guchar *) malloc(RW*RH);
10129
10130   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height, FALSE, FALSE);
10131   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height, FALSE, FALSE);
10132
10133   /* Grab enough to save a row of image and a row of mask. */
10134   src_row       = (guchar *) malloc (width*bytes);
10135   src_mask_row  = (guchar *) malloc (width);
10136
10137   for (i=0; i < RH; i++) {
10138     whichrow=(float)i*(float)height/(float)RH;
10139     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
10140     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
10141
10142     for (j=0; j < RW; j++) {
10143       whichcol=(float)j*(float)width/(float)RW;
10144
10145       /* No selection made = each point is completely selected! */
10146       if (NoSelectionMade)
10147         tempmask[i*RW+j]=255;
10148       else
10149         tempmask[i*RW+j]=src_mask_row[whichcol];
10150
10151       /* Add the row to the one long string which now contains the image! */
10152       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
10153       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
10154       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
10155
10156       /* Hold on to the alpha as well */
10157       if (bytes==4)
10158         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
10159     }
10160   }
10161   temp->bpp=bytes;
10162   temp->width=RW;
10163   temp->height=RH;
10164   temp->rgb=tempRGB;
10165   temp->mask=tempmask;
10166   return temp;
10167 }
10168
10169 The following is a preview function which used the same ReducedImage type!
10170 Note that it uses fakes transparency (if one is present by means of
10171 fake_transparency which is defined as follows:
10172
10173 gint fake_transparency(gint i, gint j)
10174 {
10175   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
10176     return 64;
10177   else
10178     return 196;
10179 }
10180
10181 Now here's the preview function:
10182
10183 void
10184 my_preview_render_function(GtkWidget     *preview,
10185                            gint          changewhat,
10186                            gint          changewhich)
10187 {
10188   gint Inten, bytes=drawable->bpp;
10189   gint i, j, k;
10190   float partial;
10191   gint RW=reduced->width;
10192   gint RH=reduced->height;
10193   guchar *row=malloc(bytes*RW);;
10194
10195
10196   for (i=0; i < RH; i++) {
10197     for (j=0; j < RW; j++) {
10198
10199       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
10200       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
10201       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
10202
10203       if (bytes==4)
10204         for (k=0; k<3; k++) {
10205           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
10206           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
10207         }
10208     }
10209     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
10210   }
10211
10212   free(a);
10213   gtk_widget_draw(preview,NULL);
10214   gdk_flush();
10215 }
10216
10217 Applicable Routines
10218
10219 guint           gtk_preview_get_type           (void);
10220 /* No idea */
10221 void            gtk_preview_uninit             (void);
10222 /* No idea */
10223 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
10224 /* Described above */
10225 void            gtk_preview_size               (GtkPreview      *preview,
10226                                                 gint             width,
10227                                                 gint             height);
10228 /* Allows you to resize an existing preview.    */
10229 /* Apparently there's a bug in GTK which makes  */
10230 /* this process messy. A way to clean up a mess */
10231 /* is to manually resize the window containing  */
10232 /* the preview after resizing the preview.      */
10233
10234 void            gtk_preview_put                (GtkPreview      *preview,
10235                                                 GdkWindow       *window,
10236                                                 GdkGC           *gc,
10237                                                 gint             srcx,
10238                                                 gint             srcy,
10239                                                 gint             destx,
10240                                                 gint             desty,
10241                                                 gint             width,
10242                                                 gint             height);
10243 /* No idea */
10244
10245 void            gtk_preview_put_row            (GtkPreview      *preview,
10246                                                 guchar          *src,
10247                                                 guchar          *dest,
10248                                                 gint             x,
10249                                                 gint             y,
10250                                                 gint             w);
10251 /* No idea */
10252
10253 void            gtk_preview_draw_row           (GtkPreview      *preview,
10254                                                 guchar          *data,
10255                                                 gint             x,
10256                                                 gint             y,
10257                                                 gint             w);
10258 /* Described in the text */
10259
10260 void            gtk_preview_set_expand         (GtkPreview      *preview,
10261                                                 gint             expand);
10262 /* No idea */
10263
10264 /* No clue for any of the below but    */
10265 /* should be standard for most widgets */
10266 void            gtk_preview_set_gamma          (double           gamma);
10267 void            gtk_preview_set_color_cube     (guint            nred_shades,
10268                                                 guint            ngreen_shades,
10269                                                 guint            nblue_shades,
10270                                                 guint            ngray_shades);
10271 void            gtk_preview_set_install_cmap   (gint             install_cmap);
10272 void            gtk_preview_set_reserved       (gint             nreserved);
10273 GdkVisual*      gtk_preview_get_visual         (void);
10274 GdkColormap*    gtk_preview_get_cmap           (void);
10275 GtkPreviewInfo* gtk_preview_get_info           (void);
10276
10277 That's all, folks!
10278
10279 </verb></tscreen>
10280
10281 -->
10282
10283 <!-- ***************************************************************** -->
10284 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
10285 <!-- ***************************************************************** -->
10286 <p>
10287 This describes the functions used to operate on widgets.  These can be
10288 used to set style, padding, size etc.
10289
10290 (Maybe I should make a whole section on accelerators.)
10291
10292 <tscreen><verb>
10293 void gtk_widget_install_accelerator( GtkWidget           *widget,
10294                                      GtkAcceleratorTable *table,
10295                                      gchar               *signal_name,
10296                                      gchar                key,
10297                                      guint8               modifiers );
10298
10299 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
10300                                      GtkAcceleratorTable *table,
10301                                      gchar               *signal_name);
10302
10303 void gtk_widget_activate( GtkWidget *widget );
10304
10305 void gtk_widget_set_name( GtkWidget *widget,
10306                           gchar     *name );
10307
10308 gchar *gtk_widget_get_name( GtkWidget *widget );
10309
10310 void gtk_widget_set_sensitive( GtkWidget *widget,
10311                                gint       sensitive );
10312
10313 void gtk_widget_set_style( GtkWidget *widget,
10314                            GtkStyle  *style );
10315                                            
10316 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
10317
10318 GtkStyle *gtk_widget_get_default_style( void );
10319
10320 void gtk_widget_set_uposition( GtkWidget *widget,
10321                                gint       x,
10322                                gint       y );
10323
10324 void gtk_widget_set_usize( GtkWidget *widget,
10325                            gint       width,
10326                            gint       height );
10327
10328 void gtk_widget_grab_focus( GtkWidget *widget );
10329
10330 void gtk_widget_show( GtkWidget *widget );
10331
10332 void gtk_widget_hide( GtkWidget *widget );
10333 </verb></tscreen>
10334
10335 <!-- ***************************************************************** -->
10336 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
10337 <!-- ***************************************************************** -->
10338
10339 <!-- ----------------------------------------------------------------- -->
10340 <sect1>Timeouts
10341 <p>
10342 You may be wondering how you make GTK do useful work when in gtk_main.
10343 Well, you have several options. Using the following functions you can
10344 create a timeout function that will be called every "interval"
10345 milliseconds.
10346
10347 <tscreen><verb>
10348 gint gtk_timeout_add( guint32     interval,
10349                       GtkFunction function,
10350                       gpointer    data );
10351 </verb></tscreen>
10352
10353 The first argument is the number of milliseconds between calls to your
10354 function. The second argument is the function you wish to have called,
10355 and the third, the data passed to this callback function. The return
10356 value is an integer "tag" which may be used to stop the timeout by
10357 calling:
10358
10359 <tscreen><verb>
10360 void gtk_timeout_remove( gint tag );
10361 </verb></tscreen>
10362
10363 You may also stop the timeout function by returning zero or FALSE from
10364 your callback function. Obviously this means if you want your function
10365 to continue to be called, it should return a non-zero value,
10366 i.e. TRUE.
10367
10368 The declaration of your callback should look something like this:
10369
10370 <tscreen><verb>
10371 gint timeout_callback( gpointer data );
10372 </verb></tscreen>
10373
10374 <!-- ----------------------------------------------------------------- -->
10375 <sect1>Monitoring IO
10376 <p>
10377 A nifty feature of GDK (the library that underlies GTK), is the
10378 ability to have it check for data on a file descriptor for you (as
10379 returned by open(2) or socket(2)). This is especially useful for
10380 networking applications. The function:
10381
10382 <tscreen><verb>
10383 gint gdk_input_add( gint              source,
10384                     GdkInputCondition condition,
10385                     GdkInputFunction  function,
10386                     gpointer          data );
10387 </verb></tscreen>
10388
10389 Where the first argument is the file descriptor you wish to have
10390 watched, and the second specifies what you want GDK to look for. This
10391 may be one of:
10392
10393 <itemize>
10394 <item>GDK_INPUT_READ - Call your function when there is data ready for
10395 reading on your file descriptor.
10396
10397 <item>GDK_INPUT_WRITE - Call your function when the file descriptor is
10398 ready for writing.
10399 </itemize>
10400
10401 As I'm sure you've figured out already, the third argument is the
10402 function you wish to have called when the above conditions are
10403 satisfied, and the fourth is the data to pass to this function.
10404
10405 The return value is a tag that may be used to stop GDK from monitoring
10406 this file descriptor using the following function.
10407
10408 <tscreen><verb>
10409 void gdk_input_remove( gint tag );
10410 </verb></tscreen>
10411
10412 The callback function should be declared as:
10413
10414 <tscreen><verb>
10415 void input_callback( gpointer          data,
10416                      gint              source, 
10417                      GdkInputCondition condition );
10418 </verb></tscreen>
10419
10420 Where <tt/source/ and <tt/condition/ are as specified above.
10421
10422 <!-- ----------------------------------------------------------------- -->
10423 <sect1>Idle Functions
10424 <p>
10425 <!-- TODO: Need to check on idle priorities - TRG -->
10426 What if you have a function you want called when nothing else is
10427 happening ?
10428
10429 <tscreen><verb>
10430 gint gtk_idle_add( GtkFunction function,
10431                    gpointer    data );
10432 </verb></tscreen>
10433
10434 This causes GTK to call the specified function whenever nothing else
10435 is happening.
10436
10437 <tscreen><verb>
10438 void gtk_idle_remove( gint tag );
10439 </verb></tscreen>
10440
10441 I won't explain the meaning of the arguments as they follow very much
10442 like the ones above. The function pointed to by the first argument to
10443 gtk_idle_add will be called whenever the opportunity arises. As with
10444 the others, returning FALSE will stop the idle function from being
10445 called.
10446
10447 <!-- ***************************************************************** -->
10448 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
10449 <!-- ***************************************************************** -->
10450
10451 <!-- ----------------------------------------------------------------- -->
10452 <sect1>Signal Functions
10453
10454 <!-- ----------------------------------------------------------------- -->
10455 <sect2>Connecting and Disconnecting Signal Handlers
10456 <p>
10457
10458 <tscreen><verb>
10459 guint gtk_signal_connect( GtkObject     *object,
10460                           const gchar   *name,
10461                           GtkSignalFunc  func,
10462                           gpointer       func_data );
10463
10464 guint gtk_signal_connect_after( GtkObject     *object,
10465                                 const gchar   *name,
10466                                 GtkSignalFunc  func,
10467                                 gpointer       func_data );
10468
10469 guint gtk_signal_connect_object( GtkObject     *object,
10470                                  const gchar   *name,
10471                                  GtkSignalFunc  func,
10472                                  GtkObject     *slot_object );
10473
10474 guint gtk_signal_connect_object_after( GtkObject     *object,
10475                                        const gchar   *name,
10476                                        GtkSignalFunc  func,
10477                                        GtkObject     *slot_object );
10478
10479 guint gtk_signal_connect_full( GtkObject          *object,
10480                                const gchar        *name,
10481                                GtkSignalFunc       func,
10482                                GtkCallbackMarshal  marshal,
10483                                gpointer            data,
10484                                GtkDestroyNotify    destroy_func,
10485                                gint                object_signal,
10486                                gint                after );
10487
10488 guint gtk_signal_connect_interp( GtkObject          *object,
10489                                  const gchar        *name,
10490                                  GtkCallbackMarshal  func,
10491                                  gpointer            data,
10492                                  GtkDestroyNotify    destroy_func,
10493                                  gint                after );
10494
10495 void gtk_signal_connect_object_while_alive( GtkObject     *object,
10496                                             const gchar   *signal,
10497                                             GtkSignalFunc  func,
10498                                             GtkObject     *alive_object );
10499
10500 void gtk_signal_connect_while_alive( GtkObject     *object,
10501                                      const gchar   *signal,
10502                                      GtkSignalFunc  func,
10503                                      gpointer       func_data,
10504                                      GtkObject     *alive_object );
10505
10506 void gtk_signal_disconnect( GtkObject *object,
10507                             guint      handler_id );
10508
10509 void gtk_signal_disconnect_by_func( GtkObject     *object,
10510                                     GtkSignalFunc  func,
10511                                     gpointer       data );
10512 </verb></tscreen>
10513
10514 <!-- ----------------------------------------------------------------- -->
10515 <sect2>Blocking and Unblocking Signal Handlers
10516 <p>
10517 <tscreen><verb>
10518 void gtk_signal_handler_block( GtkObject *object,
10519                                guint      handler_id);
10520
10521 void gtk_signal_handler_block_by_func( GtkObject     *object,
10522                                        GtkSignalFunc  func,
10523                                        gpointer       data );
10524
10525 void gtk_signal_handler_block_by_data( GtkObject *object,
10526                                        gpointer   data );
10527
10528 void gtk_signal_handler_unblock( GtkObject *object,
10529                                  guint      handler_id );
10530
10531 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
10532                                          GtkSignalFunc  func,
10533                                          gpointer       data );
10534
10535 void gtk_signal_handler_unblock_by_data( GtkObject *object,
10536                                          gpointer   data );
10537 </verb></tscreen>
10538
10539 <!-- ----------------------------------------------------------------- -->
10540 <sect2>Emitting and Stopping Signals
10541 <p>
10542 <tscreen><verb>
10543 void gtk_signal_emit( GtkObject *object,
10544                       guint      signal_id,
10545                       ... );
10546
10547 void gtk_signal_emit_by_name( GtkObject   *object,
10548                               const gchar *name,
10549                               ... );
10550
10551 void gtk_signal_emitv( GtkObject *object,
10552                        guint      signal_id,
10553                        GtkArg    *params );
10554
10555 void gtk_signal_emitv_by_name( GtkObject   *object,
10556                                const gchar *name,
10557                                GtkArg      *params );
10558
10559 guint gtk_signal_n_emissions( GtkObject *object,
10560                               guint      signal_id );
10561
10562 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
10563                                       const gchar *name );
10564
10565 void gtk_signal_emit_stop( GtkObject *object,
10566                            guint      signal_id );
10567
10568 void gtk_signal_emit_stop_by_name( GtkObject   *object,
10569                                    const gchar *name );
10570 </verb></tscreen>
10571
10572 <!-- ----------------------------------------------------------------- -->
10573 <sect1>Signal Emission and Propagation
10574 <p>
10575 Signal emission is the process wherby GTK runs all handlers for a
10576 specific object and signal.
10577
10578 First, note that the return value from a signal emission is the return
10579 value of the <em>last</em> handler executed. Since event signals are
10580 all of type GTK_RUN_LAST, this will be the default (GTK supplied)
10581 default handler, unless you connect with gtk_signal_connect_after().
10582
10583 The way an event (say GTK_BUTTON_PRESS) is handled, is:
10584 <itemize>
10585 <item>Start with the widget where the event occured.
10586
10587 <item>Emit the generic "event" signal. If that signal handler returns
10588 a value of TRUE, stop all processing.
10589
10590 <item>Otherwise, emit a specific, "button_press_event" signal. If that
10591 returns TRUE, stop all processing.
10592
10593 <item>Otherwise, go to the widget's parent, and repeat the above steps.
10594
10595 <item>Contimue until some signal handler returns TRUE, or until the
10596 top-level widget is reached.
10597 </itemize>
10598
10599 Some consequences of the above are:
10600 <itemize>
10601 <item>Your handler's return value will have no effect if there is a
10602 default handler, unless you connect with gtk_signal_connect_after().
10603
10604 <item>To prevent the default handler from being run, you need to
10605 connect with gtk_signal_connect() and use
10606 gtk_signal_emit_stop_by_name() - the return value only affects whether
10607 the signal is propagated, not the current emission.
10608 </itemize>
10609
10610 <!-- ***************************************************************** -->
10611 <sect>Managing Selections
10612 <!-- ***************************************************************** -->
10613
10614 <!-- ----------------------------------------------------------------- -->
10615 <sect1> Overview
10616 <p>
10617 One type of interprocess communication supported by GTK is
10618 <em>selections</em>. A selection identifies a chunk of data, for
10619 instance, a portion of text, selected by the user in some fashion, for
10620 instance, by dragging with the mouse. Only one application on a
10621 display, (the <em>owner</em>) can own a particular selection at one
10622 time, so when a selection is claimed by one application, the previous
10623 owner must indicate to the user that selection has been
10624 relinquished. Other applications can request the contents of a
10625 selection in different forms, called <em>targets</em>. There can be
10626 any number of selections, but most X applications only handle one, the
10627 <em>primary selection</em>.
10628
10629 In most cases, it isn't necessary for a GTK application to deal with
10630 selections itself. The standard widgets, such as the Entry widget,
10631 already have the capability to claim the selection when appropriate
10632 (e.g., when the user drags over text), and to retrieve the contents of
10633 the selection owned by another widget, or another application (e.g.,
10634 when the user clicks the second mouse button). However, there may be
10635 cases in which you want to give other widgets the ability to supply
10636 the selection, or you wish to retrieve targets not supported by
10637 default.
10638
10639 A fundamental concept needed to understand selection handling is that
10640 of the <em>atom</em>. An atom is an integer that uniquely identifies a
10641 string (on a certain display). Certain atoms are predefined by the X
10642 server, and in some cases there are constants in <tt>gtk.h</tt>
10643 corresponding to these atoms. For instance the constant
10644 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
10645 In other cases, you should use the functions
10646 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
10647 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
10648 selections and targets are identified by atoms.
10649
10650 <!-- ----------------------------------------------------------------- -->
10651 <sect1> Retrieving the selection
10652 <p>
10653 Retrieving the selection is an asynchronous process. To start the
10654 process, you call:
10655
10656 <tscreen><verb>
10657 gint gtk_selection_convert( GtkWidget *widget, 
10658                             GdkAtom    selection, 
10659                             GdkAtom    target,
10660                             guint32    time );
10661 </verb</tscreen>
10662
10663 This <em>converts</em> the selection into the form specified by
10664 <tt/target/. If at all possible, the time field should be the time
10665 from the event that triggered the selection. This helps make sure that
10666 events occur in the order that the user requested them. However, if it
10667 is not available (for instance, if the conversion was triggered by a
10668 "clicked" signal), then you can use the constant
10669 <tt>GDK_CURRENT_TIME</tt>.
10670
10671 When the selection owner responds to the request, a
10672 "selection_received" signal is sent to your application. The handler
10673 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
10674 structure, which is defined as:
10675
10676 <tscreen><verb>
10677 struct _GtkSelectionData
10678 {
10679   GdkAtom selection;
10680   GdkAtom target;
10681   GdkAtom type;
10682   gint    format;
10683   guchar *data;
10684   gint    length;
10685 };
10686 </verb></tscreen>
10687
10688 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
10689 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
10690 identifies the type of data returned by the selection owner. Some
10691 possible values are "STRING", a string of latin-1 characters, "ATOM",
10692 a series of atoms, "INTEGER", an integer, etc. Most targets can only
10693 return one type. <tt/format/ gives the length of the units (for
10694 instance characters) in bits. Usually, you don't care about this when
10695 receiving data. <tt>data</tt> is a pointer to the returned data, and
10696 <tt>length</tt> gives the length of the returned data, in bytes. If
10697 <tt>length</tt> is negative, then an error occurred and the selection
10698 could not be retrieved. This might happen if no application owned the
10699 selection, or if you requested a target that the application didn't
10700 support. The buffer is actually guaranteed to be one byte longer than
10701 <tt>length</tt>; the extra byte will always be zero, so it isn't
10702 necessary to make a copy of strings just to null terminate them.
10703
10704 In the following example, we retrieve the special target "TARGETS",
10705 which is a list of all targets into which the selection can be
10706 converted.
10707
10708 <tscreen><verb>
10709 /* example-start selection gettargets.c */
10710
10711 #include <gtk/gtk.h>
10712
10713 void selection_received (GtkWidget *widget, 
10714                          GtkSelectionData *selection_data, 
10715                          gpointer data);
10716
10717 /* Signal handler invoked when user clicks on the "Get Targets" button */
10718 void
10719 get_targets (GtkWidget *widget, gpointer data)
10720 {
10721   static GdkAtom targets_atom = GDK_NONE;
10722
10723   /* Get the atom corresponding to the string "TARGETS" */
10724   if (targets_atom == GDK_NONE)
10725     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
10726
10727   /* And request the "TARGETS" target for the primary selection */
10728   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
10729                          GDK_CURRENT_TIME);
10730 }
10731
10732 /* Signal handler called when the selections owner returns the data */
10733 void
10734 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
10735                     gpointer data)
10736 {
10737   GdkAtom *atoms;
10738   GList *item_list;
10739   int i;
10740
10741   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
10742   if (selection_data->length < 0)
10743     {
10744       g_print ("Selection retrieval failed\n");
10745       return;
10746     }
10747   /* Make sure we got the data in the expected form */
10748   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
10749     {
10750       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
10751       return;
10752     }
10753   
10754   /* Print out the atoms we received */
10755   atoms = (GdkAtom *)selection_data->data;
10756
10757   item_list = NULL;
10758   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
10759     {
10760       char *name;
10761       name = gdk_atom_name (atoms[i]);
10762       if (name != NULL)
10763         g_print ("%s\n",name);
10764       else
10765         g_print ("(bad atom)\n");
10766     }
10767
10768   return;
10769 }
10770
10771 int 
10772 main (int argc, char *argv[])
10773 {
10774   GtkWidget *window;
10775   GtkWidget *button;
10776   
10777   gtk_init (&amp;argc, &amp;argv);
10778
10779   /* Create the toplevel window */
10780
10781   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10782   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
10783   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10784
10785   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10786                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
10787
10788   /* Create a button the user can click to get targets */
10789
10790   button = gtk_button_new_with_label ("Get Targets");
10791   gtk_container_add (GTK_CONTAINER (window), button);
10792
10793   gtk_signal_connect (GTK_OBJECT(button), "clicked",
10794                       GTK_SIGNAL_FUNC (get_targets), NULL);
10795   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
10796                       GTK_SIGNAL_FUNC (selection_received), NULL);
10797
10798   gtk_widget_show (button);
10799   gtk_widget_show (window);
10800   
10801   gtk_main ();
10802   
10803   return 0;
10804 }
10805 /* example-end */
10806 </verb></tscreen>
10807
10808 <!-- ----------------------------------------------------------------- -->
10809 <sect1> Supplying the selection 
10810 <p>
10811 Supplying the selection is a bit more complicated. You must register 
10812 handlers that will be called when your selection is requested. For
10813 each selection/target pair you will handle, you make a call to:
10814
10815 <tscreen><verb>
10816 void gtk_selection_add_handler( GtkWidget            *widget, 
10817                                 GdkAtom               selection,
10818                                 GdkAtom               target,
10819                                 GtkSelectionFunction  function,
10820                                 GtkRemoveFunction     remove_func,
10821                                 gpointer              data );
10822 </verb></tscreen>
10823
10824 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
10825 this handler will manage.  <tt/remove_func/, if not
10826 NULL, will be called when the signal handler is removed. This is
10827 useful, for instance, for interpreted languages which need to
10828 keep track of a reference count for <tt/data/.
10829
10830 The callback function has the signature:
10831
10832 <tscreen><verb>
10833 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
10834                                       GtkSelectionData *selection_data,
10835                                       gpointer          data );
10836
10837 </verb></tscreen>
10838
10839 The GtkSelectionData is the same as above, but this time, we're
10840 responsible for filling in the fields <tt/type/, <tt/format/,
10841 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
10842 important here - the X server uses it to figure out whether the data
10843 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
10844 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
10845 function:
10846
10847 <tscreen><verb>
10848 void gtk_selection_data_set( GtkSelectionData *selection_data,
10849                              GdkAtom           type,
10850                              gint              format,
10851                              guchar           *data,
10852                              gint              length );
10853 </verb></tscreen>
10854
10855 This function takes care of properly making a copy of the data so that
10856 you don't have to worry about keeping it around. (You should not fill
10857 in the fields of the GtkSelectionData structure by hand.)
10858
10859 When prompted by the user, you claim ownership of the selection by
10860 calling:
10861
10862 <tscreen><verb>
10863 gint gtk_selection_owner_set( GtkWidget *widget,
10864                               GdkAtom    selection,
10865                               guint32    time );
10866 </verb></tscreen>
10867
10868 If another application claims ownership of the selection, you will
10869 receive a "selection_clear_event".
10870
10871 As an example of supplying the selection, the following program adds
10872 selection functionality to a toggle button. When the toggle button is
10873 depressed, the program claims the primary selection. The only target
10874 supported (aside from certain targets like "TARGETS" supplied by GTK
10875 itself), is the "STRING" target. When this target is requested, a
10876 string representation of the time is returned.
10877
10878 <tscreen><verb>
10879 /* example-start selection setselection.c */
10880
10881 #include <gtk/gtk.h>
10882 #include <time.h>
10883
10884 /* Callback when the user toggles the selection */
10885 void
10886 selection_toggled (GtkWidget *widget, gint *have_selection)
10887 {
10888   if (GTK_TOGGLE_BUTTON(widget)->active)
10889     {
10890       *have_selection = gtk_selection_owner_set (widget,
10891                                                  GDK_SELECTION_PRIMARY,
10892                                                  GDK_CURRENT_TIME);
10893       /* if claiming the selection failed, we return the button to
10894          the out state */
10895       if (!*have_selection)
10896         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
10897     }
10898   else
10899     {
10900       if (*have_selection)
10901         {
10902           /* Before clearing the selection by setting the owner to NULL,
10903              we check if we are the actual owner */
10904           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
10905             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
10906                                      GDK_CURRENT_TIME);
10907           *have_selection = FALSE;
10908         }
10909     }
10910 }
10911
10912 /* Called when another application claims the selection */
10913 gint
10914 selection_clear (GtkWidget *widget, GdkEventSelection *event,
10915                  gint *have_selection)
10916 {
10917   *have_selection = FALSE;
10918   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
10919
10920   return TRUE;
10921 }
10922
10923 /* Supplies the current time as the selection. */
10924 void
10925 selection_handle (GtkWidget *widget, 
10926                   GtkSelectionData *selection_data,
10927                   gpointer data)
10928 {
10929   gchar *timestr;
10930   time_t current_time;
10931
10932   current_time = time (NULL);
10933   timestr = asctime (localtime(&amp;current_time)); 
10934   /* When we return a single string, it should not be null terminated.
10935      That will be done for us */
10936
10937   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
10938                           8, timestr, strlen(timestr));
10939 }
10940
10941 int
10942 main (int argc, char *argv[])
10943 {
10944   GtkWidget *window;
10945
10946   GtkWidget *selection_button;
10947
10948   static int have_selection = FALSE;
10949   
10950   gtk_init (&amp;argc, &amp;argv);
10951
10952   /* Create the toplevel window */
10953
10954   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10955   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
10956   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10957
10958   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10959                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
10960
10961   /* Create a toggle button to act as the selection */
10962
10963   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
10964   gtk_container_add (GTK_CONTAINER (window), selection_button);
10965   gtk_widget_show (selection_button);
10966
10967   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
10968                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
10969   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
10970                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
10971
10972   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
10973                              GDK_SELECTION_TYPE_STRING,
10974                              selection_handle, NULL);
10975
10976   gtk_widget_show (selection_button);
10977   gtk_widget_show (window);
10978   
10979   gtk_main ();
10980   
10981   return 0;
10982 }
10983 /* example-end */
10984 </verb></tscreen>
10985
10986
10987 <!-- ***************************************************************** -->
10988 <sect>glib<label id="sec_glib">
10989 <!-- ***************************************************************** -->
10990 <p>
10991 glib provides many useful functions and definitions available for use
10992 when creating GDK and GTK applications. I will list them all here with
10993 a brief explanation. Many are duplicates of standard libc functions so
10994 I won't go into detail on those. This is mostly to be used as a reference,
10995 so you know what is available for use.
10996
10997 <!-- ----------------------------------------------------------------- -->
10998 <sect1>Definitions
10999 <p>
11000 Definitions for the extremes of many of the standard types are:
11001
11002 <tscreen><verb>
11003 G_MINFLOAT
11004 G_MAXFLOAT
11005 G_MINDOUBLE
11006 G_MAXDOUBLE
11007 G_MINSHORT
11008 G_MAXSHORT
11009 G_MININT
11010 G_MAXINT
11011 G_MINLONG
11012 G_MAXLONG
11013 </verb></tscreen>
11014
11015 Also, the following typedefs. The ones left unspecified are dynamically set
11016 depending on the architecture. Remember to avoid counting on the size of a
11017 pointer if you want to be portable! E.g., a pointer on an Alpha is 8 bytes, but 4
11018 on Intel.
11019
11020 <tscreen><verb>
11021 char   gchar;
11022 short  gshort;
11023 long   glong;
11024 int    gint;
11025 char   gboolean;
11026
11027 unsigned char   guchar;
11028 unsigned short  gushort;
11029 unsigned long   gulong;
11030 unsigned int    guint;
11031
11032 float   gfloat;
11033 double  gdouble;
11034 long double gldouble;
11035
11036 void* gpointer;
11037
11038 gint8
11039 guint8
11040 gint16
11041 guint16
11042 gint32
11043 guint32
11044 </verb></tscreen>
11045
11046 <!-- ----------------------------------------------------------------- -->
11047 <sect1>Doubly Linked Lists
11048 <p>
11049 The following functions are used to create, manage, and destroy doubly
11050 linked lists.  I assume you know what linked lists are, as it is beyond the scope
11051 of this document to explain them.  Of course, it's not required that you
11052 know these for general use of GTK, but they are nice to know.
11053
11054 <tscreen><verb>
11055 GList *g_list_alloc( void );
11056
11057 void g_list_free( GList *list );
11058
11059 void g_list_free_1( GList *list );
11060
11061 GList *g_list_append( GList     *list,
11062                       gpointer   data );
11063                            
11064 GList *g_list_prepend( GList    *list,
11065                        gpointer  data );
11066                         
11067 GList *g_list_insert( GList    *list,
11068                       gpointer  data,
11069                             gint      position );
11070
11071 GList *g_list_remove( GList    *list,
11072                       gpointer  data );
11073                            
11074 GList *g_list_remove_link( GList *list,
11075                            GList *link );
11076
11077 GList *g_list_reverse( GList *list );
11078
11079 GList *g_list_nth( GList *list,
11080                    gint   n );
11081                            
11082 GList *g_list_find( GList    *list,
11083                     gpointer  data );
11084
11085 GList *g_list_last( GList *list );
11086
11087 GList *g_list_first( GList *list );
11088
11089 gint g_list_length( GList *list );
11090
11091 void g_list_foreach( GList    *list,
11092                      GFunc     func,
11093                      gpointer  user_data );
11094 </verb></tscreen>                                             
11095
11096 <!-- ----------------------------------------------------------------- -->
11097 <sect1>Singly Linked Lists
11098 <p>
11099 Many of the above functions for singly linked lists are identical to the
11100 above. Here is a complete list:
11101 <tscreen><verb>
11102 GSList *g_slist_alloc( void );
11103
11104 void g_slist_free( GSList *list );
11105
11106 void g_slist_free_1( GSList *list );
11107
11108 GSList *g_slist_append( GSList   *list,
11109                         gpointer  data );
11110                 
11111 GSList *g_slist_prepend( GSList   *list,
11112                          gpointer  data );
11113                              
11114 GSList *g_slist_insert( GSList   *list,
11115                         gpointer  data,
11116                             gint      position );
11117                              
11118 GSList *g_slist_remove( GSList   *list,
11119                         gpointer  data );
11120                              
11121 GSList *g_slist_remove_link( GSList *list,
11122                              GSList *link );
11123                              
11124 GSList *g_slist_reverse( GSList *list );
11125
11126 GSList *g_slist_nth( GSList *list,
11127                      gint    n );
11128                              
11129 GSList *g_slist_find( GSList   *list,
11130                       gpointer  data );
11131                              
11132 GSList *g_slist_last( GSList *list );
11133
11134 gint g_slist_length( GSList *list );
11135
11136 void g_slist_foreach( GSList   *list,
11137                       GFunc     func,
11138                             gpointer  user_data );
11139         
11140 </verb></tscreen>
11141
11142 <!-- ----------------------------------------------------------------- -->
11143 <sect1>Memory Management
11144 <p>
11145 <tscreen><verb>
11146 gpointer g_malloc( gulong size );
11147 </verb></tscreen>
11148
11149 This is a replacement for malloc(). You do not need to check the return
11150 value as it is done for you in this function.
11151
11152 <tscreen><verb>
11153 gpointer g_malloc0( gulong size );
11154 </verb></tscreen>
11155
11156 Same as above, but zeroes the memory before returning a pointer to it.
11157
11158 <tscreen><verb>
11159 gpointer g_realloc( gpointer mem,
11160                     gulong   size );
11161 </verb></tscreen>
11162
11163 Relocates "size" bytes of memory starting at "mem".  Obviously, the
11164 memory should have been previously allocated.
11165
11166 <tscreen><verb>
11167 void g_free( gpointer mem );
11168 </verb></tscreen>
11169
11170 Frees memory. Easy one.
11171
11172 <tscreen><verb>
11173 void g_mem_profile( void );
11174 </verb></tscreen>
11175
11176 Dumps a profile of used memory, but requires that you add #define
11177 MEM_PROFILE to the top of glib/gmem.c and re-make and make install.
11178
11179 <tscreen><verb>
11180 void g_mem_check( gpointer mem );
11181 </verb></tscreen>
11182
11183 Checks that a memory location is valid.  Requires you add #define
11184 MEM_CHECK to the top of gmem.c and re-make and make install.
11185
11186 <!-- ----------------------------------------------------------------- -->
11187 <sect1>Timers
11188 <p>
11189 Timer functions..
11190
11191 <tscreen><verb>
11192 GTimer *g_timer_new( void );
11193
11194 void g_timer_destroy( GTimer *timer );
11195
11196 void g_timer_start( GTimer  *timer );
11197
11198 void g_timer_stop( GTimer  *timer );
11199
11200 void g_timer_reset( GTimer  *timer );
11201
11202 gdouble g_timer_elapsed( GTimer *timer,
11203                          gulong *microseconds );
11204 </verb></tscreen>                        
11205
11206 <!-- ----------------------------------------------------------------- -->
11207 <sect1>String Handling
11208 <p>
11209 A whole mess of string handling functions. They all look very interesting, and
11210 probably better for many purposes than the standard C string functions, but
11211 require documentation.
11212
11213 <tscreen><verb>
11214 GString *g_string_new( gchar *init );
11215
11216 void g_string_free( GString *string,
11217                     gint     free_segment );
11218                              
11219 GString *g_string_assign( GString *lval,
11220                           gchar   *rval );
11221                              
11222 GString *g_string_truncate( GString *string,
11223                             gint     len );
11224                              
11225 GString *g_string_append( GString *string,
11226                           gchar   *val );
11227                             
11228 GString *g_string_append_c( GString *string,
11229                             gchar    c );
11230         
11231 GString *g_string_prepend( GString *string,
11232                            gchar   *val );
11233                              
11234 GString *g_string_prepend_c( GString *string,
11235                              gchar    c );
11236         
11237 void g_string_sprintf( GString *string,
11238                        gchar   *fmt,
11239                        ...);
11240         
11241 void g_string_sprintfa ( GString *string,
11242                          gchar   *fmt,
11243                          ... );
11244 </verb></tscreen>                                                         
11245
11246 <!-- ----------------------------------------------------------------- -->
11247 <sect1>Utility and Error Functions
11248 <p>
11249 <tscreen><verb>
11250 gchar *g_strdup( const gchar *str );
11251 </verb></tscreen>
11252
11253 Replacement strdup function.  Copies the original strings contents to
11254 newly allocated memory, and returns a pointer to it.
11255
11256 <tscreen><verb>
11257 gchar *g_strerror( gint errnum );
11258 </verb></tscreen>
11259
11260 I recommend using this for all error messages.  It's much nicer, and more
11261 portable than perror() or others.  The output is usually of the form:
11262
11263 <tscreen><verb>
11264 program name:function that failed:file or further description:strerror
11265 </verb></tscreen>
11266
11267 Here's an example of one such call used in our hello_world program:
11268
11269 <tscreen><verb>
11270 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
11271 </verb></tscreen>
11272
11273 <tscreen><verb>
11274 void g_error( gchar *format, ... );
11275 </verb></tscreen>
11276
11277 Prints an error message. The format is just like printf, but it
11278 prepends "** ERROR **: " to your message, and exits the program.  
11279 Use only for fatal errors.
11280
11281 <tscreen><verb>
11282 void g_warning( gchar *format, ... );
11283 </verb></tscreen>
11284
11285 Same as above, but prepends "** WARNING **: ", and does not exit the
11286 program.
11287
11288 <tscreen><verb>
11289 void g_message( gchar *format, ... );
11290 </verb></tscreen>
11291
11292 Prints "message: " prepended to the string you pass in.
11293
11294 <tscreen><verb>
11295 void g_print( gchar *format, ... );
11296 </verb></tscreen>
11297
11298 Replacement for printf().
11299
11300 And our last function:
11301
11302 <tscreen><verb>
11303 gchar *g_strsignal( gint signum );
11304 </verb></tscreen>
11305
11306 Prints out the name of the Unix system signal given the signal number.
11307 Useful in generic signal handling functions.
11308
11309 All of the above are more or less just stolen from glib.h.  If anyone cares
11310 to document any function, just send me an email!
11311
11312 <!-- ***************************************************************** -->
11313 <sect>GTK's rc Files
11314 <!-- ***************************************************************** -->
11315 <p>
11316 GTK has its own way of dealing with application defaults, by using rc
11317 files. These can be used to set the colors of just about any widget, and
11318 can also be used to tile pixmaps onto the background of some widgets.  
11319
11320 <!-- ----------------------------------------------------------------- -->
11321 <sect1>Functions For rc Files 
11322 <p>
11323 When your application starts, you should include a call to:
11324
11325 <tscreen><verb>
11326 void gtk_rc_parse( char *filename );
11327 </verb></tscreen>
11328
11329 Passing in the filename of your rc file. This will cause GTK to parse
11330 this file, and use the style settings for the widget types defined
11331 there.
11332
11333 If you wish to have a special set of widgets that can take on a
11334 different style from others, or any other logical division of widgets,
11335 use a call to:
11336
11337 <tscreen><verb>
11338 void gtk_widget_set_name( GtkWidget *widget,
11339                           gchar     *name );
11340 </verb></tscreen>
11341
11342 Passing your newly created widget as the first argument, and the name
11343 you wish to give it as the second. This will allow you to change the
11344 attributes of this widget by name through the rc file.
11345
11346 If we use a call something like this:
11347
11348 <tscreen><verb>
11349 button = gtk_button_new_with_label ("Special Button");
11350 gtk_widget_set_name (button, "special button");
11351 </verb></tscreen>
11352
11353 Then this button is given the name "special button" and may be addressed by
11354 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
11355
11356 The example rc file below, sets the properties of the main window, and lets
11357 all children of that main window inherit the style described by the "main
11358 button" style.  The code used in the application is:
11359
11360 <tscreen><verb>
11361 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11362 gtk_widget_set_name (window, "main window");
11363 </verb></tscreen>
11364
11365 And then the style is defined in the rc file using:
11366
11367 <tscreen><verb>
11368 widget "main window.*GtkButton*" style "main_button"
11369 </verb></tscreen>
11370
11371 Which sets all the GtkButton widgets in the "main window" to the
11372 "main_buttons" style as defined in the rc file.
11373
11374 As you can see, this is a fairly powerful and flexible system.  Use your
11375 imagination as to how best to take advantage of this.
11376
11377 <!-- ----------------------------------------------------------------- -->
11378 <sect1>GTK's rc File Format
11379 <p>
11380 The format of the GTK file is illustrated in the example below. This is
11381 the testgtkrc file from the GTK distribution, but I've added a
11382 few comments and things. You may wish to include this explanation
11383 your application to allow the user to fine tune his application.
11384
11385 There are several directives to change the attributes of a widget.
11386
11387 <itemize>
11388 <item>fg - Sets the foreground color of a widget.
11389 <item>bg - Sets the background color of a widget.
11390 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
11391 <item>font - Sets the font to be used with the given widget.
11392 </itemize>
11393
11394 In addition to this, there are several states a widget can be in, and you
11395 can set different colors, pixmaps and fonts for each state. These states are:
11396
11397 <itemize>
11398 <item>NORMAL - The normal state of a widget, without the mouse over top of
11399 it, and not being pressed etc.
11400 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
11401 using this state will be in effect.
11402 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
11403 the attributes assigned by this tag will be in effect.
11404 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
11405 activated, it will take these attributes.
11406 <item>SELECTED - When an object is selected, it takes these attributes.
11407 </itemize>
11408
11409 When using the "fg" and "bg" keywords to set the colors of widgets, the
11410 format is:
11411
11412 <tscreen><verb>
11413 fg[<STATE>] = { Red, Green, Blue }
11414 </verb></tscreen>
11415
11416 Where STATE is one of the above states (PRELIGHT, ACTIVE etc), and the Red,
11417 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
11418 white. They must be in float form, or they will register as 0, so a straight 
11419 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
11420 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
11421
11422 bg_pixmap is very similar to the above, except the colors are replaced by a
11423 filename.
11424
11425 pixmap_path is a list of paths separated by ":"'s.  These paths will be
11426 searched for any pixmap you specify.
11427
11428 The font directive is simply:
11429 <tscreen><verb>
11430 font = "<font name>"
11431 </verb></tscreen>
11432
11433 Where the only hard part is figuring out the font string. Using xfontsel or
11434 similar utility should help.
11435
11436 The "widget_class" sets the style of a class of widgets. These classes are
11437 listed in the widget overview on the class hierarchy.
11438
11439 The "widget" directive sets a specifically named set of widgets to a
11440 given style, overriding any style set for the given widget class.
11441 These widgets are registered inside the application using the
11442 gtk_widget_set_name() call. This allows you to specify the attributes of a
11443 widget on a per widget basis, rather than setting the attributes of an
11444 entire widget class. I urge you to document any of these special widgets so
11445 users may customize them.
11446
11447 When the keyword <tt>parent</> is used as an attribute, the widget will take on
11448 the attributes of its parent in the application.
11449
11450 When defining a style, you may assign the attributes of a previously defined
11451 style to this new one.
11452
11453 <tscreen><verb>
11454 style "main_button" = "button"
11455 {
11456   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11457   bg[PRELIGHT] = { 0.75, 0, 0 }
11458 }
11459 </verb></tscreen>
11460
11461 This example takes the "button" style, and creates a new "main_button" style
11462 simply by changing the font and prelight background color of the "button"
11463 style.
11464
11465 Of course, many of these attributes don't apply to all widgets. It's a
11466 simple matter of common sense really. Anything that could apply, should.
11467
11468 <!-- ----------------------------------------------------------------- -->
11469 <sect1>Example rc file
11470 <p>
11471
11472 <tscreen><verb>
11473 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
11474 #
11475 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
11476 #
11477 # style <name> [= <name>]
11478 # {
11479 #   <option>
11480 # }
11481 #
11482 # widget <widget_set> style <style_name>
11483 # widget_class <widget_class_set> style <style_name>
11484
11485
11486 # Here is a list of all the possible states.  Note that some do not apply to
11487 # certain widgets.
11488 #
11489 # NORMAL - The normal state of a widget, without the mouse over top of
11490 # it, and not being pressed etc.
11491 #
11492 # PRELIGHT - When the mouse is over top of the widget, colors defined
11493 # using this state will be in effect.
11494 #
11495 # ACTIVE - When the widget is pressed or clicked it will be active, and
11496 # the attributes assigned by this tag will be in effect.
11497 #
11498 # INSENSITIVE - When a widget is set insensitive, and cannot be
11499 # activated, it will take these attributes.
11500 #
11501 # SELECTED - When an object is selected, it takes these attributes.
11502 #
11503 # Given these states, we can set the attributes of the widgets in each of
11504 # these states using the following directives.
11505 #
11506 # fg - Sets the foreground color of a widget.
11507 # fg - Sets the background color of a widget.
11508 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
11509 # font - Sets the font to be used with the given widget.
11510 #
11511
11512 # This sets a style called "button".  The name is not really important, as
11513 # it is assigned to the actual widgets at the bottom of the file.
11514
11515 style "window"
11516 {
11517   #This sets the padding around the window to the pixmap specified.
11518   #bg_pixmap[<STATE>] = "<pixmap filename>"
11519   bg_pixmap[NORMAL] = "warning.xpm"
11520 }
11521
11522 style "scale"
11523 {
11524   #Sets the foreground color (font color) to red when in the "NORMAL"
11525   #state.
11526   
11527   fg[NORMAL] = { 1.0, 0, 0 }
11528   
11529   #Sets the background pixmap of this widget to that of its parent.
11530   bg_pixmap[NORMAL] = "<parent>"
11531 }
11532
11533 style "button"
11534 {
11535   # This shows all the possible states for a button.  The only one that
11536   # doesn't apply is the SELECTED state.
11537   
11538   fg[PRELIGHT] = { 0, 1.0, 1.0 }
11539   bg[PRELIGHT] = { 0, 0, 1.0 }
11540   bg[ACTIVE] = { 1.0, 0, 0 }
11541   fg[ACTIVE] = { 0, 1.0, 0 }
11542   bg[NORMAL] = { 1.0, 1.0, 0 }
11543   fg[NORMAL] = { .99, 0, .99 }
11544   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
11545   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
11546 }
11547
11548 # In this example, we inherit the attributes of the "button" style and then
11549 # override the font and background color when prelit to create a new
11550 # "main_button" style.
11551
11552 style "main_button" = "button"
11553 {
11554   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11555   bg[PRELIGHT] = { 0.75, 0, 0 }
11556 }
11557
11558 style "toggle_button" = "button"
11559 {
11560   fg[NORMAL] = { 1.0, 0, 0 }
11561   fg[ACTIVE] = { 1.0, 0, 0 }
11562   
11563   # This sets the background pixmap of the toggle_button to that of its
11564   # parent widget (as defined in the application).
11565   bg_pixmap[NORMAL] = "<parent>"
11566 }
11567
11568 style "text"
11569 {
11570   bg_pixmap[NORMAL] = "marble.xpm"
11571   fg[NORMAL] = { 1.0, 1.0, 1.0 }
11572 }
11573
11574 style "ruler"
11575 {
11576   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
11577 }
11578
11579 # pixmap_path "~/.pixmaps"
11580
11581 # These set the widget types to use the styles defined above.
11582 # The widget types are listed in the class hierarchy, but could probably be
11583 # just listed in this document for the users reference.
11584
11585 widget_class "GtkWindow" style "window"
11586 widget_class "GtkDialog" style "window"
11587 widget_class "GtkFileSelection" style "window"
11588 widget_class "*Gtk*Scale" style "scale"
11589 widget_class "*GtkCheckButton*" style "toggle_button"
11590 widget_class "*GtkRadioButton*" style "toggle_button"
11591 widget_class "*GtkButton*" style "button"
11592 widget_class "*Ruler" style "ruler"
11593 widget_class "*GtkText" style "text"
11594
11595 # This sets all the buttons that are children of the "main window" to
11596 # the main_button style.  These must be documented to be taken advantage of.
11597 widget "main window.*GtkButton*" style "main_button"
11598 </verb></tscreen>
11599
11600 <!-- ***************************************************************** -->
11601 <sect>Writing Your Own Widgets 
11602 <!-- ***************************************************************** -->
11603
11604 <!-- ----------------------------------------------------------------- -->
11605 <sect1> Overview
11606 <p>
11607 Although the GTK distribution comes with many types of widgets that
11608 should cover most basic needs, there may come a time when you need to
11609 create your own new widget type. Since GTK uses widget inheritance
11610 extensively, and there is already a widget that is close to what you want,
11611 it is often possible to make a useful new widget type in
11612 just a few lines of code. But before starting work on a new widget, check
11613 around first to make sure that someone has not already written
11614 it. This will prevent duplication of effort and keep the number of
11615 GTK widgets out there to a minimum, which will help keep both the code
11616 and the interface of different applications consistent. As a flip side
11617 to this, once you finish your widget, announce it to the world so
11618 other people can benefit. The best place to do this is probably the
11619 <tt>gtk-list</tt>.
11620
11621 Complete sources for the example widgets are available at the place you 
11622 got this tutorial, or from:
11623
11624 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
11625 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
11626
11627
11628 <!-- ----------------------------------------------------------------- -->
11629 <sect1> The Anatomy Of A Widget
11630 <p>
11631 In order to create a new widget, it is important to have an
11632 understanding of how GTK objects work. This section is just meant as a
11633 brief overview. See the reference documentation for the details. 
11634
11635 GTK widgets are implemented in an object oriented fashion. However,
11636 they are implemented in standard C. This greatly improves portability
11637 and stability over using current generation C++ compilers; however,
11638 it does mean that the widget writer has to pay attention to some of
11639 the implementation details. The information common to all instances of
11640 one class of widgets (e.g., to all Button widgets) is stored in the 
11641 <em>class structure</em>. There is only one copy of this in
11642 which is stored information about the class's signals
11643 (which act like virtual functions in C). To support inheritance, the
11644 first field in the class structure must be a copy of the parent's
11645 class structure. The declaration of the class structure of GtkButtton
11646 looks like:
11647
11648 <tscreen><verb>
11649 struct _GtkButtonClass
11650 {
11651   GtkContainerClass parent_class;
11652
11653   void (* pressed)  (GtkButton *button);
11654   void (* released) (GtkButton *button);
11655   void (* clicked)  (GtkButton *button);
11656   void (* enter)    (GtkButton *button);
11657   void (* leave)    (GtkButton *button);
11658 };
11659 </verb></tscreen>
11660
11661 When a button is treated as a container (for instance, when it is
11662 resized), its class structure can be cast to GtkContainerClass, and
11663 the relevant fields used to handle the signals.
11664
11665 There is also a structure for each widget that is created on a
11666 per-instance basis. This structure has fields to store information that
11667 is different for each instance of the widget. We'll call this
11668 structure the <em>object structure</em>. For the Button class, it looks
11669 like:
11670
11671 <tscreen><verb>
11672 struct _GtkButton
11673 {
11674   GtkContainer container;
11675
11676   GtkWidget *child;
11677
11678   guint in_button : 1;
11679   guint button_down : 1;
11680 };
11681 </verb></tscreen>
11682
11683 Note that, similar to the class structure, the first field is the
11684 object structure of the parent class, so that this structure can be
11685 cast to the parent class's object structure as needed.
11686
11687 <!-- ----------------------------------------------------------------- -->
11688 <sect1> Creating a Composite widget
11689
11690 <!-- ----------------------------------------------------------------- -->
11691 <sect2> Introduction
11692 <p>
11693 One type of widget that you may be interested in creating is a
11694 widget that is merely an aggregate of other GTK widgets. This type of
11695 widget does nothing that couldn't be done without creating new
11696 widgets, but provides a convenient way of packaging user interface
11697 elements for reuse. The FileSelection and ColorSelection widgets in
11698 the standard distribution are examples of this type of widget.
11699
11700 The example widget that we'll create in this section is the Tictactoe
11701 widget, a 3x3 array of toggle buttons which triggers a signal when all
11702 three buttons in a row, column, or on one of the diagonals are
11703 depressed. 
11704
11705 <!-- ----------------------------------------------------------------- -->
11706 <sect2> Choosing a parent class
11707 <p>
11708 The parent class for a composite widget is typically the container
11709 class that holds all of the elements of the composite widget. For
11710 example, the parent class of the FileSelection widget is the
11711 Dialog class. Since our buttons will be arranged in a table, it
11712 might seem natural to make our parent class the GtkTable
11713 class. Unfortunately, this turns out not to work. The creation of a
11714 widget is divided among two functions - a <tt/WIDGETNAME_new()/
11715 function that the user calls, and a <tt/WIDGETNAME_init()/ function
11716 which does the basic work of initializing the widget which is
11717 independent of the arguments passed to the <tt/_new()/
11718 function. Descendent widgets only call the <tt/_init/ function of
11719 their parent widget. But this division of labor doesn't work well for
11720 tables, which when created, need to know the number of rows and
11721 columns in the table. Unless we want to duplicate most of the
11722 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
11723 best avoid deriving it from GtkTable. For that reason, we derive it
11724 from GtkVBox instead, and stick our table inside the VBox.
11725
11726 <!-- ----------------------------------------------------------------- -->
11727 <sect2> The header file
11728 <p>
11729 Each widget class has a header file which declares the object and
11730 class structures for that widget, along with public functions. 
11731 A couple of features are worth pointing out. To prevent duplicate
11732 definitions, we wrap the entire header file in:
11733
11734 <tscreen><verb>
11735 #ifndef __TICTACTOE_H__
11736 #define __TICTACTOE_H__
11737 .
11738 .
11739 .
11740 #endif /* __TICTACTOE_H__ */
11741 </verb></tscreen>
11742
11743 And to keep C++ programs that include the header file happy, in:
11744
11745 <tscreen><verb>
11746 #ifdef __cplusplus
11747 extern "C" {
11748 #endif /* __cplusplus */
11749 .
11750 .
11751 .
11752 #ifdef __cplusplus
11753 }
11754 #endif /* __cplusplus */
11755 </verb></tscreen>
11756
11757 Along with the functions and structures, we declare three standard
11758 macros in our header file, <tt/TICTACTOE(obj)/,
11759 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
11760 pointer into a pointer to the object or class structure, and check
11761 if an object is a Tictactoe widget respectively.
11762
11763 Here is the complete header file:
11764
11765 <tscreen><verb>
11766 /* tictactoe.h */
11767
11768 #ifndef __TICTACTOE_H__
11769 #define __TICTACTOE_H__
11770
11771 #include <gdk/gdk.h>
11772 #include <gtk/gtkvbox.h>
11773
11774 #ifdef __cplusplus
11775 extern "C" {
11776 #endif /* __cplusplus */
11777
11778 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
11779 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
11780 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
11781
11782
11783 typedef struct _Tictactoe       Tictactoe;
11784 typedef struct _TictactoeClass  TictactoeClass;
11785
11786 struct _Tictactoe
11787 {
11788   GtkVBox vbox;
11789   
11790   GtkWidget *buttons[3][3];
11791 };
11792
11793 struct _TictactoeClass
11794 {
11795   GtkVBoxClass parent_class;
11796
11797   void (* tictactoe) (Tictactoe *ttt);
11798 };
11799
11800 guint          tictactoe_get_type        (void);
11801 GtkWidget*     tictactoe_new             (void);
11802 void           tictactoe_clear           (Tictactoe *ttt);
11803
11804 #ifdef __cplusplus
11805 }
11806 #endif /* __cplusplus */
11807
11808 #endif /* __TICTACTOE_H__ */
11809
11810 </verb></tscreen>
11811
11812 <!-- ----------------------------------------------------------------- -->
11813 <sect2> The <tt/_get_type()/ function.
11814 <p>
11815 We now continue on to the implementation of our widget. A core
11816 function for every widget is the function
11817 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
11818 GTK about the widget class, and gets an ID that uniquely identifies
11819 the widget class. Upon subsequent calls, it just returns the ID.
11820
11821 <tscreen><verb>
11822 guint
11823 tictactoe_get_type ()
11824 {
11825   static guint ttt_type = 0;
11826
11827   if (!ttt_type)
11828     {
11829       GtkTypeInfo ttt_info =
11830       {
11831         "Tictactoe",
11832         sizeof (Tictactoe),
11833         sizeof (TictactoeClass),
11834         (GtkClassInitFunc) tictactoe_class_init,
11835         (GtkObjectInitFunc) tictactoe_init,
11836         (GtkArgSetFunc) NULL,
11837         (GtkArgGetFunc) NULL
11838       };
11839
11840       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
11841     }
11842
11843   return ttt_type;
11844 }
11845 </verb></tscreen>
11846
11847 The GtkTypeInfo structure has the following definition:
11848
11849 <tscreen><verb>
11850 struct _GtkTypeInfo
11851 {
11852   gchar *type_name;
11853   guint object_size;
11854   guint class_size;
11855   GtkClassInitFunc class_init_func;
11856   GtkObjectInitFunc object_init_func;
11857   GtkArgSetFunc arg_set_func;
11858   GtkArgGetFunc arg_get_func;
11859 };
11860 </verb></tscreen>
11861
11862 The fields of this structure are pretty self-explanatory. We'll ignore
11863 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
11864 but as yet largely
11865 unimplemented, role in allowing widget options to be conveniently set
11866 from interpreted languages. Once GTK has a correctly filled in copy of
11867 this structure, it knows how to create objects of a particular widget
11868 type. 
11869
11870 <!-- ----------------------------------------------------------------- -->
11871 <sect2> The <tt/_class_init()/ function
11872 <p>
11873 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
11874 the widget's class structure, and sets up any signals for the
11875 class. For our Tictactoe widget it looks like:
11876
11877 <tscreen><verb>
11878
11879 enum {
11880   TICTACTOE_SIGNAL,
11881   LAST_SIGNAL
11882 };
11883
11884 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
11885
11886 static void
11887 tictactoe_class_init (TictactoeClass *class)
11888 {
11889   GtkObjectClass *object_class;
11890
11891   object_class = (GtkObjectClass*) class;
11892   
11893   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
11894                                          GTK_RUN_FIRST,
11895                                          object_class->type,
11896                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
11897                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
11898
11899
11900   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
11901
11902   class->tictactoe = NULL;
11903 }
11904 </verb></tscreen>
11905
11906 Our widget has just one signal, the <tt/tictactoe/ signal that is
11907 invoked when a row, column, or diagonal is completely filled in. Not
11908 every composite widget needs signals, so if you are reading this for
11909 the first time, you may want to skip to the next section now, as
11910 things are going to get a bit complicated.
11911
11912 The function:
11913
11914 <tscreen><verb>
11915 gint gtk_signal_new( const gchar         *name,
11916                      GtkSignalRunType     run_type,
11917                      GtkType              object_type,
11918                      gint                 function_offset,
11919                      GtkSignalMarshaller  marshaller,
11920                      GtkType              return_val,
11921                      guint                nparams,
11922                      ...);
11923 </verb></tscreen>
11924
11925 Creates a new signal. The parameters are:
11926
11927 <itemize>
11928 <item> <tt/name/: The name of the signal.
11929 <item> <tt/run_type/: Whether the default handler runs before or after
11930 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
11931 although there are other possibilities.
11932 <item> <tt/object_type/: The ID of the object that this signal applies
11933 to. (It will also apply to that objects descendents)
11934 <item> <tt/function_offset/: The offset within the class structure of
11935 a pointer to the default handler.
11936 <item> <tt/marshaller/: A function that is used to invoke the signal
11937 handler. For signal handlers that have no arguments other than the
11938 object that emitted the signal and user data, we can use the
11939 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
11940 <item> <tt/return_val/: The type of the return val.
11941 <item> <tt/nparams/: The number of parameters of the signal handler
11942 (other than the two default ones mentioned above)
11943 <item> <tt/.../: The types of the parameters.
11944 </itemize>
11945
11946 When specifying types, the <tt/GtkType/ enumeration is used:
11947
11948 <tscreen><verb>
11949 typedef enum
11950 {
11951   GTK_TYPE_INVALID,
11952   GTK_TYPE_NONE,
11953   GTK_TYPE_CHAR,
11954   GTK_TYPE_BOOL,
11955   GTK_TYPE_INT,
11956   GTK_TYPE_UINT,
11957   GTK_TYPE_LONG,
11958   GTK_TYPE_ULONG,
11959   GTK_TYPE_FLOAT,
11960   GTK_TYPE_DOUBLE,
11961   GTK_TYPE_STRING,
11962   GTK_TYPE_ENUM,
11963   GTK_TYPE_FLAGS,
11964   GTK_TYPE_BOXED,
11965   GTK_TYPE_FOREIGN,
11966   GTK_TYPE_CALLBACK,
11967   GTK_TYPE_ARGS,
11968
11969   GTK_TYPE_POINTER,
11970
11971   /* it'd be great if the next two could be removed eventually */
11972   GTK_TYPE_SIGNAL,
11973   GTK_TYPE_C_CALLBACK,
11974
11975   GTK_TYPE_OBJECT
11976
11977 } GtkFundamentalType;
11978 </verb></tscreen>
11979
11980 <tt/gtk_signal_new()/ returns a unique integer identifier for the
11981 signal, that we store in the <tt/tictactoe_signals/ array, which we
11982 index using an enumeration. (Conventionally, the enumeration elements
11983 are the signal name, uppercased, but here there would be a conflict
11984 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
11985 instead.
11986
11987 After creating our signals, we need to tell GTK to associate our
11988 signals with the Tictactoe class. We do that by calling
11989 <tt/gtk_object_class_add_signals()/. We then set the pointer which
11990 points to the default handler for the `tictactoe' signal to NULL,
11991 indicating that there is no default action.
11992
11993 <!-- ----------------------------------------------------------------- -->
11994 <sect2> The <tt/_init()/ function.
11995 <p>
11996 Each widget class also needs a function to initialize the object
11997 structure. Usually, this function has the fairly limited role of
11998 setting the fields of the structure to default values. For composite
11999 widgets, however, this function also creates the component widgets.
12000
12001 <tscreen><verb>
12002 static void
12003 tictactoe_init (Tictactoe *ttt)
12004 {
12005   GtkWidget *table;
12006   gint i,j;
12007   
12008   table = gtk_table_new (3, 3, TRUE);
12009   gtk_container_add (GTK_CONTAINER(ttt), table);
12010   gtk_widget_show (table);
12011
12012   for (i=0;i<3; i++)
12013     for (j=0;j<3; j++)
12014       {
12015         ttt->buttons[i][j] = gtk_toggle_button_new ();
12016         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
12017                                    i, i+1, j, j+1);
12018         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
12019                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
12020         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
12021         gtk_widget_show (ttt->buttons[i][j]);
12022       }
12023 }
12024 </verb></tscreen>
12025
12026 <!-- ----------------------------------------------------------------- -->
12027 <sect2> And the rest...
12028 <p>
12029 There is one more function that every widget (except for base widget
12030 types like GtkBin that cannot be instantiated) needs to have - the
12031 function that the user calls to create an object of that type. This is
12032 conventionally called <tt/WIDGETNAME_new()/. In some
12033 widgets, though not for the Tictactoe widgets, this function takes
12034 arguments, and does some setup based on the arguments. The other two
12035 functions are specific to the Tictactoe widget. 
12036
12037 <tt/tictactoe_clear()/ is a public function that resets all the
12038 buttons in the widget to the up position. Note the use of
12039 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
12040 button toggles from being triggered unnecessarily.
12041
12042 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
12043 user clicks on a button. It checks to see if there are any winning
12044 combinations that involve the toggled button, and if so, emits
12045 the "tictactoe" signal.
12046
12047 <tscreen><verb>  
12048 GtkWidget*
12049 tictactoe_new ()
12050 {
12051   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
12052 }
12053
12054 void           
12055 tictactoe_clear (Tictactoe *ttt)
12056 {
12057   int i,j;
12058
12059   for (i=0;i<3;i++)
12060     for (j=0;j<3;j++)
12061       {
12062         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12063         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
12064                                      FALSE);
12065         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12066       }
12067 }
12068
12069 static void
12070 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
12071 {
12072   int i,k;
12073
12074   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12075                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12076                              { 0, 1, 2 }, { 0, 1, 2 } };
12077   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12078                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12079                              { 0, 1, 2 }, { 2, 1, 0 } };
12080
12081   int success, found;
12082
12083   for (k=0; k<8; k++)
12084     {
12085       success = TRUE;
12086       found = FALSE;
12087
12088       for (i=0;i<3;i++)
12089         {
12090           success = success &amp;&amp; 
12091             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
12092           found = found ||
12093             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
12094         }
12095       
12096       if (success &amp;&amp; found)
12097         {
12098           gtk_signal_emit (GTK_OBJECT (ttt), 
12099                            tictactoe_signals[TICTACTOE_SIGNAL]);
12100           break;
12101         }
12102     }
12103 }
12104 </verb></tscreen>
12105
12106 And finally, an example program using our Tictactoe widget:
12107
12108 <tscreen><verb>
12109 #include <gtk/gtk.h>
12110 #include "tictactoe.h"
12111
12112 /* Invoked when a row, column or diagonal is completed */
12113 void
12114 win (GtkWidget *widget, gpointer data)
12115 {
12116   g_print ("Yay!\n");
12117   tictactoe_clear (TICTACTOE (widget));
12118 }
12119
12120 int 
12121 main (int argc, char *argv[])
12122 {
12123   GtkWidget *window;
12124   GtkWidget *ttt;
12125   
12126   gtk_init (&amp;argc, &amp;argv);
12127
12128   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12129   
12130   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
12131   
12132   gtk_signal_connect (GTK_OBJECT (window), "destroy",
12133                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
12134   
12135   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12136
12137   /* Create a new Tictactoe widget */
12138   ttt = tictactoe_new ();
12139   gtk_container_add (GTK_CONTAINER (window), ttt);
12140   gtk_widget_show (ttt);
12141
12142   /* And attach to its "tictactoe" signal */
12143   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
12144                       GTK_SIGNAL_FUNC (win), NULL);
12145
12146   gtk_widget_show (window);
12147   
12148   gtk_main ();
12149   
12150   return 0;
12151 }
12152
12153 </verb></tscreen>
12154
12155 <!-- ----------------------------------------------------------------- -->
12156 <sect1> Creating a widget from scratch.
12157
12158 <!-- ----------------------------------------------------------------- -->
12159 <sect2> Introduction
12160 <p>
12161 In this section, we'll learn more about how widgets display themselves
12162 on the screen and interact with events. As an example of this, we'll
12163 create an analog dial widget with a pointer that the user can drag to
12164 set the value.
12165
12166 <!-- ----------------------------------------------------------------- -->
12167 <sect2> Displaying a widget on the screen
12168 <p>
12169 There are several steps that are involved in displaying on the screen.
12170 After the widget is created with a call to <tt/WIDGETNAME_new()/,
12171 several more functions are needed:
12172
12173 <itemize>
12174 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
12175 window for the widget if it has one.
12176 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
12177 <tt/gtk_widget_show()/. It is responsible for making sure the widget
12178 is actually drawn on the screen (<em/mapped/). For a container class,
12179 it must also make calls to <tt/map()/> functions of any child widgets.
12180 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
12181 is called for the widget or one of its ancestors. It makes the actual
12182 calls to the drawing functions to draw the widget on the screen. For
12183 container widgets, this function must make calls to
12184 <tt/gtk_widget_draw()/ for its child widgets.
12185 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
12186 widget. It makes the necessary calls to the drawing functions to draw
12187 the exposed portion on the screen. For container widgets, this
12188 function must generate expose events for its child widgets which don't
12189 have their own windows. (If they have their own windows, then X will
12190 generate the necessary expose events)
12191 </itemize>
12192
12193 You might notice that the last two functions are quite similar - each
12194 is responsible for drawing the widget on the screen. In fact many
12195 types of widgets don't really care about the difference between the
12196 two. The default <tt/draw()/ function in the widget class simply
12197 generates a synthetic expose event for the redrawn area. However, some
12198 types of widgets can save work by distinguishing between the two
12199 functions. For instance, if a widget has multiple X windows, then
12200 since expose events identify the exposed window, it can redraw only
12201 the affected window, which is not possible for calls to <tt/draw()/.
12202
12203 Container widgets, even if they don't care about the difference for
12204 themselves, can't simply use the default <tt/draw()/ function because
12205 their child widgets might care about the difference. However,
12206 it would be wasteful to duplicate the drawing code between the two
12207 functions. The convention is that such widgets have a function called
12208 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
12209 widget, that is then called by the <tt/draw()/ and <tt/expose()/
12210 functions.
12211
12212 In our example approach, since the dial widget is not a container
12213 widget, and only has a single window, we can take the simplest
12214 approach and use the default <tt/draw()/ function and only implement
12215 an <tt/expose()/ function.
12216
12217 <!-- ----------------------------------------------------------------- -->
12218 <sect2> The origins of the Dial Widget
12219 <p>
12220 Just as all land animals are just variants on the first amphibian that
12221 crawled up out of the mud, Gtk widgets tend to start off as variants
12222 of some other, previously written widget.  Thus, although this section
12223 is entitled `Creating a Widget from Scratch', the Dial widget really
12224 began with the source code for the Range widget. This was picked as a
12225 starting point because it would be nice if our Dial had the same
12226 interface as the Scale widgets which are just specialized descendents
12227 of the Range widget. So, though the source code is presented below in
12228 finished form, it should not be implied that it was written, <em>deus
12229 ex machina</em> in this fashion. Also, if you aren't yet familiar with
12230 how scale widgets work from the application writer's point of view, it
12231 would be a good idea to look them over before continuing.
12232
12233 <!-- ----------------------------------------------------------------- -->
12234 <sect2> The Basics
12235 <p>
12236 Quite a bit of our widget should look pretty familiar from the
12237 Tictactoe widget. First, we have a header file:
12238
12239 <tscreen><verb>
12240 /* GTK - The GIMP Toolkit
12241  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
12242  *
12243  * This library is free software; you can redistribute it and/or
12244  * modify it under the terms of the GNU Library General Public
12245  * License as published by the Free Software Foundation; either
12246  * version 2 of the License, or (at your option) any later version.
12247  *
12248  * This library is distributed in the hope that it will be useful,
12249  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12250  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12251  * Library General Public License for more details.
12252  *
12253  * You should have received a copy of the GNU Library General Public
12254  * License along with this library; if not, write to the Free
12255  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12256  */
12257
12258 #ifndef __GTK_DIAL_H__
12259 #define __GTK_DIAL_H__
12260
12261 #include <gdk/gdk.h>
12262 #include <gtk/gtkadjustment.h>
12263 #include <gtk/gtkwidget.h>
12264
12265
12266 #ifdef __cplusplus
12267 extern "C" {
12268 #endif /* __cplusplus */
12269
12270
12271 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
12272 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
12273 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
12274
12275
12276 typedef struct _GtkDial        GtkDial;
12277 typedef struct _GtkDialClass   GtkDialClass;
12278
12279 struct _GtkDial
12280 {
12281   GtkWidget widget;
12282
12283   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
12284   guint policy : 2;
12285
12286   /* Button currently pressed or 0 if none */
12287   guint8 button;
12288
12289   /* Dimensions of dial components */
12290   gint radius;
12291   gint pointer_width;
12292
12293   /* ID of update timer, or 0 if none */
12294   guint32 timer;
12295
12296   /* Current angle */
12297   gfloat angle;
12298
12299   /* Old values from adjustment stored so we know when something changes */
12300   gfloat old_value;
12301   gfloat old_lower;
12302   gfloat old_upper;
12303
12304   /* The adjustment object that stores the data for this dial */
12305   GtkAdjustment *adjustment;
12306 };
12307
12308 struct _GtkDialClass
12309 {
12310   GtkWidgetClass parent_class;
12311 };
12312
12313
12314 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
12315 guint          gtk_dial_get_type               (void);
12316 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
12317 void           gtk_dial_set_update_policy      (GtkDial      *dial,
12318                                                 GtkUpdateType  policy);
12319
12320 void           gtk_dial_set_adjustment         (GtkDial      *dial,
12321                                                 GtkAdjustment *adjustment);
12322 #ifdef __cplusplus
12323 }
12324 #endif /* __cplusplus */
12325
12326
12327 #endif /* __GTK_DIAL_H__ */
12328 </verb></tscreen>
12329
12330 Since there is quite a bit more going on in this widget, than the last
12331 one, we have more fields in the data structure, but otherwise things
12332 are pretty similar.
12333
12334 Next, after including header files, and declaring a few constants,
12335 we have some functions to provide information about the widget
12336 and initialize it:
12337
12338 <tscreen><verb>
12339 #include <math.h>
12340 #include <stdio.h>
12341 #include <gtk/gtkmain.h>
12342 #include <gtk/gtksignal.h>
12343
12344 #include "gtkdial.h"
12345
12346 #define SCROLL_DELAY_LENGTH  300
12347 #define DIAL_DEFAULT_SIZE 100
12348
12349 /* Forward declarations */
12350
12351 [ omitted to save space ]
12352
12353 /* Local data */
12354
12355 static GtkWidgetClass *parent_class = NULL;
12356
12357 guint
12358 gtk_dial_get_type ()
12359 {
12360   static guint dial_type = 0;
12361
12362   if (!dial_type)
12363     {
12364       GtkTypeInfo dial_info =
12365       {
12366         "GtkDial",
12367         sizeof (GtkDial),
12368         sizeof (GtkDialClass),
12369         (GtkClassInitFunc) gtk_dial_class_init,
12370         (GtkObjectInitFunc) gtk_dial_init,
12371         (GtkArgSetFunc) NULL,
12372         (GtkArgGetFunc) NULL,
12373       };
12374
12375       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
12376     }
12377
12378   return dial_type;
12379 }
12380
12381 static void
12382 gtk_dial_class_init (GtkDialClass *class)
12383 {
12384   GtkObjectClass *object_class;
12385   GtkWidgetClass *widget_class;
12386
12387   object_class = (GtkObjectClass*) class;
12388   widget_class = (GtkWidgetClass*) class;
12389
12390   parent_class = gtk_type_class (gtk_widget_get_type ());
12391
12392   object_class->destroy = gtk_dial_destroy;
12393
12394   widget_class->realize = gtk_dial_realize;
12395   widget_class->expose_event = gtk_dial_expose;
12396   widget_class->size_request = gtk_dial_size_request;
12397   widget_class->size_allocate = gtk_dial_size_allocate;
12398   widget_class->button_press_event = gtk_dial_button_press;
12399   widget_class->button_release_event = gtk_dial_button_release;
12400   widget_class->motion_notify_event = gtk_dial_motion_notify;
12401 }
12402
12403 static void
12404 gtk_dial_init (GtkDial *dial)
12405 {
12406   dial->button = 0;
12407   dial->policy = GTK_UPDATE_CONTINUOUS;
12408   dial->timer = 0;
12409   dial->radius = 0;
12410   dial->pointer_width = 0;
12411   dial->angle = 0.0;
12412   dial->old_value = 0.0;
12413   dial->old_lower = 0.0;
12414   dial->old_upper = 0.0;
12415   dial->adjustment = NULL;
12416 }
12417
12418 GtkWidget*
12419 gtk_dial_new (GtkAdjustment *adjustment)
12420 {
12421   GtkDial *dial;
12422
12423   dial = gtk_type_new (gtk_dial_get_type ());
12424
12425   if (!adjustment)
12426     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
12427
12428   gtk_dial_set_adjustment (dial, adjustment);
12429
12430   return GTK_WIDGET (dial);
12431 }
12432
12433 static void
12434 gtk_dial_destroy (GtkObject *object)
12435 {
12436   GtkDial *dial;
12437
12438   g_return_if_fail (object != NULL);
12439   g_return_if_fail (GTK_IS_DIAL (object));
12440
12441   dial = GTK_DIAL (object);
12442
12443   if (dial->adjustment)
12444     gtk_object_unref (GTK_OBJECT (dial->adjustment));
12445
12446   if (GTK_OBJECT_CLASS (parent_class)->destroy)
12447     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
12448 }
12449 </verb></tscreen>
12450
12451 Note that this <tt/init()/ function does less than for the Tictactoe
12452 widget, since this is not a composite widget, and the <tt/new()/
12453 function does more, since it now has an argument. Also, note that when
12454 we store a pointer to the Adjustment object, we increment its
12455 reference count, (and correspondingly decrement when we no longer use
12456 it) so that GTK can keep track of when it can be safely destroyed.
12457
12458 <p>
12459 Also, there are a few function to manipulate the widget's options:
12460
12461 <tscreen><verb>
12462 GtkAdjustment*
12463 gtk_dial_get_adjustment (GtkDial *dial)
12464 {
12465   g_return_val_if_fail (dial != NULL, NULL);
12466   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
12467
12468   return dial->adjustment;
12469 }
12470
12471 void
12472 gtk_dial_set_update_policy (GtkDial      *dial,
12473                              GtkUpdateType  policy)
12474 {
12475   g_return_if_fail (dial != NULL);
12476   g_return_if_fail (GTK_IS_DIAL (dial));
12477
12478   dial->policy = policy;
12479 }
12480
12481 void
12482 gtk_dial_set_adjustment (GtkDial      *dial,
12483                           GtkAdjustment *adjustment)
12484 {
12485   g_return_if_fail (dial != NULL);
12486   g_return_if_fail (GTK_IS_DIAL (dial));
12487
12488   if (dial->adjustment)
12489     {
12490       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
12491       gtk_object_unref (GTK_OBJECT (dial->adjustment));
12492     }
12493
12494   dial->adjustment = adjustment;
12495   gtk_object_ref (GTK_OBJECT (dial->adjustment));
12496
12497   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
12498                       (GtkSignalFunc) gtk_dial_adjustment_changed,
12499                       (gpointer) dial);
12500   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
12501                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
12502                       (gpointer) dial);
12503
12504   dial->old_value = adjustment->value;
12505   dial->old_lower = adjustment->lower;
12506   dial->old_upper = adjustment->upper;
12507
12508   gtk_dial_update (dial);
12509 }
12510 </verb></tscreen>
12511
12512 <sect2> <tt/gtk_dial_realize()/
12513
12514 <p>
12515 Now we come to some new types of functions. First, we have a function
12516 that does the work of creating the X window. Notice that a mask is
12517 passed to the function <tt/gdk_window_new()/ which specifies which fields of
12518 the GdkWindowAttr structure actually have data in them (the remaining
12519 fields will be given default values). Also worth noting is the way the
12520 event mask of the widget is created. We call
12521 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
12522 has specified for this widget (with <tt/gtk_widget_set_events()/, and
12523 add the events that we are interested in ourselves.
12524
12525 <p>
12526 After creating the window, we set its style and background, and put a
12527 pointer to the widget in the user data field of the GdkWindow. This
12528 last step allows GTK to dispatch events for this window to the correct
12529 widget.
12530
12531 <tscreen><verb>
12532 static void
12533 gtk_dial_realize (GtkWidget *widget)
12534 {
12535   GtkDial *dial;
12536   GdkWindowAttr attributes;
12537   gint attributes_mask;
12538
12539   g_return_if_fail (widget != NULL);
12540   g_return_if_fail (GTK_IS_DIAL (widget));
12541
12542   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
12543   dial = GTK_DIAL (widget);
12544
12545   attributes.x = widget->allocation.x;
12546   attributes.y = widget->allocation.y;
12547   attributes.width = widget->allocation.width;
12548   attributes.height = widget->allocation.height;
12549   attributes.wclass = GDK_INPUT_OUTPUT;
12550   attributes.window_type = GDK_WINDOW_CHILD;
12551   attributes.event_mask = gtk_widget_get_events (widget) | 
12552     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
12553     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
12554     GDK_POINTER_MOTION_HINT_MASK;
12555   attributes.visual = gtk_widget_get_visual (widget);
12556   attributes.colormap = gtk_widget_get_colormap (widget);
12557
12558   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
12559   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
12560
12561   widget->style = gtk_style_attach (widget->style, widget->window);
12562
12563   gdk_window_set_user_data (widget->window, widget);
12564
12565   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
12566 }
12567 </verb></tscreen>
12568
12569 <sect2> Size negotiation
12570
12571 <p>
12572 Before the first time that the window containing a widget is
12573 displayed, and whenever the layout of the window changes, GTK asks
12574 each child widget for its desired size. This request is handled by the
12575 function, <tt/gtk_dial_size_request()/. Since our widget isn't a
12576 container widget, and has no real constraints on its size, we just
12577 return a reasonable default value.
12578
12579 <tscreen><verb>
12580 static void 
12581 gtk_dial_size_request (GtkWidget      *widget,
12582                        GtkRequisition *requisition)
12583 {
12584   requisition->width = DIAL_DEFAULT_SIZE;
12585   requisition->height = DIAL_DEFAULT_SIZE;
12586 }
12587 </verb></tscreen>
12588
12589 <p>
12590 After all the widgets have requested an ideal size, the layout of the
12591 window is computed and each child widget is notified of its actual
12592 size. Usually, this will at least as large as the requested size, but
12593 if for instance, the user has resized the window, it may occasionally
12594 be smaller than the requested size. The size notification is handled
12595 by the function <tt/gtk_dial_size_allocate()/. Notice that as well as
12596 computing the sizes of some component pieces for future use, this
12597 routine also does the grunt work of moving the widgets X window into
12598 the new position and size.
12599
12600 <tscreen><verb>
12601 static void
12602 gtk_dial_size_allocate (GtkWidget     *widget,
12603                         GtkAllocation *allocation)
12604 {
12605   GtkDial *dial;
12606
12607   g_return_if_fail (widget != NULL);
12608   g_return_if_fail (GTK_IS_DIAL (widget));
12609   g_return_if_fail (allocation != NULL);
12610
12611   widget->allocation = *allocation;
12612   if (GTK_WIDGET_REALIZED (widget))
12613     {
12614       dial = GTK_DIAL (widget);
12615
12616       gdk_window_move_resize (widget->window,
12617                               allocation->x, allocation->y,
12618                               allocation->width, allocation->height);
12619
12620       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
12621       dial->pointer_width = dial->radius / 5;
12622     }
12623 }
12624 </verb></tscreen>.
12625
12626 <!-- ----------------------------------------------------------------- -->
12627 <sect2> <tt/gtk_dial_expose()/
12628
12629 <p>
12630 As mentioned above, all the drawing of this widget is done in the
12631 handler for expose events. There's not much to remark on here except
12632 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
12633 three dimensional shading according to the colors stored in the
12634 widget's style.
12635
12636 <tscreen><verb>
12637 static gint
12638 gtk_dial_expose (GtkWidget      *widget,
12639                  GdkEventExpose *event)
12640 {
12641   GtkDial *dial;
12642   GdkPoint points[3];
12643   gdouble s,c;
12644   gdouble theta;
12645   gint xc, yc;
12646   gint tick_length;
12647   gint i;
12648
12649   g_return_val_if_fail (widget != NULL, FALSE);
12650   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12651   g_return_val_if_fail (event != NULL, FALSE);
12652
12653   if (event->count > 0)
12654     return FALSE;
12655   
12656   dial = GTK_DIAL (widget);
12657
12658   gdk_window_clear_area (widget->window,
12659                          0, 0,
12660                          widget->allocation.width,
12661                          widget->allocation.height);
12662
12663   xc = widget->allocation.width/2;
12664   yc = widget->allocation.height/2;
12665
12666   /* Draw ticks */
12667
12668   for (i=0; i<25; i++)
12669     {
12670       theta = (i*M_PI/18. - M_PI/6.);
12671       s = sin(theta);
12672       c = cos(theta);
12673
12674       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
12675       
12676       gdk_draw_line (widget->window,
12677                      widget->style->fg_gc[widget->state],
12678                      xc + c*(dial->radius - tick_length),
12679                      yc - s*(dial->radius - tick_length),
12680                      xc + c*dial->radius,
12681                      yc - s*dial->radius);
12682     }
12683
12684   /* Draw pointer */
12685
12686   s = sin(dial->angle);
12687   c = cos(dial->angle);
12688
12689
12690   points[0].x = xc + s*dial->pointer_width/2;
12691   points[0].y = yc + c*dial->pointer_width/2;
12692   points[1].x = xc + c*dial->radius;
12693   points[1].y = yc - s*dial->radius;
12694   points[2].x = xc - s*dial->pointer_width/2;
12695   points[2].y = yc - c*dial->pointer_width/2;
12696
12697   gtk_draw_polygon (widget->style,
12698                     widget->window,
12699                     GTK_STATE_NORMAL,
12700                     GTK_SHADOW_OUT,
12701                     points, 3,
12702                     TRUE);
12703   
12704   return FALSE;
12705 }
12706 </verb></tscreen>
12707
12708 <!-- ----------------------------------------------------------------- -->
12709 <sect2> Event handling
12710
12711 <p>
12712
12713 The rest of the widget's code handles various types of events, and
12714 isn't too different from what would be found in many GTK
12715 applications. Two types of events can occur - either the user can
12716 click on the widget with the mouse and drag to move the pointer, or
12717 the value of the Adjustment object can change due to some external
12718 circumstance. 
12719
12720 <p>
12721 When the user clicks on the widget, we check to see if the click was
12722 appropriately near the pointer, and if so, store then button that the
12723 user clicked with in the <tt/button/ field of the widget
12724 structure, and grab all mouse events with a call to
12725 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
12726 value of the control to be recomputed (by the function
12727 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
12728 set, "value_changed" events are either generated instantly
12729 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
12730 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
12731 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
12732
12733 <tscreen><verb>
12734 static gint
12735 gtk_dial_button_press (GtkWidget      *widget,
12736                        GdkEventButton *event)
12737 {
12738   GtkDial *dial;
12739   gint dx, dy;
12740   double s, c;
12741   double d_parallel;
12742   double d_perpendicular;
12743
12744   g_return_val_if_fail (widget != NULL, FALSE);
12745   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12746   g_return_val_if_fail (event != NULL, FALSE);
12747
12748   dial = GTK_DIAL (widget);
12749
12750   /* Determine if button press was within pointer region - we 
12751      do this by computing the parallel and perpendicular distance of
12752      the point where the mouse was pressed from the line passing through
12753      the pointer */
12754   
12755   dx = event->x - widget->allocation.width / 2;
12756   dy = widget->allocation.height / 2 - event->y;
12757   
12758   s = sin(dial->angle);
12759   c = cos(dial->angle);
12760   
12761   d_parallel = s*dy + c*dx;
12762   d_perpendicular = fabs(s*dx - c*dy);
12763   
12764   if (!dial->button &&
12765       (d_perpendicular < dial->pointer_width/2) &&
12766       (d_parallel > - dial->pointer_width))
12767     {
12768       gtk_grab_add (widget);
12769
12770       dial->button = event->button;
12771
12772       gtk_dial_update_mouse (dial, event->x, event->y);
12773     }
12774
12775   return FALSE;
12776 }
12777
12778 static gint
12779 gtk_dial_button_release (GtkWidget      *widget,
12780                           GdkEventButton *event)
12781 {
12782   GtkDial *dial;
12783
12784   g_return_val_if_fail (widget != NULL, FALSE);
12785   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12786   g_return_val_if_fail (event != NULL, FALSE);
12787
12788   dial = GTK_DIAL (widget);
12789
12790   if (dial->button == event->button)
12791     {
12792       gtk_grab_remove (widget);
12793
12794       dial->button = 0;
12795
12796       if (dial->policy == GTK_UPDATE_DELAYED)
12797         gtk_timeout_remove (dial->timer);
12798       
12799       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
12800           (dial->old_value != dial->adjustment->value))
12801         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12802     }
12803
12804   return FALSE;
12805 }
12806
12807 static gint
12808 gtk_dial_motion_notify (GtkWidget      *widget,
12809                          GdkEventMotion *event)
12810 {
12811   GtkDial *dial;
12812   GdkModifierType mods;
12813   gint x, y, mask;
12814
12815   g_return_val_if_fail (widget != NULL, FALSE);
12816   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12817   g_return_val_if_fail (event != NULL, FALSE);
12818
12819   dial = GTK_DIAL (widget);
12820
12821   if (dial->button != 0)
12822     {
12823       x = event->x;
12824       y = event->y;
12825
12826       if (event->is_hint || (event->window != widget->window))
12827         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
12828
12829       switch (dial->button)
12830         {
12831         case 1:
12832           mask = GDK_BUTTON1_MASK;
12833           break;
12834         case 2:
12835           mask = GDK_BUTTON2_MASK;
12836           break;
12837         case 3:
12838           mask = GDK_BUTTON3_MASK;
12839           break;
12840         default:
12841           mask = 0;
12842           break;
12843         }
12844
12845       if (mods & mask)
12846         gtk_dial_update_mouse (dial, x,y);
12847     }
12848
12849   return FALSE;
12850 }
12851
12852 static gint
12853 gtk_dial_timer (GtkDial *dial)
12854 {
12855   g_return_val_if_fail (dial != NULL, FALSE);
12856   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
12857
12858   if (dial->policy == GTK_UPDATE_DELAYED)
12859     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12860
12861   return FALSE;
12862 }
12863
12864 static void
12865 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
12866 {
12867   gint xc, yc;
12868   gfloat old_value;
12869
12870   g_return_if_fail (dial != NULL);
12871   g_return_if_fail (GTK_IS_DIAL (dial));
12872
12873   xc = GTK_WIDGET(dial)->allocation.width / 2;
12874   yc = GTK_WIDGET(dial)->allocation.height / 2;
12875
12876   old_value = dial->adjustment->value;
12877   dial->angle = atan2(yc-y, x-xc);
12878
12879   if (dial->angle < -M_PI/2.)
12880     dial->angle += 2*M_PI;
12881
12882   if (dial->angle < -M_PI/6)
12883     dial->angle = -M_PI/6;
12884
12885   if (dial->angle > 7.*M_PI/6.)
12886     dial->angle = 7.*M_PI/6.;
12887
12888   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
12889     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
12890
12891   if (dial->adjustment->value != old_value)
12892     {
12893       if (dial->policy == GTK_UPDATE_CONTINUOUS)
12894         {
12895           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12896         }
12897       else
12898         {
12899           gtk_widget_draw (GTK_WIDGET(dial), NULL);
12900
12901           if (dial->policy == GTK_UPDATE_DELAYED)
12902             {
12903               if (dial->timer)
12904                 gtk_timeout_remove (dial->timer);
12905
12906               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
12907                                              (GtkFunction) gtk_dial_timer,
12908                                              (gpointer) dial);
12909             }
12910         }
12911     }
12912 }
12913 </verb></tscreen>
12914
12915 <p>
12916 Changes to the Adjustment by external means are communicated to our
12917 widget by the `changed' and `value_changed' signals. The handlers
12918 for these functions call <tt/gtk_dial_update()/ to validate the
12919 arguments, compute the new pointer angle, and redraw the widget (by
12920 calling <tt/gtk_widget_draw()/).
12921
12922 <tscreen><verb>
12923 static void
12924 gtk_dial_update (GtkDial *dial)
12925 {
12926   gfloat new_value;
12927   
12928   g_return_if_fail (dial != NULL);
12929   g_return_if_fail (GTK_IS_DIAL (dial));
12930
12931   new_value = dial->adjustment->value;
12932   
12933   if (new_value < dial->adjustment->lower)
12934     new_value = dial->adjustment->lower;
12935
12936   if (new_value > dial->adjustment->upper)
12937     new_value = dial->adjustment->upper;
12938
12939   if (new_value != dial->adjustment->value)
12940     {
12941       dial->adjustment->value = new_value;
12942       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12943     }
12944
12945   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
12946     (dial->adjustment->upper - dial->adjustment->lower);
12947
12948   gtk_widget_draw (GTK_WIDGET(dial), NULL);
12949 }
12950
12951 static void
12952 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
12953                               gpointer       data)
12954 {
12955   GtkDial *dial;
12956
12957   g_return_if_fail (adjustment != NULL);
12958   g_return_if_fail (data != NULL);
12959
12960   dial = GTK_DIAL (data);
12961
12962   if ((dial->old_value != adjustment->value) ||
12963       (dial->old_lower != adjustment->lower) ||
12964       (dial->old_upper != adjustment->upper))
12965     {
12966       gtk_dial_update (dial);
12967
12968       dial->old_value = adjustment->value;
12969       dial->old_lower = adjustment->lower;
12970       dial->old_upper = adjustment->upper;
12971     }
12972 }
12973
12974 static void
12975 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
12976                                     gpointer       data)
12977 {
12978   GtkDial *dial;
12979
12980   g_return_if_fail (adjustment != NULL);
12981   g_return_if_fail (data != NULL);
12982
12983   dial = GTK_DIAL (data);
12984
12985   if (dial->old_value != adjustment->value)
12986     {
12987       gtk_dial_update (dial);
12988
12989       dial->old_value = adjustment->value;
12990     }
12991 }
12992 </verb></tscreen>
12993
12994 <!-- ----------------------------------------------------------------- -->
12995 <sect2> Possible Enhancements
12996 <p>
12997
12998 The Dial widget as we've described it so far runs about 670 lines of
12999 code. Although that might sound like a fair bit, we've really
13000 accomplished quite a bit with that much code, especially since much of
13001 that length is headers and boilerplate. However, there are quite a few
13002 more enhancements that could be made to this widget:
13003
13004 <itemize>
13005 <item> If you try this widget out, you'll find that there is some
13006 flashing as the pointer is dragged around. This is because the entire
13007 widget is erased every time the pointer is moved before being
13008 redrawn. Often, the best way to handle this problem is to draw to an
13009 offscreen pixmap, then copy the final results onto the screen in one
13010 step. (The ProgressBar widget draws itself in this fashion.)
13011
13012 <item> The user should be able to use the up and down arrow keys to
13013 increase and decrease the value.
13014
13015 <item> It would be nice if the widget had buttons to increase and
13016 decrease the value in small or large steps. Although it would be
13017 possible to use embedded Button widgets for this, we would also like
13018 the buttons to auto-repeat when held down, as the arrows on a
13019 scrollbar do. Most of the code to implement this type of behavior can
13020 be found in the GtkRange widget.
13021
13022 <item> The Dial widget could be made into a container widget with a
13023 single child widget positioned at the bottom between the buttons
13024 mentioned above. The user could then add their choice of a label or
13025 entry widget to display the current value of the dial.
13026
13027 </itemize>
13028
13029 <!-- ----------------------------------------------------------------- -->
13030 <sect1> Learning More
13031
13032 <p>
13033 Only a small part of the many details involved in creating widgets
13034 could be described above. If you want to write your own widgets, the
13035 best source of examples is the GTK source itself. Ask yourself some
13036 questions about the widget you want to write: is it a Container
13037 widget? does it have its own window? is it a modification of an
13038 existing widget? Then find a similar widget, and start making changes.
13039 Good luck!
13040
13041 <!-- ***************************************************************** -->
13042 <sect>Scribble, A Simple Example Drawing Program
13043 <!-- ***************************************************************** -->
13044
13045 <!-- ----------------------------------------------------------------- -->
13046 <sect1> Overview
13047
13048 <p>
13049 In this section, we will build a simple drawing program. In the
13050 process, we will examine how to handle mouse events, how to draw in a
13051 window, and how to do drawing better by using a backing pixmap. After
13052 creating the simple drawing program, we will extend it by adding
13053 support for XInput devices, such as drawing tablets. GTK provides
13054 support routines which makes getting extended information, such as
13055 pressure and tilt, from such devices quite easy.
13056
13057 <!-- ----------------------------------------------------------------- -->
13058 <sect1> Event Handling
13059
13060 <p>
13061 The GTK signals we have already discussed are for high-level actions,
13062 such as a menu item being selected. However, sometimes it is useful to
13063 learn about lower-level occurrences, such as the mouse being moved, or
13064 a key being pressed. There are also GTK signals corresponding to these
13065 low-level <em>events</em>. The handlers for these signals have an
13066 extra parameter which is a pointer to a structure containing
13067 information about the event. For instance, motion events handlers are
13068 passed a pointer to a GdkEventMotion structure which looks (in part)
13069 like:
13070
13071 <tscreen><verb>
13072 struct _GdkEventMotion
13073 {
13074   GdkEventType type;
13075   GdkWindow *window;
13076   guint32 time;
13077   gdouble x;
13078   gdouble y;
13079   ...
13080   guint state;
13081   ...
13082 };
13083 </verb></tscreen>
13084
13085 <tt/type/ will be set to the event type, in this case
13086 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
13087 occurred. <tt/x/ and <tt/y/ give the coordinates of the event,
13088 and <tt/state/ specifies the modifier state when the event
13089 occurred (that is, it specifies which modifier keys and mouse buttons
13090 were pressed.) It is the bitwise OR of some of the following:
13091
13092 <tscreen><verb>
13093 GDK_SHIFT_MASK  
13094 GDK_LOCK_MASK   
13095 GDK_CONTROL_MASK
13096 GDK_MOD1_MASK   
13097 GDK_MOD2_MASK   
13098 GDK_MOD3_MASK   
13099 GDK_MOD4_MASK   
13100 GDK_MOD5_MASK   
13101 GDK_BUTTON1_MASK
13102 GDK_BUTTON2_MASK
13103 GDK_BUTTON3_MASK
13104 GDK_BUTTON4_MASK
13105 GDK_BUTTON5_MASK
13106 </verb></tscreen>
13107
13108 <p>
13109 As for other signals, to determine what happens when an event occurs
13110 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
13111 know which events we want to be notified about. To do this, we call
13112 the function:
13113
13114 <tscreen><verb>
13115 void gtk_widget_set_events (GtkWidget *widget,
13116                             gint      events);
13117 </verb></tscreen>
13118
13119 The second field specifies the events we are interested in. It
13120 is the bitwise OR of constants that specify different types
13121 of events. For future reference the event types are:
13122
13123 <tscreen><verb>
13124 GDK_EXPOSURE_MASK
13125 GDK_POINTER_MOTION_MASK
13126 GDK_POINTER_MOTION_HINT_MASK
13127 GDK_BUTTON_MOTION_MASK     
13128 GDK_BUTTON1_MOTION_MASK    
13129 GDK_BUTTON2_MOTION_MASK    
13130 GDK_BUTTON3_MOTION_MASK    
13131 GDK_BUTTON_PRESS_MASK      
13132 GDK_BUTTON_RELEASE_MASK    
13133 GDK_KEY_PRESS_MASK         
13134 GDK_KEY_RELEASE_MASK       
13135 GDK_ENTER_NOTIFY_MASK      
13136 GDK_LEAVE_NOTIFY_MASK      
13137 GDK_FOCUS_CHANGE_MASK      
13138 GDK_STRUCTURE_MASK         
13139 GDK_PROPERTY_CHANGE_MASK   
13140 GDK_PROXIMITY_IN_MASK      
13141 GDK_PROXIMITY_OUT_MASK     
13142 </verb></tscreen>
13143
13144 There are a few subtle points that have to be observed when calling
13145 <tt/gtk_widget_set_events()/. First, it must be called before the X window
13146 for a GTK widget is created. In practical terms, this means you
13147 should call it immediately after creating the widget. Second, the
13148 widget must have an associated X window. For efficiency, many widget
13149 types do not have their own window, but draw in their parent's window.
13150 These widgets are:
13151
13152 <tscreen><verb>
13153 GtkAlignment
13154 GtkArrow
13155 GtkBin
13156 GtkBox
13157 GtkImage
13158 GtkItem
13159 GtkLabel
13160 GtkPixmap
13161 GtkScrolledWindow
13162 GtkSeparator
13163 GtkTable
13164 GtkAspectFrame
13165 GtkFrame
13166 GtkVBox
13167 GtkHBox
13168 GtkVSeparator
13169 GtkHSeparator
13170 </verb></tscreen>
13171
13172 To capture events for these widgets, you need to use an EventBox
13173 widget. See the section on the <ref id="sec_EventBox"
13174 name="EventBox"> widget for details.
13175
13176 <p>
13177 For our drawing program, we want to know when the mouse button is
13178 pressed and when the mouse is moved, so we specify
13179 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
13180 want to know when we need to redraw our window, so we specify
13181 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
13182 Configure event when our window size changes, we don't have to specify
13183 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
13184 automatically specified for all windows.
13185
13186 <p>
13187 It turns out, however, that there is a problem with just specifying
13188 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
13189 motion event to the event queue every time the user moves the mouse.
13190 Imagine that it takes us 0.1 seconds to handle a motion event, but the
13191 X server queues a new motion event every 0.05 seconds. We will soon
13192 get way behind the users drawing. If the user draws for 5 seconds,
13193 it will take us another 5 seconds to catch up after they release 
13194 the mouse button! What we would like is to only get one motion
13195 event for each event we process. The way to do this is to 
13196 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
13197
13198 <p>
13199 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
13200 us a motion event the first time the pointer moves after entering
13201 our window, or after a button press or release event. Subsequent 
13202 motion events will be suppressed until we explicitly ask for
13203 the position of the pointer using the function:
13204
13205 <tscreen><verb>
13206 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
13207                                           gint            *x,
13208                                           gint            *y,
13209                                           GdkModifierType *mask);
13210 </verb></tscreen>
13211
13212 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
13213 has a simpler interface, but turns out not to be very useful, since
13214 it only retrieves the position of the mouse, not whether the buttons
13215 are pressed.)
13216
13217 <p>
13218 The code to set the events for our window then looks like:
13219
13220 <tscreen><verb>
13221   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
13222                       (GtkSignalFunc) expose_event, NULL);
13223   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
13224                       (GtkSignalFunc) configure_event, NULL);
13225   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
13226                       (GtkSignalFunc) motion_notify_event, NULL);
13227   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
13228                       (GtkSignalFunc) button_press_event, NULL);
13229
13230   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
13231                          | GDK_LEAVE_NOTIFY_MASK
13232                          | GDK_BUTTON_PRESS_MASK
13233                          | GDK_POINTER_MOTION_MASK
13234                          | GDK_POINTER_MOTION_HINT_MASK);
13235 </verb></tscreen>
13236
13237 We'll save the "expose_event" and "configure_event" handlers for
13238 later. The "motion_notify_event" and "button_press_event" handlers
13239 pretty simple:
13240
13241 <tscreen><verb>
13242 static gint
13243 button_press_event (GtkWidget *widget, GdkEventButton *event)
13244 {
13245   if (event->button == 1 &amp;&amp; pixmap != NULL)
13246       draw_brush (widget, event->x, event->y);
13247
13248   return TRUE;
13249 }
13250
13251 static gint
13252 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13253 {
13254   int x, y;
13255   GdkModifierType state;
13256
13257   if (event->is_hint)
13258     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
13259   else
13260     {
13261       x = event->x;
13262       y = event->y;
13263       state = event->state;
13264     }
13265     
13266   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13267     draw_brush (widget, x, y);
13268   
13269   return TRUE;
13270 }
13271 </verb></tscreen>
13272
13273 <!-- ----------------------------------------------------------------- -->
13274 <sect1> The DrawingArea Widget, And Drawing
13275
13276 <p>
13277 We know turn to the process of drawing on the screen. The 
13278 widget we use for this is the DrawingArea widget. A drawing area
13279 widget is essentially an X window and nothing more. It is a blank
13280 canvas in which we can draw whatever we like. A drawing area
13281 is created using the call:
13282
13283 <tscreen><verb>
13284 GtkWidget* gtk_drawing_area_new        (void);
13285 </verb></tscreen>
13286
13287 A default size for the widget can be specified by calling:
13288
13289 <tscreen><verb>
13290 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
13291                                         gint                 width,
13292                                         gint                 height);
13293 </verb></tscreen>
13294
13295 This default size can be overridden, as is true for all widgets,
13296 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
13297 be overridden if the user manually resizes the the window containing
13298 the drawing area.
13299
13300 <p>
13301 It should be noted that when we create a DrawingArea widget, we are,
13302 <em>completely</em> responsible for drawing the contents. If our
13303 window is obscured then uncovered, we get an exposure event and must
13304 redraw what was previously hidden.
13305
13306 <p>
13307 Having to remember everything that was drawn on the screen so we
13308 can properly redraw it can, to say the least, be a nuisance. In
13309 addition, it can be visually distracting if portions of the
13310 window are cleared, then redrawn step by step. The solution to
13311 this problem is to use an offscreen <em>backing pixmap</em>.
13312 Instead of drawing directly to the screen, we draw to an image
13313 stored in server memory but not displayed, then when the image
13314 changes or new portions of the image are displayed, we copy the
13315 relevant portions onto the screen.
13316
13317 <p>
13318 To create an offscreen pixmap, we call the function:
13319
13320 <tscreen><verb>
13321 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
13322                                          gint        width,
13323                                          gint        height,
13324                                          gint        depth);
13325 </verb></tscreen>
13326
13327 The <tt>window</tt> parameter specifies a GDK window that this pixmap
13328 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
13329 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
13330 depth</em>, that is the number of bits per pixel, for the new window.
13331 If the depth is specified as <tt>-1</tt>, it will match the depth
13332 of <tt>window</tt>.
13333
13334 <p>
13335 We create the pixmap in our "configure_event" handler. This event
13336 is generated whenever the window changes size, including when it
13337 is originally created.
13338
13339 <tscreen><verb>
13340 /* Backing pixmap for drawing area */
13341 static GdkPixmap *pixmap = NULL;
13342
13343 /* Create a new backing pixmap of the appropriate size */
13344 static gint
13345 configure_event (GtkWidget *widget, GdkEventConfigure *event)
13346 {
13347   if (pixmap)
13348     gdk_pixmap_unref(pixmap);
13349
13350   pixmap = gdk_pixmap_new(widget->window,
13351                           widget->allocation.width,
13352                           widget->allocation.height,
13353                           -1);
13354   gdk_draw_rectangle (pixmap,
13355                       widget->style->white_gc,
13356                       TRUE,
13357                       0, 0,
13358                       widget->allocation.width,
13359                       widget->allocation.height);
13360
13361   return TRUE;
13362 }
13363 </verb></tscreen>
13364
13365 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
13366 initially to white. We'll say more about that in a moment.
13367
13368 <p>
13369 Our exposure event handler then simply copies the relevant portion
13370 of the pixmap onto the screen (we determine the area we need
13371 to redraw by using the event->area field of the exposure event):
13372
13373 <tscreen><verb>
13374 /* Redraw the screen from the backing pixmap */
13375 static gint
13376 expose_event (GtkWidget *widget, GdkEventExpose *event)
13377 {
13378   gdk_draw_pixmap(widget->window,
13379                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
13380                   pixmap,
13381                   event->area.x, event->area.y,
13382                   event->area.x, event->area.y,
13383                   event->area.width, event->area.height);
13384
13385   return FALSE;
13386 }
13387 </verb></tscreen>
13388
13389 We've now seen how to keep the screen up to date with our pixmap, but
13390 how do we actually draw interesting stuff on our pixmap?  There are a
13391 large number of calls in GTK's GDK library for drawing on
13392 <em>drawables</em>. A drawable is simply something that can be drawn
13393 upon. It can be a window, a pixmap, or a bitmap (a black and white
13394 image).  We've already seen two such calls above,
13395 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
13396 complete list is:
13397
13398 <tscreen><verb>
13399 gdk_draw_line ()
13400 gdk_draw_rectangle ()
13401 gdk_draw_arc ()
13402 gdk_draw_polygon ()
13403 gdk_draw_string ()
13404 gdk_draw_text ()
13405 gdk_draw_pixmap ()
13406 gdk_draw_bitmap ()
13407 gdk_draw_image ()
13408 gdk_draw_points ()
13409 gdk_draw_segments ()
13410 </verb></tscreen>
13411
13412 See the reference documentation or the header file
13413 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
13414 These functions all share the same first two arguments. The first
13415 argument is the drawable to draw upon, the second argument is a
13416 <em>graphics context</em> (GC). 
13417
13418 <p>
13419 A graphics context encapsulates information about things such as
13420 foreground and background color and line width. GDK has a full set of
13421 functions for creating and modifying graphics contexts, but to keep
13422 things simple we'll just use predefined graphics contexts. Each widget
13423 has an associated style. (Which can be modified in a gtkrc file, see
13424 the section GTK's rc file.) This, among other things, stores a number
13425 of graphics contexts. Some examples of accessing these graphics
13426 contexts are:
13427
13428 <tscreen><verb>
13429 widget->style->white_gc
13430 widget->style->black_gc
13431 widget->style->fg_gc[GTK_STATE_NORMAL]
13432 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
13433 </verb></tscreen>
13434
13435 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
13436 <tt>light_gc</tt> are indexed by a parameter of type
13437 <tt>GtkStateType</tt> which can take on the values:
13438
13439 <tscreen><verb>
13440 GTK_STATE_NORMAL,
13441 GTK_STATE_ACTIVE,
13442 GTK_STATE_PRELIGHT,
13443 GTK_STATE_SELECTED,
13444 GTK_STATE_INSENSITIVE
13445 </verb></tscreen>
13446
13447 For instance, the for <tt/GTK_STATE_SELECTED/ the default foreground
13448 color is white and the default background color, dark blue.
13449
13450 <p>
13451 Our function <tt>draw_brush()</tt>, which does the actual drawing
13452 on the screen, is then:
13453
13454 <tscreen><verb>
13455 /* Draw a rectangle on the screen */
13456 static void
13457 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
13458 {
13459   GdkRectangle update_rect;
13460
13461   update_rect.x = x - 5;
13462   update_rect.y = y - 5;
13463   update_rect.width = 10;
13464   update_rect.height = 10;
13465   gdk_draw_rectangle (pixmap,
13466                       widget->style->black_gc,
13467                       TRUE,
13468                       update_rect.x, update_rect.y,
13469                       update_rect.width, update_rect.height);
13470   gtk_widget_draw (widget, &amp;update_rect);
13471 }
13472 </verb></tscreen>
13473
13474 After we draw the rectangle representing the brush onto the pixmap,
13475 we call the function:
13476
13477 <tscreen><verb>
13478 void       gtk_widget_draw                (GtkWidget           *widget,
13479                                            GdkRectangle        *area);
13480 </verb></tscreen>
13481
13482 which notifies X that the area given by the <tt>area</tt> parameter
13483 needs to be updated. X will eventually generate an expose event
13484 (possibly combining the areas passed in several calls to
13485 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
13486 to copy the relevant portions to the screen.
13487
13488 <p>
13489 We have now covered the entire drawing program except for a few
13490 mundane details like creating the main window. The complete
13491 source code is available from the location from which you got
13492 this tutorial, or from:
13493
13494 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13495 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13496
13497
13498 <!-- ----------------------------------------------------------------- -->
13499 <sect1> Adding XInput support
13500
13501 <p>
13502
13503 It is now possible to buy quite inexpensive input devices such 
13504 as drawing tablets, which allow drawing with a much greater
13505 ease of artistic expression than does a mouse. The simplest way
13506 to use such devices is simply as a replacement for the mouse,
13507 but that misses out many of the advantages of these devices,
13508 such as:
13509
13510 <itemize>
13511 <item> Pressure sensitivity
13512 <item> Tilt reporting
13513 <item> Sub-pixel positioning
13514 <item> Multiple inputs (for example, a stylus with a point and eraser)
13515 </itemize>
13516
13517 For information about the XInput extension, see the <htmlurl
13518 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13519 name="XInput-HOWTO">.
13520
13521 <p>
13522 If we examine the full definition of, for example, the GdkEventMotion
13523 structure, we see that it has fields to support extended device
13524 information.
13525
13526 <tscreen><verb>
13527 struct _GdkEventMotion
13528 {
13529   GdkEventType type;
13530   GdkWindow *window;
13531   guint32 time;
13532   gdouble x;
13533   gdouble y;
13534   gdouble pressure;
13535   gdouble xtilt;
13536   gdouble ytilt;
13537   guint state;
13538   gint16 is_hint;
13539   GdkInputSource source;
13540   guint32 deviceid;
13541 };
13542 </verb></tscreen>
13543
13544 <tt/pressure/ gives the pressure as a floating point number between
13545 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
13546 -1 and 1, corresponding to the degree of tilt in each direction.
13547 <tt/source/ and <tt/deviceid/ specify the device for which the
13548 event occurred in two different ways. <tt/source/ gives some simple
13549 information about the type of device. It can take the enumeration
13550 values.
13551
13552 <tscreen><verb>
13553 GDK_SOURCE_MOUSE
13554 GDK_SOURCE_PEN
13555 GDK_SOURCE_ERASER
13556 GDK_SOURCE_CURSOR
13557 </verb></tscreen>
13558
13559 <tt/deviceid/ specifies a unique numeric ID for the device. This can
13560 be used to find out further information about the device using the
13561 <tt/gdk_input_list_devices()/ call (see below). The special value
13562 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
13563 the mouse.)
13564
13565 <sect2> Enabling extended device information
13566
13567 <p>
13568 To let GTK know about our interest in the extended device information,
13569 we merely have to add a single line to our program:
13570
13571 <tscreen><verb>
13572 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
13573 </verb></tscreen>
13574
13575 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
13576 we are interested in extension events, but only if we don't have
13577 to draw our own cursor. See the section <ref
13578 id="sec_Further_Sophistications" name="Further Sophistications"> below
13579 for more information about drawing the cursor. We could also 
13580 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
13581 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
13582 back to the default condition.
13583
13584 <p>
13585 This is not completely the end of the story however. By default,
13586 no extension devices are enabled. We need a mechanism to allow
13587 users to enable and configure their extension devices. GTK provides
13588 the InputDialog widget to automate this process. The following
13589 procedure manages an InputDialog widget. It creates the dialog if
13590 it isn't present, and raises it to the top otherwise.
13591
13592 <tscreen><verb>
13593 void
13594 input_dialog_destroy (GtkWidget *w, gpointer data)
13595 {
13596   *((GtkWidget **)data) = NULL;
13597 }
13598
13599 void
13600 create_input_dialog ()
13601 {
13602   static GtkWidget *inputd = NULL;
13603
13604   if (!inputd)
13605     {
13606       inputd = gtk_input_dialog_new();
13607
13608       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
13609                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
13610       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
13611                                  "clicked",
13612                                  (GtkSignalFunc)gtk_widget_hide,
13613                                  GTK_OBJECT(inputd));
13614       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
13615
13616       gtk_widget_show (inputd);
13617     }
13618   else
13619     {
13620       if (!GTK_WIDGET_MAPPED(inputd))
13621         gtk_widget_show(inputd);
13622       else
13623         gdk_window_raise(inputd->window);
13624     }
13625 }
13626 </verb></tscreen>
13627
13628 (You might want to take note of the way we handle this dialog.  By
13629 connecting to the "destroy" signal, we make sure that we don't keep a
13630 pointer to dialog around after it is destroyed - that could lead to a
13631 segfault.)
13632
13633 <p>
13634 The InputDialog has two buttons "Close" and "Save", which by default
13635 have no actions assigned to them. In the above function we make
13636 "Close" hide the dialog, hide the "Save" button, since we don't
13637 implement saving of XInput options in this program.
13638
13639 <sect2> Using extended device information
13640
13641 <p>
13642 Once we've enabled the device, we can just use the extended 
13643 device information in the extra fields of the event structures.
13644 In fact, it is always safe to use this information since these
13645 fields will have reasonable default values even when extended
13646 events are not enabled.
13647
13648 <p>
13649 Once change we do have to make is to call
13650 <tt/gdk_input_window_get_pointer()/ instead of
13651 <tt/gdk_window_get_pointer/. This is necessary because
13652 <tt/gdk_window_get_pointer/ doesn't return the extended device
13653 information.
13654
13655 <tscreen><verb>
13656 void gdk_input_window_get_pointer     (GdkWindow       *window,
13657                                        guint32         deviceid,
13658                                        gdouble         *x,
13659                                        gdouble         *y,
13660                                        gdouble         *pressure,
13661                                        gdouble         *xtilt,
13662                                        gdouble         *ytilt,
13663                                        GdkModifierType *mask);
13664 </verb></tscreen>
13665
13666 When calling this function, we need to specify the device ID as
13667 well as the window. Usually, we'll get the device ID from the
13668 <tt/deviceid/ field of an event structure. Again, this function
13669 will return reasonable values when extension events are not
13670 enabled. (In this case, <tt/event->deviceid/ will have the value
13671 <tt/GDK_CORE_POINTER/).
13672
13673 So the basic structure of our button-press and motion event handlers,
13674 doesn't change much - we just need to add code to deal with the
13675 extended information.
13676
13677 <tscreen><verb>
13678 static gint
13679 button_press_event (GtkWidget *widget, GdkEventButton *event)
13680 {
13681   print_button_press (event->deviceid);
13682   
13683   if (event->button == 1 &amp;&amp; pixmap != NULL)
13684     draw_brush (widget, event->source, event->x, event->y, event->pressure);
13685
13686   return TRUE;
13687 }
13688
13689 static gint
13690 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13691 {
13692   gdouble x, y;
13693   gdouble pressure;
13694   GdkModifierType state;
13695
13696   if (event->is_hint)
13697     gdk_input_window_get_pointer (event->window, event->deviceid,
13698                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
13699   else
13700     {
13701       x = event->x;
13702       y = event->y;
13703       pressure = event->pressure;
13704       state = event->state;
13705     }
13706     
13707   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13708     draw_brush (widget, event->source, x, y, pressure);
13709   
13710   return TRUE;
13711 }
13712 </verb></tscreen>
13713
13714 We also need to do something with the new information. Our new
13715 <tt/draw_brush()/ function draws with a different color for
13716 each <tt/event->source/ and changes the brush size depending
13717 on the pressure.
13718
13719 <tscreen><verb>
13720 /* Draw a rectangle on the screen, size depending on pressure,
13721    and color on the type of device */
13722 static void
13723 draw_brush (GtkWidget *widget, GdkInputSource source,
13724             gdouble x, gdouble y, gdouble pressure)
13725 {
13726   GdkGC *gc;
13727   GdkRectangle update_rect;
13728
13729   switch (source)
13730     {
13731     case GDK_SOURCE_MOUSE:
13732       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
13733       break;
13734     case GDK_SOURCE_PEN:
13735       gc = widget->style->black_gc;
13736       break;
13737     case GDK_SOURCE_ERASER:
13738       gc = widget->style->white_gc;
13739       break;
13740     default:
13741       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
13742     }
13743
13744   update_rect.x = x - 10 * pressure;
13745   update_rect.y = y - 10 * pressure;
13746   update_rect.width = 20 * pressure;
13747   update_rect.height = 20 * pressure;
13748   gdk_draw_rectangle (pixmap, gc, TRUE,
13749                       update_rect.x, update_rect.y,
13750                       update_rect.width, update_rect.height);
13751   gtk_widget_draw (widget, &amp;update_rect);
13752 }
13753 </verb></tscreen>
13754
13755 <sect2> Finding out more about a device
13756
13757 <p>
13758 As an example of how to find out more about a device, our program
13759 will print the name of the device that generates each button
13760 press. To find out the name of a device, we call the function:
13761
13762 <tscreen><verb>
13763 GList *gdk_input_list_devices               (void);
13764 </verb></tscreen>
13765
13766 which returns a GList (a linked list type from the glib library)
13767 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
13768 as:
13769
13770 <tscreen><verb>
13771 struct _GdkDeviceInfo
13772 {
13773   guint32 deviceid;
13774   gchar *name;
13775   GdkInputSource source;
13776   GdkInputMode mode;
13777   gint has_cursor;
13778   gint num_axes;
13779   GdkAxisUse *axes;
13780   gint num_keys;
13781   GdkDeviceKey *keys;
13782 };
13783 </verb></tscreen>
13784
13785 Most of these fields are configuration information that you
13786 can ignore unless you are implemented XInput configuration
13787 saving. The we are interested in here is <tt/name/ which is
13788 simply the name that X assigns to the device. The other field
13789 that isn't configuration information is <tt/has_cursor/. If
13790 <tt/has_cursor/ is false, then we we need to draw our own
13791 cursor. But since we've specified <tt/GDK_EXTENSION_EVENTS_CURSOR/,
13792 we don't have to worry about this.
13793
13794 <p>
13795 Our <tt/print_button_press()/ function simply iterates through
13796 the returned list until it finds a match, then prints out
13797 the name of the device.
13798
13799 <tscreen><verb>
13800 static void
13801 print_button_press (guint32 deviceid)
13802 {
13803   GList *tmp_list;
13804
13805   /* gdk_input_list_devices returns an internal list, so we shouldn't
13806      free it afterwards */
13807   tmp_list = gdk_input_list_devices();
13808
13809   while (tmp_list)
13810     {
13811       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
13812
13813       if (info->deviceid == deviceid)
13814         {
13815           printf("Button press on device '%s'\n", info->name);
13816           return;
13817         }
13818
13819       tmp_list = tmp_list->next;
13820     }
13821 }
13822 </verb></tscreen>
13823
13824 That completes the changes to `XInputize' our program. As with
13825 the first version, the complete source is available at the location
13826 from which you got this tutorial, or from:
13827
13828 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13829 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13830
13831
13832 <sect2> Further sophistications <label id="sec_Further_Sophistications">
13833
13834 <p>
13835 Although our program now supports XInput quite well, it lacks some
13836 features we would want in a full-featured application. First, the user
13837 probably doesn't want to have to configure their device each time they
13838 run the program, so we should allow them to save the device
13839 configuration. This is done by iterating through the return of
13840 <tt/gdk_input_list_devices()/ and writing out the configuration to a
13841 file.
13842
13843 <p>
13844 To restore the state next time the program is run, GDK provides
13845 functions to change device configuration:
13846
13847 <tscreen><verb>
13848 gdk_input_set_extension_events()
13849 gdk_input_set_source()
13850 gdk_input_set_mode()
13851 gdk_input_set_axes()
13852 gdk_input_set_key()
13853 </verb></tscreen>
13854
13855 (The list returned from <tt/gdk_input_list_devices()/ should not be
13856 modified directly.) An example of doing this can be found in the
13857 drawing program gsumi. (Available from <htmlurl
13858 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
13859 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
13860 would be nice to have a standard way of doing this for all
13861 applications. This probably belongs at a slightly higher level than
13862 GTK, perhaps in the GNOME library.
13863
13864 <p>
13865 Another major omission that we have mentioned above is the lack of
13866 cursor drawing. Platforms other than XFree86 currently do not allow
13867 simultaneously using a device as both the core pointer and directly by
13868 an application. See the <url
13869 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13870 name="XInput-HOWTO"> for more information about this. This means that
13871 applications that want to support the widest audience need to draw
13872 their own cursor.
13873
13874 <p>
13875 An application that draws its own cursor needs to do two things:
13876 determine if the current device needs a cursor drawn or not, and
13877 determine if the current device is in proximity. (If the current
13878 device is a drawing tablet, it's a nice touch to make the cursor 
13879 disappear when the stylus is lifted from the tablet. When the
13880 device is touching the stylus, that is called "in proximity.")
13881 The first is done by searching the device list, as we did
13882 to find out the device name. The second is achieved by selecting
13883 "proximity_out" events. An example of drawing one's own cursor is
13884 found in the 'testinput' program found in the GTK distribution.
13885
13886 <!-- ***************************************************************** -->
13887 <sect>Tips For Writing GTK Applications
13888 <!-- ***************************************************************** -->
13889
13890 <p>
13891 This section is simply a gathering of wisdom, general style guidelines
13892 and hints to creating good GTK applications. It is totally useless
13893 right now cause its only a topic sentence :)
13894
13895 Use GNU autoconf and automake!  They are your friends :) I am planning
13896 to make a quick intro on them here.
13897
13898 <!-- ***************************************************************** -->
13899 <sect>Contributing <label id="sec_Contributing">
13900 <!-- ***************************************************************** -->
13901
13902 <p>
13903 This document, like so much other great software out there, was
13904 created for free by volunteers.  If you are at all knowledgeable about
13905 any aspect of GTK that does not already have documentation, please
13906 consider contributing to this document.
13907 <p>
13908 If you do decide to contribute, please mail your text to Tony Gale,
13909 <tt><htmlurl url="mailto:gale@gtk.org"
13910 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
13911 document is free, and any addition by you provide must also be
13912 free. That is, people may use any portion of your examples in their
13913 programs, and copies of this document may be distributed at will etc.
13914 <p>
13915 Thank you.
13916
13917 <!-- ***************************************************************** -->
13918 <sect>Credits
13919 <!-- ***************************************************************** -->
13920 <p>
13921 I would like to thank the following for their contributions to this text.
13922
13923 <itemize>
13924 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
13925 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
13926
13927 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
13928 name="raph@acm.org"></tt>
13929 for hello world ala GTK, widget packing, and general all around wisdom.
13930 He's also generously donated a home for this tutorial.
13931
13932 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
13933 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
13934 and the ability to make it :)
13935
13936 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
13937 name="werner.koch@guug.de"></tt> for converting the original plain text to
13938 SGML, and the widget class hierarchy.
13939
13940 <item>Mark Crichton <tt><htmlurl
13941 url="mailto:crichton@expert.cc.purdue.edu"
13942 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
13943 and the table packing tutorial.
13944
13945 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
13946 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
13947 patch to the distro).  He's also responsible for the selections code
13948 and tutorial, as well as the sections on writing your own GTK widgets,
13949 and the example application. Thanks a lot Owen for all you help!
13950
13951 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
13952 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
13953 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
13954 lot Mark!  You've been a great help.
13955
13956 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
13957 name="timj@psynet.net"></tt> for his great job on the Lists
13958 Widget. His excellent work on automatically extracting the widget tree
13959 and signal information from GTK. Thanks Tim :)
13960
13961 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
13962 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
13963 tutorial.
13964
13965 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
13966 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
13967
13968 <item>David Huggins-Daines <tt><htmlurl
13969 url="mailto:bn711@freenet.carleton.ca"
13970 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
13971 Widget sections.
13972
13973 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
13974 name="mars@lysator.liu.se"></tt> for the GtkCList section
13975 </itemize>
13976
13977 And to all of you who commented and helped refine this document.
13978
13979 Thanks.
13980
13981 <!-- ***************************************************************** -->
13982 <sect> Tutorial Copyright and Permissions Notice
13983 <!-- ***************************************************************** -->
13984
13985 <p>
13986 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
13987
13988 Copyright (C) 1998-1999 Tony Gale.
13989
13990 Permission is granted to make and distribute verbatim copies of this 
13991 manual provided the copyright notice and this permission notice are 
13992 preserved on all copies.
13993
13994 Permission is granted to copy and distribute modified versions of 
13995 this document under the conditions for verbatim copying, provided that 
13996 this copyright notice is included exactly as in the original,
13997 and that the entire resulting derived work is distributed under 
13998 the terms of a permission notice identical to this one.
13999 <P>Permission is granted to copy and distribute translations of this 
14000 document into another language, under the above conditions for modified 
14001 versions.
14002
14003 If you are intending to incorporate this document into a published 
14004 work, please contact the maintainer, and we will make an effort 
14005 to ensure that you have the most up to date information available.
14006
14007 There is no guarantee that this document lives up to its intended
14008 purpose.  This is simply provided as a free resource.  As such,
14009 the authors and maintainers of the information provided within can
14010 not make any guarantee that the information is even accurate.
14011
14012 <!-- ***************************************************************** -->
14013 <appendix>
14014 <!-- ***************************************************************** -->
14015
14016 <!-- ***************************************************************** -->
14017 <sect> GTK Signals <label id="sec_GTK_Signals">
14018 <!-- ***************************************************************** -->
14019 <p>
14020 As GTK is an object oriented widget set, it has a hierarchy of
14021 inheritance. This inheritance mechanism applies for
14022 signals. Therefore, you should refer to the widget hierarchy tree when
14023 using the signals listed in this section.
14024
14025 <!-- ----------------------------------------------------------------- -->
14026 <sect1>GtkObject
14027 <!-- ----------------------------------------------------------------- -->
14028 <p>
14029 <tscreen><verb>
14030 void GtkObject::destroy (GtkObject *,
14031                          gpointer);
14032 </verb></tscreen>
14033
14034 <!-- ----------------------------------------------------------------- -->
14035 <sect1>GtkWidget
14036 <!-- ----------------------------------------------------------------- -->
14037 <p>
14038 <tscreen><verb>
14039
14040 void GtkWidget::show    (GtkWidget *,
14041                          gpointer);
14042 void GtkWidget::hide    (GtkWidget *,
14043                          gpointer);
14044 void GtkWidget::map     (GtkWidget *,
14045                          gpointer);
14046 void GtkWidget::unmap   (GtkWidget *,
14047                          gpointer);
14048 void GtkWidget::realize (GtkWidget *,
14049                          gpointer);
14050 void GtkWidget::unrealize       (GtkWidget *,
14051                                  gpointer);
14052 void GtkWidget::draw    (GtkWidget *,
14053                          ggpointer,
14054                          gpointer);
14055 void GtkWidget::draw-focus      (GtkWidget *,
14056                                  gpointer);
14057 void GtkWidget::draw-default    (GtkWidget *,
14058                                  gpointer);
14059 void GtkWidget::size-request    (GtkWidget *,
14060                                  ggpointer,
14061                                  gpointer);
14062 void GtkWidget::size-allocate   (GtkWidget *,
14063                                  ggpointer,
14064                                  gpointer);
14065 void GtkWidget::state-changed   (GtkWidget *,
14066                                  GtkStateType,
14067                                  gpointer);
14068 void GtkWidget::parent-set      (GtkWidget *,
14069                                  GtkObject *,
14070                                  gpointer);
14071 void GtkWidget::style-set       (GtkWidget *,
14072                                  GtkStyle *,
14073                                  gpointer);
14074 void GtkWidget::add-accelerator (GtkWidget *,
14075                                  gguint,
14076                                  GtkAccelGroup *,
14077                                  gguint,
14078                                  GdkModifierType,
14079                                  GtkAccelFlags,
14080                                  gpointer);
14081 void GtkWidget::remove-accelerator      (GtkWidget *,
14082                                          GtkAccelGroup *,
14083                                          gguint,
14084                                          GdkModifierType,
14085                                          gpointer);
14086 gboolean GtkWidget::event       (GtkWidget *,
14087                                  GdkEvent *,
14088                                  gpointer);
14089 gboolean GtkWidget::button-press-event  (GtkWidget *,
14090                                          GdkEvent *,
14091                                          gpointer);
14092 gboolean GtkWidget::button-release-event        (GtkWidget *,
14093                                                  GdkEvent *,
14094                                                  gpointer);
14095 gboolean GtkWidget::motion-notify-event (GtkWidget *,
14096                                          GdkEvent *,
14097                                          gpointer);
14098 gboolean GtkWidget::delete-event        (GtkWidget *,
14099                                          GdkEvent *,
14100                                          gpointer);
14101 gboolean GtkWidget::destroy-event       (GtkWidget *,
14102                                          GdkEvent *,
14103                                          gpointer);
14104 gboolean GtkWidget::expose-event        (GtkWidget *,
14105                                          GdkEvent *,
14106                                          gpointer);
14107 gboolean GtkWidget::key-press-event     (GtkWidget *,
14108                                          GdkEvent *,
14109                                          gpointer);
14110 gboolean GtkWidget::key-release-event   (GtkWidget *,
14111                                          GdkEvent *,
14112                                          gpointer);
14113 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
14114                                          GdkEvent *,
14115                                          gpointer);
14116 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
14117                                          GdkEvent *,
14118                                          gpointer);
14119 gboolean GtkWidget::configure-event     (GtkWidget *,
14120                                          GdkEvent *,
14121                                          gpointer);
14122 gboolean GtkWidget::focus-in-event      (GtkWidget *,
14123                                          GdkEvent *,
14124                                          gpointer);
14125 gboolean GtkWidget::focus-out-event     (GtkWidget *,
14126                                          GdkEvent *,
14127                                          gpointer);
14128 gboolean GtkWidget::map-event   (GtkWidget *,
14129                                  GdkEvent *,
14130                                  gpointer);
14131 gboolean GtkWidget::unmap-event (GtkWidget *,
14132                                  GdkEvent *,
14133                                  gpointer);
14134 gboolean GtkWidget::property-notify-event       (GtkWidget *,
14135                                                  GdkEvent *,
14136                                                  gpointer);
14137 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
14138                                                  GdkEvent *,
14139                                                  gpointer);
14140 gboolean GtkWidget::selection-request-event     (GtkWidget *,
14141                                                  GdkEvent *,
14142                                                  gpointer);
14143 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
14144                                                  GdkEvent *,
14145                                                  gpointer);
14146 void GtkWidget::selection-get   (GtkWidget *,
14147                                  GtkSelectionData *,
14148                                  gguint,
14149                                  gpointer);
14150 void GtkWidget::selection-received      (GtkWidget *,
14151                                          GtkSelectionData *,
14152                                          gguint,
14153                                          gpointer);
14154 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
14155                                          GdkEvent *,
14156                                          gpointer);
14157 gboolean GtkWidget::proximity-out-event (GtkWidget *,
14158                                          GdkEvent *,
14159                                          gpointer);
14160 void GtkWidget::drag-begin      (GtkWidget *,
14161                                  GdkDragContext *,
14162                                  gpointer);
14163 void GtkWidget::drag-end        (GtkWidget *,
14164                                  GdkDragContext *,
14165                                  gpointer);
14166 void GtkWidget::drag-data-delete        (GtkWidget *,
14167                                          GdkDragContext *,
14168                                          gpointer);
14169 void GtkWidget::drag-leave      (GtkWidget *,
14170                                  GdkDragContext *,
14171                                  gguint,
14172                                  gpointer);
14173 gboolean GtkWidget::drag-motion (GtkWidget *,
14174                                  GdkDragContext *,
14175                                  ggint,
14176                                  ggint,
14177                                  gguint,
14178                                  gpointer);
14179 gboolean GtkWidget::drag-drop   (GtkWidget *,
14180                                  GdkDragContext *,
14181                                  ggint,
14182                                  ggint,
14183                                  gguint,
14184                                  gpointer);
14185 void GtkWidget::drag-data-get   (GtkWidget *,
14186                                  GdkDragContext *,
14187                                  GtkSelectionData *,
14188                                  gguint,
14189                                  gguint,
14190                                  gpointer);
14191 void GtkWidget::drag-data-received      (GtkWidget *,
14192                                          GdkDragContext *,
14193                                          ggint,
14194                                          ggint,
14195                                          GtkSelectionData *,
14196                                          gguint,
14197                                          gguint,
14198                                          gpointer);
14199 gboolean GtkWidget::client-event        (GtkWidget *,
14200                                          GdkEvent *,
14201                                          gpointer);
14202 gboolean GtkWidget::no-expose-event     (GtkWidget *,
14203                                          GdkEvent *,
14204                                          gpointer);
14205 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
14206                                                  GdkEvent *,
14207                                                  gpointer);
14208 void GtkWidget::debug-msg       (GtkWidget *,
14209                                  GtkString *,
14210                                  gpointer);
14211 </verb></tscreen>
14212
14213 <!-- ----------------------------------------------------------------- -->
14214 <sect1>GtkData
14215 <!-- ----------------------------------------------------------------- -->
14216 <p>
14217 <tscreen><verb>
14218 void GtkData::disconnect        (GtkData *,
14219                                  gpointer);
14220 </verb></tscreen>
14221
14222 <!-- ----------------------------------------------------------------- -->
14223 <sect1>GtkContainer
14224 <!-- ----------------------------------------------------------------- -->
14225 <p>
14226 <tscreen><verb>
14227 void GtkContainer::add  (GtkContainer *,
14228                          GtkWidget *,
14229                          gpointer);
14230 void GtkContainer::remove       (GtkContainer *,
14231                                  GtkWidget *,
14232                                  gpointer);
14233 void GtkContainer::check-resize (GtkContainer *,
14234                                  gpointer);
14235 GtkDirectionType GtkContainer::focus    (GtkContainer *,
14236                                          GtkDirectionType,
14237                                          gpointer);
14238 void GtkContainer::set-focus-child      (GtkContainer *,
14239                                          GtkWidget *,
14240                                          gpointer);
14241 </verb></tscreen>
14242
14243 <!-- ----------------------------------------------------------------- -->
14244 <sect1>GtkCalendar
14245 <!-- ----------------------------------------------------------------- -->
14246 <p>
14247 <tscreen><verb>
14248 void GtkCalendar::month-changed (GtkCalendar *,
14249                                  gpointer);
14250 void GtkCalendar::day-selected  (GtkCalendar *,
14251                                  gpointer);
14252 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
14253                                                  gpointer);
14254 void GtkCalendar::prev-month    (GtkCalendar *,
14255                                  gpointer);
14256 void GtkCalendar::next-month    (GtkCalendar *,
14257                                  gpointer);
14258 void GtkCalendar::prev-year     (GtkCalendar *,
14259                                  gpointer);
14260 void GtkCalendar::next-year     (GtkCalendar *,
14261                                  gpointer);
14262 </verb></tscreen>
14263
14264 <!-- ----------------------------------------------------------------- -->
14265 <sect1>GtkEditable
14266 <!-- ----------------------------------------------------------------- -->
14267 <p>
14268 <tscreen><verb>
14269 void GtkEditable::changed       (GtkEditable *,
14270                                  gpointer);
14271 void GtkEditable::insert-text   (GtkEditable *,
14272                                  GtkString *,
14273                                  ggint,
14274                                  ggpointer,
14275                                  gpointer);
14276 void GtkEditable::delete-text   (GtkEditable *,
14277                                  ggint,
14278                                  ggint,
14279                                  gpointer);
14280 void GtkEditable::activate      (GtkEditable *,
14281                                  gpointer);
14282 void GtkEditable::set-editable  (GtkEditable *,
14283                                  gboolean,
14284                                  gpointer);
14285 void GtkEditable::move-cursor   (GtkEditable *,
14286                                  ggint,
14287                                  ggint,
14288                                  gpointer);
14289 void GtkEditable::move-word     (GtkEditable *,
14290                                  ggint,
14291                                  gpointer);
14292 void GtkEditable::move-page     (GtkEditable *,
14293                                  ggint,
14294                                  ggint,
14295                                  gpointer);
14296 void GtkEditable::move-to-row   (GtkEditable *,
14297                                  ggint,
14298                                  gpointer);
14299 void GtkEditable::move-to-column        (GtkEditable *,
14300                                          ggint,
14301                                          gpointer);
14302 void GtkEditable::kill-char     (GtkEditable *,
14303                                  ggint,
14304                                  gpointer);
14305 void GtkEditable::kill-word     (GtkEditable *,
14306                                  ggint,
14307                                  gpointer);
14308 void GtkEditable::kill-line     (GtkEditable *,
14309                                  ggint,
14310                                  gpointer);
14311 void GtkEditable::cut-clipboard (GtkEditable *,
14312                                  gpointer);
14313 void GtkEditable::copy-clipboard        (GtkEditable *,
14314                                          gpointer);
14315 void GtkEditable::paste-clipboard       (GtkEditable *,
14316                                          gpointer);
14317 </verb></tscreen>
14318
14319 <!-- ----------------------------------------------------------------- -->
14320 <sect1>GtkTipsQuery
14321 <!-- ----------------------------------------------------------------- -->
14322 <p>
14323 <tscreen><verb>
14324 void GtkTipsQuery::start-query  (GtkTipsQuery *,
14325                                  gpointer);
14326 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
14327                                  gpointer);
14328 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
14329                                          GtkWidget *,
14330                                          GtkString *,
14331                                          GtkString *,
14332                                          gpointer);
14333 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
14334                                          GtkWidget *,
14335                                          GtkString *,
14336                                          GtkString *,
14337                                          GdkEvent *,
14338                                          gpointer);
14339 </verb></tscreen>
14340
14341 <!-- ----------------------------------------------------------------- -->
14342 <sect1>GtkCList
14343 <!-- ----------------------------------------------------------------- -->
14344 <p>
14345 <tscreen><verb>
14346 void GtkCList::select-row       (GtkCList *,
14347                                  ggint,
14348                                  ggint,
14349                                  GdkEvent *,
14350                                  gpointer);
14351 void GtkCList::unselect-row     (GtkCList *,
14352                                  ggint,
14353                                  ggint,
14354                                  GdkEvent *,
14355                                  gpointer);
14356 void GtkCList::row-move (GtkCList *,
14357                          ggint,
14358                          ggint,
14359                          gpointer);
14360 void GtkCList::click-column     (GtkCList *,
14361                                  ggint,
14362                                  gpointer);
14363 void GtkCList::resize-column    (GtkCList *,
14364                                  ggint,
14365                                  ggint,
14366                                  gpointer);
14367 void GtkCList::toggle-focus-row (GtkCList *,
14368                                  gpointer);
14369 void GtkCList::select-all       (GtkCList *,
14370                                  gpointer);
14371 void GtkCList::unselect-all     (GtkCList *,
14372                                  gpointer);
14373 void GtkCList::undo-selection   (GtkCList *,
14374                                  gpointer);
14375 void GtkCList::start-selection  (GtkCList *,
14376                                  gpointer);
14377 void GtkCList::end-selection    (GtkCList *,
14378                                  gpointer);
14379 void GtkCList::toggle-add-mode  (GtkCList *,
14380                                  gpointer);
14381 void GtkCList::extend-selection (GtkCList *,
14382                                  GtkScrollType,
14383                                  ggfloat,
14384                                  gboolean,
14385                                  gpointer);
14386 void GtkCList::scroll-vertical  (GtkCList *,
14387                                  GtkScrollType,
14388                                  ggfloat,
14389                                  gpointer);
14390 void GtkCList::scroll-horizontal        (GtkCList *,
14391                                          GtkScrollType,
14392                                          ggfloat,
14393                                          gpointer);
14394 void GtkCList::abort-column-resize      (GtkCList *,
14395                                          gpointer);
14396 </verb></tscreen>
14397
14398 <!-- ----------------------------------------------------------------- -->
14399 <sect1>GtkNotebook
14400 <!-- ----------------------------------------------------------------- -->
14401 <p>
14402 <tscreen><verb>
14403 void GtkNotebook::switch-page   (GtkNotebook *,
14404                                  ggpointer,
14405                                  gguint,
14406                                  gpointer);
14407
14408 </verb></tscreen>
14409
14410 <!-- ----------------------------------------------------------------- -->
14411 <sect1>GtkList
14412 <!-- ----------------------------------------------------------------- -->
14413 <p>
14414 <tscreen><verb>
14415 void GtkList::selection-changed (GtkList *,
14416                                  gpointer);
14417 void GtkList::select-child      (GtkList *,
14418                                  GtkWidget *,
14419                                  gpointer);
14420 void GtkList::unselect-child    (GtkList *,
14421                                  GtkWidget *,
14422                                  gpointer);
14423 </verb></tscreen>
14424
14425 <!-- ----------------------------------------------------------------- -->
14426 <sect1>GtkMenuShell
14427 <!-- ----------------------------------------------------------------- -->
14428 <p>
14429 <tscreen><verb>
14430 void GtkMenuShell::deactivate   (GtkMenuShell *,
14431                                  gpointer);
14432 void GtkMenuShell::selection-done       (GtkMenuShell *,
14433                                          gpointer);
14434 void GtkMenuShell::move-current (GtkMenuShell *,
14435                                  GtkMenuDirectionType,
14436                                  gpointer);
14437 void GtkMenuShell::activate-current     (GtkMenuShell *,
14438                                          gboolean,
14439                                          gpointer);
14440 void GtkMenuShell::cancel       (GtkMenuShell *,
14441                                  gpointer);
14442 </verb></tscreen>
14443
14444 <!-- ----------------------------------------------------------------- -->
14445 <sect1>GtkToolbar
14446 <!-- ----------------------------------------------------------------- -->
14447 <p>
14448 <tscreen><verb>
14449 void GtkToolbar::orientation-changed    (GtkToolbar *,
14450                                          ggint,
14451                                          gpointer);
14452 void GtkToolbar::style-changed  (GtkToolbar *,
14453                                  ggint,
14454                                  gpointer);
14455 </verb></tscreen>
14456
14457 <!-- ----------------------------------------------------------------- -->
14458 <sect1>GtkTree
14459 <!-- ----------------------------------------------------------------- -->
14460 <p>
14461 <tscreen><verb>
14462 void GtkTree::selection-changed (GtkTree *,
14463                                  gpointer);
14464 void GtkTree::select-child      (GtkTree *,
14465                                  GtkWidget *,
14466                                  gpointer);
14467 void GtkTree::unselect-child    (GtkTree *,
14468                                  GtkWidget *,
14469                                  gpointer);
14470 </verb></tscreen>
14471
14472 <!-- ----------------------------------------------------------------- -->
14473 <sect1>GtkButton
14474 <!-- ----------------------------------------------------------------- -->
14475 <p>
14476 <tscreen><verb>
14477 void GtkButton::pressed (GtkButton *,
14478                          gpointer);
14479 void GtkButton::released        (GtkButton *,
14480                                  gpointer);
14481 void GtkButton::clicked (GtkButton *,
14482                          gpointer);
14483 void GtkButton::enter   (GtkButton *,
14484                          gpointer);
14485 void GtkButton::leave   (GtkButton *,
14486                          gpointer);
14487 </verb></tscreen>
14488
14489 <!-- ----------------------------------------------------------------- -->
14490 <sect1>GtkItem
14491 <!-- ----------------------------------------------------------------- -->
14492 <p>
14493 <tscreen><verb>
14494 void GtkItem::select    (GtkItem *,
14495                          gpointer);
14496 void GtkItem::deselect  (GtkItem *,
14497                          gpointer);
14498 void GtkItem::toggle    (GtkItem *,
14499                          gpointer);
14500 </verb></tscreen>
14501
14502 <!-- ----------------------------------------------------------------- -->
14503 <sect1>GtkWindow
14504 <!-- ----------------------------------------------------------------- -->
14505 <p>
14506 <tscreen><verb>
14507 void GtkWindow::set-focus       (GtkWindow *,
14508                                  ggpointer,
14509                                  gpointer);
14510 </verb></tscreen>
14511
14512 <!-- ----------------------------------------------------------------- -->
14513 <sect1>GtkHandleBox
14514 <!-- ----------------------------------------------------------------- -->
14515 <p>
14516 <tscreen><verb>
14517 void GtkHandleBox::child-attached       (GtkHandleBox *,
14518                                          GtkWidget *,
14519                                          gpointer);
14520 void GtkHandleBox::child-detached       (GtkHandleBox *,
14521                                          GtkWidget *,
14522                                          gpointer);
14523 </verb></tscreen>
14524
14525 <!-- ----------------------------------------------------------------- -->
14526 <sect1>GtkToggleButton
14527 <!-- ----------------------------------------------------------------- -->
14528 <p>
14529 <tscreen><verb>
14530 void GtkToggleButton::toggled   (GtkToggleButton *,
14531                                  gpointer);
14532
14533 </verb></tscreen>
14534
14535 <!-- ----------------------------------------------------------------- -->
14536 <sect1>GtkMenuItem
14537 <!-- ----------------------------------------------------------------- -->
14538 <p>
14539 <tscreen><verb>
14540 void GtkMenuItem::activate      (GtkMenuItem *,
14541                                  gpointer);
14542 void GtkMenuItem::activate-item (GtkMenuItem *,
14543                                  gpointer);
14544 </verb></tscreen>
14545
14546 <!-- ----------------------------------------------------------------- -->
14547 <sect1>GtkListItem
14548 <!-- ----------------------------------------------------------------- -->
14549 <p>
14550 <tscreen><verb>
14551 void GtkListItem::toggle-focus-row      (GtkListItem *,
14552                                          gpointer);
14553 void GtkListItem::select-all    (GtkListItem *,
14554                                  gpointer);
14555 void GtkListItem::unselect-all  (GtkListItem *,
14556                                  gpointer);
14557 void GtkListItem::undo-selection        (GtkListItem *,
14558                                          gpointer);
14559 void GtkListItem::start-selection       (GtkListItem *,
14560                                          gpointer);
14561 void GtkListItem::end-selection (GtkListItem *,
14562                                  gpointer);
14563 void GtkListItem::toggle-add-mode       (GtkListItem *,
14564                                          gpointer);
14565 void GtkListItem::extend-selection      (GtkListItem *,
14566                                          GtkEnum,
14567                                          ggfloat,
14568                                          gboolean,
14569                                          gpointer);
14570 void GtkListItem::scroll-vertical       (GtkListItem *,
14571                                          GtkEnum,
14572                                          ggfloat,
14573                                          gpointer);
14574 void GtkListItem::scroll-horizontal     (GtkListItem *,
14575                                          GtkEnum,
14576                                          ggfloat,
14577                                          gpointer);
14578 </verb></tscreen>
14579
14580 <!-- ----------------------------------------------------------------- -->
14581 <sect1>GtkTreeItem
14582 <!-- ----------------------------------------------------------------- -->
14583 <p>
14584 <tscreen><verb>
14585 void GtkTreeItem::collapse      (GtkTreeItem *,
14586                                  gpointer);
14587 void GtkTreeItem::expand        (GtkTreeItem *,
14588                                  gpointer);
14589 </verb></tscreen>
14590
14591 <!-- ----------------------------------------------------------------- -->
14592 <sect1>GtkCheckMenuItem
14593 <!-- ----------------------------------------------------------------- -->
14594 <p>
14595 <tscreen><verb>
14596 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
14597                                  gpointer);
14598 </verb></tscreen>
14599
14600 <!-- ----------------------------------------------------------------- -->
14601 <sect1>GtkInputDialog
14602 <!-- ----------------------------------------------------------------- -->
14603 <p>
14604 <tscreen><verb>
14605 void GtkInputDialog::enable-device      (GtkInputDialog *,
14606                                          ggint,
14607                                          gpointer);
14608 void GtkInputDialog::disable-device     (GtkInputDialog *,
14609                                          ggint,
14610                                          gpointer);
14611 </verb></tscreen>
14612
14613 <!-- ----------------------------------------------------------------- -->
14614 <sect1>GtkColorSelection
14615 <!-- ----------------------------------------------------------------- -->
14616 <p>
14617 <tscreen><verb>
14618 void GtkColorSelection::color-changed   (GtkColorSelection *,
14619                                          gpointer);
14620 </verb></tscreen>
14621
14622 <!-- ----------------------------------------------------------------- -->
14623 <sect1>GtkStatusBar
14624 <!-- ----------------------------------------------------------------- -->
14625 <p>
14626 <tscreen><verb>
14627 void GtkStatusbar::text-pushed  (GtkStatusbar *,
14628                                  gguint,
14629                                  GtkString *,
14630                                  gpointer);
14631 void GtkStatusbar::text-popped  (GtkStatusbar *,
14632                                  gguint,
14633                                  GtkString *,
14634                                  gpointer);
14635 </verb></tscreen>
14636
14637 <!-- ----------------------------------------------------------------- -->
14638 <sect1>GtkCTree
14639 <!-- ----------------------------------------------------------------- -->
14640 <p>
14641 <tscreen><verb>
14642 void GtkCTree::tree-select-row  (GtkCTree *,
14643                                  GtkCTreeNode *,
14644                                  ggint,
14645                                  gpointer);
14646 void GtkCTree::tree-unselect-row        (GtkCTree *,
14647                                          GtkCTreeNode *,
14648                                          ggint,
14649                                          gpointer);
14650 void GtkCTree::tree-expand      (GtkCTree *,
14651                                  GtkCTreeNode *,
14652                                  gpointer);
14653 void GtkCTree::tree-collapse    (GtkCTree *,
14654                                  ggpointer,
14655                                  gpointer);
14656 void GtkCTree::tree-move        (GtkCTree *,
14657                                  GtkCTreeNode *,
14658                                  GtkCTreeNode *,
14659                                  GtkCTreeNode *,
14660                                  gpointer);
14661 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
14662                                                  GtkCTreeExpansionType,
14663                                                  gpointer);
14664 </verb></tscreen>
14665
14666 <!-- ----------------------------------------------------------------- -->
14667 <sect1>GtkCurve
14668 <!-- ----------------------------------------------------------------- -->
14669 <p>
14670 <tscreen><verb>
14671 void GtkCurve::curve-type-changed       (GtkCurve *,
14672                                          gpointer);
14673 </verb></tscreen>
14674
14675 <!-- ----------------------------------------------------------------- -->
14676 <sect1>GtkAdjustment
14677 <!-- ----------------------------------------------------------------- -->
14678 <p>
14679 <tscreen><verb>
14680 void GtkAdjustment::changed     (GtkAdjustment *,
14681                                  gpointer);
14682 void GtkAdjustment::value-changed       (GtkAdjustment *,
14683                                          gpointer);
14684 </verb></tscreen>
14685
14686 <!-- ***************************************************************** -->
14687 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
14688 <!-- ***************************************************************** -->
14689 <p>
14690 The follwing data types are passed into event handlers by GTK+. For
14691 each data type listed, the signals that use this data type are listed.
14692
14693 <itemize>
14694 <item>  GdkEvent
14695           <itemize>
14696           <item>drag_end_event
14697           </itemize>
14698
14699 <item>  GdkEventType
14700
14701 <item>  GdkEventAny
14702           <itemize>
14703           <item>delete_event
14704           <item>destroy_event
14705           <item>map_event
14706           <item>unmap_event
14707           <item>no_expose_event
14708           </itemize>
14709
14710 <item>  GdkEventExpose
14711           <itemize>
14712           <item>expose_event
14713           </itemize>
14714
14715 <item>  GdkEventNoExpose
14716
14717 <item>  GdkEventVisibility
14718
14719 <item>  GdkEventMotion
14720           <itemize>
14721           <item>motion_notify_event
14722           </itemize>
14723
14724 <item>  GdkEventButton
14725           <itemize>
14726           <item>button_press_event
14727           <item>button_release_event
14728           </itemize>
14729
14730 <item>  GdkEventKey
14731           <itemize>
14732           <item>key_press_event
14733           <item>key_release_event
14734           </itemize>
14735
14736 <item>  GdkEventCrossing
14737           <itemize>
14738           <item>enter_notify_event
14739           <item>leave_notify_event
14740           </itemize>
14741
14742 <item>  GdkEventFocus
14743           <itemize>
14744           <item>focus_in_event
14745           <item>focus_out_event
14746           </itemize>
14747
14748 <item>  GdkEventConfigure
14749           <itemize>
14750           <item>configure_event
14751           </itemize>
14752
14753 <item>  GdkEventProperty
14754           <itemize>
14755           <item>property_notify_event
14756           </itemize>
14757
14758 <item>  GdkEventSelection
14759           <itemize>
14760           <item>selection_clear_event
14761           <item>selection_request_event
14762           <item>selection_notify_event
14763           </itemize>
14764
14765 <item>  GdkEventProximity
14766           <itemize>
14767           <item>proximity_in_event
14768           <item>proximity_out_event
14769           </itemize>
14770
14771 <item>  GdkEventDragBegin
14772           <itemize>
14773           <item>drag_begin_event
14774           </itemize>
14775
14776 <item>  GdkEventDragRequest
14777           <itemize>
14778           <item>drag_request_event
14779           </itemize>
14780
14781 <item>  GdkEventDropEnter
14782           <itemize>
14783           <item>drop_enter_event
14784           </itemize>
14785
14786 <item>  GdkEventDropLeave
14787           <itemize>
14788           <item>drop_leave_event
14789           </itemize>
14790
14791 <item>  GdkEventDropDataAvailable
14792           <itemize>
14793           <item>drop_data_available_event
14794           </itemize>
14795
14796 <item>  GdkEventClient
14797           <itemize>
14798           <item>client_event
14799           </itemize>
14800
14801 <item>  GdkEventOther
14802           <itemize>
14803           <item>other_event
14804           </itemize>
14805 </itemize>
14806
14807 The data type <tt/GdkEventType/ is a special data type that is used by
14808 all the other data types as an indicator of the data type being passed
14809 to the signal handler. As you will see below, each of the event data
14810 structures has a member of this type. It is defined as an enumeration
14811 type as follows:
14812
14813 <tscreen><verb>
14814 typedef enum
14815 {
14816   GDK_NOTHING           = -1,
14817   GDK_DELETE            = 0,
14818   GDK_DESTROY           = 1,
14819   GDK_EXPOSE            = 2,
14820   GDK_MOTION_NOTIFY     = 3,
14821   GDK_BUTTON_PRESS      = 4,
14822   GDK_2BUTTON_PRESS     = 5,
14823   GDK_3BUTTON_PRESS     = 6,
14824   GDK_BUTTON_RELEASE    = 7,
14825   GDK_KEY_PRESS         = 8,
14826   GDK_KEY_RELEASE       = 9,
14827   GDK_ENTER_NOTIFY      = 10,
14828   GDK_LEAVE_NOTIFY      = 11,
14829   GDK_FOCUS_CHANGE      = 12,
14830   GDK_CONFIGURE         = 13,
14831   GDK_MAP               = 14,
14832   GDK_UNMAP             = 15,
14833   GDK_PROPERTY_NOTIFY   = 16,
14834   GDK_SELECTION_CLEAR   = 17,
14835   GDK_SELECTION_REQUEST = 18,
14836   GDK_SELECTION_NOTIFY  = 19,
14837   GDK_PROXIMITY_IN      = 20,
14838   GDK_PROXIMITY_OUT     = 21,
14839   GDK_DRAG_BEGIN        = 22,
14840   GDK_DRAG_REQUEST      = 23,
14841   GDK_DROP_ENTER        = 24,
14842   GDK_DROP_LEAVE        = 25,
14843   GDK_DROP_DATA_AVAIL   = 26,
14844   GDK_CLIENT_EVENT      = 27,
14845   GDK_VISIBILITY_NOTIFY = 28,
14846   GDK_NO_EXPOSE         = 29,
14847   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
14848 } GdkEventType;
14849 </verb></tscreen>
14850
14851 The other event type that is different from the others is
14852 <tt/GdkEvent/ itself. This is a union of all the other
14853 data types, which allows it to be cast to a specific
14854 event data type within a signal handler.
14855
14856 <!-- Just a big list for now, needs expanding upon - TRG -->
14857 So, the event data types are defined as follows:
14858
14859 <tscreen><verb>
14860 struct _GdkEventAny
14861 {
14862   GdkEventType type;
14863   GdkWindow *window;
14864   gint8 send_event;
14865 };
14866
14867 struct _GdkEventExpose
14868 {
14869   GdkEventType type;
14870   GdkWindow *window;
14871   gint8 send_event;
14872   GdkRectangle area;
14873   gint count; /* If non-zero, how many more events follow. */
14874 };
14875
14876 struct _GdkEventNoExpose
14877 {
14878   GdkEventType type;
14879   GdkWindow *window;
14880   gint8 send_event;
14881   /* XXX: does anyone need the X major_code or minor_code fields? */
14882 };
14883
14884 struct _GdkEventVisibility
14885 {
14886   GdkEventType type;
14887   GdkWindow *window;
14888   gint8 send_event;
14889   GdkVisibilityState state;
14890 };
14891
14892 struct _GdkEventMotion
14893 {
14894   GdkEventType type;
14895   GdkWindow *window;
14896   gint8 send_event;
14897   guint32 time;
14898   gdouble x;
14899   gdouble y;
14900   gdouble pressure;
14901   gdouble xtilt;
14902   gdouble ytilt;
14903   guint state;
14904   gint16 is_hint;
14905   GdkInputSource source;
14906   guint32 deviceid;
14907   gdouble x_root, y_root;
14908 };
14909
14910 struct _GdkEventButton
14911 {
14912   GdkEventType type;
14913   GdkWindow *window;
14914   gint8 send_event;
14915   guint32 time;
14916   gdouble x;
14917   gdouble y;
14918   gdouble pressure;
14919   gdouble xtilt;
14920   gdouble ytilt;
14921   guint state;
14922   guint button;
14923   GdkInputSource source;
14924   guint32 deviceid;
14925   gdouble x_root, y_root;
14926 };
14927
14928 struct _GdkEventKey
14929 {
14930   GdkEventType type;
14931   GdkWindow *window;
14932   gint8 send_event;
14933   guint32 time;
14934   guint state;
14935   guint keyval;
14936   gint length;
14937   gchar *string;
14938 };
14939
14940 struct _GdkEventCrossing
14941 {
14942   GdkEventType type;
14943   GdkWindow *window;
14944   gint8 send_event;
14945   GdkWindow *subwindow;
14946   GdkNotifyType detail;
14947 };
14948
14949 struct _GdkEventFocus
14950 {
14951   GdkEventType type;
14952   GdkWindow *window;
14953   gint8 send_event;
14954   gint16 in;
14955 };
14956
14957 struct _GdkEventConfigure
14958 {
14959   GdkEventType type;
14960   GdkWindow *window;
14961   gint8 send_event;
14962   gint16 x, y;
14963   gint16 width;
14964   gint16 height;
14965 };
14966
14967 struct _GdkEventProperty
14968 {
14969   GdkEventType type;
14970   GdkWindow *window;
14971   gint8 send_event;
14972   GdkAtom atom;
14973   guint32 time;
14974   guint state;
14975 };
14976
14977 struct _GdkEventSelection
14978 {
14979   GdkEventType type;
14980   GdkWindow *window;
14981   gint8 send_event;
14982   GdkAtom selection;
14983   GdkAtom target;
14984   GdkAtom property;
14985   guint32 requestor;
14986   guint32 time;
14987 };
14988
14989 /* This event type will be used pretty rarely. It only is important
14990    for XInput aware programs that are drawing their own cursor */
14991
14992 struct _GdkEventProximity
14993 {
14994   GdkEventType type;
14995   GdkWindow *window;
14996   gint8 send_event;
14997   guint32 time;
14998   GdkInputSource source;
14999   guint32 deviceid;
15000 };
15001
15002 struct _GdkEventDragRequest
15003 {
15004   GdkEventType type;
15005   GdkWindow *window;
15006   gint8 send_event;
15007   guint32 requestor;
15008   union {
15009     struct {
15010       guint protocol_version:4;
15011       guint sendreply:1;
15012       guint willaccept:1;
15013       guint delete_data:1; /* Do *not* delete if link is sent, only
15014                               if data is sent */
15015       guint senddata:1;
15016       guint reserved:22;
15017     } flags;
15018     glong allflags;
15019   } u;
15020   guint8 isdrop; /* This gdk event can be generated by a couple of
15021                     X events - this lets the app know whether the
15022                     drop really occurred or we just set the data */
15023
15024   GdkPoint drop_coords;
15025   gchar *data_type;
15026   guint32 timestamp;
15027 };
15028
15029 struct _GdkEventDragBegin
15030 {
15031   GdkEventType type;
15032   GdkWindow *window;
15033   gint8 send_event;
15034   union {
15035     struct {
15036       guint protocol_version:4;
15037       guint reserved:28;
15038     } flags;
15039     glong allflags;
15040   } u;
15041 };
15042
15043 struct _GdkEventDropEnter
15044 {
15045   GdkEventType type;
15046   GdkWindow *window;
15047   gint8 send_event;
15048   guint32 requestor;
15049   union {
15050     struct {
15051       guint protocol_version:4;
15052       guint sendreply:1;
15053       guint extended_typelist:1;
15054       guint reserved:26;
15055     } flags;
15056     glong allflags;
15057   } u;
15058 };
15059
15060 struct _GdkEventDropLeave
15061 {
15062   GdkEventType type;
15063   GdkWindow *window;
15064   gint8 send_event;
15065   guint32 requestor;
15066   union {
15067     struct {
15068       guint protocol_version:4;
15069       guint reserved:28;
15070     } flags;
15071     glong allflags;
15072   } u;
15073 };
15074
15075 struct _GdkEventDropDataAvailable
15076 {
15077   GdkEventType type;
15078   GdkWindow *window;
15079   gint8 send_event;
15080   guint32 requestor;
15081   union {
15082     struct {
15083       guint protocol_version:4;
15084       guint isdrop:1;
15085       guint reserved:25;
15086     } flags;
15087     glong allflags;
15088   } u;
15089   gchar *data_type; /* MIME type */
15090   gulong data_numbytes;
15091   gpointer data;
15092   guint32 timestamp;
15093   GdkPoint coords;
15094 };
15095
15096 struct _GdkEventClient
15097 {
15098   GdkEventType type;
15099   GdkWindow *window;
15100   gint8 send_event;
15101   GdkAtom message_type;
15102   gushort data_format;
15103   union {
15104     char b[20];
15105     short s[10];
15106     long l[5];
15107   } data;
15108 };
15109
15110 struct _GdkEventOther
15111 {
15112   GdkEventType type;
15113   GdkWindow *window;
15114   gint8 send_event;
15115   GdkXEvent *xevent;
15116 };
15117 </verb></tscreen>
15118
15119 <!-- ***************************************************************** -->
15120 <sect> Code Examples
15121 <!-- ***************************************************************** -->
15122 <p>
15123 Below are the code examples that are used in the above text
15124 which are not included in complete form elsewhere.
15125
15126 <!-- ----------------------------------------------------------------- -->
15127 <sect1>Tictactoe
15128 <!-- ----------------------------------------------------------------- -->
15129 <sect2>tictactoe.h
15130 <p>
15131 <tscreen><verb>
15132 /* example-start tictactoe tictactoe.h */
15133
15134 /* GTK - The GIMP Toolkit
15135  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15136  *
15137  * This library is free software; you can redistribute it and/or
15138  * modify it under the terms of the GNU Library General Public
15139  * License as published by the Free Software Foundation; either
15140  * version 2 of the License, or (at your option) any later version.
15141  *
15142  * This library is distributed in the hope that it will be useful,
15143  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15144  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15145  * Library General Public License for more details.
15146  *
15147  * You should have received a copy of the GNU Library General Public
15148  * License along with this library; if not, write to the
15149  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15150  * Boston, MA 02111-1307, USA.
15151  */
15152 #ifndef __TICTACTOE_H__
15153 #define __TICTACTOE_H__
15154
15155
15156 #include <gdk/gdk.h>
15157 #include <gtk/gtkvbox.h>
15158
15159
15160 #ifdef __cplusplus
15161 extern "C" {
15162 #endif /* __cplusplus */
15163
15164 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
15165 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
15166 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
15167
15168
15169 typedef struct _Tictactoe       Tictactoe;
15170 typedef struct _TictactoeClass  TictactoeClass;
15171
15172 struct _Tictactoe
15173 {
15174   GtkVBox vbox;
15175   
15176   GtkWidget *buttons[3][3];
15177 };
15178
15179 struct _TictactoeClass
15180 {
15181   GtkVBoxClass parent_class;
15182
15183   void (* tictactoe) (Tictactoe *ttt);
15184 };
15185
15186 guint          tictactoe_get_type        (void);
15187 GtkWidget*     tictactoe_new             (void);
15188 void           tictactoe_clear           (Tictactoe *ttt);
15189
15190 #ifdef __cplusplus
15191 }
15192 #endif /* __cplusplus */
15193
15194 #endif /* __TICTACTOE_H__ */
15195
15196 /* example-end */
15197 </verb></tscreen>
15198
15199 <!-- ----------------------------------------------------------------- -->
15200 <sect2>tictactoe.c
15201 <p>
15202 <tscreen><verb>
15203 /* example-start tictactoe tictactoe.c */
15204
15205 /* GTK - The GIMP Toolkit
15206  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15207  *
15208  * This library is free software; you can redistribute it and/or
15209  * modify it under the terms of the GNU Library General Public
15210  * License as published by the Free Software Foundation; either
15211  * version 2 of the License, or (at your option) any later version.
15212  *
15213  * This library is distributed in the hope that it will be useful,
15214  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15215  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15216  * Library General Public License for more details.
15217  *
15218  * You should have received a copy of the GNU Library General Public
15219  * License along with this library; if not, write to the
15220  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15221  * Boston, MA 02111-1307, USA.
15222  */
15223 #include "gtk/gtksignal.h"
15224 #include "gtk/gtktable.h"
15225 #include "gtk/gtktogglebutton.h"
15226 #include "tictactoe.h"
15227
15228 enum {
15229   TICTACTOE_SIGNAL,
15230   LAST_SIGNAL
15231 };
15232
15233 static void tictactoe_class_init          (TictactoeClass *klass);
15234 static void tictactoe_init                (Tictactoe      *ttt);
15235 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
15236
15237 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
15238
15239 guint
15240 tictactoe_get_type ()
15241 {
15242   static guint ttt_type = 0;
15243
15244   if (!ttt_type)
15245     {
15246       GtkTypeInfo ttt_info =
15247       {
15248         "Tictactoe",
15249         sizeof (Tictactoe),
15250         sizeof (TictactoeClass),
15251         (GtkClassInitFunc) tictactoe_class_init,
15252         (GtkObjectInitFunc) tictactoe_init,
15253         (GtkArgSetFunc) NULL,
15254         (GtkArgGetFunc) NULL
15255       };
15256
15257       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
15258     }
15259
15260   return ttt_type;
15261 }
15262
15263 static void
15264 tictactoe_class_init (TictactoeClass *class)
15265 {
15266   GtkObjectClass *object_class;
15267
15268   object_class = (GtkObjectClass*) class;
15269   
15270   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
15271                                          GTK_RUN_FIRST,
15272                                          object_class->type,
15273                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
15274                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
15275
15276
15277   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
15278
15279   class->tictactoe = NULL;
15280 }
15281
15282 static void
15283 tictactoe_init (Tictactoe *ttt)
15284 {
15285   GtkWidget *table;
15286   gint i,j;
15287   
15288   table = gtk_table_new (3, 3, TRUE);
15289   gtk_container_add (GTK_CONTAINER(ttt), table);
15290   gtk_widget_show (table);
15291
15292   for (i=0;i<3; i++)
15293     for (j=0;j<3; j++)
15294       {
15295         ttt->buttons[i][j] = gtk_toggle_button_new ();
15296         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
15297                                    i, i+1, j, j+1);
15298         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
15299                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
15300         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
15301         gtk_widget_show (ttt->buttons[i][j]);
15302       }
15303 }
15304
15305 GtkWidget*
15306 tictactoe_new ()
15307 {
15308   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
15309 }
15310
15311 void           
15312 tictactoe_clear (Tictactoe *ttt)
15313 {
15314   int i,j;
15315
15316   for (i=0;i<3;i++)
15317     for (j=0;j<3;j++)
15318       {
15319         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15320         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
15321                                      FALSE);
15322         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15323       }
15324 }
15325
15326 static void
15327 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
15328 {
15329   int i,k;
15330
15331   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15332                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15333                              { 0, 1, 2 }, { 0, 1, 2 } };
15334   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15335                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15336                              { 0, 1, 2 }, { 2, 1, 0 } };
15337
15338   int success, found;
15339
15340   for (k=0; k<8; k++)
15341     {
15342       success = TRUE;
15343       found = FALSE;
15344
15345       for (i=0;i<3;i++)
15346         {
15347           success = success &amp;&amp; 
15348             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
15349           found = found ||
15350             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
15351         }
15352       
15353       if (success &amp;&amp; found)
15354         {
15355           gtk_signal_emit (GTK_OBJECT (ttt), 
15356                            tictactoe_signals[TICTACTOE_SIGNAL]);
15357           break;
15358         }
15359     }
15360 }
15361
15362 /* example-end */
15363 </verb></tscreen>
15364
15365 <!-- ----------------------------------------------------------------- -->
15366 <sect2>ttt_test.c
15367 <p>
15368 <tscreen><verb>
15369 /* example-start tictactoe ttt_test.c */
15370
15371 #include <gtk/gtk.h>
15372 #include "tictactoe.h"
15373
15374 void
15375 win (GtkWidget *widget, gpointer data)
15376 {
15377   g_print ("Yay!\n");
15378   tictactoe_clear (TICTACTOE (widget));
15379 }
15380
15381 int 
15382 main (int argc, char *argv[])
15383 {
15384   GtkWidget *window;
15385   GtkWidget *ttt;
15386   
15387   gtk_init (&amp;argc, &amp;argv);
15388
15389   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15390   
15391   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
15392   
15393   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15394                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
15395   
15396   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15397
15398   ttt = tictactoe_new ();
15399   
15400   gtk_container_add (GTK_CONTAINER (window), ttt);
15401   gtk_widget_show (ttt);
15402
15403   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
15404                       GTK_SIGNAL_FUNC (win), NULL);
15405
15406   gtk_widget_show (window);
15407   
15408   gtk_main ();
15409   
15410   return 0;
15411 }
15412
15413 /* example-end */
15414 </verb></tscreen>
15415
15416 <!-- ----------------------------------------------------------------- -->
15417 <sect1> GtkDial
15418
15419 <!-- ----------------------------------------------------------------- -->
15420 <sect2> gtkdial.h
15421 <p>
15422 <tscreen><verb>
15423 /* example-start gtkdial gtkdial.h */
15424
15425 /* GTK - The GIMP Toolkit
15426  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15427  *
15428  * This library is free software; you can redistribute it and/or
15429  * modify it under the terms of the GNU Library General Public
15430  * License as published by the Free Software Foundation; either
15431  * version 2 of the License, or (at your option) any later version.
15432  *
15433  * This library is distributed in the hope that it will be useful,
15434  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15435  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15436  * Library General Public License for more details.
15437  *
15438  * You should have received a copy of the GNU Library General Public
15439  * License along with this library; if not, write to the
15440  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15441  * Boston, MA 02111-1307, USA.
15442  */
15443 #ifndef __GTK_DIAL_H__
15444 #define __GTK_DIAL_H__
15445
15446
15447 #include <gdk/gdk.h>
15448 #include <gtk/gtkadjustment.h>
15449 #include <gtk/gtkwidget.h>
15450
15451
15452 #ifdef __cplusplus
15453 extern "C" {
15454 #endif /* __cplusplus */
15455
15456
15457 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
15458 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
15459 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
15460
15461
15462 typedef struct _GtkDial        GtkDial;
15463 typedef struct _GtkDialClass   GtkDialClass;
15464
15465 struct _GtkDial
15466 {
15467   GtkWidget widget;
15468
15469   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
15470   guint policy : 2;
15471
15472   /* Button currently pressed or 0 if none */
15473   guint8 button;
15474
15475   /* Dimensions of dial components */
15476   gint radius;
15477   gint pointer_width;
15478
15479   /* ID of update timer, or 0 if none */
15480   guint32 timer;
15481
15482   /* Current angle */
15483   gfloat angle;
15484
15485   /* Old values from adjustment stored so we know when something changes */
15486   gfloat old_value;
15487   gfloat old_lower;
15488   gfloat old_upper;
15489
15490   /* The adjustment object that stores the data for this dial */
15491   GtkAdjustment *adjustment;
15492 };
15493
15494 struct _GtkDialClass
15495 {
15496   GtkWidgetClass parent_class;
15497 };
15498
15499
15500 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
15501 guint          gtk_dial_get_type               (void);
15502 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
15503 void           gtk_dial_set_update_policy      (GtkDial      *dial,
15504                                                 GtkUpdateType  policy);
15505
15506 void           gtk_dial_set_adjustment         (GtkDial      *dial,
15507                                                 GtkAdjustment *adjustment);
15508 #ifdef __cplusplus
15509 }
15510 #endif /* __cplusplus */
15511
15512
15513 #endif /* __GTK_DIAL_H__ */
15514 /* example-end */
15515 </verb></tscreen>
15516
15517 <!-- ----------------------------------------------------------------- -->
15518 <sect2> gtkdial.c
15519 <p>
15520 <tscreen><verb>
15521 /* example-start gtkdial gtkdial.c */
15522
15523 /* GTK - The GIMP Toolkit
15524  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15525  *
15526  * This library is free software; you can redistribute it and/or
15527  * modify it under the terms of the GNU Library General Public
15528  * License as published by the Free Software Foundation; either
15529  * version 2 of the License, or (at your option) any later version.
15530  *
15531  * This library is distributed in the hope that it will be useful,
15532  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15533  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15534  * Library General Public License for more details.
15535  *
15536  * You should have received a copy of the GNU Library General Public
15537  * License along with this library; if not, write to the
15538  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15539  * Boston, MA 02111-1307, USA.
15540  */
15541 #include <math.h>
15542 #include <stdio.h>
15543 #include <gtk/gtkmain.h>
15544 #include <gtk/gtksignal.h>
15545
15546 #include "gtkdial.h"
15547
15548 #define SCROLL_DELAY_LENGTH  300
15549 #define DIAL_DEFAULT_SIZE 100
15550
15551 /* Forward declarations */
15552
15553 static void gtk_dial_class_init               (GtkDialClass    *klass);
15554 static void gtk_dial_init                     (GtkDial         *dial);
15555 static void gtk_dial_destroy                  (GtkObject        *object);
15556 static void gtk_dial_realize                  (GtkWidget        *widget);
15557 static void gtk_dial_size_request             (GtkWidget      *widget,
15558                                                GtkRequisition *requisition);
15559 static void gtk_dial_size_allocate            (GtkWidget     *widget,
15560                                                GtkAllocation *allocation);
15561 static gint gtk_dial_expose                   (GtkWidget        *widget,
15562                                                 GdkEventExpose   *event);
15563 static gint gtk_dial_button_press             (GtkWidget        *widget,
15564                                                 GdkEventButton   *event);
15565 static gint gtk_dial_button_release           (GtkWidget        *widget,
15566                                                 GdkEventButton   *event);
15567 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
15568                                                 GdkEventMotion   *event);
15569 static gint gtk_dial_timer                    (GtkDial         *dial);
15570
15571 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
15572 static void gtk_dial_update                   (GtkDial *dial);
15573 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
15574                                                 gpointer          data);
15575 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
15576                                                 gpointer          data);
15577
15578 /* Local data */
15579
15580 static GtkWidgetClass *parent_class = NULL;
15581
15582 guint
15583 gtk_dial_get_type ()
15584 {
15585   static guint dial_type = 0;
15586
15587   if (!dial_type)
15588     {
15589       GtkTypeInfo dial_info =
15590       {
15591         "GtkDial",
15592         sizeof (GtkDial),
15593         sizeof (GtkDialClass),
15594         (GtkClassInitFunc) gtk_dial_class_init,
15595         (GtkObjectInitFunc) gtk_dial_init,
15596         (GtkArgSetFunc) NULL,
15597         (GtkArgGetFunc) NULL,
15598       };
15599
15600       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
15601     }
15602
15603   return dial_type;
15604 }
15605
15606 static void
15607 gtk_dial_class_init (GtkDialClass *class)
15608 {
15609   GtkObjectClass *object_class;
15610   GtkWidgetClass *widget_class;
15611
15612   object_class = (GtkObjectClass*) class;
15613   widget_class = (GtkWidgetClass*) class;
15614
15615   parent_class = gtk_type_class (gtk_widget_get_type ());
15616
15617   object_class->destroy = gtk_dial_destroy;
15618
15619   widget_class->realize = gtk_dial_realize;
15620   widget_class->expose_event = gtk_dial_expose;
15621   widget_class->size_request = gtk_dial_size_request;
15622   widget_class->size_allocate = gtk_dial_size_allocate;
15623   widget_class->button_press_event = gtk_dial_button_press;
15624   widget_class->button_release_event = gtk_dial_button_release;
15625   widget_class->motion_notify_event = gtk_dial_motion_notify;
15626 }
15627
15628 static void
15629 gtk_dial_init (GtkDial *dial)
15630 {
15631   dial->button = 0;
15632   dial->policy = GTK_UPDATE_CONTINUOUS;
15633   dial->timer = 0;
15634   dial->radius = 0;
15635   dial->pointer_width = 0;
15636   dial->angle = 0.0;
15637   dial->old_value = 0.0;
15638   dial->old_lower = 0.0;
15639   dial->old_upper = 0.0;
15640   dial->adjustment = NULL;
15641 }
15642
15643 GtkWidget*
15644 gtk_dial_new (GtkAdjustment *adjustment)
15645 {
15646   GtkDial *dial;
15647
15648   dial = gtk_type_new (gtk_dial_get_type ());
15649
15650   if (!adjustment)
15651     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
15652
15653   gtk_dial_set_adjustment (dial, adjustment);
15654
15655   return GTK_WIDGET (dial);
15656 }
15657
15658 static void
15659 gtk_dial_destroy (GtkObject *object)
15660 {
15661   GtkDial *dial;
15662
15663   g_return_if_fail (object != NULL);
15664   g_return_if_fail (GTK_IS_DIAL (object));
15665
15666   dial = GTK_DIAL (object);
15667
15668   if (dial->adjustment)
15669     gtk_object_unref (GTK_OBJECT (dial->adjustment));
15670
15671   if (GTK_OBJECT_CLASS (parent_class)->destroy)
15672     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
15673 }
15674
15675 GtkAdjustment*
15676 gtk_dial_get_adjustment (GtkDial *dial)
15677 {
15678   g_return_val_if_fail (dial != NULL, NULL);
15679   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
15680
15681   return dial->adjustment;
15682 }
15683
15684 void
15685 gtk_dial_set_update_policy (GtkDial      *dial,
15686                              GtkUpdateType  policy)
15687 {
15688   g_return_if_fail (dial != NULL);
15689   g_return_if_fail (GTK_IS_DIAL (dial));
15690
15691   dial->policy = policy;
15692 }
15693
15694 void
15695 gtk_dial_set_adjustment (GtkDial      *dial,
15696                           GtkAdjustment *adjustment)
15697 {
15698   g_return_if_fail (dial != NULL);
15699   g_return_if_fail (GTK_IS_DIAL (dial));
15700
15701   if (dial->adjustment)
15702     {
15703       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
15704       gtk_object_unref (GTK_OBJECT (dial->adjustment));
15705     }
15706
15707   dial->adjustment = adjustment;
15708   gtk_object_ref (GTK_OBJECT (dial->adjustment));
15709
15710   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
15711                       (GtkSignalFunc) gtk_dial_adjustment_changed,
15712                       (gpointer) dial);
15713   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
15714                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
15715                       (gpointer) dial);
15716
15717   dial->old_value = adjustment->value;
15718   dial->old_lower = adjustment->lower;
15719   dial->old_upper = adjustment->upper;
15720
15721   gtk_dial_update (dial);
15722 }
15723
15724 static void
15725 gtk_dial_realize (GtkWidget *widget)
15726 {
15727   GtkDial *dial;
15728   GdkWindowAttr attributes;
15729   gint attributes_mask;
15730
15731   g_return_if_fail (widget != NULL);
15732   g_return_if_fail (GTK_IS_DIAL (widget));
15733
15734   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
15735   dial = GTK_DIAL (widget);
15736
15737   attributes.x = widget->allocation.x;
15738   attributes.y = widget->allocation.y;
15739   attributes.width = widget->allocation.width;
15740   attributes.height = widget->allocation.height;
15741   attributes.wclass = GDK_INPUT_OUTPUT;
15742   attributes.window_type = GDK_WINDOW_CHILD;
15743   attributes.event_mask = gtk_widget_get_events (widget) | 
15744     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
15745     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
15746     GDK_POINTER_MOTION_HINT_MASK;
15747   attributes.visual = gtk_widget_get_visual (widget);
15748   attributes.colormap = gtk_widget_get_colormap (widget);
15749
15750   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
15751   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
15752
15753   widget->style = gtk_style_attach (widget->style, widget->window);
15754
15755   gdk_window_set_user_data (widget->window, widget);
15756
15757   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
15758 }
15759
15760 static void 
15761 gtk_dial_size_request (GtkWidget      *widget,
15762                        GtkRequisition *requisition)
15763 {
15764   requisition->width = DIAL_DEFAULT_SIZE;
15765   requisition->height = DIAL_DEFAULT_SIZE;
15766 }
15767
15768 static void
15769 gtk_dial_size_allocate (GtkWidget     *widget,
15770                         GtkAllocation *allocation)
15771 {
15772   GtkDial *dial;
15773
15774   g_return_if_fail (widget != NULL);
15775   g_return_if_fail (GTK_IS_DIAL (widget));
15776   g_return_if_fail (allocation != NULL);
15777
15778   widget->allocation = *allocation;
15779   dial = GTK_DIAL (widget);
15780
15781   if (GTK_WIDGET_REALIZED (widget))
15782     {
15783
15784       gdk_window_move_resize (widget->window,
15785                               allocation->x, allocation->y,
15786                               allocation->width, allocation->height);
15787
15788     }
15789   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
15790   dial->pointer_width = dial->radius / 5;
15791 }
15792
15793 static gint
15794 gtk_dial_expose (GtkWidget      *widget,
15795                  GdkEventExpose *event)
15796 {
15797   GtkDial *dial;
15798   GdkPoint points[3];
15799   gdouble s,c;
15800   gdouble theta;
15801   gint xc, yc;
15802   gint tick_length;
15803   gint i;
15804
15805   g_return_val_if_fail (widget != NULL, FALSE);
15806   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15807   g_return_val_if_fail (event != NULL, FALSE);
15808
15809   if (event->count > 0)
15810     return FALSE;
15811   
15812   dial = GTK_DIAL (widget);
15813
15814   gdk_window_clear_area (widget->window,
15815                          0, 0,
15816                          widget->allocation.width,
15817                          widget->allocation.height);
15818
15819   xc = widget->allocation.width/2;
15820   yc = widget->allocation.height/2;
15821
15822   /* Draw ticks */
15823
15824   for (i=0; i<25; i++)
15825     {
15826       theta = (i*M_PI/18. - M_PI/6.);
15827       s = sin(theta);
15828       c = cos(theta);
15829
15830       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
15831       
15832       gdk_draw_line (widget->window,
15833                      widget->style->fg_gc[widget->state],
15834                      xc + c*(dial->radius - tick_length),
15835                      yc - s*(dial->radius - tick_length),
15836                      xc + c*dial->radius,
15837                      yc - s*dial->radius);
15838     }
15839
15840   /* Draw pointer */
15841
15842   s = sin(dial->angle);
15843   c = cos(dial->angle);
15844
15845
15846   points[0].x = xc + s*dial->pointer_width/2;
15847   points[0].y = yc + c*dial->pointer_width/2;
15848   points[1].x = xc + c*dial->radius;
15849   points[1].y = yc - s*dial->radius;
15850   points[2].x = xc - s*dial->pointer_width/2;
15851   points[2].y = yc - c*dial->pointer_width/2;
15852
15853   gtk_draw_polygon (widget->style,
15854                     widget->window,
15855                     GTK_STATE_NORMAL,
15856                     GTK_SHADOW_OUT,
15857                     points, 3,
15858                     TRUE);
15859   
15860   return FALSE;
15861 }
15862
15863 static gint
15864 gtk_dial_button_press (GtkWidget      *widget,
15865                        GdkEventButton *event)
15866 {
15867   GtkDial *dial;
15868   gint dx, dy;
15869   double s, c;
15870   double d_parallel;
15871   double d_perpendicular;
15872
15873   g_return_val_if_fail (widget != NULL, FALSE);
15874   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15875   g_return_val_if_fail (event != NULL, FALSE);
15876
15877   dial = GTK_DIAL (widget);
15878
15879   /* Determine if button press was within pointer region - we 
15880      do this by computing the parallel and perpendicular distance of
15881      the point where the mouse was pressed from the line passing through
15882      the pointer */
15883   
15884   dx = event->x - widget->allocation.width / 2;
15885   dy = widget->allocation.height / 2 - event->y;
15886   
15887   s = sin(dial->angle);
15888   c = cos(dial->angle);
15889   
15890   d_parallel = s*dy + c*dx;
15891   d_perpendicular = fabs(s*dx - c*dy);
15892   
15893   if (!dial->button &amp;&amp;
15894       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
15895       (d_parallel > - dial->pointer_width))
15896     {
15897       gtk_grab_add (widget);
15898
15899       dial->button = event->button;
15900
15901       gtk_dial_update_mouse (dial, event->x, event->y);
15902     }
15903
15904   return FALSE;
15905 }
15906
15907 static gint
15908 gtk_dial_button_release (GtkWidget      *widget,
15909                           GdkEventButton *event)
15910 {
15911   GtkDial *dial;
15912
15913   g_return_val_if_fail (widget != NULL, FALSE);
15914   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15915   g_return_val_if_fail (event != NULL, FALSE);
15916
15917   dial = GTK_DIAL (widget);
15918
15919   if (dial->button == event->button)
15920     {
15921       gtk_grab_remove (widget);
15922
15923       dial->button = 0;
15924
15925       if (dial->policy == GTK_UPDATE_DELAYED)
15926         gtk_timeout_remove (dial->timer);
15927       
15928       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
15929           (dial->old_value != dial->adjustment->value))
15930         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15931     }
15932
15933   return FALSE;
15934 }
15935
15936 static gint
15937 gtk_dial_motion_notify (GtkWidget      *widget,
15938                          GdkEventMotion *event)
15939 {
15940   GtkDial *dial;
15941   GdkModifierType mods;
15942   gint x, y, mask;
15943
15944   g_return_val_if_fail (widget != NULL, FALSE);
15945   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15946   g_return_val_if_fail (event != NULL, FALSE);
15947
15948   dial = GTK_DIAL (widget);
15949
15950   if (dial->button != 0)
15951     {
15952       x = event->x;
15953       y = event->y;
15954
15955       if (event->is_hint || (event->window != widget->window))
15956         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
15957
15958       switch (dial->button)
15959         {
15960         case 1:
15961           mask = GDK_BUTTON1_MASK;
15962           break;
15963         case 2:
15964           mask = GDK_BUTTON2_MASK;
15965           break;
15966         case 3:
15967           mask = GDK_BUTTON3_MASK;
15968           break;
15969         default:
15970           mask = 0;
15971           break;
15972         }
15973
15974       if (mods &amp; mask)
15975         gtk_dial_update_mouse (dial, x,y);
15976     }
15977
15978   return FALSE;
15979 }
15980
15981 static gint
15982 gtk_dial_timer (GtkDial *dial)
15983 {
15984   g_return_val_if_fail (dial != NULL, FALSE);
15985   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
15986
15987   if (dial->policy == GTK_UPDATE_DELAYED)
15988     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
15989
15990   return FALSE;
15991 }
15992
15993 static void
15994 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
15995 {
15996   gint xc, yc;
15997   gfloat old_value;
15998
15999   g_return_if_fail (dial != NULL);
16000   g_return_if_fail (GTK_IS_DIAL (dial));
16001
16002   xc = GTK_WIDGET(dial)->allocation.width / 2;
16003   yc = GTK_WIDGET(dial)->allocation.height / 2;
16004
16005   old_value = dial->adjustment->value;
16006   dial->angle = atan2(yc-y, x-xc);
16007
16008   if (dial->angle < -M_PI/2.)
16009     dial->angle += 2*M_PI;
16010
16011   if (dial->angle < -M_PI/6)
16012     dial->angle = -M_PI/6;
16013
16014   if (dial->angle > 7.*M_PI/6.)
16015     dial->angle = 7.*M_PI/6.;
16016
16017   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
16018     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
16019
16020   if (dial->adjustment->value != old_value)
16021     {
16022       if (dial->policy == GTK_UPDATE_CONTINUOUS)
16023         {
16024           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16025         }
16026       else
16027         {
16028           gtk_widget_draw (GTK_WIDGET(dial), NULL);
16029
16030           if (dial->policy == GTK_UPDATE_DELAYED)
16031             {
16032               if (dial->timer)
16033                 gtk_timeout_remove (dial->timer);
16034
16035               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
16036                                              (GtkFunction) gtk_dial_timer,
16037                                              (gpointer) dial);
16038             }
16039         }
16040     }
16041 }
16042
16043 static void
16044 gtk_dial_update (GtkDial *dial)
16045 {
16046   gfloat new_value;
16047   
16048   g_return_if_fail (dial != NULL);
16049   g_return_if_fail (GTK_IS_DIAL (dial));
16050
16051   new_value = dial->adjustment->value;
16052   
16053   if (new_value < dial->adjustment->lower)
16054     new_value = dial->adjustment->lower;
16055
16056   if (new_value > dial->adjustment->upper)
16057     new_value = dial->adjustment->upper;
16058
16059   if (new_value != dial->adjustment->value)
16060     {
16061       dial->adjustment->value = new_value;
16062       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16063     }
16064
16065   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
16066     (dial->adjustment->upper - dial->adjustment->lower);
16067
16068   gtk_widget_draw (GTK_WIDGET(dial), NULL);
16069 }
16070
16071 static void
16072 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
16073                               gpointer       data)
16074 {
16075   GtkDial *dial;
16076
16077   g_return_if_fail (adjustment != NULL);
16078   g_return_if_fail (data != NULL);
16079
16080   dial = GTK_DIAL (data);
16081
16082   if ((dial->old_value != adjustment->value) ||
16083       (dial->old_lower != adjustment->lower) ||
16084       (dial->old_upper != adjustment->upper))
16085     {
16086       gtk_dial_update (dial);
16087
16088       dial->old_value = adjustment->value;
16089       dial->old_lower = adjustment->lower;
16090       dial->old_upper = adjustment->upper;
16091     }
16092 }
16093
16094 static void
16095 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
16096                                     gpointer       data)
16097 {
16098   GtkDial *dial;
16099
16100   g_return_if_fail (adjustment != NULL);
16101   g_return_if_fail (data != NULL);
16102
16103   dial = GTK_DIAL (data);
16104
16105   if (dial->old_value != adjustment->value)
16106     {
16107       gtk_dial_update (dial);
16108
16109       dial->old_value = adjustment->value;
16110     }
16111 }
16112 /* example-end */
16113 </verb></tscreen>
16114
16115 <!-- ----------------------------------------------------------------- -->
16116 <sect1> Scribble
16117 <p>
16118 <tscreen><verb>
16119 /* example-start scribble-simple scribble-simple.c */
16120
16121 /* GTK - The GIMP Toolkit
16122  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16123  *
16124  * This library is free software; you can redistribute it and/or
16125  * modify it under the terms of the GNU Library General Public
16126  * License as published by the Free Software Foundation; either
16127  * version 2 of the License, or (at your option) any later version.
16128  *
16129  * This library is distributed in the hope that it will be useful,
16130  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16131  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16132  * Library General Public License for more details.
16133  *
16134  * You should have received a copy of the GNU Library General Public
16135  * License along with this library; if not, write to the
16136  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16137  * Boston, MA 02111-1307, USA.
16138  */
16139
16140 #include <gtk/gtk.h>
16141
16142 /* Backing pixmap for drawing area */
16143 static GdkPixmap *pixmap = NULL;
16144
16145 /* Create a new backing pixmap of the appropriate size */
16146 static gint
16147 configure_event (GtkWidget *widget, GdkEventConfigure *event)
16148 {
16149   if (pixmap)
16150     gdk_pixmap_unref(pixmap);
16151
16152   pixmap = gdk_pixmap_new(widget->window,
16153                           widget->allocation.width,
16154                           widget->allocation.height,
16155                           -1);
16156   gdk_draw_rectangle (pixmap,
16157                       widget->style->white_gc,
16158                       TRUE,
16159                       0, 0,
16160                       widget->allocation.width,
16161                       widget->allocation.height);
16162
16163   return TRUE;
16164 }
16165
16166 /* Redraw the screen from the backing pixmap */
16167 static gint
16168 expose_event (GtkWidget *widget, GdkEventExpose *event)
16169 {
16170   gdk_draw_pixmap(widget->window,
16171                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
16172                   pixmap,
16173                   event->area.x, event->area.y,
16174                   event->area.x, event->area.y,
16175                   event->area.width, event->area.height);
16176
16177   return FALSE;
16178 }
16179
16180 /* Draw a rectangle on the screen */
16181 static void
16182 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
16183 {
16184   GdkRectangle update_rect;
16185
16186   update_rect.x = x - 5;
16187   update_rect.y = y - 5;
16188   update_rect.width = 10;
16189   update_rect.height = 10;
16190   gdk_draw_rectangle (pixmap,
16191                       widget->style->black_gc,
16192                       TRUE,
16193                       update_rect.x, update_rect.y,
16194                       update_rect.width, update_rect.height);
16195   gtk_widget_draw (widget, &amp;update_rect);
16196 }
16197
16198 static gint
16199 button_press_event (GtkWidget *widget, GdkEventButton *event)
16200 {
16201   if (event->button == 1 &amp;&amp; pixmap != NULL)
16202     draw_brush (widget, event->x, event->y);
16203
16204   return TRUE;
16205 }
16206
16207 static gint
16208 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
16209 {
16210   int x, y;
16211   GdkModifierType state;
16212
16213   if (event->is_hint)
16214     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
16215   else
16216     {
16217       x = event->x;
16218       y = event->y;
16219       state = event->state;
16220     }
16221     
16222   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
16223     draw_brush (widget, x, y);
16224   
16225   return TRUE;
16226 }
16227
16228 void
16229 quit ()
16230 {
16231   gtk_exit (0);
16232 }
16233
16234 int
16235 main (int argc, char *argv[])
16236 {
16237   GtkWidget *window;
16238   GtkWidget *drawing_area;
16239   GtkWidget *vbox;
16240
16241   GtkWidget *button;
16242
16243   gtk_init (&amp;argc, &amp;argv);
16244
16245   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16246   gtk_widget_set_name (window, "Test Input");
16247
16248   vbox = gtk_vbox_new (FALSE, 0);
16249   gtk_container_add (GTK_CONTAINER (window), vbox);
16250   gtk_widget_show (vbox);
16251
16252   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16253                       GTK_SIGNAL_FUNC (quit), NULL);
16254
16255   /* Create the drawing area */
16256
16257   drawing_area = gtk_drawing_area_new ();
16258   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
16259   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16260
16261   gtk_widget_show (drawing_area);
16262
16263   /* Signals used to handle backing pixmap */
16264
16265   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
16266                       (GtkSignalFunc) expose_event, NULL);
16267   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
16268                       (GtkSignalFunc) configure_event, NULL);
16269
16270   /* Event signals */
16271
16272   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
16273                       (GtkSignalFunc) motion_notify_event, NULL);
16274   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
16275                       (GtkSignalFunc) button_press_event, NULL);
16276
16277   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16278                          | GDK_LEAVE_NOTIFY_MASK
16279                          | GDK_BUTTON_PRESS_MASK
16280                          | GDK_POINTER_MOTION_MASK
16281                          | GDK_POINTER_MOTION_HINT_MASK);
16282
16283   /* .. And a quit button */
16284   button = gtk_button_new_with_label ("Quit");
16285   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16286
16287   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
16288                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
16289                              GTK_OBJECT (window));
16290   gtk_widget_show (button);
16291
16292   gtk_widget_show (window);
16293
16294   gtk_main ();
16295
16296   return 0;
16297 }
16298 /* example-end */
16299 </verb></tscreen>
16300
16301 <!-- ***************************************************************** -->
16302 <sect> List Widget
16303 <!-- ***************************************************************** -->
16304 <p>
16305 NOTE: The GtkList widget has been superseded by the GtkCList
16306 widget. It is detailed here just for completeness.
16307
16308 The GtkList widget is designed to act as a vertical container for
16309 widgets that should be of the type GtkListItem.
16310
16311 A GtkList widget has its own window to receive events and its own
16312 background color which is usually white. As it is directly derived
16313 from a GtkContainer it can be treated as such by using the
16314 GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
16315 this. One should already be familiar with the usage of a GList and
16316 its related functions g_list_*() to be able to use the GtkList widget
16317 to it full extent.
16318
16319 There is one field inside the structure definition of the GtkList
16320 widget that will be of greater interest to us, this is:
16321
16322 <tscreen><verb>
16323 struct _GtkList
16324 {
16325   ...
16326   GList *selection;
16327   guint selection_mode;
16328   ...
16329 }; 
16330 </verb></tscreen>
16331
16332 The selection field of a GtkList points to a linked list of all items
16333 that are currently selected, or NULL if the selection is empty.  So to
16334 learn about the current selection we read the GTK_LIST()->selection
16335 field, but do not modify it since the internal fields are maintained
16336 by the gtk_list_*() functions.
16337
16338 The selection_mode of the GtkList determines the selection facilities
16339 of a GtkList and therefore the contents of the GTK_LIST()->selection
16340 field. The selection_mode may be one of the following:
16341
16342 <itemize>
16343 <item> GTK_SELECTION_SINGLE - The selection is either NULL
16344                         or contains a GList pointer
16345                         for a single selected item.
16346
16347 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list
16348                         contains no widgets or insensitive
16349                         ones only, otherwise it contains
16350                         a GList pointer for one GList
16351                         structure, and therefore exactly
16352                         one list item.
16353
16354 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list
16355                         items are selected or a GList pointer
16356                         for the first selected item. That
16357                         in turn points to a GList structure
16358                         for the second selected item and so
16359                         on.
16360
16361 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
16362 </itemize>
16363
16364 The default is GTK_SELECTION_MULTIPLE.
16365
16366 <!-- ----------------------------------------------------------------- -->
16367 <sect1> Signals
16368 <p>
16369 <tscreen><verb>
16370 void selection_changed( GtkList *list );
16371 </verb></tscreen>
16372
16373 This signal will be invoked whenever the selection field of a GtkList
16374 has changed. This happens when a child of the GtkList got selected or
16375 deselected.
16376
16377 <tscreen><verb>
16378 void select_child( GtkList   *list,
16379                    GtkWidget *child);
16380 </verb></tscreen>
16381
16382 This signal is invoked when a child of the GtkList is about to get
16383 selected. This happens mainly on calls to gtk_list_select_item(),
16384 gtk_list_select_child(), button presses and sometimes indirectly
16385 triggered on some else occasions where children get added to or
16386 removed from the GtkList.
16387
16388 <tscreen><verb>
16389 void unselect_child( GtkList   *list,
16390                      GtkWidget *child );
16391 </verb></tscreen>
16392
16393 This signal is invoked when a child of the GtkList is about to get
16394 deselected. This happens mainly on calls to gtk_list_unselect_item(),
16395 gtk_list_unselect_child(), button presses and sometimes indirectly
16396 triggered on some else occasions where children get added to or
16397 removed from the GtkList.
16398
16399 <!-- ----------------------------------------------------------------- -->
16400 <sect1> Functions
16401 <p>
16402 <tscreen><verb>
16403 guint gtk_list_get_type( void );
16404 </verb></tscreen>
16405
16406 Returns the `GtkList' type identifier.
16407
16408 <tscreen><verb>
16409 GtkWidget *gtk_list_new( void );
16410 </verb></tscreen>
16411
16412 Create a new GtkList object. The new widget is returned as a pointer
16413 to a GtkWidget object. NULL is returned on failure.
16414
16415 <tscreen><verb>
16416 void gtk_list_insert_items( GtkList *list,
16417                             GList   *items,
16418                             gint     position );
16419 </verb></tscreen>
16420
16421 Insert list items into the list, starting at <tt/position/.
16422 <tt/items/ is a doubly linked list where each nodes data pointer is
16423 expected to point to a newly created GtkListItem.  The GList nodes of
16424 <tt/items/ are taken over by the list.
16425
16426 <tscreen><verb>
16427 void gtk_list_append_items( GtkList *list,
16428                             GList   *items);
16429 </verb></tscreen>
16430
16431 Insert list items just like gtk_list_insert_items() at the end of the
16432 list. The GList nodes of <tt/items/ are taken over by the list.
16433
16434 <tscreen><verb>
16435 void gtk_list_prepend_items( GtkList *list,
16436                              GList   *items);
16437 </verb></tscreen>
16438
16439 Insert list items just like gtk_list_insert_items() at the very
16440 beginning of the list. The GList nodes of <tt/items/ are taken over by
16441 the list.
16442
16443 <tscreen><verb>
16444 void gtk_list_remove_items( GtkList *list,
16445                             GList   *items);
16446 </verb></tscreen>
16447
16448 Remove list items from the list. <tt/items/ is a doubly linked list
16449 where each nodes data pointer is expected to point to a direct child
16450 of list. It is the callers responsibility to make a call to
16451 g_list_free(items) afterwards. Also the caller has to destroy the list
16452 items himself.
16453
16454 <tscreen><verb>
16455 void gtk_list_clear_items( GtkList *list,
16456                            gint start,
16457                            gint end );
16458 </verb></tscreen>
16459
16460 Remove and destroy list items from the list. A widget is affected if
16461 its current position within the list is in the range specified by
16462 <tt/start/ and <tt/end/.
16463
16464 <tscreen><verb>
16465 void gtk_list_select_item( GtkList *list,
16466                            gint     item );
16467 </verb></tscreen>
16468
16469 Invoke the select_child signal for a list item specified through its
16470 current position within the list.
16471
16472 <tscreen><verb>
16473 void gtk_list_unselect_item( GtkList *list,
16474                              gint     item);
16475 </verb></tscreen>
16476
16477 Invoke the unselect_child signal for a list item specified through its
16478 current position within the list.
16479
16480 <tscreen><verb>
16481 void gtk_list_select_child( GtkList *list,
16482                             GtkWidget *child);
16483 </verb></tscreen>
16484
16485 Invoke the select_child signal for the specified child.
16486
16487 <tscreen><verb>
16488 void gtk_list_unselect_child( GtkList   *list,
16489                               GtkWidget *child);
16490 </verb></tscreen>
16491
16492 Invoke the unselect_child signal for the specified child.
16493
16494 <tscreen><verb>
16495 gint gtk_list_child_position( GtkList *list,
16496                               GtkWidget *child);
16497 </verb></tscreen>
16498
16499 Return the position of <tt/child/ within the list. "-1" is returned on
16500 failure.
16501
16502 <tscreen><verb>
16503 void gtk_list_set_selection_mode( GtkList         *list,
16504                                   GtkSelectionMode mode );
16505 </verb></tscreen>
16506
16507 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
16508 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
16509 GTK_SELECTION_EXTENDED.
16510
16511 <tscreen><verb>
16512 GtkList *GTK_LIST( gpointer obj );
16513 </verb></tscreen>
16514
16515 Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
16516 more info.
16517
16518 <tscreen><verb>
16519 GtkListClass *GTK_LIST_CLASS( gpointer class);
16520 </verb></tscreen>
16521
16522 Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
16523 for more info.
16524
16525 <tscreen><verb>
16526 gint GTK_IS_LIST( gpointer obj);
16527 </verb></tscreen>
16528
16529 Determine if a generic pointer refers to a `GtkList' object. *Note
16530 Standard Macros::, for more info.
16531
16532 <!-- ----------------------------------------------------------------- -->
16533 <sect1> Example
16534 <p>
16535 Following is an example program that will print out the changes of the
16536 selection of a GtkList, and lets you "arrest" list items into a prison
16537 by selecting them with the rightmost mouse button.
16538
16539 <tscreen><verb>
16540 /* example-start list list.c */
16541
16542 /* Include the gtk+ header files
16543  * Include stdio.h, we need that for the printf() function
16544  */
16545 #include        <gtk/gtk.h>
16546 #include        <stdio.h>
16547
16548 /* This is our data identification string to store
16549  * data in list items
16550  */
16551 const gchar *list_item_data_key="list_item_data";
16552
16553
16554 /* prototypes for signal handler that we are going to connect
16555  * to the GtkList widget
16556  */
16557 static void  sigh_print_selection( GtkWidget *gtklist,
16558                                    gpointer   func_data);
16559
16560 static void  sigh_button_event( GtkWidget      *gtklist,
16561                                 GdkEventButton *event,
16562                                 GtkWidget      *frame );
16563
16564
16565 /* Main function to set up the user interface */
16566
16567 gint main (int    argc,
16568            gchar *argv[])
16569 {                                  
16570     GtkWidget *separator;
16571     GtkWidget *window;
16572     GtkWidget *vbox;
16573     GtkWidget *scrolled_window;
16574     GtkWidget *frame;
16575     GtkWidget *gtklist;
16576     GtkWidget *button;
16577     GtkWidget *list_item;
16578     GList *dlist;
16579     guint i;
16580     gchar buffer[64];
16581     
16582     
16583     /* Initialize gtk+ (and subsequently gdk) */
16584
16585     gtk_init(&amp;argc, &amp;argv);
16586     
16587     
16588     /* Create a window to put all the widgets in
16589      * connect gtk_main_quit() to the "destroy" event of
16590      * the window to handle window manager close-window-events
16591      */
16592     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
16593     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
16594     gtk_signal_connect(GTK_OBJECT(window),
16595                        "destroy",
16596                        GTK_SIGNAL_FUNC(gtk_main_quit),
16597                        NULL);
16598     
16599     
16600     /* Inside the window we need a box to arrange the widgets
16601      * vertically */
16602     vbox=gtk_vbox_new(FALSE, 5);
16603     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
16604     gtk_container_add(GTK_CONTAINER(window), vbox);
16605     gtk_widget_show(vbox);
16606     
16607     /* This is the scrolled window to put the GtkList widget inside */
16608     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
16609     gtk_widget_set_usize(scrolled_window, 250, 150);
16610     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
16611     gtk_widget_show(scrolled_window);
16612     
16613     /* Create the GtkList widget.
16614      * Connect the sigh_print_selection() signal handler
16615      * function to the "selection_changed" signal of the GtkList
16616      * to print out the selected items each time the selection
16617      * has changed */
16618     gtklist=gtk_list_new();
16619     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
16620                                            gtklist);
16621     gtk_widget_show(gtklist);
16622     gtk_signal_connect(GTK_OBJECT(gtklist),
16623                        "selection_changed",
16624                        GTK_SIGNAL_FUNC(sigh_print_selection),
16625                        NULL);
16626     
16627     /* We create a "Prison" to put a list item in ;) */
16628     frame=gtk_frame_new("Prison");
16629     gtk_widget_set_usize(frame, 200, 50);
16630     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
16631     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
16632     gtk_container_add(GTK_CONTAINER(vbox), frame);
16633     gtk_widget_show(frame);
16634     
16635     /* Connect the sigh_button_event() signal handler to the GtkList
16636      * which will handle the "arresting" of list items
16637      */
16638     gtk_signal_connect(GTK_OBJECT(gtklist),
16639                        "button_release_event",
16640                        GTK_SIGNAL_FUNC(sigh_button_event),
16641                        frame);
16642     
16643     /* Create a separator */
16644     separator=gtk_hseparator_new();
16645     gtk_container_add(GTK_CONTAINER(vbox), separator);
16646     gtk_widget_show(separator);
16647     
16648     /* Finally create a button and connect it's "clicked" signal
16649      * to the destruction of the window */
16650     button=gtk_button_new_with_label("Close");
16651     gtk_container_add(GTK_CONTAINER(vbox), button);
16652     gtk_widget_show(button);
16653     gtk_signal_connect_object(GTK_OBJECT(button),
16654                               "clicked",
16655                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
16656                               GTK_OBJECT(window));
16657     
16658     
16659     /* Now we create 5 list items, each having it's own
16660      * label and add them to the GtkList using gtk_container_add()
16661      * Also we query the text string from the label and
16662      * associate it with the list_item_data_key for each list item
16663      */
16664     for (i=0; i<5; i++) {
16665         GtkWidget       *label;
16666         gchar           *string;
16667         
16668         sprintf(buffer, "ListItemContainer with Label #%d", i);
16669         label=gtk_label_new(buffer);
16670         list_item=gtk_list_item_new();
16671         gtk_container_add(GTK_CONTAINER(list_item), label);
16672         gtk_widget_show(label);
16673         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
16674         gtk_widget_show(list_item);
16675         gtk_label_get(GTK_LABEL(label), &amp;string);
16676         gtk_object_set_data(GTK_OBJECT(list_item),
16677                             list_item_data_key,
16678                             string);
16679     }
16680     /* Here, we are creating another 5 labels, this time
16681      * we use gtk_list_item_new_with_label() for the creation
16682      * we can't query the text string from the label because
16683      * we don't have the labels pointer and therefore
16684      * we just associate the list_item_data_key of each
16685      * list item with the same text string.
16686      * For adding of the list items we put them all into a doubly
16687      * linked list (GList), and then add them by a single call to
16688      * gtk_list_append_items().
16689      * Because we use g_list_prepend() to put the items into the
16690      * doubly linked list, their order will be descending (instead
16691      * of ascending when using g_list_append())
16692      */
16693     dlist=NULL;
16694     for (; i<10; i++) {
16695         sprintf(buffer, "List Item with Label %d", i);
16696         list_item=gtk_list_item_new_with_label(buffer);
16697         dlist=g_list_prepend(dlist, list_item);
16698         gtk_widget_show(list_item);
16699         gtk_object_set_data(GTK_OBJECT(list_item),
16700                             list_item_data_key,
16701                             "ListItem with integrated Label");
16702     }
16703     gtk_list_append_items(GTK_LIST(gtklist), dlist);
16704     
16705     /* Finally we want to see the window, don't we? ;) */
16706     gtk_widget_show(window);
16707     
16708     /* Fire up the main event loop of gtk */
16709     gtk_main();
16710     
16711     /* We get here after gtk_main_quit() has been called which
16712      * happens if the main window gets destroyed
16713      */
16714     return(0);
16715 }
16716
16717 /* This is the signal handler that got connected to button
16718  * press/release events of the GtkList
16719  */
16720 void sigh_button_event( GtkWidget      *gtklist,
16721                         GdkEventButton *event,
16722                         GtkWidget      *frame )
16723 {
16724     /* We only do something if the third (rightmost mouse button
16725      * was released
16726      */
16727     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
16728         event->button==3) {
16729         GList           *dlist, *free_list;
16730         GtkWidget       *new_prisoner;
16731         
16732         /* Fetch the currently selected list item which
16733          * will be our next prisoner ;)
16734          */
16735         dlist=GTK_LIST(gtklist)->selection;
16736         if (dlist)
16737                 new_prisoner=GTK_WIDGET(dlist->data);
16738         else
16739                 new_prisoner=NULL;
16740         
16741         /* Look for already imprisoned list items, we
16742          * will put them back into the list.
16743          * Remember to free the doubly linked list that
16744          * gtk_container_children() returns
16745          */
16746         dlist=gtk_container_children(GTK_CONTAINER(frame));
16747         free_list=dlist;
16748         while (dlist) {
16749             GtkWidget       *list_item;
16750             
16751             list_item=dlist->data;
16752             
16753             gtk_widget_reparent(list_item, gtklist);
16754             
16755             dlist=dlist->next;
16756         }
16757         g_list_free(free_list);
16758         
16759         /* If we have a new prisoner, remove him from the
16760          * GtkList and put him into the frame "Prison".
16761          * We need to unselect the item first.
16762          */
16763         if (new_prisoner) {
16764             GList   static_dlist;
16765             
16766             static_dlist.data=new_prisoner;
16767             static_dlist.next=NULL;
16768             static_dlist.prev=NULL;
16769             
16770             gtk_list_unselect_child(GTK_LIST(gtklist),
16771                                     new_prisoner);
16772             gtk_widget_reparent(new_prisoner, frame);
16773         }
16774     }
16775 }
16776
16777 /* This is the signal handler that gets called if GtkList
16778  * emits the "selection_changed" signal
16779  */
16780 void sigh_print_selection( GtkWidget *gtklist,
16781                            gpointer   func_data)
16782 {
16783     GList   *dlist;
16784     
16785     /* Fetch the doubly linked list of selected items
16786      * of the GtkList, remember to treat this as read-only!
16787      */
16788     dlist=GTK_LIST(gtklist)->selection;
16789     
16790     /* If there are no selected items there is nothing more
16791      * to do than just telling the user so
16792      */
16793     if (!dlist) {
16794         g_print("Selection cleared\n");
16795         return;
16796     }
16797     /* Ok, we got a selection and so we print it
16798      */
16799     g_print("The selection is a ");
16800     
16801     /* Get the list item from the doubly linked list
16802      * and then query the data associated with list_item_data_key.
16803      * We then just print it */
16804     while (dlist) {
16805         GtkObject       *list_item;
16806         gchar           *item_data_string;
16807         
16808         list_item=GTK_OBJECT(dlist->data);
16809         item_data_string=gtk_object_get_data(list_item,
16810                                              list_item_data_key);
16811         g_print("%s ", item_data_string);
16812         
16813         dlist=dlist->next;
16814     }
16815     g_print("\n");
16816 }
16817 /* example-end */
16818 </verb></tscreen>
16819
16820 <!-- ----------------------------------------------------------------- -->
16821 <sect1> List Item Widget
16822 <p>
16823 The GtkListItem widget is designed to act as a container holding up to
16824 one child, providing functions for selection/deselection just like the
16825 GtkList widget requires them for its children.
16826
16827 A GtkListItem has its own window to receive events and has its own
16828 background color which is usually white.
16829
16830 As it is directly derived from a GtkItem it can be treated as such by
16831 using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
16832 this. Usually a GtkListItem just holds a label to identify e.g. a
16833 filename within a GtkList -- therefore the convenience function
16834 gtk_list_item_new_with_label() is provided. The same effect can be
16835 achieved by creating a GtkLabel on its own, setting its alignment to
16836 xalign=0 and yalign=0.5 with a subsequent container addition to the
16837 GtkListItem.
16838
16839 As one is not forced to add a GtkLabel to a GtkListItem, you could
16840 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
16841
16842 <!-- ----------------------------------------------------------------- -->
16843 <sect1> Signals
16844 <p>
16845 A GtkListItem does not create new signals on its own, but inherits
16846 the signals of a GtkItem. *Note GtkItem::, for more info.
16847
16848 <!-- ----------------------------------------------------------------- -->
16849 <sect1> Functions
16850 <p>
16851 <tscreen><verb>
16852 guint gtk_list_item_get_type( void );
16853 </verb></tscreen>
16854
16855 Returns the `GtkListItem' type identifier.
16856
16857 <tscreen><verb>
16858 GtkWidget *gtk_list_item_new( void );
16859 </verb></tscreen>
16860
16861 Create a new GtkListItem object. The new widget is returned as a
16862 pointer to a GtkWidget object. NULL is returned on failure.
16863
16864 <tscreen><verb>
16865 GtkWidget *gtk_list_item_new_with_label( gchar *label );
16866 </verb></tscreen>
16867
16868 Create a new GtkListItem object, having a single GtkLabel as the sole
16869 child. The new widget is returned as a pointer to a GtkWidget
16870 object. NULL is returned on failure.
16871
16872 <tscreen><verb>
16873 void gtk_list_item_select( GtkListItem *list_item );
16874 </verb></tscreen>
16875
16876 This function is basically a wrapper around a call to gtk_item_select
16877 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
16878 GtkItem::, for more info.
16879
16880 <tscreen><verb>
16881 void gtk_list_item_deselect( GtkListItem *list_item );
16882 </verb></tscreen>
16883
16884 This function is basically a wrapper around a call to
16885 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
16886 signal.  *Note GtkItem::, for more info.
16887
16888 <tscreen><verb>
16889 GtkListItem *GTK_LIST_ITEM( gpointer obj );
16890 </verb></tscreen>
16891
16892 Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
16893 more info.
16894
16895 <tscreen><verb>
16896 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
16897 </verb></tscreen>
16898
16899 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
16900 for more info.
16901
16902 <tscreen><verb>
16903 gint GTK_IS_LIST_ITEM( gpointer obj );
16904 </verb></tscreen>
16905
16906 Determine if a generic pointer refers to a `GtkListItem' object.
16907 *Note Standard Macros::, for more info.
16908  
16909 <!-- ----------------------------------------------------------------- -->
16910 <sect1> Example
16911 <p>
16912 Please see the GtkList example on this, which covers the usage of a
16913 GtkListItem as well.
16914
16915
16916 </article>