]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
- Heavily edited GtkCombo section initially from Christopher T. Lansdown
[~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.2 Tutorial
9 <author>
10 Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
11                               name="&lt;gale@gtk.org&gt;"></tt>
12 Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
13                               name="&lt;imain@gtk.org&gt;"></tt>,
14 <date>February 7th, 1999
15 <abstract>
16 This is a tutorial on how to use GTK (the GIMP Toolkit) through its C
17 interface.
18 </abstract>
19
20 <!-- Table of contents -->
21 <!-- Older versions of this tutorial did not have a table of contents,
22      but the tutorial is now so large that having one is very useful. -->
23 <toc>
24  
25
26 <!-- ***************************************************************** -->
27 <sect>Introduction
28 <!-- ***************************************************************** -->
29 <p>
30 GTK (GIMP Toolkit) is a library for creating graphical user
31 interfaces. It is licensed using the LGPL license, so you can develop
32 open software, free software, or even commercial non-free software
33 using GTK without having to spend anything for licenses or royalties.
34
35 It's called the GIMP toolkit because it was originally written for
36 developing the General Image Manipulation Program (GIMP), but GTK has
37 now been used in a large number of software projects, including the
38 GNU Network Object Model Environment (GNOME) project. GTK is built on
39 top of GDK (GIMP Drawing Kit) which is basically a wrapper around the
40 low-level functions for accessing the underlying windowing functions
41 (Xlib in the case of X windows). The primary authors of GTK are:
42
43 <itemize>
44 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
45                            name="petm@xcf.berkeley.edu"></tt>
46 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
47                            name="spencer@xcf.berkeley.edu"></tt>
48 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
49                            name="jmacd@xcf.berkeley.edu"></tt>
50 </itemize>
51
52 GTK is essentially an object oriented application programmers
53 interface (API). Although written completely in C, it is implemented
54 using the idea of classes and callback functions (pointers to
55 functions).
56
57 There is also a third component called glib which contains a few
58 replacements for some standard calls, as well as some additional
59 functions for handling linked lists etc. The replacement functions are
60 used to increase GTK's portability, as some of the functions
61 implemented here are not available or are nonstandard on other unixes
62 such as g_strerror(). Some also contain enhancements to the libc
63 versions, such as g_malloc that has enhanced debugging utilities.
64
65 This tutorial describes the C interface to GTK. There are GTK
66 bindings for many other languages including C++, Guile, Perl, Python,
67 TOM, Ada95, Objective C, Free Pascal, and Eiffel. If you intend to
68 use another language's bindings to GTK, look at that binding's
69 documentation first. In some cases that documentation may describe
70 some important conventions (which you should know first) and then
71 refer you back to this tutorial. There are also some cross-platform
72 APIs (such as wxWindows and V) which use GTK as one of their target
73 platforms; again, consult their documentation first.
74
75 If you're developing your GTK application in C++, a few extra notes
76 are in order. There's a C++ binding to GTK called GTK--, which
77 provides a more C++-like interface to GTK; you should probably look
78 into this instead. If you don't like that approach for whatever
79 reason, there are two alternatives for using GTK. First, you can use
80 only the C subset of C++ when interfacing with GTK and then use the C
81 interface as described in this tutorial. Second, you can use GTK and
82 C++ together by declaring all callbacks as static functions in C++
83 classes, and again calling GTK using its C interface. If you choose
84 this last approach, you can include as the callback's data value a
85 pointer to the object to be manipulated (the so-called "this" value).
86 Selecting between these options is simply a matter of preference,
87 since in all three approaches you get C++ and GTK. None of these
88 approaches requires the use of a specialized preprocessor, so no
89 matter what you choose you can use standard C++ with GTK.
90
91 This tutorial is an attempt to document as much as possible of GTK,
92 but it is by no means complete. This tutorial assumes a good
93 understanding of C, and how to create C programs. It would be a great
94 benefit for the reader to have previous X programming experience, but
95 it shouldn't be necessary. If you are learning GTK as your first
96 widget set, please comment on how you found this tutorial, and what
97 you had trouble with. Note that there is also a C++ API for GTK
98 (GTK--) in the works, so if you prefer to use C++, you should look
99 into this instead. There are also Objective C, ADA, Guile and other
100 language bindings available, but I don't follow these.
101
102 This document is a 'work in progress'. Please look for updates on
103 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
104 name="http://www.gtk.org/">.
105
106 I would very much like to hear of any problems you have learning GTK
107 from this document, and would appreciate input as to how it may be
108 improved. Please see the section on <ref id="sec_Contributing"
109 name="Contributing"> for further information.
110
111 <!-- ***************************************************************** -->
112 <sect>Getting Started
113 <!-- ***************************************************************** -->
114
115 <p>
116 The first thing to do of course, is download the GTK source and
117 install it. You can always get the latest version from ftp.gtk.org in
118 /pub/gtk. You can also view other sources of GTK information on
119 http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
120 name="http://www.gtk.org/">. GTK uses GNU autoconf for configuration.
121 Once untar'd, type ./configure --help to see a list of options.
122
123 Th GTK source distribution also contains the complete source to all of
124 the examples used in this tutorial, along with Makefiles to aid
125 compilation.
126
127 To begin our introduction to GTK, we'll start with the simplest
128 program possible. This program will create a 200x200 pixel window and
129 has no way of exiting except to be killed using the shell.
130
131 <tscreen><verb>
132 /* example-start base base.c */
133
134 #include <gtk/gtk.h>
135
136 int main( int   argc,
137           char *argv[] )
138 {
139     GtkWidget *window;
140     
141     gtk_init (&amp;argc, &amp;argv);
142     
143     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
144     gtk_widget_show  (window);
145     
146     gtk_main ();
147     
148     return(0);
149 }
150 /* example-end */
151 </verb></tscreen>
152
153 You can compile the above program with gcc using:
154 <tscreen><verb>
155 gcc base.c -o base `gtk-config --cflags --libs`
156 </verb></tscreen>
157
158 The meaning of the unusual compilation options is explained below.
159
160 All programs will of course include gtk/gtk.h which declares the
161 variables, functions, structures etc. that will be used in your GTK
162 application.
163
164 The next line:
165
166 <tscreen><verb>
167 gtk_init (&amp;argc, &amp;argv);
168 </verb></tscreen>
169
170 calls the function gtk_init(gint *argc, gchar ***argv) which will be
171 called in all GTK applications. This sets up a few things for us such
172 as the default visual and color map and then proceeds to call
173 gdk_init(gint *argc, gchar ***argv). This function initializes the
174 library for use, sets up default signal handlers, and checks the
175 arguments passed to your application on the command line, looking for
176 one of the following:
177
178 <itemize>
179 <item> <tt/--gtk-module/
180 <item> <tt/--g-fatal-warnings/
181 <item> <tt/--gtk-debug/
182 <item> <tt/--gtk-no-debug/
183 <item> <tt/--gdk-debug/
184 <item> <tt/--gdk-no-debug/
185 <item> <tt/--display/
186 <item> <tt/--sync/
187 <item> <tt/--no-xshm/
188 <item> <tt/--name/
189 <item> <tt/--class/
190 </itemize>
191
192 It removes these from the argument list, leaving anything it does not
193 recognize for your application to parse or ignore. This creates a set
194 of standard arguments accepted by all GTK applications.
195
196 The next two lines of code create and display a window.
197
198 <tscreen><verb>
199   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
200   gtk_widget_show (window);
201 </verb></tscreen>
202
203 The GTK_WINDOW_TOPLEVEL argument specifies that we want the window to
204 undergo window manager decoration and placement. Rather than create a
205 window of 0x0 size, a window without children is set to 200x200 by
206 default so you can still manipulate it.
207
208 The gtk_widget_show() function lets GTK know that we are done setting
209 the attributes of this widget, and that it can display it.
210
211 The last line enters the GTK main processing loop.
212
213 <tscreen><verb>
214   gtk_main ();
215 </verb></tscreen>
216
217 gtk_main() is another call you will see in every GTK application.
218 When control reaches this point, GTK will sleep waiting for X events
219 (such as button or key presses), timeouts, or file IO notifications to
220 occur. In our simple example however, events are ignored.
221
222 <!-- ----------------------------------------------------------------- -->
223 <sect1>Hello World in GTK
224 <p>
225 Now for a program with a widget (a button).  It's the classic
226 hello world a la GTK.
227
228 <tscreen><verb>
229 /* example-start helloworld helloworld.c */
230
231 #include <gtk/gtk.h>
232
233 /* This is a callback function. The data arguments are ignored
234  * in this example. More on callbacks below. */
235 void hello( GtkWidget *widget,
236             gpointer   data )
237 {
238     g_print ("Hello World\n");
239 }
240
241 gint delete_event( GtkWidget *widget,
242                    GdkEvent  *event,
243                    gpointer   data )
244 {
245     /* If you return FALSE in the "delete_event" signal handler,
246      * GTK will emit the "destroy" signal. Returning TRUE means
247      * you don't want the window to be destroyed.
248      * This is useful for popping up 'are you sure you want to quit?'
249      * type dialogs. */
250
251     g_print ("delete event occurred\n");
252
253     /* Change TRUE to FALSE and the main window will be destroyed with
254      * a "delete_event". */
255
256     return(TRUE);
257 }
258
259 /* Another callback */
260 void destroy( GtkWidget *widget,
261               gpointer   data )
262 {
263     gtk_main_quit();
264 }
265
266 int main( int   argc,
267           char *argv[] )
268 {
269     /* GtkWidget is the storage type for widgets */
270     GtkWidget *window;
271     GtkWidget *button;
272     
273     /* This is called in all GTK applications. Arguments are parsed
274      * from the command line and are returned to the application. */
275     gtk_init(&amp;argc, &amp;argv);
276     
277     /* create a new window */
278     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
279     
280     /* When the window is given the "delete_event" signal (this is given
281      * by the window manager, usually by the 'close' option, or on the
282      * titlebar), we ask it to call the delete_event () function
283      * as defined above. The data passed to the callback
284      * function is NULL and is ignored in the callback function. */
285     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
286                         GTK_SIGNAL_FUNC (delete_event), NULL);
287     
288     /* Here we connect the "destroy" event to a signal handler.  
289      * This event occurs when we call gtk_widget_destroy() on the window,
290      * or if we return 'FALSE' in the "delete_event" callback. */
291     gtk_signal_connect (GTK_OBJECT (window), "destroy",
292                         GTK_SIGNAL_FUNC (destroy), NULL);
293     
294     /* Sets the border width of the window. */
295     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
296     
297     /* Creates a new button with the label "Hello World". */
298     button = gtk_button_new_with_label ("Hello World");
299     
300     /* When the button receives the "clicked" signal, it will call the
301      * function hello() passing it NULL as its argument.  The hello()
302      * function is defined above. */
303     gtk_signal_connect (GTK_OBJECT (button), "clicked",
304                         GTK_SIGNAL_FUNC (hello), NULL);
305     
306     /* This will cause the window to be destroyed by calling
307      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
308      * signal could come from here, or the window manager. */
309     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
310                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
311                                GTK_OBJECT (window));
312     
313     /* This packs the button into the window (a gtk container). */
314     gtk_container_add (GTK_CONTAINER (window), button);
315     
316     /* The final step is to display this newly created widget. */
317     gtk_widget_show (button);
318     
319     /* and the window */
320     gtk_widget_show (window);
321     
322     /* All GTK applications must have a gtk_main(). Control ends here
323      * and waits for an event to occur (like a key press or
324      * mouse event). */
325     gtk_main ();
326     
327     return(0);
328 }
329 /* example-end */
330 </verb></tscreen>
331
332 <!-- ----------------------------------------------------------------- -->
333 <sect1>Compiling Hello World
334 <p>
335 To compile use:
336
337 <tscreen><verb>
338 gcc -Wall -g helloworld.c -o helloworld `gtk-config --cflags` \
339     `gtk-config --libs`
340 </verb></tscreen>
341
342 This uses the program <tt>gtk-config</>, which comes with gtk. This
343 program 'knows' what compiler switches are needed to compile programs
344 that use gtk. <tt>gtk-config --cflags</> will output a list of include
345 directories for the compiler to look in, and <tt>gtk-config --libs</>
346 will output the list of libraries for the compiler to link with and
347 the directories to find them in. In the aboce example they could have
348 been combined into a single instance, such as
349 `gtk-config --cflags --libs`.
350
351 Note that the type of single quote used in the compile command above
352 is significant.
353
354 The libraries that are usually linked in are:
355 <itemize>
356 <item>The GTK library (-lgtk), the widget library, based on top of GDK.
357 <item>The GDK library (-lgdk), the Xlib wrapper.
358 <item>The gmodule library (-lgmodule), which is used to load run time
359 extensions.
360 <item>The glib library (-lglib), containing miscellaneous functions, only
361 g_print() is used in this particular example. GTK is built on top
362 of glib so you will always require this library. See the section on 
363 <ref id="sec_glib" name="glib"> for details.
364 <item>The Xlib library (-lX11) which is used by GDK.
365 <item>The Xext library (-lXext). This contains code for shared memory
366 pixmaps and other X extensions.
367 <item>The math library (-lm). This is used by GTK for various purposes.
368 </itemize>
369
370 <!-- ----------------------------------------------------------------- -->
371 <sect1>Theory of Signals and Callbacks
372 <p>
373 Before we look in detail at <em>helloworld</em>, we'll discuss signals
374 and callbacks. GTK is an event driven toolkit, which means it will
375 sleep in gtk_main until an event occurs and control is passed to the
376 appropriate function.
377
378 This passing of control is done using the idea of "signals". When an
379 event occurs, such as the press of a mouse button, the appropriate
380 signal will be "emitted" by the widget that was pressed.  This is how
381 GTK does most of its useful work. There are a set of signals that all
382 widgets inherit, such as "destroy", and there are signals that are
383 widget specific, such as "toggled" on a toggle button.
384
385 To make a button perform an action, we set up a signal handler to
386 catch these signals and call the appropriate function. This is done by
387 using a function such as:
388
389 <tscreen><verb>
390 gint gtk_signal_connect( GtkObject     *object,
391                          gchar         *name,
392                          GtkSignalFunc  func,
393                          gpointer       func_data );
394 </verb></tscreen>
395
396 Where the first argument is the widget which will be emitting the
397 signal, and the second, the name of the signal you wish to catch. The
398 third is the function you wish to be called when it is caught, and the
399 fourth, the data you wish to have passed to this function.
400
401 The function specified in the third argument is called a "callback
402 function", and should generally be of the form:
403
404 <tscreen><verb>
405 void callback_func( GtkWidget *widget,
406                     gpointer   callback_data );
407 </verb></tscreen>
408
409 Where the first argument will be a pointer to the widget that emitted
410 the signal, and the second, a pointer to the data given as the last
411 argument to the gtk_signal_connect() function as shown above.
412
413 Note that the above form for a signal callback function declaration is
414 only a general guide, as some widget specific signals generate
415 different calling parameters. For example, the GtkCList "select_row"
416 signal provides both row and column parameters.
417
418 Another call used in the <em>helloworld</em> example, is:
419
420 <tscreen><verb>
421 gint gtk_signal_connect_object( GtkObject     *object,
422                                 gchar         *name,
423                                 GtkSignalFunc  func,
424                                 GtkObject     *slot_object );
425 </verb></tscreen>
426
427 gtk_signal_connect_object() is the same as gtk_signal_connect() except
428 that the callback function only uses one argument, a pointer to a GTK
429 object. So when using this function to connect signals, the callback
430 should be of the form:
431
432 <tscreen><verb>
433 void callback_func( GtkObject *object );
434 </verb></tscreen>
435
436 Where the object is usually a widget. We usually don't setup callbacks
437 for gtk_signal_connect_object however. They are usually used to call a
438 GTK function that accepts a single widget or object as an argument, as
439 is the case in our <em>helloworld</em> example.
440
441 The purpose of having two functions to connect signals is simply to
442 allow the callbacks to have a different number of arguments. Many
443 functions in the GTK library accept only a single GtkWidget pointer as
444 an argument, so you want to use the gtk_signal_connect_object() for
445 these, whereas for your functions, you may need to have additional
446 data supplied to the callbacks.
447
448 <!-- ----------------------------------------------------------------- -->
449 <sect1>Events
450 <p>
451 In addition to the signal mechanism described above, there are a set
452 of <em>events</em> that reflect the X event mechanism. Callbacks may
453 also be attached to these events. These events are:
454
455 <itemize>
456 <item> event
457 <item> button_press_event
458 <item> button_release_event
459 <item> motion_notify_event
460 <item> delete_event
461 <item> destroy_event
462 <item> expose_event
463 <item> key_press_event
464 <item> key_release_event
465 <item> enter_notify_event
466 <item> leave_notify_event
467 <item> configure_event
468 <item> focus_in_event
469 <item> focus_out_event
470 <item> map_event
471 <item> unmap_event
472 <item> property_notify_event
473 <item> selection_clear_event
474 <item> selection_request_event
475 <item> selection_notify_event
476 <item> proximity_in_event
477 <item> proximity_out_event
478 <item> drag_begin_event
479 <item> drag_request_event
480 <item> drag_end_event
481 <item> drop_enter_event
482 <item> drop_leave_event
483 <item> drop_data_available_event
484 <item> other_event
485 </itemize>
486
487 In order to connect a callback function to one of these events, you
488 use the function gtk_signal_connect, as described above, using one of
489 the above event names as the <tt/name/ parameter. The callback
490 function for events has a slightly different form than that for
491 signals:
492
493 <tscreen><verb>
494 void callback_func( GtkWidget *widget,
495                     GdkEvent  *event,
496                     gpointer   callback_data );
497 </verb></tscreen>
498
499 GdkEvent is a C <tt/union/ structure whose type will depend upon which
500 of the above events has occurred. In order for us to tell which event
501 has been issued each of the possible alternatives has a <tt/type/
502 parameter which reflects the event being issued. The other components
503 of the event structure will depend upon the type of the
504 event. Possible values for the type are:
505
506 <tscreen><verb>
507   GDK_NOTHING
508   GDK_DELETE
509   GDK_DESTROY
510   GDK_EXPOSE
511   GDK_MOTION_NOTIFY
512   GDK_BUTTON_PRESS
513   GDK_2BUTTON_PRESS
514   GDK_3BUTTON_PRESS
515   GDK_BUTTON_RELEASE
516   GDK_KEY_PRESS
517   GDK_KEY_RELEASE
518   GDK_ENTER_NOTIFY
519   GDK_LEAVE_NOTIFY
520   GDK_FOCUS_CHANGE
521   GDK_CONFIGURE
522   GDK_MAP
523   GDK_UNMAP
524   GDK_PROPERTY_NOTIFY
525   GDK_SELECTION_CLEAR
526   GDK_SELECTION_REQUEST
527   GDK_SELECTION_NOTIFY
528   GDK_PROXIMITY_IN
529   GDK_PROXIMITY_OUT
530   GDK_DRAG_BEGIN
531   GDK_DRAG_REQUEST
532   GDK_DROP_ENTER
533   GDK_DROP_LEAVE
534   GDK_DROP_DATA_AVAIL
535   GDK_CLIENT_EVENT
536   GDK_VISIBILITY_NOTIFY
537   GDK_NO_EXPOSE
538   GDK_OTHER_EVENT       /* Deprecated, use filters instead */
539 </verb></tscreen>
540
541 So, to connect a callback function to one of these events we would use
542 something like:
543
544 <tscreen><verb>
545 gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
546                     GTK_SIGNAL_FUNC(button_press_callback), 
547                         NULL);
548 </verb></tscreen>
549
550 This assumes that <tt/button/ is a GtkButton widget. Now, when the
551 mouse is over the button and a mouse button is pressed, the function
552 <tt/button_press_callback/ will be called. This function may be
553 declared as:
554
555 <tscreen><verb>
556 static gint button_press_event (GtkWidget      *widget, 
557                                 GdkEventButton *event,
558                                 gpointer        data);
559 </verb></tscreen>
560
561 Note that we can declare the second argument as type
562 <tt/GdkEventButton/ as we know what type of event will occur for this
563 function to be called.
564
565 The value returned from this function indicates whether the event
566 should be propagated further by the GTK event handling
567 mechanism. Returning TRUE indicates that the event has been handled,
568 and that it should not propagate further. Returning FALSE continues
569 the normal event handling.  See the section on
570 <ref id="sec_Adv_Events_and_Signals"
571 name="Advanced Event and Signal Handling"> for more details on this
572 propagation process.
573
574 For details on the GdkEvent data types, see the appendix entitled
575 <ref id="sec_GDK_Event_Types" name="GDK Event Types">.
576
577 <!-- ----------------------------------------------------------------- -->
578 <sect1>Stepping Through Hello World
579 <p>
580 Now that we know the theory behind this, lets clarify by walking through 
581 the example <em>helloworld</em> program.
582
583 Here is the callback function that will be called when the button is
584 "clicked". We ignore both the widget and the data in this example, but
585 it is not hard to do things with them. The next example will use the
586 data argument to tell us which button was pressed.
587
588 <tscreen><verb>
589 void hello( GtkWidget *widget,
590             gpointer   data )
591 {
592     g_print ("Hello World\n");
593 }
594 </verb></tscreen>
595
596 The next callback is a bit special. The "delete_event" occurs when the
597 window manager sends this event to the application. We have a choice
598 here as to what to do about these events. We can ignore them, make
599 some sort of response, or simply quit the application.
600
601 The value you return in this callback lets GTK know what action to
602 take.  By returning TRUE, we let it know that we don't want to have
603 the "destroy" signal emitted, keeping our application running. By
604 returning FALSE, we ask that "destroy" is emitted, which in turn will
605 call our "destroy" signal handler.
606
607 <tscreen><verb>
608 gint delete_event( GtkWidget *widget,
609                    GdkEvent  *event,
610                    gpointer   data )
611 {
612     g_print ("delete event occurred\n");
613
614     return (TRUE); 
615 }
616 </verb></tscreen>
617
618 Here is another callback function which causes the program to quit by
619 calling gtk_main_quit(). This function tells GTK that it is to exit
620 from gtk_main when control is returned to it.
621
622 <tscreen><verb>
623 void destroy( GtkWidget *widget,
624               gpointer   data )
625 {
626     gtk_main_quit ();
627 }
628 </verb></tscreen>
629
630 I assume you know about the main() function... yes, as with other
631 applications, all GTK applications will also have one of these.
632
633 <tscreen><verb>
634 int main( int   argc,
635           char *argv[] )
636 {
637 </verb></tscreen>
638
639 This next part, declares a pointer to a structure of type
640 GtkWidget. These are used below to create a window and a button.
641
642 <tscreen><verb>
643     GtkWidget *window;
644     GtkWidget *button;
645 </verb></tscreen>
646
647 Here is our gtk_init again. As before, this initializes the toolkit,
648 and parses the arguments found on the command line. Any argument it
649 recognizes from the command line, it removes from the list, and
650 modifies argc and argv to make it look like they never existed,
651 allowing your application to parse the remaining arguments.
652
653 <tscreen><verb>
654     gtk_init (&amp;argc, &amp;argv);
655 </verb></tscreen>
656
657 Create a new window. This is fairly straight forward. Memory is
658 allocated for the GtkWidget *window structure so it now points to a
659 valid structure. It sets up a new window, but it is not displayed
660 until we call gtk_widget_show(window) near the end of our program.
661
662 <tscreen><verb>
663     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
664 </verb></tscreen>
665
666 Here is an example of connecting a signal handler to an object, in
667 this case, the window. Here, the "destroy" signal is caught. This is
668 emitted when we use the window manager to kill the window (and we
669 return FALSE in the "delete_event" handler), or when we use the
670 gtk_widget_destroy() call passing in the window widget as the object
671 to destroy. By setting this up, we handle both cases with a single
672 call. Here, it just calls the destroy() function defined above with a
673 NULL argument, which quits GTK for us.
674
675 The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform type
676 casting and checking for us, as well as aid the readability of the
677 code.
678
679 <tscreen><verb>
680     gtk_signal_connect (GTK_OBJECT (window), "destroy",
681                         GTK_SIGNAL_FUNC (destroy), NULL);
682 </verb></tscreen>
683
684 This next function is used to set an attribute of a container object.
685 This just sets the window so it has a blank area along the inside of
686 it 10 pixels wide where no widgets will go. There are other similar
687 functions which we will look at in the section on
688 <ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
689
690 And again, GTK_CONTAINER is a macro to perform type casting.
691
692 <tscreen><verb>
693     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
694 </verb></tscreen>
695
696 This call creates a new button. It allocates space for a new GtkWidget
697 structure in memory, initializes it, and makes the button pointer
698 point to it. It will have the label "Hello World" on it when
699 displayed.
700
701 <tscreen><verb>
702     button = gtk_button_new_with_label ("Hello World");
703 </verb></tscreen>
704
705 Here, we take this button, and make it do something useful. We attach
706 a signal handler to it so when it emits the "clicked" signal, our
707 hello() function is called. The data is ignored, so we simply pass in
708 NULL to the hello() callback function. Obviously, the "clicked" signal
709 is emitted when we click the button with our mouse pointer.
710
711 <tscreen><verb>
712     gtk_signal_connect (GTK_OBJECT (button), "clicked",
713                         GTK_SIGNAL_FUNC (hello), NULL);
714 </verb></tscreen>
715
716 We are also going to use this button to exit our program. This will
717 illustrate how the "destroy" signal may come from either the window
718 manager, or our program. When the button is "clicked", same as above,
719 it calls the first hello() callback function, and then this one in the
720 order they are set up. You may have as many callback functions as you
721 need, and all will be executed in the order you connected
722 them. Because the gtk_widget_destroy() function accepts only a
723 GtkWidget *widget as an argument, we use the
724 gtk_signal_connect_object() function here instead of straight
725 gtk_signal_connect().
726
727 <tscreen><verb>
728     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
729                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
730                                GTK_OBJECT (window));
731 </verb></tscreen>
732
733 This is a packing call, which will be explained in depth later on. But
734 it is fairly easy to understand. It simply tells GTK that the button
735 is to be placed in the window where it will be displayed. Note that a
736 GTK container can only contain one widget. There are other widgets,
737 that are described later, which are designed to layout multiple
738 widgets in various ways.
739  
740 <tscreen><verb>
741     gtk_container_add (GTK_CONTAINER (window), button);
742 </verb></tscreen>
743
744 Now we have everything set up the way we want it to be. With all the
745 signal handlers in place, and the button placed in the window where it
746 should be, we ask GTK to "show" the widgets on the screen. The window
747 widget is shown last so the whole window will pop up at once rather
748 than seeing the window pop up, and then the button form inside of
749 it. Although with such a simple example, you'd never notice.
750
751 <tscreen><verb>
752     gtk_widget_show (button);
753
754     gtk_widget_show (window);
755 </verb></tscreen>
756
757 And of course, we call gtk_main() which waits for events to come from
758 the X server and will call on the widgets to emit signals when these
759 events come.
760
761 <tscreen><verb>
762     gtk_main ();
763 </verb></tscreen>
764
765 And the final return. Control returns here after gtk_quit() is called.
766
767 <tscreen><verb>
768     return 0;
769 </verb></tscreen>
770
771 Now, when we click the mouse button on a GTK button, the widget emits
772 a "clicked" signal. In order for us to use this information, our
773 program sets up a signal handler to catch that signal, which
774 dispatches the function of our choice. In our example, when the button
775 we created is "clicked", the hello() function is called with a NULL
776 argument, and then the next handler for this signal is called. This
777 calls the gtk_widget_destroy() function, passing it the window widget
778 as its argument, destroying the window widget. This causes the window
779 to emit the "destroy" signal, which is caught, and calls our destroy()
780 callback function, which simply exits GTK.
781
782 Another course of events, is to use the window manager to kill the
783 window. This will cause the "delete_event" to be emitted. This will
784 call our "delete_event" handler. If we return TRUE here, the window
785 will be left as is and nothing will happen. Returning FALSE will cause
786 GTK to emit the "destroy" signal which of course, calls the "destroy"
787 callback, exiting GTK.
788
789 Note that these signals are not the same as the Unix system signals,
790 and are not implemented using them, although the terminology is almost
791 identical.
792
793 <!-- ***************************************************************** -->
794 <sect>Moving On
795 <!-- ***************************************************************** -->
796
797 <!-- ----------------------------------------------------------------- -->
798 <sect1>Data Types
799 <p>
800 There are a few things you probably noticed in the previous examples
801 that need explaining. The gint, gchar etc. that you see are typedefs
802 to int and char respectively. This is done to get around that nasty
803 dependency on the size of simple data types when doing calculations.
804
805 A good example is "gint32" which will be typedef'd to a 32 bit integer
806 for any given platform, whether it be the 64 bit alpha, or the 32 bit
807 i386. The typedefs are very straight forward and intuitive. They are
808 all defined in glib/glib.h (which gets included from gtk.h).
809
810 You'll also notice the ability to use GtkWidget when the function
811 calls for a GtkObject. GTK is an object oriented design, and a widget
812 is an object.
813
814 <!-- ----------------------------------------------------------------- -->
815 <sect1>More on Signal Handlers
816 <p>
817 Lets take another look at the gtk_signal_connect declaration.
818
819 <tscreen><verb>
820 gint gtk_signal_connect( GtkObject *object,
821                          gchar *name,
822                          GtkSignalFunc func,
823                          gpointer func_data );
824 </verb></tscreen>
825
826 Notice the gint return value? This is a tag that identifies your
827 callback function. As stated above, you may have as many callbacks per
828 signal and per object as you need, and each will be executed in turn,
829 in the order they were attached.
830
831 This tag allows you to remove this callback from the list by using:
832
833 <tscreen><verb>
834 void gtk_signal_disconnect( GtkObject *object,
835                             gint id );
836 </verb></tscreen>
837
838 So, by passing in the widget you wish to remove the handler from, and
839 the tag returned by one of the signal_connect functions, you can
840 disconnect a signal handler.
841
842 Another function to remove all the signal handers from an object is:
843
844 <tscreen><verb>
845 void gtk_signal_handlers_destroy( GtkObject *object );
846 </verb></tscreen>
847
848 This call is fairly self explanatory. It simply removes all the
849 current signal handlers from the object passed in as the first
850 argument.
851
852 <!-- ----------------------------------------------------------------- -->
853 <sect1>An Upgraded Hello World
854 <p>
855 Let's take a look at a slightly improved <em>helloworld</em> with
856 better examples of callbacks. This will also introduce us to our next
857 topic, packing widgets.
858
859 <tscreen><verb>
860 /* example-start helloworld2 helloworld2.c */
861
862 #include <gtk/gtk.h>
863
864 /* Our new improved callback.  The data passed to this function
865  * is printed to stdout. */
866 void callback( GtkWidget *widget,
867                gpointer   data )
868 {
869     g_print ("Hello again - %s was pressed\n", (char *) data);
870 }
871
872 /* another callback */
873 void delete_event( GtkWidget *widget,
874                    GdkEvent  *event,
875                    gpointer   data )
876 {
877     gtk_main_quit ();
878 }
879
880 int main( int   argc,
881           char *argv[] )
882 {
883     /* GtkWidget is the storage type for widgets */
884     GtkWidget *window;
885     GtkWidget *button;
886     GtkWidget *box1;
887
888     /* This is called in all GTK applications. Arguments are parsed
889      * from the command line and are returned to the application. */
890     gtk_init (&amp;argc, &amp;argv);
891
892     /* Create a new window */
893     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
894
895     /* This is a new call, this just sets the title of our
896      * new window to "Hello Buttons!" */
897     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
898
899     /* Here we just set a handler for delete_event that immediately
900      * exits GTK. */
901     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
902                         GTK_SIGNAL_FUNC (delete_event), NULL);
903
904     /* Sets the border width of the window. */
905     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
906
907     /* We create a box to pack widgets into.  This is described in detail
908      * in the "packing" section. The box is not really visible, it
909      * is just used as a tool to arrange widgets. */
910     box1 = gtk_hbox_new(FALSE, 0);
911
912     /* Put the box into the main window. */
913     gtk_container_add (GTK_CONTAINER (window), box1);
914
915     /* Creates a new button with the label "Button 1". */
916     button = gtk_button_new_with_label ("Button 1");
917
918     /* Now when the button is clicked, we call the "callback" function
919      * with a pointer to "button 1" as its argument */
920     gtk_signal_connect (GTK_OBJECT (button), "clicked",
921                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
922
923     /* Instead of gtk_container_add, we pack this button into the invisible
924      * box, which has been packed into the window. */
925     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
926
927     /* Always remember this step, this tells GTK that our preparation for
928      * this button is complete, and it can now be displayed. */
929     gtk_widget_show(button);
930
931     /* Do these same steps again to create a second button */
932     button = gtk_button_new_with_label ("Button 2");
933
934     /* Call the same callback function with a different argument,
935      * passing a pointer to "button 2" instead. */
936     gtk_signal_connect (GTK_OBJECT (button), "clicked",
937                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
938
939     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
940
941     /* The order in which we show the buttons is not really important, but I
942      * recommend showing the window last, so it all pops up at once. */
943     gtk_widget_show(button);
944
945     gtk_widget_show(box1);
946
947     gtk_widget_show (window);
948
949     /* Rest in gtk_main and wait for the fun to begin! */
950     gtk_main ();
951
952     return(0);
953 }
954 /* example-end */
955 </verb></tscreen>
956
957 Compile this program using the same linking arguments as our first
958 example.  You'll notice this time there is no easy way to exit the
959 program, you have to use your window manager or command line to kill
960 it. A good exercise for the reader would be to insert a third "Quit"
961 button that will exit the program. You may also wish to play with the
962 options to gtk_box_pack_start() while reading the next section.  Try
963 resizing the window, and observe the behavior.
964
965 Just as a side note, there is another useful define for
966 gtk_window_new() - GTK_WINDOW_DIALOG. This interacts with the window
967 manager a little differently and should be used for transient windows.
968
969 <!-- ***************************************************************** -->
970 <sect>Packing Widgets
971 <!-- ***************************************************************** -->
972 <p>
973 When creating an application, you'll want to put more than one widget
974 inside a window. Our first <em>helloworld</em> example only used one
975 widget so we could simply use a gtk_container_add call to "pack" the
976 widget into the window. But when you want to put more than one widget
977 into a window, how do you control where that widget is positioned?
978 This is where packing comes in.
979
980 <!-- ----------------------------------------------------------------- -->
981 <sect1>Theory of Packing Boxes
982 <p>
983 Most packing is done by creating boxes as in the example above. These
984 are invisible widget containers that we can pack our widgets into
985 which come in two forms, a horizontal box, and a vertical box. When
986 packing widgets into a horizontal box, the objects are inserted
987 horizontally from left to right or right to left depending on the call
988 used. In a vertical box, widgets are packed from top to bottom or vice
989 versa. You may use any combination of boxes inside or beside other
990 boxes to create the desired effect.
991
992 To create a new horizontal box, we use a call to gtk_hbox_new(), and
993 for vertical boxes, gtk_vbox_new().The gtk_box_pack_start() and
994 gtk_box_pack_end() functions are used to place objects inside of these
995 containers. The gtk_box_pack_start() function will start at the top
996 and work its way down in a vbox, and pack left to right in an hbox.
997 gtk_box_pack_end() will do the opposite, packing from bottom to top in
998 a vbox, and right to left in an hbox. Using these functions allow us
999 to right justify or left justify our widgets and may be mixed in any
1000 way to achieve the desired effect. We will use gtk_box_pack_start() in
1001 most of our examples. An object may be another container or a
1002 widget. In fact, many widgets are actually containers themselves,
1003 including the button, but we usually only use a label inside a button.
1004
1005 By using these calls, GTK knows where you want to place your widgets
1006 so it can do automatic resizing and other nifty things. There's also a
1007 number of options as to how your widgets should be packed. As you can
1008 imagine, this method gives us a quite a bit of flexibility when
1009 placing and creating widgets.
1010
1011 <!-- ----------------------------------------------------------------- -->
1012 <sect1>Details of Boxes
1013 <p>
1014 Because of this flexibility, packing boxes in GTK can be confusing at
1015 first. There are a lot of options, and it's not immediately obvious how
1016 they all fit together. In the end however, there are basically five
1017 different styles.
1018
1019 <? <CENTER> >
1020 <?
1021 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
1022 HEIGHT="235" ALT="Box Packing Example Image">
1023 >
1024 <? </CENTER> >
1025
1026 Each line contains one horizontal box (hbox) with several buttons. The
1027 call to gtk_box_pack is shorthand for the call to pack each of the
1028 buttons into the hbox. Each of the buttons is packed into the hbox the
1029 same way (i.e. same arguments to the gtk_box_pack_start() function).
1030
1031 This is the declaration of the gtk_box_pack_start function.
1032
1033 <tscreen><verb>
1034 void gtk_box_pack_start( GtkBox    *box,
1035                          GtkWidget *child,
1036                          gint       expand,
1037                          gint       fill,
1038                          gint       padding );
1039 </verb></tscreen>
1040
1041 The first argument is the box you are packing the object into, the
1042 second is the object. The objects will all be buttons for now, so
1043 we'll be packing buttons into boxes.
1044
1045 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1046 controls whether the widgets are laid out in the box to fill in all
1047 the extra space in the box so the box is expanded to fill the area
1048 alloted to it (TRUE).  Or the box is shrunk to just fit the widgets
1049 (FALSE). Setting expand to FALSE will allow you to do right and left
1050 justification of your widgets.  Otherwise, they will all expand to fit
1051 into the box, and the same effect could be achieved by using only one
1052 of gtk_box_pack_start or gtk_box_pack_end.
1053
1054 The fill argument to the gtk_box_pack functions control whether the
1055 extra space is allocated to the objects themselves (TRUE), or as extra
1056 padding in the box around these objects (FALSE). It only has an effect
1057 if the expand argument is also TRUE.
1058
1059 When creating a new box, the function looks like this:
1060
1061 <tscreen><verb>
1062 GtkWidget *gtk_hbox_new (gint homogeneous,
1063                          gint spacing);
1064 </verb></tscreen>
1065
1066 The homogeneous argument to gtk_hbox_new (and the same for
1067 gtk_vbox_new) controls whether each object in the box has the same
1068 size (i.e. the same width in an hbox, or the same height in a
1069 vbox). If it is set, the expand argument to the gtk_box_pack routines
1070 is always turned on.
1071
1072 What's the difference between spacing (set when the box is created)
1073 and padding (set when elements are packed)? Spacing is added between
1074 objects, and padding is added on either side of an object. The
1075 following figure should make it clearer:
1076
1077 <? <CENTER> >
1078 <?
1079 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1080 HEIGHT="213" VSPACE="15" HSPACE="10"
1081 ALT="Box Packing Example Image">
1082 >
1083 <? </CENTER> >
1084
1085 Here is the code used to create the above images. I've commented it
1086 fairly heavily so hopefully you won't have any problems following
1087 it. Compile it yourself and play with it.
1088
1089 <!-- ----------------------------------------------------------------- -->
1090 <sect1>Packing Demonstration Program
1091 <p>
1092 <tscreen><verb>
1093 /* example-start packbox packbox.c */
1094
1095 #include <stdio.h>
1096 #include "gtk/gtk.h"
1097
1098 void delete_event( GtkWidget *widget,
1099                    GdkEvent  *event,
1100                    gpointer   data )
1101 {
1102     gtk_main_quit ();
1103 }
1104
1105 /* Make a new hbox filled with button-labels. Arguments for the 
1106  * variables we're interested are passed in to this function. 
1107  * We do not show the box, but do show everything inside. */
1108 GtkWidget *make_box( gint homogeneous,
1109                      gint spacing,
1110                      gint expand,
1111                      gint fill,
1112                      gint padding ) 
1113 {
1114     GtkWidget *box;
1115     GtkWidget *button;
1116     char padstr[80];
1117     
1118     /* Create a new hbox with the appropriate homogeneous
1119      * and spacing settings */
1120     box = gtk_hbox_new (homogeneous, spacing);
1121     
1122     /* Create a series of buttons with the appropriate settings */
1123     button = gtk_button_new_with_label ("gtk_box_pack");
1124     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1125     gtk_widget_show (button);
1126     
1127     button = gtk_button_new_with_label ("(box,");
1128     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1129     gtk_widget_show (button);
1130     
1131     button = gtk_button_new_with_label ("button,");
1132     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1133     gtk_widget_show (button);
1134     
1135     /* Create a button with the label depending on the value of
1136      * expand. */
1137     if (expand == TRUE)
1138             button = gtk_button_new_with_label ("TRUE,");
1139     else
1140             button = gtk_button_new_with_label ("FALSE,");
1141     
1142     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1143     gtk_widget_show (button);
1144     
1145     /* This is the same as the button creation for "expand"
1146      * above, but uses the shorthand form. */
1147     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1148     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1149     gtk_widget_show (button);
1150     
1151     sprintf (padstr, "%d);", padding);
1152     
1153     button = gtk_button_new_with_label (padstr);
1154     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1155     gtk_widget_show (button);
1156     
1157     return box;
1158 }
1159
1160 int main( int   argc,
1161           char *argv[]) 
1162 {
1163     GtkWidget *window;
1164     GtkWidget *button;
1165     GtkWidget *box1;
1166     GtkWidget *box2;
1167     GtkWidget *separator;
1168     GtkWidget *label;
1169     GtkWidget *quitbox;
1170     int which;
1171     
1172     /* Our init, don't forget this! :) */
1173     gtk_init (&amp;argc, &amp;argv);
1174     
1175     if (argc != 2) {
1176         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1177         /* This just does cleanup in GTK and exits with an exit status of 1. */
1178         gtk_exit (1);
1179     }
1180     
1181     which = atoi (argv[1]);
1182
1183     /* Create our window */
1184     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1185
1186     /* You should always remember to connect the destroy signal to the
1187      * main window. This is very important for proper intuitive
1188      * behavior */
1189     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1190                         GTK_SIGNAL_FUNC (delete_event), NULL);
1191     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1192     
1193     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1194      * This allows us to stack the horizontal boxes filled with buttons one
1195      * on top of the other in this vbox. */
1196     box1 = gtk_vbox_new (FALSE, 0);
1197     
1198     /* which example to show. These correspond to the pictures above. */
1199     switch (which) {
1200     case 1:
1201         /* create a new label. */
1202         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1203         
1204         /* Align the label to the left side.  We'll discuss this function and 
1205          * others in the section on Widget Attributes. */
1206         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1207
1208         /* Pack the label into the vertical box (vbox box1).  Remember that 
1209          * widgets added to a vbox will be packed one on top of the other in
1210          * order. */
1211         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1212         
1213         /* Show the label */
1214         gtk_widget_show (label);
1215         
1216         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1217          * expand = FALSE, fill = FALSE, padding = 0 */
1218         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1219         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1220         gtk_widget_show (box2);
1221
1222         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1223          * expand = FALSE, fill = FALSE, padding = 0 */
1224         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1225         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1226         gtk_widget_show (box2);
1227         
1228         /* Args are: homogeneous, spacing, expand, fill, padding */
1229         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1230         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1231         gtk_widget_show (box2);
1232         
1233         /* Creates a separator, we'll learn more about these later, 
1234          * but they are quite simple. */
1235         separator = gtk_hseparator_new ();
1236         
1237         /* Cack the separator into the vbox. Remember each of these
1238          * widgets are being packed into a vbox, so they'll be stacked
1239          * vertically. */
1240         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1241         gtk_widget_show (separator);
1242         
1243         /* Create another new label, and show it. */
1244         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1245         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1246         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1247         gtk_widget_show (label);
1248         
1249         /* Args are: homogeneous, spacing, expand, fill, padding */
1250         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1251         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1252         gtk_widget_show (box2);
1253         
1254         /* Args are: homogeneous, spacing, expand, fill, padding */
1255         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1256         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1257         gtk_widget_show (box2);
1258         
1259         /* Another new separator. */
1260         separator = gtk_hseparator_new ();
1261         /* The last 3 arguments to gtk_box_pack_start are:
1262          * expand, fill, padding. */
1263         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1264         gtk_widget_show (separator);
1265         
1266         break;
1267
1268     case 2:
1269
1270         /* Create a new label, remember box1 is a vbox as created 
1271          * near the beginning of main() */
1272         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1273         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1274         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1275         gtk_widget_show (label);
1276         
1277         /* Args are: homogeneous, spacing, expand, fill, padding */
1278         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1279         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1280         gtk_widget_show (box2);
1281         
1282         /* Args are: homogeneous, spacing, expand, fill, padding */
1283         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1284         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1285         gtk_widget_show (box2);
1286         
1287         separator = gtk_hseparator_new ();
1288         /* The last 3 arguments to gtk_box_pack_start are:
1289          * expand, fill, padding. */
1290         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1291         gtk_widget_show (separator);
1292         
1293         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1294         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1295         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1296         gtk_widget_show (label);
1297         
1298         /* Args are: homogeneous, spacing, expand, fill, padding */
1299         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1300         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1301         gtk_widget_show (box2);
1302         
1303         /* Args are: homogeneous, spacing, expand, fill, padding */
1304         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1305         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1306         gtk_widget_show (box2);
1307         
1308         separator = gtk_hseparator_new ();
1309         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1310         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1311         gtk_widget_show (separator);
1312         break;
1313     
1314     case 3:
1315
1316         /* This demonstrates the ability to use gtk_box_pack_end() to
1317          * right justify widgets. First, we create a new box as before. */
1318         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1319
1320         /* Create the label that will be put at the end. */
1321         label = gtk_label_new ("end");
1322         /* Pack it using gtk_box_pack_end(), so it is put on the right
1323          * side of the hbox created in the make_box() call. */
1324         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1325         /* Show the label. */
1326         gtk_widget_show (label);
1327         
1328         /* Pack box2 into box1 (the vbox remember ? :) */
1329         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1330         gtk_widget_show (box2);
1331         
1332         /* A separator for the bottom. */
1333         separator = gtk_hseparator_new ();
1334         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1335          * high. This is so the hbox we created will also be 400 pixels wide,
1336          * and the "end" label will be separated from the other labels in the
1337          * hbox. Otherwise, all the widgets in the hbox would be packed as
1338          * close together as possible. */
1339         gtk_widget_set_usize (separator, 400, 5);
1340         /* pack the separator into the vbox (box1) created near the start 
1341          * of main() */
1342         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1343         gtk_widget_show (separator);    
1344     }
1345     
1346     /* Create another new hbox.. remember we can use as many as we need! */
1347     quitbox = gtk_hbox_new (FALSE, 0);
1348     
1349     /* Our quit button. */
1350     button = gtk_button_new_with_label ("Quit");
1351     
1352     /* Setup the signal to destroy the window. Remember that this will send
1353      * the "destroy" signal to the window which will be caught by our signal
1354      * handler as defined above. */
1355     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1356                                GTK_SIGNAL_FUNC (gtk_main_quit),
1357                                GTK_OBJECT (window));
1358     /* Pack the button into the quitbox.
1359      * The last 3 arguments to gtk_box_pack_start are:
1360      * expand, fill, padding. */
1361     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1362     /* pack the quitbox into the vbox (box1) */
1363     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1364     
1365     /* Pack the vbox (box1) which now contains all our widgets, into the
1366      * main window. */
1367     gtk_container_add (GTK_CONTAINER (window), box1);
1368     
1369     /* And show everything left */
1370     gtk_widget_show (button);
1371     gtk_widget_show (quitbox);
1372     
1373     gtk_widget_show (box1);
1374     /* Showing the window last so everything pops up at once. */
1375     gtk_widget_show (window);
1376     
1377     /* And of course, our main function. */
1378     gtk_main ();
1379
1380     /* Control returns here when gtk_main_quit() is called, but not when 
1381      * gtk_exit is used. */
1382     
1383     return(0);
1384 }
1385 /* example-end */
1386 </verb></tscreen>
1387
1388 <!-- ----------------------------------------------------------------- -->
1389 <sect1>Packing Using Tables
1390 <p>
1391 Let's take a look at another way of packing - Tables. These can be
1392 extremely useful in certain situations.
1393
1394 Using tables, we create a grid that we can place widgets in. The
1395 widgets may take up as many spaces as we specify.
1396
1397 The first thing to look at of course, is the gtk_table_new function:
1398
1399 <tscreen><verb>
1400 GtkWidget *gtk_table_new( gint rows,
1401                           gint columns,
1402                           gint homogeneous );
1403 </verb></tscreen>
1404
1405 The first argument is the number of rows to make in the table, while
1406 the second, obviously, is the number of columns.
1407
1408 The homogeneous argument has to do with how the table's boxes are
1409 sized. If homogeneous is TRUE, the table boxes are resized to the size
1410 of the largest widget in the table. If homogeneous is FALSE, the size
1411 of a table boxes is dictated by the tallest widget in its same row,
1412 and the widest widget in its column.
1413
1414 The rows and columns are laid out from 0 to n, where n was the number
1415 specified in the call to gtk_table_new. So, if you specify rows = 2
1416 and columns = 2, the layout would look something like this:
1417
1418 <tscreen><verb>
1419  0          1          2
1420 0+----------+----------+
1421  |          |          |
1422 1+----------+----------+
1423  |          |          |
1424 2+----------+----------+
1425 </verb></tscreen>
1426
1427 Note that the coordinate system starts in the upper left hand corner.
1428 To place a widget into a box, use the following function:
1429
1430 <tscreen><verb>
1431 void gtk_table_attach( GtkTable  *table,
1432                        GtkWidget *child,
1433                        gint       left_attach,
1434                        gint       right_attach,
1435                        gint       top_attach,
1436                        gint       bottom_attach,
1437                        gint       xoptions,
1438                        gint       yoptions,
1439                        gint       xpadding,
1440                        gint       ypadding );
1441 </verb></tscreen>                                      
1442
1443 Where the first argument ("table") is the table you've created and the
1444 second ("child") the widget you wish to place in the table.
1445
1446 The left and right attach arguments specify where to place the widget,
1447 and how many boxes to use. If you want a button in the lower right
1448 table entry of our 2x2 table, and want it to fill that entry ONLY,
1449 left_attach would be = 1, right_attach = 2, top_attach = 1,
1450 bottom_attach = 2.
1451
1452 Now, if you wanted a widget to take up the whole top row of our 2x2
1453 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1454 bottom_attach = 1.
1455
1456 The xoptions and yoptions are used to specify packing options and may
1457 be bitwise OR'ed together to allow multiple options.
1458
1459 These options are:
1460 <itemize>
1461 <item>GTK_FILL - If the table box is larger than the widget, and
1462 GTK_FILL is specified, the widget will expand to use all the room
1463 available.
1464
1465 <item>GTK_SHRINK - If the table widget was allocated less space then
1466 was requested (usually by the user resizing the window), then the
1467 widgets would normally just be pushed off the bottom of the window and
1468 disappear. If GTK_SHRINK is specified, the widgets will shrink with
1469 the table.
1470
1471 <item>GTK_EXPAND - This will cause the table to expand to use up any
1472 remaining space in the window.
1473 </itemize>
1474
1475 Padding is just like in boxes, creating a clear area around the widget
1476 specified in pixels.
1477
1478 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1479
1480 <tscreen><verb>
1481 void gtk_table_attach_defaults( GtkTable  *table,
1482                                 GtkWidget *widget,
1483                                 gint       left_attach,
1484                                 gint       right_attach,
1485                                 gint       top_attach,
1486                                 gint       bottom_attach );
1487 </verb></tscreen>
1488
1489 The X and Y options default to GTK_FILL | GTK_EXPAND, and X and Y
1490 padding are set to 0. The rest of the arguments are identical to the
1491 previous function.
1492
1493 We also have gtk_table_set_row_spacing() and
1494 gtk_table_set_col_spacing().  This places spacing between the rows at
1495 the specified row or column.
1496
1497 <tscreen><verb>
1498 void gtk_table_set_row_spacing( GtkTable *table,
1499                                 gint      row,
1500                                 gint      spacing );
1501 </verb></tscreen>
1502
1503 and
1504
1505 <tscreen><verb>
1506 void gtk_table_set_col_spacing ( GtkTable *table,
1507                                  gint      column,
1508                                  gint      spacing );
1509 </verb></tscreen>
1510
1511 Note that for columns, the space goes to the right of the column, and
1512 for rows, the space goes below the row.
1513
1514 You can also set a consistent spacing of all rows and/or columns with:
1515
1516 <tscreen><verb>
1517 void gtk_table_set_row_spacings( GtkTable *table,
1518                                  gint      spacing );
1519 </verb></tscreen>
1520
1521 And,
1522
1523 <tscreen><verb>
1524 void gtk_table_set_col_spacings( GtkTable *table,
1525                                  gint      spacing );
1526 </verb></tscreen>
1527
1528 Note that with these calls, the last row and last column do not get
1529 any spacing.
1530
1531 <!-- ----------------------------------------------------------------- -->
1532 <sect1>Table Packing Example
1533 <p>
1534 Here we make a window with three buttons in a 2x2 table.
1535 The first two buttons will be placed in the upper row.
1536 A third, quit button, is placed in the lower row, spanning both columns.
1537 Which means it should look something like this:
1538
1539 <? <CENTER> >
1540 <?
1541 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1542 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1543 >
1544 <? </CENTER> >
1545
1546 Here's the source code:
1547
1548 <tscreen><verb>
1549 /* example-start table table.c */
1550
1551 #include <gtk/gtk.h>
1552
1553 /* Our callback.
1554  * The data passed to this function is printed to stdout */
1555 void callback( GtkWidget *widget,
1556                gpointer   data )
1557 {
1558     g_print ("Hello again - %s was pressed\n", (char *) data);
1559 }
1560
1561 /* This callback quits the program */
1562 void delete_event( GtkWidget *widget,
1563                    GdkEvent  *event,
1564                    gpointer   data )
1565 {
1566     gtk_main_quit ();
1567 }
1568
1569 int main( int   argc,
1570           char *argv[] )
1571 {
1572     GtkWidget *window;
1573     GtkWidget *button;
1574     GtkWidget *table;
1575
1576     gtk_init (&amp;argc, &amp;argv);
1577
1578     /* Create a new window */
1579     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1580
1581     /* Set the window title */
1582     gtk_window_set_title (GTK_WINDOW (window), "Table");
1583
1584     /* Set a handler for delete_event that immediately
1585      * exits GTK. */
1586     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1587                         GTK_SIGNAL_FUNC (delete_event), NULL);
1588
1589     /* Sets the border width of the window. */
1590     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1591
1592     /* Create a 2x2 table */
1593     table = gtk_table_new (2, 2, TRUE);
1594
1595     /* Put the table in the main window */
1596     gtk_container_add (GTK_CONTAINER (window), table);
1597
1598     /* Create first button */
1599     button = gtk_button_new_with_label ("button 1");
1600
1601     /* When the button is clicked, we call the "callback" function
1602      * with a pointer to "button 1" as its argument */
1603     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1604               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1605
1606
1607     /* Insert button 1 into the upper left quadrant of the table */
1608     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1609
1610     gtk_widget_show (button);
1611
1612     /* Create second button */
1613
1614     button = gtk_button_new_with_label ("button 2");
1615
1616     /* When the button is clicked, we call the "callback" function
1617      * with a pointer to "button 2" as its argument */
1618     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1619               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1620     /* Insert button 2 into the upper right quadrant of the table */
1621     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1622
1623     gtk_widget_show (button);
1624
1625     /* Create "Quit" button */
1626     button = gtk_button_new_with_label ("Quit");
1627
1628     /* When the button is clicked, we call the "delete_event" function
1629      * and the program exits */
1630     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1631                         GTK_SIGNAL_FUNC (delete_event), NULL);
1632
1633     /* Insert the quit button into the both 
1634      * lower quadrants of the table */
1635     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1636
1637     gtk_widget_show (button);
1638
1639     gtk_widget_show (table);
1640     gtk_widget_show (window);
1641
1642     gtk_main ();
1643
1644     return 0;
1645 }
1646 /* example-end */
1647 </verb></tscreen>
1648
1649 <!-- ***************************************************************** -->
1650 <sect>Widget Overview
1651 <!-- ***************************************************************** -->
1652 <p>
1653 The general steps to creating a widget in GTK are:
1654 <enum>
1655 <item> gtk_*_new - one of various functions to create a new widget.
1656 These are all detailed in this section.
1657
1658 <item> Connect all signals and events we wish to use to the
1659 appropriate handlers.
1660
1661 <item> Set the attributes of the widget.
1662
1663 <item> Pack the widget into a container using the appropriate call
1664 such as gtk_container_add() or gtk_box_pack_start().
1665
1666 <item> gtk_widget_show() the widget.
1667 </enum>
1668
1669 gtk_widget_show() lets GTK know that we are done setting the
1670 attributes of the widget, and it is ready to be displayed. You may
1671 also use gtk_widget_hide to make it disappear again. The order in
1672 which you show the widgets is not important, but I suggest showing the
1673 window last so the whole window pops up at once rather than seeing the
1674 individual widgets come up on the screen as they're formed. The
1675 children of a widget (a window is a widget too) will not be displayed
1676 until the window itself is shown using the gtk_widget_show() function.
1677
1678 <!-- ----------------------------------------------------------------- -->
1679 <sect1> Casting
1680 <p>
1681 You'll notice as you go on, that GTK uses a type casting system. This
1682 is always done using macros that both test the ability to cast the
1683 given item, and perform the cast. Some common ones you will see are:
1684
1685 <itemize>
1686 <item> GTK_WIDGET(widget)
1687 <item> GTK_OBJECT(object)
1688 <item> GTK_SIGNAL_FUNC(function)
1689 <item> GTK_CONTAINER(container)
1690 <item> GTK_WINDOW(window)
1691 <item> GTK_BOX(box)
1692 </itemize>
1693
1694 These are all used to cast arguments in functions. You'll see them in the
1695 examples, and can usually tell when to use them simply by looking at the
1696 function's declaration.
1697
1698 As you can see below in the class hierarchy, all GtkWidgets are
1699 derived from the GtkObject base class. This means you can use a widget
1700 in any place the function asks for an object - simply use the
1701 GTK_OBJECT() macro.
1702
1703 For example:
1704
1705 <tscreen><verb>
1706 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1707                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1708 </verb></tscreen> 
1709
1710 This casts the button into an object, and provides a cast for the
1711 function pointer to the callback.
1712
1713 Many widgets are also containers. If you look in the class hierarchy
1714 below, you'll notice that many widgets derive from the GtkContainer
1715 class. Any one of these widgets may be used with the GTK_CONTAINER
1716 macro to pass them to functions that ask for containers.
1717
1718 Unfortunately, these macros are not extensively covered in the
1719 tutorial, but I recommend taking a look through the GTK header
1720 files. It can be very educational. In fact, it's not difficult to
1721 learn how a widget works just by looking at the function declarations.
1722
1723 <!-- ----------------------------------------------------------------- -->
1724 <sect1>Widget Hierarchy
1725 <p>
1726 For your reference, here is the class hierarchy tree used to implement widgets.
1727
1728 <tscreen><verb>
1729  GtkObject
1730   +GtkWidget
1731   | +GtkMisc
1732   | | +GtkLabel
1733   | | | +GtkAccelLabel
1734   | | | `GtkTipsQuery
1735   | | +GtkArrow
1736   | | +GtkImage
1737   | | `GtkPixmap
1738   | +GtkContainer
1739   | | +GtkBin
1740   | | | +GtkAlignment
1741   | | | +GtkFrame
1742   | | | | `GtkAspectFrame
1743   | | | +GtkButton
1744   | | | | +GtkToggleButton
1745   | | | | | `GtkCheckButton
1746   | | | | |   `GtkRadioButton
1747   | | | | `GtkOptionMenu
1748   | | | +GtkItem
1749   | | | | +GtkMenuItem
1750   | | | | | +GtkCheckMenuItem
1751   | | | | | | `GtkRadioMenuItem
1752   | | | | | `GtkTearoffMenuItem
1753   | | | | +GtkListItem
1754   | | | | `GtkTreeItem
1755   | | | +GtkWindow
1756   | | | | +GtkColorSelectionDialog
1757   | | | | +GtkDialog
1758   | | | | | `GtkInputDialog
1759   | | | | +GtkDrawWindow
1760   | | | | +GtkFileSelection
1761   | | | | +GtkFontSelectionDialog
1762   | | | | `GtkPlug
1763   | | | +GtkEventBox
1764   | | | +GtkHandleBox
1765   | | | +GtkScrolledWindow
1766   | | | `GtkViewport
1767   | | +GtkBox
1768   | | | +GtkButtonBox
1769   | | | | +GtkHButtonBox
1770   | | | | `GtkVButtonBox
1771   | | | +GtkVBox
1772   | | | | +GtkColorSelection
1773   | | | | `GtkGammaCurve
1774   | | | `GtkHBox
1775   | | |   +GtkCombo
1776   | | |   `GtkStatusbar
1777   | | +GtkCList
1778   | | | `GtkCTree
1779   | | +GtkFixed
1780   | | +GtkNotebook
1781   | | | `GtkFontSelection
1782   | | +GtkPaned
1783   | | | +GtkHPaned
1784   | | | `GtkVPaned
1785   | | +GtkLayout
1786   | | +GtkList
1787   | | +GtkMenuShell
1788   | | | +GtkMenuBar
1789   | | | `GtkMenu
1790   | | +GtkPacker
1791   | | +GtkSocket
1792   | | +GtkTable
1793   | | +GtkToolbar
1794   | | `GtkTree
1795   | +GtkCalendar
1796   | +GtkDrawingArea
1797   | | `GtkCurve
1798   | +GtkEditable
1799   | | +GtkEntry
1800   | | | `GtkSpinButton
1801   | | `GtkText
1802   | +GtkRuler
1803   | | +GtkHRuler
1804   | | `GtkVRuler
1805   | +GtkRange
1806   | | +GtkScale
1807   | | | +GtkHScale
1808   | | | `GtkVScale
1809   | | `GtkScrollbar
1810   | |   +GtkHScrollbar
1811   | |   `GtkVScrollbar
1812   | +GtkSeparator
1813   | | +GtkHSeparator
1814   | | `GtkVSeparator
1815   | +GtkPreview
1816   | `GtkProgress
1817   |   `GtkProgressBar
1818   +GtkData
1819   | +GtkAdjustment
1820   | `GtkTooltips
1821   `GtkItemFactory
1822 </verb></tscreen>
1823
1824 <!-- ----------------------------------------------------------------- -->
1825 <sect1>Widgets Without Windows
1826 <p>
1827 The following widgets do not have an associated window. If you want to
1828 capture events, you'll have to use the GtkEventBox. See the section on
1829 the <ref id="sec_EventBox" name="EventBox"> widget.
1830
1831 <tscreen><verb>
1832 GtkAlignment
1833 GtkArrow
1834 GtkBin
1835 GtkBox
1836 GtkImage
1837 GtkItem
1838 GtkLabel
1839 GtkPixmap
1840 GtkScrolledWindow
1841 GtkSeparator
1842 GtkTable
1843 GtkAspectFrame
1844 GtkFrame
1845 GtkVBox
1846 GtkHBox
1847 GtkVSeparator
1848 GtkHSeparator
1849 </verb></tscreen>
1850
1851 We'll further our exploration of GTK by examining each widget in turn,
1852 creating a few simple functions to display them. Another good source
1853 is the testgtk.c program that comes with GTK. It can be found in
1854 gtk/testgtk.c.
1855
1856 <!-- ***************************************************************** -->
1857 <sect>The Button Widget
1858 <!-- ***************************************************************** -->
1859
1860 <!-- ----------------------------------------------------------------- -->
1861 <sect1>Normal Buttons
1862 <p>
1863 We've almost seen all there is to see of the button widget. It's
1864 pretty simple. There are however two ways to create a button. You can
1865 use the gtk_button_new_with_label() to create a button with a label,
1866 or use gtk_button_new() to create a blank button. It's then up to you
1867 to pack a label or pixmap into this new button. To do this, create a
1868 new box, and then pack your objects into this box using the usual
1869 gtk_box_pack_start, and then use gtk_container_add to pack the box
1870 into the button.
1871
1872 Here's an example of using gtk_button_new to create a button with a
1873 picture and a label in it. I've broken up the code to create a box
1874 from the rest so you can use it in your programs. There are further
1875 examples of using pixmaps later in the tutorial.
1876
1877 <tscreen><verb>
1878 /* example-start buttons buttons.c */
1879
1880 #include <gtk/gtk.h>
1881
1882 /* Create a new hbox with an image and a label packed into it
1883  * and return the box. */
1884
1885 GtkWidget *xpm_label_box( GtkWidget *parent,
1886                           gchar     *xpm_filename,
1887                           gchar     *label_text )
1888 {
1889     GtkWidget *box1;
1890     GtkWidget *label;
1891     GtkWidget *pixmapwid;
1892     GdkPixmap *pixmap;
1893     GdkBitmap *mask;
1894     GtkStyle *style;
1895
1896     /* Create box for xpm and label */
1897     box1 = gtk_hbox_new (FALSE, 0);
1898     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1899
1900     /* Get the style of the button to get the
1901      * background color. */
1902     style = gtk_widget_get_style(parent);
1903
1904     /* Now on to the xpm stuff */
1905     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1906                                          &amp;style->bg[GTK_STATE_NORMAL],
1907                                          xpm_filename);
1908     pixmapwid = gtk_pixmap_new (pixmap, mask);
1909
1910     /* Create a label for the button */
1911     label = gtk_label_new (label_text);
1912
1913     /* Pack the pixmap and label into the box */
1914     gtk_box_pack_start (GTK_BOX (box1),
1915                         pixmapwid, FALSE, FALSE, 3);
1916
1917     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1918
1919     gtk_widget_show(pixmapwid);
1920     gtk_widget_show(label);
1921
1922     return(box1);
1923 }
1924
1925 /* Our usual callback function */
1926 void callback( GtkWidget *widget,
1927                gpointer   data )
1928 {
1929     g_print ("Hello again - %s was pressed\n", (char *) data);
1930 }
1931
1932
1933 int main( int   argc,
1934           char *argv[] )
1935 {
1936     /* GtkWidget is the storage type for widgets */
1937     GtkWidget *window;
1938     GtkWidget *button;
1939     GtkWidget *box1;
1940
1941     gtk_init (&amp;argc, &amp;argv);
1942
1943     /* Create a new window */
1944     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1945
1946     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1947
1948     /* It's a good idea to do this for all windows. */
1949     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1950                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1951
1952     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1953                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1954
1955
1956     /* Sets the border width of the window. */
1957     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1958     gtk_widget_realize(window);
1959
1960     /* Create a new button */
1961     button = gtk_button_new ();
1962
1963     /* Connect the "clicked" signal of the button to our callback */
1964     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1965                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1966
1967     /* This calls our box creating function */
1968     box1 = xpm_label_box(window, "info.xpm", "cool button");
1969
1970     /* Pack and show all our widgets */
1971     gtk_widget_show(box1);
1972
1973     gtk_container_add (GTK_CONTAINER (button), box1);
1974
1975     gtk_widget_show(button);
1976
1977     gtk_container_add (GTK_CONTAINER (window), button);
1978
1979     gtk_widget_show (window);
1980
1981     /* Rest in gtk_main and wait for the fun to begin! */
1982     gtk_main ();
1983
1984     return(0);
1985 }
1986 /* example-end */
1987 </verb></tscreen>
1988
1989 The xpm_label_box function could be used to pack xpm's and labels into
1990 any widget that can be a container.
1991
1992 The Button widget has the following signals:
1993
1994 <itemize>
1995 <item> pressed
1996 <item> released
1997 <item> clicked
1998 <item> enter
1999 <item> leave
2000 </itemize>
2001
2002 <!-- ----------------------------------------------------------------- -->
2003 <sect1> Toggle Buttons
2004 <p>
2005 Toggle buttons are derived from normal buttons and are very similar,
2006 except they will always be in one of two states, alternated by a
2007 click. They may be depressed, and when you click again, they will pop
2008 back up. Click again, and they will pop back down.
2009
2010 Toggle buttons are the basis for check buttons and radio buttons, as
2011 such, many of the calls used for toggle buttons are inherited by radio
2012 and check buttons. I will point these out when we come to them.
2013
2014 Creating a new toggle button:
2015
2016 <tscreen><verb>
2017 GtkWidget *gtk_toggle_button_new( void );
2018
2019 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
2020 </verb></tscreen>
2021
2022 As you can imagine, these work identically to the normal button widget
2023 calls. The first creates a blank toggle button, and the second, a
2024 button with a label widget already packed into it.
2025
2026 To retrieve the state of the toggle widget, including radio and check
2027 buttons, we use a GTK macro as shown in our example below. This tests
2028 the state of the toggle in a callback. The signal of interest emitted
2029 to us by toggle buttons (the toggle button, check button, and radio
2030 button widgets), is the "toggled" signal. To check the state of these
2031 buttons, set up a signal handler to catch the toggled signal, and use
2032 the macro to determine its state. The callback will look something
2033 like:
2034
2035 <tscreen><verb>
2036 void toggle_button_callback (GtkWidget *widget, gpointer data)
2037 {
2038     if (GTK_TOGGLE_BUTTON (widget)->active) 
2039     {
2040         /* If control reaches here, the toggle button is down */
2041     
2042     } else {
2043     
2044         /* If control reaches here, the toggle button is up */
2045     }
2046 }
2047 </verb></tscreen>
2048
2049 <tscreen><verb>
2050 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2051                                   gint             state );
2052 </verb></tscreen>
2053
2054 The above call can be used to set the state of the toggle button, and
2055 its children the radio and check buttons. Passing in your created
2056 button as the first argument, and a TRUE or FALSE for the second state
2057 argument to specify whether it should be down (depressed) or up
2058 (released). Default is up, or FALSE.
2059
2060 Note that when you use the gtk_toggle_button_set_active() function, and
2061 the state is actually changed, it causes the "clicked" signal to be
2062 emitted from the button.
2063
2064 <tscreen><verb>
2065 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2066 </verb></tscreen>
2067
2068 This simply toggles the button, and emits the "toggled" signal.
2069
2070 <!-- ----------------------------------------------------------------- -->
2071 <sect1> Check Buttons
2072 <p>
2073 Check buttons inherent many properties and functions from the the
2074 toggle buttons above, but look a little different. Rather than being
2075 buttons with text inside them, they are small squares with the text to
2076 the right of them. These are often used for toggling options on and
2077 off in applications.
2078
2079 The two creation functions are similar to those of the normal button.
2080
2081 <tscreen><verb>
2082 GtkWidget *gtk_check_button_new( void );
2083
2084 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2085 </verb></tscreen>
2086
2087 The new_with_label function creates a check button with a label beside
2088 it.
2089
2090 Checking the state of the check button is identical to that of the
2091 toggle button.
2092
2093 <!-- ----------------------------------------------------------------- -->
2094 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2095 <p>
2096 Radio buttons are similar to check buttons except they are grouped so
2097 that only one may be selected/depressed at a time. This is good for
2098 places in your application where you need to select from a short list
2099 of options.
2100
2101 Creating a new radio button is done with one of these calls:
2102
2103 <tscreen><verb>
2104 GtkWidget *gtk_radio_button_new( GSList *group );
2105
2106 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2107                                             gchar  *label );
2108 </verb></tscreen>
2109
2110 You'll notice the extra argument to these calls. They require a group
2111 to perform their duty properly. The first call to
2112 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2113 should pass NULL as the first argument. Then create a group using:
2114
2115 <tscreen><verb>
2116 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2117 </verb></tscreen>
2118
2119 The important thing to remember is that gtk_radio_button_group must be
2120 called for each new button added to the group, with the previous
2121 button passed in as an argument. The result is then passed into the
2122 call to gtk_radio_button_new or gtk_radio_button_new_with_label. This
2123 allows a chain of buttons to be established. The example below should
2124 make this clear.
2125
2126 You can shorten this slightly by using the following syntax, which
2127 removes the need for a variable to hold the list of buttons. This form
2128 is used in the example to create the third button:
2129
2130 <tscreen><verb>
2131      button2 = gtk_radio_button_new_with_label(
2132                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2133                  "button2");
2134 </verb></tscreen>
2135
2136 It is also a good idea to explicitly set which button should be the
2137 default depressed button with:
2138
2139 <tscreen><verb>
2140 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2141                                   gint             state );
2142 </verb></tscreen>
2143
2144 This is described in the section on toggle buttons, and works in
2145 exactly the same way.
2146
2147 The following example creates a radio button group with three buttons.
2148
2149 <tscreen><verb>
2150 /* example-start radiobuttons radiobuttons.c */
2151
2152 #include <gtk/gtk.h>
2153 #include <glib.h>
2154
2155 void close_application( GtkWidget *widget,
2156                         GdkEvent  *event,
2157                         gpointer   data )
2158 {
2159   gtk_main_quit();
2160 }
2161
2162 int main( int   argc,
2163           char *argv[] )
2164 {
2165     GtkWidget *window = NULL;
2166     GtkWidget *box1;
2167     GtkWidget *box2;
2168     GtkWidget *button;
2169     GtkWidget *separator;
2170     GSList *group;
2171   
2172     gtk_init(&amp;argc,&amp;argv);    
2173       
2174     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2175   
2176     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2177                         GTK_SIGNAL_FUNC(close_application),
2178                         NULL);
2179
2180     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2181     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2182
2183     box1 = gtk_vbox_new (FALSE, 0);
2184     gtk_container_add (GTK_CONTAINER (window), box1);
2185     gtk_widget_show (box1);
2186
2187     box2 = gtk_vbox_new (FALSE, 10);
2188     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2189     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2190     gtk_widget_show (box2);
2191
2192     button = gtk_radio_button_new_with_label (NULL, "button1");
2193     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2194     gtk_widget_show (button);
2195
2196     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2197     button = gtk_radio_button_new_with_label(group, "button2");
2198     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2199     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2200     gtk_widget_show (button);
2201
2202     button = gtk_radio_button_new_with_label(
2203                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2204                  "button3");
2205     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2206     gtk_widget_show (button);
2207
2208     separator = gtk_hseparator_new ();
2209     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2210     gtk_widget_show (separator);
2211
2212     box2 = gtk_vbox_new (FALSE, 10);
2213     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2214     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2215     gtk_widget_show (box2);
2216
2217     button = gtk_button_new_with_label ("close");
2218     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2219                                GTK_SIGNAL_FUNC(close_application),
2220                                GTK_OBJECT (window));
2221     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2222     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2223     gtk_widget_grab_default (button);
2224     gtk_widget_show (button);
2225     gtk_widget_show (window);
2226      
2227     gtk_main();
2228
2229     return(0);
2230 }
2231 /* example-end */
2232 </verb></tscreen>
2233
2234 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2235
2236 <!-- ***************************************************************** -->
2237 <sect> Adjustments <label id="sec_Adjustment">
2238 <!-- ***************************************************************** -->
2239 <p>
2240 GTK+ has various widgets that can be visually adjusted by the user
2241 using the mouse or the keyboard, such as the range widgets, described
2242 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2243 section. There are also a few widgets that display some adjustable
2244 portion of a larger area of data, such as the text widget and the
2245 viewport widget.
2246
2247 Obviously, an application needs to be able to react to changes the
2248 user makes in range widgets. One way to do this would be to have each
2249 widget emit its own type of signal when its adjustment changes, and
2250 either pass the new value to the signal handler, or require it to look
2251 inside the widget's data structure in order to ascertain the value.
2252 But you may also want to connect the adjustments of several widgets
2253 together, so that adjusting one adjusts the others. The most obvious
2254 example of this is connecting a scrollbar to a panning viewport or a
2255 scrolling text area. If each widget has its own way of setting or
2256 getting the adjustment value, then the programmer may have to write
2257 their own signal handlers to translate between the output of one
2258 widget's signal and the "input" of another's adjustment setting
2259 function.
2260
2261 GTK+ solves this problem using the GtkAdjustment object, which is a
2262 way for widgets to store and pass adjustment information in an
2263 abstract and flexible form. The most obvious use of GtkAdjustment is
2264 to store the configuration parameters and values of range widgets,
2265 such as scrollbars and scale controls. However, since GtkAdjustments
2266 are derived from GtkObject, they have some special powers beyond those
2267 of normal data structures. Most importantly, they can emit signals,
2268 just like widgets, and these signals can be used not only to allow
2269 your program to react to user input on adjustable widgets, but also to
2270 propagate adjustment values transparently between adjustable widgets.
2271
2272 <sect1> Creating an Adjustment
2273 <p>
2274 You create an adjustment using:
2275
2276 <tscreen><verb>
2277 GtkObject *gtk_adjustment_new( gfloat value,
2278                                gfloat lower,
2279                                gfloat upper,
2280                                gfloat step_increment,
2281                                gfloat page_increment,
2282                                gfloat page_size );
2283 </verb></tscreen>
2284
2285 The <tt/value/ argument is the initial value you want to give to the
2286 adjustment, usually corresponding to the topmost or leftmost position
2287 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2288 value which the adjustment can hold. The <tt/step_increment/ argument
2289 specifies the "smaller" of the two increments by which the user can
2290 change the value, while the <tt/page_increment/ is the "larger" one.
2291 The <tt/page_size/ argument usually corresponds somehow to the visible
2292 area of a panning widget. The <tt/upper/ argument is used to represent
2293 the bottom most or right most coordinate in a panning widget's
2294 child. Therefore it is <em/not/ always the largest number that
2295 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2296 usually non-zero.
2297
2298 <!-- ----------------------------------------------------------------- -->
2299 <sect1> Using Adjustments the Easy Way
2300 <p>
2301 The adjustable widgets can be roughly divided into those which use and
2302 require specific units for these values and those which treat them as
2303 arbitrary numbers. The group which treats the values as arbitrary
2304 numbers includes the range widgets (scrollbars and scales, the
2305 progress bar widget, and the spin button widget). These widgets are
2306 all the widgets which are typically "adjusted" directly by the user
2307 with the mouse or keyboard. They will treat the <tt/lower/ and
2308 <tt/upper/ values of an adjustment as a range within which the user
2309 can manipulate the adjustment's <tt/value/. By default, they will only
2310 modify the <tt/value/ of an adjustment.
2311
2312 The other group includes the text widget, the viewport widget, the
2313 compound list widget, and the scrolled window widget. All of these
2314 widgets use pixel values for their adjustments. These are also all
2315 widgets which are typically "adjusted" indirectly using scrollbars.
2316 While all widgets which use adjustments can either create their own
2317 adjustments or use ones you supply, you'll generally want to let this
2318 particular category of widgets create its own adjustments. Usually,
2319 they will eventually override all the values except the <tt/value/
2320 itself in whatever adjustments you give them, but the results are, in
2321 general, undefined (meaning, you'll have to read the source code to
2322 find out, and it may be different from widget to widget).
2323
2324 Now, you're probably thinking, since text widgets and viewports insist
2325 on setting everything except the <tt/value/ of their adjustments,
2326 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2327 you <em/share/ an adjustment object between a scrollbar and a text
2328 widget, manipulating the scrollbar will automagically adjust the text
2329 widget?  Of course it will! Just like this:
2330
2331 <tscreen><verb>
2332   /* creates its own adjustments */
2333   text = gtk_text_new (NULL, NULL);
2334   /* uses the newly-created adjustment for the scrollbar as well */
2335   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2336 </verb></tscreen>
2337
2338 </sect1>
2339 <!-- ----------------------------------------------------------------- -->
2340 <sect1> Adjustment Internals
2341 <p>
2342 Ok, you say, that's nice, but what if I want to create my own handlers
2343 to respond when the user adjusts a range widget or a spin button, and
2344 how do I get at the value of the adjustment in these handlers?  To
2345 answer these questions and more, let's start by taking a look at
2346 <tt>struct _GtkAdjustment</tt> itself:
2347
2348 <tscreen><verb>
2349 struct _GtkAdjustment
2350 {
2351   GtkData data;
2352   
2353   gfloat lower;
2354   gfloat upper;
2355   gfloat value;
2356   gfloat step_increment;
2357   gfloat page_increment;
2358   gfloat page_size;
2359 };     
2360 </verb></tscreen>
2361
2362 The first thing you should know is that there aren't any handy-dandy
2363 macros or accessor functions for getting the <tt/value/ out of a
2364 GtkAdjustment, so you'll have to (horror of horrors) do it like a
2365 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2366 (Object)</tt> macro does run-time type checking (as do all the GTK+
2367 type-casting macros, actually).
2368
2369 Since, when you set the <tt/value/ of an adjustment, you generally
2370 want the change to be reflected by every widget that uses this
2371 adjustment, GTK+ provides this convenience function to do this:
2372
2373 <tscreen><verb>
2374 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2375                                gfloat         value );
2376 </verb></tscreen>
2377
2378 As mentioned earlier, GtkAdjustment is a subclass of GtkObject just
2379 like all the various widgets, and thus it is able to emit signals.
2380 This is, of course, why updates happen automagically when you share an
2381 adjustment object between a scrollbar and another adjustable widget;
2382 all adjustable widgets connect signal handlers to their adjustment's
2383 <tt/value_changed/ signal, as can your program. Here's the definition
2384 of this signal in <tt/struct _GtkAdjustmentClass/:
2385
2386 <tscreen><verb>
2387   void (* value_changed) (GtkAdjustment *adjustment);
2388 </verb></tscreen>
2389
2390 The various widgets that use the GtkAdjustment object will emit this
2391 signal on an adjustment whenever they change its value. This happens
2392 both when user input causes the slider to move on a range widget, as
2393 well as when the program explicitly changes the value with
2394 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2395 widget, and you want to change the rotation of a picture whenever its
2396 value changes, you would create a callback like this:
2397
2398 <tscreen><verb>
2399 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2400 {
2401   set_picture_rotation (picture, adj->value);
2402 ...
2403 </verb></tscreen>
2404
2405 and connect it to the scale widget's adjustment like this:
2406
2407 <tscreen><verb>
2408 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2409                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2410 </verb></tscreen>
2411
2412 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2413 fields of its adjustment, such as when a user adds more text to a text
2414 widget?  In this case, it emits the <tt/changed/ signal, which looks
2415 like this:
2416
2417 <tscreen><verb>
2418   void (* changed)       (GtkAdjustment *adjustment);
2419 </verb></tscreen>
2420
2421 Range widgets typically connect a handler to this signal, which
2422 changes their appearance to reflect the change - for example, the size
2423 of the slider in a scrollbar will grow or shrink in inverse proportion
2424 to the difference between the <tt/lower/ and <tt/upper/ values of its
2425 adjustment.
2426
2427 You probably won't ever need to attach a handler to this signal,
2428 unless you're writing a new type of range widget.  However, if you
2429 change any of the values in a GtkAdjustment directly, you should emit
2430 this signal on it to reconfigure whatever widgets are using it, like
2431 this:
2432
2433 <tscreen><verb>
2434 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2435 </verb></tscreen>
2436
2437 Now go forth and adjust!
2438 </sect1>
2439 </sect>
2440
2441 <!-- ***************************************************************** -->
2442 <sect> Range Widgets<label id="sec_Range_Widgets">
2443 <!-- ***************************************************************** -->
2444
2445 <p>
2446 The category of range widgets includes the ubiquitous scrollbar widget
2447 and the less common "scale" widget. Though these two types of widgets
2448 are generally used for different purposes, they are quite similar in
2449 function and implementation. All range widgets share a set of common
2450 graphic elements, each of which has its own X window and receives
2451 events. They all contain a "trough" and a "slider" (what is sometimes
2452 called a "thumbwheel" in other GUI environments). Dragging the slider
2453 with the pointer moves it back and forth within the trough, while
2454 clicking in the trough advances the slider towards the location of the
2455 click, either completely, or by a designated amount, depending on
2456 which mouse button is used.
2457
2458 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2459 all range widgets are associated with an adjustment object, from which
2460 they calculate the length of the slider and its position within the
2461 trough. When the user manipulates the slider, the range widget will
2462 change the value of the adjustment.
2463
2464 <!-- ----------------------------------------------------------------- -->
2465 <sect1> Scrollbar Widgets
2466 <p>
2467 These are your standard, run-of-the-mill scrollbars. These should be
2468 used only for scrolling some other widget, such as a list, a text box,
2469 or a viewport (and it's generally easier to use the scrolled window
2470 widget in most cases).  For other purposes, you should use scale
2471 widgets, as they are friendlier and more featureful.
2472
2473 There are separate types for horizontal and vertical scrollbars.
2474 There really isn't much to say about these. You create them with the
2475 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2476 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2477
2478 <tscreen><verb>
2479 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2480
2481 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2482 </verb></tscreen>
2483
2484 and that's about it (if you don't believe me, look in the header
2485 files!).  The <tt/adjustment/ argument can either be a pointer to an
2486 existing GtkAdjustment, or NULL, in which case one will be created for
2487 you. Specifying NULL might actually be useful in this case, if you
2488 wish to pass the newly-created adjustment to the constructor function
2489 of some other widget which will configure it for you, such as a text
2490 widget.
2491 </sect1>
2492
2493 <!-- ----------------------------------------------------------------- -->
2494 <sect1> Scale Widgets
2495 <p>
2496 Scale widgets are used to allow the user to visually select and
2497 manipulate a value within a specific range. You might want to use a
2498 scale widget, for example, to adjust the magnification level on a
2499 zoomed preview of a picture, or to control the brightness of a colour,
2500 or to specify the number of minutes of inactivity before a screensaver
2501 takes over the screen.
2502
2503 <!-- ----------------------------------------------------------------- -->
2504 <sect2>Creating a Scale Widget
2505 <p>
2506 As with scrollbars, there are separate widget types for horizontal and
2507 vertical scale widgets. (Most programmers seem to favour horizontal
2508 scale widgets). Since they work essentially the same way, there's no
2509 need to treat them separately here. The following functions, defined
2510 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2511 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2512 widgets, respectively:
2513
2514 <tscreen>
2515 <verb>
2516 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2517
2518 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2519 </verb>
2520 </tscreen>
2521
2522 The <tt/adjustment/ argument can either be an adjustment which has
2523 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2524 which case, an anonymous GtkAdjustment is created with all of its
2525 values set to <tt/0.0/ (which isn't very useful in this case). In
2526 order to avoid confusing yourself, you probably want to create your
2527 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2528 value actually corresponds to the highest value the user can select.
2529 (If you're <em/already/ thoroughly confused, read the section on <ref
2530 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2531 what exactly adjustments do and how to create and manipulate them).
2532
2533 <!-- ----------------------------------------------------------------- -->
2534 <sect2> Functions and Signals (well, functions, at least)
2535 <p>
2536 Scale widgets can display their current value as a number beside the
2537 trough. The default behaviour is to show the value, but you can change
2538 this with this function:
2539
2540 <tscreen><verb>
2541 void gtk_scale_set_draw_value( GtkScale *scale,
2542                                gint      draw_value );
2543 </verb></tscreen>
2544
2545 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2546 <tt/FALSE/, with predictable consequences for either one.
2547
2548 The value displayed by a scale widget is rounded to one decimal point
2549 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2550 change this with:
2551
2552 <tscreen>
2553 <verb>
2554 void gtk_scale_set_digits( GtkScale *scale,
2555                             gint     digits );
2556 </verb>
2557 </tscreen>
2558
2559 where <tt/digits/ is the number of decimal places you want. You can
2560 set <tt/digits/ to anything you like, but no more than 13 decimal
2561 places will actually be drawn on screen.
2562
2563 Finally, the value can be drawn in different positions
2564 relative to the trough:
2565
2566 <tscreen>
2567 <verb>
2568 void gtk_scale_set_value_pos( GtkScale        *scale,
2569                               GtkPositionType  pos );
2570 </verb>
2571 </tscreen>
2572
2573 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2574 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2575 following values:
2576
2577 <itemize>
2578 <item> GTK_POS_LEFT
2579 <item> GTK_POS_RIGHT
2580 <item> GTK_POS_TOP
2581 <item> GTK_POS_BOTTOM
2582 </itemize>
2583
2584 If you position the value on the "side" of the trough (e.g. on the top
2585 or bottom of a horizontal scale widget), then it will follow the
2586 slider up and down the trough.
2587
2588 All the preceding functions are defined in
2589 <tt>&lt;gtk/gtkscale.h&gt;</tt>.
2590 </sect2>
2591 </sect1>
2592
2593 <!-- ----------------------------------------------------------------- -->
2594 <sect1> Common Functions <label id="sec_Range_Functions">
2595 <p>
2596 The GtkRange widget class is fairly complicated internally, but, like
2597 all the "base class" widgets, most of its complexity is only
2598 interesting if you want to hack on it. Also, almost all of the
2599 functions and signals it defines are only really used in writing
2600 derived widgets. There are, however, a few useful functions that are
2601 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2602 widgets.
2603
2604 <!-- ----------------------------------------------------------------- -->
2605 <sect2> Setting the Update Policy
2606 <p>
2607 The "update policy" of a range widget defines at what points during
2608 user interaction it will change the <tt/value/ field of its
2609 GtkAdjustment and emit the "value_changed" signal on this
2610 GtkAdjustment. The update policies, defined in
2611 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2612 are:
2613
2614 <itemize>
2615 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2616 "value_changed" signal is emitted continuously, i.e. whenever the
2617 slider is moved by even the tiniest amount.
2618 </item>
2619 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2620 only emitted once the slider has stopped moving and the user has
2621 released the mouse button.
2622 </item>
2623 <item>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emitted
2624 when the user releases the mouse button, or if the slider stops moving
2625 for a short period of time.
2626 </item>
2627 </itemize>
2628
2629 The update policy of a range widget can be set by casting it using the
2630 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2631
2632 <tscreen><verb>
2633 void gtk_range_set_update_policy( GtkRange      *range,
2634                                   GtkUpdateType  policy) ;
2635 </verb></tscreen>
2636
2637 <!-- ----------------------------------------------------------------- -->
2638 <sect2>Getting and Setting Adjustments
2639 <p>
2640 Getting and setting the adjustment for a range widget "on the fly" is
2641 done, predictably, with:
2642
2643 <tscreen><verb>
2644 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2645
2646 void gtk_range_set_adjustment( GtkRange      *range,
2647                                GtkAdjustment *adjustment );
2648 </verb></tscreen>
2649
2650 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2651 which <tt/range/ is connected.
2652
2653 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2654 the adjustment that <tt/range/ is already using, regardless of whether
2655 you changed any of its fields or not. If you pass it a new
2656 GtkAdjustment, it will unreference the old one if it exists (possibly
2657 destroying it), connect the appropriate signals to the new one, and
2658 call the private function <tt/gtk_range_adjustment_changed()/, which
2659 will (or at least, is supposed to...) recalculate the size and/or
2660 position of the slider and redraw if necessary. As mentioned in the
2661 section on adjustments, if you wish to reuse the same GtkAdjustment,
2662 when you modify its values directly, you should emit the "changed"
2663 signal on it, like this:
2664
2665 <tscreen><verb>
2666 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2667 </verb></tscreen>
2668 </sect2>
2669 </sect1>
2670
2671 <!-- ----------------------------------------------------------------- -->
2672 <sect1> Key and Mouse bindings
2673 <p>
2674 All of the GTK+ range widgets react to mouse clicks in more or less
2675 the same way. Clicking button-1 in the trough will cause its
2676 adjustment's <tt/page_increment/ to be added or subtracted from its
2677 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2678 button-2 in the trough will jump the slider to the point at which the
2679 button was clicked. Clicking any button on a scrollbar's arrows will
2680 cause its adjustment's value to change <tt/step_increment/ at a time.
2681
2682 It may take a little while to get used to, but by default, scrollbars
2683 as well as scale widgets can take the keyboard focus in GTK+. If you
2684 think your users will find this too confusing, you can always disable
2685 this by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:
2686
2687 <tscreen><verb>
2688 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2689 </verb></tscreen>
2690
2691 The key bindings (which are, of course, only active when the widget
2692 has focus) are slightly different between horizontal and vertical
2693 range widgets, for obvious reasons. They are also not quite the same
2694 for scale widgets as they are for scrollbars, for somewhat less
2695 obvious reasons (possibly to avoid confusion between the keys for
2696 horizontal and vertical scrollbars in scrolled windows, where both
2697 operate on the same area).
2698
2699 <sect2> Vertical Range Widgets
2700 <p>
2701 All vertical range widgets can be operated with the up and down arrow
2702 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2703 arrows move the slider up and down by <tt/step_increment/, while
2704 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2705
2706 The user can also move the slider all the way to one end or the other
2707 of the trough using the keyboard. With the GtkVScale widget, this is
2708 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2709 GtkVScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2710 and <tt>Control-Page Down</tt>.
2711
2712 <!-- ----------------------------------------------------------------- -->
2713 <sect2> Horizontal Range Widgets
2714 <p>
2715 The left and right arrow keys work as you might expect in these
2716 widgets, moving the slider back and forth by <tt/step_increment/. The
2717 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2718 For the GtkHScale widget, moving the slider by <tt/page_increment/ is
2719 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2720 while for GtkHScrollbar, it's done with <tt>Control-Home</tt> and
2721 <tt>Control-End</tt>.
2722 </sect2>
2723 </sect1>
2724
2725 <!-- ----------------------------------------------------------------- -->
2726 <sect1> Example<label id="sec_Range_Example">
2727 <p>
2728 This example is a somewhat modified version of the "range controls"
2729 test from <tt/testgtk.c/. It basically puts up a window with three
2730 range widgets all connected to the same adjustment, and a couple of
2731 controls for adjusting some of the parameters mentioned above and in
2732 the seciton on adjustments, so you can see how they affect the way
2733 these widgets work for the user.
2734
2735 <tscreen><verb>
2736 /* example-start rangewidgets rangewidgets.c */
2737
2738 #include <gtk/gtk.h>
2739
2740 GtkWidget *hscale, *vscale;
2741
2742 void cb_pos_menu_select( GtkWidget       *item,
2743                          GtkPositionType  pos )
2744 {
2745     /* Set the value position on both scale widgets */
2746     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2747     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2748 }
2749
2750 void cb_update_menu_select( GtkWidget     *item,
2751                             GtkUpdateType  policy )
2752 {
2753     /* Set the update policy for both scale widgets */
2754     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2755     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2756 }
2757
2758 void cb_digits_scale( GtkAdjustment *adj )
2759 {
2760     /* Set the number of decimal places to which adj->value is rounded */
2761     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2762     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2763 }
2764
2765 void cb_page_size( GtkAdjustment *get,
2766                    GtkAdjustment *set )
2767 {
2768     /* Set the page size and page increment size of the sample
2769      * adjustment to the value specified by the "Page Size" scale */
2770     set->page_size = get->value;
2771     set->page_increment = get->value;
2772     /* Now emit the "changed" signal to reconfigure all the widgets that
2773      * are attached to this adjustment */
2774     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2775 }
2776
2777 void cb_draw_value( GtkToggleButton *button )
2778 {
2779     /* Turn the value display on the scale widgets off or on depending
2780      *  on the state of the checkbutton */
2781     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2782     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2783 }
2784
2785 /* Convenience functions */
2786
2787 GtkWidget *make_menu_item( gchar         *name,
2788                            GtkSignalFunc  callback,
2789                            gpointer       data )
2790 {
2791     GtkWidget *item;
2792   
2793     item = gtk_menu_item_new_with_label (name);
2794     gtk_signal_connect (GTK_OBJECT (item), "activate",
2795                         callback, data);
2796     gtk_widget_show (item);
2797
2798     return(item);
2799 }
2800
2801 void scale_set_default_values( GtkScale *scale )
2802 {
2803     gtk_range_set_update_policy (GTK_RANGE (scale),
2804                                  GTK_UPDATE_CONTINUOUS);
2805     gtk_scale_set_digits (scale, 1);
2806     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2807     gtk_scale_set_draw_value (scale, TRUE);
2808 }
2809
2810 /* makes the sample window */
2811
2812 void create_range_controls( void )
2813 {
2814     GtkWidget *window;
2815     GtkWidget *box1, *box2, *box3;
2816     GtkWidget *button;
2817     GtkWidget *scrollbar;
2818     GtkWidget *separator;
2819     GtkWidget *opt, *menu, *item;
2820     GtkWidget *label;
2821     GtkWidget *scale;
2822     GtkObject *adj1, *adj2;
2823
2824     /* Standard window-creating stuff */
2825     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2826     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2827                         GTK_SIGNAL_FUNC(gtk_main_quit),
2828                         NULL);
2829     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2830
2831     box1 = gtk_vbox_new (FALSE, 0);
2832     gtk_container_add (GTK_CONTAINER (window), box1);
2833     gtk_widget_show (box1);
2834
2835     box2 = gtk_hbox_new (FALSE, 10);
2836     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2837     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2838     gtk_widget_show (box2);
2839
2840     /* calue, lower, upper, step_increment, page_increment, page_size */
2841     /* Note that the page_size value only makes a difference for
2842      * scrollbar widgets, and the highest value you'll get is actually
2843      * (upper - page_size). */
2844     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2845   
2846     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2847     scale_set_default_values (GTK_SCALE (vscale));
2848     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2849     gtk_widget_show (vscale);
2850
2851     box3 = gtk_vbox_new (FALSE, 10);
2852     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2853     gtk_widget_show (box3);
2854
2855     /* Reuse the same adjustment */
2856     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2857     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2858     scale_set_default_values (GTK_SCALE (hscale));
2859     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2860     gtk_widget_show (hscale);
2861
2862     /* Reuse the same adjustment again */
2863     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2864     /* Notice how this causes the scales to always be updated
2865      * continuously when the scrollbar is moved */
2866     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2867                                  GTK_UPDATE_CONTINUOUS);
2868     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2869     gtk_widget_show (scrollbar);
2870
2871     box2 = gtk_hbox_new (FALSE, 10);
2872     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2873     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2874     gtk_widget_show (box2);
2875
2876     /* A checkbutton to control whether the value is displayed or not */
2877     button = gtk_check_button_new_with_label("Display value on scale widgets");
2878     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2879     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2880                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2881     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2882     gtk_widget_show (button);
2883   
2884     box2 = gtk_hbox_new (FALSE, 10);
2885     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2886
2887     /* An option menu to change the position of the value */
2888     label = gtk_label_new ("Scale Value Position:");
2889     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2890     gtk_widget_show (label);
2891   
2892     opt = gtk_option_menu_new();
2893     menu = gtk_menu_new();
2894
2895     item = make_menu_item ("Top",
2896                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2897                            GINT_TO_POINTER (GTK_POS_TOP));
2898     gtk_menu_append (GTK_MENU (menu), item);
2899   
2900     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2901                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2902     gtk_menu_append (GTK_MENU (menu), item);
2903   
2904     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2905                            GINT_TO_POINTER (GTK_POS_LEFT));
2906     gtk_menu_append (GTK_MENU (menu), item);
2907   
2908     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2909                             GINT_TO_POINTER (GTK_POS_RIGHT));
2910     gtk_menu_append (GTK_MENU (menu), item);
2911   
2912     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2913     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2914     gtk_widget_show (opt);
2915
2916     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2917     gtk_widget_show (box2);
2918
2919     box2 = gtk_hbox_new (FALSE, 10);
2920     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2921
2922     /* Yet another option menu, this time for the update policy of the
2923      * scale widgets */
2924     label = gtk_label_new ("Scale Update Policy:");
2925     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2926     gtk_widget_show (label);
2927   
2928     opt = gtk_option_menu_new();
2929     menu = gtk_menu_new();
2930   
2931     item = make_menu_item ("Continuous",
2932                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2933                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2934     gtk_menu_append (GTK_MENU (menu), item);
2935   
2936     item = make_menu_item ("Discontinuous",
2937                             GTK_SIGNAL_FUNC (cb_update_menu_select),
2938                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2939     gtk_menu_append (GTK_MENU (menu), item);
2940   
2941     item = make_menu_item ("Delayed",
2942                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2943                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2944     gtk_menu_append (GTK_MENU (menu), item);
2945   
2946     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2947     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2948     gtk_widget_show (opt);
2949   
2950     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2951     gtk_widget_show (box2);
2952
2953     box2 = gtk_hbox_new (FALSE, 10);
2954     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2955   
2956     /* A GtkHScale widget for adjusting the number of digits on the
2957      * sample scales. */
2958     label = gtk_label_new ("Scale Digits:");
2959     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2960     gtk_widget_show (label);
2961
2962     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
2963     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2964                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
2965     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2966     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2967     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2968     gtk_widget_show (scale);
2969
2970     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2971     gtk_widget_show (box2);
2972   
2973     box2 = gtk_hbox_new (FALSE, 10);
2974     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2975   
2976     /* And, one last GtkHScale widget for adjusting the page size of the
2977      * scrollbar. */
2978     label = gtk_label_new ("Scrollbar Page Size:");
2979     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2980     gtk_widget_show (label);
2981
2982     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
2983     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
2984                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
2985     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
2986     gtk_scale_set_digits (GTK_SCALE (scale), 0);
2987     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
2988     gtk_widget_show (scale);
2989
2990     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2991     gtk_widget_show (box2);
2992
2993     separator = gtk_hseparator_new ();
2994     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2995     gtk_widget_show (separator);
2996
2997     box2 = gtk_vbox_new (FALSE, 10);
2998     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2999     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3000     gtk_widget_show (box2);
3001
3002     button = gtk_button_new_with_label ("Quit");
3003     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3004                                GTK_SIGNAL_FUNC(gtk_main_quit),
3005                                NULL);
3006     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3007     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3008     gtk_widget_grab_default (button);
3009     gtk_widget_show (button);
3010
3011     gtk_widget_show (window);
3012 }
3013
3014 int main( int   argc,
3015           char *argv[] )
3016 {
3017     gtk_init(&amp;argc, &amp;argv);
3018
3019     create_range_controls();
3020
3021     gtk_main();
3022
3023     return(0);
3024 }
3025
3026 /* example-end */
3027 </verb></tscreen>
3028 </sect1>
3029 </sect>
3030
3031 <!-- ***************************************************************** -->
3032 <sect> Miscellaneous Widgets
3033 <!-- ***************************************************************** -->
3034
3035 <!-- ----------------------------------------------------------------- -->
3036 <sect1> Labels
3037 <p>
3038 Labels are used a lot in GTK, and are relatively simple. Labels emit
3039 no signals as they do not have an associated X window. If you need to
3040 catch signals, or do clipping, use the <ref id="sec_EventBox"
3041 name="EventBox"> widget.
3042
3043 To create a new label, use:
3044
3045 <tscreen><verb>
3046 GtkWidget *gtk_label_new( char *str );
3047 </verb></tscreen>
3048
3049 Where the sole argument is the string you wish the label to display.
3050
3051 To change the label's text after creation, use the function:
3052
3053 <tscreen><verb>
3054 void gtk_label_set_text( GtkLabel *label,
3055                          char     *str );
3056 </verb></tscreen>
3057
3058 Where the first argument is the label you created previously (cast
3059 using the GTK_LABEL() macro), and the second is the new string.
3060
3061 The space needed for the new string will be automatically adjusted if
3062 needed. You can produce multi-line labels by putting line breaks in
3063 the label string.
3064
3065 To retrieve the current string, use:
3066
3067 <tscreen><verb>
3068 void gtk_label_get( GtkLabel  *label,
3069                     char     **str );
3070 </verb></tscreen>
3071
3072 Where the first argument is the label you've created, and the second,
3073 the return for the string. Do not free the return string, as it is
3074 used internally by GTK.
3075
3076 The label text can be justified using:
3077
3078 <tscreen><verb>
3079 void gtk_label_set_justify( GtkLabel         *label,
3080                             GtkJustification  jtype );
3081 </verb></tscreen>
3082
3083 Values for <tt/jtype/ are:
3084 <itemize>
3085 <item> GTK_JUSTIFY_LEFT
3086 <item> GTK_JUSTIFY_RIGHT
3087 <item> GTK_JUSTIFY_CENTER (the default)
3088 <item> GTK_JUSTIFY_FILL
3089 </itemize>
3090
3091 The label widget is also capable of line wrapping the text
3092 automatically. This can be activated using:
3093
3094 <tscreen><verb>
3095 void gtk_label_set_line_wrap (GtkLabel *label,
3096                               gboolean  wrap);
3097 </verb></tscreen>
3098
3099 The <//wrap/ argument takes a TRUE or FALSE value.
3100
3101 If you want your label underlined, then you can set a pattern on the
3102 label:
3103
3104 <tscreen><verb>
3105 void       gtk_label_set_pattern   (GtkLabel          *label,
3106                                     const gchar       *pattern);
3107 </verb></tscreen>
3108
3109 The pattern argument indicates how the underlining should look. It
3110 consists of a string of underscore and space characters. An underscore
3111 indicates that the corresponding character in the label should be
3112 underlined. For example, the string <verb/"__     __"/ would underline the
3113 first two characters and eigth and ninth characters.
3114
3115 Below is a short example to illustrate these functions. This example
3116 makes use of the Frame widget to better demonstrate the label
3117 styles. You can ignore this for now as the <ref id="sec_Frames"
3118 name="Frame"> widget is explained later on.
3119
3120 <tscreen><verb>
3121 /* example-start label label.c */
3122
3123 #include <gtk/gtk.h>
3124
3125 int main( int   argc,
3126           char *argv[] )
3127 {
3128   static GtkWidget *window = NULL;
3129   GtkWidget *hbox;
3130   GtkWidget *vbox;
3131   GtkWidget *frame;
3132   GtkWidget *label;
3133
3134   /* Initialise GTK */
3135   gtk_init(&amp;argc, &amp;argv);
3136
3137   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3138   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3139                       GTK_SIGNAL_FUNC(gtk_main_quit),
3140                       NULL);
3141
3142   gtk_window_set_title (GTK_WINDOW (window), "Label");
3143   vbox = gtk_vbox_new (FALSE, 5);
3144   hbox = gtk_hbox_new (FALSE, 5);
3145   gtk_container_add (GTK_CONTAINER (window), hbox);
3146   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3147   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3148   
3149   frame = gtk_frame_new ("Normal Label");
3150   label = gtk_label_new ("This is a Normal label");
3151   gtk_container_add (GTK_CONTAINER (frame), label);
3152   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3153   
3154   frame = gtk_frame_new ("Multi-line Label");
3155   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3156                          "Third line");
3157   gtk_container_add (GTK_CONTAINER (frame), label);
3158   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3159   
3160   frame = gtk_frame_new ("Left Justified Label");
3161   label = gtk_label_new ("This is a Left-Justified\n" \
3162                          "Multi-line label.\nThird      line");
3163   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3164   gtk_container_add (GTK_CONTAINER (frame), label);
3165   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3166   
3167   frame = gtk_frame_new ("Right Justified Label");
3168   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3169                          "Fourth line, (j/k)");
3170   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3171   gtk_container_add (GTK_CONTAINER (frame), label);
3172   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3173
3174   vbox = gtk_vbox_new (FALSE, 5);
3175   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3176   frame = gtk_frame_new ("Line wrapped label");
3177   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3178                          "should not be taking up the entire             " /* big space to test spacing */\
3179                          "width allocated to it, but automatically " \
3180                          "wraps the words to fit.  " \
3181                          "The time has come, for all good men, to come to " \
3182                          "the aid of their party.  " \
3183                          "The sixth sheik's six sheep's sick.\n" \
3184                          "     It supports multiple paragraphs correctly, " \
3185                          "and  correctly   adds "\
3186                          "many          extra  spaces. ");
3187   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3188   gtk_container_add (GTK_CONTAINER (frame), label);
3189   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3190   
3191   frame = gtk_frame_new ("Filled, wrapped label");
3192   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3193                          "It should be taking "\
3194                          "up the entire              width allocated to it.  " \
3195                          "Here is a seneance to prove "\
3196                          "my point.  Here is another sentence. "\
3197                          "Here comes the sun, do de do de do.\n"\
3198                          "    This is a new paragraph.\n"\
3199                          "    This is another newer, longer, better " \
3200                          "paragraph.  It is coming to an end, "\
3201                          "unfortunately.");
3202   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3203   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3204   gtk_container_add (GTK_CONTAINER (frame), label);
3205   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3206   
3207   frame = gtk_frame_new ("Underlined label");
3208   label = gtk_label_new ("This label is underlined!\n"
3209                          "This one is underlined in quite a funky fashion");
3210   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3211   gtk_label_set_pattern (GTK_LABEL (label),
3212                          "_________________________ _ _________ _ ______     __ _______ ___");
3213   gtk_container_add (GTK_CONTAINER (frame), label);
3214   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3215   
3216   gtk_widget_show_all (window);
3217
3218   gtk_main ();
3219   
3220   return(0);
3221 }
3222 /* example-end */
3223 </verb></tscreen>
3224
3225 <!-- ----------------------------------------------------------------- -->
3226 <sect1> Arrows
3227 <p>
3228 The Arrow widget draws an arrowhead, facing in a number of possible
3229 directions and having a number of possible styles. It can be very
3230 useful when placed on a button in many applications.
3231
3232 There are only two functions for manipulating an Arrow widget:
3233
3234 <tscreen><verb>
3235 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3236                           GtkShadowType  shadow_type );
3237
3238 void gtk_arrow_set( GtkArrow      *arrow,
3239                     GtkArrowType   arrow_type,
3240                     GtkShadowType  shadow_type );
3241 </verb></tscreen>
3242
3243 The first creates a new arrow widget with the indicated type and
3244 appearance. The second allows these values to be altered
3245 retrospectively. The <tt/arrow_type/ argument may take one of the
3246 following values:
3247
3248 <itemize>
3249 <item> GTK_ARROW_UP
3250 <item> GTK_ARROW_DOWN
3251 <item> GTK_ARROW_LEFT
3252 <item> GTK_ARROW_RIGHT
3253 </itemize>
3254
3255 These values obviously indicate the direction in which the arrow will
3256 point. The <tt/shadow_type/ argument may take one of these values:
3257
3258 <itemize>
3259 <item> GTK_SHADOW_IN
3260 <item> GTK_SHADOW_OUT (the default)
3261 <item> GTK_SHADOW_ETCHED_IN
3262 <item> GTK_SHADOW_ETCHED_OUT
3263 </itemize>
3264
3265 Here's a brief example to illustrate their use.
3266
3267 <tscreen><verb>
3268 /* example-start arrow arrow.c */
3269
3270 #include <gtk/gtk.h>
3271
3272 /* Create an Arrow widget with the specified parameters
3273  * and pack it into a button */
3274 GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3275                                 GtkShadowType shadow_type )
3276 {
3277   GtkWidget *button;
3278   GtkWidget *arrow;
3279
3280   button = gtk_button_new();
3281   arrow = gtk_arrow_new (arrow_type, shadow_type);
3282
3283   gtk_container_add (GTK_CONTAINER (button), arrow);
3284   
3285   gtk_widget_show(button);
3286   gtk_widget_show(arrow);
3287
3288   return(button);
3289 }
3290
3291 int main( int   argc,
3292           char *argv[] )
3293 {
3294   /* GtkWidget is the storage type for widgets */
3295   GtkWidget *window;
3296   GtkWidget *button;
3297   GtkWidget *box;
3298
3299   /* Initialize the toolkit */
3300   gtk_init (&amp;argc, &amp;argv);
3301
3302   /* Create a new window */
3303   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3304
3305   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3306
3307   /* It's a good idea to do this for all windows. */
3308   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3309                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3310
3311   /* Sets the border width of the window. */
3312   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3313
3314   /* Create a box to hold the arrows/buttons */
3315   box = gtk_hbox_new (FALSE, 0);
3316   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3317   gtk_container_add (GTK_CONTAINER (window), box);
3318
3319   /* Pack and show all our widgets */
3320   gtk_widget_show(box);
3321
3322   button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN);
3323   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3324
3325   button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3326   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3327   
3328   button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3329   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3330   
3331   button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3332   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3333   
3334   gtk_widget_show (window);
3335   
3336   /* Rest in gtk_main and wait for the fun to begin! */
3337   gtk_main ();
3338   
3339   return(0);
3340 }
3341 /* example-end */
3342 </verb></tscreen>
3343
3344 <!-- ----------------------------------------------------------------- -->
3345 <sect1>The Tooltips Widget
3346 <p>
3347 These are the little text strings that pop up when you leave your
3348 pointer over a button or other widget for a few seconds. They are easy
3349 to use, so I will just explain them without giving an example. If you
3350 want to see some code, take a look at the testgtk.c program
3351 distributed with GTK.
3352
3353 Widgets that do not receieve events (widgets that do not have their
3354 own window) will not work with tooltips.
3355
3356 The first call you will use creates a new tooltip. You only need to do
3357 this once for a set of tooltips as the <tt/GtkTooltip/ object this
3358 function returns can be used to create multiple tooltips.
3359
3360 <tscreen><verb>
3361 GtkTooltips *gtk_tooltips_new( void );
3362 </verb></tscreen>
3363
3364 Once you have created a new tooltip, and the widget you wish to use it
3365 on, simply use this call to set it:
3366
3367 <tscreen><verb>
3368 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3369                            GtkWidget   *widget,
3370                            const gchar *tip_text,
3371                            const gchar *tip_private );
3372 </verb></tscreen>
3373
3374 The first argument is the tooltip you've already created, followed by
3375 the widget you wish to have this tooltip pop up for, and the text you
3376 wish it to say. The last argument is a text string that can be used as
3377 an identifier when using GtkTipsQuery to implement context sensitive
3378 help. For now, you can set it to NULL.
3379
3380 <!-- TODO: sort out what how to do the context sensitive help -->
3381
3382 Here's a short example:
3383
3384 <tscreen><verb>
3385 GtkTooltips *tooltips;
3386 GtkWidget *button;
3387 .
3388 .
3389 .
3390 tooltips = gtk_tooltips_new ();
3391 button = gtk_button_new_with_label ("button 1");
3392 .
3393 .
3394 .
3395 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3396 </verb></tscreen>
3397
3398 There are other calls that can be used with tooltips. I will just list
3399 them with a brief description of what they do.
3400
3401 <tscreen><verb>
3402 void gtk_tooltips_enable( GtkTooltips *tooltips );
3403 </verb></tscreen>
3404
3405 Enable a disabled set of tooltips.
3406
3407 <tscreen><verb>
3408 void gtk_tooltips_disable( GtkTooltips *tooltips );
3409 </verb></tscreen>
3410
3411 Disable an enabled set of tooltips.
3412
3413 <tscreen><verb>
3414 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3415                              gint         delay );
3416
3417 </verb></tscreen>
3418
3419 Sets how many milliseconds you have to hold your pointer over the
3420 widget before the tooltip will pop up. The default is 500
3421 milliseconds (half a second).
3422
3423 <tscreen><verb>
3424 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3425                               GdkColor    *background,
3426                               GdkColor    *foreground );
3427 </verb></tscreen>
3428
3429 Set the foreground and background color of the tooltips.
3430
3431 And that's all the functions associated with tooltips. More than
3432 you'll ever want to know :-)
3433
3434 <!-- ----------------------------------------------------------------- -->
3435 <sect1> Progress Bars <label id="sec_ProgressBar">
3436 <p>
3437 Progress bars are used to show the status of an operation. They are
3438 pretty easy to use, as you will see with the code below. But first
3439 lets start out with the calls to create a new progress bar.
3440
3441 There are two ways to create a progress bar, one simple that takes
3442 no arguments, and one that takes a GtkAdjustment object as an
3443 argument. If the former is used, the progress bar creates its own
3444 adjustment object.
3445
3446 <tscreen><verb>
3447 GtkWidget *gtk_progress_bar_new( void );
3448
3449 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3450 </verb></tscreen>
3451
3452 The second method has the advantage that we can use the adjustment
3453 object to specify our own range parameters for the progress bar.
3454
3455 Now that the progress bar has been created we can use it.
3456
3457 <tscreen><verb>
3458 void gtk_progress_bar_update( GtkProgressBar *pbar,
3459                               gfloat          percentage );
3460 </verb></tscreen>
3461
3462 The first argument is the progress bar you wish to operate on, and the
3463 second argument is the amount 'completed', meaning the amount the
3464 progress bar has been filled from 0-100%. This is passed to the
3465 function as a real number ranging from 0 to 1.
3466
3467 GTK v1.2 has added new functionality to the progress bar that enables
3468 it to display its value in different ways, and to inform the user of
3469 its current value and its range.
3470
3471 A progress bar may be set to one of a number of orientations using the
3472 function
3473
3474 <tscreen><verb>
3475 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3476                                        GtkProgressBarOrientation orientation );
3477 </verb></tscreen>
3478
3479 Where the <tt/orientation/ argument may take one of the following
3480 values to indicate the direction in which the progress bar moves:
3481
3482 <itemize>
3483 <item> GTK_PROGRESS_LEFT_TO_RIGHT
3484 <item> GTK_PROGRESS_RIGHT_TO_LEFT
3485 <item> GTK_PROGRESS_BOTTOM_TO_TOP
3486 <item> GTK_PROGRESS_TOP_TO_BOTTOM
3487 </itemize>
3488
3489 When used as a measure of how far a process has progressed, the
3490 GtkProgressBar can be set to display its value in either a continuous
3491 or discrete mode. In continuous mode, the progress bar is updated for
3492 each value. In discrete mode, the progress bar is updated in a number
3493 of discrete blocks. The number of blocks is also configurable.
3494
3495 The style of a progress bar can be set using the following function.
3496
3497 <tscreen><verb>
3498 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3499                                      GtkProgressBarStyle  style );
3500 </verb></tscreen>
3501
3502 The <tt/style/ parameter can take one of two values:
3503
3504 <itemize>
3505 <item>GTK_PROGRESS_CONTINUOUS
3506 <item>GTK_PROGRESS_DISCRETE
3507 </itemize>
3508
3509 The number of discrete blocks can be set by calling
3510
3511 <tscreen><verb>
3512 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3513                                            guint           blocks );
3514 </verb></tscreen>
3515
3516 As well as indicating the amount of progress that has occured, the
3517 progress bar may be set to just indicate that there is some
3518 activity. This can be useful in situations where progress cannot be
3519 measured against a value range. Activity mode is not effected by the
3520 bar style that is described above, and overrides it.This mode is
3521 selected by the following function.
3522
3523 <tscreen><verb>
3524 void gtk_progress_set_activity_mode( GtkProgress *progress,
3525                                      guint        activity_mode );
3526 </verb></tscreen>
3527
3528 The step size of the activity indicator, and the number of blocks are
3529 set using the following functions.
3530
3531 <tscreen><verb>
3532 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3533                                          guint           step );
3534
3535 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3536                                            guint           blocks );
3537 </verb></tscreen>
3538
3539 When in continuous mode, the progress bar can also display a
3540 configurable text string within its trough, using the following
3541 function.
3542
3543 <tscreen><verb>
3544 void gtk_progress_set_format_string( GtkProgress *progress,
3545                                      gchar       *format);
3546 </verb></tscreen>
3547
3548 The <tt/format/ argument is similiar to one that would be used in a C
3549 <tt/printf/ statement. The following directives may be used within the
3550 format string:
3551
3552 <itemize>
3553 <item> %p - percentage
3554 <item> %v - value
3555 <item> %l - lower range value
3556 <item> %u - upper range value
3557 </itemize>
3558  
3559 Progress Bars are usually used with timeouts or other such functions
3560 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3561 Functions">) to give the illusion of multitasking. All will employ the
3562 gtk_progress_bar_update function in the same manner.
3563
3564 Here is an example of the progress bar, updated using timeouts.  This
3565 code also shows you how to reset the Progress Bar.
3566
3567 <tscreen><verb>
3568 /* example-start progressbar progressbar.c */
3569
3570 #include <gtk/gtk.h>
3571
3572 typedef struct _ProgressData {
3573     GtkWidget *window;
3574     GtkWidget *pbar;
3575     int timer;
3576 } ProgressData;
3577
3578 /* Update the value of the progress bar so that we get
3579  * some movement */
3580 gint progress_timeout( gpointer data )
3581 {
3582     gfloat new_val;
3583     GtkAdjustment *adj;
3584
3585     adj = GTK_PROGRESS (data)->adjustment;
3586
3587     /* Calculate the value of the progress bar using the
3588      * value range set in the adjustment object */
3589     new_val = adj->value + 1;
3590     if (new_val > adj->upper)
3591       new_val = adj->lower;
3592
3593     /* Set the new value */
3594     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3595
3596     /* As this is a timeout function, return TRUE so that it
3597      * continues to get called */
3598     return(TRUE);
3599
3600
3601 /* Callback that toggles the text display within the progress
3602  * bar trough */
3603 void toggle_show_text( GtkWidget    *widget,
3604                        ProgressData *pdata )
3605 {
3606     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3607                                 GTK_TOGGLE_BUTTON (widget)->active);
3608 }
3609
3610 /* Callback that toggles the activity mode of the progress
3611  * bar */
3612 void toggle_activity_mode( GtkWidget    *widget,
3613                            ProgressData *pdata )
3614 {
3615     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3616                                     GTK_TOGGLE_BUTTON (widget)->active);
3617 }
3618
3619 /* Callback that toggles the continuous mode of the progress
3620  * bar */
3621 void set_continuous_mode( GtkWidget    *widget,
3622                           ProgressData *pdata )
3623 {
3624     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3625                                     GTK_PROGRESS_CONTINUOUS);
3626 }
3627
3628 /* Callback that toggles the discrete mode of the progress
3629  * bar */
3630 void set_discrete_mode( GtkWidget    *widget,
3631                         ProgressData *pdata )
3632 {
3633     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3634                                     GTK_PROGRESS_DISCRETE);
3635 }
3636  
3637 /* Clean up allocated memory and remove the timer */
3638 void destroy_progress( GtkWidget     *widget,
3639                        ProgressData *pdata)
3640 {
3641     gtk_timeout_remove (pdata->timer);
3642     pdata->timer = 0;
3643     pdata->window = NULL;
3644     g_free(pdata);
3645     gtk_main_quit();
3646 }
3647
3648 int main( int   argc,
3649           char *argv[])
3650 {
3651     ProgressData *pdata;
3652     GtkWidget *align;
3653     GtkWidget *separator;
3654     GtkWidget *table;
3655     GtkAdjustment *adj;
3656     GtkWidget *button;
3657     GtkWidget *check;
3658     GtkWidget *vbox;
3659
3660     gtk_init (&amp;argc, &amp;argv);
3661
3662     /* Allocate memory for the data that is passwd to the callbacks */
3663     pdata = g_malloc( sizeof(ProgressData) );
3664   
3665     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3666     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3667
3668     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3669                         GTK_SIGNAL_FUNC (destroy_progress),
3670                         pdata);
3671     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3672     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3673
3674     vbox = gtk_vbox_new (FALSE, 5);
3675     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3676     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3677     gtk_widget_show(vbox);
3678   
3679     /* Create a centering alignment object */
3680     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3681     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3682     gtk_widget_show(align);
3683
3684     /* Create a GtkAdjusment object to hold the range of the
3685      * progress bar */
3686     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3687
3688     /* Create the GtkProgressBar using the adjustment */
3689     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3690
3691     /* Set the format of the string that can be displayed in the
3692      * trough of the progress bar:
3693      * %p - percentage
3694      * %v - value
3695      * %l - lower range value
3696      * %u - upper range value */
3697     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3698                                     "%v from [%l-%u] (=%p%%)");
3699     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3700     gtk_widget_show(pdata->pbar);
3701
3702     /* Add a timer callback to update the value of the progress bar */
3703     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3704
3705     separator = gtk_hseparator_new ();
3706     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3707     gtk_widget_show(separator);
3708
3709     /* rows, columns, homogeneous */
3710     table = gtk_table_new (2, 3, FALSE);
3711     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3712     gtk_widget_show(table);
3713
3714     /* Add a check button to select displaying of the trough text */
3715     check = gtk_check_button_new_with_label ("Show text");
3716     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3717                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3718                       5, 5);
3719     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3720                         GTK_SIGNAL_FUNC (toggle_show_text),
3721                         pdata);
3722     gtk_widget_show(check);
3723
3724     /* Add a check button to toggle activity mode */
3725     check = gtk_check_button_new_with_label ("Activity mode");
3726     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3727                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3728                       5, 5);
3729     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3730                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3731                         pdata);
3732     gtk_widget_show(check);
3733
3734     separator = gtk_vseparator_new ();
3735     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3736                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3737                       5, 5);
3738     gtk_widget_show(separator);
3739
3740     /* Add a radio button to select continuous display mode */
3741     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3742     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3743                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3744                       5, 5);
3745     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3746                         GTK_SIGNAL_FUNC (set_continuous_mode),
3747                         pdata);
3748     gtk_widget_show (button);
3749
3750     /* Add a radio button to select discrete display mode */
3751     button = gtk_radio_button_new_with_label(
3752                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3753                "Discrete");
3754     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3755                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3756                       5, 5);
3757     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3758                         GTK_SIGNAL_FUNC (set_discrete_mode),
3759                         pdata);
3760     gtk_widget_show (button);
3761
3762     separator = gtk_hseparator_new ();
3763     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3764     gtk_widget_show(separator);
3765
3766     /* Add a button to exit the program */
3767     button = gtk_button_new_with_label ("close");
3768     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3769                                (GtkSignalFunc) gtk_widget_destroy,
3770                                GTK_OBJECT (pdata->window));
3771     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3772
3773     /* This makes it so the button is the default. */
3774     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3775
3776     /* This grabs this button to be the default button. Simply hitting
3777      * the "Enter" key will cause this button to activate. */
3778     gtk_widget_grab_default (button);
3779     gtk_widget_show(button);
3780
3781     gtk_widget_show (pdata->window);
3782
3783     gtk_main ();
3784     
3785     return(0);
3786 }
3787 /* example-end */
3788 </verb></tscreen>
3789
3790 <!-- ----------------------------------------------------------------- -->
3791 <sect1> Dialogs
3792 <p>
3793 The Dialog widget is very simple, and is actually just a window with a
3794 few things pre-packed into it for you. The structure for a Dialog is:
3795
3796 <tscreen><verb>
3797 struct GtkDialog
3798 {
3799       GtkWindow window;
3800     
3801       GtkWidget *vbox;
3802       GtkWidget *action_area;
3803 };
3804 </verb></tscreen>
3805
3806 So you see, it simply creates a window, and then packs a vbox into the
3807 top, then a separator, and then an hbox for the "action_area".
3808
3809 The Dialog widget can be used for pop-up messages to the user, and
3810 other similar tasks. It is really basic, and there is only one
3811 function for the dialog box, which is:
3812
3813 <tscreen><verb>
3814 GtkWidget *gtk_dialog_new( void );
3815 </verb></tscreen>
3816
3817 So to create a new dialog box, use,
3818
3819 <tscreen><verb>
3820     GtkWidget *window;
3821     window = gtk_dialog_new ();
3822 </verb></tscreen>
3823
3824 This will create the dialog box, and it is now up to you to use it.
3825 you could pack a button in the action_area by doing something like this:
3826
3827 <tscreen><verb>
3828     button = ...
3829     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3830                         button, TRUE, TRUE, 0);
3831     gtk_widget_show (button);
3832 </verb></tscreen>
3833
3834 And you could add to the vbox area by packing, for instance, a label 
3835 in it, try something like this:
3836
3837 <tscreen><verb>
3838     label = gtk_label_new ("Dialogs are groovy");
3839     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3840                         label, TRUE, TRUE, 0);
3841     gtk_widget_show (label);
3842 </verb></tscreen>
3843
3844 As an example in using the dialog box, you could put two buttons in
3845 the action_area, a Cancel button and an Ok button, and a label in the
3846 vbox area, asking the user a question or giving an error etc. Then
3847 you could attach a different signal to each of the buttons and perform
3848 the operation the user selects.
3849
3850 If the simple functionality provided by the default vertical and
3851 horizontal boxes in the two areas does't give you enough control for
3852 your application, then you can simply pack another layout widget into
3853 the boxes provided. For example, you could pack a table into the
3854 vertical box.
3855
3856 <!-- ----------------------------------------------------------------- -->
3857 <sect1> Pixmaps <label id="sec_Pixmaps">
3858 <p>
3859 Pixmaps are data structures that contain pictures. These pictures can
3860 be used in various places, but most visibly as icons on the X-Windows
3861 desktop, or as cursors.
3862
3863 A pixmap which only has 2 colors is called a bitmap, and there are a
3864 few additional routines for handling this common special case.
3865
3866 To understand pixmaps, it would help to understand how X-windows
3867 works. Under X-windows, applications do not need to be running on the
3868 same computer that is interacting with the user. Instead, the various
3869 applications, called "clients", all communicate with a program which
3870 displays the graphics and handles the keyboard and mouse. This
3871 program which interacts directly with the user is called a "display
3872 server" or "X server." Since the communication might take place over
3873 a network, it's important to keep some information with the X server.
3874 Pixmaps, for example, are stored in the memory of the X server. This
3875 means that once pixmap values are set, they don't need to keep getting
3876 transmitted over the network; instead a command is sent to "display
3877 pixmap number XYZ here." Even if you aren't using X-windows with GTK
3878 currently, using constructs such as Pixmaps will make your programs
3879 work acceptably under X-windows.
3880
3881 To use pixmaps in GTK, we must first build a GdkPixmap structure using
3882 routines from the GDK layer. Pixmaps can either be created from
3883 in-memory data, or from data read from a file. We'll go through each
3884 of the calls to create a pixmap.
3885
3886 <tscreen><verb>
3887 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
3888                                         gchar     *data,
3889                                         gint       width,
3890                                         gint       height );
3891 </verb></tscreen>
3892
3893 This routine is used to create a single-plane pixmap (2 colors) from
3894 data in memory. Each bit of the data represents whether that pixel is
3895 off or on. Width and height are in pixels. The GdkWindow pointer is
3896 to the current window, since a pixmap resources are meaningful only in
3897 the context of the screen where it is to be displayed.
3898
3899 <tscreen><verb>
3900 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
3901                                         gchar     *data,
3902                                         gint       width,
3903                                         gint       height,
3904                                         gint       depth,
3905                                         GdkColor  *fg,
3906                                         GdkColor  *bg );
3907 </verb></tscreen>
3908
3909 This is used to create a pixmap of the given depth (number of colors) from
3910 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
3911 background color to use.
3912
3913 <tscreen><verb>
3914 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
3915                                        GdkBitmap  **mask,
3916                                        GdkColor    *transparent_color,
3917                                        const gchar *filename );
3918 </verb></tscreen>
3919
3920 XPM format is a readable pixmap representation for the X Window
3921 System. It is widely used and many different utilities are available
3922 for creating image files in this format. The file specified by
3923 filename must contain an image in that format and it is loaded into
3924 the pixmap structure. The mask specifies which bits of the pixmap are
3925 opaque. All other bits are colored using the color specified by
3926 transparent_color. An example using this follows below.
3927
3928 <tscreen><verb>
3929 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
3930                                          GdkBitmap **mask,
3931                                          GdkColor   *transparent_color,
3932                                          gchar     **data );
3933 </verb></tscreen>
3934
3935 Small images can be incorporated into a program as data in the XPM
3936 format. A pixmap is created using this data, instead of reading it
3937 from a file. An example of such data is
3938
3939 <tscreen><verb>
3940 /* XPM */
3941 static const char * xpm_data[] = {
3942 "16 16 3 1",
3943 "       c None",
3944 ".      c #000000000000",
3945 "X      c #FFFFFFFFFFFF",
3946 "                ",
3947 "   ......       ",
3948 "   .XXX.X.      ",
3949 "   .XXX.XX.     ",
3950 "   .XXX.XXX.    ",
3951 "   .XXX.....    ",
3952 "   .XXXXXXX.    ",
3953 "   .XXXXXXX.    ",
3954 "   .XXXXXXX.    ",
3955 "   .XXXXXXX.    ",
3956 "   .XXXXXXX.    ",
3957 "   .XXXXXXX.    ",
3958 "   .XXXXXXX.    ",
3959 "   .........    ",
3960 "                ",
3961 "                "};
3962 </verb></tscreen>
3963
3964 When we're done using a pixmap and not likely to reuse it again soon,
3965 it is a good idea to release the resource using
3966 gdk_pixmap_unref(). Pixmaps should be considered a precious resource.
3967
3968 Once we've created a pixmap, we can display it as a GTK widget. We
3969 must create a GTK pixmap widget to contain the GDK pixmap. This is
3970 done using
3971
3972 <tscreen><verb>
3973 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
3974                            GdkBitmap *mask );
3975 </verb></tscreen>
3976
3977 The other pixmap widget calls are
3978
3979 <tscreen><verb>
3980 guint gtk_pixmap_get_type( void );
3981
3982 void  gtk_pixmap_set( GtkPixmap  *pixmap,
3983                       GdkPixmap  *val,
3984                       GdkBitmap  *mask );
3985
3986 void  gtk_pixmap_get( GtkPixmap  *pixmap,
3987                       GdkPixmap **val,
3988                       GdkBitmap **mask);
3989 </verb></tscreen>
3990
3991 gtk_pixmap_set is used to change the pixmap that the widget is currently
3992 managing. Val is the pixmap created using GDK.
3993
3994 The following is an example of using a pixmap in a button.
3995
3996 <tscreen><verb>
3997 /* example-start pixmap pixmap.c */
3998
3999 #include <gtk/gtk.h>
4000
4001
4002 /* XPM data of Open-File icon */
4003 static const char * xpm_data[] = {
4004 "16 16 3 1",
4005 "       c None",
4006 ".      c #000000000000",
4007 "X      c #FFFFFFFFFFFF",
4008 "                ",
4009 "   ......       ",
4010 "   .XXX.X.      ",
4011 "   .XXX.XX.     ",
4012 "   .XXX.XXX.    ",
4013 "   .XXX.....    ",
4014 "   .XXXXXXX.    ",
4015 "   .XXXXXXX.    ",
4016 "   .XXXXXXX.    ",
4017 "   .XXXXXXX.    ",
4018 "   .XXXXXXX.    ",
4019 "   .XXXXXXX.    ",
4020 "   .XXXXXXX.    ",
4021 "   .........    ",
4022 "                ",
4023 "                "};
4024
4025
4026 /* when invoked (via signal delete_event), terminates the application.
4027  */
4028 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4029     gtk_main_quit();
4030 }
4031
4032
4033 /* is invoked when the button is clicked.  It just prints a message.
4034  */
4035 void button_clicked( GtkWidget *widget, gpointer data ) {
4036     printf( "button clicked\n" );
4037 }
4038
4039 int main( int argc, char *argv[] )
4040 {
4041     /* GtkWidget is the storage type for widgets */
4042     GtkWidget *window, *pixmapwid, *button;
4043     GdkPixmap *pixmap;
4044     GdkBitmap *mask;
4045     GtkStyle *style;
4046     
4047     /* create the main window, and attach delete_event signal to terminating
4048        the application */
4049     gtk_init( &amp;argc, &amp;argv );
4050     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4051     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
4052                         GTK_SIGNAL_FUNC (close_application), NULL );
4053     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
4054     gtk_widget_show( window );
4055
4056     /* now for the pixmap from gdk */
4057     style = gtk_widget_get_style( window );
4058     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
4059                                            &amp;style->bg[GTK_STATE_NORMAL],
4060                                            (gchar **)xpm_data );
4061
4062     /* a pixmap widget to contain the pixmap */
4063     pixmapwid = gtk_pixmap_new( pixmap, mask );
4064     gtk_widget_show( pixmapwid );
4065
4066     /* a button to contain the pixmap widget */
4067     button = gtk_button_new();
4068     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
4069     gtk_container_add( GTK_CONTAINER(window), button );
4070     gtk_widget_show( button );
4071
4072     gtk_signal_connect( GTK_OBJECT(button), "clicked",
4073                         GTK_SIGNAL_FUNC(button_clicked), NULL );
4074
4075     /* show the window */
4076     gtk_main ();
4077           
4078     return 0;
4079 }
4080 /* example-end */
4081 </verb></tscreen>
4082
4083 To load a file from an XPM data file called icon0.xpm in the current
4084 directory, we would have created the pixmap thus
4085
4086 <tscreen><verb>
4087     /* load a pixmap from a file */
4088     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
4089                                          &amp;style->bg[GTK_STATE_NORMAL],
4090                                          "./icon0.xpm" );
4091     pixmapwid = gtk_pixmap_new( pixmap, mask );
4092     gtk_widget_show( pixmapwid );
4093     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
4094 </verb></tscreen>
4095
4096 A disadvantage of using pixmaps is that the displayed object is always
4097 rectangular, regardless of the image. We would like to create desktops
4098 and applications with icons that have more natural shapes. For
4099 example, for a game interface, we would like to have round buttons to
4100 push. The way to do this is using shaped windows.
4101
4102 A shaped window is simply a pixmap where the background pixels are
4103 transparent. This way, when the background image is multi-colored, we
4104 don't overwrite it with a rectangular, non-matching border around our
4105 icon. The following example displays a full wheelbarrow image on the
4106 desktop.
4107
4108 <tscreen><verb>
4109 /* example-start wheelbarrow wheelbarrow.c */
4110
4111 #include <gtk/gtk.h>
4112
4113 /* XPM */
4114 static char * WheelbarrowFull_xpm[] = {
4115 "48 48 64 1",
4116 "       c None",
4117 ".      c #DF7DCF3CC71B",
4118 "X      c #965875D669A6",
4119 "o      c #71C671C671C6",
4120 "O      c #A699A289A699",
4121 "+      c #965892489658",
4122 "@      c #8E38410330C2",
4123 "#      c #D75C7DF769A6",
4124 "$      c #F7DECF3CC71B",
4125 "%      c #96588A288E38",
4126 "&amp;      c #A69992489E79",
4127 "*      c #8E3886178E38",
4128 "=      c #104008200820",
4129 "-      c #596510401040",
4130 ";      c #C71B30C230C2",
4131 ":      c #C71B9A699658",
4132 ">      c #618561856185",
4133 ",      c #20811C712081",
4134 "<      c #104000000000",
4135 "1      c #861720812081",
4136 "2      c #DF7D4D344103",
4137 "3      c #79E769A671C6",
4138 "4      c #861782078617",
4139 "5      c #41033CF34103",
4140 "6      c #000000000000",
4141 "7      c #49241C711040",
4142 "8      c #492445144924",
4143 "9      c #082008200820",
4144 "0      c #69A618611861",
4145 "q      c #B6DA71C65144",
4146 "w      c #410330C238E3",
4147 "e      c #CF3CBAEAB6DA",
4148 "r      c #71C6451430C2",
4149 "t      c #EFBEDB6CD75C",
4150 "y      c #28A208200820",
4151 "u      c #186110401040",
4152 "i      c #596528A21861",
4153 "p      c #71C661855965",
4154 "a      c #A69996589658",
4155 "s      c #30C228A230C2",
4156 "d      c #BEFBA289AEBA",
4157 "f      c #596545145144",
4158 "g      c #30C230C230C2",
4159 "h      c #8E3882078617",
4160 "j      c #208118612081",
4161 "k      c #38E30C300820",
4162 "l      c #30C2208128A2",
4163 "z      c #38E328A238E3",
4164 "x      c #514438E34924",
4165 "c      c #618555555965",
4166 "v      c #30C2208130C2",
4167 "b      c #38E328A230C2",
4168 "n      c #28A228A228A2",
4169 "m      c #41032CB228A2",
4170 "M      c #104010401040",
4171 "N      c #492438E34103",
4172 "B      c #28A2208128A2",
4173 "V      c #A699596538E3",
4174 "C      c #30C21C711040",
4175 "Z      c #30C218611040",
4176 "A      c #965865955965",
4177 "S      c #618534D32081",
4178 "D      c #38E31C711040",
4179 "F      c #082000000820",
4180 "                                                ",
4181 "          .XoO                                  ",
4182 "         +@#$%o&amp;                                ",
4183 "         *=-;#::o+                              ",
4184 "           >,<12#:34                            ",
4185 "             45671#:X3                          ",
4186 "               +89<02qwo                        ",
4187 "e*                >,67;ro                       ",
4188 "ty>                 459@>+&amp;&amp;                    ",
4189 "$2u+                  ><ipas8*                  ",
4190 "%$;=*                *3:.Xa.dfg>                ",
4191 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
4192 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
4193 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
4194 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
4195 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
4196 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
4197 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
4198 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
4199 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
4200 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
4201 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
4202 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
4203 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
4204 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
4205 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
4206 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
4207 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
4208 "              p;<69BvwwsszslllbBlllllllu<5+     ",
4209 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
4210 "               c1-699Blvlllllu7k96MMMg4         ",
4211 "               *10y8n6FjvllllB<166668           ",
4212 "                S-kg+>666<M<996-y6n<8*          ",
4213 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
4214 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
4215 "                 N-k-<>     >=01-kuu666>        ",
4216 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
4217 "                 Ou0<>       o66y<ulw<66&amp;       ",
4218 "                  *kk5       >66By7=xu664       ",
4219 "                   <<M4      466lj<Mxu66o       ",
4220 "                   *>>       +66uv,zN666*       ",
4221 "                              566,xxj669        ",
4222 "                              4666FF666>        ",
4223 "                               >966666M         ",
4224 "                                oM6668+         ",
4225 "                                  *4            ",
4226 "                                                ",
4227 "                                                "};
4228
4229
4230 /* When invoked (via signal delete_event), terminates the application */
4231 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4232     gtk_main_quit();
4233 }
4234
4235 int main (int argc, char *argv[])
4236 {
4237     /* GtkWidget is the storage type for widgets */
4238     GtkWidget *window, *pixmap, *fixed;
4239     GdkPixmap *gdk_pixmap;
4240     GdkBitmap *mask;
4241     GtkStyle *style;
4242     GdkGC *gc;
4243     
4244     /* Create the main window, and attach delete_event signal to terminate
4245      * the application.  Note that the main window will not have a titlebar
4246      * since we're making it a popup. */
4247     gtk_init (&amp;argc, &amp;argv);
4248     window = gtk_window_new( GTK_WINDOW_POPUP );
4249     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4250                         GTK_SIGNAL_FUNC (close_application), NULL);
4251     gtk_widget_show (window);
4252
4253     /* Now for the pixmap and the pixmap widget */
4254     style = gtk_widget_get_default_style();
4255     gc = style->black_gc;
4256     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
4257                                              &amp;style->bg[GTK_STATE_NORMAL],
4258                                              WheelbarrowFull_xpm );
4259     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
4260     gtk_widget_show( pixmap );
4261
4262     /* To display the pixmap, we use a fixed widget to place the pixmap */
4263     fixed = gtk_fixed_new();
4264     gtk_widget_set_usize( fixed, 200, 200 );
4265     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
4266     gtk_container_add( GTK_CONTAINER(window), fixed );
4267     gtk_widget_show( fixed );
4268
4269     /* This masks out everything except for the image itself */
4270     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
4271     
4272     /* show the window */
4273     gtk_widget_set_uposition( window, 20, 400 );
4274     gtk_widget_show( window );
4275     gtk_main ();
4276           
4277     return(0);
4278 }
4279 /* example-end */
4280 </verb></tscreen>
4281
4282 To make the wheelbarrow image sensitive, we could attach the button
4283 press event signal to make it do something. The following few lines
4284 would make the picture sensitive to a mouse button being pressed which
4285 makes the application terminate.
4286
4287 <tscreen><verb>
4288     gtk_widget_set_events( window,
4289                           gtk_widget_get_events( window ) |
4290                           GDK_BUTTON_PRESS_MASK );
4291
4292    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
4293                        GTK_SIGNAL_FUNC(close_application), NULL );
4294 </verb></tscreen>
4295
4296 <!-- ----------------------------------------------------------------- -->
4297 <sect1>Rulers
4298 <p>
4299 Ruler widgets are used to indicate the location of the mouse pointer
4300 in a given window. A window can have a vertical ruler spanning across
4301 the width and a horizontal ruler spanning down the height. A small
4302 triangular indicator on the ruler shows the exact location of the
4303 pointer relative to the ruler.
4304
4305 A ruler must first be created. Horizontal and vertical rulers are
4306 created using
4307
4308 <tscreen><verb>
4309 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4310
4311 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4312 </verb></tscreen>
4313
4314 Once a ruler is created, we can define the unit of measurement. Units
4315 of measure for rulers can be GTK_PIXELS, GTK_INCHES or
4316 GTK_CENTIMETERS. This is set using
4317
4318 <tscreen><verb>
4319 void gtk_ruler_set_metric( GtkRuler      *ruler,
4320                            GtkMetricType  metric );
4321 </verb></tscreen>
4322
4323 The default measure is GTK_PIXELS.
4324
4325 <tscreen><verb>
4326     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4327 </verb></tscreen>
4328
4329 Other important characteristics of a ruler are how to mark the units
4330 of scale and where the position indicator is initially placed. These
4331 are set for a ruler using
4332
4333 <tscreen><verb>
4334 void gtk_ruler_set_range( GtkRuler *ruler,
4335                           gfloat    lower,
4336                           gfloat    upper,
4337                           gfloat    position,
4338                           gfloat    max_size );
4339 </verb></tscreen>
4340
4341 The lower and upper arguments define the extent of the ruler, and
4342 max_size is the largest possible number that will be displayed.
4343 Position defines the initial position of the pointer indicator within
4344 the ruler.
4345
4346 A vertical ruler can span an 800 pixel wide window thus
4347
4348 <tscreen><verb>
4349     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4350 </verb></tscreen>
4351
4352 The markings displayed on the ruler will be from 0 to 800, with a
4353 number for every 100 pixels. If instead we wanted the ruler to range
4354 from 7 to 16, we would code
4355
4356 <tscreen><verb>
4357     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4358 </verb></tscreen>
4359
4360 The indicator on the ruler is a small triangular mark that indicates
4361 the position of the pointer relative to the ruler. If the ruler is
4362 used to follow the mouse pointer, the motion_notify_event signal
4363 should be connected to the motion_notify_event method of the ruler.
4364 To follow all mouse movements within a window area, we would use
4365
4366 <tscreen><verb>
4367 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4368
4369     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4370            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4371            GTK_OBJECT(ruler) );
4372 </verb></tscreen>
4373
4374 The following example creates a drawing area with a horizontal ruler
4375 above it and a vertical ruler to the left of it. The size of the
4376 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4377 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4378 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4379 Placement of the drawing area and the rulers is done using a table.
4380
4381 <tscreen><verb>
4382 /* example-start rulers rulers.c */
4383
4384 #include <gtk/gtk.h>
4385
4386 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4387
4388 #define XSIZE  600
4389 #define YSIZE  400
4390
4391 /* This routine gets control when the close button is clicked */
4392 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4393     gtk_main_quit();
4394 }
4395
4396 /* The main routine */
4397 int main( int argc, char *argv[] ) {
4398     GtkWidget *window, *table, *area, *hrule, *vrule;
4399
4400     /* Initialize GTK and create the main window */
4401     gtk_init( &amp;argc, &amp;argv );
4402
4403     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4404     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4405             GTK_SIGNAL_FUNC( close_application ), NULL);
4406     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4407
4408     /* Create a table for placing the ruler and the drawing area */
4409     table = gtk_table_new( 3, 2, FALSE );
4410     gtk_container_add( GTK_CONTAINER(window), table );
4411
4412     area = gtk_drawing_area_new();
4413     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4414     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4415                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4416     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK |
4417                                  GDK_POINTER_MOTION_HINT_MASK );
4418
4419     /* The horizontal ruler goes on top. As the mouse moves across the
4420      * drawing area, a motion_notify_event is passed to the
4421      * appropriate event handler for the ruler. */
4422     hrule = gtk_hruler_new();
4423     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4424     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4425     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4426                                (GtkSignalFunc)EVENT_METHOD(hrule,
4427                                                         motion_notify_event),
4428                                GTK_OBJECT(hrule) );
4429     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4430     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4431                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4432     
4433     /* The vertical ruler goes on the left. As the mouse moves across
4434      * the drawing area, a motion_notify_event is passed to the
4435      * appropriate event handler for the ruler. */
4436     vrule = gtk_vruler_new();
4437     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4438     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4439     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4440                                (GtkSignalFunc)
4441                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->
4442                                                          motion_notify_event,
4443                                GTK_OBJECT(vrule) );
4444     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4445                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4446
4447     /* Now show everything */
4448     gtk_widget_show( area );
4449     gtk_widget_show( hrule );
4450     gtk_widget_show( vrule );
4451     gtk_widget_show( table );
4452     gtk_widget_show( window );
4453     gtk_main();
4454
4455     return(0);
4456 }
4457 /* example-end */
4458 </verb></tscreen>
4459
4460 <!-- ----------------------------------------------------------------- -->
4461 <sect1>Statusbars
4462 <p>
4463 Statusbars are simple widgets used to display a text message. They
4464 keep a stack of the messages pushed onto them, so that popping the
4465 current message will re-display the previous text message.
4466
4467 In order to allow different parts of an application to use the same
4468 statusbar to display messages, the statusbar widget issues Context
4469 Identifiers which are used to identify different 'users'. The message
4470 on top of the stack is the one displayed, no matter what context it is
4471 in. Messages are stacked in last-in-first-out order, not context
4472 identifier order.
4473
4474 A statusbar is created with a call to:
4475
4476 <tscreen><verb>
4477 GtkWidget *gtk_statusbar_new( void );
4478 </verb></tscreen>
4479
4480 A new Context Identifier is requested using a call to the following 
4481 function with a short textual description of the context:
4482
4483 <tscreen><verb>
4484 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4485                                     const gchar  *context_description );
4486 </verb></tscreen>
4487
4488 There are three functions that can operate on statusbars:
4489
4490 <tscreen><verb>
4491 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4492                           guint         context_id,
4493                           gchar        *text );
4494
4495 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4496                         guint         context_id );
4497
4498 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4499                            guint         context_id,
4500                            guint         message_id ); 
4501 </verb></tscreen>
4502
4503 The first, gtk_statusbar_push, is used to add a new message to the
4504 statusbar.  It returns a Message Identifier, which can be passed later
4505 to the function gtk_statusbar_remove to remove the message with the
4506 given Message and Context Identifiers from the statusbar's stack.
4507
4508 The function gtk_statusbar_pop removes the message highest in the
4509 stack with the given Context Identifier.
4510
4511 The following example creates a statusbar and two buttons, one for
4512 pushing items onto the statusbar, and one for popping the last item
4513 back off.
4514
4515 <tscreen><verb>
4516 /* example-start statusbar statusbar.c */
4517
4518 #include <gtk/gtk.h>
4519 #include <glib.h>
4520
4521 GtkWidget *status_bar;
4522
4523 void push_item (GtkWidget *widget, gpointer data)
4524 {
4525   static int count = 1;
4526   char buff[20];
4527
4528   g_snprintf(buff, 20, "Item %d", count++);
4529   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4530
4531   return;
4532 }
4533
4534 void pop_item (GtkWidget *widget, gpointer data)
4535 {
4536   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4537   return;
4538 }
4539
4540 int main (int argc, char *argv[])
4541 {
4542
4543     GtkWidget *window;
4544     GtkWidget *vbox;
4545     GtkWidget *button;
4546
4547     gint context_id;
4548
4549     gtk_init (&amp;argc, &amp;argv);
4550
4551     /* create a new window */
4552     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4553     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4554     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4555     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4556                        (GtkSignalFunc) gtk_exit, NULL);
4557  
4558     vbox = gtk_vbox_new(FALSE, 1);
4559     gtk_container_add(GTK_CONTAINER(window), vbox);
4560     gtk_widget_show(vbox);
4561           
4562     status_bar = gtk_statusbar_new();      
4563     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4564     gtk_widget_show (status_bar);
4565
4566     context_id = gtk_statusbar_get_context_id(
4567                           GTK_STATUSBAR(status_bar), "Statusbar example");
4568
4569     button = gtk_button_new_with_label("push item");
4570     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4571         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4572     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4573     gtk_widget_show(button);              
4574
4575     button = gtk_button_new_with_label("pop last item");
4576     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4577         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4578     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4579     gtk_widget_show(button);              
4580
4581     /* always display the window as the last step so it all splashes on
4582      * the screen at once. */
4583     gtk_widget_show(window);
4584
4585     gtk_main ();
4586
4587     return 0;
4588 }
4589 /* example-end */
4590 </verb></tscreen>
4591
4592 <!-- ----------------------------------------------------------------- -->
4593 <sect1>Text Entries
4594 <p>
4595 The Entry widget allows text to be typed and displayed in a single line
4596 text box. The text may be set with function calls that allow new text
4597 to replace, prepend or append the current contents of the Entry widget.
4598
4599 There are two functions for creating Entry widgets:
4600
4601 <tscreen><verb>
4602 GtkWidget *gtk_entry_new( void );
4603
4604 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4605 </verb></tscreen>
4606
4607 The first just creates a new Entry widget, whilst the second creates a
4608 new Entry and sets a limit on the length of the text within the Entry.
4609
4610 There are several functions for altering the text which is currently
4611 within the Entry widget.
4612
4613 <tscreen><verb>
4614 void gtk_entry_set_text( GtkEntry    *entry,
4615                          const gchar *text );
4616
4617 void gtk_entry_append_text( GtkEntry    *entry,
4618                             const gchar *text );
4619
4620 void gtk_entry_prepend_text( GtkEntry    *entry,
4621                              const gchar *text );
4622 </verb></tscreen>
4623
4624 The function gtk_entry_set_text sets the contents of the Entry widget,
4625 replacing the current contents. The functions gtk_entry_append_text
4626 and gtk_entry_prepend_text allow the current contents to be appended
4627 and prepended to.
4628
4629 The next function allows the current insertion point to be set.
4630
4631 <tscreen><verb>
4632 void gtk_entry_set_position( GtkEntry *entry,
4633                              gint      position );
4634 </verb></tscreen>
4635
4636 The contents of the Entry can be retrieved by using a call to the
4637 following function. This is useful in the callback functions described below.
4638
4639 <tscreen><verb>
4640 gchar *gtk_entry_get_text( GtkEntry *entry );
4641 </verb></tscreen>
4642
4643 The value returned by this function is used internally, and must not
4644 be freed using either free() or g_free()
4645
4646 If we don't want the contents of the Entry to be changed by someone typing
4647 into it, we can change its editable state.
4648
4649 <tscreen><verb>
4650 void gtk_entry_set_editable( GtkEntry *entry,
4651                              gboolean  editable );
4652 </verb></tscreen>
4653
4654 The function above allows us to toggle the editable state of the
4655 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4656 argument.
4657
4658 If we are using the Entry where we don't want the text entered to be
4659 visible, for example when a password is being entered, we can use the
4660 following function, which also takes a boolean flag.
4661
4662 <tscreen><verb>
4663 void gtk_entry_set_visibility( GtkEntry *entry,
4664                                gboolean  visible );
4665 </verb></tscreen>
4666
4667 A region of the text may be set as selected by using the following
4668 function. This would most often be used after setting some default
4669 text in an Entry, making it easy for the user to remove it.
4670
4671 <tscreen><verb>
4672 void gtk_entry_select_region( GtkEntry *entry,
4673                               gint      start,
4674                               gint      end );
4675 </verb></tscreen>
4676
4677 If we want to catch when the user has entered text, we can connect to
4678 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4679 user hits the enter key within the Entry widget. Changed is raised
4680 when the text changes at all, e.g. for every character entered or
4681 removed.
4682
4683 The following code is an example of using an Entry widget.
4684
4685 <tscreen><verb>
4686 /* example-start entry entry.c */
4687
4688 #include <gtk/gtk.h>
4689
4690 void enter_callback(GtkWidget *widget, GtkWidget *entry)
4691 {
4692   gchar *entry_text;
4693   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4694   printf("Entry contents: %s\n", entry_text);
4695 }
4696
4697 void entry_toggle_editable (GtkWidget *checkbutton,
4698                                    GtkWidget *entry)
4699 {
4700   gtk_entry_set_editable(GTK_ENTRY(entry),
4701                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4702 }
4703
4704 void entry_toggle_visibility (GtkWidget *checkbutton,
4705                                    GtkWidget *entry)
4706 {
4707   gtk_entry_set_visibility(GTK_ENTRY(entry),
4708                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4709 }
4710
4711 int main (int argc, char *argv[])
4712 {
4713
4714     GtkWidget *window;
4715     GtkWidget *vbox, *hbox;
4716     GtkWidget *entry;
4717     GtkWidget *button;
4718     GtkWidget *check;
4719
4720     gtk_init (&amp;argc, &amp;argv);
4721
4722     /* create a new window */
4723     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4724     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4725     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4726     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4727                        (GtkSignalFunc) gtk_exit, NULL);
4728
4729     vbox = gtk_vbox_new (FALSE, 0);
4730     gtk_container_add (GTK_CONTAINER (window), vbox);
4731     gtk_widget_show (vbox);
4732
4733     entry = gtk_entry_new_with_max_length (50);
4734     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4735                        GTK_SIGNAL_FUNC(enter_callback),
4736                        entry);
4737     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4738     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4739     gtk_entry_select_region (GTK_ENTRY (entry),
4740                              0, GTK_ENTRY(entry)->text_length);
4741     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4742     gtk_widget_show (entry);
4743
4744     hbox = gtk_hbox_new (FALSE, 0);
4745     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4746     gtk_widget_show (hbox);
4747                                   
4748     check = gtk_check_button_new_with_label("Editable");
4749     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4750     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4751                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4752     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4753     gtk_widget_show (check);
4754     
4755     check = gtk_check_button_new_with_label("Visible");
4756     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4757     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4758                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4759     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4760     gtk_widget_show (check);
4761                                    
4762     button = gtk_button_new_with_label ("Close");
4763     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4764                                GTK_SIGNAL_FUNC(gtk_exit),
4765                                GTK_OBJECT (window));
4766     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4767     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4768     gtk_widget_grab_default (button);
4769     gtk_widget_show (button);
4770     
4771     gtk_widget_show(window);
4772
4773     gtk_main();
4774     return(0);
4775 }
4776 /* example-end */
4777 </verb></tscreen>
4778
4779 <!-- ----------------------------------------------------------------- -->
4780 <sect1>Spin Buttons
4781 <p>
4782 The Spin Button widget is generally used to allow the user to select a
4783 value from a range of numeric values. It consists of a text
4784 entry box with up and down arrow buttons attached to the
4785 side. Selecting one of the buttons causes the value to 'spin' up and
4786 down the range of possible values. The entry box may also be edited
4787 directly to enter a specific value.
4788
4789 The Spin Button allows the value to have zero or a number of decimal
4790 places and to be incremented/decremented in configurable steps. The
4791 action of holding down one of the buttons optionally result in an
4792 acceleration of change in the value according to how long it is
4793 depressed.
4794
4795 The Spin Button uses an <ref id="sec_Adjustment" name="Adjustment">
4796 object to hold information about the range of values that the spin
4797 button can take. This makes for a powerful Spin Button widget.
4798
4799 Recall that an adjustment widget is created with the following
4800 function, which illustrates the information that it holds:
4801
4802 <tscreen><verb>
4803 GtkObject *gtk_adjustment_new( gfloat value,
4804                                gfloat lower,
4805                                gfloat upper,
4806                                gfloat step_increment,
4807                                gfloat page_increment,
4808                                gfloat page_size );
4809 </verb></tscreen>
4810
4811 These attributes of an Adjustment are used by the Spin Button in the
4812 following way:
4813
4814 <itemize>
4815 <item> <tt/value/: initial value for the Spin Button
4816 <item> <tt/lower/: lower range value
4817 <item> <tt/upper/: upper range value
4818 <item> <tt/step_increment/: value to increment/decrement when pressing
4819 mouse button 1 on a button
4820 <item> <tt/page_increment/: value to increment/decrement when pressing
4821 mouse button 2 on a button
4822 <item> <tt/page_size/: unused
4823 </itemize>
4824
4825 Additionally, mouse button 3 can be used to jump directly to the
4826 <tt/upper/ or <tt/lower/ values when used to select one of the
4827 buttons. Lets look at how to create a Spin Button:
4828
4829 <tscreen><verb>
4830 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4831                                 gfloat         climb_rate,
4832                                 guint          digits );
4833 </verb></tscreen>
4834
4835 The <tt/climb_rate/ argument take a value between 0.0 and 1.0 and
4836 indicates the amount of acceleration that the Spin Button has. The
4837 <tt/digits/ argument specifies the number of decimal places to which
4838 the value will be displayed.
4839
4840 A Spin Button can be reconfigured after creation using the following
4841 function:
4842
4843 <tscreen><verb>
4844 void gtk_spin_button_configure( GtkSpinButton *spin_button,
4845                                 GtkAdjustment *adjustment,
4846                                 gfloat         climb_rate,
4847                                 guint          digits );
4848 </verb></tscreen>
4849
4850 The <tt/spin_button/ argument specifies the Spin Button widget that is
4851 to be reconfigured. The other arguments are as specified above.
4852
4853 The adjustment can be set and retrieved independantly using the
4854 following two functions:
4855
4856 <tscreen><verb>
4857 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
4858                                      GtkAdjustment  *adjustment );
4859
4860 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
4861 </verb></tscreen>
4862
4863 The number of decimal places can also be altered using:
4864
4865 <tscreen><verb>
4866 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
4867                                  guint          digits) ;
4868 </verb></tscreen>
4869
4870 The value that a Spin Button is currently displaying can be changed
4871 using the following function:
4872
4873 <tscreen><verb>
4874 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
4875                                 gfloat         value );
4876 </verb></tscreen>
4877
4878 The current value of a Spin Button can be retrieved as either a
4879 floating point or integer value with the following functions:
4880
4881 <tscreen><verb>
4882 gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *spin_button );
4883
4884 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
4885 </verb></tscreen>
4886
4887 If you want to alter the value of a Spin Value relative to its current
4888 value, then the following function can be used:
4889
4890 <tscreen><verb>
4891 void gtk_spin_button_spin( GtkSpinButton *spin_button,
4892                            GtkSpinType    direction,
4893                            gfloat         increment );
4894 </verb></tscreen>
4895
4896 The <tt/direction/ parameter can take one of the following values:
4897
4898 <itemize>
4899 <item> GTK_SPIN_STEP_FORWARD
4900 <item> GTK_SPIN_STEP_BACKWARD
4901 <item> GTK_SPIN_PAGE_FORWARD
4902 <item> GTK_SPIN_PAGE_BACKWARD
4903 <item> GTK_SPIN_HOME
4904 <item> GTK_SPIN_END
4905 <item> GTK_SPIN_USER_DEFINED
4906 </itemize>
4907
4908 This function packs in quite a bit of functionality, which I will
4909 attempt to clearly explain. Many of these settings use values from the
4910 Adjustment object that is associated with a Spin Button.
4911
4912 GTK_SPIN_STEP_FORWARD and GTK_SPIN_STEP_BACKWARD change the value of
4913 the Spin Button by the amount specified by <tt/increment/, unless
4914 <tt/increment/ is equal to 0, in which case the value is changed by
4915 the value of <tt/step_increment/ in theAdjustment.
4916
4917 GTK_SPIN_PAGE_FORWARD and GTK_SPIN_PAGE_BACKWARD simply alter the value of
4918 the Spin Button by <tt/increment/.
4919
4920 GTK_SPIN_HOME sets the value of the Spin Button to the bottom of the
4921 Adjustments range.
4922
4923 GTK_SPIN_END sets the value of the Spin Button to the top of the
4924 Adjustments range.
4925
4926 GTK_SPIN_USER_DEFINED simply alters the value of the Spin Button by
4927 the specified amount.
4928
4929 We move away from functions for setting and retreving the range attributes
4930 of the Spin Button now, and move onto functions that effect the
4931 appearance and behaviour of the Spin Button widget itself.
4932
4933 The first of these functions is used to constrain the text box of the
4934 Spin Button such that it may only contain a numric value. This
4935 prevents a user from typing anything other than numeric values into
4936 the text box of a Spin Button:
4937
4938 <tscreen><verb>
4939 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
4940                                   gboolean       numeric );
4941 </verb></tscreen>
4942
4943 You can set whether a Spin Button will wrap around between the upper
4944 and lower range values with the following function:
4945
4946 <tscreen><verb>
4947 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
4948                                gboolean       wrap );
4949 </verb></tscreen>
4950
4951 You can set a Spin Button to round the value to the nearest
4952 <tt/step_increment/, which is set within the Adjustment object used
4953 with the Spin Button. This is accomplished with the following
4954 function:
4955
4956 <tscreen><verb>
4957 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
4958                                         gboolean        snap_to_ticks );
4959 </verb></tscreen>
4960
4961 The update policy of a Spin Button can be changed with the following
4962 function:
4963
4964 <tscreen><verb>
4965 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
4966                                     GtkSpinButtonUpdatePolicy policy );
4967 </verb></tscreen>
4968
4969 <!-- TODO: find out what this does - TRG -->
4970
4971 The possible values of <tt/policy/ are either GTK_UPDATE_ALWAYS or
4972 GTK_UPDATE_IF_VALID.
4973
4974 These policies affect the behavior of a Spin Button when parsing
4975 inserted text and syncing it's value with the values of the
4976 Adjustment.
4977
4978 In the case of GTK_UPDATE_IF_VALID the Spin Button only value gets
4979 changed if the text input is a numeric value that
4980 is within the range specified by the Adjustment. Otherwise
4981 the text is reset to the current value.
4982
4983 In case of GTK_UPDATE_ALWAYS we ignore errors while converting text
4984 into a numeric value.
4985
4986 The appearance of the buttons used in a Spin Button can be changed
4987 using the following function:
4988
4989 <tscreen><verb>
4990 void gtk_spin_button_set_shadow_type( GtkSpinButton *spin_button,
4991                                       GtkShadowType  shadow_type );
4992 </verb></tscreen>
4993
4994 As usual, the <tt/shadow_type/ can be one of:
4995
4996 <itemize>
4997 <item> GTK_SHADOW_IN
4998 <item> GTK_SHADOW_OUT
4999 <item> GTK_SHADOW_ETCHED_IN
5000 <item> GTK_SHADOW_ETCHED_OUT
5001 </itemize>
5002
5003 Finally, you can explicitly request that a Spin Button update itself:
5004
5005 <tscreen><verb>
5006 void gtk_spin_button_update( GtkSpinButton  *spin_button );
5007 </verb></tscreen>
5008
5009 It's example time again.
5010
5011 <tscreen><verb>
5012 /* example-start spinbutton spinbutton.c */
5013
5014 #include <gtk/gtk.h>
5015
5016 static GtkWidget *spinner1;
5017
5018 void toggle_snap( GtkWidget     *widget,
5019                   GtkSpinButton *spin )
5020 {
5021   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5022 }
5023
5024 void toggle_numeric( GtkWidget *widget,
5025                      GtkSpinButton *spin )
5026 {
5027   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5028 }
5029
5030 void change_digits( GtkWidget *widget,
5031                     GtkSpinButton *spin )
5032 {
5033   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5034                               gtk_spin_button_get_value_as_int (spin));
5035 }
5036
5037 void get_value( GtkWidget *widget,
5038                 gpointer data )
5039 {
5040   gchar buf[32];
5041   GtkLabel *label;
5042   GtkSpinButton *spin;
5043
5044   spin = GTK_SPIN_BUTTON (spinner1);
5045   label = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget)));
5046   if (GPOINTER_TO_INT (data) == 1)
5047     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5048   else
5049     sprintf (buf, "%0.*f", spin->digits,
5050              gtk_spin_button_get_value_as_float (spin));
5051   gtk_label_set_text (label, buf);
5052 }
5053
5054
5055 int main( int   argc,
5056           char *argv[] )
5057 {
5058   GtkWidget *window;
5059   GtkWidget *frame;
5060   GtkWidget *hbox;
5061   GtkWidget *main_vbox;
5062   GtkWidget *vbox;
5063   GtkWidget *vbox2;
5064   GtkWidget *spinner2;
5065   GtkWidget *spinner;
5066   GtkWidget *button;
5067   GtkWidget *label;
5068   GtkWidget *val_label;
5069   GtkAdjustment *adj;
5070
5071   /* Initialise GTK */
5072   gtk_init(&amp;argc, &amp;argv);
5073
5074   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5075
5076   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5077                       GTK_SIGNAL_FUNC (gtk_main_quit),
5078                       NULL);
5079
5080   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5081
5082   main_vbox = gtk_vbox_new (FALSE, 5);
5083   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5084   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5085   
5086   frame = gtk_frame_new ("Not accelerated");
5087   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5088   
5089   vbox = gtk_vbox_new (FALSE, 0);
5090   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5091   gtk_container_add (GTK_CONTAINER (frame), vbox);
5092   
5093   /* Day, month, year spinners */
5094   
5095   hbox = gtk_hbox_new (FALSE, 0);
5096   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5097   
5098   vbox2 = gtk_vbox_new (FALSE, 0);
5099   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5100   
5101   label = gtk_label_new ("Day :");
5102   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5103   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5104   
5105   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5106                                               5.0, 0.0);
5107   spinner = gtk_spin_button_new (adj, 0, 0);
5108   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5109   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5110                                    GTK_SHADOW_OUT);
5111   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5112   
5113   vbox2 = gtk_vbox_new (FALSE, 0);
5114   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5115   
5116   label = gtk_label_new ("Month :");
5117   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5118   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5119   
5120   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5121                                               5.0, 0.0);
5122   spinner = gtk_spin_button_new (adj, 0, 0);
5123   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5124   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5125                                    GTK_SHADOW_ETCHED_IN);
5126   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5127   
5128   vbox2 = gtk_vbox_new (FALSE, 0);
5129   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5130   
5131   label = gtk_label_new ("Year :");
5132   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5133   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5134   
5135   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5136                                               1.0, 100.0, 0.0);
5137   spinner = gtk_spin_button_new (adj, 0, 0);
5138   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5139   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5140                                    GTK_SHADOW_IN);
5141   gtk_widget_set_usize (spinner, 55, 0);
5142   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5143   
5144   frame = gtk_frame_new ("Accelerated");
5145   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5146   
5147   vbox = gtk_vbox_new (FALSE, 0);
5148   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5149   gtk_container_add (GTK_CONTAINER (frame), vbox);
5150   
5151   hbox = gtk_hbox_new (FALSE, 0);
5152   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5153   
5154   vbox2 = gtk_vbox_new (FALSE, 0);
5155   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5156   
5157   label = gtk_label_new ("Value :");
5158   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5159   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5160   
5161   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5162                                               0.5, 100.0, 0.0);
5163   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5164   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5165   gtk_widget_set_usize (spinner1, 100, 0);
5166   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5167   
5168   vbox2 = gtk_vbox_new (FALSE, 0);
5169   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5170   
5171   label = gtk_label_new ("Digits :");
5172   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5173   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5174   
5175   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5176   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5177   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5178   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
5179                       GTK_SIGNAL_FUNC (change_digits),
5180                       (gpointer) spinner2);
5181   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5182   
5183   hbox = gtk_hbox_new (FALSE, 0);
5184   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5185   
5186   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5187   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5188                       GTK_SIGNAL_FUNC (toggle_snap),
5189                       spinner1);
5190   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5191   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5192   
5193   button = gtk_check_button_new_with_label ("Numeric only input mode");
5194   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5195                       GTK_SIGNAL_FUNC (toggle_numeric),
5196                       spinner1);
5197   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5198   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5199   
5200   val_label = gtk_label_new ("");
5201   
5202   hbox = gtk_hbox_new (FALSE, 0);
5203   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5204   button = gtk_button_new_with_label ("Value as Int");
5205   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5206   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5207                       GTK_SIGNAL_FUNC (get_value),
5208                       GINT_TO_POINTER (1));
5209   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5210   
5211   button = gtk_button_new_with_label ("Value as Float");
5212   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5213   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5214                       GTK_SIGNAL_FUNC (get_value),
5215                       GINT_TO_POINTER (2));
5216   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5217   
5218   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5219   gtk_label_set_text (GTK_LABEL (val_label), "0");
5220   
5221   hbox = gtk_hbox_new (FALSE, 0);
5222   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5223   
5224   button = gtk_button_new_with_label ("Close");
5225   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5226                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
5227                              GTK_OBJECT (window));
5228   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5229
5230   gtk_widget_show_all (window);
5231
5232   /* Enter the event loop */
5233   gtk_main ();
5234     
5235   return(0);
5236 }
5237 /* example-end */
5238 </verb></tscreen>
5239
5240 <!-- ----------------------------------------------------------------- -->
5241 <sect1>Combo Box
5242 <p>
5243 The combo box is another fairly simple widget that is really just a
5244 collection of other widgets. From the users point of view, the widget
5245 consists of a text entry box and a pull down menu from which the user
5246 can select one of a set of predefined entries. Alternatively, the user
5247 can type a different option directly into the text box.
5248
5249 The following extract from the structure that defines a Combo Box
5250 identifies several of the components:
5251
5252 <tscreen><verb>
5253 struct _GtkCombo { 
5254         GtkHBox hbox; 
5255         GtkWidget *entry; 
5256         GtkWidget *button;
5257         GtkWidget *popup; 
5258         GtkWidget *popwin; 
5259         GtkWidget *list;
5260         ...  };
5261 </verb></tscreen>
5262
5263 As you can see, the Combo Box has two principle parts that you really
5264 care about: an entry and a list.
5265
5266 First off, to create a combo box, use:
5267
5268 <tscreen><verb>
5269 GtkWidget *gtk_combo_new( void );
5270 </verb></tscreen>
5271
5272 Now, if you want to set the string in the entry section of the combo
5273 box, this is done by manipulating the <tt/entry/ widget directly:
5274
5275 <tscreen><verb>
5276     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "My String.");
5277 </verb></tscreen>
5278
5279 To set the values in the popdown list, one uses the function:
5280
5281 <tscreen><verb>
5282 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5283                                     GList    *strings );
5284 </verb></tscreen>
5285
5286 Before you can do this, you have to assemble a GList of the strings
5287 that you want. GList is a linked list implementation that is part of
5288 <ref id="sec_glib" name="glib">, a library supporing GTK. For the
5289 moment, the quick and dirty explanation is that you need to set up a
5290 GList pointer, set it equal to NULL, then append strings to it with
5291
5292 <tscreen><verb>
5293 GList *g_list_append( GList *glist, 
5294                       gpointer data );
5295 </verb></tscreen>
5296
5297 It is important that you set the initial GList pointer to NULL. The
5298 value returned from the g_list_append function must be used as the new
5299 pointer to the GList.
5300
5301 Here's a typical code segment for creating a set of options:
5302
5303 <tscreen><verb>
5304     GList *glist=NULL;
5305
5306     glist = g_list_append(glist, "String 1");
5307     glist = g_list_append(glist, "String 2");
5308     glist = g_list_append(glist, "String 3"); 
5309     glist = g_list_append(glist, "String 4");
5310
5311     gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ;
5312 </verb></tscreen>
5313
5314 At this point you have a working combo box that has been set up.
5315 There are a few aspects of its behavior that you can change. These
5316 are accomplished with the functions: 
5317
5318 <tscreen><verb>
5319 void gtk_combo_set_use_arrows( GtkCombo *combo,
5320                                gint      val );
5321
5322 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5323                                       gint      val );
5324
5325 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5326                                    gint      val );
5327 </verb></tscreen>
5328
5329 <tt/gtk_combo_set_use_arrows()/ lets the user change the value in the
5330 entry using the up/down arrow keys. This doesn't bring up the list, but
5331 rather replaces the current text in the entry with the next list entry
5332 (up or down, as your key choice indicates). It does this by searching
5333 in the list for the item corresponding to the current value in the
5334 entry and selecting the previous/next item accordingly. Usually in an
5335 entry the arrow keys are used to change focus (you can do that anyway
5336 using TAB). Note that when the current item is the last of the list
5337 and you press arrow-down it changes the focus (the same applies with
5338 the first item and arrow-up).
5339
5340 If the current value in the entry is not in the list, then the
5341 function of <tt/gtk_combo_set_use_arrows()/ is disabled.
5342
5343 <tt/gtk_combo_set_use_arrows_always()/ similarly allows the use the
5344 the up/down arrow keys to cycle through the choices in the dropdown
5345 list, except that it wraps around the values in the list, completely
5346 disabling the use of the up and down arrow keys for changing focus.
5347
5348 <tt/gtk_combo_set_case_sensitive()/ toggles whether or not GTK
5349 searches for entries in a case sensitive manner. This is used when
5350 the Combo widget is asked to find a value from the list using the
5351 current entry in the text box. This completion can be performed in
5352 eother a case sensitive or insensitive manner, depending upon the use
5353 of this function. The Combo widget can also simply complete the
5354 current entry if the user presses the key combination MOD-1 and
5355 'Tab'. MOD-1 is often mapped to the 'Alt' key. Note, however that some
5356 Window managers also use this key combination, which will override
5357 it's use within GTK.
5358
5359 Now that we have a combo box, tailored to look and act how we want it,
5360 all that remains is being able to get data from the combo box. This is
5361 relatively straight forward. The majority of the time, all you are
5362 going to care about getting data from is the entry. The entry is
5363 accessed simply by GTK_ENTRY(GTK_COMBO(combo)->entry). The two
5364 principle things that you are going to want to do with it are attach
5365 to the activate signal, which indicates that the user has pressed the
5366 Return or Enter key,and read the text. The first is accomplished
5367 using something like:
5368
5369 <tscreen><verb>
5370     gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate",
5371                        GTK_SIGNAL_FUNC (my_callback_function), my_data);
5372 </verb></tscreen>
5373
5374 Getting the text at any arbitrary time is accomplished by simply using
5375 the entry function:
5376
5377 <tscreen><verb>
5378 gchar *gtk_entry_get_text(GtkEntry *entry);
5379 </verb></tscreen>
5380
5381 Such as:
5382
5383 <tscreen><verb>
5384     char *string;
5385
5386     string = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
5387 </verb></tscreen>
5388
5389 That's about all there is to it. There is a function
5390
5391 <tscreen><verb>
5392 void gtk_combo_disable_activate(GtkCombo *combo);
5393 </verb></tscreen>
5394
5395 that will disable the activate signal on the entry widget in the combo
5396 box. Personally, I can't think of why you'd want to use it, but it
5397 does exist.
5398
5399 <!-- There are also a function to set the string on a particular item, void
5400 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5401 *item_value), but this requires that you have a pointer to the
5402 appropriate GtkItem.  Frankly, I have no idea how to do that.
5403 -->
5404
5405 <!-- ----------------------------------------------------------------- -->
5406 <sect1> Color Selection
5407 <p>
5408 The color selection widget is, not surprisingly, a widget for
5409 interactive selection of colors. This composite widget lets the user
5410 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5411 Saturation, Value) triples.  This is done either by adjusting single
5412 values with sliders or entries, or by picking the desired color from a
5413 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5414 can also be set.
5415
5416 The color selection widget currently emits only one signal,
5417 "color_changed", which is emitted whenever the current color in the
5418 widget changes, either when the user changes it or if it's set
5419 explicitly through gtk_color_selection_set_color().
5420
5421 Lets have a look at what the color selection widget has to offer
5422 us. The widget comes in two flavours: gtk_color_selection and
5423 gtk_color_selection_dialog.
5424
5425 <tscreen><verb>
5426 GtkWidget *gtk_color_selection_new( void );
5427 </verb></tscreen>
5428         
5429 You'll probably not be using this constructor directly. It creates an
5430 orphan GtkColorSelection widget which you'll have to parent
5431 yourself. The GtkColorSelection widget inherits from the GtkVBox
5432 widget.
5433
5434 <tscreen><verb> 
5435 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5436 </verb></tscreen>
5437
5438 This is the most common color selection constructor. It creates a
5439 GtkColorSelectionDialog, which inherits from a GtkDialog. It consists
5440 of a GtkFrame containing a GtkColorSelection widget, a GtkHSeparator
5441 and a GtkHBox with three buttons, "Ok", "Cancel" and "Help". You can
5442 reach these buttons by accessing the "ok_button", "cancel_button" and
5443 "help_button" widgets in the GtkColorSelectionDialog structure,
5444 (i.e. GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
5445
5446 <tscreen><verb>
5447 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
5448                                             GtkUpdateType      policy );
5449 </verb></tscreen>
5450
5451 This function sets the update policy. The default policy is
5452 GTK_UPDATE_CONTINUOUS which means that the current color is updated
5453 continuously when the user drags the sliders or presses the mouse and
5454 drags in the hue-saturation wheel or value bar. If you experience
5455 performance problems, you may want to set the policy to
5456 GTK_UPDATE_DISCONTINUOUS or GTK_UPDATE_DELAYED.
5457
5458 <tscreen><verb>
5459 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
5460                                       gint               use_opacity );
5461 </verb></tscreen>
5462
5463 The color selection widget supports adjusting the opacity of a color
5464 (also known as the alpha channel). This is disabled by
5465 default. Calling this function with use_opacity set to TRUE enables
5466 opacity. Likewise, use_opacity set to FALSE will disable opacity.
5467
5468 <tscreen><verb>
5469 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
5470                                     gdouble           *color );
5471 </verb></tscreen>
5472
5473 You can set the current color explicitly by calling this function with
5474 a pointer to an array of colors (gdouble). The length of the array
5475 depends on whether opacity is enabled or not. Position 0 contains the
5476 red component, 1 is green, 2 is blue and opacity is at position 3
5477 (only if opacity is enabled, see
5478 gtk_color_selection_set_opacity()). All values are between 0.0 and
5479 1.0.
5480
5481 <tscreen><verb>
5482 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
5483                                     gdouble           *color );
5484 </verb></tscreen>
5485
5486 When you need to query the current color, typically when you've
5487 received a "color_changed" signal, you use this function. Color is a
5488 pointer to the array of colors to fill in. See the
5489 gtk_color_selection_set_color() function for the description of this
5490 array.
5491
5492 <!-- Need to do a whole section on DnD - TRG
5493 Drag and drop
5494 -------------
5495
5496 The color sample areas (right under the hue-saturation wheel) supports
5497 drag and drop. The type of drag and drop is "application/x-color". The
5498 message data consists of an array of 4 (or 5 if opacity is enabled)
5499 gdouble values, where the value at position 0 is 0.0 (opacity on) or
5500 1.0 (opacity off) followed by the red, green and blue values at
5501 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
5502 is passed in the value at position 4.
5503 -->
5504
5505 Here's a simple example demonstrating the use of the
5506 GtkColorSelectionDialog. The program displays a window containing a
5507 drawing area. Clicking on it opens a color selection dialog, and
5508 changing the color in the color selection dialog changes the
5509 background color.
5510
5511 <tscreen><verb>
5512 /* example-start colorsel colorsel.c */
5513
5514 #include <glib.h>
5515 #include <gdk/gdk.h>
5516 #include <gtk/gtk.h>
5517
5518 GtkWidget *colorseldlg = NULL;
5519 GtkWidget *drawingarea = NULL;
5520
5521 /* Color changed handler */
5522
5523 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
5524 {
5525   gdouble color[3];
5526   GdkColor gdk_color;
5527   GdkColormap *colormap;
5528
5529   /* Get drawingarea colormap */
5530
5531   colormap = gdk_window_get_colormap (drawingarea->window);
5532
5533   /* Get current color */
5534
5535   gtk_color_selection_get_color (colorsel,color);
5536
5537   /* Fit to a unsigned 16 bit integer (0..65535) and
5538    * insert into the GdkColor structure */
5539
5540   gdk_color.red = (guint16)(color[0]*65535.0);
5541   gdk_color.green = (guint16)(color[1]*65535.0);
5542   gdk_color.blue = (guint16)(color[2]*65535.0);
5543
5544   /* Allocate color */
5545
5546   gdk_color_alloc (colormap, &amp;gdk_color);
5547
5548   /* Set window background color */
5549
5550   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
5551
5552   /* Clear window */
5553
5554   gdk_window_clear (drawingarea->window);
5555 }
5556
5557 /* Drawingarea event handler */
5558
5559 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
5560 {
5561   gint handled = FALSE;
5562   GtkWidget *colorsel;
5563
5564   /* Check if we've received a button pressed event */
5565
5566   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
5567     {
5568       /* Yes, we have an event and there's no colorseldlg yet! */
5569
5570       handled = TRUE;
5571
5572       /* Create color selection dialog */
5573
5574       colorseldlg = gtk_color_selection_dialog_new("Select background color");
5575
5576       /* Get the GtkColorSelection widget */
5577
5578       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
5579
5580       /* Connect to the "color_changed" signal, set the client-data
5581        * to the colorsel widget */
5582
5583       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
5584         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
5585
5586       /* Show the dialog */
5587
5588       gtk_widget_show(colorseldlg);
5589     }
5590
5591   return handled;
5592 }
5593
5594 /* Close down and exit handler */
5595
5596 void destroy_window (GtkWidget *widget, gpointer client_data)
5597 {
5598   gtk_main_quit ();
5599 }
5600
5601 /* Main */
5602
5603 gint main (gint argc, gchar *argv[])
5604 {
5605   GtkWidget *window;
5606
5607   /* Initialize the toolkit, remove gtk-related commandline stuff */
5608
5609   gtk_init (&amp;argc,&amp;argv);
5610
5611   /* Create toplevel window, set title and policies */
5612
5613   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5614   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
5615   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
5616
5617   /* Attach to the "delete" and "destroy" events so we can exit */
5618
5619   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
5620     (GtkSignalFunc)destroy_window, (gpointer)window);
5621
5622   gtk_signal_connect (GTK_OBJECT(window), "destroy",
5623     (GtkSignalFunc)destroy_window, (gpointer)window);
5624   
5625   /* Create drawingarea, set size and catch button events */
5626
5627   drawingarea = gtk_drawing_area_new ();
5628
5629   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
5630
5631   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
5632
5633   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
5634     (GtkSignalFunc)area_event, (gpointer)drawingarea);
5635   
5636   /* Add drawingarea to window, then show them both */
5637
5638   gtk_container_add (GTK_CONTAINER(window), drawingarea);
5639
5640   gtk_widget_show (drawingarea);
5641   gtk_widget_show (window);
5642   
5643   /* Enter the gtk main loop (this never returns) */
5644
5645   gtk_main ();
5646
5647   /* Satisfy grumpy compilers */
5648
5649   return(0);
5650 }
5651 /* example-end */
5652 </verb></tscreen>
5653
5654 <!-- ----------------------------------------------------------------- -->
5655 <sect1> File Selections
5656 <p>
5657 The file selection widget is a quick and simple way to display a File
5658 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
5659 great way to cut down on programming time.
5660
5661 To create a new file selection box use:
5662
5663 <tscreen><verb>
5664 GtkWidget *gtk_file_selection_new( gchar *title );
5665 </verb></tscreen>
5666
5667 To set the filename, for example to bring up a specific directory, or
5668 give a default filename, use this function:
5669
5670 <tscreen><verb>
5671 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
5672                                       gchar            *filename );
5673 </verb></tscreen>
5674
5675 To grab the text that the user has entered or clicked on, use this 
5676 function:
5677
5678 <tscreen><verb>
5679 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
5680 </verb></tscreen>
5681
5682 There are also pointers to the widgets contained within the file 
5683 selection widget. These are:
5684
5685 <itemize>
5686 <item>dir_list
5687 <item>file_list
5688 <item>selection_entry
5689 <item>selection_text
5690 <item>main_vbox
5691 <item>ok_button
5692 <item>cancel_button
5693 <item>help_button
5694 </itemize>
5695
5696 Most likely you will want to use the ok_button, cancel_button, and
5697 help_button pointers in signaling their use.
5698
5699 Included here is an example stolen from testgtk.c, modified to run on
5700 its own. As you will see, there is nothing much to creating a file
5701 selection widget. While in this example the Help button appears on the
5702 screen, it does nothing as there is not a signal attached to it.
5703
5704 <tscreen><verb>
5705 /* example-start filesel filesel.c */
5706
5707 #include <gtk/gtk.h>
5708
5709 /* Get the selected filename and print it to the console */
5710 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
5711 {
5712     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
5713 }
5714
5715 void destroy (GtkWidget *widget, gpointer data)
5716 {
5717     gtk_main_quit ();
5718 }
5719
5720 int main (int argc, char *argv[])
5721 {
5722     GtkWidget *filew;
5723     
5724     gtk_init (&amp;argc, &amp;argv);
5725     
5726     /* Create a new file selection widget */
5727     filew = gtk_file_selection_new ("File selection");
5728     
5729     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
5730                         (GtkSignalFunc) destroy, &amp;filew);
5731     /* Connect the ok_button to file_ok_sel function */
5732     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
5733                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
5734     
5735     /* Connect the cancel_button to destroy the widget */
5736     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
5737                                             (filew)->cancel_button),
5738                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
5739                                GTK_OBJECT (filew));
5740     
5741     /* Lets set the filename, as if this were a save dialog, and we are giving
5742      a default filename */
5743     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
5744                                      "penguin.png");
5745     
5746     gtk_widget_show(filew);
5747     gtk_main ();
5748     return 0;
5749 }
5750 /* example-end */
5751 </verb></tscreen>
5752
5753 <!-- ***************************************************************** -->
5754 <sect> Container Widgets
5755 <!-- ***************************************************************** -->
5756
5757 <!-- ----------------------------------------------------------------- -->   
5758 <sect1>The EventBox <label id="sec_EventBox">
5759 <p> 
5760 Some GTK widgets don't have associated X windows, so they just draw on
5761 their parents. Because of this, they cannot receive events and if they
5762 are incorrectly sized, they don't clip so you can get messy
5763 overwriting etc. If you require more from these widgets, the EventBox
5764 is for you.
5765
5766 At first glance, the EventBox widget might appear to be totally
5767 useless. It draws nothing on the screen and responds to no
5768 events. However, it does serve a function - it provides an X window
5769 for its child widget. This is important as many GTK widgets do not
5770 have an associated X window. Not having an X window saves memory and
5771 improves performance, but also has some drawbacks. A widget without an
5772 X window cannot receive events, and does not perform any clipping on
5773 its contents. Although the name <em/EventBox/ emphasizes the
5774 event-handling function, the widget can also be used for clipping.
5775 (and more, see the example below).
5776
5777 To create a new EventBox widget, use:
5778
5779 <tscreen><verb>
5780 GtkWidget *gtk_event_box_new( void );
5781 </verb></tscreen>
5782
5783 A child widget can then be added to this EventBox:
5784
5785 <tscreen><verb>
5786     gtk_container_add( GTK_CONTAINER(event_box), child_widget );
5787 </verb></tscreen>
5788
5789 The following example demonstrates both uses of an EventBox - a label
5790 is created that is clipped to a small box, and set up so that a
5791 mouse-click on the label causes the program to exit. Resizing the
5792 window reveals varying amounts of the label.
5793
5794 <tscreen><verb>
5795 /* example-start eventbox eventbox.c */
5796
5797 #include <gtk/gtk.h>
5798
5799 int 
5800 main (int argc, char *argv[])
5801 {
5802     GtkWidget *window;
5803     GtkWidget *event_box;
5804     GtkWidget *label;
5805     
5806     gtk_init (&amp;argc, &amp;argv);
5807     
5808     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5809     
5810     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
5811     
5812     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5813                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5814     
5815     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5816     
5817     /* Create an EventBox and add it to our toplevel window */
5818     
5819     event_box = gtk_event_box_new ();
5820     gtk_container_add (GTK_CONTAINER(window), event_box);
5821     gtk_widget_show (event_box);
5822     
5823     /* Create a long label */
5824     
5825     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
5826     gtk_container_add (GTK_CONTAINER (event_box), label);
5827     gtk_widget_show (label);
5828     
5829     /* Clip it short. */
5830     gtk_widget_set_usize (label, 110, 20);
5831     
5832     /* And bind an action to it */
5833     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
5834     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
5835                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5836     
5837     /* Yet one more thing you need an X window for ... */
5838     
5839     gtk_widget_realize (event_box);
5840     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
5841     
5842     gtk_widget_show (window);
5843     
5844     gtk_main ();
5845     
5846     return(0);
5847 }
5848 /* example-end */
5849 </verb></tscreen>
5850
5851 <!-- ----------------------------------------------------------------- -->   
5852 <sect1>The Alignment widget <label id="sec_Alignment">
5853 <p>
5854 The alignment widget allows you to place a widget within its window at
5855 a position and size relative to the size of the Alignment widget
5856 itself. For example, it can be very useful for centering a widget
5857 within the window.
5858
5859 There are only two functions associated with the Alignment widget:
5860
5861 <tscreen><verb>
5862 GtkWidget* gtk_alignment_new( gfloat xalign,
5863                               gfloat yalign,
5864                               gfloat xscale,
5865                               gfloat yscale );
5866
5867 void gtk_alignment_set( GtkAlignment *alignment,
5868                         gfloat        xalign,
5869                         gfloat        yalign,
5870                         gfloat        xscale,
5871                         gfloat        yscale );
5872 </verb></tscreen>
5873
5874 The first function creates a new Alignment widget with the specified
5875 parameters. The second function allows the alignment paramters of an
5876 exisiting Alignment widget to be altered.
5877
5878 All four alignment parameters are floating point numbers which can
5879 range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
5880 affect the position of the widget placed within the Alignment
5881 widget. The <tt/xscale/ and <tt/yscale/ arguments effect the amount of
5882 space allocated to the widget.
5883
5884 A child widget can be added to this Alignment widget using:
5885
5886 <tscreen><verb>
5887     gtk_container_add( GTK_CONTAINER(alignment), child_widget );
5888 </verb></tscreen>
5889
5890 For an example of using an Alignment widget, refer to the example for
5891 the <ref id="sec_ProgressBar" name="Progress Bar"> widget.
5892
5893 <!-- ----------------------------------------------------------------- -->
5894 <sect1> Fixed Container
5895 <p>
5896 The Fixed container allows you to place widgets at a fixed position
5897 within it's window, relative to it's upper left hand corner. The
5898 position of the widgets can be changed dynamically.
5899
5900 There are only three functions associated with the fixed widget:
5901
5902 <tscreen><verb>
5903 GtkWidget* gtk_fixed_new( void );
5904
5905 void gtk_fixed_put( GtkFixed  *fixed,
5906                     GtkWidget *widget,
5907                     gint16     x,
5908                     gint16     y );
5909
5910 void gtk_fixed_move( GtkFixed  *fixed,
5911                      GtkWidget *widget,
5912                      gint16     x,
5913                      gint16     y );
5914 </verb></tscreen>
5915
5916 The function <tt/gtk_fixed_new/ allows you to create a new Fixed
5917 container.
5918
5919 <tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
5920 the position specified by <tt/x/ and <tt/y/.
5921
5922 <tt/gtk_fixed_move/ allows the specified widget to be moved to a new
5923 position.
5924
5925 The following example illustrates how to use the Fixed Container.
5926
5927 <tscreen><verb>
5928 /* example-start fixed fixed.c */
5929
5930 #include <gtk/gtk.h>
5931
5932 /* I'm going to be lazy and use some global variables to
5933  * store the position of the widget within the fixed
5934  * container */
5935 gint x=50;
5936 gint y=50;
5937
5938 /* This callback function moves the button to a new position
5939  * in the Fixed container. */
5940 void move_button( GtkWidget *widget,
5941                   GtkWidget *fixed )
5942 {
5943   x = (x+30)%300;
5944   y = (y+50)%300;
5945   gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); 
5946 }
5947
5948 int main( int   argc,
5949           char *argv[] )
5950 {
5951   /* GtkWidget is the storage type for widgets */
5952   GtkWidget *window;
5953   GtkWidget *fixed;
5954   GtkWidget *button;
5955   gint i;
5956
5957   /* Initialise GTK */
5958   gtk_init(&amp;argc, &amp;argv);
5959     
5960   /* Create a new window */
5961   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5962   gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
5963
5964   /* Here we connect the "destroy" event to a signal handler */ 
5965   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5966                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
5967  
5968   /* Sets the border width of the window. */
5969   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5970
5971   /* Create a Fixed Container */
5972   fixed = gtk_fixed_new();
5973   gtk_container_add(GTK_CONTAINER(window), fixed);
5974   gtk_widget_show(fixed);
5975   
5976   for (i = 1 ; i <= 3 ; i++) {
5977     /* Creates a new button with the label "Press me" */
5978     button = gtk_button_new_with_label ("Press me");
5979   
5980     /* When the button receives the "clicked" signal, it will call the
5981      * function move_button() passing it the Fixed Containter as its
5982      * argument. */
5983     gtk_signal_connect (GTK_OBJECT (button), "clicked",
5984                         GTK_SIGNAL_FUNC (move_button), fixed);
5985   
5986     /* This packs the button into the fixed containers window. */
5987     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
5988   
5989     /* The final step is to display this newly created widget. */
5990     gtk_widget_show (button);
5991   }
5992
5993   /* Display the window */
5994   gtk_widget_show (window);
5995     
5996   /* Enter the event loop */
5997   gtk_main ();
5998     
5999   return(0);
6000 }
6001 /* example-end */
6002 </verb></tscreen>
6003
6004 <!-- ----------------------------------------------------------------- -->
6005 <sect1> Layout Container
6006 <p>
6007 The Layout container is similar to the Fixed container except that it
6008 implements an infinite (where infinity is less than 2^32) scrolling
6009 area. Xwindows has a limitation where windows can be at most 32767
6010 pixels wide or tall. The Layout container gets around this limitation
6011 by doing some exotic stuff using window and bit gravities, so that you
6012 can have smooth scrolling even when you have many child widgets in
6013 your scrolling area.
6014
6015 A Layout container is created using:
6016
6017 <tscreen><verb>
6018 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6019                            GtkAdjustment *vadjustment );
6020 </verb></tscreen>
6021
6022 As you can see, you can optionally specify the Adjustment objects that
6023 the Layout widget will use for it's scrolling.
6024
6025 You can add and move widgets in the Layout container using the
6026 following two functions:
6027
6028 <tscreen><verb>
6029 void gtk_layout_put( GtkLayout *layout,
6030                      GtkWidget *widget,
6031                      gint       x,
6032                      gint       y );
6033
6034 void gtk_layout_move( GtkLayout *layout,
6035                       GtkWidget *widget,
6036                       gint       x,
6037                       gint       y );
6038 </verb></tscreen>
6039
6040 The size of the Layout container can be set using the next function:
6041
6042 <tscreen><verb>
6043 void gtk_layout_set_size( GtkLayout *layout,
6044                           guint      width,
6045                           guint      height );
6046 </verb></tscreen>
6047
6048 Layout containers are one of the very few widgets in the GTK widget
6049 set that actively repaint themselves on screen as they are changed
6050 using the above functions (the vast majority of widgets queue
6051 requests which are then processed when control returns to the
6052 <tt/gtk_main()/ function).
6053
6054 When you want to make a large number of changes to a Layout container,
6055 you can use the following two functions to disable and re-enable this
6056 repainting functionality:
6057
6058 <tscreen><verb>
6059 void gtk_layout_freeze( GtkLayout *layout );
6060
6061 void gtk_layout_thaw( GtkLayout *layout );
6062 </verb></tscreen>
6063
6064 The final four functions for use with Layout widgets are for
6065 manipulating the horizontal and vertical adjustment widgets:
6066
6067 <tscreen><verb>
6068 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6069
6070 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6071
6072 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6073                                  GtkAdjustment *adjustment );
6074
6075 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6076                                  GtkAdjustment *adjustment);
6077 </verb></tscreen>
6078
6079 <!-- ----------------------------------------------------------------- -->
6080 <sect1> Frames <label id="sec_Frames">
6081 <p>
6082 Frames can be used to enclose one or a group of widgets with a box
6083 which can optionally be labelled. The position of the label and the
6084 style of the box can be altered to suit.
6085
6086 A Frame can be created with the following function:
6087
6088 <tscreen><verb>
6089 GtkWidget *gtk_frame_new( const gchar *label );
6090 </verb></tscreen>
6091
6092 The label is by default placed in the upper left hand corner of the
6093 frame. A value of NULL for the <tt/label/ argument will result in no
6094 label being displayed. The text of the label can be changed using the
6095 next function.
6096
6097 <tscreen><verb>
6098 void gtk_frame_set_label( GtkFrame    *frame,
6099                           const gchar *label );
6100 </verb></tscreen>
6101
6102 The position of the label can be changed using this function:
6103
6104 <tscreen><verb>
6105 void gtk_frame_set_label_align( GtkFrame *frame,
6106                                 gfloat    xalign,
6107                                 gfloat    yalign );
6108 </verb></tscreen>
6109
6110 <tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
6111 indicates the position of the label along the top horizontal of the
6112 frame. <tt/yalign/ is not currently used. The default value of xalign
6113 is 0.0 which places the label at the left hand end of the frame.
6114
6115 The next function alters the style of the box that is used to outline
6116 the frame.
6117
6118 <tscreen><verb>
6119 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6120                                 GtkShadowType  type);
6121 </verb></tscreen>
6122
6123 The <tt/type/ argument can take one of the following values:
6124 <itemize>
6125 <item> GTK_SHADOW_NONE
6126 <item> GTK_SHADOW_IN
6127 <item> GTK_SHADOW_OUT
6128 <item> GTK_SHADOW_ETCHED_IN (the default)
6129 <item> GTK_SHADOW_ETCHED_OUT
6130 </itemize>
6131
6132 The following code example illustrates the use of the Frame widget.
6133
6134 <tscreen><verb>
6135 /* example-start frame frame.c */
6136
6137 #include <gtk/gtk.h>
6138
6139 int main( int   argc,
6140           char *argv[] )
6141 {
6142   /* GtkWidget is the storage type for widgets */
6143   GtkWidget *window;
6144   GtkWidget *frame;
6145   GtkWidget *button;
6146   gint i;
6147
6148   /* Initialise GTK */
6149   gtk_init(&amp;argc, &amp;argv);
6150     
6151   /* Create a new window */
6152   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6153   gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
6154
6155   /* Here we connect the "destroy" event to a signal handler */ 
6156   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6157                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6158
6159   gtk_widget_set_usize(window, 300, 300);
6160   /* Sets the border width of the window. */
6161   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6162
6163   /* Create a Frame */
6164   frame = gtk_frame_new(NULL);
6165   gtk_container_add(GTK_CONTAINER(window), frame);
6166
6167   /* Set the frames label */
6168   gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
6169
6170   /* Align the label at the right of the frame */
6171   gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
6172
6173   /* Set the style of the frame */
6174   gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
6175
6176   gtk_widget_show(frame);
6177   
6178   /* Display the window */
6179   gtk_widget_show (window);
6180     
6181   /* Enter the event loop */
6182   gtk_main ();
6183     
6184   return(0);
6185 }
6186 /* example-end */
6187
6188 </verb></tscreen>
6189
6190 <!-- ----------------------------------------------------------------- -->   
6191 <sect1> Aspect Frames
6192 <p>
6193 The aspect frame widget is like a frame widget, except that it also
6194 enforces the aspect ratio (that is, the ratio of the width to the
6195 height) of the child widget to have a certain value, adding extra
6196 space if necessary. This is useful, for instance, if you want to
6197 preview a larger image. The size of the preview should vary when the
6198 user resizes the window, but the aspect ratio needs to always match
6199 the original image.
6200   
6201 To create a new aspect frame use:
6202    
6203 <tscreen><verb>
6204 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6205                                  gfloat       xalign,
6206                                  gfloat       yalign,
6207                                  gfloat       ratio,
6208                                  gint         obey_child);
6209 </verb></tscreen>
6210    
6211 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
6212 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
6213 widget will match the aspect ratio of the ideal size it requests.
6214 Otherwise, it is given by <tt/ratio/.
6215    
6216 To change the options of an existing aspect frame, you can use:
6217    
6218 <tscreen><verb>
6219 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6220                            gfloat          xalign,
6221                            gfloat          yalign,
6222                            gfloat          ratio,
6223                            gint            obey_child);
6224 </verb></tscreen>
6225    
6226 As an example, the following program uses an AspectFrame to present a
6227 drawing area whose aspect ratio will always be 2:1, no matter how the
6228 user resizes the top-level window.
6229    
6230 <tscreen><verb>
6231 /* example-start aspectframe aspectframe.c */
6232
6233 #include <gtk/gtk.h>
6234    
6235 int
6236 main (int argc, char *argv[])
6237 {
6238     GtkWidget *window;
6239     GtkWidget *aspect_frame;
6240     GtkWidget *drawing_area;
6241     gtk_init (&amp;argc, &amp;argv);
6242    
6243     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6244     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
6245     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6246                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6247     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6248    
6249     /* Create an aspect_frame and add it to our toplevel window */
6250    
6251     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
6252                                          0.5, /* center x */
6253                                          0.5, /* center y */
6254                                          2, /* xsize/ysize = 2 */
6255                                          FALSE /* ignore child's aspect */);
6256    
6257     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
6258     gtk_widget_show (aspect_frame);
6259    
6260     /* Now add a child widget to the aspect frame */
6261    
6262     drawing_area = gtk_drawing_area_new ();
6263    
6264     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6265      * window since we are forcing a 2x1 aspect ratio */
6266     gtk_widget_set_usize (drawing_area, 200, 200);
6267     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
6268     gtk_widget_show (drawing_area);
6269    
6270     gtk_widget_show (window);
6271     gtk_main ();
6272     return 0;
6273 }
6274 /* example-end */
6275 </verb></tscreen>
6276
6277 <!-- ----------------------------------------------------------------- -->   
6278 <sect1> Paned Window Widgets
6279 <p>
6280 The paned window widgets are useful when you want to divide an area
6281 into two parts, with the relative size of the two parts controlled by
6282 the user. A groove is drawn between the two portions with a handle
6283 that the user can drag to change the ratio. The division can either be
6284 horizontal (HPaned) or vertical (VPaned).
6285    
6286 To create a new paned window, call one of:
6287    
6288 <tscreen><verb>
6289 GtkWidget *gtk_hpaned_new (void);
6290
6291 GtkWidget *gtk_vpaned_new (void);
6292 </verb></tscreen>
6293
6294 After creating the paned window widget, you need to add child widgets
6295 to its two halves. To do this, use the functions:
6296    
6297 <tscreen><verb>
6298 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6299
6300 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6301 </verb></tscreen>
6302    
6303 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
6304 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
6305 right or bottom half of the paned window.
6306
6307 A paned widget can be changed visually using the following two
6308 functions.
6309
6310 <tscreen><verb>
6311 void gtk_paned_set_handle_size( GtkPaned *paned,
6312                                 guint16   size);
6313
6314 void gtk_paned_set_gutter_size( GtkPaned *paned,
6315                                 guint16   size);
6316 </verb></tscreen>
6317
6318 The first of these sets the size of the handle and the second sets the
6319 size of the gutter that is between the two parts of the paned window.
6320
6321 As an example, we will create part of the user interface of an
6322 imaginary email program. A window is divided into two portions
6323 vertically, with the top portion being a list of email messages and
6324 the bottom portion the text of the email message. Most of the program
6325 is pretty straightforward. A couple of points to note: text can't be
6326 added to a Text widget until it is realized. This could be done by
6327 calling <tt/gtk_widget_realize()/, but as a demonstration of an
6328 alternate technique, we connect a handler to the "realize" signal to
6329 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
6330 of the items in the table containing the text window and its
6331 scrollbars, so that when the bottom portion is made smaller, the
6332 correct portions shrink instead of being pushed off the bottom of the
6333 window.
6334
6335 <tscreen><verb>
6336 /* example-start paned paned.c */
6337
6338 #include <gtk/gtk.h>
6339    
6340 /* Create the list of "messages" */
6341 GtkWidget *
6342 create_list (void)
6343 {
6344
6345     GtkWidget *scrolled_window;
6346     GtkWidget *list;
6347     GtkWidget *list_item;
6348    
6349     int i;
6350     char buffer[16];
6351    
6352     /* Create a new scrolled window, with scrollbars only if needed */
6353     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6354     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6355                                     GTK_POLICY_AUTOMATIC, 
6356                                     GTK_POLICY_AUTOMATIC);
6357    
6358     /* Create a new list and put it in the scrolled window */
6359     list = gtk_list_new ();
6360     gtk_scrolled_window_add_with_viewport (
6361                GTK_SCROLLED_WINDOW (scrolled_window), list);
6362     gtk_widget_show (list);
6363    
6364     /* Add some messages to the window */
6365     for (i=0; i<10; i++) {
6366
6367         sprintf(buffer,"Message #%d",i);
6368         list_item = gtk_list_item_new_with_label (buffer);
6369         gtk_container_add (GTK_CONTAINER(list), list_item);
6370         gtk_widget_show (list_item);
6371
6372     }
6373    
6374     return scrolled_window;
6375 }
6376    
6377 /* Add some text to our text widget - this is a callback that is invoked
6378 when our window is realized. We could also force our window to be
6379 realized with gtk_widget_realize, but it would have to be part of
6380 a hierarchy first */
6381
6382 void
6383 realize_text (GtkWidget *text, gpointer data)
6384 {
6385     gtk_text_freeze (GTK_TEXT (text));
6386     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
6387     "From: pathfinder@nasa.gov\n"
6388     "To: mom@nasa.gov\n"
6389     "Subject: Made it!\n"
6390     "\n"
6391     "We just got in this morning. The weather has been\n"
6392     "great - clear but cold, and there are lots of fun sights.\n"
6393     "Sojourner says hi. See you soon.\n"
6394     " -Path\n", -1);
6395    
6396     gtk_text_thaw (GTK_TEXT (text));
6397 }
6398    
6399 /* Create a scrolled text area that displays a "message" */
6400 GtkWidget *
6401 create_text (void)
6402 {
6403     GtkWidget *table;
6404     GtkWidget *text;
6405     GtkWidget *hscrollbar;
6406     GtkWidget *vscrollbar;
6407    
6408     /* Create a table to hold the text widget and scrollbars */
6409     table = gtk_table_new (2, 2, FALSE);
6410    
6411     /* Put a text widget in the upper left hand corner. Note the use of
6412      * GTK_SHRINK in the y direction */
6413     text = gtk_text_new (NULL, NULL);
6414     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
6415                       GTK_FILL | GTK_EXPAND,
6416                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
6417     gtk_widget_show (text);
6418    
6419     /* Put a HScrollbar in the lower left hand corner */
6420     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
6421     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
6422                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6423     gtk_widget_show (hscrollbar);
6424    
6425     /* And a VScrollbar in the upper right */
6426     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
6427     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
6428                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
6429     gtk_widget_show (vscrollbar);
6430    
6431     /* Add a handler to put a message in the text widget when it is realized */
6432     gtk_signal_connect (GTK_OBJECT (text), "realize",
6433                         GTK_SIGNAL_FUNC (realize_text), NULL);
6434    
6435     return table;
6436 }
6437    
6438 int
6439 main (int argc, char *argv[])
6440 {
6441     GtkWidget *window;
6442     GtkWidget *vpaned;
6443     GtkWidget *list;
6444     GtkWidget *text;
6445
6446     gtk_init (&amp;argc, &amp;argv);
6447    
6448     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6449     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
6450     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6451                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6452     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6453     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
6454
6455     /* create a vpaned widget and add it to our toplevel window */
6456    
6457     vpaned = gtk_vpaned_new ();
6458     gtk_container_add (GTK_CONTAINER(window), vpaned);
6459     gtk_paned_set_handle_size (GTK_PANED(vpaned),
6460                                10);
6461     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
6462                                15);                       
6463     gtk_widget_show (vpaned);
6464    
6465     /* Now create the contents of the two halves of the window */
6466    
6467     list = create_list ();
6468     gtk_paned_add1 (GTK_PANED(vpaned), list);
6469     gtk_widget_show (list);
6470    
6471     text = create_text ();
6472     gtk_paned_add2 (GTK_PANED(vpaned), text);
6473     gtk_widget_show (text);
6474     gtk_widget_show (window);
6475     gtk_main ();
6476     return 0;
6477 }
6478 /* example-end */
6479 </verb></tscreen>
6480
6481 <!-- ----------------------------------------------------------------- -->
6482 <sect1>Viewports <label id="sec_Viewports">
6483 <p>
6484 It is unlikely that you will ever need to use the Viewport widget
6485 directly. You are much more likely to use the
6486 <ref id="sec_ScrolledWindows" name="Scrolled Windows"> widget which
6487 itself uses the Viewport.
6488
6489 A viewport widget allows you to place a larger widget within it such
6490 that you can view a part of it at a time. It uses
6491 <ref id="sec_Adjustment" name="Adjustments"> to define the area that
6492 is currently in view.
6493
6494 A Viewport is created with the function
6495
6496 <tscreen><verb>
6497 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
6498                              GtkAdjustment *vadjustment );
6499 </verb></tscreen>
6500
6501 As you can see you can specify the horizontal and vertical Adjustments
6502 that the widget is to use when you create the widget. It will create
6503 it's own if you pass NULL as the value of the arguments.
6504
6505 You can get and set the adjustments after the widget has been created
6506 using the following four functions:
6507
6508 <tscreen><verb>
6509 GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
6510
6511 GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
6512
6513 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
6514                                    GtkAdjustment *adjustment );
6515
6516 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
6517                                    GtkAdjustment *adjustment );
6518 </verb></tscreen>
6519
6520 The only other viewport function is used to alter its appearance:
6521
6522 <tscreen><verb>
6523 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
6524                                    GtkShadowType  type );
6525 </verb></tscreen>
6526
6527 Possible values for the <tt/type/ parameter are:
6528 <itemize>
6529 <item> GTK_SHADOW_NONE,
6530 <item> GTK_SHADOW_IN,
6531 <item> GTK_SHADOW_OUT,
6532 <item> GTK_SHADOW_ETCHED_IN,
6533 <item> GTK_SHADOW_ETCHED_OUT
6534 </itemize>
6535
6536 <!-- ----------------------------------------------------------------- -->
6537 <sect1>Scrolled Windows <label id="sec_ScrolledWindows">
6538 <p>
6539 Scrolled windows are used to create a scrollable area inside a real
6540 window.  You may insert any type of widget into a scrolled window, and
6541 it will be accessible regardless of the size by using the scrollbars.
6542
6543 The following function is used to create a new scrolled window.
6544
6545 <tscreen><verb>
6546 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
6547                                     GtkAdjustment *vadjustment );
6548 </verb></tscreen>
6549
6550 Where the first argument is the adjustment for the horizontal
6551 direction, and the second, the adjustment for the vertical direction.
6552 These are almost always set to NULL.
6553
6554 <tscreen><verb>
6555 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
6556                                      GtkPolicyType      hscrollbar_policy,
6557                                      GtkPolicyType      vscrollbar_policy );
6558 </verb></tscreen>
6559
6560 This sets the policy to be used with respect to the scrollbars.
6561 The first argument is the scrolled window you wish to change. The second
6562 sets the policy for the horizontal scrollbar, and the third the policy for 
6563 the vertical scrollbar.
6564
6565 The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
6566 GTK_POLICY_AUTOMATIC will automatically decide whether you need
6567 scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6568 there.
6569
6570 You can then place your object into the scrolled window using the
6571 following function.
6572
6573 <tscreen><verb>
6574 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
6575                                             GtkWidget         *child);
6576 </verb></tscreen>
6577
6578 Here is a simple example that packs 100 toggle buttons into a scrolled
6579 window.  I've only commented on the parts that may be new to you.
6580
6581 <tscreen><verb>
6582 /* example-start scrolledwin scrolledwin.c */
6583
6584 #include <gtk/gtk.h>
6585
6586 void destroy(GtkWidget *widget, gpointer data)
6587 {
6588     gtk_main_quit();
6589 }
6590
6591 int main (int argc, char *argv[])
6592 {
6593     static GtkWidget *window;
6594     GtkWidget *scrolled_window;
6595     GtkWidget *table;
6596     GtkWidget *button;
6597     char buffer[32];
6598     int i, j;
6599     
6600     gtk_init (&amp;argc, &amp;argv);
6601     
6602     /* Create a new dialog window for the scrolled window to be
6603      * packed into. A dialog is just like a normal window except it has a 
6604      * vbox and a horizontal separator packed into it. It's just a shortcut
6605      * for creating dialogs */
6606     window = gtk_dialog_new ();
6607     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6608                         (GtkSignalFunc) destroy, NULL);
6609     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
6610     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6611     gtk_widget_set_usize(window, 300, 300);
6612     
6613     /* create a new scrolled window. */
6614     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6615     
6616     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
6617     
6618     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
6619      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
6620      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6621      * there.  The first one is the horizontal scrollbar, the second, 
6622      * the vertical. */
6623     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6624                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
6625     /* The dialog window is created with a vbox packed into it. */                                                              
6626     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
6627                         TRUE, TRUE, 0);
6628     gtk_widget_show (scrolled_window);
6629     
6630     /* create a table of 10 by 10 squares. */
6631     table = gtk_table_new (10, 10, FALSE);
6632     
6633     /* set the spacing to 10 on x and 10 on y */
6634     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
6635     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
6636     
6637     /* pack the table into the scrolled window */
6638     gtk_scrolled_window_add_with_viewport (
6639                    GTK_SCROLLED_WINDOW (scrolled_window), table);
6640     gtk_widget_show (table);
6641     
6642     /* this simply creates a grid of toggle buttons on the table
6643      * to demonstrate the scrolled window. */
6644     for (i = 0; i < 10; i++)
6645        for (j = 0; j < 10; j++) {
6646           sprintf (buffer, "button (%d,%d)\n", i, j);
6647           button = gtk_toggle_button_new_with_label (buffer);
6648           gtk_table_attach_defaults (GTK_TABLE (table), button,
6649                                      i, i+1, j, j+1);
6650           gtk_widget_show (button);
6651        }
6652     
6653     /* Add a "close" button to the bottom of the dialog */
6654     button = gtk_button_new_with_label ("close");
6655     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6656                                (GtkSignalFunc) gtk_widget_destroy,
6657                                GTK_OBJECT (window));
6658     
6659     /* this makes it so the button is the default. */
6660     
6661     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6662     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
6663     
6664     /* This grabs this button to be the default button. Simply hitting
6665      * the "Enter" key will cause this button to activate. */
6666     gtk_widget_grab_default (button);
6667     gtk_widget_show (button);
6668     
6669     gtk_widget_show (window);
6670     
6671     gtk_main();
6672     
6673     return(0);
6674 }
6675 /* example-end */
6676 </verb></tscreen>
6677
6678 Try playing with resizing the window. You'll notice how the scrollbars
6679 react. You may also wish to use the gtk_widget_set_usize() call to set
6680 the default size of the window or other widgets.
6681
6682 <!-- ----------------------------------------------------------------- -->   
6683 <sect1>Button Boxes
6684 <p>
6685 Button Boxes are a convenient way to quickly layout a group of
6686 buttons. They come in both horizontal and vertical flavours. You
6687 create a new Button Box with one of the following calls, which create
6688 a horizontal or vertical box, respectively:
6689
6690 <tscreen><verb>
6691 GtkWidget *gtk_hbutton_box_new( void );
6692
6693 GtkWidget *gtk_vbutton_box_new( void );
6694 </verb></tscreen>
6695
6696 The only attributes pertaining to button boxes effect how the buttons
6697 are layed out. You can change the spacing between the buttons with:
6698
6699 <tscreen><verb>
6700 void gtk_hbutton_box_set_spacing_default( gint spacing );
6701
6702 void gtk_vbutton_box_set_spacing_default( gint spacing );
6703 </verb></tscreen>
6704
6705 Similarly, the current spacing values can be queried using:
6706
6707 <tscreen><verb>
6708 gint gtk_hbutton_box_get_spacing_default( void );
6709
6710 gint gtk_vbutton_box_get_spacing_default( void );
6711 </verb></tscreen>
6712
6713 The second attribute that we can access effects the layour of the
6714 buttons within the box. It is set using one of:
6715
6716 <tscreen><verb>
6717 void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6718
6719 void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6720 </verb></tscreen>
6721
6722 The <tt/layout/ argument can take one of the following values:
6723
6724 <itemize>
6725 <item> GTK_BUTTONBOX_DEFAULT_STYLE
6726 <item> GTK_BUTTONBOX_SPREAD
6727 <item> GTK_BUTTONBOX_EDGE
6728 <item> GTK_BUTTONBOX_START
6729 <item> GTK_BUTTONBOX_END
6730 </itemize>
6731
6732 The current layout setting can be retrieved using:
6733
6734 <tscreen><verb>
6735 GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
6736
6737 GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
6738 </verb></tscreen>
6739
6740 Buttons are added to a Button Box using the usual function:
6741
6742 <tscreen><verb>
6743     gtk_container_add( GTK_CONTAINER(button_box), child_widget );
6744 </verb></tscreen>
6745
6746 Here's an example that illustrates all the different layout settings
6747 for Button Boxes.
6748
6749 <tscreen><verb>
6750 /* example-start buttonbox buttonbox.c */
6751
6752 #include <gtk/gtk.h>
6753
6754 /* Create a Button Box with the specified parameters */
6755 GtkWidget *create_bbox (gint  horizontal,
6756                         char* title,
6757                         gint  spacing,
6758                         gint  child_w,
6759                         gint  child_h,
6760                         gint  layout)
6761 {
6762   GtkWidget *frame;
6763   GtkWidget *bbox;
6764   GtkWidget *button;
6765
6766   frame = gtk_frame_new (title);
6767
6768   if (horizontal)
6769     bbox = gtk_hbutton_box_new ();
6770   else
6771     bbox = gtk_vbutton_box_new ();
6772
6773   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
6774   gtk_container_add (GTK_CONTAINER (frame), bbox);
6775
6776   /* Set the appearance of the Button Box */
6777   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
6778   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
6779   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
6780
6781   button = gtk_button_new_with_label ("OK");
6782   gtk_container_add (GTK_CONTAINER (bbox), button);
6783
6784   button = gtk_button_new_with_label ("Cancel");
6785   gtk_container_add (GTK_CONTAINER (bbox), button);
6786
6787   button = gtk_button_new_with_label ("Help");
6788   gtk_container_add (GTK_CONTAINER (bbox), button);
6789
6790   return(frame);
6791 }
6792
6793 int main( int   argc,
6794           char *argv[] )
6795 {
6796   static GtkWidget* window = NULL;
6797   GtkWidget *main_vbox;
6798   GtkWidget *vbox;
6799   GtkWidget *hbox;
6800   GtkWidget *frame_horz;
6801   GtkWidget *frame_vert;
6802
6803   /* Initialize GTK */
6804   gtk_init( &amp;argc, &amp;argv );
6805
6806   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6807   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
6808
6809   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6810                       GTK_SIGNAL_FUNC(gtk_main_quit),
6811                       NULL);
6812
6813   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6814
6815   main_vbox = gtk_vbox_new (FALSE, 0);
6816   gtk_container_add (GTK_CONTAINER (window), main_vbox);
6817
6818   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
6819   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
6820
6821   vbox = gtk_vbox_new (FALSE, 0);
6822   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6823   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
6824
6825   gtk_box_pack_start (GTK_BOX (vbox),
6826            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
6827                       TRUE, TRUE, 0);
6828
6829   gtk_box_pack_start (GTK_BOX (vbox),
6830            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6831                       TRUE, TRUE, 5);
6832
6833   gtk_box_pack_start (GTK_BOX (vbox),
6834            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6835                       TRUE, TRUE, 5);
6836
6837   gtk_box_pack_start (GTK_BOX (vbox),
6838            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
6839                       TRUE, TRUE, 5);
6840
6841   frame_vert = gtk_frame_new ("Vertical Button Boxes");
6842   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
6843
6844   hbox = gtk_hbox_new (FALSE, 0);
6845   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6846   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
6847
6848   gtk_box_pack_start (GTK_BOX (hbox),
6849            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
6850                       TRUE, TRUE, 0);
6851
6852   gtk_box_pack_start (GTK_BOX (hbox),
6853            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6854                       TRUE, TRUE, 5);
6855
6856   gtk_box_pack_start (GTK_BOX (hbox),
6857            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6858                       TRUE, TRUE, 5);
6859
6860   gtk_box_pack_start (GTK_BOX (hbox),
6861            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
6862                       TRUE, TRUE, 5);
6863
6864   gtk_widget_show_all (window);
6865
6866   /* Enter the event loop */
6867   gtk_main ();
6868     
6869   return(0);
6870 }
6871 /* example-end */
6872 </verb></tscreen>
6873
6874 <!-- ----------------------------------------------------------------- -->   
6875 <sect1>Toolbar
6876 <p>
6877 Toolbars are usually used to group some number of widgets in order to
6878 simplify customization of their look and layout. Typically a toolbar
6879 consists of buttons with icons, labels and tooltips, but any other
6880 widget can also be put inside a toolbar. Finally, items can be
6881 arranged horizontally or vertically and buttons can be displayed with
6882 icons, labels or both.
6883
6884 Creating a toolbar is (as one may already suspect) done with the
6885 following function:
6886
6887 <tscreen><verb>
6888 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
6889                             GtkToolbarStyle  style );
6890 </verb></tscreen>
6891
6892 where orientation may be one of:
6893
6894 <tscreen><verb>
6895   GTK_ORIENTATION_HORIZONTAL    
6896   GTK_ORIENTATION_VERTICAL
6897 </verb></tscreen>
6898
6899 and style one of:
6900
6901 <tscreen><verb>
6902   GTK_TOOLBAR_TEXT
6903   GTK_TOOLBAR_ICONS
6904   GTK_TOOLBAR_BOTH
6905 </verb></tscreen>
6906
6907 The style applies to all the buttons created with the `item' functions
6908 (not to buttons inserted into toolbar as separate widgets).
6909
6910 After creating a toolbar one can append, prepend and insert items
6911 (that means simple buttons) into the toolbar. To describe an item we
6912 need a label text, a tooltip text, a private tooltip text, an icon for
6913 the button and a callback function for it. For example, to append or
6914 prepend an item you may use the following functions:
6915
6916 <tscreen><verb>
6917 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
6918                                     const char    *text,
6919                                     const char    *tooltip_text,
6920                                     const char    *tooltip_private_text,
6921                                     GtkWidget     *icon,
6922                                     GtkSignalFunc  callback,
6923                                     gpointer       user_data );
6924
6925 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
6926                                      const char    *text,
6927                                      const char    *tooltip_text,
6928                                      const char    *tooltip_private_text,
6929                                      GtkWidget     *icon,
6930                                      GtkSignalFunc  callback,
6931                                      gpointer       user_data );
6932 </verb></tscreen>
6933
6934 If you want to use gtk_toolbar_insert_item, the only additional
6935 parameter which must be specified is the position in which the item
6936 should be inserted, thus:
6937
6938 <tscreen><verb>
6939 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
6940                                     const char    *text,
6941                                     const char    *tooltip_text,
6942                                     const char    *tooltip_private_text,
6943                                     GtkWidget     *icon,
6944                                     GtkSignalFunc  callback,
6945                                     gpointer       user_data,
6946                                     gint           position );
6947 </verb></tscreen>
6948
6949 To simplify adding spaces between toolbar items, you may use the
6950 following functions:
6951
6952 <tscreen><verb>
6953 void gtk_toolbar_append_space( GtkToolbar *toolbar );
6954
6955 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
6956
6957 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
6958                                gint        position );
6959  
6960 </verb></tscreen>
6961
6962 While the size of the added space can be set globally for a
6963 whole toolbar with the function:
6964
6965 <tscreen><verb>
6966 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
6967                                  gint        space_size) ;
6968 </verb></tscreen>
6969
6970 If it's required, the orientation of a toolbar and its style can be
6971 changed `on the fly' using the following functions:
6972
6973 <tscreen><verb>
6974 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
6975                                   GtkOrientation  orientation );
6976
6977 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
6978                             GtkToolbarStyle  style );
6979
6980 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
6981                                gint        enable );
6982 </verb></tscreen>
6983
6984 Where <tt/orientation/ is one of GTK_ORIENTATION_HORIZONTAL or
6985 GTK_ORIENTATION_VERTICAL. The <tt/style/ is used to set appearance of
6986 the toolbar items by using one of GTK_TOOLBAR_ICONS, GTK_TOOLBAR_TEXT
6987 or GTK_TOOLBAR_BOTH.
6988
6989 To show some other things that can be done with a toolbar, let's take
6990 the following program (we'll interrupt the listing with some
6991 additional explanations):
6992
6993 <tscreen><verb>
6994 #include <gtk/gtk.h>
6995
6996 #include "gtk.xpm"
6997
6998 /* This function is connected to the Close button or
6999  * closing the window from the WM */
7000 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
7001 {
7002   gtk_main_quit ();
7003 }
7004 </verb></tscreen>
7005
7006 The above beginning seems for sure familiar to you if it's not your first
7007 GTK program. There is one additional thing though, we include a nice XPM
7008 picture to serve as an icon for all of the buttons.
7009
7010 <tscreen><verb>
7011 GtkWidget* close_button; /* This button will emit signal to close
7012                           * application */
7013 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7014 GtkWidget* text_button,
7015          * icon_button,
7016          * both_button; /* radio buttons for toolbar style */
7017 GtkWidget* entry; /* a text entry to show packing any widget into
7018                    * toolbar */
7019 </verb></tscreen>
7020
7021 In fact not all of the above widgets are needed here, but to make things
7022 clearer I put them all together.
7023
7024 <tscreen><verb>
7025 /* that's easy... when one of the buttons is toggled, we just
7026  * check which one is active and set the style of the toolbar
7027  * accordingly
7028  * ATTENTION: our toolbar is passed as data to callback ! */
7029 void radio_event (GtkWidget *widget, gpointer data)
7030 {
7031   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7032     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
7033   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7034     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
7035   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7036     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
7037 }
7038
7039 /* even easier, just check given toggle button and enable/disable 
7040  * tooltips */
7041 void toggle_event (GtkWidget *widget, gpointer data)
7042 {
7043   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
7044                             GTK_TOGGLE_BUTTON (widget)->active );
7045 }
7046 </verb></tscreen>
7047
7048 The above are just two callback functions that will be called when
7049 one of the buttons on a toolbar is pressed. You should already be
7050 familiar with things like this if you've already used toggle buttons (and
7051 radio buttons).
7052
7053 <tscreen><verb>
7054 int main (int argc, char *argv[])
7055 {
7056   /* Here is our main window (a dialog) and a handle for the handlebox */
7057   GtkWidget* dialog;
7058   GtkWidget* handlebox;
7059
7060   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7061      the buttons) and an icon widget to put this icon in (but 
7062      we'll create a separate widget for each button) */
7063   GtkWidget * toolbar;
7064   GdkPixmap * icon;
7065   GdkBitmap * mask;
7066   GtkWidget * iconw;
7067
7068   /* this is called in all GTK application. */
7069   gtk_init (&amp;argc, &amp;argv);
7070   
7071   /* create a new window with a given title, and nice size */
7072   dialog = gtk_dialog_new ();
7073   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
7074   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
7075   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
7076
7077   /* typically we quit if someone tries to close us */
7078   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
7079                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
7080
7081   /* we need to realize the window because we use pixmaps for 
7082    * items on the toolbar in the context of it */
7083   gtk_widget_realize ( dialog );
7084
7085   /* to make it nice we'll put the toolbar into the handle box, 
7086    * so that it can be detached from the main window */
7087   handlebox = gtk_handle_box_new ();
7088   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
7089                        handlebox, FALSE, FALSE, 5 );
7090 </verb></tscreen>
7091
7092 The above should be similar to any other GTK application. Just
7093 initialization of GTK, creating the window etc.. There is only one
7094 thing that probably needs some explanation: a handle box. A handle box
7095 is just another box that can be used to pack widgets in to. The
7096 difference between it and typical boxes is that it can be detached
7097 from a parent window (or, in fact, the handle box remains in the
7098 parent, but it is reduced to a very small rectangle, while all of its
7099 contents are reparented to a new freely floating window). It is
7100 usually nice to have a detachable toolbar, so these two widgets occur
7101 together quite often.
7102
7103 <tscreen><verb>
7104   /* toolbar will be horizontal, with both icons and text, and
7105    * with 5pxl spaces between items and finally, 
7106    * we'll also put it into our handlebox */
7107   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
7108                               GTK_TOOLBAR_BOTH );
7109   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
7110   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
7111   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
7112
7113   /* now we create icon with mask: we'll reuse it to create
7114    * icon widgets for toolbar items */
7115   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
7116       &amp;dialog->style->white, gtk_xpm );
7117 </verb></tscreen>
7118
7119 Well, what we do above is just a straight-forward initialization of
7120 the toolbar widget and creation of a GDK pixmap with its mask. If you
7121 want to know something more about using pixmaps, refer to GDK
7122 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
7123 earlier in this tutorial.
7124
7125 <tscreen><verb>
7126   /* our first item is <close> button */
7127   iconw = gtk_pixmap_new ( icon, mask ); /* icon widget */
7128   close_button = 
7129     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), /* our toolbar */
7130                               "Close",               /* button label */
7131                               "Closes this app",     /* this button's tooltip */
7132                               "Private",             /* tooltip private info */
7133                               iconw,                 /* icon widget */
7134                               GTK_SIGNAL_FUNC (delete_event), /* a signal */
7135                                NULL );
7136   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); /* space after item */
7137 </verb></tscreen>
7138
7139 In the above code you see the simplest case: adding a button to
7140 toolbar.  Just before appending a new item, we have to construct a
7141 pixmap widget to serve as an icon for this item; this step will have
7142 to be repeated for each new item. Just after the item we also add a
7143 space, so the following items will not touch each other. As you see
7144 gtk_toolbar_append_item returns a pointer to our newly created button
7145 widget, so that we can work with it in the normal way.
7146
7147 <tscreen><verb>
7148   /* now, let's make our radio buttons group... */
7149   iconw = gtk_pixmap_new ( icon, mask );
7150   icon_button = gtk_toolbar_append_element(
7151                     GTK_TOOLBAR(toolbar),
7152                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7153                     NULL,                          /* pointer to widget */
7154                     "Icon",                        /* label */
7155                     "Only icons in toolbar",       /* tooltip */
7156                     "Private",                     /* tooltip private string */
7157                     iconw,                         /* icon */
7158                     GTK_SIGNAL_FUNC (radio_event), /* signal */
7159                     toolbar);                      /* data for signal */
7160   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7161 </verb></tscreen>
7162
7163 Here we begin creating a radio buttons group. To do this we use
7164 gtk_toolbar_append_element.  In fact, using this function one can also
7165 add simple items or even spaces (type = GTK_TOOLBAR_CHILD_SPACE or
7166 GTK_TOOLBAR_CHILD_BUTTON). In the above case we start creating a radio
7167 group. In creating other radio buttons for this group a pointer to the
7168 previous button in the group is required, so that a list of buttons
7169 can be easily constructed (see the section on <ref
7170 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
7171 tutorial).
7172
7173 <tscreen><verb>
7174   /* following radio buttons refer to previous ones */
7175   iconw = gtk_pixmap_new ( icon, mask );
7176   text_button = 
7177     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7178                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7179                                icon_button,
7180                                "Text",
7181                                "Only texts in toolbar",
7182                                "Private",
7183                                iconw,
7184                                GTK_SIGNAL_FUNC (radio_event),
7185                                toolbar);
7186   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7187                                           
7188   iconw = gtk_pixmap_new ( icon, mask );
7189   both_button = 
7190     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7191                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7192                                text_button,
7193                                "Both",
7194                                "Icons and text in toolbar",
7195                                "Private",
7196                                iconw,
7197                                GTK_SIGNAL_FUNC (radio_event),
7198                                toolbar);
7199   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7200   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
7201 </verb></tscreen>
7202
7203 In the end we have set the state of one of the buttons manually (otherwise
7204 they all stay in active state, preventing us from switching between them).
7205
7206 <tscreen><verb>
7207   /* here we have just a simple toggle button */
7208   iconw = gtk_pixmap_new ( icon, mask );
7209   tooltips_button = 
7210     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7211                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7212                                NULL,
7213                                "Tooltips",
7214                                "Toolbar with or without tips",
7215                                "Private",
7216                                iconw,
7217                                GTK_SIGNAL_FUNC (toggle_event),
7218                                toolbar);
7219   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7220   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
7221 </verb></tscreen>
7222
7223 A toggle button can be created in the obvious way (if one knows how to create
7224 radio buttons already).
7225
7226 <tscreen><verb>
7227   /* to pack a widget into toolbar, we only have to 
7228    * create it and append it with an appropriate tooltip */
7229   entry = gtk_entry_new ();
7230   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
7231                              entry, 
7232                              "This is just an entry", 
7233                              "Private" );
7234
7235   /* well, it isn't created within thetoolbar, so we must still show it */
7236   gtk_widget_show ( entry );
7237 </verb></tscreen>
7238
7239 As you see, adding any kind of widget to a toolbar is simple. The
7240 one thing you have to remember is that this widget must be shown manually
7241 (contrary to other items which will be shown together with the toolbar).
7242
7243 <tscreen><verb>
7244   /* that's it ! let's show everything. */
7245   gtk_widget_show ( toolbar );
7246   gtk_widget_show (handlebox);
7247   gtk_widget_show ( dialog );
7248
7249   /* rest in gtk_main and wait for the fun to begin! */
7250   gtk_main ();
7251   
7252   return 0;
7253 }
7254 </verb></tscreen>
7255
7256 So, here we are at the end of toolbar tutorial. Of course, to appreciate
7257 it in full you need also this nice XPM icon, so here it is:
7258
7259 <tscreen><verb>
7260 /* XPM */
7261 static char * gtk_xpm[] = {
7262 "32 39 5 1",
7263 ".      c none",
7264 "+      c black",
7265 "@      c #3070E0",
7266 "#      c #F05050",
7267 "$      c #35E035",
7268 "................+...............",
7269 "..............+++++.............",
7270 "............+++++@@++...........",
7271 "..........+++++@@@@@@++.........",
7272 "........++++@@@@@@@@@@++........",
7273 "......++++@@++++++++@@@++.......",
7274 ".....+++@@@+++++++++++@@@++.....",
7275 "...+++@@@@+++@@@@@@++++@@@@+....",
7276 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7277 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7278 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7279 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7280 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7281 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7282 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7283 ".+######++++@@@@@@@++@$$$$$$$$+.",
7284 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7285 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7286 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7287 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7288 ".+####+++++++#++$$@+@$$++$$$$+..",
7289 ".++####++++++#++$$@+@$++@$$$$+..",
7290 ".+#####+++++##++$$++@+++$$$$$+..",
7291 ".++####+++##+#++$$+++++@$$$$$+..",
7292 ".++####+++####++$$++++++@$$$@+..",
7293 ".+#####++#####++$$+++@++++@$@+..",
7294 ".+#####++#####++$$++@$$@+++$@@..",
7295 ".++####++#####++$$++$$$$$+@$@++.",
7296 ".++####++#####++$$++$$$$$$$$+++.",
7297 ".+++####+#####++$$++$$$$$$$@+++.",
7298 "..+++#########+@$$+@$$$$$$+++...",
7299 "...+++########+@$$$$$$$$@+++....",
7300 ".....+++######+@$$$$$$$+++......",
7301 "......+++#####+@$$$$$@++........",
7302 ".......+++####+@$$$$+++.........",
7303 ".........++###+$$$@++...........",
7304 "..........++##+$@+++............",
7305 "...........+++++++..............",
7306 ".............++++..............."};
7307 </verb></tscreen>
7308
7309 <!-- ----------------------------------------------------------------- -->
7310 <sect1> Notebooks
7311 <p>
7312 The NoteBook Widget is a collection of 'pages' that overlap each
7313 other, each page contains different information. This widget has
7314 become more common lately in GUI programming, and it is a good way to
7315 show blocks of similar information that warrant separation in their
7316 display.
7317
7318 The first function call you will need to know, as you can probably
7319 guess by now, is used to create a new notebook widget.
7320
7321 <tscreen><verb>
7322 GtkWidget *gtk_notebook_new( void );
7323 </verb></tscreen>
7324
7325 Once the notebook has been created, there are a number of functions
7326 that operate on the notebook widget. Let's look at them individually.
7327
7328 The first one we will look at is how to position the page indicators.
7329 These page indicators or 'tabs' as they are referred to, can be
7330 positioned in four ways: top, bottom, left, or right.
7331
7332 <tscreen><verb>
7333 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7334                                GtkPositionType  pos );
7335 </verb></tscreen>
7336
7337 GtkPostionType will be one of the following, which are pretty self
7338 explanatory:
7339 <itemize>
7340 <item> GTK_POS_LEFT
7341 <item> GTK_POS_RIGHT
7342 <item> GTK_POS_TOP
7343 <item> GTK_POS_BOTTOM
7344 </itemize>
7345
7346 GTK_POS_TOP is the default.
7347
7348 Next we will look at how to add pages to the notebook. There are three
7349 ways to add pages to the NoteBook. Let's look at the first two
7350 together as they are quite similar.
7351
7352 <tscreen><verb>
7353 void gtk_notebook_append_page( GtkNotebook *notebook,
7354                                GtkWidget   *child,
7355                                GtkWidget   *tab_label );
7356
7357 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7358                                 GtkWidget   *child,
7359                                 GtkWidget   *tab_label );
7360 </verb></tscreen>
7361
7362 These functions add pages to the notebook by inserting them from the
7363 back of the notebook (append), or the front of the notebook (prepend).
7364 <tt/child/ is the widget that is placed within the notebook page, and
7365 <tt/tab_label/ is the label for the page being added. The <tt/child/
7366 widget must be created separately, and is typically a set of options
7367 setout witin one of the other container widgets, such as a table.
7368
7369 The final function for adding a page to the notebook contains all of
7370 the properties of the previous two, but it allows you to specify what
7371 position you want the page to be in the notebook.
7372
7373 <tscreen><verb>
7374 void gtk_notebook_insert_page( GtkNotebook *notebook,
7375                                GtkWidget   *child,
7376                                GtkWidget   *tab_label,
7377                                gint         position );
7378 </verb></tscreen>
7379
7380 The parameters are the same as _append_ and _prepend_ except it
7381 contains an extra parameter, <tt/position/.  This parameter is used to
7382 specify what place this page will be inserted into.
7383
7384 Now that we know how to add a page, lets see how we can remove a page
7385 from the notebook.
7386
7387 <tscreen><verb>
7388 void gtk_notebook_remove_page( GtkNotebook *notebook,
7389                                gint         page_num );
7390 </verb></tscreen>
7391
7392 This function takes the page specified by <tt/page_num/ and removes it
7393 from the widget pointed to by <tt/notebook/.
7394
7395 To find out what the current page is in a notebook use the function:
7396
7397 <tscreen><verb>
7398 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7399 </verb></tscreen>
7400
7401 These next two functions are simple calls to move the notebook page
7402 forward or backward. Simply provide the respective function call with
7403 the notebook widget you wish to operate on. Note: when the NoteBook is
7404 currently on the last page, and gtk_notebook_next_page is called, the
7405 notebook will wrap back to the first page. Likewise, if the NoteBook
7406 is on the first page, and gtk_notebook_prev_page is called, the
7407 notebook will wrap to the last page.
7408
7409 <tscreen><verb>
7410 void gtk_notebook_next_page( GtkNoteBook *notebook );
7411
7412 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7413 </verb></tscreen>
7414
7415 This next function sets the 'active' page. If you wish the notebook to
7416 be opened to page 5 for example, you would use this function.  Without
7417 using this function, the notebook defaults to the first page.
7418
7419 <tscreen><verb>
7420 void gtk_notebook_set_page( GtkNotebook *notebook,
7421                             gint         page_num );
7422 </verb></tscreen>
7423
7424 The next two functions add or remove the notebook page tabs and the
7425 notebook border respectively.
7426
7427 <tscreen><verb>
7428 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7429                                  gboolean     show_tabs);
7430
7431 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7432                                    gboolean     show_border );
7433 </verb></tscreen>
7434
7435 The next function is useful when the you have a large number of pages,
7436 and the tabs don't fit on the page. It allows the tabs to be scrolled
7437 through using two arrow buttons.
7438
7439 <tscreen><verb>
7440 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7441                                   gboolean     scrollable );
7442 </verb></tscreen>
7443
7444 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
7445 TRUE or FALSE.
7446
7447 Now lets look at an example, it is expanded from the testgtk.c code
7448 that comes with the GTK distribution. This small program creates a
7449 window with a notebook and six buttons. The notebook contains 11
7450 pages, added in three different ways, appended, inserted, and
7451 prepended. The buttons allow you rotate the tab positions, add/remove
7452 the tabs and border, remove a page, change pages in both a forward and
7453 backward manner, and exit the program.
7454
7455 <tscreen><verb>
7456 /* example-start notebook notebook.c */
7457
7458 #include <gtk/gtk.h>
7459
7460 /* This function rotates the position of the tabs */
7461 void rotate_book (GtkButton *button, GtkNotebook *notebook)
7462 {
7463     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
7464 }
7465
7466 /* Add/Remove the page tabs and the borders */
7467 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
7468 {
7469     gint tval = FALSE;
7470     gint bval = FALSE;
7471     if (notebook->show_tabs == 0)
7472             tval = TRUE; 
7473     if (notebook->show_border == 0)
7474             bval = TRUE;
7475     
7476     gtk_notebook_set_show_tabs (notebook, tval);
7477     gtk_notebook_set_show_border (notebook, bval);
7478 }
7479
7480 /* Remove a page from the notebook */
7481 void remove_book (GtkButton *button, GtkNotebook *notebook)
7482 {
7483     gint page;
7484     
7485     page = gtk_notebook_get_current_page(notebook);
7486     gtk_notebook_remove_page (notebook, page);
7487     /* Need to refresh the widget -- 
7488      This forces the widget to redraw itself. */
7489     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
7490 }
7491
7492 void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
7493 {
7494     gtk_main_quit ();
7495 }
7496
7497 int main (int argc, char *argv[])
7498 {
7499     GtkWidget *window;
7500     GtkWidget *button;
7501     GtkWidget *table;
7502     GtkWidget *notebook;
7503     GtkWidget *frame;
7504     GtkWidget *label;
7505     GtkWidget *checkbutton;
7506     int i;
7507     char bufferf[32];
7508     char bufferl[32];
7509     
7510     gtk_init (&amp;argc, &amp;argv);
7511     
7512     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7513     
7514     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
7515                         GTK_SIGNAL_FUNC (delete), NULL);
7516     
7517     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7518
7519     table = gtk_table_new(3,6,FALSE);
7520     gtk_container_add (GTK_CONTAINER (window), table);
7521     
7522     /* Create a new notebook, place the position of the tabs */
7523     notebook = gtk_notebook_new ();
7524     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
7525     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
7526     gtk_widget_show(notebook);
7527     
7528     /* Lets append a bunch of pages to the notebook */
7529     for (i=0; i < 5; i++) {
7530         sprintf(bufferf, "Append Frame %d", i+1);
7531         sprintf(bufferl, "Page %d", i+1);
7532         
7533         frame = gtk_frame_new (bufferf);
7534         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7535         gtk_widget_set_usize (frame, 100, 75);
7536         gtk_widget_show (frame);
7537         
7538         label = gtk_label_new (bufferf);
7539         gtk_container_add (GTK_CONTAINER (frame), label);
7540         gtk_widget_show (label);
7541         
7542         label = gtk_label_new (bufferl);
7543         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
7544     }
7545       
7546     /* Now lets add a page to a specific spot */
7547     checkbutton = gtk_check_button_new_with_label ("Check me please!");
7548     gtk_widget_set_usize(checkbutton, 100, 75);
7549     gtk_widget_show (checkbutton);
7550    
7551     label = gtk_label_new ("Add page");
7552     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
7553     
7554     /* Now finally lets prepend pages to the notebook */
7555     for (i=0; i < 5; i++) {
7556         sprintf(bufferf, "Prepend Frame %d", i+1);
7557         sprintf(bufferl, "PPage %d", i+1);
7558         
7559         frame = gtk_frame_new (bufferf);
7560         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7561         gtk_widget_set_usize (frame, 100, 75);
7562         gtk_widget_show (frame);
7563         
7564         label = gtk_label_new (bufferf);
7565         gtk_container_add (GTK_CONTAINER (frame), label);
7566         gtk_widget_show (label);
7567         
7568         label = gtk_label_new (bufferl);
7569         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
7570     }
7571     
7572     /* Set what page to start at (page 4) */
7573     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
7574
7575     /* Create a bunch of buttons */
7576     button = gtk_button_new_with_label ("close");
7577     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7578                                GTK_SIGNAL_FUNC (delete), NULL);
7579     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
7580     gtk_widget_show(button);
7581     
7582     button = gtk_button_new_with_label ("next page");
7583     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7584                                (GtkSignalFunc) gtk_notebook_next_page,
7585                                GTK_OBJECT (notebook));
7586     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
7587     gtk_widget_show(button);
7588     
7589     button = gtk_button_new_with_label ("prev page");
7590     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7591                                (GtkSignalFunc) gtk_notebook_prev_page,
7592                                GTK_OBJECT (notebook));
7593     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
7594     gtk_widget_show(button);
7595     
7596     button = gtk_button_new_with_label ("tab position");
7597     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7598                         (GtkSignalFunc) rotate_book,
7599                         GTK_OBJECT(notebook));
7600     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
7601     gtk_widget_show(button);
7602     
7603     button = gtk_button_new_with_label ("tabs/border on/off");
7604     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7605                         (GtkSignalFunc) tabsborder_book,
7606                         GTK_OBJECT (notebook));
7607     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
7608     gtk_widget_show(button);
7609     
7610     button = gtk_button_new_with_label ("remove page");
7611     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7612                         (GtkSignalFunc) remove_book,
7613                         GTK_OBJECT(notebook));
7614     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
7615     gtk_widget_show(button);
7616     
7617     gtk_widget_show(table);
7618     gtk_widget_show(window);
7619     
7620     gtk_main ();
7621     
7622     return(0);
7623 }
7624 /* example-end */
7625 </verb></tscreen>
7626
7627 Hopefully this helps you on your way with creating notebooks for your
7628 GTK applications.
7629
7630 <!-- ***************************************************************** -->
7631 <sect>CList Widget
7632 <!-- ***************************************************************** -->
7633
7634 <!-- ----------------------------------------------------------------- -->
7635 <p>
7636 The GtkCList widget has replaced the GtkList widget (which is still
7637 available).
7638
7639 The GtkCList widget is a multi-column list widget that is capable of
7640 handling literally thousands of rows of information. Each column can
7641 optionally have a title, which itself is optionally active, allowing
7642 us to bind a function to its selection.
7643
7644 <!-- ----------------------------------------------------------------- -->
7645 <sect1>Creating a GtkCList widget
7646 <p>
7647 Creating a GtkCList is quite straightforward, once you have learned
7648 about widgets in general. It provides the almost standard two ways,
7649 that is the hard way, and the easy way. But before we create it, there
7650 is one thing we should figure out beforehand: how many columns should
7651 it have?
7652
7653 Not all columns have to be visible and can be used to store data that
7654 is related to a certain cell in the list.
7655
7656 <tscreen><verb>
7657 GtkWidget *gtk_clist_new ( gint columns );
7658
7659 GtkWidget *gtk_clist_new_with_titles( gint   columns,
7660                                       gchar *titles[] );
7661 </verb></tscreen>
7662
7663 The first form is very straight forward, the second might require some
7664 explanation. Each column can have a title associated with it, and this
7665 title can be a label or a button that reacts when we click on it. If
7666 we use the second form, we must provide pointers to the title texts,
7667 and the number of pointers should equal the number of columns
7668 specified. Of course we can always use the first form, and manually
7669 add titles later.
7670
7671 Note: the GtkCList widget does not have its own scrollbars and should
7672 be placed within a GtkScrolledWindow widget if your require this
7673 functionality. This is a change from the GTK 1.0 implementation.
7674
7675 <!-- ----------------------------------------------------------------- -->
7676 <sect1>Modes of operation
7677 <p>
7678 There are several attributes that can be used to alter the behaviour of
7679 a GtkCList. First there is
7680
7681 <tscreen><verb>
7682 void gtk_clist_set_selection_mode( GtkCList         *clist,
7683                                    GtkSelectionMode  mode );
7684 </verb></tscreen>
7685
7686 which, as the name implies, sets the selection mode of the
7687 GtkCList. The first argument is the GtkCList widget, and the second
7688 specifies the cell selection mode (they are defined in gtkenums.h). At
7689 the time of this writing, the following modes are available to us:
7690
7691 <itemize>
7692 <item> GTK_SELECTION_SINGLE - The selection is either NULL or contains
7693 a GList pointer for a single selected item.
7694
7695 <item> GTK_SELECTION_BROWSE - The selection is NULL if the list
7696 contains no widgets or insensitive ones only, otherwise it contains a
7697 GList pointer for one GList structure, and therefore exactly one list
7698 item.
7699
7700 <item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list items
7701 are selected or a GList pointer for the first selected item. That in
7702 turn points to a GList structure for the second selected item and so
7703 on. This is currently the <bf>default</bf> for the GtkCList widget.
7704
7705 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
7706 </itemize>
7707
7708 Others might be added in later revisions of GTK.
7709
7710 We can also define what the border of the GtkCList widget should look
7711 like. It is done through
7712
7713 <tscreen><verb>
7714 void gtk_clist_set_shadow_type( GtkCList      *clist,
7715                                 GtkShadowType  border );
7716 </verb></tscreen>
7717
7718 And the possible values for the second argument are
7719
7720 <itemize>
7721 <item> GTK_SHADOW_NONE
7722
7723 <item> GTK_SHADOW_IN
7724
7725 <item> GTK_SHADOW_OUT
7726
7727 <item> GTK_SHADOW_ETCHED_IN
7728
7729 <item> GTK_SHADOW_ETCHED_OUT
7730 </itemize>
7731
7732 <!-- ----------------------------------------------------------------- -->
7733 <sect1>Working with titles
7734 <p>
7735 When you create a GtkCList widget, you will also get a set of title
7736 buttons automatically. They live in the top of the CList window, and
7737 can act either as normal buttons that respond to being pressed, or
7738 they can be passive, in which case they are nothing more than a
7739 title. There are four different calls that aid us in setting the
7740 status of the title buttons.
7741
7742 <tscreen><verb>
7743 void gtk_clist_column_title_active( GtkCList *clist,
7744                                      gint     column );
7745
7746 void gtk_clist_column_title_passive( GtkCList *clist,
7747                                      gint      column );
7748
7749 void gtk_clist_column_titles_active( GtkCList *clist );
7750
7751 void gtk_clist_column_titles_passive( GtkCList *clist );
7752 </verb></tscreen>
7753
7754 An active title is one which acts as a normal button, a passive one is
7755 just a label. The first two calls above will activate/deactivate the
7756 title button above the specific column, while the last two calls
7757 activate/deactivate all title buttons in the supplied clist widget.
7758
7759 But of course there are those cases when we don't want them at all,
7760 and so they can be hidden and shown at will using the following two
7761 calls.
7762
7763 <tscreen><verb>
7764 void gtk_clist_column_titles_show( GtkCList *clist );
7765
7766 void gtk_clist_column_titles_hide( GtkCList *clist );
7767 </verb></tscreen>
7768
7769 For titles to be really useful we need a mechanism to set and change
7770 them, and this is done using
7771
7772 <tscreen><verb>
7773 void gtk_clist_set_column_title( GtkCList *clist,
7774                                  gint      column,
7775                                  gchar    *title );
7776 </verb></tscreen>
7777
7778 Note that only the title of one column can be set at a time, so if all
7779 the titles are known from the beginning, then I really suggest using
7780 gtk_clist_new_with_titles (as described above) to set them. Saves you
7781 coding time, and makes your program smaller. There are some cases
7782 where getting the job done the manual way is better, and that's when
7783 not all titles will be text. GtkCList provides us with title buttons
7784 that can in fact incorporate whole widgets, for example a pixmap. It's
7785 all done through
7786
7787 <tscreen><verb>
7788 void gtk_clist_set_column_widget( GtkCList  *clist,
7789                                   gint       column,
7790                                   GtkWidget *widget );
7791 </verb></tscreen>
7792
7793 which should require no special explanation.
7794
7795 <!-- ----------------------------------------------------------------- -->
7796 <sect1>Manipulating the list itself
7797 <p>
7798 It is possible to change the justification for a column, and it is
7799 done through
7800
7801 <tscreen><verb>
7802 void gtk_clist_set_column_justification( GtkCList         *clist,
7803                                          gint              column,
7804                                          GtkJustification  justification );
7805 </verb></tscreen>
7806
7807 The GtkJustification type can take the following values:
7808
7809 <itemize>
7810 <item>GTK_JUSTIFY_LEFT - The text in the column will begin from the
7811 left edge.
7812
7813 <item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the
7814 right edge.
7815
7816 <item>GTK_JUSTIFY_CENTER - The text is placed in the center of the
7817 column.
7818
7819 <item>GTK_JUSTIFY_FILL - The text will use up all available space in
7820 the column. It is normally done by inserting extra blank spaces
7821 between words (or between individual letters if it's a single
7822 word). Much in the same way as any ordinary WYSIWYG text editor.
7823 </itemize>
7824
7825 The next function is a very important one, and should be standard in
7826 the setup of all GtkCList widgets. When the list is created, the width
7827 of the various columns are chosen to match their titles, and since
7828 this is seldom the right width we have to set it using
7829
7830 <tscreen><verb>
7831 void gtk_clist_set_column_width( GtkCList *clist,
7832                                  gint      column,
7833                                  gint      width );
7834 </verb></tscreen>
7835
7836 Note that the width is given in pixels and not letters. The same goes
7837 for the height of the cells in the columns, but as the default value
7838 is the height of the current font this isn't as critical to the
7839 application. Still, it is done through
7840
7841 <tscreen><verb>
7842 void gtk_clist_set_row_height( GtkCList *clist,
7843                                gint      height );
7844 </verb></tscreen>
7845
7846 Again, note that the height is given in pixels.
7847
7848 We can also move the list around without user interaction, however, it
7849 does require that we know what we are looking for. Or in other words,
7850 we need the row and column of the item we want to scroll to.
7851
7852 <tscreen><verb>
7853 void gtk_clist_moveto( GtkCList *clist,
7854                        gint      row,
7855                        gint      column,
7856                        gfloat    row_align,
7857                        gfloat    col_align );
7858 </verb></tscreen>
7859
7860 The gfloat row_align is pretty important to understand. It's a value
7861 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
7862 the row appears at the top, while if the value of row_align is 1.0,
7863 the row will appear at the bottom instead. All other values between
7864 0.0 and 1.0 are also valid and will place the row between the top and
7865 the bottom. The last argument, gfloat col_align works in the same way,
7866 though 0.0 marks left and 1.0 marks right instead.
7867
7868 Depending on the application's needs, we don't have to scroll to an
7869 item that is already visible to us. So how do we know if it is
7870 visible? As usual, there is a function to find that out as well.
7871
7872 <tscreen><verb>
7873 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
7874                                         gint      row );
7875 </verb></tscreen>
7876
7877 The return value is is one of the following:
7878
7879 <itemize>
7880 <item>GTK_VISIBILITY_NONE
7881
7882 <item>GTK_VISIBILITY_PARTIAL
7883
7884 <item>GTK_VISIBILITY_FULL
7885 </itemize>
7886
7887 Note that it will only tell us if a row is visible. Currently there is
7888 no way to determine this for a column. We can get partial information
7889 though, because if the return is GTK_VISIBILITY_PARTIAL, then some of
7890 it is hidden, but we don't know if it is the row that is being cut by
7891 the lower edge of the listbox, or if the row has columns that are
7892 outside.
7893
7894 We can also change both the foreground and background colors of a
7895 particular row. This is useful for marking the row selected by the
7896 user, and the two functions that is used to do it are
7897
7898 <tscreen><verb>
7899 void gtk_clist_set_foreground( GtkCList *clist,
7900                                gint      row,
7901                                GdkColor *color );
7902
7903 void gtk_clist_set_background( GtkCList *clist,
7904                                gint      row,
7905                                GdkColor *color );
7906 </verb></tscreen>
7907
7908 Please note that the colors must have been previously allocated.
7909
7910 <!-- ----------------------------------------------------------------- -->
7911 <sect1>Adding rows to the list
7912 <p>
7913 We can add rows in three ways. They can be prepended or appended to
7914 the list using
7915
7916 <tscreen><verb>
7917 gint gtk_clist_prepend( GtkCList *clist,
7918                         gchar    *text[] );
7919
7920 gint gtk_clist_append( GtkCList *clist,
7921                        gchar    *text[] );
7922 </verb></tscreen>
7923
7924 The return value of these two functions indicate the index of the row
7925 that was just added. We can insert a row at a given place using
7926
7927 <tscreen><verb>
7928 void gtk_clist_insert( GtkCList *clist,
7929                        gint      row,
7930                        gchar    *text[] );
7931 </verb></tscreen>
7932
7933 In these calls we have to provide a collection of pointers that are
7934 the texts we want to put in the columns. The number of pointers should
7935 equal the number of columns in the list. If the text[] argument is
7936 NULL, then there will be no text in the columns of the row. This is
7937 useful, for example, if we want to add pixmaps instead (something that
7938 has to be done manually).
7939
7940 Also, please note that the numbering of both rows and columns start at 0.
7941
7942 To remove an individual row we use
7943
7944 <tscreen><verb>
7945 void gtk_clist_remove( GtkCList *clist,
7946                        gint      row );
7947 </verb></tscreen>
7948
7949 There is also a call that removes all rows in the list. This is a lot
7950 faster than calling gtk_clist_remove once for each row, which is the
7951 only alternative.
7952
7953 <tscreen><verb>
7954 void gtk_clist_clear( GtkCList *clist );
7955 </verb></tscreen>
7956
7957 There are also two convenience functions that should be used when a
7958 lot of changes have to be made to the list. This is to prevent the
7959 list flickering while being repeatedly updated, which may be highly
7960 annoying to the user. So instead it is a good idea to freeze the list,
7961 do the updates to it, and finally thaw it which causes the list to be
7962 updated on the screen.
7963
7964 <tscreen><verb>
7965 void gtk_clist_freeze( GtkCList * clist );
7966
7967 void gtk_clist_thaw( GtkCList * clist );
7968 </verb></tscreen>
7969
7970 <!-- ----------------------------------------------------------------- -->
7971 <sect1>Setting text and pixmaps in the cells
7972 <p>
7973 A cell can contain a pixmap, text or both. To set them the following
7974 functions are used.
7975
7976 <tscreen><verb>
7977 void gtk_clist_set_text( GtkCList *clist,
7978                          gint      row,
7979                          gint      column,
7980                          gchar    *text );
7981
7982 void gtk_clist_set_pixmap( GtkCList  *clist,
7983                            gint       row,
7984                            gint       column,
7985                            GdkPixmap *pixmap,
7986                            GdkBitmap *mask );
7987
7988 void gtk_clist_set_pixtext( GtkCList  *clist,
7989                             gint       row,
7990                             gint       column,
7991                             gchar     *text,
7992                             guint8     spacing,
7993                             GdkPixmap *pixmap,
7994                             GdkBitmap *mask );
7995 </verb></tscreen>
7996
7997 It's quite straightforward. All the calls have the GtkCList as the
7998 first argument, followed by the row and column of the cell, followed
7999 by the data to be set. The <tt/spacing/ argument in
8000 gtk_clist_set_pixtext is the number of pixels between the pixmap and
8001 the beginning of the text.
8002
8003 To read back the data, we instead use
8004
8005 <tscreen><verb>
8006 gint gtk_clist_get_text( GtkCList  *clist,
8007                          gint       row,
8008                          gint       column,
8009                          gchar    **text );
8010
8011 gint gtk_clist_get_pixmap( GtkCList   *clist,
8012                            gint        row,
8013                            gint        column,
8014                            GdkPixmap **pixmap,
8015                            GdkBitmap **mask );
8016
8017 gint gtk_clist_get_pixtext( GtkCList   *clist,
8018                             gint        row,
8019                             gint        column,
8020                             gchar     **text,
8021                             guint8     *spacing,
8022                             GdkPixmap **pixmap,
8023                             GdkBitmap **mask );
8024 </verb></tscreen>
8025
8026 It isn't necessary to read it all back in case you aren't
8027 interested. Any of the pointers that are meant for return values (all
8028 except the clist) can be NULL. So if we want to read back only the
8029 text from a cell that is of type pixtext, then we would do the
8030 following, assuming that clist, row and column already exist:
8031
8032 <tscreen><verb>
8033 gchar *mytext;
8034
8035 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
8036 </verb></tscreen>
8037
8038 There is one more call that is related to what's inside a cell in the
8039 clist, and that's
8040
8041 <tscreen><verb>
8042 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
8043                                      gint      row,
8044                                      gint      column );
8045 </verb></tscreen>
8046
8047 which returns the type of data in a cell. The return value is one of
8048
8049 <itemize>
8050 <item>GTK_CELL_EMPTY
8051
8052 <item>GTK_CELL_TEXT
8053
8054 <item>GTK_CELL_PIXMAP
8055
8056 <item>GTK_CELL_PIXTEXT
8057
8058 <item>GTK_CELL_WIDGET
8059 </itemize>
8060
8061 There is also a function that will let us set the indentation, both
8062 vertical and horizontal, of a cell. The indentation value is of type
8063 gint, given in pixels, and can be both positive and negative.
8064
8065 <tscreen><verb>
8066 void gtk_clist_set_shift( GtkCList *clist,
8067                           gint      row,
8068                           gint      column,
8069                           gint      vertical,
8070                           gint      horizontal );
8071 </verb></tscreen>
8072
8073 <!-- ----------------------------------------------------------------- -->
8074 <sect1>Storing data pointers
8075 <p>
8076 With a GtkCList it is possible to set a data pointer for a row. This
8077 pointer will not be visible for the user, but is merely a convenience
8078 for the programmer to associate a row with a pointer to some
8079 additional data.
8080
8081 The functions should be fairly self-explanatory by now
8082
8083 <tscreen><verb>
8084 void gtk_clist_set_row_data( GtkCList *clist,
8085                              gint      row,
8086                              gpointer  data );
8087
8088 void gtk_clist_set_row_data_full( GtkCList         *clist,
8089                                   gint              row,
8090                                   gpointer          data,
8091                                   GtkDestroyNotify  destroy );
8092
8093 gpointer gtk_clist_get_row_data( GtkCList *clist,
8094                                  gint      row );
8095
8096 gint gtk_clist_find_row_from_data( GtkCList *clist,
8097                                    gpointer  data );
8098 </verb></tscreen>
8099
8100 <!-- ----------------------------------------------------------------- -->
8101 <sect1>Working with selections
8102 <p>
8103 There are also functions available that let us force the (un)selection
8104 of a row. These are
8105
8106 <tscreen><verb>
8107 void gtk_clist_select_row( GtkCList *clist,
8108                            gint      row,
8109                            gint      column );
8110
8111 void gtk_clist_unselect_row( GtkCList *clist,
8112                              gint      row,
8113                              gint      column );
8114 </verb></tscreen>
8115
8116 And also a function that will take x and y coordinates (for example,
8117 read from the mousepointer), and map that onto the list, returning the
8118 corresponding row and column.
8119
8120 <tscreen><verb>
8121 gint gtk_clist_get_selection_info( GtkCList *clist,
8122                                    gint      x,
8123                                    gint      y,
8124                                    gint     *row,
8125                                    gint     *column );
8126 </verb></tscreen>
8127
8128 When we detect something of interest, it might be movement of the
8129 pointer, a click somewhere in the list, we can read the pointer
8130 coordinates and find out where in the list the pointer is. Cumbersome?
8131 Luckily, there is a simpler way...
8132
8133 <!-- ----------------------------------------------------------------- -->
8134 <sect1>The signals that bring it together
8135 <p>
8136 As with all other widgets, there are a few signals that can be used. The
8137 GtkCList widget is derived from the GtkContainer widget, and so has all the
8138 same signals, but also the adds following:
8139
8140 <itemize>
8141 <item>select_row - This signal will send the following information, in
8142 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
8143
8144 <item>unselect_row - When the user unselects a row, this signal is
8145 activated. It sends the same information as select_row
8146
8147 <item>click_column - Send GtkCList *clist, gint column
8148 </itemize>
8149
8150 So if we want to connect a callback to select_row, the callback
8151 function would be declared like this
8152
8153 <tscreen><verb>
8154 void select_row_callback(GtkWidget *widget,
8155                          gint row,
8156                          gint column,
8157                          GdkEventButton *event,
8158                          gpointer data);
8159 </verb></tscreen>
8160
8161 The callback is connected as usual with
8162
8163 <tscreen><verb>
8164 gtk_signal_connect(GTK_OBJECT( clist),
8165                    "select_row"
8166                    GTK_SIGNAL_FUNC(select_row_callback),
8167                    NULL);
8168 </verb></tscreen>
8169
8170 <!-- ----------------------------------------------------------------- -->
8171 <sect1>A GtkCList example
8172 <p>
8173
8174 <tscreen><verb>
8175 /* example-start clist clist.c */
8176
8177 #include        <gtk/gtk.h>
8178 #include        <glib.h>
8179
8180 /* These are just the prototypes of the various callbacks */
8181 void button_add_clicked( GtkWidget *button, gpointer data);
8182 void button_clear_clicked( GtkWidget *button, gpointer data);
8183 void button_hide_show_clicked( GtkWidget *button, gpointer data);
8184 void selection_made( GtkWidget *clist, gint row, gint column,
8185                      GdkEventButton *event, gpointer data);
8186
8187 gint main (int argc, gchar *argv[])
8188 {                                  
8189     GtkWidget       *window;
8190     GtkWidget       *vbox, *hbox;
8191     GtkWidget       *clist;
8192     GtkWidget       *button_add, *button_clear, *button_hide_show;    
8193     gchar           *titles[2] = {"Ingredients","Amount"};
8194
8195     gtk_init(&amp;argc, &amp;argv);
8196     
8197     
8198     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
8199     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
8200
8201     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
8202     gtk_signal_connect(GTK_OBJECT(window),
8203                        "destroy",
8204                        GTK_SIGNAL_FUNC(gtk_main_quit),
8205                        NULL);
8206     
8207     vbox=gtk_vbox_new(FALSE, 5);
8208     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
8209     gtk_container_add(GTK_CONTAINER(window), vbox);
8210     gtk_widget_show(vbox);
8211     
8212     /* Create the GtkCList. For this example we use 2 columns */
8213     clist = gtk_clist_new_with_titles( 2, titles);
8214
8215     /* When a selection is made, we want to know about it. The callback
8216      * used is selection_made, and its code can be found further down */
8217     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
8218                        GTK_SIGNAL_FUNC(selection_made),
8219                        NULL);
8220
8221     /* It isn't necessary to shadow the border, but it looks nice :) */
8222     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
8223
8224     /* What however is important, is that we set the column widths as
8225      * they will never be right otherwise. Note that the columns are
8226      * numbered from 0 and up (to 1 in this case).
8227      */
8228     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
8229
8230     /* Add the GtkCList widget to the vertical box and show it. */
8231     gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
8232     gtk_widget_show(clist);
8233
8234     /* Create the buttons and add them to the window. See the button
8235      * tutorial for more examples and comments on this.
8236      */
8237     hbox = gtk_hbox_new(FALSE, 0);
8238     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
8239     gtk_widget_show(hbox);
8240
8241     button_add = gtk_button_new_with_label("Add List");
8242     button_clear = gtk_button_new_with_label("Clear List");
8243     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
8244
8245     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
8246     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
8247     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
8248
8249     /* Connect our callbacks to the three buttons */
8250     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
8251                               GTK_SIGNAL_FUNC(button_add_clicked),
8252                               (gpointer) clist);
8253     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
8254                               GTK_SIGNAL_FUNC(button_clear_clicked),
8255                               (gpointer) clist);
8256     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
8257                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
8258                               (gpointer) clist);
8259
8260     gtk_widget_show(button_add);
8261     gtk_widget_show(button_clear);
8262     gtk_widget_show(button_hide_show);
8263
8264     /* The interface is completely set up so we show the window and
8265      * enter the gtk_main loop.
8266      */
8267     gtk_widget_show(window);
8268     gtk_main();
8269     
8270     return(0);
8271 }
8272
8273 /* User clicked the "Add List" button. */
8274 void button_add_clicked( GtkWidget *button, gpointer data)
8275 {
8276     int         indx;
8277
8278     /* Something silly to add to the list. 4 rows of 2 columns each */
8279     gchar      *drink[4][2] = {{"Milk", "3 Oz"},
8280                                {"Water", "6 l"},
8281                                {"Carrots", "2"},
8282                                {"Snakes", "55"}};
8283
8284     /* Here we do the actual adding of the text. It's done once for
8285      * each row.
8286      */
8287     for( indx=0; indx < 4; indx++)
8288         gtk_clist_append( (GtkCList*) data, drink[indx]);
8289
8290     return;
8291 }
8292
8293 /* User clicked the "Clear List" button. */
8294 void button_clear_clicked( GtkWidget *button, gpointer data)
8295 {
8296     /* Clear the list using gtk_clist_clear. This is much faster than
8297      * calling gtk_clist_remove once for each row.
8298      */
8299     gtk_clist_clear((GtkCList*) data);
8300
8301     return;
8302 }
8303
8304 /* The user clicked the "Hide/Show titles" button. */
8305 void button_hide_show_clicked( GtkWidget *button, gpointer data)
8306 {
8307     /* Just a flag to remember the status. 0 = currently visible */
8308     static short int flag = 0;
8309
8310     if (flag == 0)
8311     {
8312         /* Hide the titles and set the flag to 1 */
8313         gtk_clist_column_titles_hide((GtkCList*) data);
8314         flag++;
8315     }
8316     else
8317     {
8318         /* Show the titles and reset flag to 0 */
8319         gtk_clist_column_titles_show((GtkCList*) data);
8320         flag--;
8321     }
8322
8323     return;
8324 }
8325
8326 /* If we come here, then the user has selected a row in the list. */
8327 void selection_made( GtkWidget *clist, gint row, gint column,
8328                      GdkEventButton *event, gpointer data)
8329 {
8330     gchar       *text;
8331
8332     /* Get the text that is stored in the selected row and column
8333      * which was clicked in. We will receive it as a pointer in the
8334      * argument text.
8335      */
8336     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
8337
8338     /* Just prints some information about the selected row */
8339     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);
8340
8341     return;
8342 }
8343 /* example-end */
8344 </verb></tscreen>
8345                     
8346 <!-- ***************************************************************** -->
8347 <sect> Tree Widget <label id="sec_Tree_Widgets">
8348 <!-- ***************************************************************** -->
8349 <p>
8350 The purpose of tree widgets is to display hierarchically-organized
8351 data. The GtkTree widget itself is a vertical container for widgets of
8352 type GtkTreeItem. GtkTree itself is not terribly different from
8353 GtkList - both are derived directly from GtkContainer, and the
8354 GtkContainer methods work in the same way on GtkTree widgets as on
8355 GtkList widgets. The difference is that GtkTree widgets can be nested
8356 within other GtkTree widgets. We'll see how to do this shortly.
8357
8358 The GtkTree widget has its own window, and defaults to a white
8359 background, as does GtkList. Also, most of the GtkTree methods work in
8360 the same way as the corresponding GtkList ones. However, GtkTree is
8361 not derived from GtkList, so you cannot use them interchangeably.
8362
8363 <sect1> Creating a Tree
8364 <p>
8365 A GtkTree is created in the usual way, using:
8366
8367 <tscreen><verb>
8368 GtkWidget* gtk_tree_new( void );
8369 </verb></tscreen>
8370
8371 Like the GtkList widget, a GtkTree will simply keep growing as more
8372 items are added to it, as well as when subtrees are expanded.  For
8373 this reason, they are almost always packed into a
8374 GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
8375 scrolled window to ensure that it is big enough to see the tree's
8376 items, as the default size for GtkScrolledWindow is quite small.
8377
8378 Now that you have a tree, you'll probably want to add some items to
8379 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
8380 explains the gory details of GtkTreeItem. For now, it'll suffice to
8381 create one, using:
8382
8383 <tscreen><verb>
8384 GtkWidget* gtk_tree_item_new_with_label( gchar *label );
8385 </verb></tscreen>
8386
8387 You can then add it to the tree using one of the following (see
8388 <ref id="sec_GtkTree_Functions" name="Functions and Macros">
8389 below for more options):
8390
8391 <tscreen><verb>
8392 void gtk_tree_append( GtkTree    *tree,
8393                        GtkWidget *tree_item );
8394
8395 void gtk_tree_prepend( GtkTree   *tree,
8396                        GtkWidget *tree_item );
8397 </verb></tscreen>
8398
8399 Note that you must add items to a GtkTree one at a time - there is no
8400 equivalent to gtk_list_*_items().
8401
8402 <!-- ----------------------------------------------------------------- -->
8403 <sect1> Adding a Subtree
8404 <p>
8405 A subtree is created like any other GtkTree widget. A subtree is added
8406 to another tree beneath a tree item, using:
8407
8408 <tscreen><verb>
8409 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8410                                 GtkWidget   *subtree );
8411 </verb></tscreen>
8412
8413 You do not need to call gtk_widget_show() on a subtree before or after
8414 adding it to a GtkTreeItem. However, you <em>must</em> have added the
8415 GtkTreeItem in question to a parent tree before calling
8416 gtk_tree_item_set_subtree(). This is because, technically, the parent
8417 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
8418 rather the GtkTree which holds that GtkTreeItem.
8419
8420 When you add a subtree to a GtkTreeItem, a plus or minus sign appears
8421 beside it, which the user can click on to "expand" or "collapse" it,
8422 meaning, to show or hide its subtree. GtkTreeItems are collapsed by
8423 default. Note that when you collapse a GtkTreeItem, any selected
8424 items in its subtree remain selected, which may not be what the user
8425 expects.
8426
8427 <!-- ----------------------------------------------------------------- -->
8428 <sect1> Handling the Selection List
8429 <p>
8430 As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
8431 it is possible to control the behaviour of the tree (somewhat) by
8432 setting the selection type using:
8433
8434 <tscreen><verb>
8435 void gtk_tree_set_selection_mode( GtkTree          *tree,
8436                                   GtkSelectionMode  mode );
8437 </verb></tscreen>
8438
8439 The semantics associated with the various selection modes are
8440 described in the section on the GtkList widget. As with the GtkList
8441 widget, the "select_child", "unselect_child" (not really - see <ref
8442 id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
8443 and "selection_changed" signals are emitted when list items are
8444 selected or unselected. However, in order to take advantage of these
8445 signals, you need to know <em>which</em> GtkTree widget they will be
8446 emitted by, and where to find the list of selected items.
8447
8448 This is a source of potential confusion. The best way to explain this
8449 is that though all GtkTree widgets are created equal, some are more
8450 equal than others. All GtkTree widgets have their own X window, and
8451 can therefore receive events such as mouse clicks (if their
8452 GtkTreeItems or their children don't catch them first!). However, to
8453 make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
8454 behave in a sane manner, the list of selected items is specific to the
8455 topmost GtkTree widget in a hierarchy, known as the "root tree".
8456
8457 Thus, accessing the <tt>selection</tt>field directly in an arbitrary
8458 GtkTree widget is not a good idea unless you <em>know</em> it's the
8459 root tree.  Instead, use the GTK_TREE_SELECTION (Tree) macro, which
8460 gives the root tree's selection list as a GList pointer. Of course,
8461 this list can include items that are not in the subtree in question if 
8462 the selection type is GTK_SELECTION_MULTIPLE.
8463
8464 Finally, the "select_child" (and "unselect_child", in theory) signals
8465 are emitted by all trees, but the "selection_changed" signal is only
8466 emitted by the root tree. Consequently, if you want to handle the
8467 "select_child" signal for a tree and all its subtrees, you will have
8468 to call gtk_signal_connect() for every subtree.
8469
8470 <sect1> Tree Widget Internals
8471 <p>
8472 The GtkTree's struct definition looks like this:
8473
8474 <tscreen><verb>
8475 struct _GtkTree
8476 {
8477   GtkContainer container;
8478
8479   GList *children;
8480   
8481   GtkTree* root_tree; /* owner of selection list */
8482   GtkWidget* tree_owner;
8483   GList *selection;
8484   guint level;
8485   guint indent_value;
8486   guint current_indent;
8487   guint selection_mode : 2;
8488   guint view_mode : 1;
8489   guint view_line : 1;
8490 };
8491 </verb></tscreen>
8492
8493 The perils associated with accessing the <tt>selection</tt> field
8494 directly have already been mentioned. The other important fields of
8495 the struct can also be accessed with handy macros or class functions.
8496 GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
8497 whether a tree is the root tree in a GtkTree hierarchy, while
8498 GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
8499 GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
8500 to use one of the gtk_widget_*() functions on it).
8501
8502 Instead of directly accessing the children field of a GtkTree widget,
8503 it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
8504 to the gtk_container_children() function. This creates a duplicate of
8505 the original list, so it's advisable to free it up using g_list_free()
8506 after you're done with it, or to iterate on it destructively, like
8507 this:
8508
8509 <tscreen><verb>
8510     children = gtk_container_children (GTK_CONTAINER (tree));
8511     while (children) {
8512       do_something_nice (GTK_TREE_ITEM (children->data));
8513       children = g_list_remove_link (children, children);
8514 }
8515 </verb></tscreen>
8516
8517 The <tt>tree_owner</tt> field is defined only in subtrees, where it
8518 points to the GtkTreeItem widget which holds the tree in question.
8519 The <tt>level</tt> field indicates how deeply nested a particular tree
8520 is; root trees have level 0, and each successive level of subtrees has
8521 a level one greater than the parent level. This field is set only
8522 after a GtkTree widget is actually mapped (i.e. drawn on the screen).
8523
8524 <sect2> Signals<label id="sec_GtkTree_Signals">
8525 <p>
8526 <tscreen><verb>
8527 void selection_changed( GtkTree *tree );
8528 </verb></tscreen>
8529
8530 This signal will be emitted whenever the <tt>selection</tt> field of a
8531 GtkTree has changed. This happens when a child of the GtkTree is
8532 selected or deselected.
8533
8534 <tscreen><verb>
8535 void select_child( GtkTree   *tree,
8536                    GtkWidget *child );
8537 </verb></tscreen>
8538
8539 This signal is emitted when a child of the GtkTree is about to get
8540 selected. This happens on calls to gtk_tree_select_item(),
8541 gtk_tree_select_child(), on <em>all</em> button presses and calls to
8542 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
8543 indirectly triggered on other occasions where children get added to or
8544 removed from the GtkTree.
8545
8546 <tscreen><verb>
8547 void unselect_child (GtkTree   *tree,
8548                      GtkWidget *child);
8549 </verb></tscreen>
8550
8551 This signal is emitted when a child of the GtkTree is about to get
8552 deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
8553 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
8554 other occasions, but <em>not</em> when a button press deselects a
8555 child, nor on emission of the "toggle" signal by gtk_item_toggle().
8556
8557 <sect2> Functions and Macros<label id="sec_GtkTree_Functions">
8558 <p>
8559 <tscreen><verb>
8560 guint gtk_tree_get_type( void );
8561 </verb></tscreen>
8562
8563 Returns the `GtkTree' type identifier.
8564
8565 <tscreen><verb>
8566 GtkWidget* gtk_tree_new( void );
8567 </verb></tscreen>
8568
8569 Create a new GtkTree object. The new widget is returned as a pointer
8570 to a GtkWidget object. NULL is returned on failure.
8571
8572 <tscreen><verb>
8573 void gtk_tree_append( GtkTree   *tree,
8574                       GtkWidget *tree_item );
8575 </verb></tscreen>
8576
8577 Append a tree item to a GtkTree.
8578
8579 <tscreen><verb>
8580 void gtk_tree_prepend( GtkTree   *tree,
8581                        GtkWidget *tree_item );
8582 </verb></tscreen>
8583
8584 Prepend a tree item to a GtkTree.
8585
8586 <tscreen><verb>
8587 void gtk_tree_insert( GtkTree   *tree,
8588                       GtkWidget *tree_item,
8589                       gint       position );
8590 </verb></tscreen>
8591
8592 Insert a tree item into a GtkTree at the position in the list
8593 specified by <tt>position.</tt>
8594
8595 <tscreen><verb>
8596 void gtk_tree_remove_items( GtkTree *tree,
8597                             GList   *items );
8598 </verb></tscreen>
8599
8600 Remove a list of items (in the form of a GList *) from a GtkTree.
8601 Note that removing an item from a tree dereferences (and thus usually)
8602 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
8603 subtrees in that subtree.  If you want to remove only one item, you
8604 can use gtk_container_remove().
8605
8606 <tscreen><verb>
8607 void gtk_tree_clear_items( GtkTree *tree,
8608                            gint     start,
8609                            gint     end );
8610 </verb></tscreen>
8611
8612 Remove the items from position <tt>start</tt> to position <tt>end</tt>
8613 from a GtkTree.  The same warning about dereferencing applies here, as
8614 gtk_tree_clear_items() simply constructs a list and passes it to
8615 gtk_tree_remove_items().
8616
8617 <tscreen><verb>
8618 void gtk_tree_select_item( GtkTree *tree,
8619                            gint     item );
8620 </verb></tscreen>
8621
8622 Emits the "select_item" signal for the child at position
8623 <tt>item</tt>, thus selecting the child (unless you unselect it in a
8624 signal handler).
8625
8626 <tscreen><verb>
8627 void gtk_tree_unselect_item( GtkTree *tree,
8628                              gint     item );
8629 </verb></tscreen>
8630
8631 Emits the "unselect_item" signal for the child at position
8632 <tt>item</tt>, thus unselecting the child.
8633
8634 <tscreen><verb>
8635 void gtk_tree_select_child( GtkTree   *tree,
8636                             GtkWidget *tree_item );
8637 </verb></tscreen>
8638
8639 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
8640 selecting it.
8641
8642 <tscreen><verb>
8643 void gtk_tree_unselect_child( GtkTree   *tree,
8644                               GtkWidget *tree_item );
8645 </verb></tscreen>
8646
8647 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
8648 thus unselecting it.
8649
8650 <tscreen><verb>
8651 gint gtk_tree_child_position( GtkTree   *tree,
8652                               GtkWidget *child );
8653 </verb></tscreen>
8654
8655 Returns the position in the tree of <tt>child</tt>, unless
8656 <tt>child</tt> is not in the tree, in which case it returns -1.
8657
8658 <tscreen><verb>
8659 void gtk_tree_set_selection_mode( GtkTree          *tree,
8660                                   GtkSelectionMode  mode );
8661 </verb></tscreen>
8662
8663 Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
8664 default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
8665 GTK_SELECTION_EXTENDED. This is only defined for root trees, which
8666 makes sense, since the root tree "owns" the selection. Setting it for
8667 subtrees has no effect at all; the value is simply ignored.
8668
8669 <tscreen><verb>
8670 void gtk_tree_set_view_mode( GtkTree         *tree,
8671                              GtkTreeViewMode  mode ); 
8672 </verb></tscreen>
8673
8674 Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
8675 default) or GTK_TREE_VIEW_ITEM.  The view mode propagates from a tree
8676 to its subtrees, and can't be set exclusively to a subtree (this is
8677 not exactly true - see the example code comments).
8678
8679 The term "view mode" is rather ambiguous - basically, it controls the
8680 way the highlight is drawn when one of a tree's children is selected.
8681 If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
8682 highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
8683 (i.e. usually the label) is highlighted.
8684
8685 <tscreen><verb>
8686 void gtk_tree_set_view_lines( GtkTree *tree,
8687                               guint    flag );
8688 </verb></tscreen>
8689
8690 Controls whether connecting lines between tree items are drawn.
8691 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
8692 which case they aren't.
8693
8694 <tscreen><verb>
8695 GtkTree *GTK_TREE (gpointer obj);
8696 </verb></tscreen>
8697
8698 Cast a generic pointer to `GtkTree *'.
8699
8700 <tscreen><verb>
8701 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
8702 </verb></tscreen>
8703
8704 Cast a generic pointer to `GtkTreeClass*'.
8705
8706 <tscreen><verb>
8707 gint GTK_IS_TREE (gpointer obj);
8708 </verb></tscreen>
8709
8710 Determine if a generic pointer refers to a `GtkTree' object.
8711
8712 <tscreen><verb>
8713 gint GTK_IS_ROOT_TREE (gpointer obj)
8714 </verb></tscreen>
8715
8716 Determine if a generic pointer refers to a `GtkTree' object
8717 <em>and</em> is a root tree. Though this will accept any pointer, the
8718 results of passing it a pointer that does not refer to a GtkTree are
8719 undefined and possibly harmful.
8720
8721 <tscreen><verb>
8722 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
8723 </verb></tscreen>
8724
8725 Return the root tree of a pointer to a `GtkTree' object. The above
8726 warning applies.
8727
8728 <tscreen><verb>
8729 GList *GTK_TREE_SELECTION( gpointer obj)
8730 </verb></tscreen>
8731
8732 Return the selection list of the root tree of a `GtkTree' object. The
8733 above warning applies here, too.
8734
8735 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
8736 <p>
8737 The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
8738 which in turn is derived from GtkBin.  Therefore, the item itself is a
8739 generic container holding exactly one child widget, which can be of
8740 any type.  The GtkTreeItem widget has a number of extra fields, but
8741 the only one we need be concerned with is the <tt>subtree</tt> field.
8742
8743 The definition for the GtkTreeItem struct looks like this:
8744
8745 <tscreen><verb>
8746 struct _GtkTreeItem
8747 {
8748   GtkItem item;
8749
8750   GtkWidget *subtree;
8751   GtkWidget *pixmaps_box;
8752   GtkWidget *plus_pix_widget, *minus_pix_widget;
8753
8754   GList *pixmaps;               /* pixmap node for this items color depth */
8755
8756   guint expanded : 1;
8757 };
8758 </verb></tscreen>
8759
8760 The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
8761 on the plus/minus symbol which controls expansion and collapsing.  The
8762 <tt>pixmaps</tt> field points to an internal data structure.  Since
8763 you can always obtain the subtree of a GtkTreeItem in a (relatively)
8764 type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
8765 probably advisable never to touch the insides of a GtkTreeItem unless
8766 you <em>really</em> know what you're doing.
8767
8768 Since it is directly derived from a GtkItem it can be treated as such
8769 by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
8770 label, so the convenience function gtk_list_item_new_with_label() is
8771 provided. The same effect can be achieved using code like the
8772 following, which is actually copied verbatim from
8773 gtk_tree_item_new_with_label():
8774
8775 <tscreen><verb>
8776 tree_item = gtk_tree_item_new ();
8777 label_widget = gtk_label_new (label);
8778 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
8779
8780 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
8781 gtk_widget_show (label_widget);
8782 </verb></tscreen>
8783
8784 As one is not forced to add a GtkLabel to a GtkTreeItem, you could
8785 also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
8786 app will likely be quite unpopular in this case) to the GtkTreeItem.
8787
8788 If you remove all the items from a subtree, it will be destroyed and
8789 unparented, unless you reference it beforehand, and the GtkTreeItem
8790 which owns it will be collapsed.  So, if you want it to stick around,
8791 do something like the following:
8792
8793 <tscreen><verb>
8794 gtk_widget_ref (tree);
8795 owner = GTK_TREE(tree)->tree_owner;
8796 gtk_container_remove (GTK_CONTAINER(tree), item);
8797 if (tree->parent == NULL){
8798   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
8799   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
8800 }
8801 else
8802   gtk_widget_unref (tree);
8803 </verb></tscreen>
8804
8805 Finally, drag-n-drop <em>does</em> work with GtkTreeItems.  You just
8806 have to make sure that the GtkTreeItem you want to make into a drag
8807 item or a drop site has not only been added to a GtkTree, but that
8808 each successive parent widget has a parent itself, all the way back to
8809 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
8810 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
8811
8812 <sect2> Signals
8813 <p>
8814 GtkTreeItem inherits the "select", "deselect", and "toggle" signals
8815 from GtkItem.  In addition, it adds two signals of its own, "expand"
8816 and "collapse".
8817
8818 <tscreen><verb>
8819 void select( GtkItem *tree_item );
8820 </verb></tscreen>
8821
8822 This signal is emitted when an item is about to be selected, either
8823 after it has been clicked on by the user, or when the program calls
8824 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
8825
8826 <tscreen><verb>
8827 void deselect( GtkItem *tree_item );
8828 </verb></tscreen>
8829
8830 This signal is emitted when an item is about to be unselected, either
8831 after it has been clicked on by the user, or when the program calls
8832 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
8833 GtkTreeItems, it is also emitted by gtk_tree_unselect_child(), and
8834 sometimes gtk_tree_select_child().
8835
8836 <tscreen><verb>
8837 void toggle( GtkItem *tree_item );
8838 </verb></tscreen>
8839
8840 This signal is emitted when the program calls gtk_item_toggle().  The
8841 effect it has when emitted on a GtkTreeItem is to call
8842 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
8843 item's parent tree, if the item has a parent tree.  If it doesn't,
8844 then the highlight is reversed on the item.
8845
8846 <tscreen><verb>
8847 void expand( GtkTreeItem *tree_item );
8848 </verb></tscreen>
8849
8850 This signal is emitted when the tree item's subtree is about to be
8851 expanded, that is, when the user clicks on the plus sign next to the
8852 item, or when the program calls gtk_tree_item_expand().
8853
8854 <tscreen><verb>
8855 void collapse( GtkTreeItem *tree_item );
8856 </verb></tscreen>
8857
8858 This signal is emitted when the tree item's subtree is about to be
8859 collapsed, that is, when the user clicks on the minus sign next to the
8860 item, or when the program calls gtk_tree_item_collapse().
8861
8862 <sect2> Functions and Macros
8863 <p>
8864 <tscreen><verb>
8865 guint gtk_tree_item_get_type( void );
8866 </verb></tscreen>
8867
8868 Returns the `GtkTreeItem' type identifier.
8869
8870 <tscreen><verb>
8871 GtkWidget* gtk_tree_item_new( void );
8872 </verb></tscreen>
8873
8874 Create a new GtkTreeItem object. The new widget is returned as a
8875 pointer to a GtkWidget object. NULL is returned on failure.
8876
8877 <tscreen><verb>
8878 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
8879 </verb></tscreen>
8880
8881 Create a new GtkTreeItem object, having a single GtkLabel as the sole
8882 child. The new widget is returned as a pointer to a GtkWidget
8883 object. NULL is returned on failure.
8884
8885 <tscreen><verb>
8886 void gtk_tree_item_select( GtkTreeItem *tree_item );
8887 </verb></tscreen>
8888
8889 This function is basically a wrapper around a call to gtk_item_select
8890 (GTK_ITEM (tree_item)) which will emit the select signal.
8891
8892 <tscreen><verb>
8893 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
8894 </verb></tscreen>
8895
8896 This function is basically a wrapper around a call to
8897 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
8898 signal.
8899
8900 <tscreen><verb>
8901 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8902                                 GtkWidget   *subtree );
8903 </verb></tscreen>
8904
8905 This function adds subtree to tree_item, showing it if tree_item is
8906 expanded, or hiding it if tree_item is collapsed. Again, remember that
8907 the tree_item must have already been added to a tree for this to work.
8908
8909 <tscreen><verb>
8910 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
8911 </verb></tscreen>
8912
8913 This removes all of tree_item's subtree's children (thus unreferencing
8914 and destroying it, any of its children's subtrees, and so on...), then
8915 removes the subtree itself, and hides the plus/minus sign.
8916
8917 <tscreen><verb>
8918 void gtk_tree_item_expand( GtkTreeItem *tree_item );
8919 </verb></tscreen>
8920
8921 This emits the "expand" signal on tree_item, which expands it.
8922
8923 <tscreen><verb>
8924 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
8925 </verb></tscreen>
8926
8927 This emits the "collapse" signal on tree_item, which collapses it.
8928
8929 <tscreen><verb>
8930 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
8931 </verb></tscreen>
8932
8933 Cast a generic pointer to `GtkTreeItem*'.
8934
8935 <tscreen><verb>
8936 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
8937 </verb></tscreen>
8938
8939 Cast a generic pointer to `GtkTreeItemClass'.
8940
8941 <tscreen><verb>
8942 gint GTK_IS_TREE_ITEM (gpointer obj)
8943 </verb></tscreen>
8944
8945 Determine if a generic pointer refers to a `GtkTreeItem' object.
8946  
8947 <tscreen><verb>
8948 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
8949 </verb></tscreen>
8950
8951 Returns a tree item's subtree (obj should point to a `GtkTreeItem'
8952 object).
8953
8954 <sect1> Tree Example
8955 <p>
8956 This is somewhat like the tree example in testgtk.c, but a lot less
8957 complete (although much better commented).  It puts up a window with a
8958 tree, and connects all the signals for the relevant objects, so you
8959 can see when they are emitted.
8960
8961 <tscreen><verb>
8962 /* example-start tree tree.c */
8963
8964 #include <gtk/gtk.h>
8965
8966 /* for all the GtkItem:: and GtkTreeItem:: signals */
8967 static void cb_itemsignal (GtkWidget *item, gchar *signame)
8968 {
8969   gchar *name;
8970   GtkLabel *label;
8971
8972   /* It's a GtkBin, so it has one child, which we know to be a
8973      label, so get that */
8974   label = GTK_LABEL (GTK_BIN (item)->child);
8975   /* Get the text of the label */
8976   gtk_label_get (label, &amp;name);
8977   /* Get the level of the tree which the item is in */
8978   g_print ("%s called for item %s->%p, level %d\n", signame, name,
8979            item, GTK_TREE (item->parent)->level);
8980 }
8981
8982 /* Note that this is never called */
8983 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
8984                                GtkWidget *subtree)
8985 {
8986   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
8987            root_tree, subtree, child);
8988 }
8989
8990 /* Note that this is called every time the user clicks on an item,
8991    whether it is already selected or not. */
8992 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
8993                              GtkWidget *subtree)
8994 {
8995   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
8996            root_tree, subtree, child);
8997 }
8998
8999 static void cb_selection_changed (GtkWidget *tree)
9000 {
9001   GList *i;
9002   
9003   g_print ("selection_change called for tree %p\n", tree);
9004   g_print ("selected objects are:\n");
9005
9006   i = GTK_TREE_SELECTION(tree);
9007   while (i){
9008     gchar *name;
9009     GtkLabel *label;
9010     GtkWidget *item;
9011
9012     /* Get a GtkWidget pointer from the list node */
9013     item = GTK_WIDGET (i->data);
9014     label = GTK_LABEL (GTK_BIN (item)->child);
9015     gtk_label_get (label, &amp;name);
9016     g_print ("\t%s on level %d\n", name, GTK_TREE
9017              (item->parent)->level);
9018     i = i->next;
9019   }
9020 }
9021
9022 int main (int argc, char *argv[])
9023 {
9024   GtkWidget *window, *scrolled_win, *tree;
9025   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
9026                                "Maurice"};
9027   gint i;
9028
9029   gtk_init (&amp;argc, &amp;argv);
9030
9031   /* a generic toplevel window */
9032   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9033   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
9034                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
9035   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
9036
9037   /* A generic scrolled window */
9038   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9039   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9040                                   GTK_POLICY_AUTOMATIC,
9041                                   GTK_POLICY_AUTOMATIC);
9042   gtk_widget_set_usize (scrolled_win, 150, 200);
9043   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
9044   gtk_widget_show (scrolled_win);
9045   
9046   /* Create the root tree */
9047   tree = gtk_tree_new();
9048   g_print ("root tree is %p\n", tree);
9049   /* connect all GtkTree:: signals */
9050   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
9051                       GTK_SIGNAL_FUNC(cb_select_child), tree);
9052   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
9053                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
9054   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
9055                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
9056   /* Add it to the scrolled window */
9057   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
9058                                          tree);
9059   /* Set the selection mode */
9060   gtk_tree_set_selection_mode (GTK_TREE(tree),
9061                                GTK_SELECTION_MULTIPLE);
9062   /* Show it */
9063   gtk_widget_show (tree);
9064
9065   for (i = 0; i < 5; i++){
9066     GtkWidget *subtree, *item;
9067     gint j;
9068
9069     /* Create a tree item */
9070     item = gtk_tree_item_new_with_label (itemnames[i]);
9071     /* Connect all GtkItem:: and GtkTreeItem:: signals */
9072     gtk_signal_connect (GTK_OBJECT(item), "select",
9073                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9074     gtk_signal_connect (GTK_OBJECT(item), "deselect",
9075                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9076     gtk_signal_connect (GTK_OBJECT(item), "toggle",
9077                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9078     gtk_signal_connect (GTK_OBJECT(item), "expand",
9079                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9080     gtk_signal_connect (GTK_OBJECT(item), "collapse",
9081                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9082     /* Add it to the parent tree */
9083     gtk_tree_append (GTK_TREE(tree), item);
9084     /* Show it - this can be done at any time */
9085     gtk_widget_show (item);
9086     /* Create this item's subtree */
9087     subtree = gtk_tree_new();
9088     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
9089              subtree);
9090
9091     /* This is still necessary if you want these signals to be called
9092        for the subtree's children.  Note that selection_change will be 
9093        signalled for the root tree regardless. */
9094     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
9095                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
9096     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
9097                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
9098     /* This has absolutely no effect, because it is completely ignored 
9099        in subtrees */
9100     gtk_tree_set_selection_mode (GTK_TREE(subtree),
9101                                  GTK_SELECTION_SINGLE);
9102     /* Neither does this, but for a rather different reason - the
9103        view_mode and view_line values of a tree are propagated to
9104        subtrees when they are mapped.  So, setting it later on would
9105        actually have a (somewhat unpredictable) effect */
9106     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
9107     /* Set this item's subtree - note that you cannot do this until
9108        AFTER the item has been added to its parent tree! */
9109     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
9110
9111     for (j = 0; j < 5; j++){
9112       GtkWidget *subitem;
9113
9114       /* Create a subtree item, in much the same way */
9115       subitem = gtk_tree_item_new_with_label (itemnames[j]);
9116       /* Connect all GtkItem:: and GtkTreeItem:: signals */
9117       gtk_signal_connect (GTK_OBJECT(subitem), "select",
9118                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9119       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
9120                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9121       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
9122                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9123       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
9124                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9125       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
9126                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9127       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
9128       /* Add it to its parent tree */
9129       gtk_tree_append (GTK_TREE(subtree), subitem);
9130       /* Show it */
9131       gtk_widget_show (subitem);
9132     }
9133   }
9134
9135   /* Show the window and loop endlessly */
9136   gtk_widget_show (window);
9137   gtk_main();
9138   return 0;
9139 }
9140 /* example-end */
9141 </verb></tscreen>
9142
9143 <!-- ***************************************************************** -->
9144 <sect>Menu Widget
9145 <!-- ***************************************************************** -->
9146 <p>
9147 There are two ways to create menus, there's the easy way, and there's
9148 the hard way. Both have their uses, but you can usually use the
9149 itemfactory (the easy way). The "hard" way is to create all the menus
9150 using the calls directly. The easy way is to use the gtk_item_factory
9151 calls. This is much simpler, but there are advantages and
9152 disadvantages to each approach.
9153
9154 The itemfactory is much easier to use, and to add new menus to,
9155 although writing a few wrapper functions to create menus using the
9156 manual method could go a long way towards usability. With the
9157 menufactory, it is not possible to add images or the character '/' to
9158 the menus.
9159
9160 <!-- ----------------------------------------------------------------- -->
9161 <sect1>Manual Menu Creation
9162 <p>
9163 In the true tradition of teaching, we'll show you the hard way
9164 first. <tt>:)</>
9165
9166 There are three widgets that go into making a menubar and submenus:
9167 <itemize>
9168 <item>a menu item, which is what the user wants to select, e.g. 'Save'
9169 <item>a menu, which acts as a container for the menu items, and
9170 <item>a menubar, which is a container for each of the individual
9171 menus.
9172 </itemize>
9173
9174 This is slightly complicated by the fact that menu item widgets are
9175 used for two different things. They are both the widgets that are
9176 packed into the menu, and the widget that is packed into the menubar,
9177 which, when selected, activates the menu.
9178
9179 Let's look at the functions that are used to create menus and
9180 menubars.  This first function is used to create a new menubar.
9181
9182 <tscreen>
9183 <verb>
9184 GtkWidget *gtk_menu_bar_new( void );
9185 </verb>
9186 </tscreen>
9187
9188 This rather self explanatory function creates a new menubar. You use
9189 gtk_container_add to pack this into a window, or the box_pack
9190 functions to pack it into a box - the same as buttons.
9191
9192 <tscreen><verb>
9193 GtkWidget *gtk_menu_new( void );
9194 </verb></tscreen>
9195
9196 This function returns a pointer to a new menu, it is never actually
9197 shown (with gtk_widget_show), it is just a container for the menu
9198 items. Hopefully this will become more clear when you look at the
9199 example below.
9200
9201 The next two calls are used to create menu items that are packed into
9202 the menu (and menubar).
9203
9204 <tscreen><verb>
9205 GtkWidget *gtk_menu_item_new( void );
9206 </verb></tscreen>
9207
9208 and
9209
9210 <tscreen><verb>
9211 GtkWidget *gtk_menu_item_new_with_label( const char *label );
9212 </verb></tscreen>
9213
9214 These calls are used to create the menu items that are to be
9215 displayed.  Remember to differentiate between a "menu" as created with
9216 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
9217 functions. The menu item will be an actual button with an associated
9218 action, whereas a menu will be a container holding menu items.
9219
9220 The gtk_menu_new_with_label and gtk_menu_new functions are just as
9221 you'd expect after reading about the buttons. One creates a new menu
9222 item with a label already packed into it, and the other just creates a
9223 blank menu item.
9224
9225 Once you've created a menu item you have to put it into a menu. This
9226 is done using the function gtk_menu_append. In order to capture when
9227 the item is selected by the user, we need to connect to the
9228 <tt/activate/ signal in the usual way. So, if we wanted to create a
9229 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/ and
9230 <tt/Quit/ the code would look something like:
9231
9232 <tscreen><verb>
9233     file_menu = gtk_menu_new();    /* Don't need to show menus */
9234
9235     /* Create the menu items */
9236     open_item = gtk_menu_item_new_with_label("Open");
9237     save_item = gtk_menu_item_new_with_label("Save");
9238     quit_item = gtk_menu_item_new_with_label("Quit");
9239
9240     /* Add them to the menu */
9241     gtk_menu_append( GTK_MENU(file_menu), open_item);
9242     gtk_menu_append( GTK_MENU(file_menu), save_item);
9243     gtk_menu_append( GTK_MENU(file_menu), quit_item);
9244
9245     /* Attach the callback functions to the activate signal */
9246     gtk_signal_connect_object( GTK_OBJECT(open_items), "activate",
9247                                GTK_SIGNAL_FUNC(menuitem_response),
9248                                (gpointer) "file.open");
9249     gtk_signal_connect_object( GTK_OBJECT(save_items), "activate",
9250                                GTK_SIGNAL_FUNC(menuitem_response),
9251                                (gpointer) "file.save");
9252
9253     /* We can attach the Quit menu item to our exit function */
9254     gtk_signal_connect_object( GTK_OBJECT(quit_items), "activate",
9255                                GTK_SIGNAL_FUNC(destroy),
9256                                (gpointer) "file.quit");
9257
9258     /* We do need to show menu items */
9259     gtk_widget_show( open_item );
9260     gtk_widget_show( save_item );
9261     gtk_widget_show( quit_item );
9262 </verb></tscreen>
9263
9264 At this point we have our menu. Now we need to create a menubar and a
9265 menu item for the <tt/File/ entry, to which we add our menu. The code
9266 looks like this:
9267
9268 <tscreen><verb>
9269     menu_bar = gtk_menu_bar_new();
9270     gtk_container_add( GTK_CONTAINER(window), menu_bar);
9271     gtk_widget_show( menu_bar );
9272
9273     file_item = gtk_menu_item_new_with_label("File");
9274     gtk_widget_show(file_item);
9275 </verb></tscreen>
9276
9277 Now we need to associate the menu with <tt/file_item/. This is done
9278 with the function
9279
9280 <tscreen>
9281 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
9282                                 GtkWidget   *submenu );
9283 </tscreen>
9284
9285 So, our example would continue with
9286
9287 <tscreen><verb>
9288     gtk_menu_item_set_submenu( GTK_MENU_ITEM(file_item), file_menu );
9289 </verb></tscreen>
9290
9291 All that is left to do is to add the menu to the menubar, which is
9292 accomplished using the function
9293
9294 <tscreen>
9295 void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item);
9296 </tscreen>
9297
9298 which in our case looks like this:
9299
9300 <tscreen><verb>
9301     gtk_menu_bar_append( GTK_MENU_BAR (menu_bar), file_item );
9302 </verb></tscreen>
9303
9304 If we wanted the menu right justified on the menubar, such as help
9305 menus often are, we can use the following function (again on
9306 <tt/file_item/ in the current example) before attaching it to the
9307 menubar.
9308
9309 <tscreen><verb>
9310 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
9311 </verb></tscreen>
9312
9313 Here is a summary of the steps needed to create a menu bar with menus
9314 attached:
9315
9316 <itemize>
9317 <item> Create a new menu using gtk_menu_new()
9318 <item> Use multiple calls to gtk_menu_item_new() for each item you
9319 wish to have on your menu. And use gtk_menu_append() to put each of
9320 these new items on to the menu.
9321 <item> Create a menu item using gtk_menu_item_new(). This will be the
9322 root of the menu, the text appearing here will be on the menubar
9323 itself.
9324 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
9325 menu item (the one created in the above step).
9326 <item> Create a new menubar using gtk_menu_bar_new. This step only
9327 needs to be done once when creating a series of menus on one menu bar.
9328 <item> Use gtk_menu_bar_append to put the root menu onto the menubar.
9329 </itemize>
9330
9331 Creating a popup menu is nearly the same. The difference is that the
9332 menu is not posted `automatically' by a menubar, but explicitly by
9333 calling the function gtk_menu_popup() from a button-press event, for
9334 example.  Take these steps:
9335
9336 <itemize>
9337 <item>Create an event handling function. It needs to have the
9338 prototype
9339 <tscreen>
9340 static gint handler( GtkWidget *widget,
9341                      GdkEvent  *event );
9342 </tscreen>
9343 and it will use the event to find out where to pop up the menu.
9344 <item>In the event handler, if the event is a mouse button press,
9345 treat <tt>event</tt> as a button event (which it is) and use it as
9346 shown in the sample code to pass information to gtk_menu_popup().
9347 <item>Bind that event handler to a widget with
9348 <tscreen>
9349     gtk_signal_connect_object(GTK_OBJECT(widget), "event",
9350                               GTK_SIGNAL_FUNC (handler),
9351                               GTK_OBJECT(menu));
9352 </tscreen>
9353 where <tt>widget</tt> is the widget you are binding to,
9354 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
9355 created with gtk_menu_new(). This can be a menu which is also posted
9356 by a menu bar, as shown in the sample code.
9357 </itemize>
9358
9359 <!-- ----------------------------------------------------------------- -->
9360 <sect1>Manual Menu Example
9361 <p>
9362 That should about do it. Let's take a look at an example to help clarify.
9363
9364 <tscreen><verb>
9365 /* example-start menu menu.c */
9366
9367 #include <gtk/gtk.h>
9368
9369 static gint button_press (GtkWidget *, GdkEvent *);
9370 static void menuitem_response (gchar *);
9371
9372 int main (int argc, char *argv[])
9373 {
9374
9375     GtkWidget *window;
9376     GtkWidget *menu;
9377     GtkWidget *menu_bar;
9378     GtkWidget *root_menu;
9379     GtkWidget *menu_items;
9380     GtkWidget *vbox;
9381     GtkWidget *button;
9382     char buf[128];
9383     int i;
9384
9385     gtk_init (&amp;argc, &amp;argv);
9386
9387     /* create a new window */
9388     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9389     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
9390     gtk_window_set_title(GTK_WINDOW (window), "GTK Menu Test");
9391     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
9392                        (GtkSignalFunc) gtk_main_quit, NULL);
9393
9394     /* Init the menu-widget, and remember -- never
9395      * gtk_show_widget() the menu widget!! 
9396      * This is the menu that holds the menu items, the one that
9397      * will pop up when you click on the "Root Menu" in the app */
9398     menu = gtk_menu_new();
9399
9400     /* Next we make a little loop that makes three menu-entries for "test-menu".
9401      * Notice the call to gtk_menu_append.  Here we are adding a list of
9402      * menu items to our menu.  Normally, we'd also catch the "clicked"
9403      * signal on each of the menu items and setup a callback for it,
9404      * but it's omitted here to save space. */
9405
9406     for(i = 0; i < 3; i++)
9407         {
9408             /* Copy the names to the buf. */
9409             sprintf(buf, "Test-undermenu - %d", i);
9410
9411             /* Create a new menu-item with a name... */
9412             menu_items = gtk_menu_item_new_with_label(buf);
9413
9414             /* ...and add it to the menu. */
9415             gtk_menu_append(GTK_MENU (menu), menu_items);
9416
9417             /* Do something interesting when the menuitem is selected */
9418             gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
9419                 GTK_SIGNAL_FUNC(menuitem_response), (gpointer) g_strdup(buf));
9420
9421             /* Show the widget */
9422             gtk_widget_show(menu_items);
9423         }
9424
9425     /* This is the root menu, and will be the label
9426      * displayed on the menu bar.  There won't be a signal handler attached,
9427      * as it only pops up the rest of the menu when pressed. */
9428     root_menu = gtk_menu_item_new_with_label("Root Menu");
9429
9430     gtk_widget_show(root_menu);
9431
9432     /* Now we specify that we want our newly created "menu" to be the menu
9433      * for the "root menu" */
9434     gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_menu), menu);
9435
9436     /* A vbox to put a menu and a button in: */
9437     vbox = gtk_vbox_new(FALSE, 0);
9438     gtk_container_add(GTK_CONTAINER(window), vbox);
9439     gtk_widget_show(vbox);
9440
9441     /* Create a menu-bar to hold the menus and add it to our main window */
9442     menu_bar = gtk_menu_bar_new();
9443     gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
9444     gtk_widget_show(menu_bar);
9445
9446     /* Create a button to which to attach menu as a popup */
9447     button = gtk_button_new_with_label("press me");
9448     gtk_signal_connect_object(GTK_OBJECT(button), "event",
9449         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT(menu));
9450     gtk_box_pack_end(GTK_BOX(vbox), button, TRUE, TRUE, 2);
9451     gtk_widget_show(button);
9452
9453     /* And finally we append the menu-item to the menu-bar -- this is the
9454      * "root" menu-item I have been raving about =) */
9455     gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_menu);
9456
9457     /* always display the window as the last step so it all splashes on
9458      * the screen at once. */
9459     gtk_widget_show(window);
9460
9461     gtk_main ();
9462
9463     return 0;
9464 }
9465
9466 /* Respond to a button-press by posting a menu passed in as widget.
9467  *
9468  * Note that the "widget" argument is the menu being posted, NOT
9469  * the button that was pressed.
9470  */
9471
9472 static gint button_press (GtkWidget *widget, GdkEvent *event)
9473 {
9474
9475     if (event->type == GDK_BUTTON_PRESS) {
9476         GdkEventButton *bevent = (GdkEventButton *) event; 
9477         gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL,
9478                         bevent->button, bevent->time);
9479         /* Tell calling code that we have handled this event; the buck
9480          * stops here. */
9481         return TRUE;
9482     }
9483
9484     /* Tell calling code that we have not handled this event; pass it on. */
9485     return FALSE;
9486 }
9487
9488
9489 /* Print a string when a menu item is selected */
9490
9491 static void menuitem_response (gchar *string)
9492 {
9493     printf("%s\n", string);
9494 }
9495 /* example-end */
9496 </verb></tscreen>
9497
9498 You may also set a menu item to be insensitive and, using an accelerator
9499 table, bind keys to menu functions.
9500
9501 <!-- ----------------------------------------------------------------- -->
9502 <sect1>Using GtkItemFactory
9503 <p>
9504 Now that we've shown you the hard way, here's how you do it using the
9505 gtk_item_factory calls.
9506
9507 <!-- ----------------------------------------------------------------- -->
9508 <sect1>Item Factory Example
9509 <p>
9510 Here is an example using the GTK item factory.
9511
9512 <tscreen><verb>
9513 /* example-start menu itemfactory.c */
9514
9515 #include <gtk/gtk.h>
9516 #include <strings.h>
9517
9518 /* Obligatory basic callback */
9519 static void print_hello(GtkWidget *w, gpointer data) {
9520   g_message("Hello, World!\n");
9521 }
9522
9523 /* This is the GtkItemFactoryEntry structure used to generate new menus.
9524    Item 1: The menu path. The letter after the underscore indicates an
9525            accelerator key once the menu is open.
9526    Item 2: The accelerator key for the entry
9527    Item 3: The callback function.
9528    Item 4: The callback action.  This changes the parameters with
9529            which the function is called.  The default is 0.
9530    Item 5: The item type, used to define what kind of an item it is.
9531            Here are the possible values:
9532
9533            NULL               -> "<Item>"
9534            ""                 -> "<Item>"
9535            "<Title>"          -> create a title item
9536            "<Item>"           -> create a simple item
9537            "<CheckItem>"      -> create a check item
9538            "<ToggleItem>"     -> create a toggle item
9539            "<RadioItem>"      -> create a radio item
9540            <path>             -> path of a radio item to link against
9541            "<Separator>"      -> create a separator
9542            "<Branch>"         -> create an item to hold sub items
9543            "<LastBranch>"     -> create a right justified branch 
9544 */
9545
9546 static GtkItemFactoryEntry menu_items[] = {
9547   {"/_File",         NULL,         NULL, 0, "<Branch>"},
9548   {"/File/_New",     "<control>N", print_hello, 0, NULL},
9549   {"/File/_Open",    "<control>O", print_hello, 0, NULL},
9550   {"/File/_Save",    "<control>S", print_hello, 0, NULL},
9551   {"/File/Save _As", NULL,         NULL, 0, NULL},
9552   {"/File/sep1",     NULL,         NULL, 0, "<Separator>"},
9553   {"/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL},
9554   {"/_Options",      NULL,         NULL, 0, "<Branch>"},
9555   {"/Options/Test",  NULL,         NULL, 0, NULL},
9556   {"/_Help",         NULL,         NULL, 0, "<LastBranch>"},
9557   {"/_Help/About",   NULL,         NULL, 0, NULL},
9558 };
9559
9560
9561 void get_main_menu(GtkWidget *window, GtkWidget ** menubar) {
9562   int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
9563   GtkItemFactory *item_factory;
9564   GtkAccelGroup *accel_group;
9565
9566   accel_group = gtk_accel_group_new();
9567
9568   /* This function initializes the item factory.
9569      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
9570               or GTK_TYPE_OPTION_MENU.
9571      Param 2: The path of the menu.
9572      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
9573               the accelerator table while generating menus.
9574   */
9575
9576   item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", 
9577                                        accel_group);
9578
9579   /* This function generates the menu items. Pass the item factory,
9580      the number of items in the array, the array itself, and any
9581      callback data for the the menu items. */
9582   gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
9583
9584   /* Attach the new accelerator group to the window. */
9585   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
9586
9587   if (menubar)
9588     /* Finally, return the actual menu bar created by the item factory. */ 
9589     *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
9590 }
9591
9592 int main(int argc, char *argv[]) {
9593   GtkWidget *window;
9594   GtkWidget *main_vbox;
9595   GtkWidget *menubar;
9596   
9597   gtk_init(&amp;argc, &amp;argv);
9598   
9599   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
9600   gtk_signal_connect(GTK_OBJECT(window), "destroy", 
9601                      GTK_SIGNAL_FUNC(gtk_main_quit), 
9602                      "WM destroy");
9603   gtk_window_set_title(GTK_WINDOW(window), "Item Factory");
9604   gtk_widget_set_usize(GTK_WIDGET(window), 300, 200);
9605   
9606   main_vbox = gtk_vbox_new(FALSE, 1);
9607   gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
9608   gtk_container_add(GTK_CONTAINER(window), main_vbox);
9609   gtk_widget_show(main_vbox);
9610   
9611   get_main_menu(window, &amp;menubar);
9612   gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
9613   gtk_widget_show(menubar);
9614   
9615   gtk_widget_show(window);
9616   gtk_main();
9617   
9618   return(0);
9619 }
9620 /* example-end */
9621 </verb></tscreen>
9622
9623
9624 For now, there's only this example.  An explanation and lots 'o' comments
9625 will follow later.
9626
9627 <!-- ***************************************************************** -->
9628 <sect> Text Widget
9629 <!-- ***************************************************************** -->
9630 <p>
9631 The Text widget allows multiple lines of text to be displayed and
9632 edited.  It supports both multi-colored and multi-font text, allowing
9633 them to be mixed in any way we wish. It also has a wide set of key
9634 based text editing commands, which are compatible with Emacs.
9635
9636 The text widget supports full cut-and-paste facilities, including the
9637 use of double- and triple-click to select a word and a whole line,
9638 respectively.
9639
9640 <!-- ----------------------------------------------------------------- -->
9641 <sect1>Creating and Configuring a Text box
9642 <p>
9643 There is only one function for creating a new Text widget.
9644
9645 <tscreen><verb>
9646 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
9647                          GtkAdjustment *vadj );
9648 </verb></tscreen>
9649
9650 The arguments allow us to give the Text widget pointers to Adjustments
9651 that can be used to track the viewing position of the widget. Passing
9652 NULL values to either or both of these arguments will cause the
9653 gtk_text_new function to create its own.
9654
9655 <tscreen><verb>
9656 void gtk_text_set_adjustments( GtkText       *text,
9657                                GtkAdjustment *hadj,
9658                                GtkAdjustment *vadj );
9659 </verb></tscreen>
9660
9661 The above function allows the horizontal and vertical adjustments of a
9662 text widget to be changed at any time.
9663
9664 The text widget will not automatically create its own scrollbars when
9665 the amount of text to be displayed is too long for the display
9666 window. We therefore have to create and add them to the display layout
9667 ourselves.
9668
9669 <tscreen><verb>
9670   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
9671   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
9672   gtk_widget_show (vscrollbar);
9673 </verb></tscreen>
9674
9675 The above code snippet creates a new vertical scrollbar, and attaches
9676 it to the vertical adjustment of the text widget, <tt/text/. It then
9677 packs it into a box in the normal way.
9678
9679 Note, currently the GtkText widget does not support horizontal
9680 scrollbars.
9681
9682 There are two main ways in which a Text widget can be used: to allow
9683 the user to edit a body of text, or to allow us to display multiple
9684 lines of text to the user. In order for us to switch between these
9685 modes of operation, the text widget has the following function:
9686
9687 <tscreen><verb>
9688 void gtk_text_set_editable( GtkText *text,
9689                             gint     editable );
9690 </verb></tscreen>
9691
9692 The <tt/editable/ argument is a TRUE or FALSE value that specifies
9693 whether the user is permitted to edit the contents of the Text
9694 widget. When the text widget is editable, it will display a cursor at
9695 the current insertion point.
9696
9697 You are not, however, restricted to just using the text widget in
9698 these two modes. You can toggle the editable state of the text widget
9699 at any time, and can insert text at any time.
9700
9701 The text widget wraps lines of text that are too long to fit onto a
9702 single line of the display window. Its default behaviour is to break
9703 words across line breaks. This can be changed using the next function:
9704
9705 <tscreen><verb>
9706 void gtk_text_set_word_wrap( GtkText *text,
9707                              gint     word_wrap );
9708 </verb></tscreen>
9709
9710 Using this function allows us to specify that the text widget should
9711 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
9712 TRUE or FALSE value.
9713
9714 <!-- ----------------------------------------------------------------- -->
9715 <sect1>Text Manipulation
9716 <P>
9717 The current insertion point of a Text widget can be set using
9718 <tscreen><verb>
9719 void gtk_text_set_point( GtkText *text,
9720                          guint    index );
9721 </verb></tscreen>
9722
9723 where <tt/index/ is the position to set the insertion point.
9724
9725 Analogous to this is the function for getting the current insertion
9726 point:
9727
9728 <tscreen><verb>
9729 guint gtk_text_get_point( GtkText *text );
9730 </verb></tscreen>
9731
9732 A function that is useful in combination with the above two functions
9733 is
9734
9735 <tscreen><verb>
9736 guint gtk_text_get_length( GtkText *text );
9737 </verb></tscreen>
9738
9739 which returns the current length of the Text widget. The length is the
9740 number of characters that are within the text block of the widget,
9741 including characters such as carriage-return, which marks the end of
9742 lines.
9743
9744 In order to insert text at the current insertion point of a Text
9745 widget, the function gtk_text_insert is used, which also allows us to
9746 specify background and foreground colors and a font for the text.
9747
9748 <tscreen><verb>
9749 void gtk_text_insert( GtkText    *text,
9750                       GdkFont    *font,
9751                       GdkColor   *fore,
9752                       GdkColor   *back,
9753                       const char *chars,
9754                       gint        length );
9755 </verb></tscreen>
9756
9757 Passing a value of <tt/NULL/ in as the value for the foreground color,
9758 background colour or font will result in the values set within the
9759 widget style to be used. Using a value of <tt/-1/ for the length
9760 parameter will result in the whole of the text string given being
9761 inserted.
9762
9763 The text widget is one of the few within GTK that redraws itself
9764 dynamically, outside of the gtk_main function. This means that all
9765 changes to the contents of the text widget take effect
9766 immediately. This may be undesirable when performing multiple changes
9767 to the text widget. In order to allow us to perform multiple updates
9768 to the text widget without it continuously redrawing, we can freeze
9769 the widget, which temporarily stops it from automatically redrawing
9770 itself every time it is changed. We can then thaw the widget after our
9771 updates are complete.
9772
9773 The following two functions perform this freeze and thaw action:
9774
9775 <tscreen><verb>
9776 void gtk_text_freeze( GtkText *text );
9777
9778 void gtk_text_thaw( GtkText *text );         
9779 </verb></tscreen>
9780
9781 Text is deleted from the text widget relative to the current insertion
9782 point by the following two functions. The return value is a TRUE or
9783 FALSE indicator of whether the operation was successful.
9784
9785 <tscreen><verb>
9786 gint gtk_text_backward_delete( GtkText *text,
9787                                guint    nchars );
9788
9789 gint gtk_text_forward_delete ( GtkText *text,
9790                                guint    nchars );
9791 </verb></tscreen>
9792
9793 If you want to retrieve the contents of the text widget, then the
9794 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
9795 character at position <tt/index/ within the text widget <tt/t/.
9796
9797 To retrieve larger blocks of text, we can use the function
9798
9799 <tscreen><verb>
9800 gchar *gtk_editable_get_chars( GtkEditable *editable,
9801                                gint         start_pos,
9802                                gint         end_pos );   
9803 </verb></tscreen>
9804
9805 This is a function of the parent class of the text widget. A value of
9806 -1 as <tt/end_pos/ signifies the end of the text. The index of the
9807 text starts at 0.
9808
9809 The function allocates a new chunk of memory for the text block, so
9810 don't forget to free it with a call to g_free when you have finished
9811 with it.
9812  
9813 <!-- ----------------------------------------------------------------- -->
9814 <sect1>Keyboard Shortcuts
9815 <p>
9816 The text widget has a number of pre-installed keyboard shortcuts for
9817 common editing, motion and selection functions. These are accessed
9818 using Control and Alt key combinations.
9819
9820 In addition to these, holding down the Control key whilst using cursor
9821 key movement will move the cursor by words rather than
9822 characters. Holding down Shift whilst using cursor movement will
9823 extend the selection.
9824
9825 <sect2>Motion Shortcuts
9826 <p>
9827 <itemize>
9828 <item> Ctrl-A   Beginning of line
9829 <item> Ctrl-E   End of line
9830 <item> Ctrl-N   Next Line
9831 <item> Ctrl-P   Previous Line
9832 <item> Ctrl-B   Backward one character
9833 <item> Ctrl-F   Forward one character
9834 <item> Alt-B    Backward one word
9835 <item> Alt-F    Forward one word
9836 </itemize>
9837
9838 <sect2>Editing Shortcuts
9839 <p>
9840 <itemize>
9841 <item> Ctrl-H   Delete Backward Character (Backspace)
9842 <item> Ctrl-D   Delete Forward Character (Delete)
9843 <item> Ctrl-W   Delete Backward Word
9844 <item> Alt-D    Delete Forward Word
9845 <item> Ctrl-K   Delete to end of line
9846 <item> Ctrl-U   Delete line
9847 </itemize>
9848
9849 <sect2>Selection Shortcuts
9850 <p>
9851 <itemize>
9852 <item> Ctrl-X   Cut to clipboard
9853 <item> Ctrl-C   Copy to clipboard
9854 <item> Ctrl-V   Paste from clipboard
9855 </itemize>
9856
9857 <!-- ----------------------------------------------------------------- -->
9858 <sect1>A GtkText Example
9859 <p>
9860 <tscreen><verb>
9861 /* example-start text text.c */
9862
9863 /* text.c */
9864
9865 #include <stdio.h>
9866 #include <gtk/gtk.h>
9867
9868 void text_toggle_editable (GtkWidget *checkbutton,
9869                            GtkWidget *text)
9870 {
9871   gtk_text_set_editable(GTK_TEXT(text),
9872                         GTK_TOGGLE_BUTTON(checkbutton)->active);
9873 }
9874
9875 void text_toggle_word_wrap (GtkWidget *checkbutton,
9876                             GtkWidget *text)
9877 {
9878   gtk_text_set_word_wrap(GTK_TEXT(text),
9879                          GTK_TOGGLE_BUTTON(checkbutton)->active);
9880 }
9881
9882 void close_application( GtkWidget *widget, gpointer data )
9883 {
9884        gtk_main_quit();
9885 }
9886
9887 int main (int argc, char *argv[])
9888 {
9889   GtkWidget *window;
9890   GtkWidget *box1;
9891   GtkWidget *box2;
9892   GtkWidget *hbox;
9893   GtkWidget *button;
9894   GtkWidget *check;
9895   GtkWidget *separator;
9896   GtkWidget *table;
9897   GtkWidget *vscrollbar;
9898   GtkWidget *text;
9899   GdkColormap *cmap;
9900   GdkColor colour;
9901   GdkFont *fixed_font;
9902
9903   FILE *infile;
9904
9905   gtk_init (&amp;argc, &amp;argv);
9906  
9907   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9908   gtk_widget_set_usize (window, 600, 500);
9909   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
9910   gtk_signal_connect (GTK_OBJECT (window), "destroy",
9911                       GTK_SIGNAL_FUNC(close_application),
9912                       NULL);
9913   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
9914   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9915   
9916   
9917   box1 = gtk_vbox_new (FALSE, 0);
9918   gtk_container_add (GTK_CONTAINER (window), box1);
9919   gtk_widget_show (box1);
9920   
9921   
9922   box2 = gtk_vbox_new (FALSE, 10);
9923   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9924   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9925   gtk_widget_show (box2);
9926   
9927   
9928   table = gtk_table_new (2, 2, FALSE);
9929   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
9930   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
9931   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
9932   gtk_widget_show (table);
9933   
9934   /* Create the GtkText widget */
9935   text = gtk_text_new (NULL, NULL);
9936   gtk_text_set_editable (GTK_TEXT (text), TRUE);
9937   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
9938                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
9939                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
9940   gtk_widget_show (text);
9941
9942   /* Add a vertical scrollbar to the GtkText widget */
9943   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
9944   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
9945                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
9946   gtk_widget_show (vscrollbar);
9947
9948   /* Get the system colour map and allocate the colour red */
9949   cmap = gdk_colormap_get_system();
9950   colour.red = 0xffff;
9951   colour.green = 0;
9952   colour.blue = 0;
9953   if (!gdk_color_alloc(cmap, &amp;colour)) {
9954     g_error("couldn't allocate colour");
9955   }
9956
9957   /* Load a fixed font */
9958   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
9959
9960   /* Realizing a widget creates a window for it,
9961    * ready for us to insert some text */
9962   gtk_widget_realize (text);
9963
9964   /* Freeze the text widget, ready for multiple updates */
9965   gtk_text_freeze (GTK_TEXT (text));
9966   
9967   /* Insert some coloured text */
9968   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9969                    "Supports ", -1);
9970   gtk_text_insert (GTK_TEXT (text), NULL, &amp;colour, NULL,
9971                    "colored ", -1);
9972   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
9973                    "text and different ", -1);
9974   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
9975                    "fonts\n\n", -1);
9976   
9977   /* Load the file text.c into the text window */
9978
9979   infile = fopen("text.c", "r");
9980   
9981   if (infile) {
9982     char buffer[1024];
9983     int nchars;
9984     
9985     while (1)
9986       {
9987         nchars = fread(buffer, 1, 1024, infile);
9988         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
9989                          NULL, buffer, nchars);
9990         
9991         if (nchars < 1024)
9992           break;
9993       }
9994     
9995     fclose (infile);
9996   }
9997
9998   /* Thaw the text widget, allowing the updates to become visible */  
9999   gtk_text_thaw (GTK_TEXT (text));
10000   
10001   hbox = gtk_hbutton_box_new ();
10002   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
10003   gtk_widget_show (hbox);
10004
10005   check = gtk_check_button_new_with_label("Editable");
10006   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
10007   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10008                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
10009   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
10010   gtk_widget_show (check);
10011   check = gtk_check_button_new_with_label("Wrap Words");
10012   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
10013   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10014                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
10015   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
10016   gtk_widget_show (check);
10017
10018   separator = gtk_hseparator_new ();
10019   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10020   gtk_widget_show (separator);
10021
10022   box2 = gtk_vbox_new (FALSE, 10);
10023   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10024   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10025   gtk_widget_show (box2);
10026   
10027   button = gtk_button_new_with_label ("close");
10028   gtk_signal_connect (GTK_OBJECT (button), "clicked",
10029                       GTK_SIGNAL_FUNC(close_application),
10030                       NULL);
10031   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10032   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10033   gtk_widget_grab_default (button);
10034   gtk_widget_show (button);
10035
10036   gtk_widget_show (window);
10037
10038   gtk_main ();
10039   
10040   return(0);       
10041 }
10042 /* example-end */
10043 </verb></tscreen>
10044
10045
10046 <!-- ***************************************************************** -->
10047 <sect> Undocumented Widgets
10048 <!-- ***************************************************************** -->
10049 <p>
10050 These all require authors! :) Please consider contributing to our
10051 tutorial.
10052
10053 If you must use one of these widgets that are undocumented, I strongly
10054 suggest you take a look at their respective header files in the GTK
10055 distribution. GTK's function names are very descriptive. Once you
10056 have an understanding of how things work, it's not difficult to figure
10057 out how to use a widget simply by looking at its function
10058 declarations. This, along with a few examples from others' code, and
10059 it should be no problem.
10060
10061 When you do come to understand all the functions of a new undocumented
10062 widget, please consider writing a tutorial on it so others may benefit
10063 from your time.
10064
10065 <!-- ----------------------------------------------------------------- -->
10066 <sect1> Calendar
10067 <p>
10068 <!-- ----------------------------------------------------------------- -->
10069 <sect1> CTree
10070 <p>
10071 <!-- ----------------------------------------------------------------- -->
10072 <sect1> Curves
10073 <p>
10074 <!-- ----------------------------------------------------------------- -->
10075 <sect1> Drawing Area
10076 <p>
10077 <!-- ----------------------------------------------------------------- -->
10078 <sect1> Font Selection Dialog
10079 <p>
10080 <!-- ----------------------------------------------------------------- -->
10081 <sect1> Gamma Curve
10082 <p>
10083 <!-- ----------------------------------------------------------------- -->
10084 <sect1> Image
10085 <p>
10086 <!-- ----------------------------------------------------------------- -->
10087 <sect1> Packer
10088 <p>
10089 <!-- ----------------------------------------------------------------- -->
10090 <sect1> Plugs and Sockets
10091 <p>
10092 <!-- ----------------------------------------------------------------- -->
10093 <sect1> Preview
10094 <p>
10095
10096 <!--
10097
10098 (This may need to be rewritten to follow the style of the rest of the tutorial)
10099
10100 <tscreen><verb>
10101
10102 Previews serve a number of purposes in GIMP/GTK. The most important one is
10103 this. High quality images may take up to tens of megabytes of memory - easy!
10104 Any operation on an image that big is bound to take a long time. If it takes
10105 you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after
10106 you make an error) to choose the desired modification, it make take you
10107 literally hours to make the right one - if you don't run out of memory
10108 first. People who have spent hours in color darkrooms know the feeling.
10109 Previews to the rescue!
10110
10111 But the annoyance of the delay is not the only issue. Oftentimes it is
10112 helpful to compare the Before and After versions side-by-side or at least
10113 back-to-back. If you're working with big images and 10 second delays,
10114 obtaining the Before and After impressions is, to say the least, difficult.
10115 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
10116 out for most people, while back-to-back is more like back-to-1001, 1002,
10117 ..., 1010-back! Previews to the rescue!
10118
10119 But there's more. Previews allow for side-by-side pre-previews. In other
10120 words, you write a plug-in (e.g. the filterpack simulation) which would have
10121 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
10122 An approach like this acts as a sort of a preview palette and is very
10123 effective for subtle changes. Let's go previews!
10124
10125 There's more. For certain plug-ins real-time image-specific human
10126 intervention maybe necessary. In the SuperNova plug-in, for example, the
10127 user is asked to enter the coordinates of the center of the future
10128 supernova. The easiest way to do this, really, is to present the user with a
10129 preview and ask him to interactively select the spot. Let's go previews!
10130
10131 Finally, a couple of misc uses. One can use previews even when not working
10132 with big images. For example, they are useful when rendering complicated
10133 patterns. (Just check out the venerable Diffraction plug-in + many other
10134 ones!) As another example, take a look at the colormap rotation plug-in
10135 (work in progress). You can also use previews for little logos inside you
10136 plug-ins and even for an image of yourself, The Author. Let's go previews!
10137
10138 When Not to Use Previews
10139
10140 Don't use previews for graphs, drawing etc. GDK is much faster for that. Use
10141 previews only for rendered images!
10142
10143 Let's go previews!
10144
10145 You can stick a preview into just about anything. In a vbox, an hbox, a
10146 table, a button, etc. But they look their best in tight frames around them.
10147 Previews by themselves do not have borders and look flat without them. (Of
10148 course, if the flat look is what you want...) Tight frames provide the
10149 necessary borders.
10150
10151                                [Image][Image]
10152
10153 Previews in many ways are like any other widgets in GTK (whatever that
10154 means) except they possess an additional feature: they need to be filled with
10155 some sort of an image! First, we will deal exclusively with the GTK aspect
10156 of previews and then we'll discuss how to fill them.
10157
10158 GtkWidget *preview!
10159
10160 Without any ado:
10161
10162                               /* Create a preview widget,
10163                               set its size, an show it */
10164 GtkWidget *preview;
10165 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
10166                               /*Other option:
10167                               GTK_PREVIEW_GRAYSCALE);*/
10168 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
10169 gtk_widget_show(preview);
10170 my_preview_rendering_function(preview);
10171
10172 Oh yeah, like I said, previews look good inside frames, so how about:
10173
10174 GtkWidget *create_a_preview(int        Width,
10175                             int        Height,
10176                             int        Colorfulness)
10177 {
10178   GtkWidget *preview;
10179   GtkWidget *frame;
10180   
10181   frame = gtk_frame_new(NULL);
10182   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
10183   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
10184   gtk_widget_show(frame);
10185
10186   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
10187                                        :GTK_PREVIEW_GRAYSCALE);
10188   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
10189   gtk_container_add(GTK_CONTAINER(frame),preview);
10190   gtk_widget_show(preview);
10191
10192   my_preview_rendering_function(preview);
10193   return frame;
10194 }
10195
10196 That's my basic preview. This routine returns the "parent" frame so you can
10197 place it somewhere else in your interface. Of course, you can pass the
10198 parent frame to this routine as a parameter. In many situations, however,
10199 the contents of the preview are changed continually by your application. In
10200 this case you may want to pass a pointer to the preview to a
10201 "create_a_preview()" and thus have control of it later.
10202
10203 One more important note that may one day save you a lot of time. Sometimes
10204 it is desirable to label you preview. For example, you may label the preview
10205 containing the original image as "Original" and the one containing the
10206 modified image as "Less Original". It might occur to you to pack the
10207 preview along with the appropriate label into a vbox. The unexpected caveat
10208 is that if the label is wider than the preview (which may happen for a
10209 variety of reasons unforseeable to you, from the dynamic decision on the
10210 size of the preview to the size of the font) the frame expands and no longer
10211 fits tightly over the preview. The same problem can probably arise in other
10212 situations as well.
10213
10214                                    [Image]
10215
10216 The solution is to place the preview and the label into a 2x1 table and by
10217 attaching them with the following parameters (this is one possible variations
10218 of course. The key is no GTK_FILL in the second attachment):
10219
10220 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
10221                  0,
10222                  GTK_EXPAND|GTK_FILL,
10223                  0,0);
10224 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
10225                  GTK_EXPAND,
10226                  GTK_EXPAND,
10227                  0,0);
10228
10229
10230 And here's the result:
10231
10232                                    [Image]
10233
10234 Misc
10235
10236 Making a preview clickable is achieved most easily by placing it in a
10237 button. It also adds a nice border around the preview and you may not even
10238 need to place it in a frame. See the Filter Pack Simulation plug-in for an
10239 example.
10240
10241 This is pretty much it as far as GTK is concerned.
10242
10243 Filling In a Preview
10244
10245 In order to familiarize ourselves with the basics of filling in previews,
10246 let's create the following pattern (contrived by trial and error):
10247
10248                                    [Image]
10249
10250 void
10251 my_preview_rendering_function(GtkWidget     *preview)
10252 {
10253 #define SIZE 100
10254 #define HALF (SIZE/2)
10255
10256   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
10257   gint i, j;                             /* Coordinates    */
10258   double r, alpha, x, y;
10259
10260   if (preview==NULL) return; /* I usually add this when I want */
10261                              /* to avoid silly crashes. You    */
10262                              /* should probably make sure that */
10263                              /* everything has been nicely     */
10264                              /* initialized!                   */
10265   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
10266                                          /* glib.h contains ABS(x).   */
10267         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
10268         row[i*3+1] = 128;                /* Define Green              */
10269         row[i*3+2] = 224;                /* Define Blue               */
10270       }                                  /* "+0" is for alignment!    */
10271       else {
10272         row[i*3+0] = r*255;
10273         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
10274         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
10275       }
10276     }
10277     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
10278     /* Insert "row" into "preview" starting at the point with  */
10279     /* coordinates (0,j) first column, j_th row extending SIZE */
10280     /* pixels to the right */
10281   }
10282
10283   free(row); /* save some space */
10284   gtk_widget_draw(preview,NULL); /* what does this do? */
10285   gdk_flush(); /* or this? */
10286 }
10287
10288 Non-GIMP users can have probably seen enough to do a lot of things already.
10289 For the GIMP users I have a few pointers to add.
10290
10291 Image Preview
10292
10293 It is probably wise to keep a reduced version of the image around with just
10294 enough pixels to fill the preview. This is done by selecting every n'th
10295 pixel where n is the ratio of the size of the image to the size of the
10296 preview. All further operations (including filling in the previews) are then
10297 performed on the reduced number of pixels only. The following is my
10298 implementation of reducing the image. (Keep in mind that I've had only basic
10299 C!)
10300
10301 (UNTESTED CODE ALERT!!!)
10302
10303 typedef struct {
10304   gint      width;
10305   gint      height;
10306   gint      bbp;
10307   guchar    *rgb;
10308   guchar    *mask;
10309 } ReducedImage;
10310
10311 enum {
10312   SELECTION_ONLY,
10313   SELECTION_IN_CONTEXT,
10314   ENTIRE_IMAGE
10315 };
10316
10317 ReducedImage *Reduce_The_Image(GDrawable *drawable,
10318                                GDrawable *mask,
10319                                gint LongerSize,
10320                                gint Selection)
10321 {
10322   /* This function reduced the image down to the the selected preview size */
10323   /* The preview size is determine by LongerSize, i.e. the greater of the  */
10324   /* two dimensions. Works for RGB images only!                            */
10325   gint RH, RW;          /* Reduced height and reduced width                */
10326   gint width, height;   /* Width and Height of the area being reduced      */
10327   gint bytes=drawable->bpp;
10328   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
10329
10330   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
10331   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
10332   GPixelRgn srcPR, srcMask;
10333   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
10334                              /* image.                                     */
10335
10336   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
10337   width  = x2-x1;
10338   height = y2-y1;
10339   /* If there's a SELECTION, we got its bounds!)
10340
10341   if (width != drawable->width &amp;&amp; height != drawable->height)
10342     NoSelectionMade=FALSE;
10343   /* Become aware of whether the user has made an active selection   */
10344   /* This will become important later, when creating a reduced mask. */
10345
10346   /* If we want to preview the entire image, overrule the above!  */
10347   /* Of course, if no selection has been made, this does nothing! */
10348   if (Selection==ENTIRE_IMAGE) {
10349     x1=0;
10350     x2=drawable->width;
10351     y1=0;
10352     y2=drawable->height;
10353   }
10354
10355   /* If we want to preview a selection with some surrounding area we */
10356   /* have to expand it a little bit. Consider it a bit of a riddle. */
10357   if (Selection==SELECTION_IN_CONTEXT) {
10358     x1=MAX(0,                x1-width/2.0);
10359     x2=MIN(drawable->width,  x2+width/2.0);
10360     y1=MAX(0,                y1-height/2.0);
10361     y2=MIN(drawable->height, y2+height/2.0);
10362   }
10363
10364   /* How we can determine the width and the height of the area being */
10365   /* reduced.                                                        */
10366   width  = x2-x1;
10367   height = y2-y1;
10368
10369   /* The lines below determine which dimension is to be the longer   */
10370   /* side. The idea borrowed from the supernova plug-in. I suspect I */
10371   /* could've thought of it myself, but the truth must be told.      */
10372   /* Plagiarism stinks!                                               */
10373   if (width>height) {
10374     RW=LongerSize;
10375     RH=(float) height * (float) LongerSize/ (float) width;
10376   }
10377   else {
10378     RH=LongerSize;
10379     RW=(float)width * (float) LongerSize/ (float) height;
10380   }
10381
10382   /* The entire image is stretched into a string! */
10383   tempRGB   = (guchar *) malloc(RW*RH*bytes);
10384   tempmask  = (guchar *) malloc(RW*RH);
10385
10386   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height,
10387                        FALSE, FALSE);
10388   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height,
10389                        FALSE, FALSE);
10390
10391   /* Grab enough to save a row of image and a row of mask. */
10392   src_row       = (guchar *) malloc (width*bytes);
10393   src_mask_row  = (guchar *) malloc (width);
10394
10395   for (i=0; i < RH; i++) {
10396     whichrow=(float)i*(float)height/(float)RH;
10397     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
10398     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
10399
10400     for (j=0; j < RW; j++) {
10401       whichcol=(float)j*(float)width/(float)RW;
10402
10403       /* No selection made = each point is completely selected! */
10404       if (NoSelectionMade)
10405         tempmask[i*RW+j]=255;
10406       else
10407         tempmask[i*RW+j]=src_mask_row[whichcol];
10408
10409       /* Add the row to the one long string which now contains the image! */
10410       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
10411       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
10412       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
10413
10414       /* Hold on to the alpha as well */
10415       if (bytes==4)
10416         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
10417     }
10418   }
10419   temp->bpp=bytes;
10420   temp->width=RW;
10421   temp->height=RH;
10422   temp->rgb=tempRGB;
10423   temp->mask=tempmask;
10424   return temp;
10425 }
10426
10427 The following is a preview function which used the same ReducedImage type!
10428 Note that it uses fakes transparency (if one is present by means of
10429 fake_transparency which is defined as follows:
10430
10431 gint fake_transparency(gint i, gint j)
10432 {
10433   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
10434     return 64;
10435   else
10436     return 196;
10437 }
10438
10439 Now here's the preview function:
10440
10441 void
10442 my_preview_render_function(GtkWidget     *preview,
10443                            gint          changewhat,
10444                            gint          changewhich)
10445 {
10446   gint Inten, bytes=drawable->bpp;
10447   gint i, j, k;
10448   float partial;
10449   gint RW=reduced->width;
10450   gint RH=reduced->height;
10451   guchar *row=malloc(bytes*RW);;
10452
10453
10454   for (i=0; i < RH; i++) {
10455     for (j=0; j < RW; j++) {
10456
10457       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
10458       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
10459       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
10460
10461       if (bytes==4)
10462         for (k=0; k<3; k++) {
10463           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
10464           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
10465         }
10466     }
10467     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
10468   }
10469
10470   free(a);
10471   gtk_widget_draw(preview,NULL);
10472   gdk_flush();
10473 }
10474
10475 Applicable Routines
10476
10477 guint           gtk_preview_get_type           (void);
10478 /* No idea */
10479 void            gtk_preview_uninit             (void);
10480 /* No idea */
10481 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
10482 /* Described above */
10483 void            gtk_preview_size               (GtkPreview      *preview,
10484                                                 gint             width,
10485                                                 gint             height);
10486 /* Allows you to resize an existing preview.    */
10487 /* Apparently there's a bug in GTK which makes  */
10488 /* this process messy. A way to clean up a mess */
10489 /* is to manually resize the window containing  */
10490 /* the preview after resizing the preview.      */
10491
10492 void            gtk_preview_put                (GtkPreview      *preview,
10493                                                 GdkWindow       *window,
10494                                                 GdkGC           *gc,
10495                                                 gint             srcx,
10496                                                 gint             srcy,
10497                                                 gint             destx,
10498                                                 gint             desty,
10499                                                 gint             width,
10500                                                 gint             height);
10501 /* No idea */
10502
10503 void            gtk_preview_put_row            (GtkPreview      *preview,
10504                                                 guchar          *src,
10505                                                 guchar          *dest,
10506                                                 gint             x,
10507                                                 gint             y,
10508                                                 gint             w);
10509 /* No idea */
10510
10511 void            gtk_preview_draw_row           (GtkPreview      *preview,
10512                                                 guchar          *data,
10513                                                 gint             x,
10514                                                 gint             y,
10515                                                 gint             w);
10516 /* Described in the text */
10517
10518 void            gtk_preview_set_expand         (GtkPreview      *preview,
10519                                                 gint             expand);
10520 /* No idea */
10521
10522 /* No clue for any of the below but    */
10523 /* should be standard for most widgets */
10524 void            gtk_preview_set_gamma          (double           gamma);
10525 void            gtk_preview_set_color_cube     (guint            nred_shades,
10526                                                 guint            ngreen_shades,
10527                                                 guint            nblue_shades,
10528                                                 guint            ngray_shades);
10529 void            gtk_preview_set_install_cmap   (gint             install_cmap);
10530 void            gtk_preview_set_reserved       (gint             nreserved);
10531 GdkVisual*      gtk_preview_get_visual         (void);
10532 GdkColormap*    gtk_preview_get_cmap           (void);
10533 GtkPreviewInfo* gtk_preview_get_info           (void);
10534
10535 That's all, folks!
10536
10537 </verb></tscreen>
10538
10539 -->
10540
10541 <!-- ***************************************************************** -->
10542 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
10543 <!-- ***************************************************************** -->
10544 <p>
10545 This describes the functions used to operate on widgets.  These can be
10546 used to set style, padding, size etc.
10547
10548 (Maybe I should make a whole section on accelerators.)
10549
10550 <tscreen><verb>
10551 void gtk_widget_install_accelerator( GtkWidget           *widget,
10552                                      GtkAcceleratorTable *table,
10553                                      gchar               *signal_name,
10554                                      gchar                key,
10555                                      guint8               modifiers );
10556
10557 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
10558                                      GtkAcceleratorTable *table,
10559                                      gchar               *signal_name);
10560
10561 void gtk_widget_activate( GtkWidget *widget );
10562
10563 void gtk_widget_set_name( GtkWidget *widget,
10564                           gchar     *name );
10565
10566 gchar *gtk_widget_get_name( GtkWidget *widget );
10567
10568 void gtk_widget_set_sensitive( GtkWidget *widget,
10569                                gint       sensitive );
10570
10571 void gtk_widget_set_style( GtkWidget *widget,
10572                            GtkStyle  *style );
10573                                            
10574 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
10575
10576 GtkStyle *gtk_widget_get_default_style( void );
10577
10578 void gtk_widget_set_uposition( GtkWidget *widget,
10579                                gint       x,
10580                                gint       y );
10581
10582 void gtk_widget_set_usize( GtkWidget *widget,
10583                            gint       width,
10584                            gint       height );
10585
10586 void gtk_widget_grab_focus( GtkWidget *widget );
10587
10588 void gtk_widget_show( GtkWidget *widget );
10589
10590 void gtk_widget_hide( GtkWidget *widget );
10591 </verb></tscreen>
10592
10593 <!-- ***************************************************************** -->
10594 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
10595 <!-- ***************************************************************** -->
10596
10597 <!-- ----------------------------------------------------------------- -->
10598 <sect1>Timeouts
10599 <p>
10600 You may be wondering how you make GTK do useful work when in gtk_main.
10601 Well, you have several options. Using the following functions you can
10602 create a timeout function that will be called every "interval"
10603 milliseconds.
10604
10605 <tscreen><verb>
10606 gint gtk_timeout_add( guint32     interval,
10607                       GtkFunction function,
10608                       gpointer    data );
10609 </verb></tscreen>
10610
10611 The first argument is the number of milliseconds between calls to your
10612 function. The second argument is the function you wish to have called,
10613 and the third, the data passed to this callback function. The return
10614 value is an integer "tag" which may be used to stop the timeout by
10615 calling:
10616
10617 <tscreen><verb>
10618 void gtk_timeout_remove( gint tag );
10619 </verb></tscreen>
10620
10621 You may also stop the timeout function by returning zero or FALSE from
10622 your callback function. Obviously this means if you want your function
10623 to continue to be called, it should return a non-zero value,
10624 i.e. TRUE.
10625
10626 The declaration of your callback should look something like this:
10627
10628 <tscreen><verb>
10629 gint timeout_callback( gpointer data );
10630 </verb></tscreen>
10631
10632 <!-- ----------------------------------------------------------------- -->
10633 <sect1>Monitoring IO
10634 <p>
10635 A nifty feature of GDK (the library that underlies GTK), is the
10636 ability to have it check for data on a file descriptor for you (as
10637 returned by open(2) or socket(2)). This is especially useful for
10638 networking applications. The function:
10639
10640 <tscreen><verb>
10641 gint gdk_input_add( gint              source,
10642                     GdkInputCondition condition,
10643                     GdkInputFunction  function,
10644                     gpointer          data );
10645 </verb></tscreen>
10646
10647 Where the first argument is the file descriptor you wish to have
10648 watched, and the second specifies what you want GDK to look for. This
10649 may be one of:
10650
10651 <itemize>
10652 <item>GDK_INPUT_READ - Call your function when there is data ready for
10653 reading on your file descriptor.
10654
10655 <item>GDK_INPUT_WRITE - Call your function when the file descriptor is
10656 ready for writing.
10657 </itemize>
10658
10659 As I'm sure you've figured out already, the third argument is the
10660 function you wish to have called when the above conditions are
10661 satisfied, and the fourth is the data to pass to this function.
10662
10663 The return value is a tag that may be used to stop GDK from monitoring
10664 this file descriptor using the following function.
10665
10666 <tscreen><verb>
10667 void gdk_input_remove( gint tag );
10668 </verb></tscreen>
10669
10670 The callback function should be declared as:
10671
10672 <tscreen><verb>
10673 void input_callback( gpointer          data,
10674                      gint              source, 
10675                      GdkInputCondition condition );
10676 </verb></tscreen>
10677
10678 Where <tt/source/ and <tt/condition/ are as specified above.
10679
10680 <!-- ----------------------------------------------------------------- -->
10681 <sect1>Idle Functions
10682 <p>
10683 <!-- TODO: Need to check on idle priorities - TRG -->
10684 What if you have a function you want called when nothing else is
10685 happening ?
10686
10687 <tscreen><verb>
10688 gint gtk_idle_add( GtkFunction function,
10689                    gpointer    data );
10690 </verb></tscreen>
10691
10692 This causes GTK to call the specified function whenever nothing else
10693 is happening.
10694
10695 <tscreen><verb>
10696 void gtk_idle_remove( gint tag );
10697 </verb></tscreen>
10698
10699 I won't explain the meaning of the arguments as they follow very much
10700 like the ones above. The function pointed to by the first argument to
10701 gtk_idle_add will be called whenever the opportunity arises. As with
10702 the others, returning FALSE will stop the idle function from being
10703 called.
10704
10705 <!-- ***************************************************************** -->
10706 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
10707 <!-- ***************************************************************** -->
10708
10709 <!-- ----------------------------------------------------------------- -->
10710 <sect1>Signal Functions
10711
10712 <!-- ----------------------------------------------------------------- -->
10713 <sect2>Connecting and Disconnecting Signal Handlers
10714 <p>
10715
10716 <tscreen><verb>
10717 guint gtk_signal_connect( GtkObject     *object,
10718                           const gchar   *name,
10719                           GtkSignalFunc  func,
10720                           gpointer       func_data );
10721
10722 guint gtk_signal_connect_after( GtkObject     *object,
10723                                 const gchar   *name,
10724                                 GtkSignalFunc  func,
10725                                 gpointer       func_data );
10726
10727 guint gtk_signal_connect_object( GtkObject     *object,
10728                                  const gchar   *name,
10729                                  GtkSignalFunc  func,
10730                                  GtkObject     *slot_object );
10731
10732 guint gtk_signal_connect_object_after( GtkObject     *object,
10733                                        const gchar   *name,
10734                                        GtkSignalFunc  func,
10735                                        GtkObject     *slot_object );
10736
10737 guint gtk_signal_connect_full( GtkObject          *object,
10738                                const gchar        *name,
10739                                GtkSignalFunc       func,
10740                                GtkCallbackMarshal  marshal,
10741                                gpointer            data,
10742                                GtkDestroyNotify    destroy_func,
10743                                gint                object_signal,
10744                                gint                after );
10745
10746 guint gtk_signal_connect_interp( GtkObject          *object,
10747                                  const gchar        *name,
10748                                  GtkCallbackMarshal  func,
10749                                  gpointer            data,
10750                                  GtkDestroyNotify    destroy_func,
10751                                  gint                after );
10752
10753 void gtk_signal_connect_object_while_alive( GtkObject     *object,
10754                                             const gchar   *signal,
10755                                             GtkSignalFunc  func,
10756                                             GtkObject     *alive_object );
10757
10758 void gtk_signal_connect_while_alive( GtkObject     *object,
10759                                      const gchar   *signal,
10760                                      GtkSignalFunc  func,
10761                                      gpointer       func_data,
10762                                      GtkObject     *alive_object );
10763
10764 void gtk_signal_disconnect( GtkObject *object,
10765                             guint      handler_id );
10766
10767 void gtk_signal_disconnect_by_func( GtkObject     *object,
10768                                     GtkSignalFunc  func,
10769                                     gpointer       data );
10770 </verb></tscreen>
10771
10772 <!-- ----------------------------------------------------------------- -->
10773 <sect2>Blocking and Unblocking Signal Handlers
10774 <p>
10775 <tscreen><verb>
10776 void gtk_signal_handler_block( GtkObject *object,
10777                                guint      handler_id);
10778
10779 void gtk_signal_handler_block_by_func( GtkObject     *object,
10780                                        GtkSignalFunc  func,
10781                                        gpointer       data );
10782
10783 void gtk_signal_handler_block_by_data( GtkObject *object,
10784                                        gpointer   data );
10785
10786 void gtk_signal_handler_unblock( GtkObject *object,
10787                                  guint      handler_id );
10788
10789 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
10790                                          GtkSignalFunc  func,
10791                                          gpointer       data );
10792
10793 void gtk_signal_handler_unblock_by_data( GtkObject *object,
10794                                          gpointer   data );
10795 </verb></tscreen>
10796
10797 <!-- ----------------------------------------------------------------- -->
10798 <sect2>Emitting and Stopping Signals
10799 <p>
10800 <tscreen><verb>
10801 void gtk_signal_emit( GtkObject *object,
10802                       guint      signal_id,
10803                       ... );
10804
10805 void gtk_signal_emit_by_name( GtkObject   *object,
10806                               const gchar *name,
10807                               ... );
10808
10809 void gtk_signal_emitv( GtkObject *object,
10810                        guint      signal_id,
10811                        GtkArg    *params );
10812
10813 void gtk_signal_emitv_by_name( GtkObject   *object,
10814                                const gchar *name,
10815                                GtkArg      *params );
10816
10817 guint gtk_signal_n_emissions( GtkObject *object,
10818                               guint      signal_id );
10819
10820 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
10821                                       const gchar *name );
10822
10823 void gtk_signal_emit_stop( GtkObject *object,
10824                            guint      signal_id );
10825
10826 void gtk_signal_emit_stop_by_name( GtkObject   *object,
10827                                    const gchar *name );
10828 </verb></tscreen>
10829
10830 <!-- ----------------------------------------------------------------- -->
10831 <sect1>Signal Emission and Propagation
10832 <p>
10833 Signal emission is the process wherby GTK runs all handlers for a
10834 specific object and signal.
10835
10836 First, note that the return value from a signal emission is the return
10837 value of the <em>last</em> handler executed. Since event signals are
10838 all of type GTK_RUN_LAST, this will be the default (GTK supplied)
10839 default handler, unless you connect with gtk_signal_connect_after().
10840
10841 The way an event (say GTK_BUTTON_PRESS) is handled, is:
10842 <itemize>
10843 <item>Start with the widget where the event occured.
10844
10845 <item>Emit the generic "event" signal. If that signal handler returns
10846 a value of TRUE, stop all processing.
10847
10848 <item>Otherwise, emit a specific, "button_press_event" signal. If that
10849 returns TRUE, stop all processing.
10850
10851 <item>Otherwise, go to the widget's parent, and repeat the above steps.
10852
10853 <item>Contimue until some signal handler returns TRUE, or until the
10854 top-level widget is reached.
10855 </itemize>
10856
10857 Some consequences of the above are:
10858 <itemize>
10859 <item>Your handler's return value will have no effect if there is a
10860 default handler, unless you connect with gtk_signal_connect_after().
10861
10862 <item>To prevent the default handler from being run, you need to
10863 connect with gtk_signal_connect() and use
10864 gtk_signal_emit_stop_by_name() - the return value only affects whether
10865 the signal is propagated, not the current emission.
10866 </itemize>
10867
10868 <!-- ***************************************************************** -->
10869 <sect>Managing Selections
10870 <!-- ***************************************************************** -->
10871
10872 <!-- ----------------------------------------------------------------- -->
10873 <sect1> Overview
10874 <p>
10875 One type of interprocess communication supported by GTK is
10876 <em>selections</em>. A selection identifies a chunk of data, for
10877 instance, a portion of text, selected by the user in some fashion, for
10878 instance, by dragging with the mouse. Only one application on a
10879 display, (the <em>owner</em>) can own a particular selection at one
10880 time, so when a selection is claimed by one application, the previous
10881 owner must indicate to the user that selection has been
10882 relinquished. Other applications can request the contents of a
10883 selection in different forms, called <em>targets</em>. There can be
10884 any number of selections, but most X applications only handle one, the
10885 <em>primary selection</em>.
10886
10887 In most cases, it isn't necessary for a GTK application to deal with
10888 selections itself. The standard widgets, such as the Entry widget,
10889 already have the capability to claim the selection when appropriate
10890 (e.g., when the user drags over text), and to retrieve the contents of
10891 the selection owned by another widget, or another application (e.g.,
10892 when the user clicks the second mouse button). However, there may be
10893 cases in which you want to give other widgets the ability to supply
10894 the selection, or you wish to retrieve targets not supported by
10895 default.
10896
10897 A fundamental concept needed to understand selection handling is that
10898 of the <em>atom</em>. An atom is an integer that uniquely identifies a
10899 string (on a certain display). Certain atoms are predefined by the X
10900 server, and in some cases there are constants in <tt>gtk.h</tt>
10901 corresponding to these atoms. For instance the constant
10902 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
10903 In other cases, you should use the functions
10904 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
10905 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
10906 selections and targets are identified by atoms.
10907
10908 <!-- ----------------------------------------------------------------- -->
10909 <sect1> Retrieving the selection
10910 <p>
10911 Retrieving the selection is an asynchronous process. To start the
10912 process, you call:
10913
10914 <tscreen><verb>
10915 gint gtk_selection_convert( GtkWidget *widget, 
10916                             GdkAtom    selection, 
10917                             GdkAtom    target,
10918                             guint32    time );
10919 </verb</tscreen>
10920
10921 This <em>converts</em> the selection into the form specified by
10922 <tt/target/. If at all possible, the time field should be the time
10923 from the event that triggered the selection. This helps make sure that
10924 events occur in the order that the user requested them. However, if it
10925 is not available (for instance, if the conversion was triggered by a
10926 "clicked" signal), then you can use the constant
10927 <tt>GDK_CURRENT_TIME</tt>.
10928
10929 When the selection owner responds to the request, a
10930 "selection_received" signal is sent to your application. The handler
10931 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
10932 structure, which is defined as:
10933
10934 <tscreen><verb>
10935 struct _GtkSelectionData
10936 {
10937   GdkAtom selection;
10938   GdkAtom target;
10939   GdkAtom type;
10940   gint    format;
10941   guchar *data;
10942   gint    length;
10943 };
10944 </verb></tscreen>
10945
10946 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
10947 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
10948 identifies the type of data returned by the selection owner. Some
10949 possible values are "STRING", a string of latin-1 characters, "ATOM",
10950 a series of atoms, "INTEGER", an integer, etc. Most targets can only
10951 return one type. <tt/format/ gives the length of the units (for
10952 instance characters) in bits. Usually, you don't care about this when
10953 receiving data. <tt>data</tt> is a pointer to the returned data, and
10954 <tt>length</tt> gives the length of the returned data, in bytes. If
10955 <tt>length</tt> is negative, then an error occurred and the selection
10956 could not be retrieved. This might happen if no application owned the
10957 selection, or if you requested a target that the application didn't
10958 support. The buffer is actually guaranteed to be one byte longer than
10959 <tt>length</tt>; the extra byte will always be zero, so it isn't
10960 necessary to make a copy of strings just to null terminate them.
10961
10962 In the following example, we retrieve the special target "TARGETS",
10963 which is a list of all targets into which the selection can be
10964 converted.
10965
10966 <tscreen><verb>
10967 /* example-start selection gettargets.c */
10968
10969 #include <gtk/gtk.h>
10970
10971 void selection_received (GtkWidget *widget, 
10972                          GtkSelectionData *selection_data, 
10973                          gpointer data);
10974
10975 /* Signal handler invoked when user clicks on the "Get Targets" button */
10976 void
10977 get_targets (GtkWidget *widget, gpointer data)
10978 {
10979   static GdkAtom targets_atom = GDK_NONE;
10980
10981   /* Get the atom corresponding to the string "TARGETS" */
10982   if (targets_atom == GDK_NONE)
10983     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
10984
10985   /* And request the "TARGETS" target for the primary selection */
10986   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
10987                          GDK_CURRENT_TIME);
10988 }
10989
10990 /* Signal handler called when the selections owner returns the data */
10991 void
10992 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
10993                     gpointer data)
10994 {
10995   GdkAtom *atoms;
10996   GList *item_list;
10997   int i;
10998
10999   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
11000   if (selection_data->length < 0)
11001     {
11002       g_print ("Selection retrieval failed\n");
11003       return;
11004     }
11005   /* Make sure we got the data in the expected form */
11006   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
11007     {
11008       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
11009       return;
11010     }
11011   
11012   /* Print out the atoms we received */
11013   atoms = (GdkAtom *)selection_data->data;
11014
11015   item_list = NULL;
11016   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
11017     {
11018       char *name;
11019       name = gdk_atom_name (atoms[i]);
11020       if (name != NULL)
11021         g_print ("%s\n",name);
11022       else
11023         g_print ("(bad atom)\n");
11024     }
11025
11026   return;
11027 }
11028
11029 int 
11030 main (int argc, char *argv[])
11031 {
11032   GtkWidget *window;
11033   GtkWidget *button;
11034   
11035   gtk_init (&amp;argc, &amp;argv);
11036
11037   /* Create the toplevel window */
11038
11039   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11040   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11041   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11042
11043   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11044                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11045
11046   /* Create a button the user can click to get targets */
11047
11048   button = gtk_button_new_with_label ("Get Targets");
11049   gtk_container_add (GTK_CONTAINER (window), button);
11050
11051   gtk_signal_connect (GTK_OBJECT(button), "clicked",
11052                       GTK_SIGNAL_FUNC (get_targets), NULL);
11053   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
11054                       GTK_SIGNAL_FUNC (selection_received), NULL);
11055
11056   gtk_widget_show (button);
11057   gtk_widget_show (window);
11058   
11059   gtk_main ();
11060   
11061   return 0;
11062 }
11063 /* example-end */
11064 </verb></tscreen>
11065
11066 <!-- ----------------------------------------------------------------- -->
11067 <sect1> Supplying the selection 
11068 <p>
11069 Supplying the selection is a bit more complicated. You must register 
11070 handlers that will be called when your selection is requested. For
11071 each selection/target pair you will handle, you make a call to:
11072
11073 <tscreen><verb>
11074 void gtk_selection_add_handler( GtkWidget            *widget, 
11075                                 GdkAtom               selection,
11076                                 GdkAtom               target,
11077                                 GtkSelectionFunction  function,
11078                                 GtkRemoveFunction     remove_func,
11079                                 gpointer              data );
11080 </verb></tscreen>
11081
11082 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
11083 this handler will manage.  <tt/remove_func/, if not
11084 NULL, will be called when the signal handler is removed. This is
11085 useful, for instance, for interpreted languages which need to
11086 keep track of a reference count for <tt/data/.
11087
11088 The callback function has the signature:
11089
11090 <tscreen><verb>
11091 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
11092                                       GtkSelectionData *selection_data,
11093                                       gpointer          data );
11094
11095 </verb></tscreen>
11096
11097 The GtkSelectionData is the same as above, but this time, we're
11098 responsible for filling in the fields <tt/type/, <tt/format/,
11099 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
11100 important here - the X server uses it to figure out whether the data
11101 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
11102 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
11103 function:
11104
11105 <tscreen><verb>
11106 void gtk_selection_data_set( GtkSelectionData *selection_data,
11107                              GdkAtom           type,
11108                              gint              format,
11109                              guchar           *data,
11110                              gint              length );
11111 </verb></tscreen>
11112
11113 This function takes care of properly making a copy of the data so that
11114 you don't have to worry about keeping it around. (You should not fill
11115 in the fields of the GtkSelectionData structure by hand.)
11116
11117 When prompted by the user, you claim ownership of the selection by
11118 calling:
11119
11120 <tscreen><verb>
11121 gint gtk_selection_owner_set( GtkWidget *widget,
11122                               GdkAtom    selection,
11123                               guint32    time );
11124 </verb></tscreen>
11125
11126 If another application claims ownership of the selection, you will
11127 receive a "selection_clear_event".
11128
11129 As an example of supplying the selection, the following program adds
11130 selection functionality to a toggle button. When the toggle button is
11131 depressed, the program claims the primary selection. The only target
11132 supported (aside from certain targets like "TARGETS" supplied by GTK
11133 itself), is the "STRING" target. When this target is requested, a
11134 string representation of the time is returned.
11135
11136 <tscreen><verb>
11137 /* example-start selection setselection.c */
11138
11139 #include <gtk/gtk.h>
11140 #include <time.h>
11141
11142 /* Callback when the user toggles the selection */
11143 void
11144 selection_toggled (GtkWidget *widget, gint *have_selection)
11145 {
11146   if (GTK_TOGGLE_BUTTON(widget)->active)
11147     {
11148       *have_selection = gtk_selection_owner_set (widget,
11149                                                  GDK_SELECTION_PRIMARY,
11150                                                  GDK_CURRENT_TIME);
11151       /* if claiming the selection failed, we return the button to
11152          the out state */
11153       if (!*have_selection)
11154         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11155     }
11156   else
11157     {
11158       if (*have_selection)
11159         {
11160           /* Before clearing the selection by setting the owner to NULL,
11161              we check if we are the actual owner */
11162           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
11163             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
11164                                      GDK_CURRENT_TIME);
11165           *have_selection = FALSE;
11166         }
11167     }
11168 }
11169
11170 /* Called when another application claims the selection */
11171 gint
11172 selection_clear (GtkWidget *widget, GdkEventSelection *event,
11173                  gint *have_selection)
11174 {
11175   *have_selection = FALSE;
11176   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11177
11178   return TRUE;
11179 }
11180
11181 /* Supplies the current time as the selection. */
11182 void
11183 selection_handle (GtkWidget *widget, 
11184                   GtkSelectionData *selection_data,
11185                   gpointer data)
11186 {
11187   gchar *timestr;
11188   time_t current_time;
11189
11190   current_time = time (NULL);
11191   timestr = asctime (localtime(&amp;current_time)); 
11192   /* When we return a single string, it should not be null terminated.
11193      That will be done for us */
11194
11195   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
11196                           8, timestr, strlen(timestr));
11197 }
11198
11199 int
11200 main (int argc, char *argv[])
11201 {
11202   GtkWidget *window;
11203
11204   GtkWidget *selection_button;
11205
11206   static int have_selection = FALSE;
11207   
11208   gtk_init (&amp;argc, &amp;argv);
11209
11210   /* Create the toplevel window */
11211
11212   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11213   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11214   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11215
11216   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11217                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11218
11219   /* Create a toggle button to act as the selection */
11220
11221   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
11222   gtk_container_add (GTK_CONTAINER (window), selection_button);
11223   gtk_widget_show (selection_button);
11224
11225   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
11226                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
11227   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
11228                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
11229
11230   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
11231                              GDK_SELECTION_TYPE_STRING,
11232                              selection_handle, NULL);
11233
11234   gtk_widget_show (selection_button);
11235   gtk_widget_show (window);
11236   
11237   gtk_main ();
11238   
11239   return 0;
11240 }
11241 /* example-end */
11242 </verb></tscreen>
11243
11244
11245 <!-- ***************************************************************** -->
11246 <sect>glib<label id="sec_glib">
11247 <!-- ***************************************************************** -->
11248 <p>
11249 glib is a lower-level library that provides many useful definitions
11250 and functions available for use when creating GDK and GTK
11251 applications. These include definitions for basic types and their
11252 limits, standard macros, type conversions, byte order, memory
11253 allocation, warnings and assertions, message logging, timers, string
11254 utilities, hook functions, a lexical scanner, dynamic loading of
11255 modules, and automatic string completion. A number of data structures
11256 (and their related operations) are also defined, including memory
11257 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
11258 (which can grow dynamically), string chunks (groups of strings),
11259 arrays (which can grow in size as elements are added), balanced binary
11260 trees, N-ary trees, quarks (a two-way association of a string and a
11261 unique integer identifier), keyed data lists (lists of data elements
11262 accessible by a string or integer id), relations and tuples (tables of
11263 data which can be indexed on any number of fields), and caches.
11264
11265 A summary of some of glib's capabilities follows; not every function,
11266 data structure, or operation is covered here.  For more complete
11267 information about the glib routines, see the glib documentation. One
11268 source of glib documentation is http://www.gtk.org/ <htmlurl
11269 url="http://www.gtk.org/" name="http://www.gtk.org/">.
11270
11271 If you are using a language other than C, you should consult your
11272 language's binding documentation. In some cases your language may
11273 have equivalent functionality built-in, while in other cases it may
11274 not.
11275
11276 <!-- ----------------------------------------------------------------- -->
11277 <sect1>Definitions
11278 <p>
11279 Definitions for the extremes of many of the standard types are:
11280
11281 <tscreen><verb>
11282 G_MINFLOAT
11283 G_MAXFLOAT
11284 G_MINDOUBLE
11285 G_MAXDOUBLE
11286 G_MINSHORT
11287 G_MAXSHORT
11288 G_MININT
11289 G_MAXINT
11290 G_MINLONG
11291 G_MAXLONG
11292 </verb></tscreen>
11293
11294 Also, the following typedefs. The ones left unspecified are dynamically set
11295 depending on the architecture. Remember to avoid counting on the size of a
11296 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
11297 bytes, but 4 on Intel 80x86 family CPUs.
11298
11299 <tscreen><verb>
11300 char   gchar;
11301 short  gshort;
11302 long   glong;
11303 int    gint;
11304 char   gboolean;
11305
11306 unsigned char   guchar;
11307 unsigned short  gushort;
11308 unsigned long   gulong;
11309 unsigned int    guint;
11310
11311 float   gfloat;
11312 double  gdouble;
11313 long double gldouble;
11314
11315 void* gpointer;
11316
11317 gint8
11318 guint8
11319 gint16
11320 guint16
11321 gint32
11322 guint32
11323 </verb></tscreen>
11324
11325 <!-- ----------------------------------------------------------------- -->
11326 <sect1>Doubly Linked Lists
11327 <p>
11328 The following functions are used to create, manage, and destroy
11329 standard doubly linked lists. Each element in the list contains a
11330 piece of data, together with pointers which link to the previous and
11331 next elements in the list. This enables easy movement in either
11332 direction through the list. The data item is of type "gpointer",
11333 which means the data can be a pointer to your real data or (through
11334 casting) a numeric value (but do not assume that int and gpointer have
11335 the same size!). These routines internally allocate list elements in
11336 blocks, which is more efficient than allocating elements individually.
11337
11338 There is no function to specifically create a list. Instead, simply
11339 create a variable of type GList* and set its value to NULL; NULL is
11340 considered to be the empty list.
11341
11342 To add elements to a list, use the g_list_append(), g_list_prepend(),
11343 g_list_insert(), or g_list_insert_sorted() routines. In all cases
11344 they accept a pointer to the beginning of the list, and return the
11345 (possibly changed) pointer to the beginning of the list. Thus, for
11346 all of the operations that add or remove elements, be sure to save the
11347 returned value!
11348
11349 <tscreen><verb>
11350 GList *g_list_append( GList    *list,
11351                       gpointer  data );
11352 </verb></tscreen>
11353
11354 This adds a new element (with value <tt/data/) onto the end of the
11355 list.
11356   
11357 <tscreen><verb>    
11358 GList *g_list_prepend( GList    *list,
11359                        gpointer  data );
11360 </verb></tscreen>
11361
11362 This adds a new element (with value <tt/data/) to the beginning of the
11363 list.
11364
11365 <tscreen><verb>         
11366 GList *g_list_insert( GList    *list,
11367                       gpointer  data,
11368                       gint      position );
11369
11370 </verb></tscreen>
11371
11372 This inserts a new element (with value data) into the list at the
11373 given position. If position is 0, this is just like g_list_prepend();
11374 if position is less than 0, this is just like g_list_append().
11375
11376 <tscreen><verb>
11377 GList *g_list_remove( GList    *list,
11378                       gpointer  data );
11379 </verb></tscreen>
11380
11381 This removes the element in the list with the value <tt/data/;
11382 if the element isn't there, the list is unchanged.
11383
11384 <tscreen><verb>
11385 void g_list_free( GList *list );
11386 </verb></tscreen>
11387
11388 This frees all of the memory used by a GList. If the list elements
11389 refer to dynamically-allocated memory, then they should be freed
11390 first.
11391
11392 There are many other glib functions that support doubly linked lists;
11393 see the glib documentation for more information.  Here are a few of
11394 the more useful functions' signatures:
11395
11396 <tscreen><verb>            
11397 GList *g_list_remove_link( GList *list,
11398                            GList *link );
11399
11400 GList *g_list_reverse( GList *list );
11401
11402 GList *g_list_nth( GList *list,
11403                    gint   n );
11404                            
11405 GList *g_list_find( GList    *list,
11406                     gpointer  data );
11407
11408 GList *g_list_last( GList *list );
11409
11410 GList *g_list_first( GList *list );
11411
11412 gint g_list_length( GList *list );
11413
11414 void g_list_foreach( GList    *list,
11415                      GFunc     func,
11416                      gpointer  user_data );
11417 </verb></tscreen>                                             
11418
11419 <!-- ----------------------------------------------------------------- -->
11420 <sect1>Singly Linked Lists
11421 <p>
11422 Many of the above functions for singly linked lists are identical to the
11423 above. Here is a list of some of their operations:
11424
11425 <tscreen><verb>
11426 GSList *g_slist_append( GSList   *list,
11427                         gpointer  data );
11428                 
11429 GSList *g_slist_prepend( GSList   *list,
11430                          gpointer  data );
11431                              
11432 GSList *g_slist_insert( GSList   *list,
11433                         gpointer  data,
11434                         gint      position );
11435                              
11436 GSList *g_slist_remove( GSList   *list,
11437                         gpointer  data );
11438                              
11439 GSList *g_slist_remove_link( GSList *list,
11440                              GSList *link );
11441                              
11442 GSList *g_slist_reverse( GSList *list );
11443
11444 GSList *g_slist_nth( GSList *list,
11445                      gint    n );
11446                              
11447 GSList *g_slist_find( GSList   *list,
11448                       gpointer  data );
11449                              
11450 GSList *g_slist_last( GSList *list );
11451
11452 gint g_slist_length( GSList *list );
11453
11454 void g_slist_foreach( GSList   *list,
11455                       GFunc     func,
11456                       gpointer  user_data );
11457         
11458 </verb></tscreen>
11459
11460 <!-- ----------------------------------------------------------------- -->
11461 <sect1>Memory Management
11462 <p>
11463 <tscreen><verb>
11464 gpointer g_malloc( gulong size );
11465 </verb></tscreen>
11466
11467 This is a replacement for malloc(). You do not need to check the return
11468 value as it is done for you in this function. If the memory allocation
11469 fails for whatever reasons, your applications will be terminated.
11470
11471 <tscreen><verb>
11472 gpointer g_malloc0( gulong size );
11473 </verb></tscreen>
11474
11475 Same as above, but zeroes the memory before returning a pointer to it.
11476
11477 <tscreen><verb>
11478 gpointer g_realloc( gpointer mem,
11479                     gulong   size );
11480 </verb></tscreen>
11481
11482 Relocates "size" bytes of memory starting at "mem".  Obviously, the
11483 memory should have been previously allocated.
11484
11485 <tscreen><verb>
11486 void g_free( gpointer mem );
11487 </verb></tscreen>
11488
11489 Frees memory. Easy one. If <tt/mem/ is NULL it simply returns.
11490
11491 <tscreen><verb>
11492 void g_mem_profile( void );
11493 </verb></tscreen>
11494
11495 Dumps a profile of used memory, but requires that you add #define
11496 MEM_PROFILE to the top of glib/gmem.c and re-make and make install.
11497
11498 <tscreen><verb>
11499 void g_mem_check( gpointer mem );
11500 </verb></tscreen>
11501
11502 Checks that a memory location is valid.  Requires you add #define
11503 MEM_CHECK to the top of gmem.c and re-make and make install.
11504
11505 <!-- ----------------------------------------------------------------- -->
11506 <sect1>Timers
11507 <p>
11508 Timer functions can be used to time operations (e.g. to see how much
11509 time has elapsed). First, you create a new timer with g_timer_new().
11510 You can then use g_timer_start() to start timing an operation,
11511 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
11512 determine the elapsed time.
11513
11514 <tscreen><verb>
11515 GTimer *g_timer_new( void );
11516
11517 void g_timer_destroy( GTimer *timer );
11518
11519 void g_timer_start( GTimer  *timer );
11520
11521 void g_timer_stop( GTimer  *timer );
11522
11523 void g_timer_reset( GTimer  *timer );
11524
11525 gdouble g_timer_elapsed( GTimer *timer,
11526                          gulong *microseconds );
11527 </verb></tscreen>                        
11528
11529 <!-- ----------------------------------------------------------------- -->
11530 <sect1>String Handling
11531 <p>
11532 glib defines a new type called a GString, which is similar to a
11533 standard C string but one that grows automatically. Its string data
11534 is null-terminated. What this gives you is protection from buffer
11535 overflow programming errors within your program. This is a very
11536 important feature, and hence I recommend that you make use of
11537 GStrings. GString itself has a simple public definition:
11538
11539 <tscreen><verb>
11540 struct GString 
11541 {
11542   gchar *str; /* Points to the string's current \0-terminated value. */
11543   gint len; /* Current length */
11544 };
11545 </verb></tscreen>
11546
11547 As you might expect, there are a number of operations you can do with
11548 a GString.
11549
11550 <tscreen><verb>
11551 GString *g_string_new( gchar *init );
11552 </verb></tscreen>
11553
11554 This constructs a GString, copying the string value of <tt/init/
11555 into the GString and returning a pointer to it. NULL may be given as
11556 the argument for an initially empty GString.
11557  
11558 <tscreen><verb>
11559
11560 void g_string_free( GString *string,
11561                     gint     free_segment );
11562 </verb></tscreen>
11563
11564 This frees the memory for the given GString. If <tt/free_segment/ is
11565 TRUE, then this also frees its character data.
11566
11567 <tscreen><verb>
11568                              
11569 GString *g_string_assign( GString     *lval,
11570                           const gchar *rval );
11571 </verb></tscreen>
11572
11573 This copies the characters from rval into lval, destroying the
11574 previous contents of lval. Note that lval will be lengthened as
11575 necessary to hold the string's contents, unlike the standard strcpy()
11576 function.
11577
11578 The rest of these functions should be relatively obvious (the _c
11579 versions accept a character instead of a string):
11580
11581 <tscreen><verb>              
11582 GString *g_string_truncate( GString *string,
11583                             gint     len );
11584                              
11585 GString *g_string_append( GString *string,
11586                           gchar   *val );
11587                             
11588 GString *g_string_append_c( GString *string,
11589                             gchar    c );
11590         
11591 GString *g_string_prepend( GString *string,
11592                            gchar   *val );
11593                              
11594 GString *g_string_prepend_c( GString *string,
11595                              gchar    c );
11596         
11597 void g_string_sprintf( GString *string,
11598                        gchar   *fmt,
11599                        ...);
11600         
11601 void g_string_sprintfa ( GString *string,
11602                          gchar   *fmt,
11603                          ... );
11604 </verb></tscreen>                                                         
11605
11606 <!-- ----------------------------------------------------------------- -->
11607 <sect1>Utility and Error Functions
11608 <p>
11609 <tscreen><verb>
11610 gchar *g_strdup( const gchar *str );
11611 </verb></tscreen>
11612
11613 Replacement strdup function.  Copies the original strings contents to
11614 newly allocated memory, and returns a pointer to it.
11615
11616 <tscreen><verb>
11617 gchar *g_strerror( gint errnum );
11618 </verb></tscreen>
11619
11620 I recommend using this for all error messages.  It's much nicer, and more
11621 portable than perror() or others.  The output is usually of the form:
11622
11623 <tscreen><verb>
11624 program name:function that failed:file or further description:strerror
11625 </verb></tscreen>
11626
11627 Here's an example of one such call used in our hello_world program:
11628
11629 <tscreen><verb>
11630 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
11631 </verb></tscreen>
11632
11633 <tscreen><verb>
11634 void g_error( gchar *format, ... );
11635 </verb></tscreen>
11636
11637 Prints an error message. The format is just like printf, but it
11638 prepends "** ERROR **: " to your message, and exits the program.  
11639 Use only for fatal errors.
11640
11641 <tscreen><verb>
11642 void g_warning( gchar *format, ... );
11643 </verb></tscreen>
11644
11645 Same as above, but prepends "** WARNING **: ", and does not exit the
11646 program.
11647
11648 <tscreen><verb>
11649 void g_message( gchar *format, ... );
11650 </verb></tscreen>
11651
11652 Prints "message: " prepended to the string you pass in.
11653
11654 <tscreen><verb>
11655 void g_print( gchar *format, ... );
11656 </verb></tscreen>
11657
11658 Replacement for printf().
11659
11660 And our last function:
11661
11662 <tscreen><verb>
11663 gchar *g_strsignal( gint signum );
11664 </verb></tscreen>
11665
11666 Prints out the name of the Unix system signal given the signal number.
11667 Useful in generic signal handling functions.
11668
11669 All of the above are more or less just stolen from glib.h.  If anyone cares
11670 to document any function, just send me an email!
11671
11672 <!-- ***************************************************************** -->
11673 <sect>GTK's rc Files
11674 <!-- ***************************************************************** -->
11675 <p>
11676 GTK has its own way of dealing with application defaults, by using rc
11677 files. These can be used to set the colors of just about any widget, and
11678 can also be used to tile pixmaps onto the background of some widgets.  
11679
11680 <!-- ----------------------------------------------------------------- -->
11681 <sect1>Functions For rc Files 
11682 <p>
11683 When your application starts, you should include a call to:
11684
11685 <tscreen><verb>
11686 void gtk_rc_parse( char *filename );
11687 </verb></tscreen>
11688
11689 Passing in the filename of your rc file. This will cause GTK to parse
11690 this file, and use the style settings for the widget types defined
11691 there.
11692
11693 If you wish to have a special set of widgets that can take on a
11694 different style from others, or any other logical division of widgets,
11695 use a call to:
11696
11697 <tscreen><verb>
11698 void gtk_widget_set_name( GtkWidget *widget,
11699                           gchar     *name );
11700 </verb></tscreen>
11701
11702 Passing your newly created widget as the first argument, and the name
11703 you wish to give it as the second. This will allow you to change the
11704 attributes of this widget by name through the rc file.
11705
11706 If we use a call something like this:
11707
11708 <tscreen><verb>
11709 button = gtk_button_new_with_label ("Special Button");
11710 gtk_widget_set_name (button, "special button");
11711 </verb></tscreen>
11712
11713 Then this button is given the name "special button" and may be addressed by
11714 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
11715
11716 The example rc file below, sets the properties of the main window, and lets
11717 all children of that main window inherit the style described by the "main
11718 button" style.  The code used in the application is:
11719
11720 <tscreen><verb>
11721 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11722 gtk_widget_set_name (window, "main window");
11723 </verb></tscreen>
11724
11725 And then the style is defined in the rc file using:
11726
11727 <tscreen><verb>
11728 widget "main window.*GtkButton*" style "main_button"
11729 </verb></tscreen>
11730
11731 Which sets all the GtkButton widgets in the "main window" to the
11732 "main_buttons" style as defined in the rc file.
11733
11734 As you can see, this is a fairly powerful and flexible system.  Use your
11735 imagination as to how best to take advantage of this.
11736
11737 <!-- ----------------------------------------------------------------- -->
11738 <sect1>GTK's rc File Format
11739 <p>
11740 The format of the GTK file is illustrated in the example below. This is
11741 the testgtkrc file from the GTK distribution, but I've added a
11742 few comments and things. You may wish to include this explanation
11743 your application to allow the user to fine tune his application.
11744
11745 There are several directives to change the attributes of a widget.
11746
11747 <itemize>
11748 <item>fg - Sets the foreground color of a widget.
11749 <item>bg - Sets the background color of a widget.
11750 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
11751 <item>font - Sets the font to be used with the given widget.
11752 </itemize>
11753
11754 In addition to this, there are several states a widget can be in, and you
11755 can set different colors, pixmaps and fonts for each state. These states are:
11756
11757 <itemize>
11758 <item>NORMAL - The normal state of a widget, without the mouse over top of
11759 it, and not being pressed etc.
11760 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
11761 using this state will be in effect.
11762 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
11763 the attributes assigned by this tag will be in effect.
11764 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
11765 activated, it will take these attributes.
11766 <item>SELECTED - When an object is selected, it takes these attributes.
11767 </itemize>
11768
11769 When using the "fg" and "bg" keywords to set the colors of widgets, the
11770 format is:
11771
11772 <tscreen><verb>
11773 fg[<STATE>] = { Red, Green, Blue }
11774 </verb></tscreen>
11775
11776 Where STATE is one of the above states (PRELIGHT, ACTIVE etc), and the Red,
11777 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
11778 white. They must be in float form, or they will register as 0, so a straight 
11779 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
11780 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
11781
11782 bg_pixmap is very similar to the above, except the colors are replaced by a
11783 filename.
11784
11785 pixmap_path is a list of paths separated by ":"'s.  These paths will be
11786 searched for any pixmap you specify.
11787
11788 The font directive is simply:
11789 <tscreen><verb>
11790 font = "<font name>"
11791 </verb></tscreen>
11792
11793 Where the only hard part is figuring out the font string. Using xfontsel or
11794 similar utility should help.
11795
11796 The "widget_class" sets the style of a class of widgets. These classes are
11797 listed in the widget overview on the class hierarchy.
11798
11799 The "widget" directive sets a specifically named set of widgets to a
11800 given style, overriding any style set for the given widget class.
11801 These widgets are registered inside the application using the
11802 gtk_widget_set_name() call. This allows you to specify the attributes of a
11803 widget on a per widget basis, rather than setting the attributes of an
11804 entire widget class. I urge you to document any of these special widgets so
11805 users may customize them.
11806
11807 When the keyword <tt>parent</> is used as an attribute, the widget will take on
11808 the attributes of its parent in the application.
11809
11810 When defining a style, you may assign the attributes of a previously defined
11811 style to this new one.
11812
11813 <tscreen><verb>
11814 style "main_button" = "button"
11815 {
11816   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11817   bg[PRELIGHT] = { 0.75, 0, 0 }
11818 }
11819 </verb></tscreen>
11820
11821 This example takes the "button" style, and creates a new "main_button" style
11822 simply by changing the font and prelight background color of the "button"
11823 style.
11824
11825 Of course, many of these attributes don't apply to all widgets. It's a
11826 simple matter of common sense really. Anything that could apply, should.
11827
11828 <!-- ----------------------------------------------------------------- -->
11829 <sect1>Example rc file
11830 <p>
11831
11832 <tscreen><verb>
11833 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
11834 #
11835 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
11836 #
11837 # style <name> [= <name>]
11838 # {
11839 #   <option>
11840 # }
11841 #
11842 # widget <widget_set> style <style_name>
11843 # widget_class <widget_class_set> style <style_name>
11844
11845
11846 # Here is a list of all the possible states.  Note that some do not apply to
11847 # certain widgets.
11848 #
11849 # NORMAL - The normal state of a widget, without the mouse over top of
11850 # it, and not being pressed etc.
11851 #
11852 # PRELIGHT - When the mouse is over top of the widget, colors defined
11853 # using this state will be in effect.
11854 #
11855 # ACTIVE - When the widget is pressed or clicked it will be active, and
11856 # the attributes assigned by this tag will be in effect.
11857 #
11858 # INSENSITIVE - When a widget is set insensitive, and cannot be
11859 # activated, it will take these attributes.
11860 #
11861 # SELECTED - When an object is selected, it takes these attributes.
11862 #
11863 # Given these states, we can set the attributes of the widgets in each of
11864 # these states using the following directives.
11865 #
11866 # fg - Sets the foreground color of a widget.
11867 # fg - Sets the background color of a widget.
11868 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
11869 # font - Sets the font to be used with the given widget.
11870 #
11871
11872 # This sets a style called "button".  The name is not really important, as
11873 # it is assigned to the actual widgets at the bottom of the file.
11874
11875 style "window"
11876 {
11877   #This sets the padding around the window to the pixmap specified.
11878   #bg_pixmap[<STATE>] = "<pixmap filename>"
11879   bg_pixmap[NORMAL] = "warning.xpm"
11880 }
11881
11882 style "scale"
11883 {
11884   #Sets the foreground color (font color) to red when in the "NORMAL"
11885   #state.
11886   
11887   fg[NORMAL] = { 1.0, 0, 0 }
11888   
11889   #Sets the background pixmap of this widget to that of its parent.
11890   bg_pixmap[NORMAL] = "<parent>"
11891 }
11892
11893 style "button"
11894 {
11895   # This shows all the possible states for a button.  The only one that
11896   # doesn't apply is the SELECTED state.
11897   
11898   fg[PRELIGHT] = { 0, 1.0, 1.0 }
11899   bg[PRELIGHT] = { 0, 0, 1.0 }
11900   bg[ACTIVE] = { 1.0, 0, 0 }
11901   fg[ACTIVE] = { 0, 1.0, 0 }
11902   bg[NORMAL] = { 1.0, 1.0, 0 }
11903   fg[NORMAL] = { .99, 0, .99 }
11904   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
11905   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
11906 }
11907
11908 # In this example, we inherit the attributes of the "button" style and then
11909 # override the font and background color when prelit to create a new
11910 # "main_button" style.
11911
11912 style "main_button" = "button"
11913 {
11914   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11915   bg[PRELIGHT] = { 0.75, 0, 0 }
11916 }
11917
11918 style "toggle_button" = "button"
11919 {
11920   fg[NORMAL] = { 1.0, 0, 0 }
11921   fg[ACTIVE] = { 1.0, 0, 0 }
11922   
11923   # This sets the background pixmap of the toggle_button to that of its
11924   # parent widget (as defined in the application).
11925   bg_pixmap[NORMAL] = "<parent>"
11926 }
11927
11928 style "text"
11929 {
11930   bg_pixmap[NORMAL] = "marble.xpm"
11931   fg[NORMAL] = { 1.0, 1.0, 1.0 }
11932 }
11933
11934 style "ruler"
11935 {
11936   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
11937 }
11938
11939 # pixmap_path "~/.pixmaps"
11940
11941 # These set the widget types to use the styles defined above.
11942 # The widget types are listed in the class hierarchy, but could probably be
11943 # just listed in this document for the users reference.
11944
11945 widget_class "GtkWindow" style "window"
11946 widget_class "GtkDialog" style "window"
11947 widget_class "GtkFileSelection" style "window"
11948 widget_class "*Gtk*Scale" style "scale"
11949 widget_class "*GtkCheckButton*" style "toggle_button"
11950 widget_class "*GtkRadioButton*" style "toggle_button"
11951 widget_class "*GtkButton*" style "button"
11952 widget_class "*Ruler" style "ruler"
11953 widget_class "*GtkText" style "text"
11954
11955 # This sets all the buttons that are children of the "main window" to
11956 # the main_button style.  These must be documented to be taken advantage of.
11957 widget "main window.*GtkButton*" style "main_button"
11958 </verb></tscreen>
11959
11960 <!-- ***************************************************************** -->
11961 <sect>Writing Your Own Widgets 
11962 <!-- ***************************************************************** -->
11963
11964 <!-- ----------------------------------------------------------------- -->
11965 <sect1> Overview
11966 <p>
11967 Although the GTK distribution comes with many types of widgets that
11968 should cover most basic needs, there may come a time when you need to
11969 create your own new widget type. Since GTK uses widget inheritance
11970 extensively, and there is already a widget that is close to what you want,
11971 it is often possible to make a useful new widget type in
11972 just a few lines of code. But before starting work on a new widget, check
11973 around first to make sure that someone has not already written
11974 it. This will prevent duplication of effort and keep the number of
11975 GTK widgets out there to a minimum, which will help keep both the code
11976 and the interface of different applications consistent. As a flip side
11977 to this, once you finish your widget, announce it to the world so
11978 other people can benefit. The best place to do this is probably the
11979 <tt>gtk-list</tt>.
11980
11981 Complete sources for the example widgets are available at the place you 
11982 got this tutorial, or from:
11983
11984 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
11985 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
11986
11987
11988 <!-- ----------------------------------------------------------------- -->
11989 <sect1> The Anatomy Of A Widget
11990 <p>
11991 In order to create a new widget, it is important to have an
11992 understanding of how GTK objects work. This section is just meant as a
11993 brief overview. See the reference documentation for the details. 
11994
11995 GTK widgets are implemented in an object oriented fashion. However,
11996 they are implemented in standard C. This greatly improves portability
11997 and stability over using current generation C++ compilers; however,
11998 it does mean that the widget writer has to pay attention to some of
11999 the implementation details. The information common to all instances of
12000 one class of widgets (e.g., to all Button widgets) is stored in the 
12001 <em>class structure</em>. There is only one copy of this in
12002 which is stored information about the class's signals
12003 (which act like virtual functions in C). To support inheritance, the
12004 first field in the class structure must be a copy of the parent's
12005 class structure. The declaration of the class structure of GtkButtton
12006 looks like:
12007
12008 <tscreen><verb>
12009 struct _GtkButtonClass
12010 {
12011   GtkContainerClass parent_class;
12012
12013   void (* pressed)  (GtkButton *button);
12014   void (* released) (GtkButton *button);
12015   void (* clicked)  (GtkButton *button);
12016   void (* enter)    (GtkButton *button);
12017   void (* leave)    (GtkButton *button);
12018 };
12019 </verb></tscreen>
12020
12021 When a button is treated as a container (for instance, when it is
12022 resized), its class structure can be cast to GtkContainerClass, and
12023 the relevant fields used to handle the signals.
12024
12025 There is also a structure for each widget that is created on a
12026 per-instance basis. This structure has fields to store information that
12027 is different for each instance of the widget. We'll call this
12028 structure the <em>object structure</em>. For the Button class, it looks
12029 like:
12030
12031 <tscreen><verb>
12032 struct _GtkButton
12033 {
12034   GtkContainer container;
12035
12036   GtkWidget *child;
12037
12038   guint in_button : 1;
12039   guint button_down : 1;
12040 };
12041 </verb></tscreen>
12042
12043 Note that, similar to the class structure, the first field is the
12044 object structure of the parent class, so that this structure can be
12045 cast to the parent class's object structure as needed.
12046
12047 <!-- ----------------------------------------------------------------- -->
12048 <sect1> Creating a Composite widget
12049
12050 <!-- ----------------------------------------------------------------- -->
12051 <sect2> Introduction
12052 <p>
12053 One type of widget that you may be interested in creating is a
12054 widget that is merely an aggregate of other GTK widgets. This type of
12055 widget does nothing that couldn't be done without creating new
12056 widgets, but provides a convenient way of packaging user interface
12057 elements for reuse. The FileSelection and ColorSelection widgets in
12058 the standard distribution are examples of this type of widget.
12059
12060 The example widget that we'll create in this section is the Tictactoe
12061 widget, a 3x3 array of toggle buttons which triggers a signal when all
12062 three buttons in a row, column, or on one of the diagonals are
12063 depressed. 
12064
12065 <!-- ----------------------------------------------------------------- -->
12066 <sect2> Choosing a parent class
12067 <p>
12068 The parent class for a composite widget is typically the container
12069 class that holds all of the elements of the composite widget. For
12070 example, the parent class of the FileSelection widget is the
12071 Dialog class. Since our buttons will be arranged in a table, it
12072 might seem natural to make our parent class the GtkTable
12073 class. Unfortunately, this turns out not to work. The creation of a
12074 widget is divided among two functions - a <tt/WIDGETNAME_new()/
12075 function that the user calls, and a <tt/WIDGETNAME_init()/ function
12076 which does the basic work of initializing the widget which is
12077 independent of the arguments passed to the <tt/_new()/
12078 function. Descendent widgets only call the <tt/_init/ function of
12079 their parent widget. But this division of labor doesn't work well for
12080 tables, which when created, need to know the number of rows and
12081 columns in the table. Unless we want to duplicate most of the
12082 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
12083 best avoid deriving it from GtkTable. For that reason, we derive it
12084 from GtkVBox instead, and stick our table inside the VBox.
12085
12086 <!-- ----------------------------------------------------------------- -->
12087 <sect2> The header file
12088 <p>
12089 Each widget class has a header file which declares the object and
12090 class structures for that widget, along with public functions. 
12091 A couple of features are worth pointing out. To prevent duplicate
12092 definitions, we wrap the entire header file in:
12093
12094 <tscreen><verb>
12095 #ifndef __TICTACTOE_H__
12096 #define __TICTACTOE_H__
12097 .
12098 .
12099 .
12100 #endif /* __TICTACTOE_H__ */
12101 </verb></tscreen>
12102
12103 And to keep C++ programs that include the header file happy, in:
12104
12105 <tscreen><verb>
12106 #ifdef __cplusplus
12107 extern "C" {
12108 #endif /* __cplusplus */
12109 .
12110 .
12111 .
12112 #ifdef __cplusplus
12113 }
12114 #endif /* __cplusplus */
12115 </verb></tscreen>
12116
12117 Along with the functions and structures, we declare three standard
12118 macros in our header file, <tt/TICTACTOE(obj)/,
12119 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
12120 pointer into a pointer to the object or class structure, and check
12121 if an object is a Tictactoe widget respectively.
12122
12123 Here is the complete header file:
12124
12125 <tscreen><verb>
12126 /* tictactoe.h */
12127
12128 #ifndef __TICTACTOE_H__
12129 #define __TICTACTOE_H__
12130
12131 #include <gdk/gdk.h>
12132 #include <gtk/gtkvbox.h>
12133
12134 #ifdef __cplusplus
12135 extern "C" {
12136 #endif /* __cplusplus */
12137
12138 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
12139 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
12140 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
12141
12142
12143 typedef struct _Tictactoe       Tictactoe;
12144 typedef struct _TictactoeClass  TictactoeClass;
12145
12146 struct _Tictactoe
12147 {
12148   GtkVBox vbox;
12149   
12150   GtkWidget *buttons[3][3];
12151 };
12152
12153 struct _TictactoeClass
12154 {
12155   GtkVBoxClass parent_class;
12156
12157   void (* tictactoe) (Tictactoe *ttt);
12158 };
12159
12160 guint          tictactoe_get_type        (void);
12161 GtkWidget*     tictactoe_new             (void);
12162 void           tictactoe_clear           (Tictactoe *ttt);
12163
12164 #ifdef __cplusplus
12165 }
12166 #endif /* __cplusplus */
12167
12168 #endif /* __TICTACTOE_H__ */
12169
12170 </verb></tscreen>
12171
12172 <!-- ----------------------------------------------------------------- -->
12173 <sect2> The <tt/_get_type()/ function.
12174 <p>
12175 We now continue on to the implementation of our widget. A core
12176 function for every widget is the function
12177 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
12178 GTK about the widget class, and gets an ID that uniquely identifies
12179 the widget class. Upon subsequent calls, it just returns the ID.
12180
12181 <tscreen><verb>
12182 guint
12183 tictactoe_get_type ()
12184 {
12185   static guint ttt_type = 0;
12186
12187   if (!ttt_type)
12188     {
12189       GtkTypeInfo ttt_info =
12190       {
12191         "Tictactoe",
12192         sizeof (Tictactoe),
12193         sizeof (TictactoeClass),
12194         (GtkClassInitFunc) tictactoe_class_init,
12195         (GtkObjectInitFunc) tictactoe_init,
12196         (GtkArgSetFunc) NULL,
12197         (GtkArgGetFunc) NULL
12198       };
12199
12200       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
12201     }
12202
12203   return ttt_type;
12204 }
12205 </verb></tscreen>
12206
12207 The GtkTypeInfo structure has the following definition:
12208
12209 <tscreen><verb>
12210 struct _GtkTypeInfo
12211 {
12212   gchar *type_name;
12213   guint object_size;
12214   guint class_size;
12215   GtkClassInitFunc class_init_func;
12216   GtkObjectInitFunc object_init_func;
12217   GtkArgSetFunc arg_set_func;
12218   GtkArgGetFunc arg_get_func;
12219 };
12220 </verb></tscreen>
12221
12222 The fields of this structure are pretty self-explanatory. We'll ignore
12223 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
12224 but as yet largely
12225 unimplemented, role in allowing widget options to be conveniently set
12226 from interpreted languages. Once GTK has a correctly filled in copy of
12227 this structure, it knows how to create objects of a particular widget
12228 type. 
12229
12230 <!-- ----------------------------------------------------------------- -->
12231 <sect2> The <tt/_class_init()/ function
12232 <p>
12233 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
12234 the widget's class structure, and sets up any signals for the
12235 class. For our Tictactoe widget it looks like:
12236
12237 <tscreen><verb>
12238
12239 enum {
12240   TICTACTOE_SIGNAL,
12241   LAST_SIGNAL
12242 };
12243
12244 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
12245
12246 static void
12247 tictactoe_class_init (TictactoeClass *class)
12248 {
12249   GtkObjectClass *object_class;
12250
12251   object_class = (GtkObjectClass*) class;
12252   
12253   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
12254                                          GTK_RUN_FIRST,
12255                                          object_class->type,
12256                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
12257                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
12258
12259
12260   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
12261
12262   class->tictactoe = NULL;
12263 }
12264 </verb></tscreen>
12265
12266 Our widget has just one signal, the <tt/tictactoe/ signal that is
12267 invoked when a row, column, or diagonal is completely filled in. Not
12268 every composite widget needs signals, so if you are reading this for
12269 the first time, you may want to skip to the next section now, as
12270 things are going to get a bit complicated.
12271
12272 The function:
12273
12274 <tscreen><verb>
12275 gint gtk_signal_new( const gchar         *name,
12276                      GtkSignalRunType     run_type,
12277                      GtkType              object_type,
12278                      gint                 function_offset,
12279                      GtkSignalMarshaller  marshaller,
12280                      GtkType              return_val,
12281                      guint                nparams,
12282                      ...);
12283 </verb></tscreen>
12284
12285 Creates a new signal. The parameters are:
12286
12287 <itemize>
12288 <item> <tt/name/: The name of the signal.
12289 <item> <tt/run_type/: Whether the default handler runs before or after
12290 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
12291 although there are other possibilities.
12292 <item> <tt/object_type/: The ID of the object that this signal applies
12293 to. (It will also apply to that objects descendents)
12294 <item> <tt/function_offset/: The offset within the class structure of
12295 a pointer to the default handler.
12296 <item> <tt/marshaller/: A function that is used to invoke the signal
12297 handler. For signal handlers that have no arguments other than the
12298 object that emitted the signal and user data, we can use the
12299 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
12300 <item> <tt/return_val/: The type of the return val.
12301 <item> <tt/nparams/: The number of parameters of the signal handler
12302 (other than the two default ones mentioned above)
12303 <item> <tt/.../: The types of the parameters.
12304 </itemize>
12305
12306 When specifying types, the <tt/GtkType/ enumeration is used:
12307
12308 <tscreen><verb>
12309 typedef enum
12310 {
12311   GTK_TYPE_INVALID,
12312   GTK_TYPE_NONE,
12313   GTK_TYPE_CHAR,
12314   GTK_TYPE_BOOL,
12315   GTK_TYPE_INT,
12316   GTK_TYPE_UINT,
12317   GTK_TYPE_LONG,
12318   GTK_TYPE_ULONG,
12319   GTK_TYPE_FLOAT,
12320   GTK_TYPE_DOUBLE,
12321   GTK_TYPE_STRING,
12322   GTK_TYPE_ENUM,
12323   GTK_TYPE_FLAGS,
12324   GTK_TYPE_BOXED,
12325   GTK_TYPE_FOREIGN,
12326   GTK_TYPE_CALLBACK,
12327   GTK_TYPE_ARGS,
12328
12329   GTK_TYPE_POINTER,
12330
12331   /* it'd be great if the next two could be removed eventually */
12332   GTK_TYPE_SIGNAL,
12333   GTK_TYPE_C_CALLBACK,
12334
12335   GTK_TYPE_OBJECT
12336
12337 } GtkFundamentalType;
12338 </verb></tscreen>
12339
12340 <tt/gtk_signal_new()/ returns a unique integer identifier for the
12341 signal, that we store in the <tt/tictactoe_signals/ array, which we
12342 index using an enumeration. (Conventionally, the enumeration elements
12343 are the signal name, uppercased, but here there would be a conflict
12344 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
12345 instead.
12346
12347 After creating our signals, we need to tell GTK to associate our
12348 signals with the Tictactoe class. We do that by calling
12349 <tt/gtk_object_class_add_signals()/. We then set the pointer which
12350 points to the default handler for the `tictactoe' signal to NULL,
12351 indicating that there is no default action.
12352
12353 <!-- ----------------------------------------------------------------- -->
12354 <sect2> The <tt/_init()/ function.
12355 <p>
12356 Each widget class also needs a function to initialize the object
12357 structure. Usually, this function has the fairly limited role of
12358 setting the fields of the structure to default values. For composite
12359 widgets, however, this function also creates the component widgets.
12360
12361 <tscreen><verb>
12362 static void
12363 tictactoe_init (Tictactoe *ttt)
12364 {
12365   GtkWidget *table;
12366   gint i,j;
12367   
12368   table = gtk_table_new (3, 3, TRUE);
12369   gtk_container_add (GTK_CONTAINER(ttt), table);
12370   gtk_widget_show (table);
12371
12372   for (i=0;i<3; i++)
12373     for (j=0;j<3; j++)
12374       {
12375         ttt->buttons[i][j] = gtk_toggle_button_new ();
12376         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
12377                                    i, i+1, j, j+1);
12378         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
12379                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
12380         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
12381         gtk_widget_show (ttt->buttons[i][j]);
12382       }
12383 }
12384 </verb></tscreen>
12385
12386 <!-- ----------------------------------------------------------------- -->
12387 <sect2> And the rest...
12388 <p>
12389 There is one more function that every widget (except for base widget
12390 types like GtkBin that cannot be instantiated) needs to have - the
12391 function that the user calls to create an object of that type. This is
12392 conventionally called <tt/WIDGETNAME_new()/. In some
12393 widgets, though not for the Tictactoe widgets, this function takes
12394 arguments, and does some setup based on the arguments. The other two
12395 functions are specific to the Tictactoe widget. 
12396
12397 <tt/tictactoe_clear()/ is a public function that resets all the
12398 buttons in the widget to the up position. Note the use of
12399 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
12400 button toggles from being triggered unnecessarily.
12401
12402 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
12403 user clicks on a button. It checks to see if there are any winning
12404 combinations that involve the toggled button, and if so, emits
12405 the "tictactoe" signal.
12406
12407 <tscreen><verb>  
12408 GtkWidget*
12409 tictactoe_new ()
12410 {
12411   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
12412 }
12413
12414 void           
12415 tictactoe_clear (Tictactoe *ttt)
12416 {
12417   int i,j;
12418
12419   for (i=0;i<3;i++)
12420     for (j=0;j<3;j++)
12421       {
12422         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12423         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
12424                                      FALSE);
12425         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12426       }
12427 }
12428
12429 static void
12430 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
12431 {
12432   int i,k;
12433
12434   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12435                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12436                              { 0, 1, 2 }, { 0, 1, 2 } };
12437   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12438                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12439                              { 0, 1, 2 }, { 2, 1, 0 } };
12440
12441   int success, found;
12442
12443   for (k=0; k<8; k++)
12444     {
12445       success = TRUE;
12446       found = FALSE;
12447
12448       for (i=0;i<3;i++)
12449         {
12450           success = success &amp;&amp; 
12451             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
12452           found = found ||
12453             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
12454         }
12455       
12456       if (success &amp;&amp; found)
12457         {
12458           gtk_signal_emit (GTK_OBJECT (ttt), 
12459                            tictactoe_signals[TICTACTOE_SIGNAL]);
12460           break;
12461         }
12462     }
12463 }
12464 </verb></tscreen>
12465
12466 And finally, an example program using our Tictactoe widget:
12467
12468 <tscreen><verb>
12469 #include <gtk/gtk.h>
12470 #include "tictactoe.h"
12471
12472 /* Invoked when a row, column or diagonal is completed */
12473 void
12474 win (GtkWidget *widget, gpointer data)
12475 {
12476   g_print ("Yay!\n");
12477   tictactoe_clear (TICTACTOE (widget));
12478 }
12479
12480 int 
12481 main (int argc, char *argv[])
12482 {
12483   GtkWidget *window;
12484   GtkWidget *ttt;
12485   
12486   gtk_init (&amp;argc, &amp;argv);
12487
12488   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12489   
12490   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
12491   
12492   gtk_signal_connect (GTK_OBJECT (window), "destroy",
12493                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
12494   
12495   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12496
12497   /* Create a new Tictactoe widget */
12498   ttt = tictactoe_new ();
12499   gtk_container_add (GTK_CONTAINER (window), ttt);
12500   gtk_widget_show (ttt);
12501
12502   /* And attach to its "tictactoe" signal */
12503   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
12504                       GTK_SIGNAL_FUNC (win), NULL);
12505
12506   gtk_widget_show (window);
12507   
12508   gtk_main ();
12509   
12510   return 0;
12511 }
12512
12513 </verb></tscreen>
12514
12515 <!-- ----------------------------------------------------------------- -->
12516 <sect1> Creating a widget from scratch.
12517
12518 <!-- ----------------------------------------------------------------- -->
12519 <sect2> Introduction
12520 <p>
12521 In this section, we'll learn more about how widgets display themselves
12522 on the screen and interact with events. As an example of this, we'll
12523 create an analog dial widget with a pointer that the user can drag to
12524 set the value.
12525
12526 <!-- ----------------------------------------------------------------- -->
12527 <sect2> Displaying a widget on the screen
12528 <p>
12529 There are several steps that are involved in displaying on the screen.
12530 After the widget is created with a call to <tt/WIDGETNAME_new()/,
12531 several more functions are needed:
12532
12533 <itemize>
12534 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
12535 window for the widget if it has one.
12536 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
12537 <tt/gtk_widget_show()/. It is responsible for making sure the widget
12538 is actually drawn on the screen (<em/mapped/). For a container class,
12539 it must also make calls to <tt/map()/> functions of any child widgets.
12540 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
12541 is called for the widget or one of its ancestors. It makes the actual
12542 calls to the drawing functions to draw the widget on the screen. For
12543 container widgets, this function must make calls to
12544 <tt/gtk_widget_draw()/ for its child widgets.
12545 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
12546 widget. It makes the necessary calls to the drawing functions to draw
12547 the exposed portion on the screen. For container widgets, this
12548 function must generate expose events for its child widgets which don't
12549 have their own windows. (If they have their own windows, then X will
12550 generate the necessary expose events)
12551 </itemize>
12552
12553 You might notice that the last two functions are quite similar - each
12554 is responsible for drawing the widget on the screen. In fact many
12555 types of widgets don't really care about the difference between the
12556 two. The default <tt/draw()/ function in the widget class simply
12557 generates a synthetic expose event for the redrawn area. However, some
12558 types of widgets can save work by distinguishing between the two
12559 functions. For instance, if a widget has multiple X windows, then
12560 since expose events identify the exposed window, it can redraw only
12561 the affected window, which is not possible for calls to <tt/draw()/.
12562
12563 Container widgets, even if they don't care about the difference for
12564 themselves, can't simply use the default <tt/draw()/ function because
12565 their child widgets might care about the difference. However,
12566 it would be wasteful to duplicate the drawing code between the two
12567 functions. The convention is that such widgets have a function called
12568 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
12569 widget, that is then called by the <tt/draw()/ and <tt/expose()/
12570 functions.
12571
12572 In our example approach, since the dial widget is not a container
12573 widget, and only has a single window, we can take the simplest
12574 approach and use the default <tt/draw()/ function and only implement
12575 an <tt/expose()/ function.
12576
12577 <!-- ----------------------------------------------------------------- -->
12578 <sect2> The origins of the Dial Widget
12579 <p>
12580 Just as all land animals are just variants on the first amphibian that
12581 crawled up out of the mud, Gtk widgets tend to start off as variants
12582 of some other, previously written widget.  Thus, although this section
12583 is entitled `Creating a Widget from Scratch', the Dial widget really
12584 began with the source code for the Range widget. This was picked as a
12585 starting point because it would be nice if our Dial had the same
12586 interface as the Scale widgets which are just specialized descendents
12587 of the Range widget. So, though the source code is presented below in
12588 finished form, it should not be implied that it was written, <em>deus
12589 ex machina</em> in this fashion. Also, if you aren't yet familiar with
12590 how scale widgets work from the application writer's point of view, it
12591 would be a good idea to look them over before continuing.
12592
12593 <!-- ----------------------------------------------------------------- -->
12594 <sect2> The Basics
12595 <p>
12596 Quite a bit of our widget should look pretty familiar from the
12597 Tictactoe widget. First, we have a header file:
12598
12599 <tscreen><verb>
12600 /* GTK - The GIMP Toolkit
12601  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
12602  *
12603  * This library is free software; you can redistribute it and/or
12604  * modify it under the terms of the GNU Library General Public
12605  * License as published by the Free Software Foundation; either
12606  * version 2 of the License, or (at your option) any later version.
12607  *
12608  * This library is distributed in the hope that it will be useful,
12609  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12610  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12611  * Library General Public License for more details.
12612  *
12613  * You should have received a copy of the GNU Library General Public
12614  * License along with this library; if not, write to the Free
12615  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12616  */
12617
12618 #ifndef __GTK_DIAL_H__
12619 #define __GTK_DIAL_H__
12620
12621 #include <gdk/gdk.h>
12622 #include <gtk/gtkadjustment.h>
12623 #include <gtk/gtkwidget.h>
12624
12625
12626 #ifdef __cplusplus
12627 extern "C" {
12628 #endif /* __cplusplus */
12629
12630
12631 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
12632 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
12633 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
12634
12635
12636 typedef struct _GtkDial        GtkDial;
12637 typedef struct _GtkDialClass   GtkDialClass;
12638
12639 struct _GtkDial
12640 {
12641   GtkWidget widget;
12642
12643   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
12644   guint policy : 2;
12645
12646   /* Button currently pressed or 0 if none */
12647   guint8 button;
12648
12649   /* Dimensions of dial components */
12650   gint radius;
12651   gint pointer_width;
12652
12653   /* ID of update timer, or 0 if none */
12654   guint32 timer;
12655
12656   /* Current angle */
12657   gfloat angle;
12658
12659   /* Old values from adjustment stored so we know when something changes */
12660   gfloat old_value;
12661   gfloat old_lower;
12662   gfloat old_upper;
12663
12664   /* The adjustment object that stores the data for this dial */
12665   GtkAdjustment *adjustment;
12666 };
12667
12668 struct _GtkDialClass
12669 {
12670   GtkWidgetClass parent_class;
12671 };
12672
12673
12674 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
12675 guint          gtk_dial_get_type               (void);
12676 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
12677 void           gtk_dial_set_update_policy      (GtkDial      *dial,
12678                                                 GtkUpdateType  policy);
12679
12680 void           gtk_dial_set_adjustment         (GtkDial      *dial,
12681                                                 GtkAdjustment *adjustment);
12682 #ifdef __cplusplus
12683 }
12684 #endif /* __cplusplus */
12685
12686
12687 #endif /* __GTK_DIAL_H__ */
12688 </verb></tscreen>
12689
12690 Since there is quite a bit more going on in this widget, than the last
12691 one, we have more fields in the data structure, but otherwise things
12692 are pretty similar.
12693
12694 Next, after including header files, and declaring a few constants,
12695 we have some functions to provide information about the widget
12696 and initialize it:
12697
12698 <tscreen><verb>
12699 #include <math.h>
12700 #include <stdio.h>
12701 #include <gtk/gtkmain.h>
12702 #include <gtk/gtksignal.h>
12703
12704 #include "gtkdial.h"
12705
12706 #define SCROLL_DELAY_LENGTH  300
12707 #define DIAL_DEFAULT_SIZE 100
12708
12709 /* Forward declarations */
12710
12711 [ omitted to save space ]
12712
12713 /* Local data */
12714
12715 static GtkWidgetClass *parent_class = NULL;
12716
12717 guint
12718 gtk_dial_get_type ()
12719 {
12720   static guint dial_type = 0;
12721
12722   if (!dial_type)
12723     {
12724       GtkTypeInfo dial_info =
12725       {
12726         "GtkDial",
12727         sizeof (GtkDial),
12728         sizeof (GtkDialClass),
12729         (GtkClassInitFunc) gtk_dial_class_init,
12730         (GtkObjectInitFunc) gtk_dial_init,
12731         (GtkArgSetFunc) NULL,
12732         (GtkArgGetFunc) NULL,
12733       };
12734
12735       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
12736     }
12737
12738   return dial_type;
12739 }
12740
12741 static void
12742 gtk_dial_class_init (GtkDialClass *class)
12743 {
12744   GtkObjectClass *object_class;
12745   GtkWidgetClass *widget_class;
12746
12747   object_class = (GtkObjectClass*) class;
12748   widget_class = (GtkWidgetClass*) class;
12749
12750   parent_class = gtk_type_class (gtk_widget_get_type ());
12751
12752   object_class->destroy = gtk_dial_destroy;
12753
12754   widget_class->realize = gtk_dial_realize;
12755   widget_class->expose_event = gtk_dial_expose;
12756   widget_class->size_request = gtk_dial_size_request;
12757   widget_class->size_allocate = gtk_dial_size_allocate;
12758   widget_class->button_press_event = gtk_dial_button_press;
12759   widget_class->button_release_event = gtk_dial_button_release;
12760   widget_class->motion_notify_event = gtk_dial_motion_notify;
12761 }
12762
12763 static void
12764 gtk_dial_init (GtkDial *dial)
12765 {
12766   dial->button = 0;
12767   dial->policy = GTK_UPDATE_CONTINUOUS;
12768   dial->timer = 0;
12769   dial->radius = 0;
12770   dial->pointer_width = 0;
12771   dial->angle = 0.0;
12772   dial->old_value = 0.0;
12773   dial->old_lower = 0.0;
12774   dial->old_upper = 0.0;
12775   dial->adjustment = NULL;
12776 }
12777
12778 GtkWidget*
12779 gtk_dial_new (GtkAdjustment *adjustment)
12780 {
12781   GtkDial *dial;
12782
12783   dial = gtk_type_new (gtk_dial_get_type ());
12784
12785   if (!adjustment)
12786     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
12787
12788   gtk_dial_set_adjustment (dial, adjustment);
12789
12790   return GTK_WIDGET (dial);
12791 }
12792
12793 static void
12794 gtk_dial_destroy (GtkObject *object)
12795 {
12796   GtkDial *dial;
12797
12798   g_return_if_fail (object != NULL);
12799   g_return_if_fail (GTK_IS_DIAL (object));
12800
12801   dial = GTK_DIAL (object);
12802
12803   if (dial->adjustment)
12804     gtk_object_unref (GTK_OBJECT (dial->adjustment));
12805
12806   if (GTK_OBJECT_CLASS (parent_class)->destroy)
12807     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
12808 }
12809 </verb></tscreen>
12810
12811 Note that this <tt/init()/ function does less than for the Tictactoe
12812 widget, since this is not a composite widget, and the <tt/new()/
12813 function does more, since it now has an argument. Also, note that when
12814 we store a pointer to the Adjustment object, we increment its
12815 reference count, (and correspondingly decrement when we no longer use
12816 it) so that GTK can keep track of when it can be safely destroyed.
12817
12818 <p>
12819 Also, there are a few function to manipulate the widget's options:
12820
12821 <tscreen><verb>
12822 GtkAdjustment*
12823 gtk_dial_get_adjustment (GtkDial *dial)
12824 {
12825   g_return_val_if_fail (dial != NULL, NULL);
12826   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
12827
12828   return dial->adjustment;
12829 }
12830
12831 void
12832 gtk_dial_set_update_policy (GtkDial      *dial,
12833                              GtkUpdateType  policy)
12834 {
12835   g_return_if_fail (dial != NULL);
12836   g_return_if_fail (GTK_IS_DIAL (dial));
12837
12838   dial->policy = policy;
12839 }
12840
12841 void
12842 gtk_dial_set_adjustment (GtkDial      *dial,
12843                           GtkAdjustment *adjustment)
12844 {
12845   g_return_if_fail (dial != NULL);
12846   g_return_if_fail (GTK_IS_DIAL (dial));
12847
12848   if (dial->adjustment)
12849     {
12850       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
12851       gtk_object_unref (GTK_OBJECT (dial->adjustment));
12852     }
12853
12854   dial->adjustment = adjustment;
12855   gtk_object_ref (GTK_OBJECT (dial->adjustment));
12856
12857   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
12858                       (GtkSignalFunc) gtk_dial_adjustment_changed,
12859                       (gpointer) dial);
12860   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
12861                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
12862                       (gpointer) dial);
12863
12864   dial->old_value = adjustment->value;
12865   dial->old_lower = adjustment->lower;
12866   dial->old_upper = adjustment->upper;
12867
12868   gtk_dial_update (dial);
12869 }
12870 </verb></tscreen>
12871
12872 <sect2> <tt/gtk_dial_realize()/
12873
12874 <p>
12875 Now we come to some new types of functions. First, we have a function
12876 that does the work of creating the X window. Notice that a mask is
12877 passed to the function <tt/gdk_window_new()/ which specifies which fields of
12878 the GdkWindowAttr structure actually have data in them (the remaining
12879 fields will be given default values). Also worth noting is the way the
12880 event mask of the widget is created. We call
12881 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
12882 has specified for this widget (with <tt/gtk_widget_set_events()/, and
12883 add the events that we are interested in ourselves.
12884
12885 <p>
12886 After creating the window, we set its style and background, and put a
12887 pointer to the widget in the user data field of the GdkWindow. This
12888 last step allows GTK to dispatch events for this window to the correct
12889 widget.
12890
12891 <tscreen><verb>
12892 static void
12893 gtk_dial_realize (GtkWidget *widget)
12894 {
12895   GtkDial *dial;
12896   GdkWindowAttr attributes;
12897   gint attributes_mask;
12898
12899   g_return_if_fail (widget != NULL);
12900   g_return_if_fail (GTK_IS_DIAL (widget));
12901
12902   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
12903   dial = GTK_DIAL (widget);
12904
12905   attributes.x = widget->allocation.x;
12906   attributes.y = widget->allocation.y;
12907   attributes.width = widget->allocation.width;
12908   attributes.height = widget->allocation.height;
12909   attributes.wclass = GDK_INPUT_OUTPUT;
12910   attributes.window_type = GDK_WINDOW_CHILD;
12911   attributes.event_mask = gtk_widget_get_events (widget) | 
12912     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
12913     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
12914     GDK_POINTER_MOTION_HINT_MASK;
12915   attributes.visual = gtk_widget_get_visual (widget);
12916   attributes.colormap = gtk_widget_get_colormap (widget);
12917
12918   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
12919   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
12920
12921   widget->style = gtk_style_attach (widget->style, widget->window);
12922
12923   gdk_window_set_user_data (widget->window, widget);
12924
12925   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
12926 }
12927 </verb></tscreen>
12928
12929 <sect2> Size negotiation
12930
12931 <p>
12932 Before the first time that the window containing a widget is
12933 displayed, and whenever the layout of the window changes, GTK asks
12934 each child widget for its desired size. This request is handled by the
12935 function, <tt/gtk_dial_size_request()/. Since our widget isn't a
12936 container widget, and has no real constraints on its size, we just
12937 return a reasonable default value.
12938
12939 <tscreen><verb>
12940 static void 
12941 gtk_dial_size_request (GtkWidget      *widget,
12942                        GtkRequisition *requisition)
12943 {
12944   requisition->width = DIAL_DEFAULT_SIZE;
12945   requisition->height = DIAL_DEFAULT_SIZE;
12946 }
12947 </verb></tscreen>
12948
12949 <p>
12950 After all the widgets have requested an ideal size, the layout of the
12951 window is computed and each child widget is notified of its actual
12952 size. Usually, this will at least as large as the requested size, but
12953 if for instance, the user has resized the window, it may occasionally
12954 be smaller than the requested size. The size notification is handled
12955 by the function <tt/gtk_dial_size_allocate()/. Notice that as well as
12956 computing the sizes of some component pieces for future use, this
12957 routine also does the grunt work of moving the widgets X window into
12958 the new position and size.
12959
12960 <tscreen><verb>
12961 static void
12962 gtk_dial_size_allocate (GtkWidget     *widget,
12963                         GtkAllocation *allocation)
12964 {
12965   GtkDial *dial;
12966
12967   g_return_if_fail (widget != NULL);
12968   g_return_if_fail (GTK_IS_DIAL (widget));
12969   g_return_if_fail (allocation != NULL);
12970
12971   widget->allocation = *allocation;
12972   if (GTK_WIDGET_REALIZED (widget))
12973     {
12974       dial = GTK_DIAL (widget);
12975
12976       gdk_window_move_resize (widget->window,
12977                               allocation->x, allocation->y,
12978                               allocation->width, allocation->height);
12979
12980       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
12981       dial->pointer_width = dial->radius / 5;
12982     }
12983 }
12984 </verb></tscreen>.
12985
12986 <!-- ----------------------------------------------------------------- -->
12987 <sect2> <tt/gtk_dial_expose()/
12988
12989 <p>
12990 As mentioned above, all the drawing of this widget is done in the
12991 handler for expose events. There's not much to remark on here except
12992 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
12993 three dimensional shading according to the colors stored in the
12994 widget's style.
12995
12996 <tscreen><verb>
12997 static gint
12998 gtk_dial_expose (GtkWidget      *widget,
12999                  GdkEventExpose *event)
13000 {
13001   GtkDial *dial;
13002   GdkPoint points[3];
13003   gdouble s,c;
13004   gdouble theta;
13005   gint xc, yc;
13006   gint tick_length;
13007   gint i;
13008
13009   g_return_val_if_fail (widget != NULL, FALSE);
13010   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13011   g_return_val_if_fail (event != NULL, FALSE);
13012
13013   if (event->count > 0)
13014     return FALSE;
13015   
13016   dial = GTK_DIAL (widget);
13017
13018   gdk_window_clear_area (widget->window,
13019                          0, 0,
13020                          widget->allocation.width,
13021                          widget->allocation.height);
13022
13023   xc = widget->allocation.width/2;
13024   yc = widget->allocation.height/2;
13025
13026   /* Draw ticks */
13027
13028   for (i=0; i<25; i++)
13029     {
13030       theta = (i*M_PI/18. - M_PI/6.);
13031       s = sin(theta);
13032       c = cos(theta);
13033
13034       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
13035       
13036       gdk_draw_line (widget->window,
13037                      widget->style->fg_gc[widget->state],
13038                      xc + c*(dial->radius - tick_length),
13039                      yc - s*(dial->radius - tick_length),
13040                      xc + c*dial->radius,
13041                      yc - s*dial->radius);
13042     }
13043
13044   /* Draw pointer */
13045
13046   s = sin(dial->angle);
13047   c = cos(dial->angle);
13048
13049
13050   points[0].x = xc + s*dial->pointer_width/2;
13051   points[0].y = yc + c*dial->pointer_width/2;
13052   points[1].x = xc + c*dial->radius;
13053   points[1].y = yc - s*dial->radius;
13054   points[2].x = xc - s*dial->pointer_width/2;
13055   points[2].y = yc - c*dial->pointer_width/2;
13056
13057   gtk_draw_polygon (widget->style,
13058                     widget->window,
13059                     GTK_STATE_NORMAL,
13060                     GTK_SHADOW_OUT,
13061                     points, 3,
13062                     TRUE);
13063   
13064   return FALSE;
13065 }
13066 </verb></tscreen>
13067
13068 <!-- ----------------------------------------------------------------- -->
13069 <sect2> Event handling
13070 <p>
13071 The rest of the widget's code handles various types of events, and
13072 isn't too different from what would be found in many GTK
13073 applications. Two types of events can occur - either the user can
13074 click on the widget with the mouse and drag to move the pointer, or
13075 the value of the Adjustment object can change due to some external
13076 circumstance. 
13077
13078 When the user clicks on the widget, we check to see if the click was
13079 appropriately near the pointer, and if so, store then button that the
13080 user clicked with in the <tt/button/ field of the widget
13081 structure, and grab all mouse events with a call to
13082 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
13083 value of the control to be recomputed (by the function
13084 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
13085 set, "value_changed" events are either generated instantly
13086 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
13087 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
13088 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
13089
13090 <tscreen><verb>
13091 static gint
13092 gtk_dial_button_press (GtkWidget      *widget,
13093                        GdkEventButton *event)
13094 {
13095   GtkDial *dial;
13096   gint dx, dy;
13097   double s, c;
13098   double d_parallel;
13099   double d_perpendicular;
13100
13101   g_return_val_if_fail (widget != NULL, FALSE);
13102   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13103   g_return_val_if_fail (event != NULL, FALSE);
13104
13105   dial = GTK_DIAL (widget);
13106
13107   /* Determine if button press was within pointer region - we 
13108      do this by computing the parallel and perpendicular distance of
13109      the point where the mouse was pressed from the line passing through
13110      the pointer */
13111   
13112   dx = event->x - widget->allocation.width / 2;
13113   dy = widget->allocation.height / 2 - event->y;
13114   
13115   s = sin(dial->angle);
13116   c = cos(dial->angle);
13117   
13118   d_parallel = s*dy + c*dx;
13119   d_perpendicular = fabs(s*dx - c*dy);
13120   
13121   if (!dial->button &&
13122       (d_perpendicular < dial->pointer_width/2) &&
13123       (d_parallel > - dial->pointer_width))
13124     {
13125       gtk_grab_add (widget);
13126
13127       dial->button = event->button;
13128
13129       gtk_dial_update_mouse (dial, event->x, event->y);
13130     }
13131
13132   return FALSE;
13133 }
13134
13135 static gint
13136 gtk_dial_button_release (GtkWidget      *widget,
13137                           GdkEventButton *event)
13138 {
13139   GtkDial *dial;
13140
13141   g_return_val_if_fail (widget != NULL, FALSE);
13142   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13143   g_return_val_if_fail (event != NULL, FALSE);
13144
13145   dial = GTK_DIAL (widget);
13146
13147   if (dial->button == event->button)
13148     {
13149       gtk_grab_remove (widget);
13150
13151       dial->button = 0;
13152
13153       if (dial->policy == GTK_UPDATE_DELAYED)
13154         gtk_timeout_remove (dial->timer);
13155       
13156       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
13157           (dial->old_value != dial->adjustment->value))
13158         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13159     }
13160
13161   return FALSE;
13162 }
13163
13164 static gint
13165 gtk_dial_motion_notify (GtkWidget      *widget,
13166                          GdkEventMotion *event)
13167 {
13168   GtkDial *dial;
13169   GdkModifierType mods;
13170   gint x, y, mask;
13171
13172   g_return_val_if_fail (widget != NULL, FALSE);
13173   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13174   g_return_val_if_fail (event != NULL, FALSE);
13175
13176   dial = GTK_DIAL (widget);
13177
13178   if (dial->button != 0)
13179     {
13180       x = event->x;
13181       y = event->y;
13182
13183       if (event->is_hint || (event->window != widget->window))
13184         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
13185
13186       switch (dial->button)
13187         {
13188         case 1:
13189           mask = GDK_BUTTON1_MASK;
13190           break;
13191         case 2:
13192           mask = GDK_BUTTON2_MASK;
13193           break;
13194         case 3:
13195           mask = GDK_BUTTON3_MASK;
13196           break;
13197         default:
13198           mask = 0;
13199           break;
13200         }
13201
13202       if (mods & mask)
13203         gtk_dial_update_mouse (dial, x,y);
13204     }
13205
13206   return FALSE;
13207 }
13208
13209 static gint
13210 gtk_dial_timer (GtkDial *dial)
13211 {
13212   g_return_val_if_fail (dial != NULL, FALSE);
13213   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
13214
13215   if (dial->policy == GTK_UPDATE_DELAYED)
13216     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13217
13218   return FALSE;
13219 }
13220
13221 static void
13222 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
13223 {
13224   gint xc, yc;
13225   gfloat old_value;
13226
13227   g_return_if_fail (dial != NULL);
13228   g_return_if_fail (GTK_IS_DIAL (dial));
13229
13230   xc = GTK_WIDGET(dial)->allocation.width / 2;
13231   yc = GTK_WIDGET(dial)->allocation.height / 2;
13232
13233   old_value = dial->adjustment->value;
13234   dial->angle = atan2(yc-y, x-xc);
13235
13236   if (dial->angle < -M_PI/2.)
13237     dial->angle += 2*M_PI;
13238
13239   if (dial->angle < -M_PI/6)
13240     dial->angle = -M_PI/6;
13241
13242   if (dial->angle > 7.*M_PI/6.)
13243     dial->angle = 7.*M_PI/6.;
13244
13245   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
13246     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
13247
13248   if (dial->adjustment->value != old_value)
13249     {
13250       if (dial->policy == GTK_UPDATE_CONTINUOUS)
13251         {
13252           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13253         }
13254       else
13255         {
13256           gtk_widget_draw (GTK_WIDGET(dial), NULL);
13257
13258           if (dial->policy == GTK_UPDATE_DELAYED)
13259             {
13260               if (dial->timer)
13261                 gtk_timeout_remove (dial->timer);
13262
13263               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
13264                                              (GtkFunction) gtk_dial_timer,
13265                                              (gpointer) dial);
13266             }
13267         }
13268     }
13269 }
13270 </verb></tscreen>
13271
13272 Changes to the Adjustment by external means are communicated to our
13273 widget by the `changed' and `value_changed' signals. The handlers
13274 for these functions call <tt/gtk_dial_update()/ to validate the
13275 arguments, compute the new pointer angle, and redraw the widget (by
13276 calling <tt/gtk_widget_draw()/).
13277
13278 <tscreen><verb>
13279 static void
13280 gtk_dial_update (GtkDial *dial)
13281 {
13282   gfloat new_value;
13283   
13284   g_return_if_fail (dial != NULL);
13285   g_return_if_fail (GTK_IS_DIAL (dial));
13286
13287   new_value = dial->adjustment->value;
13288   
13289   if (new_value < dial->adjustment->lower)
13290     new_value = dial->adjustment->lower;
13291
13292   if (new_value > dial->adjustment->upper)
13293     new_value = dial->adjustment->upper;
13294
13295   if (new_value != dial->adjustment->value)
13296     {
13297       dial->adjustment->value = new_value;
13298       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13299     }
13300
13301   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
13302     (dial->adjustment->upper - dial->adjustment->lower);
13303
13304   gtk_widget_draw (GTK_WIDGET(dial), NULL);
13305 }
13306
13307 static void
13308 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
13309                               gpointer       data)
13310 {
13311   GtkDial *dial;
13312
13313   g_return_if_fail (adjustment != NULL);
13314   g_return_if_fail (data != NULL);
13315
13316   dial = GTK_DIAL (data);
13317
13318   if ((dial->old_value != adjustment->value) ||
13319       (dial->old_lower != adjustment->lower) ||
13320       (dial->old_upper != adjustment->upper))
13321     {
13322       gtk_dial_update (dial);
13323
13324       dial->old_value = adjustment->value;
13325       dial->old_lower = adjustment->lower;
13326       dial->old_upper = adjustment->upper;
13327     }
13328 }
13329
13330 static void
13331 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
13332                                     gpointer       data)
13333 {
13334   GtkDial *dial;
13335
13336   g_return_if_fail (adjustment != NULL);
13337   g_return_if_fail (data != NULL);
13338
13339   dial = GTK_DIAL (data);
13340
13341   if (dial->old_value != adjustment->value)
13342     {
13343       gtk_dial_update (dial);
13344
13345       dial->old_value = adjustment->value;
13346     }
13347 }
13348 </verb></tscreen>
13349
13350 <!-- ----------------------------------------------------------------- -->
13351 <sect2> Possible Enhancements
13352 <p>
13353 The Dial widget as we've described it so far runs about 670 lines of
13354 code. Although that might sound like a fair bit, we've really
13355 accomplished quite a bit with that much code, especially since much of
13356 that length is headers and boilerplate. However, there are quite a few
13357 more enhancements that could be made to this widget:
13358
13359 <itemize>
13360 <item> If you try this widget out, you'll find that there is some
13361 flashing as the pointer is dragged around. This is because the entire
13362 widget is erased every time the pointer is moved before being
13363 redrawn. Often, the best way to handle this problem is to draw to an
13364 offscreen pixmap, then copy the final results onto the screen in one
13365 step. (The ProgressBar widget draws itself in this fashion.)
13366
13367 <item> The user should be able to use the up and down arrow keys to
13368 increase and decrease the value.
13369
13370 <item> It would be nice if the widget had buttons to increase and
13371 decrease the value in small or large steps. Although it would be
13372 possible to use embedded Button widgets for this, we would also like
13373 the buttons to auto-repeat when held down, as the arrows on a
13374 scrollbar do. Most of the code to implement this type of behavior can
13375 be found in the GtkRange widget.
13376
13377 <item> The Dial widget could be made into a container widget with a
13378 single child widget positioned at the bottom between the buttons
13379 mentioned above. The user could then add their choice of a label or
13380 entry widget to display the current value of the dial.
13381
13382 </itemize>
13383
13384 <!-- ----------------------------------------------------------------- -->
13385 <sect1> Learning More
13386
13387 <p>
13388 Only a small part of the many details involved in creating widgets
13389 could be described above. If you want to write your own widgets, the
13390 best source of examples is the GTK source itself. Ask yourself some
13391 questions about the widget you want to write: is it a Container
13392 widget? does it have its own window? is it a modification of an
13393 existing widget? Then find a similar widget, and start making changes.
13394 Good luck!
13395
13396 <!-- ***************************************************************** -->
13397 <sect>Scribble, A Simple Example Drawing Program
13398 <!-- ***************************************************************** -->
13399
13400 <!-- ----------------------------------------------------------------- -->
13401 <sect1> Overview
13402 <p>
13403 In this section, we will build a simple drawing program. In the
13404 process, we will examine how to handle mouse events, how to draw in a
13405 window, and how to do drawing better by using a backing pixmap. After
13406 creating the simple drawing program, we will extend it by adding
13407 support for XInput devices, such as drawing tablets. GTK provides
13408 support routines which makes getting extended information, such as
13409 pressure and tilt, from such devices quite easy.
13410
13411 <!-- ----------------------------------------------------------------- -->
13412 <sect1> Event Handling
13413 <p>
13414 The GTK signals we have already discussed are for high-level actions,
13415 such as a menu item being selected. However, sometimes it is useful to
13416 learn about lower-level occurrences, such as the mouse being moved, or
13417 a key being pressed. There are also GTK signals corresponding to these
13418 low-level <em>events</em>. The handlers for these signals have an
13419 extra parameter which is a pointer to a structure containing
13420 information about the event. For instance, motion events handlers are
13421 passed a pointer to a GdkEventMotion structure which looks (in part)
13422 like:
13423
13424 <tscreen><verb>
13425 struct _GdkEventMotion
13426 {
13427   GdkEventType type;
13428   GdkWindow *window;
13429   guint32 time;
13430   gdouble x;
13431   gdouble y;
13432   ...
13433   guint state;
13434   ...
13435 };
13436 </verb></tscreen>
13437
13438 <tt/type/ will be set to the event type, in this case
13439 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
13440 occurred. <tt/x/ and <tt/y/ give the coordinates of the event,
13441 and <tt/state/ specifies the modifier state when the event
13442 occurred (that is, it specifies which modifier keys and mouse buttons
13443 were pressed.) It is the bitwise OR of some of the following:
13444
13445 <tscreen><verb>
13446 GDK_SHIFT_MASK  
13447 GDK_LOCK_MASK   
13448 GDK_CONTROL_MASK
13449 GDK_MOD1_MASK   
13450 GDK_MOD2_MASK   
13451 GDK_MOD3_MASK   
13452 GDK_MOD4_MASK   
13453 GDK_MOD5_MASK   
13454 GDK_BUTTON1_MASK
13455 GDK_BUTTON2_MASK
13456 GDK_BUTTON3_MASK
13457 GDK_BUTTON4_MASK
13458 GDK_BUTTON5_MASK
13459 </verb></tscreen>
13460
13461 As for other signals, to determine what happens when an event occurs
13462 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
13463 know which events we want to be notified about. To do this, we call
13464 the function:
13465
13466 <tscreen><verb>
13467 void gtk_widget_set_events (GtkWidget *widget,
13468                             gint      events);
13469 </verb></tscreen>
13470
13471 The second field specifies the events we are interested in. It
13472 is the bitwise OR of constants that specify different types
13473 of events. For future reference the event types are:
13474
13475 <tscreen><verb>
13476 GDK_EXPOSURE_MASK
13477 GDK_POINTER_MOTION_MASK
13478 GDK_POINTER_MOTION_HINT_MASK
13479 GDK_BUTTON_MOTION_MASK     
13480 GDK_BUTTON1_MOTION_MASK    
13481 GDK_BUTTON2_MOTION_MASK    
13482 GDK_BUTTON3_MOTION_MASK    
13483 GDK_BUTTON_PRESS_MASK      
13484 GDK_BUTTON_RELEASE_MASK    
13485 GDK_KEY_PRESS_MASK         
13486 GDK_KEY_RELEASE_MASK       
13487 GDK_ENTER_NOTIFY_MASK      
13488 GDK_LEAVE_NOTIFY_MASK      
13489 GDK_FOCUS_CHANGE_MASK      
13490 GDK_STRUCTURE_MASK         
13491 GDK_PROPERTY_CHANGE_MASK   
13492 GDK_PROXIMITY_IN_MASK      
13493 GDK_PROXIMITY_OUT_MASK     
13494 </verb></tscreen>
13495
13496 There are a few subtle points that have to be observed when calling
13497 <tt/gtk_widget_set_events()/. First, it must be called before the X window
13498 for a GTK widget is created. In practical terms, this means you
13499 should call it immediately after creating the widget. Second, the
13500 widget must have an associated X window. For efficiency, many widget
13501 types do not have their own window, but draw in their parent's window.
13502 These widgets are:
13503
13504 <tscreen><verb>
13505 GtkAlignment
13506 GtkArrow
13507 GtkBin
13508 GtkBox
13509 GtkImage
13510 GtkItem
13511 GtkLabel
13512 GtkPixmap
13513 GtkScrolledWindow
13514 GtkSeparator
13515 GtkTable
13516 GtkAspectFrame
13517 GtkFrame
13518 GtkVBox
13519 GtkHBox
13520 GtkVSeparator
13521 GtkHSeparator
13522 </verb></tscreen>
13523
13524 To capture events for these widgets, you need to use an EventBox
13525 widget. See the section on the <ref id="sec_EventBox"
13526 name="EventBox"> widget for details.
13527
13528 For our drawing program, we want to know when the mouse button is
13529 pressed and when the mouse is moved, so we specify
13530 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
13531 want to know when we need to redraw our window, so we specify
13532 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
13533 Configure event when our window size changes, we don't have to specify
13534 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
13535 automatically specified for all windows.
13536
13537 It turns out, however, that there is a problem with just specifying
13538 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
13539 motion event to the event queue every time the user moves the mouse.
13540 Imagine that it takes us 0.1 seconds to handle a motion event, but the
13541 X server queues a new motion event every 0.05 seconds. We will soon
13542 get way behind the users drawing. If the user draws for 5 seconds,
13543 it will take us another 5 seconds to catch up after they release 
13544 the mouse button! What we would like is to only get one motion
13545 event for each event we process. The way to do this is to 
13546 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
13547
13548 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
13549 us a motion event the first time the pointer moves after entering
13550 our window, or after a button press or release event. Subsequent 
13551 motion events will be suppressed until we explicitly ask for
13552 the position of the pointer using the function:
13553
13554 <tscreen><verb>
13555 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
13556                                           gint            *x,
13557                                           gint            *y,
13558                                           GdkModifierType *mask);
13559 </verb></tscreen>
13560
13561 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
13562 has a simpler interface, but turns out not to be very useful, since
13563 it only retrieves the position of the mouse, not whether the buttons
13564 are pressed.)
13565
13566 The code to set the events for our window then looks like:
13567
13568 <tscreen><verb>
13569   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
13570                       (GtkSignalFunc) expose_event, NULL);
13571   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
13572                       (GtkSignalFunc) configure_event, NULL);
13573   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
13574                       (GtkSignalFunc) motion_notify_event, NULL);
13575   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
13576                       (GtkSignalFunc) button_press_event, NULL);
13577
13578   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
13579                          | GDK_LEAVE_NOTIFY_MASK
13580                          | GDK_BUTTON_PRESS_MASK
13581                          | GDK_POINTER_MOTION_MASK
13582                          | GDK_POINTER_MOTION_HINT_MASK);
13583 </verb></tscreen>
13584
13585 We'll save the "expose_event" and "configure_event" handlers for
13586 later. The "motion_notify_event" and "button_press_event" handlers
13587 pretty simple:
13588
13589 <tscreen><verb>
13590 static gint
13591 button_press_event (GtkWidget *widget, GdkEventButton *event)
13592 {
13593   if (event->button == 1 &amp;&amp; pixmap != NULL)
13594       draw_brush (widget, event->x, event->y);
13595
13596   return TRUE;
13597 }
13598
13599 static gint
13600 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13601 {
13602   int x, y;
13603   GdkModifierType state;
13604
13605   if (event->is_hint)
13606     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
13607   else
13608     {
13609       x = event->x;
13610       y = event->y;
13611       state = event->state;
13612     }
13613     
13614   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13615     draw_brush (widget, x, y);
13616   
13617   return TRUE;
13618 }
13619 </verb></tscreen>
13620
13621 <!-- ----------------------------------------------------------------- -->
13622 <sect1> The DrawingArea Widget, And Drawing
13623 <p>
13624 We know turn to the process of drawing on the screen. The 
13625 widget we use for this is the DrawingArea widget. A drawing area
13626 widget is essentially an X window and nothing more. It is a blank
13627 canvas in which we can draw whatever we like. A drawing area
13628 is created using the call:
13629
13630 <tscreen><verb>
13631 GtkWidget* gtk_drawing_area_new        (void);
13632 </verb></tscreen>
13633
13634 A default size for the widget can be specified by calling:
13635
13636 <tscreen><verb>
13637 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
13638                                         gint                 width,
13639                                         gint                 height);
13640 </verb></tscreen>
13641
13642 This default size can be overridden, as is true for all widgets,
13643 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
13644 be overridden if the user manually resizes the the window containing
13645 the drawing area.
13646
13647 It should be noted that when we create a DrawingArea widget, we are,
13648 <em>completely</em> responsible for drawing the contents. If our
13649 window is obscured then uncovered, we get an exposure event and must
13650 redraw what was previously hidden.
13651
13652 Having to remember everything that was drawn on the screen so we
13653 can properly redraw it can, to say the least, be a nuisance. In
13654 addition, it can be visually distracting if portions of the
13655 window are cleared, then redrawn step by step. The solution to
13656 this problem is to use an offscreen <em>backing pixmap</em>.
13657 Instead of drawing directly to the screen, we draw to an image
13658 stored in server memory but not displayed, then when the image
13659 changes or new portions of the image are displayed, we copy the
13660 relevant portions onto the screen.
13661
13662 To create an offscreen pixmap, we call the function:
13663
13664 <tscreen><verb>
13665 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
13666                                          gint        width,
13667                                          gint        height,
13668                                          gint        depth);
13669 </verb></tscreen>
13670
13671 The <tt>window</tt> parameter specifies a GDK window that this pixmap
13672 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
13673 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
13674 depth</em>, that is the number of bits per pixel, for the new window.
13675 If the depth is specified as <tt>-1</tt>, it will match the depth
13676 of <tt>window</tt>.
13677
13678 We create the pixmap in our "configure_event" handler. This event
13679 is generated whenever the window changes size, including when it
13680 is originally created.
13681
13682 <tscreen><verb>
13683 /* Backing pixmap for drawing area */
13684 static GdkPixmap *pixmap = NULL;
13685
13686 /* Create a new backing pixmap of the appropriate size */
13687 static gint
13688 configure_event (GtkWidget *widget, GdkEventConfigure *event)
13689 {
13690   if (pixmap)
13691     gdk_pixmap_unref(pixmap);
13692
13693   pixmap = gdk_pixmap_new(widget->window,
13694                           widget->allocation.width,
13695                           widget->allocation.height,
13696                           -1);
13697   gdk_draw_rectangle (pixmap,
13698                       widget->style->white_gc,
13699                       TRUE,
13700                       0, 0,
13701                       widget->allocation.width,
13702                       widget->allocation.height);
13703
13704   return TRUE;
13705 }
13706 </verb></tscreen>
13707
13708 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
13709 initially to white. We'll say more about that in a moment.
13710
13711 Our exposure event handler then simply copies the relevant portion
13712 of the pixmap onto the screen (we determine the area we need
13713 to redraw by using the event->area field of the exposure event):
13714
13715 <tscreen><verb>
13716 /* Redraw the screen from the backing pixmap */
13717 static gint
13718 expose_event (GtkWidget *widget, GdkEventExpose *event)
13719 {
13720   gdk_draw_pixmap(widget->window,
13721                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
13722                   pixmap,
13723                   event->area.x, event->area.y,
13724                   event->area.x, event->area.y,
13725                   event->area.width, event->area.height);
13726
13727   return FALSE;
13728 }
13729 </verb></tscreen>
13730
13731 We've now seen how to keep the screen up to date with our pixmap, but
13732 how do we actually draw interesting stuff on our pixmap?  There are a
13733 large number of calls in GTK's GDK library for drawing on
13734 <em>drawables</em>. A drawable is simply something that can be drawn
13735 upon. It can be a window, a pixmap, or a bitmap (a black and white
13736 image).  We've already seen two such calls above,
13737 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
13738 complete list is:
13739
13740 <tscreen><verb>
13741 gdk_draw_line ()
13742 gdk_draw_rectangle ()
13743 gdk_draw_arc ()
13744 gdk_draw_polygon ()
13745 gdk_draw_string ()
13746 gdk_draw_text ()
13747 gdk_draw_pixmap ()
13748 gdk_draw_bitmap ()
13749 gdk_draw_image ()
13750 gdk_draw_points ()
13751 gdk_draw_segments ()
13752 </verb></tscreen>
13753
13754 See the reference documentation or the header file
13755 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
13756 These functions all share the same first two arguments. The first
13757 argument is the drawable to draw upon, the second argument is a
13758 <em>graphics context</em> (GC). 
13759
13760 A graphics context encapsulates information about things such as
13761 foreground and background color and line width. GDK has a full set of
13762 functions for creating and modifying graphics contexts, but to keep
13763 things simple we'll just use predefined graphics contexts. Each widget
13764 has an associated style. (Which can be modified in a gtkrc file, see
13765 the section GTK's rc file.) This, among other things, stores a number
13766 of graphics contexts. Some examples of accessing these graphics
13767 contexts are:
13768
13769 <tscreen><verb>
13770 widget->style->white_gc
13771 widget->style->black_gc
13772 widget->style->fg_gc[GTK_STATE_NORMAL]
13773 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
13774 </verb></tscreen>
13775
13776 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
13777 <tt>light_gc</tt> are indexed by a parameter of type
13778 <tt>GtkStateType</tt> which can take on the values:
13779
13780 <tscreen><verb>
13781 GTK_STATE_NORMAL,
13782 GTK_STATE_ACTIVE,
13783 GTK_STATE_PRELIGHT,
13784 GTK_STATE_SELECTED,
13785 GTK_STATE_INSENSITIVE
13786 </verb></tscreen>
13787
13788 For instance, the for <tt/GTK_STATE_SELECTED/ the default foreground
13789 color is white and the default background color, dark blue.
13790
13791 Our function <tt>draw_brush()</tt>, which does the actual drawing
13792 on the screen, is then:
13793
13794 <tscreen><verb>
13795 /* Draw a rectangle on the screen */
13796 static void
13797 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
13798 {
13799   GdkRectangle update_rect;
13800
13801   update_rect.x = x - 5;
13802   update_rect.y = y - 5;
13803   update_rect.width = 10;
13804   update_rect.height = 10;
13805   gdk_draw_rectangle (pixmap,
13806                       widget->style->black_gc,
13807                       TRUE,
13808                       update_rect.x, update_rect.y,
13809                       update_rect.width, update_rect.height);
13810   gtk_widget_draw (widget, &amp;update_rect);
13811 }
13812 </verb></tscreen>
13813
13814 After we draw the rectangle representing the brush onto the pixmap,
13815 we call the function:
13816
13817 <tscreen><verb>
13818 void       gtk_widget_draw                (GtkWidget           *widget,
13819                                            GdkRectangle        *area);
13820 </verb></tscreen>
13821
13822 which notifies X that the area given by the <tt>area</tt> parameter
13823 needs to be updated. X will eventually generate an expose event
13824 (possibly combining the areas passed in several calls to
13825 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
13826 to copy the relevant portions to the screen.
13827
13828 We have now covered the entire drawing program except for a few
13829 mundane details like creating the main window. The complete
13830 source code is available from the location from which you got
13831 this tutorial, or from:
13832
13833 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13834 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13835
13836
13837 <!-- ----------------------------------------------------------------- -->
13838 <sect1> Adding XInput support
13839 <p>
13840 It is now possible to buy quite inexpensive input devices such 
13841 as drawing tablets, which allow drawing with a much greater
13842 ease of artistic expression than does a mouse. The simplest way
13843 to use such devices is simply as a replacement for the mouse,
13844 but that misses out many of the advantages of these devices,
13845 such as:
13846
13847 <itemize>
13848 <item> Pressure sensitivity
13849 <item> Tilt reporting
13850 <item> Sub-pixel positioning
13851 <item> Multiple inputs (for example, a stylus with a point and eraser)
13852 </itemize>
13853
13854 For information about the XInput extension, see the <htmlurl
13855 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13856 name="XInput-HOWTO">.
13857
13858 If we examine the full definition of, for example, the GdkEventMotion
13859 structure, we see that it has fields to support extended device
13860 information.
13861
13862 <tscreen><verb>
13863 struct _GdkEventMotion
13864 {
13865   GdkEventType type;
13866   GdkWindow *window;
13867   guint32 time;
13868   gdouble x;
13869   gdouble y;
13870   gdouble pressure;
13871   gdouble xtilt;
13872   gdouble ytilt;
13873   guint state;
13874   gint16 is_hint;
13875   GdkInputSource source;
13876   guint32 deviceid;
13877 };
13878 </verb></tscreen>
13879
13880 <tt/pressure/ gives the pressure as a floating point number between
13881 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
13882 -1 and 1, corresponding to the degree of tilt in each direction.
13883 <tt/source/ and <tt/deviceid/ specify the device for which the
13884 event occurred in two different ways. <tt/source/ gives some simple
13885 information about the type of device. It can take the enumeration
13886 values.
13887
13888 <tscreen><verb>
13889 GDK_SOURCE_MOUSE
13890 GDK_SOURCE_PEN
13891 GDK_SOURCE_ERASER
13892 GDK_SOURCE_CURSOR
13893 </verb></tscreen>
13894
13895 <tt/deviceid/ specifies a unique numeric ID for the device. This can
13896 be used to find out further information about the device using the
13897 <tt/gdk_input_list_devices()/ call (see below). The special value
13898 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
13899 the mouse.)
13900
13901 <sect2> Enabling extended device information
13902 <p>
13903 To let GTK know about our interest in the extended device information,
13904 we merely have to add a single line to our program:
13905
13906 <tscreen><verb>
13907 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
13908 </verb></tscreen>
13909
13910 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
13911 we are interested in extension events, but only if we don't have
13912 to draw our own cursor. See the section <ref
13913 id="sec_Further_Sophistications" name="Further Sophistications"> below
13914 for more information about drawing the cursor. We could also 
13915 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
13916 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
13917 back to the default condition.
13918
13919 This is not completely the end of the story however. By default,
13920 no extension devices are enabled. We need a mechanism to allow
13921 users to enable and configure their extension devices. GTK provides
13922 the InputDialog widget to automate this process. The following
13923 procedure manages an InputDialog widget. It creates the dialog if
13924 it isn't present, and raises it to the top otherwise.
13925
13926 <tscreen><verb>
13927 void
13928 input_dialog_destroy (GtkWidget *w, gpointer data)
13929 {
13930   *((GtkWidget **)data) = NULL;
13931 }
13932
13933 void
13934 create_input_dialog ()
13935 {
13936   static GtkWidget *inputd = NULL;
13937
13938   if (!inputd)
13939     {
13940       inputd = gtk_input_dialog_new();
13941
13942       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
13943                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
13944       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
13945                                  "clicked",
13946                                  (GtkSignalFunc)gtk_widget_hide,
13947                                  GTK_OBJECT(inputd));
13948       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
13949
13950       gtk_widget_show (inputd);
13951     }
13952   else
13953     {
13954       if (!GTK_WIDGET_MAPPED(inputd))
13955         gtk_widget_show(inputd);
13956       else
13957         gdk_window_raise(inputd->window);
13958     }
13959 }
13960 </verb></tscreen>
13961
13962 (You might want to take note of the way we handle this dialog.  By
13963 connecting to the "destroy" signal, we make sure that we don't keep a
13964 pointer to dialog around after it is destroyed - that could lead to a
13965 segfault.)
13966
13967 The InputDialog has two buttons "Close" and "Save", which by default
13968 have no actions assigned to them. In the above function we make
13969 "Close" hide the dialog, hide the "Save" button, since we don't
13970 implement saving of XInput options in this program.
13971
13972 <sect2> Using extended device information
13973 <p>
13974 Once we've enabled the device, we can just use the extended 
13975 device information in the extra fields of the event structures.
13976 In fact, it is always safe to use this information since these
13977 fields will have reasonable default values even when extended
13978 events are not enabled.
13979
13980 Once change we do have to make is to call
13981 <tt/gdk_input_window_get_pointer()/ instead of
13982 <tt/gdk_window_get_pointer/. This is necessary because
13983 <tt/gdk_window_get_pointer/ doesn't return the extended device
13984 information.
13985
13986 <tscreen><verb>
13987 void gdk_input_window_get_pointer( GdkWindow       *window,
13988                                    guint32         deviceid,
13989                                    gdouble         *x,
13990                                    gdouble         *y,
13991                                    gdouble         *pressure,
13992                                    gdouble         *xtilt,
13993                                    gdouble         *ytilt,
13994                                    GdkModifierType *mask);
13995 </verb></tscreen>
13996
13997 When calling this function, we need to specify the device ID as
13998 well as the window. Usually, we'll get the device ID from the
13999 <tt/deviceid/ field of an event structure. Again, this function
14000 will return reasonable values when extension events are not
14001 enabled. (In this case, <tt/event->deviceid/ will have the value
14002 <tt/GDK_CORE_POINTER/).
14003
14004 So the basic structure of our button-press and motion event handlers,
14005 doesn't change much - we just need to add code to deal with the
14006 extended information.
14007
14008 <tscreen><verb>
14009 static gint
14010 button_press_event (GtkWidget *widget, GdkEventButton *event)
14011 {
14012   print_button_press (event->deviceid);
14013   
14014   if (event->button == 1 &amp;&amp; pixmap != NULL)
14015     draw_brush (widget, event->source, event->x, event->y, event->pressure);
14016
14017   return TRUE;
14018 }
14019
14020 static gint
14021 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14022 {
14023   gdouble x, y;
14024   gdouble pressure;
14025   GdkModifierType state;
14026
14027   if (event->is_hint)
14028     gdk_input_window_get_pointer (event->window, event->deviceid,
14029                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
14030   else
14031     {
14032       x = event->x;
14033       y = event->y;
14034       pressure = event->pressure;
14035       state = event->state;
14036     }
14037     
14038   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14039     draw_brush (widget, event->source, x, y, pressure);
14040   
14041   return TRUE;
14042 }
14043 </verb></tscreen>
14044
14045 We also need to do something with the new information. Our new
14046 <tt/draw_brush()/ function draws with a different color for
14047 each <tt/event->source/ and changes the brush size depending
14048 on the pressure.
14049
14050 <tscreen><verb>
14051 /* Draw a rectangle on the screen, size depending on pressure,
14052    and color on the type of device */
14053 static void
14054 draw_brush (GtkWidget *widget, GdkInputSource source,
14055             gdouble x, gdouble y, gdouble pressure)
14056 {
14057   GdkGC *gc;
14058   GdkRectangle update_rect;
14059
14060   switch (source)
14061     {
14062     case GDK_SOURCE_MOUSE:
14063       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
14064       break;
14065     case GDK_SOURCE_PEN:
14066       gc = widget->style->black_gc;
14067       break;
14068     case GDK_SOURCE_ERASER:
14069       gc = widget->style->white_gc;
14070       break;
14071     default:
14072       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
14073     }
14074
14075   update_rect.x = x - 10 * pressure;
14076   update_rect.y = y - 10 * pressure;
14077   update_rect.width = 20 * pressure;
14078   update_rect.height = 20 * pressure;
14079   gdk_draw_rectangle (pixmap, gc, TRUE,
14080                       update_rect.x, update_rect.y,
14081                       update_rect.width, update_rect.height);
14082   gtk_widget_draw (widget, &amp;update_rect);
14083 }
14084 </verb></tscreen>
14085
14086 <sect2> Finding out more about a device
14087 <p>
14088 As an example of how to find out more about a device, our program
14089 will print the name of the device that generates each button
14090 press. To find out the name of a device, we call the function:
14091
14092 <tscreen><verb>
14093 GList *gdk_input_list_devices               (void);
14094 </verb></tscreen>
14095
14096 which returns a GList (a linked list type from the glib library)
14097 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
14098 as:
14099
14100 <tscreen><verb>
14101 struct _GdkDeviceInfo
14102 {
14103   guint32 deviceid;
14104   gchar *name;
14105   GdkInputSource source;
14106   GdkInputMode mode;
14107   gint has_cursor;
14108   gint num_axes;
14109   GdkAxisUse *axes;
14110   gint num_keys;
14111   GdkDeviceKey *keys;
14112 };
14113 </verb></tscreen>
14114
14115 Most of these fields are configuration information that you
14116 can ignore unless you are implemented XInput configuration
14117 saving. The we are interested in here is <tt/name/ which is
14118 simply the name that X assigns to the device. The other field
14119 that isn't configuration information is <tt/has_cursor/. If
14120 <tt/has_cursor/ is false, then we we need to draw our own
14121 cursor. But since we've specified <tt/GDK_EXTENSION_EVENTS_CURSOR/,
14122 we don't have to worry about this.
14123
14124 Our <tt/print_button_press()/ function simply iterates through
14125 the returned list until it finds a match, then prints out
14126 the name of the device.
14127
14128 <tscreen><verb>
14129 static void
14130 print_button_press (guint32 deviceid)
14131 {
14132   GList *tmp_list;
14133
14134   /* gdk_input_list_devices returns an internal list, so we shouldn't
14135      free it afterwards */
14136   tmp_list = gdk_input_list_devices();
14137
14138   while (tmp_list)
14139     {
14140       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
14141
14142       if (info->deviceid == deviceid)
14143         {
14144           printf("Button press on device '%s'\n", info->name);
14145           return;
14146         }
14147
14148       tmp_list = tmp_list->next;
14149     }
14150 }
14151 </verb></tscreen>
14152
14153 That completes the changes to `XInputize' our program. As with
14154 the first version, the complete source is available at the location
14155 from which you got this tutorial, or from:
14156
14157 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
14158 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
14159
14160
14161 <sect2> Further sophistications <label id="sec_Further_Sophistications">
14162 <p>
14163 Although our program now supports XInput quite well, it lacks some
14164 features we would want in a full-featured application. First, the user
14165 probably doesn't want to have to configure their device each time they
14166 run the program, so we should allow them to save the device
14167 configuration. This is done by iterating through the return of
14168 <tt/gdk_input_list_devices()/ and writing out the configuration to a
14169 file.
14170
14171 To restore the state next time the program is run, GDK provides
14172 functions to change device configuration:
14173
14174 <tscreen><verb>
14175 gdk_input_set_extension_events()
14176 gdk_input_set_source()
14177 gdk_input_set_mode()
14178 gdk_input_set_axes()
14179 gdk_input_set_key()
14180 </verb></tscreen>
14181
14182 (The list returned from <tt/gdk_input_list_devices()/ should not be
14183 modified directly.) An example of doing this can be found in the
14184 drawing program gsumi. (Available from <htmlurl
14185 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
14186 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
14187 would be nice to have a standard way of doing this for all
14188 applications. This probably belongs at a slightly higher level than
14189 GTK, perhaps in the GNOME library.
14190
14191 Another major omission that we have mentioned above is the lack of
14192 cursor drawing. Platforms other than XFree86 currently do not allow
14193 simultaneously using a device as both the core pointer and directly by
14194 an application. See the <url
14195 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14196 name="XInput-HOWTO"> for more information about this. This means that
14197 applications that want to support the widest audience need to draw
14198 their own cursor.
14199
14200 An application that draws its own cursor needs to do two things:
14201 determine if the current device needs a cursor drawn or not, and
14202 determine if the current device is in proximity. (If the current
14203 device is a drawing tablet, it's a nice touch to make the cursor 
14204 disappear when the stylus is lifted from the tablet. When the
14205 device is touching the stylus, that is called "in proximity.")
14206 The first is done by searching the device list, as we did
14207 to find out the device name. The second is achieved by selecting
14208 "proximity_out" events. An example of drawing one's own cursor is
14209 found in the 'testinput' program found in the GTK distribution.
14210
14211 <!-- ***************************************************************** -->
14212 <sect>Tips For Writing GTK Applications
14213 <!-- ***************************************************************** -->
14214 <p>
14215 This section is simply a gathering of wisdom, general style guidelines
14216 and hints to creating good GTK applications. Currently this section
14217 is very short, but hopefully it will get longer in future editions of
14218 this tutorial.
14219
14220 Use GNU autoconf and automake! They are your friends :) Automake
14221 examines C files, determines how they depend on each other, and
14222 generates a Makefile so the files can be compiled in the correct
14223 order. Autoconf permits automatic configuration of software
14224 installation, handling a large number of system quirks to increase
14225 portability. I am planning to make a quick intro on them here.
14226
14227 When writing C code, use only C comments (beginning with "/*" and
14228 ending with "*/"), and don't use C++-style comments ("//").  Although
14229 many C compilers understand C++ comments, others don't, and the ANSI C
14230 standard does not require that C++-style comments be processed as
14231 comments.
14232
14233 <!-- ***************************************************************** -->
14234 <sect>Contributing <label id="sec_Contributing">
14235 <!-- ***************************************************************** -->
14236 <p>
14237 This document, like so much other great software out there, was
14238 created for free by volunteers.  If you are at all knowledgeable about
14239 any aspect of GTK that does not already have documentation, please
14240 consider contributing to this document.
14241
14242 If you do decide to contribute, please mail your text to Tony Gale,
14243 <tt><htmlurl url="mailto:gale@gtk.org"
14244 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
14245 document is free, and any addition by you provide must also be
14246 free. That is, people may use any portion of your examples in their
14247 programs, and copies of this document may be distributed at will etc.
14248
14249 Thank you.
14250
14251 <!-- ***************************************************************** -->
14252 <sect>Credits
14253 <!-- ***************************************************************** -->
14254 <p>
14255 I would like to thank the following for their contributions to this text.
14256
14257 <itemize>
14258 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
14259 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
14260
14261 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
14262 name="raph@acm.org"></tt>
14263 for hello world ala GTK, widget packing, and general all around wisdom.
14264 He's also generously donated a home for this tutorial.
14265
14266 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
14267 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
14268 and the ability to make it :)
14269
14270 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
14271 name="werner.koch@guug.de"></tt> for converting the original plain text to
14272 SGML, and the widget class hierarchy.
14273
14274 <item>Mark Crichton <tt><htmlurl
14275 url="mailto:crichton@expert.cc.purdue.edu"
14276 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
14277 and the table packing tutorial.
14278
14279 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
14280 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
14281 patch to the distro).  He's also responsible for the selections code
14282 and tutorial, as well as the sections on writing your own GTK widgets,
14283 and the example application. Thanks a lot Owen for all you help!
14284
14285 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
14286 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
14287 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
14288 lot Mark!  You've been a great help.
14289
14290 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
14291 name="timj@psynet.net"></tt> for his great job on the Lists
14292 Widget. His excellent work on automatically extracting the widget tree
14293 and signal information from GTK. Thanks Tim :)
14294
14295 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
14296 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
14297 tutorial.
14298
14299 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
14300 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
14301
14302 <item>David Huggins-Daines <tt><htmlurl
14303 url="mailto:bn711@freenet.carleton.ca"
14304 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
14305 Widget sections.
14306
14307 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
14308 name="mars@lysator.liu.se"></tt> for the GtkCList section.
14309
14310 <item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org"
14311 name="dwheeler@ida.org"></tt> for portions of the text on glib
14312 and various tutorial fixups and improvements.
14313 The glib text was in turn based on material developed by Damon Chaplin
14314 <tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt>
14315 </itemize>
14316
14317 And to all of you who commented and helped refine this document.
14318
14319 Thanks.
14320
14321 <!-- ***************************************************************** -->
14322 <sect> Tutorial Copyright and Permissions Notice
14323 <!-- ***************************************************************** -->
14324
14325 <p>
14326 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
14327
14328 Copyright (C) 1998-1999 Tony Gale.
14329
14330 Permission is granted to make and distribute verbatim copies of this 
14331 manual provided the copyright notice and this permission notice are 
14332 preserved on all copies.
14333
14334 Permission is granted to copy and distribute modified versions of 
14335 this document under the conditions for verbatim copying, provided that 
14336 this copyright notice is included exactly as in the original,
14337 and that the entire resulting derived work is distributed under 
14338 the terms of a permission notice identical to this one.
14339 <P>Permission is granted to copy and distribute translations of this 
14340 document into another language, under the above conditions for modified 
14341 versions.
14342
14343 If you are intending to incorporate this document into a published 
14344 work, please contact the maintainer, and we will make an effort 
14345 to ensure that you have the most up to date information available.
14346
14347 There is no guarantee that this document lives up to its intended
14348 purpose.  This is simply provided as a free resource.  As such,
14349 the authors and maintainers of the information provided within can
14350 not make any guarantee that the information is even accurate.
14351
14352 <!-- ***************************************************************** -->
14353 <appendix>
14354 <!-- ***************************************************************** -->
14355
14356 <!-- ***************************************************************** -->
14357 <sect> GTK Signals <label id="sec_GTK_Signals">
14358 <!-- ***************************************************************** -->
14359 <p>
14360 As GTK is an object oriented widget set, it has a hierarchy of
14361 inheritance. This inheritance mechanism applies for
14362 signals. Therefore, you should refer to the widget hierarchy tree when
14363 using the signals listed in this section.
14364
14365 <!-- ----------------------------------------------------------------- -->
14366 <sect1>GtkObject
14367 <!-- ----------------------------------------------------------------- -->
14368 <p>
14369 <tscreen><verb>
14370 void GtkObject::destroy (GtkObject *,
14371                          gpointer);
14372 </verb></tscreen>
14373
14374 <!-- ----------------------------------------------------------------- -->
14375 <sect1>GtkWidget
14376 <!-- ----------------------------------------------------------------- -->
14377 <p>
14378 <tscreen><verb>
14379
14380 void GtkWidget::show    (GtkWidget *,
14381                          gpointer);
14382 void GtkWidget::hide    (GtkWidget *,
14383                          gpointer);
14384 void GtkWidget::map     (GtkWidget *,
14385                          gpointer);
14386 void GtkWidget::unmap   (GtkWidget *,
14387                          gpointer);
14388 void GtkWidget::realize (GtkWidget *,
14389                          gpointer);
14390 void GtkWidget::unrealize       (GtkWidget *,
14391                                  gpointer);
14392 void GtkWidget::draw    (GtkWidget *,
14393                          ggpointer,
14394                          gpointer);
14395 void GtkWidget::draw-focus      (GtkWidget *,
14396                                  gpointer);
14397 void GtkWidget::draw-default    (GtkWidget *,
14398                                  gpointer);
14399 void GtkWidget::size-request    (GtkWidget *,
14400                                  ggpointer,
14401                                  gpointer);
14402 void GtkWidget::size-allocate   (GtkWidget *,
14403                                  ggpointer,
14404                                  gpointer);
14405 void GtkWidget::state-changed   (GtkWidget *,
14406                                  GtkStateType,
14407                                  gpointer);
14408 void GtkWidget::parent-set      (GtkWidget *,
14409                                  GtkObject *,
14410                                  gpointer);
14411 void GtkWidget::style-set       (GtkWidget *,
14412                                  GtkStyle *,
14413                                  gpointer);
14414 void GtkWidget::add-accelerator (GtkWidget *,
14415                                  gguint,
14416                                  GtkAccelGroup *,
14417                                  gguint,
14418                                  GdkModifierType,
14419                                  GtkAccelFlags,
14420                                  gpointer);
14421 void GtkWidget::remove-accelerator      (GtkWidget *,
14422                                          GtkAccelGroup *,
14423                                          gguint,
14424                                          GdkModifierType,
14425                                          gpointer);
14426 gboolean GtkWidget::event       (GtkWidget *,
14427                                  GdkEvent *,
14428                                  gpointer);
14429 gboolean GtkWidget::button-press-event  (GtkWidget *,
14430                                          GdkEvent *,
14431                                          gpointer);
14432 gboolean GtkWidget::button-release-event        (GtkWidget *,
14433                                                  GdkEvent *,
14434                                                  gpointer);
14435 gboolean GtkWidget::motion-notify-event (GtkWidget *,
14436                                          GdkEvent *,
14437                                          gpointer);
14438 gboolean GtkWidget::delete-event        (GtkWidget *,
14439                                          GdkEvent *,
14440                                          gpointer);
14441 gboolean GtkWidget::destroy-event       (GtkWidget *,
14442                                          GdkEvent *,
14443                                          gpointer);
14444 gboolean GtkWidget::expose-event        (GtkWidget *,
14445                                          GdkEvent *,
14446                                          gpointer);
14447 gboolean GtkWidget::key-press-event     (GtkWidget *,
14448                                          GdkEvent *,
14449                                          gpointer);
14450 gboolean GtkWidget::key-release-event   (GtkWidget *,
14451                                          GdkEvent *,
14452                                          gpointer);
14453 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
14454                                          GdkEvent *,
14455                                          gpointer);
14456 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
14457                                          GdkEvent *,
14458                                          gpointer);
14459 gboolean GtkWidget::configure-event     (GtkWidget *,
14460                                          GdkEvent *,
14461                                          gpointer);
14462 gboolean GtkWidget::focus-in-event      (GtkWidget *,
14463                                          GdkEvent *,
14464                                          gpointer);
14465 gboolean GtkWidget::focus-out-event     (GtkWidget *,
14466                                          GdkEvent *,
14467                                          gpointer);
14468 gboolean GtkWidget::map-event   (GtkWidget *,
14469                                  GdkEvent *,
14470                                  gpointer);
14471 gboolean GtkWidget::unmap-event (GtkWidget *,
14472                                  GdkEvent *,
14473                                  gpointer);
14474 gboolean GtkWidget::property-notify-event       (GtkWidget *,
14475                                                  GdkEvent *,
14476                                                  gpointer);
14477 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
14478                                                  GdkEvent *,
14479                                                  gpointer);
14480 gboolean GtkWidget::selection-request-event     (GtkWidget *,
14481                                                  GdkEvent *,
14482                                                  gpointer);
14483 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
14484                                                  GdkEvent *,
14485                                                  gpointer);
14486 void GtkWidget::selection-get   (GtkWidget *,
14487                                  GtkSelectionData *,
14488                                  gguint,
14489                                  gpointer);
14490 void GtkWidget::selection-received      (GtkWidget *,
14491                                          GtkSelectionData *,
14492                                          gguint,
14493                                          gpointer);
14494 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
14495                                          GdkEvent *,
14496                                          gpointer);
14497 gboolean GtkWidget::proximity-out-event (GtkWidget *,
14498                                          GdkEvent *,
14499                                          gpointer);
14500 void GtkWidget::drag-begin      (GtkWidget *,
14501                                  GdkDragContext *,
14502                                  gpointer);
14503 void GtkWidget::drag-end        (GtkWidget *,
14504                                  GdkDragContext *,
14505                                  gpointer);
14506 void GtkWidget::drag-data-delete        (GtkWidget *,
14507                                          GdkDragContext *,
14508                                          gpointer);
14509 void GtkWidget::drag-leave      (GtkWidget *,
14510                                  GdkDragContext *,
14511                                  gguint,
14512                                  gpointer);
14513 gboolean GtkWidget::drag-motion (GtkWidget *,
14514                                  GdkDragContext *,
14515                                  ggint,
14516                                  ggint,
14517                                  gguint,
14518                                  gpointer);
14519 gboolean GtkWidget::drag-drop   (GtkWidget *,
14520                                  GdkDragContext *,
14521                                  ggint,
14522                                  ggint,
14523                                  gguint,
14524                                  gpointer);
14525 void GtkWidget::drag-data-get   (GtkWidget *,
14526                                  GdkDragContext *,
14527                                  GtkSelectionData *,
14528                                  gguint,
14529                                  gguint,
14530                                  gpointer);
14531 void GtkWidget::drag-data-received      (GtkWidget *,
14532                                          GdkDragContext *,
14533                                          ggint,
14534                                          ggint,
14535                                          GtkSelectionData *,
14536                                          gguint,
14537                                          gguint,
14538                                          gpointer);
14539 gboolean GtkWidget::client-event        (GtkWidget *,
14540                                          GdkEvent *,
14541                                          gpointer);
14542 gboolean GtkWidget::no-expose-event     (GtkWidget *,
14543                                          GdkEvent *,
14544                                          gpointer);
14545 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
14546                                                  GdkEvent *,
14547                                                  gpointer);
14548 void GtkWidget::debug-msg       (GtkWidget *,
14549                                  GtkString *,
14550                                  gpointer);
14551 </verb></tscreen>
14552
14553 <!-- ----------------------------------------------------------------- -->
14554 <sect1>GtkData
14555 <!-- ----------------------------------------------------------------- -->
14556 <p>
14557 <tscreen><verb>
14558 void GtkData::disconnect        (GtkData *,
14559                                  gpointer);
14560 </verb></tscreen>
14561
14562 <!-- ----------------------------------------------------------------- -->
14563 <sect1>GtkContainer
14564 <!-- ----------------------------------------------------------------- -->
14565 <p>
14566 <tscreen><verb>
14567 void GtkContainer::add  (GtkContainer *,
14568                          GtkWidget *,
14569                          gpointer);
14570 void GtkContainer::remove       (GtkContainer *,
14571                                  GtkWidget *,
14572                                  gpointer);
14573 void GtkContainer::check-resize (GtkContainer *,
14574                                  gpointer);
14575 GtkDirectionType GtkContainer::focus    (GtkContainer *,
14576                                          GtkDirectionType,
14577                                          gpointer);
14578 void GtkContainer::set-focus-child      (GtkContainer *,
14579                                          GtkWidget *,
14580                                          gpointer);
14581 </verb></tscreen>
14582
14583 <!-- ----------------------------------------------------------------- -->
14584 <sect1>GtkCalendar
14585 <!-- ----------------------------------------------------------------- -->
14586 <p>
14587 <tscreen><verb>
14588 void GtkCalendar::month-changed (GtkCalendar *,
14589                                  gpointer);
14590 void GtkCalendar::day-selected  (GtkCalendar *,
14591                                  gpointer);
14592 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
14593                                                  gpointer);
14594 void GtkCalendar::prev-month    (GtkCalendar *,
14595                                  gpointer);
14596 void GtkCalendar::next-month    (GtkCalendar *,
14597                                  gpointer);
14598 void GtkCalendar::prev-year     (GtkCalendar *,
14599                                  gpointer);
14600 void GtkCalendar::next-year     (GtkCalendar *,
14601                                  gpointer);
14602 </verb></tscreen>
14603
14604 <!-- ----------------------------------------------------------------- -->
14605 <sect1>GtkEditable
14606 <!-- ----------------------------------------------------------------- -->
14607 <p>
14608 <tscreen><verb>
14609 void GtkEditable::changed       (GtkEditable *,
14610                                  gpointer);
14611 void GtkEditable::insert-text   (GtkEditable *,
14612                                  GtkString *,
14613                                  ggint,
14614                                  ggpointer,
14615                                  gpointer);
14616 void GtkEditable::delete-text   (GtkEditable *,
14617                                  ggint,
14618                                  ggint,
14619                                  gpointer);
14620 void GtkEditable::activate      (GtkEditable *,
14621                                  gpointer);
14622 void GtkEditable::set-editable  (GtkEditable *,
14623                                  gboolean,
14624                                  gpointer);
14625 void GtkEditable::move-cursor   (GtkEditable *,
14626                                  ggint,
14627                                  ggint,
14628                                  gpointer);
14629 void GtkEditable::move-word     (GtkEditable *,
14630                                  ggint,
14631                                  gpointer);
14632 void GtkEditable::move-page     (GtkEditable *,
14633                                  ggint,
14634                                  ggint,
14635                                  gpointer);
14636 void GtkEditable::move-to-row   (GtkEditable *,
14637                                  ggint,
14638                                  gpointer);
14639 void GtkEditable::move-to-column        (GtkEditable *,
14640                                          ggint,
14641                                          gpointer);
14642 void GtkEditable::kill-char     (GtkEditable *,
14643                                  ggint,
14644                                  gpointer);
14645 void GtkEditable::kill-word     (GtkEditable *,
14646                                  ggint,
14647                                  gpointer);
14648 void GtkEditable::kill-line     (GtkEditable *,
14649                                  ggint,
14650                                  gpointer);
14651 void GtkEditable::cut-clipboard (GtkEditable *,
14652                                  gpointer);
14653 void GtkEditable::copy-clipboard        (GtkEditable *,
14654                                          gpointer);
14655 void GtkEditable::paste-clipboard       (GtkEditable *,
14656                                          gpointer);
14657 </verb></tscreen>
14658
14659 <!-- ----------------------------------------------------------------- -->
14660 <sect1>GtkTipsQuery
14661 <!-- ----------------------------------------------------------------- -->
14662 <p>
14663 <tscreen><verb>
14664 void GtkTipsQuery::start-query  (GtkTipsQuery *,
14665                                  gpointer);
14666 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
14667                                  gpointer);
14668 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
14669                                          GtkWidget *,
14670                                          GtkString *,
14671                                          GtkString *,
14672                                          gpointer);
14673 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
14674                                          GtkWidget *,
14675                                          GtkString *,
14676                                          GtkString *,
14677                                          GdkEvent *,
14678                                          gpointer);
14679 </verb></tscreen>
14680
14681 <!-- ----------------------------------------------------------------- -->
14682 <sect1>GtkCList
14683 <!-- ----------------------------------------------------------------- -->
14684 <p>
14685 <tscreen><verb>
14686 void GtkCList::select-row       (GtkCList *,
14687                                  ggint,
14688                                  ggint,
14689                                  GdkEvent *,
14690                                  gpointer);
14691 void GtkCList::unselect-row     (GtkCList *,
14692                                  ggint,
14693                                  ggint,
14694                                  GdkEvent *,
14695                                  gpointer);
14696 void GtkCList::row-move (GtkCList *,
14697                          ggint,
14698                          ggint,
14699                          gpointer);
14700 void GtkCList::click-column     (GtkCList *,
14701                                  ggint,
14702                                  gpointer);
14703 void GtkCList::resize-column    (GtkCList *,
14704                                  ggint,
14705                                  ggint,
14706                                  gpointer);
14707 void GtkCList::toggle-focus-row (GtkCList *,
14708                                  gpointer);
14709 void GtkCList::select-all       (GtkCList *,
14710                                  gpointer);
14711 void GtkCList::unselect-all     (GtkCList *,
14712                                  gpointer);
14713 void GtkCList::undo-selection   (GtkCList *,
14714                                  gpointer);
14715 void GtkCList::start-selection  (GtkCList *,
14716                                  gpointer);
14717 void GtkCList::end-selection    (GtkCList *,
14718                                  gpointer);
14719 void GtkCList::toggle-add-mode  (GtkCList *,
14720                                  gpointer);
14721 void GtkCList::extend-selection (GtkCList *,
14722                                  GtkScrollType,
14723                                  ggfloat,
14724                                  gboolean,
14725                                  gpointer);
14726 void GtkCList::scroll-vertical  (GtkCList *,
14727                                  GtkScrollType,
14728                                  ggfloat,
14729                                  gpointer);
14730 void GtkCList::scroll-horizontal        (GtkCList *,
14731                                          GtkScrollType,
14732                                          ggfloat,
14733                                          gpointer);
14734 void GtkCList::abort-column-resize      (GtkCList *,
14735                                          gpointer);
14736 </verb></tscreen>
14737
14738 <!-- ----------------------------------------------------------------- -->
14739 <sect1>GtkNotebook
14740 <!-- ----------------------------------------------------------------- -->
14741 <p>
14742 <tscreen><verb>
14743 void GtkNotebook::switch-page   (GtkNotebook *,
14744                                  ggpointer,
14745                                  gguint,
14746                                  gpointer);
14747
14748 </verb></tscreen>
14749
14750 <!-- ----------------------------------------------------------------- -->
14751 <sect1>GtkList
14752 <!-- ----------------------------------------------------------------- -->
14753 <p>
14754 <tscreen><verb>
14755 void GtkList::selection-changed (GtkList *,
14756                                  gpointer);
14757 void GtkList::select-child      (GtkList *,
14758                                  GtkWidget *,
14759                                  gpointer);
14760 void GtkList::unselect-child    (GtkList *,
14761                                  GtkWidget *,
14762                                  gpointer);
14763 </verb></tscreen>
14764
14765 <!-- ----------------------------------------------------------------- -->
14766 <sect1>GtkMenuShell
14767 <!-- ----------------------------------------------------------------- -->
14768 <p>
14769 <tscreen><verb>
14770 void GtkMenuShell::deactivate   (GtkMenuShell *,
14771                                  gpointer);
14772 void GtkMenuShell::selection-done       (GtkMenuShell *,
14773                                          gpointer);
14774 void GtkMenuShell::move-current (GtkMenuShell *,
14775                                  GtkMenuDirectionType,
14776                                  gpointer);
14777 void GtkMenuShell::activate-current     (GtkMenuShell *,
14778                                          gboolean,
14779                                          gpointer);
14780 void GtkMenuShell::cancel       (GtkMenuShell *,
14781                                  gpointer);
14782 </verb></tscreen>
14783
14784 <!-- ----------------------------------------------------------------- -->
14785 <sect1>GtkToolbar
14786 <!-- ----------------------------------------------------------------- -->
14787 <p>
14788 <tscreen><verb>
14789 void GtkToolbar::orientation-changed    (GtkToolbar *,
14790                                          ggint,
14791                                          gpointer);
14792 void GtkToolbar::style-changed  (GtkToolbar *,
14793                                  ggint,
14794                                  gpointer);
14795 </verb></tscreen>
14796
14797 <!-- ----------------------------------------------------------------- -->
14798 <sect1>GtkTree
14799 <!-- ----------------------------------------------------------------- -->
14800 <p>
14801 <tscreen><verb>
14802 void GtkTree::selection-changed (GtkTree *,
14803                                  gpointer);
14804 void GtkTree::select-child      (GtkTree *,
14805                                  GtkWidget *,
14806                                  gpointer);
14807 void GtkTree::unselect-child    (GtkTree *,
14808                                  GtkWidget *,
14809                                  gpointer);
14810 </verb></tscreen>
14811
14812 <!-- ----------------------------------------------------------------- -->
14813 <sect1>GtkButton
14814 <!-- ----------------------------------------------------------------- -->
14815 <p>
14816 <tscreen><verb>
14817 void GtkButton::pressed (GtkButton *,
14818                          gpointer);
14819 void GtkButton::released        (GtkButton *,
14820                                  gpointer);
14821 void GtkButton::clicked (GtkButton *,
14822                          gpointer);
14823 void GtkButton::enter   (GtkButton *,
14824                          gpointer);
14825 void GtkButton::leave   (GtkButton *,
14826                          gpointer);
14827 </verb></tscreen>
14828
14829 <!-- ----------------------------------------------------------------- -->
14830 <sect1>GtkItem
14831 <!-- ----------------------------------------------------------------- -->
14832 <p>
14833 <tscreen><verb>
14834 void GtkItem::select    (GtkItem *,
14835                          gpointer);
14836 void GtkItem::deselect  (GtkItem *,
14837                          gpointer);
14838 void GtkItem::toggle    (GtkItem *,
14839                          gpointer);
14840 </verb></tscreen>
14841
14842 <!-- ----------------------------------------------------------------- -->
14843 <sect1>GtkWindow
14844 <!-- ----------------------------------------------------------------- -->
14845 <p>
14846 <tscreen><verb>
14847 void GtkWindow::set-focus       (GtkWindow *,
14848                                  ggpointer,
14849                                  gpointer);
14850 </verb></tscreen>
14851
14852 <!-- ----------------------------------------------------------------- -->
14853 <sect1>GtkHandleBox
14854 <!-- ----------------------------------------------------------------- -->
14855 <p>
14856 <tscreen><verb>
14857 void GtkHandleBox::child-attached       (GtkHandleBox *,
14858                                          GtkWidget *,
14859                                          gpointer);
14860 void GtkHandleBox::child-detached       (GtkHandleBox *,
14861                                          GtkWidget *,
14862                                          gpointer);
14863 </verb></tscreen>
14864
14865 <!-- ----------------------------------------------------------------- -->
14866 <sect1>GtkToggleButton
14867 <!-- ----------------------------------------------------------------- -->
14868 <p>
14869 <tscreen><verb>
14870 void GtkToggleButton::toggled   (GtkToggleButton *,
14871                                  gpointer);
14872
14873 </verb></tscreen>
14874
14875 <!-- ----------------------------------------------------------------- -->
14876 <sect1>GtkMenuItem
14877 <!-- ----------------------------------------------------------------- -->
14878 <p>
14879 <tscreen><verb>
14880 void GtkMenuItem::activate      (GtkMenuItem *,
14881                                  gpointer);
14882 void GtkMenuItem::activate-item (GtkMenuItem *,
14883                                  gpointer);
14884 </verb></tscreen>
14885
14886 <!-- ----------------------------------------------------------------- -->
14887 <sect1>GtkListItem
14888 <!-- ----------------------------------------------------------------- -->
14889 <p>
14890 <tscreen><verb>
14891 void GtkListItem::toggle-focus-row      (GtkListItem *,
14892                                          gpointer);
14893 void GtkListItem::select-all    (GtkListItem *,
14894                                  gpointer);
14895 void GtkListItem::unselect-all  (GtkListItem *,
14896                                  gpointer);
14897 void GtkListItem::undo-selection        (GtkListItem *,
14898                                          gpointer);
14899 void GtkListItem::start-selection       (GtkListItem *,
14900                                          gpointer);
14901 void GtkListItem::end-selection (GtkListItem *,
14902                                  gpointer);
14903 void GtkListItem::toggle-add-mode       (GtkListItem *,
14904                                          gpointer);
14905 void GtkListItem::extend-selection      (GtkListItem *,
14906                                          GtkEnum,
14907                                          ggfloat,
14908                                          gboolean,
14909                                          gpointer);
14910 void GtkListItem::scroll-vertical       (GtkListItem *,
14911                                          GtkEnum,
14912                                          ggfloat,
14913                                          gpointer);
14914 void GtkListItem::scroll-horizontal     (GtkListItem *,
14915                                          GtkEnum,
14916                                          ggfloat,
14917                                          gpointer);
14918 </verb></tscreen>
14919
14920 <!-- ----------------------------------------------------------------- -->
14921 <sect1>GtkTreeItem
14922 <!-- ----------------------------------------------------------------- -->
14923 <p>
14924 <tscreen><verb>
14925 void GtkTreeItem::collapse      (GtkTreeItem *,
14926                                  gpointer);
14927 void GtkTreeItem::expand        (GtkTreeItem *,
14928                                  gpointer);
14929 </verb></tscreen>
14930
14931 <!-- ----------------------------------------------------------------- -->
14932 <sect1>GtkCheckMenuItem
14933 <!-- ----------------------------------------------------------------- -->
14934 <p>
14935 <tscreen><verb>
14936 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
14937                                  gpointer);
14938 </verb></tscreen>
14939
14940 <!-- ----------------------------------------------------------------- -->
14941 <sect1>GtkInputDialog
14942 <!-- ----------------------------------------------------------------- -->
14943 <p>
14944 <tscreen><verb>
14945 void GtkInputDialog::enable-device      (GtkInputDialog *,
14946                                          ggint,
14947                                          gpointer);
14948 void GtkInputDialog::disable-device     (GtkInputDialog *,
14949                                          ggint,
14950                                          gpointer);
14951 </verb></tscreen>
14952
14953 <!-- ----------------------------------------------------------------- -->
14954 <sect1>GtkColorSelection
14955 <!-- ----------------------------------------------------------------- -->
14956 <p>
14957 <tscreen><verb>
14958 void GtkColorSelection::color-changed   (GtkColorSelection *,
14959                                          gpointer);
14960 </verb></tscreen>
14961
14962 <!-- ----------------------------------------------------------------- -->
14963 <sect1>GtkStatusBar
14964 <!-- ----------------------------------------------------------------- -->
14965 <p>
14966 <tscreen><verb>
14967 void GtkStatusbar::text-pushed  (GtkStatusbar *,
14968                                  gguint,
14969                                  GtkString *,
14970                                  gpointer);
14971 void GtkStatusbar::text-popped  (GtkStatusbar *,
14972                                  gguint,
14973                                  GtkString *,
14974                                  gpointer);
14975 </verb></tscreen>
14976
14977 <!-- ----------------------------------------------------------------- -->
14978 <sect1>GtkCTree
14979 <!-- ----------------------------------------------------------------- -->
14980 <p>
14981 <tscreen><verb>
14982 void GtkCTree::tree-select-row  (GtkCTree *,
14983                                  GtkCTreeNode *,
14984                                  ggint,
14985                                  gpointer);
14986 void GtkCTree::tree-unselect-row        (GtkCTree *,
14987                                          GtkCTreeNode *,
14988                                          ggint,
14989                                          gpointer);
14990 void GtkCTree::tree-expand      (GtkCTree *,
14991                                  GtkCTreeNode *,
14992                                  gpointer);
14993 void GtkCTree::tree-collapse    (GtkCTree *,
14994                                  ggpointer,
14995                                  gpointer);
14996 void GtkCTree::tree-move        (GtkCTree *,
14997                                  GtkCTreeNode *,
14998                                  GtkCTreeNode *,
14999                                  GtkCTreeNode *,
15000                                  gpointer);
15001 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
15002                                                  GtkCTreeExpansionType,
15003                                                  gpointer);
15004 </verb></tscreen>
15005
15006 <!-- ----------------------------------------------------------------- -->
15007 <sect1>GtkCurve
15008 <!-- ----------------------------------------------------------------- -->
15009 <p>
15010 <tscreen><verb>
15011 void GtkCurve::curve-type-changed       (GtkCurve *,
15012                                          gpointer);
15013 </verb></tscreen>
15014
15015 <!-- ----------------------------------------------------------------- -->
15016 <sect1>GtkAdjustment
15017 <!-- ----------------------------------------------------------------- -->
15018 <p>
15019 <tscreen><verb>
15020 void GtkAdjustment::changed     (GtkAdjustment *,
15021                                  gpointer);
15022 void GtkAdjustment::value-changed       (GtkAdjustment *,
15023                                          gpointer);
15024 </verb></tscreen>
15025
15026 <!-- ***************************************************************** -->
15027 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
15028 <!-- ***************************************************************** -->
15029 <p>
15030 The follwing data types are passed into event handlers by GTK+. For
15031 each data type listed, the signals that use this data type are listed.
15032
15033 <itemize>
15034 <item>  GdkEvent
15035           <itemize>
15036           <item>drag_end_event
15037           </itemize>
15038
15039 <item>  GdkEventType
15040
15041 <item>  GdkEventAny
15042           <itemize>
15043           <item>delete_event
15044           <item>destroy_event
15045           <item>map_event
15046           <item>unmap_event
15047           <item>no_expose_event
15048           </itemize>
15049
15050 <item>  GdkEventExpose
15051           <itemize>
15052           <item>expose_event
15053           </itemize>
15054
15055 <item>  GdkEventNoExpose
15056
15057 <item>  GdkEventVisibility
15058
15059 <item>  GdkEventMotion
15060           <itemize>
15061           <item>motion_notify_event
15062           </itemize>
15063
15064 <item>  GdkEventButton
15065           <itemize>
15066           <item>button_press_event
15067           <item>button_release_event
15068           </itemize>
15069
15070 <item>  GdkEventKey
15071           <itemize>
15072           <item>key_press_event
15073           <item>key_release_event
15074           </itemize>
15075
15076 <item>  GdkEventCrossing
15077           <itemize>
15078           <item>enter_notify_event
15079           <item>leave_notify_event
15080           </itemize>
15081
15082 <item>  GdkEventFocus
15083           <itemize>
15084           <item>focus_in_event
15085           <item>focus_out_event
15086           </itemize>
15087
15088 <item>  GdkEventConfigure
15089           <itemize>
15090           <item>configure_event
15091           </itemize>
15092
15093 <item>  GdkEventProperty
15094           <itemize>
15095           <item>property_notify_event
15096           </itemize>
15097
15098 <item>  GdkEventSelection
15099           <itemize>
15100           <item>selection_clear_event
15101           <item>selection_request_event
15102           <item>selection_notify_event
15103           </itemize>
15104
15105 <item>  GdkEventProximity
15106           <itemize>
15107           <item>proximity_in_event
15108           <item>proximity_out_event
15109           </itemize>
15110
15111 <item>  GdkEventDragBegin
15112           <itemize>
15113           <item>drag_begin_event
15114           </itemize>
15115
15116 <item>  GdkEventDragRequest
15117           <itemize>
15118           <item>drag_request_event
15119           </itemize>
15120
15121 <item>  GdkEventDropEnter
15122           <itemize>
15123           <item>drop_enter_event
15124           </itemize>
15125
15126 <item>  GdkEventDropLeave
15127           <itemize>
15128           <item>drop_leave_event
15129           </itemize>
15130
15131 <item>  GdkEventDropDataAvailable
15132           <itemize>
15133           <item>drop_data_available_event
15134           </itemize>
15135
15136 <item>  GdkEventClient
15137           <itemize>
15138           <item>client_event
15139           </itemize>
15140
15141 <item>  GdkEventOther
15142           <itemize>
15143           <item>other_event
15144           </itemize>
15145 </itemize>
15146
15147 The data type <tt/GdkEventType/ is a special data type that is used by
15148 all the other data types as an indicator of the data type being passed
15149 to the signal handler. As you will see below, each of the event data
15150 structures has a member of this type. It is defined as an enumeration
15151 type as follows:
15152
15153 <tscreen><verb>
15154 typedef enum
15155 {
15156   GDK_NOTHING           = -1,
15157   GDK_DELETE            = 0,
15158   GDK_DESTROY           = 1,
15159   GDK_EXPOSE            = 2,
15160   GDK_MOTION_NOTIFY     = 3,
15161   GDK_BUTTON_PRESS      = 4,
15162   GDK_2BUTTON_PRESS     = 5,
15163   GDK_3BUTTON_PRESS     = 6,
15164   GDK_BUTTON_RELEASE    = 7,
15165   GDK_KEY_PRESS         = 8,
15166   GDK_KEY_RELEASE       = 9,
15167   GDK_ENTER_NOTIFY      = 10,
15168   GDK_LEAVE_NOTIFY      = 11,
15169   GDK_FOCUS_CHANGE      = 12,
15170   GDK_CONFIGURE         = 13,
15171   GDK_MAP               = 14,
15172   GDK_UNMAP             = 15,
15173   GDK_PROPERTY_NOTIFY   = 16,
15174   GDK_SELECTION_CLEAR   = 17,
15175   GDK_SELECTION_REQUEST = 18,
15176   GDK_SELECTION_NOTIFY  = 19,
15177   GDK_PROXIMITY_IN      = 20,
15178   GDK_PROXIMITY_OUT     = 21,
15179   GDK_DRAG_BEGIN        = 22,
15180   GDK_DRAG_REQUEST      = 23,
15181   GDK_DROP_ENTER        = 24,
15182   GDK_DROP_LEAVE        = 25,
15183   GDK_DROP_DATA_AVAIL   = 26,
15184   GDK_CLIENT_EVENT      = 27,
15185   GDK_VISIBILITY_NOTIFY = 28,
15186   GDK_NO_EXPOSE         = 29,
15187   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
15188 } GdkEventType;
15189 </verb></tscreen>
15190
15191 The other event type that is different from the others is
15192 <tt/GdkEvent/ itself. This is a union of all the other
15193 data types, which allows it to be cast to a specific
15194 event data type within a signal handler.
15195
15196 <!-- Just a big list for now, needs expanding upon - TRG -->
15197 So, the event data types are defined as follows:
15198
15199 <tscreen><verb>
15200 struct _GdkEventAny
15201 {
15202   GdkEventType type;
15203   GdkWindow *window;
15204   gint8 send_event;
15205 };
15206
15207 struct _GdkEventExpose
15208 {
15209   GdkEventType type;
15210   GdkWindow *window;
15211   gint8 send_event;
15212   GdkRectangle area;
15213   gint count; /* If non-zero, how many more events follow. */
15214 };
15215
15216 struct _GdkEventNoExpose
15217 {
15218   GdkEventType type;
15219   GdkWindow *window;
15220   gint8 send_event;
15221   /* XXX: does anyone need the X major_code or minor_code fields? */
15222 };
15223
15224 struct _GdkEventVisibility
15225 {
15226   GdkEventType type;
15227   GdkWindow *window;
15228   gint8 send_event;
15229   GdkVisibilityState state;
15230 };
15231
15232 struct _GdkEventMotion
15233 {
15234   GdkEventType type;
15235   GdkWindow *window;
15236   gint8 send_event;
15237   guint32 time;
15238   gdouble x;
15239   gdouble y;
15240   gdouble pressure;
15241   gdouble xtilt;
15242   gdouble ytilt;
15243   guint state;
15244   gint16 is_hint;
15245   GdkInputSource source;
15246   guint32 deviceid;
15247   gdouble x_root, y_root;
15248 };
15249
15250 struct _GdkEventButton
15251 {
15252   GdkEventType type;
15253   GdkWindow *window;
15254   gint8 send_event;
15255   guint32 time;
15256   gdouble x;
15257   gdouble y;
15258   gdouble pressure;
15259   gdouble xtilt;
15260   gdouble ytilt;
15261   guint state;
15262   guint button;
15263   GdkInputSource source;
15264   guint32 deviceid;
15265   gdouble x_root, y_root;
15266 };
15267
15268 struct _GdkEventKey
15269 {
15270   GdkEventType type;
15271   GdkWindow *window;
15272   gint8 send_event;
15273   guint32 time;
15274   guint state;
15275   guint keyval;
15276   gint length;
15277   gchar *string;
15278 };
15279
15280 struct _GdkEventCrossing
15281 {
15282   GdkEventType type;
15283   GdkWindow *window;
15284   gint8 send_event;
15285   GdkWindow *subwindow;
15286   GdkNotifyType detail;
15287 };
15288
15289 struct _GdkEventFocus
15290 {
15291   GdkEventType type;
15292   GdkWindow *window;
15293   gint8 send_event;
15294   gint16 in;
15295 };
15296
15297 struct _GdkEventConfigure
15298 {
15299   GdkEventType type;
15300   GdkWindow *window;
15301   gint8 send_event;
15302   gint16 x, y;
15303   gint16 width;
15304   gint16 height;
15305 };
15306
15307 struct _GdkEventProperty
15308 {
15309   GdkEventType type;
15310   GdkWindow *window;
15311   gint8 send_event;
15312   GdkAtom atom;
15313   guint32 time;
15314   guint state;
15315 };
15316
15317 struct _GdkEventSelection
15318 {
15319   GdkEventType type;
15320   GdkWindow *window;
15321   gint8 send_event;
15322   GdkAtom selection;
15323   GdkAtom target;
15324   GdkAtom property;
15325   guint32 requestor;
15326   guint32 time;
15327 };
15328
15329 /* This event type will be used pretty rarely. It only is important
15330    for XInput aware programs that are drawing their own cursor */
15331
15332 struct _GdkEventProximity
15333 {
15334   GdkEventType type;
15335   GdkWindow *window;
15336   gint8 send_event;
15337   guint32 time;
15338   GdkInputSource source;
15339   guint32 deviceid;
15340 };
15341
15342 struct _GdkEventDragRequest
15343 {
15344   GdkEventType type;
15345   GdkWindow *window;
15346   gint8 send_event;
15347   guint32 requestor;
15348   union {
15349     struct {
15350       guint protocol_version:4;
15351       guint sendreply:1;
15352       guint willaccept:1;
15353       guint delete_data:1; /* Do *not* delete if link is sent, only
15354                               if data is sent */
15355       guint senddata:1;
15356       guint reserved:22;
15357     } flags;
15358     glong allflags;
15359   } u;
15360   guint8 isdrop; /* This gdk event can be generated by a couple of
15361                     X events - this lets the app know whether the
15362                     drop really occurred or we just set the data */
15363
15364   GdkPoint drop_coords;
15365   gchar *data_type;
15366   guint32 timestamp;
15367 };
15368
15369 struct _GdkEventDragBegin
15370 {
15371   GdkEventType type;
15372   GdkWindow *window;
15373   gint8 send_event;
15374   union {
15375     struct {
15376       guint protocol_version:4;
15377       guint reserved:28;
15378     } flags;
15379     glong allflags;
15380   } u;
15381 };
15382
15383 struct _GdkEventDropEnter
15384 {
15385   GdkEventType type;
15386   GdkWindow *window;
15387   gint8 send_event;
15388   guint32 requestor;
15389   union {
15390     struct {
15391       guint protocol_version:4;
15392       guint sendreply:1;
15393       guint extended_typelist:1;
15394       guint reserved:26;
15395     } flags;
15396     glong allflags;
15397   } u;
15398 };
15399
15400 struct _GdkEventDropLeave
15401 {
15402   GdkEventType type;
15403   GdkWindow *window;
15404   gint8 send_event;
15405   guint32 requestor;
15406   union {
15407     struct {
15408       guint protocol_version:4;
15409       guint reserved:28;
15410     } flags;
15411     glong allflags;
15412   } u;
15413 };
15414
15415 struct _GdkEventDropDataAvailable
15416 {
15417   GdkEventType type;
15418   GdkWindow *window;
15419   gint8 send_event;
15420   guint32 requestor;
15421   union {
15422     struct {
15423       guint protocol_version:4;
15424       guint isdrop:1;
15425       guint reserved:25;
15426     } flags;
15427     glong allflags;
15428   } u;
15429   gchar *data_type; /* MIME type */
15430   gulong data_numbytes;
15431   gpointer data;
15432   guint32 timestamp;
15433   GdkPoint coords;
15434 };
15435
15436 struct _GdkEventClient
15437 {
15438   GdkEventType type;
15439   GdkWindow *window;
15440   gint8 send_event;
15441   GdkAtom message_type;
15442   gushort data_format;
15443   union {
15444     char b[20];
15445     short s[10];
15446     long l[5];
15447   } data;
15448 };
15449
15450 struct _GdkEventOther
15451 {
15452   GdkEventType type;
15453   GdkWindow *window;
15454   gint8 send_event;
15455   GdkXEvent *xevent;
15456 };
15457 </verb></tscreen>
15458
15459 <!-- ***************************************************************** -->
15460 <sect> Code Examples
15461 <!-- ***************************************************************** -->
15462 <p>
15463 Below are the code examples that are used in the above text
15464 which are not included in complete form elsewhere.
15465
15466 <!-- ----------------------------------------------------------------- -->
15467 <sect1>Tictactoe
15468 <!-- ----------------------------------------------------------------- -->
15469 <sect2>tictactoe.h
15470 <p>
15471 <tscreen><verb>
15472 /* example-start tictactoe tictactoe.h */
15473
15474 /* GTK - The GIMP Toolkit
15475  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15476  *
15477  * This library is free software; you can redistribute it and/or
15478  * modify it under the terms of the GNU Library General Public
15479  * License as published by the Free Software Foundation; either
15480  * version 2 of the License, or (at your option) any later version.
15481  *
15482  * This library is distributed in the hope that it will be useful,
15483  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15484  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15485  * Library General Public License for more details.
15486  *
15487  * You should have received a copy of the GNU Library General Public
15488  * License along with this library; if not, write to the
15489  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15490  * Boston, MA 02111-1307, USA.
15491  */
15492 #ifndef __TICTACTOE_H__
15493 #define __TICTACTOE_H__
15494
15495
15496 #include <gdk/gdk.h>
15497 #include <gtk/gtkvbox.h>
15498
15499
15500 #ifdef __cplusplus
15501 extern "C" {
15502 #endif /* __cplusplus */
15503
15504 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
15505 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
15506 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
15507
15508
15509 typedef struct _Tictactoe       Tictactoe;
15510 typedef struct _TictactoeClass  TictactoeClass;
15511
15512 struct _Tictactoe
15513 {
15514   GtkVBox vbox;
15515   
15516   GtkWidget *buttons[3][3];
15517 };
15518
15519 struct _TictactoeClass
15520 {
15521   GtkVBoxClass parent_class;
15522
15523   void (* tictactoe) (Tictactoe *ttt);
15524 };
15525
15526 guint          tictactoe_get_type        (void);
15527 GtkWidget*     tictactoe_new             (void);
15528 void           tictactoe_clear           (Tictactoe *ttt);
15529
15530 #ifdef __cplusplus
15531 }
15532 #endif /* __cplusplus */
15533
15534 #endif /* __TICTACTOE_H__ */
15535
15536 /* example-end */
15537 </verb></tscreen>
15538
15539 <!-- ----------------------------------------------------------------- -->
15540 <sect2>tictactoe.c
15541 <p>
15542 <tscreen><verb>
15543 /* example-start tictactoe tictactoe.c */
15544
15545 /* GTK - The GIMP Toolkit
15546  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15547  *
15548  * This library is free software; you can redistribute it and/or
15549  * modify it under the terms of the GNU Library General Public
15550  * License as published by the Free Software Foundation; either
15551  * version 2 of the License, or (at your option) any later version.
15552  *
15553  * This library is distributed in the hope that it will be useful,
15554  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15555  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15556  * Library General Public License for more details.
15557  *
15558  * You should have received a copy of the GNU Library General Public
15559  * License along with this library; if not, write to the
15560  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15561  * Boston, MA 02111-1307, USA.
15562  */
15563 #include "gtk/gtksignal.h"
15564 #include "gtk/gtktable.h"
15565 #include "gtk/gtktogglebutton.h"
15566 #include "tictactoe.h"
15567
15568 enum {
15569   TICTACTOE_SIGNAL,
15570   LAST_SIGNAL
15571 };
15572
15573 static void tictactoe_class_init          (TictactoeClass *klass);
15574 static void tictactoe_init                (Tictactoe      *ttt);
15575 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
15576
15577 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
15578
15579 guint
15580 tictactoe_get_type ()
15581 {
15582   static guint ttt_type = 0;
15583
15584   if (!ttt_type)
15585     {
15586       GtkTypeInfo ttt_info =
15587       {
15588         "Tictactoe",
15589         sizeof (Tictactoe),
15590         sizeof (TictactoeClass),
15591         (GtkClassInitFunc) tictactoe_class_init,
15592         (GtkObjectInitFunc) tictactoe_init,
15593         (GtkArgSetFunc) NULL,
15594         (GtkArgGetFunc) NULL
15595       };
15596
15597       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
15598     }
15599
15600   return ttt_type;
15601 }
15602
15603 static void
15604 tictactoe_class_init (TictactoeClass *class)
15605 {
15606   GtkObjectClass *object_class;
15607
15608   object_class = (GtkObjectClass*) class;
15609   
15610   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
15611                                          GTK_RUN_FIRST,
15612                                          object_class->type,
15613                                          GTK_SIGNAL_OFFSET (TictactoeClass,
15614                                                             tictactoe),
15615                                          gtk_signal_default_marshaller,
15616                                          GTK_TYPE_NONE, 0);
15617
15618
15619   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
15620
15621   class->tictactoe = NULL;
15622 }
15623
15624 static void
15625 tictactoe_init (Tictactoe *ttt)
15626 {
15627   GtkWidget *table;
15628   gint i,j;
15629   
15630   table = gtk_table_new (3, 3, TRUE);
15631   gtk_container_add (GTK_CONTAINER(ttt), table);
15632   gtk_widget_show (table);
15633
15634   for (i=0;i<3; i++)
15635     for (j=0;j<3; j++)
15636       {
15637         ttt->buttons[i][j] = gtk_toggle_button_new ();
15638         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
15639                                    i, i+1, j, j+1);
15640         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
15641                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
15642         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
15643         gtk_widget_show (ttt->buttons[i][j]);
15644       }
15645 }
15646
15647 GtkWidget*
15648 tictactoe_new ()
15649 {
15650   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
15651 }
15652
15653 void           
15654 tictactoe_clear (Tictactoe *ttt)
15655 {
15656   int i,j;
15657
15658   for (i=0;i<3;i++)
15659     for (j=0;j<3;j++)
15660       {
15661         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15662         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
15663                                      FALSE);
15664         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15665       }
15666 }
15667
15668 static void
15669 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
15670 {
15671   int i,k;
15672
15673   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15674                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15675                              { 0, 1, 2 }, { 0, 1, 2 } };
15676   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15677                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15678                              { 0, 1, 2 }, { 2, 1, 0 } };
15679
15680   int success, found;
15681
15682   for (k=0; k<8; k++)
15683     {
15684       success = TRUE;
15685       found = FALSE;
15686
15687       for (i=0;i<3;i++)
15688         {
15689           success = success &amp;&amp; 
15690             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
15691           found = found ||
15692             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
15693         }
15694       
15695       if (success &amp;&amp; found)
15696         {
15697           gtk_signal_emit (GTK_OBJECT (ttt), 
15698                            tictactoe_signals[TICTACTOE_SIGNAL]);
15699           break;
15700         }
15701     }
15702 }
15703
15704 /* example-end */
15705 </verb></tscreen>
15706
15707 <!-- ----------------------------------------------------------------- -->
15708 <sect2>ttt_test.c
15709 <p>
15710 <tscreen><verb>
15711 /* example-start tictactoe ttt_test.c */
15712
15713 #include <gtk/gtk.h>
15714 #include "tictactoe.h"
15715
15716 void
15717 win (GtkWidget *widget, gpointer data)
15718 {
15719   g_print ("Yay!\n");
15720   tictactoe_clear (TICTACTOE (widget));
15721 }
15722
15723 int 
15724 main (int argc, char *argv[])
15725 {
15726   GtkWidget *window;
15727   GtkWidget *ttt;
15728   
15729   gtk_init (&amp;argc, &amp;argv);
15730
15731   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15732   
15733   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
15734   
15735   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15736                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
15737   
15738   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15739
15740   ttt = tictactoe_new ();
15741   
15742   gtk_container_add (GTK_CONTAINER (window), ttt);
15743   gtk_widget_show (ttt);
15744
15745   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
15746                       GTK_SIGNAL_FUNC (win), NULL);
15747
15748   gtk_widget_show (window);
15749   
15750   gtk_main ();
15751   
15752   return 0;
15753 }
15754
15755 /* example-end */
15756 </verb></tscreen>
15757
15758 <!-- ----------------------------------------------------------------- -->
15759 <sect1> GtkDial
15760
15761 <!-- ----------------------------------------------------------------- -->
15762 <sect2> gtkdial.h
15763 <p>
15764 <tscreen><verb>
15765 /* example-start gtkdial gtkdial.h */
15766
15767 /* GTK - The GIMP Toolkit
15768  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15769  *
15770  * This library is free software; you can redistribute it and/or
15771  * modify it under the terms of the GNU Library General Public
15772  * License as published by the Free Software Foundation; either
15773  * version 2 of the License, or (at your option) any later version.
15774  *
15775  * This library is distributed in the hope that it will be useful,
15776  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15777  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15778  * Library General Public License for more details.
15779  *
15780  * You should have received a copy of the GNU Library General Public
15781  * License along with this library; if not, write to the
15782  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15783  * Boston, MA 02111-1307, USA.
15784  */
15785 #ifndef __GTK_DIAL_H__
15786 #define __GTK_DIAL_H__
15787
15788
15789 #include <gdk/gdk.h>
15790 #include <gtk/gtkadjustment.h>
15791 #include <gtk/gtkwidget.h>
15792
15793
15794 #ifdef __cplusplus
15795 extern "C" {
15796 #endif /* __cplusplus */
15797
15798
15799 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
15800 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
15801 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
15802
15803
15804 typedef struct _GtkDial        GtkDial;
15805 typedef struct _GtkDialClass   GtkDialClass;
15806
15807 struct _GtkDial
15808 {
15809   GtkWidget widget;
15810
15811   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
15812   guint policy : 2;
15813
15814   /* Button currently pressed or 0 if none */
15815   guint8 button;
15816
15817   /* Dimensions of dial components */
15818   gint radius;
15819   gint pointer_width;
15820
15821   /* ID of update timer, or 0 if none */
15822   guint32 timer;
15823
15824   /* Current angle */
15825   gfloat angle;
15826
15827   /* Old values from adjustment stored so we know when something changes */
15828   gfloat old_value;
15829   gfloat old_lower;
15830   gfloat old_upper;
15831
15832   /* The adjustment object that stores the data for this dial */
15833   GtkAdjustment *adjustment;
15834 };
15835
15836 struct _GtkDialClass
15837 {
15838   GtkWidgetClass parent_class;
15839 };
15840
15841
15842 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
15843 guint          gtk_dial_get_type               (void);
15844 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
15845 void           gtk_dial_set_update_policy      (GtkDial      *dial,
15846                                                 GtkUpdateType  policy);
15847
15848 void           gtk_dial_set_adjustment         (GtkDial      *dial,
15849                                                 GtkAdjustment *adjustment);
15850 #ifdef __cplusplus
15851 }
15852 #endif /* __cplusplus */
15853
15854
15855 #endif /* __GTK_DIAL_H__ */
15856 /* example-end */
15857 </verb></tscreen>
15858
15859 <!-- ----------------------------------------------------------------- -->
15860 <sect2> gtkdial.c
15861 <p>
15862 <tscreen><verb>
15863 /* example-start gtkdial gtkdial.c */
15864
15865 /* GTK - The GIMP Toolkit
15866  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15867  *
15868  * This library is free software; you can redistribute it and/or
15869  * modify it under the terms of the GNU Library General Public
15870  * License as published by the Free Software Foundation; either
15871  * version 2 of the License, or (at your option) any later version.
15872  *
15873  * This library is distributed in the hope that it will be useful,
15874  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15875  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15876  * Library General Public License for more details.
15877  *
15878  * You should have received a copy of the GNU Library General Public
15879  * License along with this library; if not, write to the
15880  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15881  * Boston, MA 02111-1307, USA.
15882  */
15883 #include <math.h>
15884 #include <stdio.h>
15885 #include <gtk/gtkmain.h>
15886 #include <gtk/gtksignal.h>
15887
15888 #include "gtkdial.h"
15889
15890 #define SCROLL_DELAY_LENGTH  300
15891 #define DIAL_DEFAULT_SIZE 100
15892
15893 /* Forward declarations */
15894
15895 static void gtk_dial_class_init               (GtkDialClass    *klass);
15896 static void gtk_dial_init                     (GtkDial         *dial);
15897 static void gtk_dial_destroy                  (GtkObject        *object);
15898 static void gtk_dial_realize                  (GtkWidget        *widget);
15899 static void gtk_dial_size_request             (GtkWidget      *widget,
15900                                                GtkRequisition *requisition);
15901 static void gtk_dial_size_allocate            (GtkWidget     *widget,
15902                                                GtkAllocation *allocation);
15903 static gint gtk_dial_expose                   (GtkWidget        *widget,
15904                                                 GdkEventExpose   *event);
15905 static gint gtk_dial_button_press             (GtkWidget        *widget,
15906                                                 GdkEventButton   *event);
15907 static gint gtk_dial_button_release           (GtkWidget        *widget,
15908                                                 GdkEventButton   *event);
15909 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
15910                                                 GdkEventMotion   *event);
15911 static gint gtk_dial_timer                    (GtkDial         *dial);
15912
15913 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
15914 static void gtk_dial_update                   (GtkDial *dial);
15915 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
15916                                                 gpointer          data);
15917 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
15918                                                 gpointer          data);
15919
15920 /* Local data */
15921
15922 static GtkWidgetClass *parent_class = NULL;
15923
15924 guint
15925 gtk_dial_get_type ()
15926 {
15927   static guint dial_type = 0;
15928
15929   if (!dial_type)
15930     {
15931       GtkTypeInfo dial_info =
15932       {
15933         "GtkDial",
15934         sizeof (GtkDial),
15935         sizeof (GtkDialClass),
15936         (GtkClassInitFunc) gtk_dial_class_init,
15937         (GtkObjectInitFunc) gtk_dial_init,
15938         (GtkArgSetFunc) NULL,
15939         (GtkArgGetFunc) NULL,
15940       };
15941
15942       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
15943     }
15944
15945   return dial_type;
15946 }
15947
15948 static void
15949 gtk_dial_class_init (GtkDialClass *class)
15950 {
15951   GtkObjectClass *object_class;
15952   GtkWidgetClass *widget_class;
15953
15954   object_class = (GtkObjectClass*) class;
15955   widget_class = (GtkWidgetClass*) class;
15956
15957   parent_class = gtk_type_class (gtk_widget_get_type ());
15958
15959   object_class->destroy = gtk_dial_destroy;
15960
15961   widget_class->realize = gtk_dial_realize;
15962   widget_class->expose_event = gtk_dial_expose;
15963   widget_class->size_request = gtk_dial_size_request;
15964   widget_class->size_allocate = gtk_dial_size_allocate;
15965   widget_class->button_press_event = gtk_dial_button_press;
15966   widget_class->button_release_event = gtk_dial_button_release;
15967   widget_class->motion_notify_event = gtk_dial_motion_notify;
15968 }
15969
15970 static void
15971 gtk_dial_init (GtkDial *dial)
15972 {
15973   dial->button = 0;
15974   dial->policy = GTK_UPDATE_CONTINUOUS;
15975   dial->timer = 0;
15976   dial->radius = 0;
15977   dial->pointer_width = 0;
15978   dial->angle = 0.0;
15979   dial->old_value = 0.0;
15980   dial->old_lower = 0.0;
15981   dial->old_upper = 0.0;
15982   dial->adjustment = NULL;
15983 }
15984
15985 GtkWidget*
15986 gtk_dial_new (GtkAdjustment *adjustment)
15987 {
15988   GtkDial *dial;
15989
15990   dial = gtk_type_new (gtk_dial_get_type ());
15991
15992   if (!adjustment)
15993     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0,
15994                                                       0.0, 0.0, 0.0);
15995
15996   gtk_dial_set_adjustment (dial, adjustment);
15997
15998   return GTK_WIDGET (dial);
15999 }
16000
16001 static void
16002 gtk_dial_destroy (GtkObject *object)
16003 {
16004   GtkDial *dial;
16005
16006   g_return_if_fail (object != NULL);
16007   g_return_if_fail (GTK_IS_DIAL (object));
16008
16009   dial = GTK_DIAL (object);
16010
16011   if (dial->adjustment)
16012     gtk_object_unref (GTK_OBJECT (dial->adjustment));
16013
16014   if (GTK_OBJECT_CLASS (parent_class)->destroy)
16015     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
16016 }
16017
16018 GtkAdjustment*
16019 gtk_dial_get_adjustment (GtkDial *dial)
16020 {
16021   g_return_val_if_fail (dial != NULL, NULL);
16022   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
16023
16024   return dial->adjustment;
16025 }
16026
16027 void
16028 gtk_dial_set_update_policy (GtkDial      *dial,
16029                              GtkUpdateType  policy)
16030 {
16031   g_return_if_fail (dial != NULL);
16032   g_return_if_fail (GTK_IS_DIAL (dial));
16033
16034   dial->policy = policy;
16035 }
16036
16037 void
16038 gtk_dial_set_adjustment (GtkDial      *dial,
16039                           GtkAdjustment *adjustment)
16040 {
16041   g_return_if_fail (dial != NULL);
16042   g_return_if_fail (GTK_IS_DIAL (dial));
16043
16044   if (dial->adjustment)
16045     {
16046       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment),
16047                                      (gpointer) dial);
16048       gtk_object_unref (GTK_OBJECT (dial->adjustment));
16049     }
16050
16051   dial->adjustment = adjustment;
16052   gtk_object_ref (GTK_OBJECT (dial->adjustment));
16053
16054   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
16055                       (GtkSignalFunc) gtk_dial_adjustment_changed,
16056                       (gpointer) dial);
16057   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
16058                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
16059                       (gpointer) dial);
16060
16061   dial->old_value = adjustment->value;
16062   dial->old_lower = adjustment->lower;
16063   dial->old_upper = adjustment->upper;
16064
16065   gtk_dial_update (dial);
16066 }
16067
16068 static void
16069 gtk_dial_realize (GtkWidget *widget)
16070 {
16071   GtkDial *dial;
16072   GdkWindowAttr attributes;
16073   gint attributes_mask;
16074
16075   g_return_if_fail (widget != NULL);
16076   g_return_if_fail (GTK_IS_DIAL (widget));
16077
16078   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
16079   dial = GTK_DIAL (widget);
16080
16081   attributes.x = widget->allocation.x;
16082   attributes.y = widget->allocation.y;
16083   attributes.width = widget->allocation.width;
16084   attributes.height = widget->allocation.height;
16085   attributes.wclass = GDK_INPUT_OUTPUT;
16086   attributes.window_type = GDK_WINDOW_CHILD;
16087   attributes.event_mask = gtk_widget_get_events (widget) | 
16088     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
16089     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
16090     GDK_POINTER_MOTION_HINT_MASK;
16091   attributes.visual = gtk_widget_get_visual (widget);
16092   attributes.colormap = gtk_widget_get_colormap (widget);
16093
16094   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
16095   widget->window = gdk_window_new (widget->parent->window,
16096                                    &amp;attributes,
16097                                    attributes_mask);
16098
16099   widget->style = gtk_style_attach (widget->style, widget->window);
16100
16101   gdk_window_set_user_data (widget->window, widget);
16102
16103   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
16104 }
16105
16106 static void 
16107 gtk_dial_size_request (GtkWidget      *widget,
16108                        GtkRequisition *requisition)
16109 {
16110   requisition->width = DIAL_DEFAULT_SIZE;
16111   requisition->height = DIAL_DEFAULT_SIZE;
16112 }
16113
16114 static void
16115 gtk_dial_size_allocate (GtkWidget     *widget,
16116                         GtkAllocation *allocation)
16117 {
16118   GtkDial *dial;
16119
16120   g_return_if_fail (widget != NULL);
16121   g_return_if_fail (GTK_IS_DIAL (widget));
16122   g_return_if_fail (allocation != NULL);
16123
16124   widget->allocation = *allocation;
16125   dial = GTK_DIAL (widget);
16126
16127   if (GTK_WIDGET_REALIZED (widget))
16128     {
16129
16130       gdk_window_move_resize (widget->window,
16131                               allocation->x, allocation->y,
16132                               allocation->width, allocation->height);
16133
16134     }
16135   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
16136   dial->pointer_width = dial->radius / 5;
16137 }
16138
16139 static gint
16140 gtk_dial_expose (GtkWidget      *widget,
16141                  GdkEventExpose *event)
16142 {
16143   GtkDial *dial;
16144   GdkPoint points[3];
16145   gdouble s,c;
16146   gdouble theta;
16147   gint xc, yc;
16148   gint tick_length;
16149   gint i;
16150
16151   g_return_val_if_fail (widget != NULL, FALSE);
16152   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16153   g_return_val_if_fail (event != NULL, FALSE);
16154
16155   if (event->count > 0)
16156     return FALSE;
16157   
16158   dial = GTK_DIAL (widget);
16159
16160   gdk_window_clear_area (widget->window,
16161                          0, 0,
16162                          widget->allocation.width,
16163                          widget->allocation.height);
16164
16165   xc = widget->allocation.width/2;
16166   yc = widget->allocation.height/2;
16167
16168   /* Draw ticks */
16169
16170   for (i=0; i<25; i++)
16171     {
16172       theta = (i*M_PI/18. - M_PI/6.);
16173       s = sin(theta);
16174       c = cos(theta);
16175
16176       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
16177       
16178       gdk_draw_line (widget->window,
16179                      widget->style->fg_gc[widget->state],
16180                      xc + c*(dial->radius - tick_length),
16181                      yc - s*(dial->radius - tick_length),
16182                      xc + c*dial->radius,
16183                      yc - s*dial->radius);
16184     }
16185
16186   /* Draw pointer */
16187
16188   s = sin(dial->angle);
16189   c = cos(dial->angle);
16190
16191
16192   points[0].x = xc + s*dial->pointer_width/2;
16193   points[0].y = yc + c*dial->pointer_width/2;
16194   points[1].x = xc + c*dial->radius;
16195   points[1].y = yc - s*dial->radius;
16196   points[2].x = xc - s*dial->pointer_width/2;
16197   points[2].y = yc - c*dial->pointer_width/2;
16198
16199   gtk_draw_polygon (widget->style,
16200                     widget->window,
16201                     GTK_STATE_NORMAL,
16202                     GTK_SHADOW_OUT,
16203                     points, 3,
16204                     TRUE);
16205   
16206   return FALSE;
16207 }
16208
16209 static gint
16210 gtk_dial_button_press (GtkWidget      *widget,
16211                        GdkEventButton *event)
16212 {
16213   GtkDial *dial;
16214   gint dx, dy;
16215   double s, c;
16216   double d_parallel;
16217   double d_perpendicular;
16218
16219   g_return_val_if_fail (widget != NULL, FALSE);
16220   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16221   g_return_val_if_fail (event != NULL, FALSE);
16222
16223   dial = GTK_DIAL (widget);
16224
16225   /* Determine if button press was within pointer region - we 
16226      do this by computing the parallel and perpendicular distance of
16227      the point where the mouse was pressed from the line passing through
16228      the pointer */
16229   
16230   dx = event->x - widget->allocation.width / 2;
16231   dy = widget->allocation.height / 2 - event->y;
16232   
16233   s = sin(dial->angle);
16234   c = cos(dial->angle);
16235   
16236   d_parallel = s*dy + c*dx;
16237   d_perpendicular = fabs(s*dx - c*dy);
16238   
16239   if (!dial->button &amp;&amp;
16240       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
16241       (d_parallel > - dial->pointer_width))
16242     {
16243       gtk_grab_add (widget);
16244
16245       dial->button = event->button;
16246
16247       gtk_dial_update_mouse (dial, event->x, event->y);
16248     }
16249
16250   return FALSE;
16251 }
16252
16253 static gint
16254 gtk_dial_button_release (GtkWidget      *widget,
16255                           GdkEventButton *event)
16256 {
16257   GtkDial *dial;
16258
16259   g_return_val_if_fail (widget != NULL, FALSE);
16260   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16261   g_return_val_if_fail (event != NULL, FALSE);
16262
16263   dial = GTK_DIAL (widget);
16264
16265   if (dial->button == event->button)
16266     {
16267       gtk_grab_remove (widget);
16268
16269       dial->button = 0;
16270
16271       if (dial->policy == GTK_UPDATE_DELAYED)
16272         gtk_timeout_remove (dial->timer);
16273       
16274       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
16275           (dial->old_value != dial->adjustment->value))
16276         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16277                                  "value_changed");
16278     }
16279
16280   return FALSE;
16281 }
16282
16283 static gint
16284 gtk_dial_motion_notify (GtkWidget      *widget,
16285                          GdkEventMotion *event)
16286 {
16287   GtkDial *dial;
16288   GdkModifierType mods;
16289   gint x, y, mask;
16290
16291   g_return_val_if_fail (widget != NULL, FALSE);
16292   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16293   g_return_val_if_fail (event != NULL, FALSE);
16294
16295   dial = GTK_DIAL (widget);
16296
16297   if (dial->button != 0)
16298     {
16299       x = event->x;
16300       y = event->y;
16301
16302       if (event->is_hint || (event->window != widget->window))
16303         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
16304
16305       switch (dial->button)
16306         {
16307         case 1:
16308           mask = GDK_BUTTON1_MASK;
16309           break;
16310         case 2:
16311           mask = GDK_BUTTON2_MASK;
16312           break;
16313         case 3:
16314           mask = GDK_BUTTON3_MASK;
16315           break;
16316         default:
16317           mask = 0;
16318           break;
16319         }
16320
16321       if (mods &amp; mask)
16322         gtk_dial_update_mouse (dial, x,y);
16323     }
16324
16325   return FALSE;
16326 }
16327
16328 static gint
16329 gtk_dial_timer (GtkDial *dial)
16330 {
16331   g_return_val_if_fail (dial != NULL, FALSE);
16332   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
16333
16334   if (dial->policy == GTK_UPDATE_DELAYED)
16335     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16336                              "value_changed");
16337
16338   return FALSE;
16339 }
16340
16341 static void
16342 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
16343 {
16344   gint xc, yc;
16345   gfloat old_value;
16346
16347   g_return_if_fail (dial != NULL);
16348   g_return_if_fail (GTK_IS_DIAL (dial));
16349
16350   xc = GTK_WIDGET(dial)->allocation.width / 2;
16351   yc = GTK_WIDGET(dial)->allocation.height / 2;
16352
16353   old_value = dial->adjustment->value;
16354   dial->angle = atan2(yc-y, x-xc);
16355
16356   if (dial->angle < -M_PI/2.)
16357     dial->angle += 2*M_PI;
16358
16359   if (dial->angle < -M_PI/6)
16360     dial->angle = -M_PI/6;
16361
16362   if (dial->angle > 7.*M_PI/6.)
16363     dial->angle = 7.*M_PI/6.;
16364
16365   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
16366     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
16367
16368   if (dial->adjustment->value != old_value)
16369     {
16370       if (dial->policy == GTK_UPDATE_CONTINUOUS)
16371         {
16372           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16373                                    "value_changed");
16374         }
16375       else
16376         {
16377           gtk_widget_draw (GTK_WIDGET(dial), NULL);
16378
16379           if (dial->policy == GTK_UPDATE_DELAYED)
16380             {
16381               if (dial->timer)
16382                 gtk_timeout_remove (dial->timer);
16383
16384               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
16385                                              (GtkFunction) gtk_dial_timer,
16386                                              (gpointer) dial);
16387             }
16388         }
16389     }
16390 }
16391
16392 static void
16393 gtk_dial_update (GtkDial *dial)
16394 {
16395   gfloat new_value;
16396   
16397   g_return_if_fail (dial != NULL);
16398   g_return_if_fail (GTK_IS_DIAL (dial));
16399
16400   new_value = dial->adjustment->value;
16401   
16402   if (new_value < dial->adjustment->lower)
16403     new_value = dial->adjustment->lower;
16404
16405   if (new_value > dial->adjustment->upper)
16406     new_value = dial->adjustment->upper;
16407
16408   if (new_value != dial->adjustment->value)
16409     {
16410       dial->adjustment->value = new_value;
16411       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16412     }
16413
16414   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 
16415                               4.*M_PI/3. /
16416     (dial->adjustment->upper - dial->adjustment->lower);
16417
16418   gtk_widget_draw (GTK_WIDGET(dial), NULL);
16419 }
16420
16421 static void
16422 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
16423                               gpointer       data)
16424 {
16425   GtkDial *dial;
16426
16427   g_return_if_fail (adjustment != NULL);
16428   g_return_if_fail (data != NULL);
16429
16430   dial = GTK_DIAL (data);
16431
16432   if ((dial->old_value != adjustment->value) ||
16433       (dial->old_lower != adjustment->lower) ||
16434       (dial->old_upper != adjustment->upper))
16435     {
16436       gtk_dial_update (dial);
16437
16438       dial->old_value = adjustment->value;
16439       dial->old_lower = adjustment->lower;
16440       dial->old_upper = adjustment->upper;
16441     }
16442 }
16443
16444 static void
16445 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
16446                                     gpointer       data)
16447 {
16448   GtkDial *dial;
16449
16450   g_return_if_fail (adjustment != NULL);
16451   g_return_if_fail (data != NULL);
16452
16453   dial = GTK_DIAL (data);
16454
16455   if (dial->old_value != adjustment->value)
16456     {
16457       gtk_dial_update (dial);
16458
16459       dial->old_value = adjustment->value;
16460     }
16461 }
16462 /* example-end */
16463 </verb></tscreen>
16464
16465 <!-- ----------------------------------------------------------------- -->
16466 <sect1> Scribble
16467 <p>
16468 <tscreen><verb>
16469 /* example-start scribble-simple scribble-simple.c */
16470
16471 /* GTK - The GIMP Toolkit
16472  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16473  *
16474  * This library is free software; you can redistribute it and/or
16475  * modify it under the terms of the GNU Library General Public
16476  * License as published by the Free Software Foundation; either
16477  * version 2 of the License, or (at your option) any later version.
16478  *
16479  * This library is distributed in the hope that it will be useful,
16480  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16481  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16482  * Library General Public License for more details.
16483  *
16484  * You should have received a copy of the GNU Library General Public
16485  * License along with this library; if not, write to the
16486  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16487  * Boston, MA 02111-1307, USA.
16488  */
16489
16490 #include <gtk/gtk.h>
16491
16492 /* Backing pixmap for drawing area */
16493 static GdkPixmap *pixmap = NULL;
16494
16495 /* Create a new backing pixmap of the appropriate size */
16496 static gint
16497 configure_event (GtkWidget *widget, GdkEventConfigure *event)
16498 {
16499   if (pixmap)
16500     gdk_pixmap_unref(pixmap);
16501
16502   pixmap = gdk_pixmap_new(widget->window,
16503                           widget->allocation.width,
16504                           widget->allocation.height,
16505                           -1);
16506   gdk_draw_rectangle (pixmap,
16507                       widget->style->white_gc,
16508                       TRUE,
16509                       0, 0,
16510                       widget->allocation.width,
16511                       widget->allocation.height);
16512
16513   return TRUE;
16514 }
16515
16516 /* Redraw the screen from the backing pixmap */
16517 static gint
16518 expose_event (GtkWidget *widget, GdkEventExpose *event)
16519 {
16520   gdk_draw_pixmap(widget->window,
16521                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
16522                   pixmap,
16523                   event->area.x, event->area.y,
16524                   event->area.x, event->area.y,
16525                   event->area.width, event->area.height);
16526
16527   return FALSE;
16528 }
16529
16530 /* Draw a rectangle on the screen */
16531 static void
16532 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
16533 {
16534   GdkRectangle update_rect;
16535
16536   update_rect.x = x - 5;
16537   update_rect.y = y - 5;
16538   update_rect.width = 10;
16539   update_rect.height = 10;
16540   gdk_draw_rectangle (pixmap,
16541                       widget->style->black_gc,
16542                       TRUE,
16543                       update_rect.x, update_rect.y,
16544                       update_rect.width, update_rect.height);
16545   gtk_widget_draw (widget, &amp;update_rect);
16546 }
16547
16548 static gint
16549 button_press_event (GtkWidget *widget, GdkEventButton *event)
16550 {
16551   if (event->button == 1 &amp;&amp; pixmap != NULL)
16552     draw_brush (widget, event->x, event->y);
16553
16554   return TRUE;
16555 }
16556
16557 static gint
16558 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
16559 {
16560   int x, y;
16561   GdkModifierType state;
16562
16563   if (event->is_hint)
16564     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
16565   else
16566     {
16567       x = event->x;
16568       y = event->y;
16569       state = event->state;
16570     }
16571     
16572   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
16573     draw_brush (widget, x, y);
16574   
16575   return TRUE;
16576 }
16577
16578 void
16579 quit ()
16580 {
16581   gtk_exit (0);
16582 }
16583
16584 int
16585 main (int argc, char *argv[])
16586 {
16587   GtkWidget *window;
16588   GtkWidget *drawing_area;
16589   GtkWidget *vbox;
16590
16591   GtkWidget *button;
16592
16593   gtk_init (&amp;argc, &amp;argv);
16594
16595   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16596   gtk_widget_set_name (window, "Test Input");
16597
16598   vbox = gtk_vbox_new (FALSE, 0);
16599   gtk_container_add (GTK_CONTAINER (window), vbox);
16600   gtk_widget_show (vbox);
16601
16602   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16603                       GTK_SIGNAL_FUNC (quit), NULL);
16604
16605   /* Create the drawing area */
16606
16607   drawing_area = gtk_drawing_area_new ();
16608   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
16609   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16610
16611   gtk_widget_show (drawing_area);
16612
16613   /* Signals used to handle backing pixmap */
16614
16615   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
16616                       (GtkSignalFunc) expose_event, NULL);
16617   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
16618                       (GtkSignalFunc) configure_event, NULL);
16619
16620   /* Event signals */
16621
16622   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
16623                       (GtkSignalFunc) motion_notify_event, NULL);
16624   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
16625                       (GtkSignalFunc) button_press_event, NULL);
16626
16627   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16628                          | GDK_LEAVE_NOTIFY_MASK
16629                          | GDK_BUTTON_PRESS_MASK
16630                          | GDK_POINTER_MOTION_MASK
16631                          | GDK_POINTER_MOTION_HINT_MASK);
16632
16633   /* .. And a quit button */
16634   button = gtk_button_new_with_label ("Quit");
16635   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16636
16637   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
16638                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
16639                              GTK_OBJECT (window));
16640   gtk_widget_show (button);
16641
16642   gtk_widget_show (window);
16643
16644   gtk_main ();
16645
16646   return 0;
16647 }
16648 /* example-end */
16649 </verb></tscreen>
16650
16651 <!-- ***************************************************************** -->
16652 <sect> List Widget
16653 <!-- ***************************************************************** -->
16654 <p>
16655 NOTE: The GtkList widget has been superseded by the GtkCList
16656 widget. It is detailed here just for completeness.
16657
16658 The GtkList widget is designed to act as a vertical container for
16659 widgets that should be of the type GtkListItem.
16660
16661 A GtkList widget has its own window to receive events and its own
16662 background color which is usually white. As it is directly derived
16663 from a GtkContainer it can be treated as such by using the
16664 GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
16665 this. One should already be familiar with the usage of a GList and
16666 its related functions g_list_*() to be able to use the GtkList widget
16667 to it full extent.
16668
16669 There is one field inside the structure definition of the GtkList
16670 widget that will be of greater interest to us, this is:
16671
16672 <tscreen><verb>
16673 struct _GtkList
16674 {
16675   ...
16676   GList *selection;
16677   guint selection_mode;
16678   ...
16679 }; 
16680 </verb></tscreen>
16681
16682 The selection field of a GtkList points to a linked list of all items
16683 that are currently selected, or NULL if the selection is empty.  So to
16684 learn about the current selection we read the GTK_LIST()->selection
16685 field, but do not modify it since the internal fields are maintained
16686 by the gtk_list_*() functions.
16687
16688 The selection_mode of the GtkList determines the selection facilities
16689 of a GtkList and therefore the contents of the GTK_LIST()->selection
16690 field. The selection_mode may be one of the following:
16691
16692 <itemize>
16693 <item> GTK_SELECTION_SINGLE - The selection is either NULL
16694                         or contains a GList pointer
16695                         for a single selected item.
16696
16697 <item> GTK_SELECTION_BROWSE -  The selection is NULL if the list
16698                         contains no widgets or insensitive
16699                         ones only, otherwise it contains
16700                         a GList pointer for one GList
16701                         structure, and therefore exactly
16702                         one list item.
16703
16704 <item> GTK_SELECTION_MULTIPLE -  The selection is NULL if no list
16705                         items are selected or a GList pointer
16706                         for the first selected item. That
16707                         in turn points to a GList structure
16708                         for the second selected item and so
16709                         on.
16710
16711 <item> GTK_SELECTION_EXTENDED - The selection is always NULL.
16712 </itemize>
16713
16714 The default is GTK_SELECTION_MULTIPLE.
16715
16716 <!-- ----------------------------------------------------------------- -->
16717 <sect1> Signals
16718 <p>
16719 <tscreen><verb>
16720 void selection_changed( GtkList *list );
16721 </verb></tscreen>
16722
16723 This signal will be invoked whenever the selection field of a GtkList
16724 has changed. This happens when a child of the GtkList got selected or
16725 deselected.
16726
16727 <tscreen><verb>
16728 void select_child( GtkList   *list,
16729                    GtkWidget *child);
16730 </verb></tscreen>
16731
16732 This signal is invoked when a child of the GtkList is about to get
16733 selected. This happens mainly on calls to gtk_list_select_item(),
16734 gtk_list_select_child(), button presses and sometimes indirectly
16735 triggered on some else occasions where children get added to or
16736 removed from the GtkList.
16737
16738 <tscreen><verb>
16739 void unselect_child( GtkList   *list,
16740                      GtkWidget *child );
16741 </verb></tscreen>
16742
16743 This signal is invoked when a child of the GtkList is about to get
16744 deselected. This happens mainly on calls to gtk_list_unselect_item(),
16745 gtk_list_unselect_child(), button presses and sometimes indirectly
16746 triggered on some else occasions where children get added to or
16747 removed from the GtkList.
16748
16749 <!-- ----------------------------------------------------------------- -->
16750 <sect1> Functions
16751 <p>
16752 <tscreen><verb>
16753 guint gtk_list_get_type( void );
16754 </verb></tscreen>
16755
16756 Returns the `GtkList' type identifier.
16757
16758 <tscreen><verb>
16759 GtkWidget *gtk_list_new( void );
16760 </verb></tscreen>
16761
16762 Create a new GtkList object. The new widget is returned as a pointer
16763 to a GtkWidget object. NULL is returned on failure.
16764
16765 <tscreen><verb>
16766 void gtk_list_insert_items( GtkList *list,
16767                             GList   *items,
16768                             gint     position );
16769 </verb></tscreen>
16770
16771 Insert list items into the list, starting at <tt/position/.
16772 <tt/items/ is a doubly linked list where each nodes data pointer is
16773 expected to point to a newly created GtkListItem.  The GList nodes of
16774 <tt/items/ are taken over by the list.
16775
16776 <tscreen><verb>
16777 void gtk_list_append_items( GtkList *list,
16778                             GList   *items);
16779 </verb></tscreen>
16780
16781 Insert list items just like gtk_list_insert_items() at the end of the
16782 list. The GList nodes of <tt/items/ are taken over by the list.
16783
16784 <tscreen><verb>
16785 void gtk_list_prepend_items( GtkList *list,
16786                              GList   *items);
16787 </verb></tscreen>
16788
16789 Insert list items just like gtk_list_insert_items() at the very
16790 beginning of the list. The GList nodes of <tt/items/ are taken over by
16791 the list.
16792
16793 <tscreen><verb>
16794 void gtk_list_remove_items( GtkList *list,
16795                             GList   *items);
16796 </verb></tscreen>
16797
16798 Remove list items from the list. <tt/items/ is a doubly linked list
16799 where each nodes data pointer is expected to point to a direct child
16800 of list. It is the callers responsibility to make a call to
16801 g_list_free(items) afterwards. Also the caller has to destroy the list
16802 items himself.
16803
16804 <tscreen><verb>
16805 void gtk_list_clear_items( GtkList *list,
16806                            gint start,
16807                            gint end );
16808 </verb></tscreen>
16809
16810 Remove and destroy list items from the list. A widget is affected if
16811 its current position within the list is in the range specified by
16812 <tt/start/ and <tt/end/.
16813
16814 <tscreen><verb>
16815 void gtk_list_select_item( GtkList *list,
16816                            gint     item );
16817 </verb></tscreen>
16818
16819 Invoke the select_child signal for a list item specified through its
16820 current position within the list.
16821
16822 <tscreen><verb>
16823 void gtk_list_unselect_item( GtkList *list,
16824                              gint     item);
16825 </verb></tscreen>
16826
16827 Invoke the unselect_child signal for a list item specified through its
16828 current position within the list.
16829
16830 <tscreen><verb>
16831 void gtk_list_select_child( GtkList *list,
16832                             GtkWidget *child);
16833 </verb></tscreen>
16834
16835 Invoke the select_child signal for the specified child.
16836
16837 <tscreen><verb>
16838 void gtk_list_unselect_child( GtkList   *list,
16839                               GtkWidget *child);
16840 </verb></tscreen>
16841
16842 Invoke the unselect_child signal for the specified child.
16843
16844 <tscreen><verb>
16845 gint gtk_list_child_position( GtkList *list,
16846                               GtkWidget *child);
16847 </verb></tscreen>
16848
16849 Return the position of <tt/child/ within the list. "-1" is returned on
16850 failure.
16851
16852 <tscreen><verb>
16853 void gtk_list_set_selection_mode( GtkList         *list,
16854                                   GtkSelectionMode mode );
16855 </verb></tscreen>
16856
16857 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
16858 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
16859 GTK_SELECTION_EXTENDED.
16860
16861 <tscreen><verb>
16862 GtkList *GTK_LIST( gpointer obj );
16863 </verb></tscreen>
16864
16865 Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
16866 more info.
16867
16868 <tscreen><verb>
16869 GtkListClass *GTK_LIST_CLASS( gpointer class);
16870 </verb></tscreen>
16871
16872 Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
16873 for more info.
16874
16875 <tscreen><verb>
16876 gint GTK_IS_LIST( gpointer obj);
16877 </verb></tscreen>
16878
16879 Determine if a generic pointer refers to a `GtkList' object. *Note
16880 Standard Macros::, for more info.
16881
16882 <!-- ----------------------------------------------------------------- -->
16883 <sect1> Example
16884 <p>
16885 Following is an example program that will print out the changes of the
16886 selection of a GtkList, and lets you "arrest" list items into a prison
16887 by selecting them with the rightmost mouse button.
16888
16889 <tscreen><verb>
16890 /* example-start list list.c */
16891
16892 /* Include the gtk+ header files
16893  * Include stdio.h, we need that for the printf() function
16894  */
16895 #include        <gtk/gtk.h>
16896 #include        <stdio.h>
16897
16898 /* This is our data identification string to store
16899  * data in list items
16900  */
16901 const gchar *list_item_data_key="list_item_data";
16902
16903
16904 /* prototypes for signal handler that we are going to connect
16905  * to the GtkList widget
16906  */
16907 static void  sigh_print_selection( GtkWidget *gtklist,
16908                                    gpointer   func_data);
16909
16910 static void  sigh_button_event( GtkWidget      *gtklist,
16911                                 GdkEventButton *event,
16912                                 GtkWidget      *frame );
16913
16914
16915 /* Main function to set up the user interface */
16916
16917 gint main (int    argc,
16918            gchar *argv[])
16919 {                                  
16920     GtkWidget *separator;
16921     GtkWidget *window;
16922     GtkWidget *vbox;
16923     GtkWidget *scrolled_window;
16924     GtkWidget *frame;
16925     GtkWidget *gtklist;
16926     GtkWidget *button;
16927     GtkWidget *list_item;
16928     GList *dlist;
16929     guint i;
16930     gchar buffer[64];
16931     
16932     
16933     /* Initialize gtk+ (and subsequently gdk) */
16934
16935     gtk_init(&amp;argc, &amp;argv);
16936     
16937     
16938     /* Create a window to put all the widgets in
16939      * connect gtk_main_quit() to the "destroy" event of
16940      * the window to handle window manager close-window-events
16941      */
16942     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
16943     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
16944     gtk_signal_connect(GTK_OBJECT(window),
16945                        "destroy",
16946                        GTK_SIGNAL_FUNC(gtk_main_quit),
16947                        NULL);
16948     
16949     
16950     /* Inside the window we need a box to arrange the widgets
16951      * vertically */
16952     vbox=gtk_vbox_new(FALSE, 5);
16953     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
16954     gtk_container_add(GTK_CONTAINER(window), vbox);
16955     gtk_widget_show(vbox);
16956     
16957     /* This is the scrolled window to put the GtkList widget inside */
16958     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
16959     gtk_widget_set_usize(scrolled_window, 250, 150);
16960     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
16961     gtk_widget_show(scrolled_window);
16962     
16963     /* Create the GtkList widget.
16964      * Connect the sigh_print_selection() signal handler
16965      * function to the "selection_changed" signal of the GtkList
16966      * to print out the selected items each time the selection
16967      * has changed */
16968     gtklist=gtk_list_new();
16969     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
16970                                            gtklist);
16971     gtk_widget_show(gtklist);
16972     gtk_signal_connect(GTK_OBJECT(gtklist),
16973                        "selection_changed",
16974                        GTK_SIGNAL_FUNC(sigh_print_selection),
16975                        NULL);
16976     
16977     /* We create a "Prison" to put a list item in ;) */
16978     frame=gtk_frame_new("Prison");
16979     gtk_widget_set_usize(frame, 200, 50);
16980     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
16981     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
16982     gtk_container_add(GTK_CONTAINER(vbox), frame);
16983     gtk_widget_show(frame);
16984     
16985     /* Connect the sigh_button_event() signal handler to the GtkList
16986      * which will handle the "arresting" of list items
16987      */
16988     gtk_signal_connect(GTK_OBJECT(gtklist),
16989                        "button_release_event",
16990                        GTK_SIGNAL_FUNC(sigh_button_event),
16991                        frame);
16992     
16993     /* Create a separator */
16994     separator=gtk_hseparator_new();
16995     gtk_container_add(GTK_CONTAINER(vbox), separator);
16996     gtk_widget_show(separator);
16997     
16998     /* Finally create a button and connect its "clicked" signal
16999      * to the destruction of the window */
17000     button=gtk_button_new_with_label("Close");
17001     gtk_container_add(GTK_CONTAINER(vbox), button);
17002     gtk_widget_show(button);
17003     gtk_signal_connect_object(GTK_OBJECT(button),
17004                               "clicked",
17005                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
17006                               GTK_OBJECT(window));
17007     
17008     
17009     /* Now we create 5 list items, each having its own
17010      * label and add them to the GtkList using gtk_container_add()
17011      * Also we query the text string from the label and
17012      * associate it with the list_item_data_key for each list item
17013      */
17014     for (i=0; i<5; i++) {
17015         GtkWidget       *label;
17016         gchar           *string;
17017         
17018         sprintf(buffer, "ListItemContainer with Label #%d", i);
17019         label=gtk_label_new(buffer);
17020         list_item=gtk_list_item_new();
17021         gtk_container_add(GTK_CONTAINER(list_item), label);
17022         gtk_widget_show(label);
17023         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
17024         gtk_widget_show(list_item);
17025         gtk_label_get(GTK_LABEL(label), &amp;string);
17026         gtk_object_set_data(GTK_OBJECT(list_item),
17027                             list_item_data_key,
17028                             string);
17029     }
17030     /* Here, we are creating another 5 labels, this time
17031      * we use gtk_list_item_new_with_label() for the creation
17032      * we can't query the text string from the label because
17033      * we don't have the labels pointer and therefore
17034      * we just associate the list_item_data_key of each
17035      * list item with the same text string.
17036      * For adding of the list items we put them all into a doubly
17037      * linked list (GList), and then add them by a single call to
17038      * gtk_list_append_items().
17039      * Because we use g_list_prepend() to put the items into the
17040      * doubly linked list, their order will be descending (instead
17041      * of ascending when using g_list_append())
17042      */
17043     dlist=NULL;
17044     for (; i<10; i++) {
17045         sprintf(buffer, "List Item with Label %d", i);
17046         list_item=gtk_list_item_new_with_label(buffer);
17047         dlist=g_list_prepend(dlist, list_item);
17048         gtk_widget_show(list_item);
17049         gtk_object_set_data(GTK_OBJECT(list_item),
17050                             list_item_data_key,
17051                             "ListItem with integrated Label");
17052     }
17053     gtk_list_append_items(GTK_LIST(gtklist), dlist);
17054     
17055     /* Finally we want to see the window, don't we? ;) */
17056     gtk_widget_show(window);
17057     
17058     /* Fire up the main event loop of gtk */
17059     gtk_main();
17060     
17061     /* We get here after gtk_main_quit() has been called which
17062      * happens if the main window gets destroyed
17063      */
17064     return(0);
17065 }
17066
17067 /* This is the signal handler that got connected to button
17068  * press/release events of the GtkList
17069  */
17070 void sigh_button_event( GtkWidget      *gtklist,
17071                         GdkEventButton *event,
17072                         GtkWidget      *frame )
17073 {
17074     /* We only do something if the third (rightmost mouse button
17075      * was released
17076      */
17077     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
17078         event->button==3) {
17079         GList           *dlist, *free_list;
17080         GtkWidget       *new_prisoner;
17081         
17082         /* Fetch the currently selected list item which
17083          * will be our next prisoner ;)
17084          */
17085         dlist=GTK_LIST(gtklist)->selection;
17086         if (dlist)
17087                 new_prisoner=GTK_WIDGET(dlist->data);
17088         else
17089                 new_prisoner=NULL;
17090         
17091         /* Look for already imprisoned list items, we
17092          * will put them back into the list.
17093          * Remember to free the doubly linked list that
17094          * gtk_container_children() returns
17095          */
17096         dlist=gtk_container_children(GTK_CONTAINER(frame));
17097         free_list=dlist;
17098         while (dlist) {
17099             GtkWidget       *list_item;
17100             
17101             list_item=dlist->data;
17102             
17103             gtk_widget_reparent(list_item, gtklist);
17104             
17105             dlist=dlist->next;
17106         }
17107         g_list_free(free_list);
17108         
17109         /* If we have a new prisoner, remove him from the
17110          * GtkList and put him into the frame "Prison".
17111          * We need to unselect the item first.
17112          */
17113         if (new_prisoner) {
17114             GList   static_dlist;
17115             
17116             static_dlist.data=new_prisoner;
17117             static_dlist.next=NULL;
17118             static_dlist.prev=NULL;
17119             
17120             gtk_list_unselect_child(GTK_LIST(gtklist),
17121                                     new_prisoner);
17122             gtk_widget_reparent(new_prisoner, frame);
17123         }
17124     }
17125 }
17126
17127 /* This is the signal handler that gets called if GtkList
17128  * emits the "selection_changed" signal
17129  */
17130 void sigh_print_selection( GtkWidget *gtklist,
17131                            gpointer   func_data)
17132 {
17133     GList   *dlist;
17134     
17135     /* Fetch the doubly linked list of selected items
17136      * of the GtkList, remember to treat this as read-only!
17137      */
17138     dlist=GTK_LIST(gtklist)->selection;
17139     
17140     /* If there are no selected items there is nothing more
17141      * to do than just telling the user so
17142      */
17143     if (!dlist) {
17144         g_print("Selection cleared\n");
17145         return;
17146     }
17147     /* Ok, we got a selection and so we print it
17148      */
17149     g_print("The selection is a ");
17150     
17151     /* Get the list item from the doubly linked list
17152      * and then query the data associated with list_item_data_key.
17153      * We then just print it */
17154     while (dlist) {
17155         GtkObject       *list_item;
17156         gchar           *item_data_string;
17157         
17158         list_item=GTK_OBJECT(dlist->data);
17159         item_data_string=gtk_object_get_data(list_item,
17160                                              list_item_data_key);
17161         g_print("%s ", item_data_string);
17162         
17163         dlist=dlist->next;
17164     }
17165     g_print("\n");
17166 }
17167 /* example-end */
17168 </verb></tscreen>
17169
17170 <!-- ----------------------------------------------------------------- -->
17171 <sect1> List Item Widget
17172 <p>
17173 The GtkListItem widget is designed to act as a container holding up to
17174 one child, providing functions for selection/deselection just like the
17175 GtkList widget requires them for its children.
17176
17177 A GtkListItem has its own window to receive events and has its own
17178 background color which is usually white.
17179
17180 As it is directly derived from a GtkItem it can be treated as such by
17181 using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
17182 this. Usually a GtkListItem just holds a label to identify e.g. a
17183 filename within a GtkList -- therefore the convenience function
17184 gtk_list_item_new_with_label() is provided. The same effect can be
17185 achieved by creating a GtkLabel on its own, setting its alignment to
17186 xalign=0 and yalign=0.5 with a subsequent container addition to the
17187 GtkListItem.
17188
17189 As one is not forced to add a GtkLabel to a GtkListItem, you could
17190 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
17191
17192 <!-- ----------------------------------------------------------------- -->
17193 <sect1> Signals
17194 <p>
17195 A GtkListItem does not create new signals on its own, but inherits
17196 the signals of a GtkItem. *Note GtkItem::, for more info.
17197
17198 <!-- ----------------------------------------------------------------- -->
17199 <sect1> Functions
17200 <p>
17201 <tscreen><verb>
17202 guint gtk_list_item_get_type( void );
17203 </verb></tscreen>
17204
17205 Returns the `GtkListItem' type identifier.
17206
17207 <tscreen><verb>
17208 GtkWidget *gtk_list_item_new( void );
17209 </verb></tscreen>
17210
17211 Create a new GtkListItem object. The new widget is returned as a
17212 pointer to a GtkWidget object. NULL is returned on failure.
17213
17214 <tscreen><verb>
17215 GtkWidget *gtk_list_item_new_with_label( gchar *label );
17216 </verb></tscreen>
17217
17218 Create a new GtkListItem object, having a single GtkLabel as the sole
17219 child. The new widget is returned as a pointer to a GtkWidget
17220 object. NULL is returned on failure.
17221
17222 <tscreen><verb>
17223 void gtk_list_item_select( GtkListItem *list_item );
17224 </verb></tscreen>
17225
17226 This function is basically a wrapper around a call to gtk_item_select
17227 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
17228 GtkItem::, for more info.
17229
17230 <tscreen><verb>
17231 void gtk_list_item_deselect( GtkListItem *list_item );
17232 </verb></tscreen>
17233
17234 This function is basically a wrapper around a call to
17235 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
17236 signal.  *Note GtkItem::, for more info.
17237
17238 <tscreen><verb>
17239 GtkListItem *GTK_LIST_ITEM( gpointer obj );
17240 </verb></tscreen>
17241
17242 Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
17243 more info.
17244
17245 <tscreen><verb>
17246 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
17247 </verb></tscreen>
17248
17249 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
17250 for more info.
17251
17252 <tscreen><verb>
17253 gint GTK_IS_LIST_ITEM( gpointer obj );
17254 </verb></tscreen>
17255
17256 Determine if a generic pointer refers to a `GtkListItem' object.
17257 *Note Standard Macros::, for more info.
17258  
17259 <!-- ----------------------------------------------------------------- -->
17260 <sect1> Example
17261 <p>
17262 Please see the GtkList example on this, which covers the usage of a
17263 GtkListItem as well.
17264
17265
17266 </article>