61b8f3987c368d2c45eea22328abce9883d85cbf
[cl-gtk2.git] / doc / tutorial.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <article>
3   <articleinfo>
4     <title>CL-GTK2 Tutorial</title>
5     <author>
6       <personname>
7         <firstname>Dmitry</firstname>
8         <surname>Kalyanov</surname>
9       </personname>
10     </author>
11   </articleinfo>
12   <section>
13     <title>TODO</title>
14     <para>Introduction</para>
15     <para>More involved example: simple text editor</para>
16     <para>More involved example walk-through: widgets, properties, packing, child properties</para>
17     <para>TreeView example</para>
18   </section>
19   <section>
20     <title>Installation</title>
21     <para>Unpack the CL-GTK2 sources, and add them to <varname>asdf:*central-registry*</varname>:</para>
22     <programlisting>
23       (push "/path/to/cl-gtk2/glib/" asdf:*central-registry*)
24       (push "/path/to/cl-gtk2/gdk/" asdf:*central-registry*)
25       (push "/path/to/cl-gtk2/gtk/" asdf:*central-registry*)
26     </programlisting>
27   </section>
28   <section>
29     <title>"Hello world" example</title>
30     <para>Let's start from a simple example.</para>
31     <graphic fileref="hello_world.png"/>
32     <para>Load the GTK system: <programlisting>(asdf:oos 'asdf:load-op :gtk)</programlisting></para>
33     <para>Having loaded the GTK system, compile the following code:</para>
34     <programlisting linenumbering="numbered">
35 (defpackage :gtk-hello
36   (:use :cl :gtk :gobject :glib)
37   (:export :run))
38
39 (in-package :gtk-hello)
40
41 (defun run ()
42   (let ((output *standard-output*))
43     (with-main-loop
44         (let ((window (make-instance 'gtk-window
45                                      :type :toplevel
46                                      :window-position :center
47                                      :title "Hello world!"
48                                      :default-width 300
49                                      :default-height 100))
50               (button (make-instance 'button :label "Hello, world!"))
51               (counter 0))
52           (g-signal-connect button "clicked"
53                             (lambda (b)
54                               (declare (ignore b))
55                               (format output "Hello, world!~%")
56                               (setf (button-label button)
57                                     (format nil
58                                             "Hello, world! (clicked ~D times)"
59                                             (incf counter)))))
60           (container-add window button)
61           (widget-show window :all t)))))
62     </programlisting>
63     <para>And now, run it:<programlisting>(gtk-hello:run)</programlisting></para>
64     <para>This code should create a form with a button. When the button is clicked, this program prints a message to standard output and changes the text of the button.</para>
65     <para>If you have a window, then congratulations! Otherwise, contact the author for support.</para>
66   </section>
67   <section>
68     <title>Example walk-through</title>
69     <para>Let's analyze the example step by step.</para>
70     <para>CL-GTK2 runs the Gtk main loop in background thread. This is done so you could have your application running and interacting with the Lisp system through the REPL.</para>
71     <para>To execute some code and ensure that Gtk+ main loop is started, WITH-MAIN-LOOP macro is used. It runs the body of code within the Gtk+ main loop. Because all calls to Gtk+ functions require locking, it is neccessary to run this code from th main loop. Because we are running the code in another thread, its dynamic bindings (including *standard-output*) will be lost. To be able to print at REPL, we save reference to the standard output stream in the closure.</para>
72     <para>Gtk+ objects are created with make-instance and are properly garbage-collected. Some properties (slots) of objects are constructor-only properties and can only be set at object construction time. For example, "type" property of GtkWindow can only be set during its creation.</para>
73     <para>Call to container-add puts button as a child widget into window, and widget-show shows all widgets of window.</para>
74     <para>In Gtk+, objects have "signals", to which handlers can be attached. When something happens that results in "emitting" the signal (e.g., button being clicked emits "clicked" signal), all handlers of this signal are called. Handler of GtkButton's "clicked" signal has only one argument - the button that was clicked. CL-GTK2 allows attaching any function (including closures) as signal handlers and ensures that closure is freed properly.</para>
75   </section>
76 </article>