@c -----------------------------------------------------------------------------
@c File     : gtk-getting-started.texi
@c License  : GNU General Public License (GPL)
@c Author   : Dieter Kaiser
@c Date     : 26.12.2011
@c Revision : 08.01.2016
@c
@c Copyright (C) 2011 - 2016 by Dieter Kaiser
@c -----------------------------------------------------------------------------

@menu
* Installation::
* A Simple Window::
* More about the Lisp binding to GTK+::
* Hello World in GTK+::
* Introduction to Signals and Callbacks::
* An Upgraded Hello World::
* Drawing::
@end menu

@c -----------------------------------------------------------------------------
@node Installation, A Simple Window, Top, Top
@section Installation

The first thing to do is to download the @code{cl-cffi-gtk} source and to
install it.  The latest version is available from the repository at
@url{http://github.com/crategus/cl-cffi-gtk}.  The @code{cl-cffi-gtk} library
is ASDF installable and can be loaded with the command
@code{(asdf:load-system :cl-cffi-gtk)} from the Lisp prompt.  The library is
developed with the Lisp SBCL 1.2.14 on a Linux system and GTK+ 3.16.
Furthermore, the library runs successfully with Clozure Common Lisp and
CLISP on Linux.  The library compiles and the demos run with Windows 7.

The minimum version requirements are GTK+ 3.4 and GLIB 2.32.

GTK+ depends on the libraries GLib, GObject, GDK, GDK-Pixbuf, GIO, Pango, and
Cairo. These libraries can be loaded separately with the following commands:
@verbatim
   (asdf:load-system 'cl-cffi-gtk-glib)
   (asdf:load-system 'cl-cffi-gtk-gobject)
   (asdf:load-system 'cl-cffi-gtk-gdk)
   (asdf:load-system 'cl-cffi-gtk-gdk-pixbuf)
   (asdf:load-system 'cl-cffi-gtk-gio)
   (asdf:load-system 'cl-cffi-gtk-pango)
   (asdf:load-system 'cl-cffi-gtk-cairo)
@end verbatim

Please consult the ASDF documentation which is available at
@url{http://common-lisp.net/project/asdf/} for configuring ASDF
to find your systems.

The @code{cl-cffi-gtk} library depends further on the following libraries:
@table @emph
@item CFFI
      the Common Foreign Function Interface, purports to be a portable
      foreign function interface for Common Lisp.
      See @url{http://common-lisp.net/project/cffi/}.

      @b{Warning:} Yout must use the version 0.11.2 or newer of the CFFI
      library. Older versions of CFFI are no longer compatible with the
      implementation of @code{cl-cffi-gtk}.

@item Trivial-Garbage
      provides a portable API to finalizers, weak hash-tables
      and weak pointers on all major CL implementations. See
      @url{http://common-lisp.net/project/trivial-garbage/}.

@item Iterate
      is a lispy and extensible replacement for the LOOP macro.
      See @url{http://common-lisp.net/project/iterate/}.

@item Bordeaux-Threads
      lets you write multi-threaded applications in a portable way.
      See @url{http://common-lisp.net/project/bordeaux-threads/}.

@item Closer-MOP
      Closer to MOP is a compatibility layer that rectifies many of the absent
      or incorrect MOP features as detected by MOP Feature Tests.
      See @url{http://common-lisp.net/project/closer/closer-mop.html}.
@end table

@findex cl-cffi-gtk-build-info

Information about the installation can be obtained with the function
@xurl{cl-cffi-gtk-build-info}.  This is an example for the output, when calling
the function from the Lisp prompt after loading the library:
@example
* (cl-cffi-gtk-build-info)

cl-cffi-gtk version: 1.0.0
cl-cffi-gtk build date: 20:55 1/5/2016
GTK+ version: 3.16.7
GLIB version: 2.46.1
GDK-Pixbuf version: 2.32.1
Pango version: 1.36.8
Cairo version: 1.14.2
Machine type: X86-64
Machine version: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz
Software type: Linux
Software version: 4.2.0-22-generic
Lisp implementation type: SBCL
Lisp implementation version: 1.2.14.debian
@end example

@c -----------------------------------------------------------------------------
@node A Simple Window, More about the Lisp binding to GTK+, Installation, Top
@section A Simple Window

@ifnotinfo
@float Figure, figure-simple-window
@caption{A Simple Window}
@center @image{figures/simple-window202x229, 135pt}
@end float
@end ifnotinfo

The @code{cl-cffi-gtk} source distribution contains the complete source to all
of the examples used in this tutorial.  To begin the introduction to GTK+, the
output of the simplest program possible is shown in @ref{figure-simple-window}.

The program creates a 200 x 200 pixel window.  In this case the window has the
default title "sbcl".  The window can be sized and moved.  First in
@ref{example-simple-window-C} the C program of the
@url{http://developer.gnome.org/gtk3/3.14/gtk-getting-started.html#id-1.2.3.3,
GTK+ 3 Reference Manual} is presented to show the close connection between the
C library and the implementation of the Lisp binding.  The code of the Lisp
program is shown in @ref{example-simple-window}.

@float Example, example-simple-window-C
@caption{A simple window in the programming language C}
@end float
@verbatim
#include <gtk/gtk.h>

int main (int argc, char *argv[])
{
  GtkWidget *window;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);

  gtk_widget_show (window);

  gtk_main ();

  return 0;
}
@end verbatim

@findex within-main-loop

@findex gtk-window-new
@findex gtk-widget-show
@findex gtk-widget-show-all
@findex gtk-main
@findex g-signal-connect
@findex gtk-main-quit
@findex leave-gtk-main

@findex window-new, gtk-window-new
@findex widget-show, gtk-widget-show
@findex widget-show-all, gtk-widget-show-all
@findex main, gtk-main
@findex signal-connect, g-signal-connect
@findex main-quit, gtk-main-quit

@float Example, example-simple-window
@caption{A Simple Window in the programming language Lisp}
@end float
@verbatim
(asdf:load-system :cl-cffi-gtk)

(defpackage :gtk-tutorial
  (:use :gtk :gdk :gdk-pixbuf :gobject
   :glib :gio :pango :cairo :common-lisp))

(in-package :gtk-tutorial)

(defun example-simple-window ()
  (within-main-loop
    (let (;; Create a toplevel window.
          (window (gtk-window-new :toplevel)))
      ;; Signal handler for the window to handle the signal "destroy".
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      ;; Show the window.
      (gtk-widget-show-all window))))
@end verbatim

The first four lines of code load the @code{cl-cffi-gtk} library and define an
own package @code{:gtk-tutorial} for the example program. The package
@code{:gtk-tutorial} includes the symbols from the packages @code{:gtk} for GTK,
@code{:gdk} for GDK, @code{:gdk-pixbuf} for GDK-Pixbuf, @code{:gobject} for
GObject, @code{:glib} for GLib, @code{:gio} for GIO, @code{:pango} for Pango,
and @code{:cairo} for Cairo.  Most of the symbols of the included packages are
not needed for the first simple examples, but we include all packages so later
no symbol is missing.  In further examples of this tutorial these first lines of
code are omitted.

The macro @xurl{within-main-loop} is a wrapper around a GTK+ program.  The
functionality of the macro corresponds to the C functions @code{gtk_init()} and
@code{gtk_main()} which initialize and start a GTK+ program.  Both functions
have corresponding Lisp functions.  The function @code{gtk_main()} is exported
as the Lisp function @xurl{gtk-main}.  The corresponding Lisp function to
@code{gtk_init()} is called internally when loading the library, but is not
exported.

Already in this simple example we have connected a signal to the created window.
More about signals and callback functions follows in
@ref{Introduction to Signals and Callbacks}.  The signal "destroy" is emitted
when the user quits the window. The function @xurl{g-signal-connect} connects a
Lisp lambda function to this signal, which calls the function
@xurl{leave-gtk-main} to destroy the GTK+ main loop.  Like the macro
@xurl{within-main-loop} the function @xurl{leave-gtk-main} is special for the
Lisp binding. It calls internally the C function @code{gtk_main_quit()}, but
does some extra work to finish the Lisp program. The C function
@code{gtk_main_quit()} is available in the Lisp binding as @xurl{gtk-main-quit},
but do not call this function in your code.

Only two further functions are needed in this simple example.  The window is
created with the function @xurl{gtk-window-new}. The keyword @code{:toplevel}
tells GTK+ to create a toplevel window.  The second function
@xurl{gtk-widget-show-all} displays the new window.

In addition to the function @xurl{gtk-widget-show-all} the function
@xurl{gtk-widget-show} is available.  It only displays the widget, which is the
argument to the function.  The function @xurl{gtk-widget-show-all} displays the
window and all including child widgets.  For the first simple window this makes
no difference, because the window has not child widgets.

@c -----------------------------------------------------------------------------
@node More about the Lisp binding to GTK+, Hello World in GTK+, A Simple Window, Top
@section More about the Lisp binding to GTK+

@ifnotinfo
@float Figure, figure-getting-started
@caption{Getting started}
@center @image{figures/getting-started252x229, 168pt}
@end float
@end ifnotinfo

@findex GtkWindow
@findex gtk-window
@findex window, gtk-window
@findex make-instance

@ref{figure-getting-started} and @ref{example-getting-started} show a second
implementation of the simple program discussed in @ref{A Simple Window}.
The second implementation uses the fact, that all GTK+ widgets are internally
represented in the Lisp binding through a Lisp class.  The Lisp class
@xurl{gtk-window} represents the required window, which corresponds to the C
class @code{GtkWindow}.  An instance of the Lisp class @xurl{gtk-window} can be
created with the function @code{make-instance}.  Furthermore, the slots of the
window class can be given new values to overwrite the default values.  These
slots represent the properties of the C classes.  In addition an instance has
all properties of the inherited classes.  The object hierarchy in the
@url{http://www.crategus.com/books/cl-cffi-gtk, cl-cffi-gtk API documentation}
shows, that the class @xurl{gtk-window} inherits all properties of the classes
@xurl{gtk-widget}, @xurl{gtk-container}, and @xurl{gtk-bin}.

@findex type
@findex title
@findex default-width

In @ref{example-getting-started} the property @code{"type"} with the keyword
@code{:toplevel} creates again a toplevel window.  In addition a title is set
assigning the string @code{"Getting started"} to the property @code{"title"}
and the width of the window is a little enlarged assigning the value 250 to
the property @code{"default-width"}.  The result of the example program is
shown in @ref{figure-getting-started}.

@findex GtkWindowType
@findex gtk-window-type
@findex GTK_WINDOW_TOPLEVEL
@findex GTK_WINDOW_POPUP

@findex window-type, gtk-window-type
@findex :toplevel
@findex :popup

The keyword @code{:toplevel} is one of the values of the enumeration type
@code{GtkWindowType} in C.  In the Lisp binding this enumeration is implemented
as @xurl{gtk-window-type} with the two possible keywords @code{:toplevel} for
@code{GTK_WINDOW_TOPLEVEL} and @code{:popup} for @code{GTK_WINDOW_POPUP}.  Most
windows are of the type @code{:toplevel}.  Windows with this type are managed
by the window manager and have a frame by default.  Windows with type
@code{:popup} are ignored by the window manager and are used to implement
widgets such as menus or tooltips.

@float Example, example-getting-started
@caption{Getting Started}
@end float
@verbatim
(defun example-getting-started ()
  (within-main-loop
    (let (;; Create a toplevel window with a title and a default width.
          (window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Getting started"
                                 :default-width 250)))
      ;; Signal handler for the window to handle the signal "destroy".
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      ;; Show the window.
      (gtk-widget-show-all window))))
@end verbatim

The @ref{example-getting-started} shows, that the Lisp function
@xurl{gtk-window-new} is not really needed.  The function @xurl{gtk-window-new}
is internally implemented in the Lisp binding simply as:

@example
(defun gtk-window-new (type)
  (make-instance 'gtk-window :type type))
@end example

@findex gtk-window-title
@findex gtk-window-default-size

@findex window-title, gtk-window-title
@findex window-default-size, gtk-window-default-size

To set the title of the window or to change the default width of a window the
C library knows accessor functions to set the corresponding values.  In C the
title of the window is set with the function @code{gtk_window_set_title()}.
The corresponding Lisp function is @xurl{gtk-window-title}.  Accordingly,
the default width of the window can be set in C with the function
@code{gtk_window_set_default_size()}, which sets both the default width and the
default height.  In Lisp this function is named @xurl{gtk-window-default-size}.

@findex default-width
@findex default-height

@findex gtk-window-default-width
@findex gtk-window-default-height

@findex window-default-width, gtk-window-default-width
@findex window-default-height, gtk-window-default-height

At last, in Lisp it is possible to use the accessors of the slots to get or
set the value of a widget property.  The properties @code{"default-width"} and
@code{"default-height"} of the Lisp class @xurl{gtk-window} have the Lisp
accessor functions @xurl{gtk-window-default-width} and
@xurl{gtk-window-default-height}.  With these accessor functions the C function
@code{gtk_window_set_default_size()} is implemented the following way in the
Lisp library as the generic function @code{(setf gtk-window-default-size)}:

@example
(defgeneric (setf gtk-window-default-size) (size window)
  (:method (size (window gtk-window))
    (destructuring-bind (width height) size
      (values (setf (gtk-window-default-width window) width)
              (setf (gtk-window-default-height window) height)))))
@end example

As a second example the Lisp implementation of the C function
@code{gtk_window_get_default_size()} is shown:

@example
(defgeneric gtk-window-default-size (window)
  (:method ((window gtk-window))
    (values (gtk-window-default-width window)
            (gtk-window-default-height window))))
@end example

In distinction to the C function @code{gtk_window_get_default_size()}, which is
implemented as

@example
void gtk_window_get_default_size (GtkWindow *window,
                                  gint      *width,
                                  gint      *height)
@end example

the Lisp implementation does not modify the arguments @code{width} and
@code{height}, but returns the values.

Note the naming conventions for the translation of C accessor functions to Lisp
generic functions.  C reader functions with the name
@code{gtk_<class>_@b{get}_<property>} get the Lisp name
@code{gtk-<class>-<property>} and the C writer functions
@code{gtk_<class>_@b{set}_<property>} are replaced by the corresponding
@code{(setf gtk-<class>-<property>)} functions.  That is, for example, to get
the property @code{"title"} of a @xurl{gtk-window} use the generic function
@xurl{gtk-window-title} and to set the title use the generic function
@code{(setf gtk-window-title)}.

@c -----------------------------------------------------------------------------
@node Hello World in GTK+, Introduction to Signals and Callbacks, More about the Lisp binding to GTK+, Top
@section Hello World in GTK+

@ifnotinfo
@float Figure, figure-hello-world
@caption{Hello World}
@center @image{figures/hello-world252x80, 168pt}
@end float
@end ifnotinfo

Now a program with a button is presented.  The output is shown in
@ref{figure-hello-world}.  Again the C program from the
@url{http://developer.gnome.org/gtk3/stable/gtk-getting-started.html, GTK+ 3
Reference Manual} is shown first in @ref{example-hello-world-C} to learn more
about the differences between a C and a Lisp implementation.

@float Example, example-hello-world-C
@caption{Hello World in the programming language C}
@end float
@verbatim
#include <gtk/gtk.h>

/* This is a callback function. The data arguments are ignored
 * in this example. More on callbacks below. */
static void hello( GtkWidget *widget, gpointer data )
{
    g_print ("Hello World\n");
}

static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    /* If you return FALSE in the "delete-event" signal handler,
     * GTK will emit the "destroy" signal. Returning TRUE means
     * you don't want the window to be destroyed.
     * This is useful for popping up 'are you sure you want to quit?'
     * type dialogs. */

    g_print ("delete event occurred\n");

    /* Change TRUE to FALSE and the main window will be destroyed with
     * a "delete-event". */

    return TRUE;
}

/* Another callback */
static void destroy( GtkWidget *widget, gpointer data )
{
    gtk_main_quit ();
}

int main( int argc, char *argv[] )
{
    /* GtkWidget is the storage type for widgets */
    GtkWidget *window;
    GtkWidget *button;

    /* This is called in all GTK applications. Arguments are parsed
     * from the command line and are returned to the application. */
    gtk_init (&argc, &argv);

    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* When the window is given the "delete-event" signal (this is given
     * by the window manager, usually by the "close" option, or on the
     * titlebar), we ask it to call the delete_event () function
     * as defined above. The data passed to the callback
     * function is NULL and is ignored in the callback function. */
    g_signal_connect (window, "delete-event",
		      G_CALLBACK (delete_event), NULL);

    /* Here we connect the "destroy" event to a signal handler.
     * This event occurs when we call gtk_widget_destroy() on the window,
     * or if we return FALSE in the "delete-event" callback. */
    g_signal_connect (window, "destroy",
		      G_CALLBACK (destroy), NULL);

    /* Sets the border width of the window. */
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);

    /* Creates a new button with the label "Hello World". */
    button = gtk_button_new_with_label ("Hello World");

    /* When the button receives the "clicked" signal, it will call the
     * function hello() passing it NULL as its argument.  The hello()
     * function is defined above. */
    g_signal_connect (button, "clicked",
		      G_CALLBACK (hello), NULL);

    /* This will cause the window to be destroyed by calling
     * gtk_widget_destroy(window) when "clicked".  Again, the destroy
     * signal could come from here, or the window manager. */
    g_signal_connect_swapped (button, "clicked",
			      G_CALLBACK (gtk_widget_destroy),
                              window);

    /* This packs the button into the window (a gtk container). */
    gtk_container_add (GTK_CONTAINER (window), button);

    /* The final step is to display this newly created widget. */
    gtk_widget_show (button);

    /* and the window */
    gtk_widget_show (window);

    /* All GTK applications must have a gtk_main(). Control ends here
     * and waits for an event to occur (like a key press or
     * mouse event). */
    gtk_main ();

    return 0;
}
@end verbatim

Now, the Lisp implementation is presented in @ref{example-hello-world}.  One
difference is, that the function @code{make-instance} is used to create the
window and the button.  Another point is, that the definition of separate
callback functions is avoided.  The callback functions are short, implemented
through Lisp @code{lambda} functions and are passed as the third argument to
the function @xurl{g-signal-connect}.  More about signals and callback functions
follows in @ref{Introduction to Signals and Callbacks}.

@findex GtkContainer

@findex gtk-container
@findex gtk-container-border-width

@findex border-width
@findex container, gtk-container
@findex container-border-width, gtk-container-border-width

In @ref{example-hello-world} a border with a width of 12 is added to the window
setting the property @code{"border-width"} when creating the window with the
function @code{make-instance}.  The C implementation uses the function
@code{gtk_container_set_border_width()} which is available in Lisp as the
accessor @xurl{gtk-container-border-width}.  The property @code{"border-width"}
is inherited from the C class @code{GtkContainer}, which in the Lisp library is
represented through the Lisp class @xurl{gtk-container}.  Therefore, the
accessor function has the prefix @code{gtk_container} in C and
@code{gtk-container} in Lisp.  A full list of properties of @code{GtkContainer}
is available at @xurl{gtk-container}.

@float Example, example-hello-world
@caption{Hello World in the programming language Lisp}
@end float
@verbatim
(defun example-hello-world ()
  (within-main-loop
    (let (;; Create a toplevel window, set a border width.
          (window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Hello World"
                                 :default-width 250
                                 :border-width 12))
          ;; Create a button with a label.
          (button (make-instance 'gtk-button :label "Hello World")))
      ;; Signal handler for the button to handle the signal "clicked".
      (g-signal-connect button "clicked"
                        (lambda (widget)
                          (declare (ignore widget))
                          (format t "Hello world.~%")
                          (gtk-widget-destroy window)))
      ;; Signal handler for the window to handle the signal "destroy".
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      ;; Signal handler for the window to handle the signal "delete-event".
      (g-signal-connect window "delete-event"
                        (lambda (widget event)
                          (declare (ignore widget event))
                          (format t "Delete Event Occured.~%")
                          +gdk-event-stop+))
      ;; Put the button into the window.
      (gtk-container-add window button)
      ;; Show the window and the button.
      (gtk-widget-show-all window))))
@end verbatim

@findex gtk-widget-show
@findex widget-show, gtk-widget-show

An attentive reader notes that in distinction to the C implementation the
function @xurl{gtk-widget-show} is not called for every single widget, which are
in @ref{example-hello-world} the window and the button.  Instead the function
@xurl{gtk-widget-show-all} is used to display the window with all including
widgets.

@findex gtk-widget-destroy
@findex gtk-main-quit
@findex leave-gtk-main
@findex gtk-container-add

@findex widget-destroy, gtk-widget-destroy
@findex main-quit, gtk-main-quit
@findex container-add, gtk-container-add

Three more functions are introduced in @ref{example-hello-world}.  The function
@xurl{gtk-widget-destroy} takes as an argument any widget and destroys it.  In
the above example this function is called by the signal handler of the button.
When the button is clicked by the user, the signal "clicked" is catched by the
signal handler, which causes a call of the function @xurl{gtk-widget-destroy}
for the toplevel window.  Now the toplevel window receives the signal "destroy",
which is handled by a signal handler of the toplevel window.  This signal
handler calls the function @xurl{leave-gtk-main}, which stops the event loop and
finishes the application.

A second signal handler is connected to the toplevel window to catch the
signal "delete-event".  The signal "delete-event" occurs, when the user or the
window manager tries to close the window.  In this case, the signal handler
prints a message on the console.   Because the value of the constant
@code{+gdk-event-stop+} is @emph{true} the signal handler stops the handling of
the signal and the window is not closed, but the execution of the application
is continued.  To close the window, the user has to press the button in this
example.  There is a second constant @code{+gdk-event-prograte+} which is used
to make sure that the propagation of the event is continued.

At last, the function @xurl{gtk-container-add} is used to put the button into
the toplevel window.  @ref{Packing Widgets} shows how it is possible to put more
than one widget into a window.

@c -----------------------------------------------------------------------------
@node Introduction to Signals and Callbacks, An Upgraded Hello World, Hello World in GTK+, Top
@section Introduction to Signals and Callbacks

GTK+ is an event driven toolkit, which means GTK+ will sleep until an event
occurs and control is passed to the appropriate function.  This passing of
control is done using the idea of "signals".  (Note that these signals are not
the same as the Unix system signals, and are not implemented using them,
although the terminology is almost identical.)  When an event occurs, such as
the press of a mouse button, the appropriate signal will be "emitted" by the
widget that was pressed.  This is how GTK+ does most of its useful work.  There
are signals that all widgets inherit, such as "destroy", and there are signals
that are widget specific, such as "toggled" on a toggle button.

To make a button perform an action, a signal handler is set up to catch these
signals and to call the appropriate function.  This is done in the C GTK+
library by using a function such as

@example
gulong g_signal_connect( gpointer      *object,
                         const gchar   *name,
                         GCallback     func,
                         gpointer      func_data );
@end example

where the first argument is the widget which will be emitting the signal, and
the second the name of the signal to catch.  The third is the function
to be called when the signal is caught, and the fourth, the data to have passed
to this function.

The function specified in the third argument is called a "callback function",
and is for a C program of the form

@example
void callback_func( GtkWidget *widget,
                    ... /* other signal arguments */
                    gpointer   callback_data );
@end example

where the first argument will be a pointer to the widget that emitted the
signal, and the last a pointer to the data given as the last argument to the C
function @code{g_signal_connect()} as shown above.  Note that the above form for
a signal callback function declaration is only a general guide, as some widget
specific signals generate different calling parameters.

@findex g-signal-connect
@findex signal-connect, g-signal-connect

This mechanism is realized in Lisp with a similar function
@xurl{g-signal-connect} which has the arguments @code{widget}, @code{name}, and
@code{func}.  In distinction from C the Lisp function @xurl{g-signal-connect}
has not the argument @code{func_data}.  The functionality of passing data to a
callback function can be realized with the help of a @code{lambda} function in
Lisp.

As an example the following code shows a typical C implementation which is used
in the Hello World program.

@example
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
@end example

This is the corresponding callback function which is called when the event
"destroy" occurs.

@example
static void destroy (GtkWidget *widget, gpointer data)
@{
    gtk_main_quit ();
@}
@end example

In the corresponding Lisp implementation we simply declare a @code{lambda}
function as a callback function which is passed as the third argument.

@example
(g-signal-connect window "destroy"
                  (lambda (widget)
                    (declare (ignore widget))
                    (leave-gtk-main)))
@end example

If it is necessary to have a separate function which needs user data, the
following implementation is possible

@example
(defun separate-event-handler (widget arg1 arg2 arg3)
  [ here is the code of the event handler ] )
@end example

@example
(g-signal-connect window "destroy"
                  (lambda (widget)
                    (separate-event-handler widget arg1 arg2 arg3)))
@end example

If no extra data is needed, but the callback function should be separated out
than it is also possible to implement something like

@example
(g-signal-connect window "destroy" #'separate-event-handler)
@end example

@c -----------------------------------------------------------------------------
@node An Upgraded Hello World, Drawing, Introduction to Signals and Callbacks, Top
@section An Upgraded Hello World

@ifnotinfo
@float Figure, figure-upgraded-hello-world
@caption{Upgraded Hello World}
@center @image{figures/upgraded-hello-world252x104, 168pt}
@end float
@end ifnotinfo

@ref{figure-upgraded-hello-world} and @ref{example-upgraded-hello-world} show
a slightly improved Hello World with better examples of callbacks.  This will
also introduce the next topic, packing widgets.  First, the C program is shown
in @ref{example-upgraded-hello-world-C}.

@float Example, example-upgraded-hello-world-C
@caption{An upgraded Hello World in the programming language C}
@end float
@verbatim
#include <gtk/gtk.h>

/* Our new improved callback.  The data passed to this function
 * is printed to stdout. */
static void callback( GtkWidget *widget, gpointer data )
{
    g_print ("Hello again - %s was pressed\n", (gchar *) data);
}

/* another callback */
static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    gtk_main_quit ();
    return FALSE;
}

int main( int argc, char *argv[] )
{
    /* GtkWidget is the storage type for widgets */
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box1;

    /* This is called in all GTK applications. Arguments are parsed
     * from the command line and are returned to the application. */
    gtk_init (&argc, &argv);

    /* Create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    /* This is a new call, which just sets the title of our
     * new window to "Hello Buttons!" */
    gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");

    /* Here we just set a handler for delete_event that immediately
     * exits GTK. */
    g_signal_connect (window, "delete-event",
		      G_CALLBACK (delete_event), NULL);

    /* Sets the border width of the window. */
    gtk_container_set_border_width (GTK_CONTAINER (window), 10);

    /* We create a box to pack widgets into.  This is described in detail
     * in the "packing" section. The box is not really visible, it
     * is just used as a tool to arrange widgets. */
    box1 = gtk_hbox_new (FALSE, 0);

    /* Put the box into the main window. */
    gtk_container_add (GTK_CONTAINER (window), box1);

    /* Creates a new button with the label "Button 1". */
    button = gtk_button_new_with_label ("Button 1");

    /* Now when the button is clicked, we call the "callback" function
     * with a pointer to "button 1" as its argument */
    g_signal_connect (button, "clicked",
		      G_CALLBACK (callback), (gpointer) "button 1");

    /* Instead of gtk_container_add, we pack this button into the invisible
     * box, which has been packed into the window. */
    gtk_box_pack_start (GTK_BOX(box1), button, TRUE, TRUE, 0);

    /* Always remember this step, this tells GTK that our preparation for
     * this button is complete, and it can now be displayed. */
    gtk_widget_show (button);

    /* Do these same steps again to create a second button */
    button = gtk_button_new_with_label ("Button 2");

    /* Call the same callback function with a different argument,
     * passing a pointer to "button 2" instead. */
    g_signal_connect (button, "clicked",
		      G_CALLBACK (callback), (gpointer) "button 2");

    gtk_box_pack_start(GTK_BOX (box1), button, TRUE, TRUE, 0);

    /* The order in which we show the buttons is not really important, but I
     * recommend showing the window last, so it all pops up at once. */
    gtk_widget_show (button);

    gtk_widget_show (box1);

    gtk_widget_show (window);

    /* Rest in gtk_main and wait for the fun to begin! */
    gtk_main ();

    return 0;
}
@end verbatim

@findex gtk-box-new
@findex box-new, gtk-box-new
@findex :horizontal

The Lisp implementation in @ref{example-upgraded-hello-world} tries to be close
to the C program.  Therefore, the window and the box are created with the
functions @xurl{gtk-window-new} and @xurl{gtk-box-new}.  Various properties like
the title of the window, the default size or the border width are set with the
functions @xurl{gtk-window-title}, @xurl{gtk-window-default-size}
and @xurl{gtk-container-border-width}.  As described for
@ref{example-hello-world} the function @xurl{gtk-widget-show-all} is used to
display the window including all child widgets.

One main difference of the Lisp implementation is the use of the function
@xurl{gtk-box-new} with an argument @code{:horizontal} to create a horizontal
box.  The @code{GtkHBox} widget which is used in the
@url{http://developer.gnome.org/gtk3/stable/gtk-getting-started.html, GTK+ 3
Reference Manual} is deprecated and is replaced by @code{GtkBox} with the
property @code{"orientation"}.  More about boxes and their usages follows in
@ref{Packing Widgets}.

@float Example, example-upgraded-hello-world
@caption{Upgraded Hello world}
@end float
@verbatim
(defun example-upgraded-hello-world ()
  (within-main-loop
    (let ((window (gtk-window-new :toplevel))
          (box (gtk-box-new :horizontal 6))
          (button  nil))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (setf (gtk-window-title window) "Hello Buttons")
      (setf (gtk-window-default-size window) '(250 75))
      (setf (gtk-container-border-width window) 12)
      (setf button (gtk-button-new-with-label "Button 1"))
      (g-signal-connect button "clicked"
                        (lambda (widget)
                          (declare (ignore widget))
                          (format t "Button 1 was pressed.~%")))
      (gtk-box-pack-start box button :expand t :fill t :padding 0)
      (setf button (gtk-button-new-with-label "Button 2"))
      (g-signal-connect button "clicked"
                        (lambda (widget)
                          (declare (ignore widget))
                          (format t "Button 2 was pressed.~%")))
      (gtk-box-pack-start box button :expand t :fill t :padding 0)
      (gtk-container-add window box)
      (gtk-widget-show-all window))))
@end verbatim

The second implementation in @ref{example-upgraded-hello-world-2} makes
more use of a Lisp style.  The window is created with the Lisp function
@code{make-instance}.  All desired properties of the window are initialized by
assigning values to the slots of the classes @xurl{gtk-window} and
@xurl{gtk-box}.  The Lisp implementation uses a lot keywords arguments with
default values for long lists of arguments.  In
@ref{example-upgraded-hello-world-2} the keyword arguments @code{expand},
@code{fill}, and @code{padding} of the function @xurl{gtk-box-pack-start} take
their default values.  In future examples of this tutorial the style shown in
@ref{example-upgraded-hello-world-2} is preferred.  Furthermore, the C code is
no longer presented for comparison.

@float Example, example-upgraded-hello-world-2
@caption{Second implementation of an Upgraded Hello World}
@end float
@verbatim
(defun example-upgraded-hello-world-2 ()
  (within-main-loop
    (let ((window (make-instance 'gtk-window
                                 :type :toplevel
                                 :title "Hello Buttons"
                                 :default-width 250
                                 :default-height 75
                                 :border-width 12))
          (box (make-instance 'gtk-box
                              :orientation :horizontal
                              :spacing 6)))
      (g-signal-connect window "destroy"
                        (lambda (widget)
                          (declare (ignore widget))
                          (leave-gtk-main)))
      (let ((button (gtk-button-new-with-label "Button 1")))
        (g-signal-connect button "clicked"
                          (lambda (widget)
                            (declare (ignore widget))
                            (format t "Button 1 was pressed.~%")))
        (gtk-box-pack-start box button))
      (let ((button (gtk-button-new-with-label "Button 2")))
        (g-signal-connect button "clicked"
                          (lambda (widget)
                            (declare (ignore widget))
                            (format t "Button 2 was pressed.~%")))
        (gtk-box-pack-start box button))
      (gtk-container-add window box)
      (gtk-widget-show-all window))))
@end verbatim

@c -----------------------------------------------------------------------------
@node Drawing, , An Upgraded Hello World, Top
@section Drawing

@ifnotinfo
@float Figure, figure-drawing
@caption{Drawing in response to input}
@center @image{figures/drawing278x255, 185pt}
@end float
@end ifnotinfo

@findex gtk-drawing-area
@findex drawing-area, gtk-drawing-area

@findex gtk-widget-queue-draw
@findex widget-queue-draw, gtk-widget-queue-draw

Many widgets, like buttons, do all their drawing themselves.  You just tell them
the label you want to see, and they figure out what font to use, draw the button
outline and focus rectangle, etc.  Sometimes, it is necessary to do some custom
drawing.  In that case, a @xurl{gtk-drawing-area} might be the right widget to
use.  It offers a canvas on which you can draw by connecting to the "draw"
signal.

The contents of a widget often need to be partially or fully redrawn, e. g. when
another window is moved and uncovers part of the widget, or when the window
containing it is resized.  It is also possible to explicitly cause part or all
of the widget to be redrawn, by calling the function
@xurl{gtk-widget-queue-draw} or its variants.  GTK+ takes care of most of the
details by providing a ready-to-use cairo context to the "draw" signal handler.

The following example shows a "draw" signal handler.  It is a more complicated
than the previous examples, since it also demonstrates input event handling by
means of "button-press" and "motion-notify" handlers.

@float Example, example-drawing
@caption{Drawing in response to input}
@end float
@verbatim
(let ((surface nil))
  (defun example-drawing ()
    (within-main-loop
      (let ((window (make-instance 'gtk-window
                                   :type :toplevel
                                   :title "Example Drawing"))
            (frame (make-instance 'gtk-frame
                                  :shadow-type :in))
            (area (make-instance 'gtk-drawing-area
                                 :width-request 250
                                 :height-request 200)))
        (g-signal-connect window "destroy"
                          (lambda (widget)
                            (declare (ignore widget))
                            (leave-gtk-main)))
        ;; Signals used to handle the backing surface
        (g-signal-connect area "draw"
           (lambda (widget cr)
             (declare (ignore widget))
             (let ((cr (pointer cr)))
               (cairo-set-source-surface cr surface 0.0 0.0)
               (cairo-paint cr)
               +gdk-event-propagate+)))
        (g-signal-connect area "configure-event"
           (lambda (widget event)
             (declare (ignore event))
             (when surface
               (cairo-surface-destroy surface))
             (setf surface
                   (gdk-window-create-similar-surface
                                   (gtk-widget-window widget)
                                   :color
                                   (gtk-widget-get-allocated-width widget)
                                   (gtk-widget-get-allocated-height widget)))
             ;; Clear surface
             (let ((cr (cairo-create surface)))
               (cairo-set-source-rgb cr 1.0 1.0 1.0)
               (cairo-paint cr)
               (cairo-destroy cr))
             (format t "leave event 'configure-event'~%")
             +gdk-event-stop+))
        ;; Event signals
        (g-signal-connect area "motion-notify-event"
           (lambda (widget event)
             (format t "MOTION-NOTIFY-EVENT ~A~%" event)
             (when (member :button1-mask (gdk-event-motion-state event))
               (let ((cr (cairo-create surface))
                     (x (gdk-event-motion-x event))
                     (y (gdk-event-motion-y event)))
                 (cairo-rectangle cr (- x 3.0) (- y 3.0) 6.0 6.0)
                 (cairo-fill cr)
                 (cairo-destroy cr)
                 (gtk-widget-queue-draw-area widget
                                             (truncate (- x 3.0))
                                             (truncate (- y 3.0))
                                             6
                                             6)))
             ;; We have handled the event, stop processing
             +gdk-event-stop+))
        (g-signal-connect area "button-press-event"
           (lambda (widget event)
             (format t "BUTTON-PRESS-EVENT ~A~%" event)
             (if (eql 1 (gdk-event-button-button event))
                 (let ((cr (cairo-create surface))
                       (x (gdk-event-button-x event))
                       (y (gdk-event-button-y event)))
                   (cairo-rectangle cr (- x 3.0) (- y 3.0) 6.0 6.0)
                   (cairo-fill cr)
                   (cairo-destroy cr)
                   (gtk-widget-queue-draw-area widget
                                               (truncate (- x 3.0))
                                               (truncate (- y 3.0))
                                               6
                                               6))
                 ;; Clear surface
                 (let ((cr (cairo-create surface)))
                   (cairo-set-source-rgb cr 1.0 1.0 1.0)
                   (cairo-paint cr)
                   (cairo-destroy cr)
                   (gtk-widget-queue-draw widget)))))
        (gtk-widget-add-events area
                               '(:button-press-mask
                                 :pointer-motion-mask))
        (gtk-container-add frame area)
        (gtk-container-add window frame)
        (gtk-widget-show-all window)))))
@end verbatim

