Merge remote-tracking branch 'andy128k/master'
[cl-gtk2.git] / doc / tutorial.xml
blobd28a0a53a90d713553f6b0f8d6c04db7b059d445
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       <email>Kalyanov.Dmitry@gmail.com</email>
11     </author>
12   </articleinfo>
13   <section>
14     <title>TODO</title>
15     <para>Introduction</para>
16     <para>More involved example: simple text editor</para>
17     <para>More involved example walk-through: widgets, properties, packing, child properties</para>
18     <para>TreeView example</para>
19   </section>
20   <section>
21     <title>Installation</title>
22     <para>CL-GTK2 is in alpha stage and is unstable and not feature-complete. It is being developed on x86-64 gentoo linux with SBCL. It should, in general, work with other lisp compilers and on other platforms. CL-GTK2 requires some features not present in the Common Lisp Standard, namely it requires CFFI support with callbacks and long-long support (most modern lisp implementations are supported, including clisp) and it requires CLOS MOP (MetaObject Protocol) which is also is present (or is being added to) most modern lisp implementations.</para>
23     <para>CL-GTK2 requires Gtk+ version 2.16 or later. CL-GTK2 was tested on SBCL-1.0.18 and SBCL-1.0.28</para>
24     <para>If you have any difficulties installing or using CL-GTK2, contact me (the author of this tutorial and of CL-GTK2) via email Kalyanov.Dmitry@gmail.com or via jabber mo3r@jabber.ru.</para>
25     <para>First, install CL-GTK2 dependcies. CL-GTK2 has the following dependencies (CL-GTK2 was tested with specified versions; it would probably not work with earlier versions but should work with later versions):</para>
26     <itemizedlist>
27       <listitem><para><ulink url="http://common-lisp.net/project/cffi">CFFI</ulink> (version 0.10.4)</para></listitem>
28       <listitem><para><ulink url="http://www.cliki.net/trivial-garbage">Trivial-Garbage</ulink> (version 0.18)</para></listitem>
29       <listitem><para><ulink url="http://common-lisp.net/project/iterate/">Iterate</ulink> (version 1.4.3)</para></listitem>
30       <listitem><para><ulink url="http://common-lisp.net/project/bordeaux-threads/">Bordeaux-Threads</ulink> (version 0.6.0)</para></listitem>
31       <listitem><para><ulink url="http:/common-lisp.net/project/closer/closer-mop.html/">Closer-MOP</ulink> (version 0.55)</para></listitem>
32     </itemizedlist>
33     <para>Currently, CL-GTK2 is only available in Git repository at <ulink url="http://repo.or.cz/w/cl-gtk2.git">http://repo.or.cz/w/cl-gtk2.git</ulink>. If you do not want or can not to use Git, download the snapshot from <ulink url="http://repo.or.cz/w/cl-gtk2.git?a=snapshot;h=HEAD;sf=tgz">http://repo.or.cz/w/cl-gtk2.git?a=snapshot;h=HEAD;sf=tgz</ulink>.</para>
34     <para>Unpack the CL-GTK2 sources, and add them to <varname>asdf:*central-registry*</varname>:</para>
35     <programlisting>
36       (push "/path/to/cl-gtk2/glib/" asdf:*central-registry*)
37       (push "/path/to/cl-gtk2/gdk/" asdf:*central-registry*)
38       (push "/path/to/cl-gtk2/gtk/" asdf:*central-registry*)
39     </programlisting>
40     <para>Now you should be able to load the CL-GTK2:</para>
41     <programlisting>(asdf:oos 'asdf:load-op :gtk)</programlisting>
42     <para>When the system is loaded, run <varname>(gtk-demo:demo-text-editor)</varname>. A text editor window should pop up:</para>
43     <graphic fileref="lisp_ide.png"/>
44     <para>This is a very simple text editor written in CL-GTK2. Apart from editing the text, it can evaluate expressions: select expression and press the "execute" button. Expression will be evaluated and its result will be put into text view.</para>
45   </section>
46   <section>
47     <title>"Hello world" example</title>
48     <para>Let's start from a simple example.</para>
49     <graphic fileref="hello_world.png"/>
50     <para>Start Slime, type the following code in the REPL:</para>
51     <programlisting linenumbering="numbered">
52 (asdf:oos 'asdf:load-op :gtk)
54 (gtk:within-main-loop
55   (let ((window (make-instance 'gtk:gtk-window :title "Hello, world!")))
56     (gtk:widget-show window)))
57     </programlisting>
58     <para>The empty window with title "Hello, world!" should appear.</para>
59     <para>Let's analyze this example line-by-line.</para>
60     <para><varname>(asdf:oos 'asdf:load-op :gtk)</varname> loads the GTK system into Lisp.</para>
61     <para>CL-GTK2 runs Gtk+ main loop in background thread (because Lisp development is interactive in its nature; if main loop would block the REPL thread, you would have to restart the Lisp image too often). Because all access to Gtk+ should come from Gtk+ thread, we should run the code in that thread. Macro <varname>gtk:within-main-loop</varname> does exactly that: it schedules the code to be tun in the Gtk+ thread. You should use this macro whenever you want evaluate the code from the REPL or when you start you application.</para>
62     <para>Next, we create the window with <varname>make-instance</varname> and set its <varname>title</varname> property to <varname>"Hello, world!"</varname>.</para>
63     <para>When the window is created, it is not yet shown on the screen. To show it, we call <varname>(gtk:widget-show window)</varname>.</para>
64     <para>After this code executes, you should get back to the REPL (rememer, Gtk+ runs in background thread) and the window should appear on the screen.</para>
65   </section>
66   <section>
67     <title>Example walk-through</title>
68     <para>Let's analyze the example step by step.</para>
69     <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>
70     <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>
71     <para>Gtk+ objects are created with make-instance and are properly garbage-collected.</para>
72     <para>Object have properties, which are represented as slots in CL-GTK2. 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. To access properties, you may use <varname>slot-value</varname> function or slot accessor methods. For property <varname>Y</varname> declared on class <varname>X</varname>, method <varname>X-Y</varname> returns the value of the property. Properties are setfable (with exception of read-only and constructor-only properties).</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>