1<?xml version='1.0' encoding='UTF-8'?>
2<page xmlns="http://projectmallard.org/1.0/"
3      xmlns:its="http://www.w3.org/2005/11/its"
4      type="topic"
5      id="image-viewer.vala">
6
7  <info>
8  <title type="text">Image viewer (Vala)</title>
9    <link type="guide" xref="vala#examples"/>
10
11    <desc>A little bit more than a simple "Hello world" GTK+ application.</desc>
12
13    <revision pkgversion="0.1" version="0.1" date="2011-03-18" status="review"/>
14    <credit type="author">
15      <name>GNOME Documentation Project</name>
16      <email its:translate="no">gnome-doc-list@gnome.org</email>
17    </credit>
18    <credit type="author">
19      <name>Johannes Schmid</name>
20      <email its:translate="no">jhs@gnome.org</email>
21    </credit>
22    <credit type="author">
23      <name>Philip Chimento</name>
24      <email its:translate="no">philip.chimento@gmail.com</email>
25    </credit>
26    <credit type="editor">
27     <name>Tiffany Antopolski</name>
28     <email its:translate="no">tiffany.antopolski@gmail.com</email>
29    </credit>
30  <credit type="editor">
31    <name>Marta Maria Casetti</name>
32    <email its:translate="no">mmcasetti@gmail.com</email>
33    <years>2013</years>
34  </credit>
35  </info>
36
37<title>Image viewer</title>
38<synopsis>
39  <p>In this tutorial you will create an application which opens and displays an image file. You will learn:</p>
40  <list type="numbered">
41    <item><p>How to set up a basic project using the <link xref="getting-ready">Anjuta IDE</link>.</p></item>
42    <item><p>How to write a <link href="http://developer.gnome.org/platform-overview/stable/gtk">Gtk application</link> in Vala</p></item>
43    <item><p>Some basic concepts of <link href="http://developer.gnome.org/gobject/stable/">GObject</link> programming</p></item>
44
45  </list>
46  <p>You'll need the following to be able to follow this tutorial:</p>
47  <list>
48    <item><p>Basic knowledge of the <link href="https://live.gnome.org/Vala/Tutorial">Vala</link> programming language.</p></item>
49    <item><p>An installed copy of <app>Anjuta</app>.</p></item>
50    <item><p>You may find the <link href="http://valadoc.org/gtk+-3.0/">gtk+-3.0</link> API Reference useful, although it is not necessary to follow the tutorial.</p></item>
51  </list>
52</synopsis>
53
54<media type="image" mime="image/png" src="media/image-viewer.png"/>
55
56<section id="anjuta">
57  <title>Create a project in Anjuta</title>
58  <p>Before you start coding, you'll need to set up a new project in Anjuta.
59  This will create all of the files you need to build and run the code later on.
60  It's also useful for keeping everything together.</p>
61  <steps>
62    <item>
63      <p>Start <app>Anjuta</app> and click <gui>Create a new project</gui> or <guiseq><gui>File</gui><gui>New</gui><gui>Project</gui></guiseq> to open the project wizard.</p>
64    </item>
65    <item>
66      <p>From the <gui>Vala</gui> tab choose <gui>GTK+ (Simple)</gui>, click <gui>Continue</gui>, and fill out your details on the next page.
67      Use <file>image-viewer</file> as project name and directory.</p>
68   	</item>
69    <item>
70      <p>Make sure that <gui>Use GtkBuilder for user interface</gui> is unchecked as we will create the UI manually in this tutorial.</p>
71     <note><p>
72      You will learn how to use the interface builder in the <link xref="guitar-tuner.vala">Guitar-Tuner</link> tutorial.</p></note>
73    </item>
74    <item>
75      <p>Click <gui>Continue</gui> then <gui>Apply</gui> and the project will be created for you.
76      Open <file>src/image_viewer.vala</file> from the <gui>Project</gui> or <gui>File</gui> tabs.
77      You will see this code:</p>
78      <code mime="text/x-csharp"><![CDATA[
79using GLib;
80using Gtk;
81
82public class Main : Object
83{
84
85	public Main ()
86	{
87		Window window = new Window();
88		window.set_title ("Hello World");
89		window.show_all();
90		window.destroy.connect(on_destroy);
91	}
92
93	public void on_destroy (Widget window)
94	{
95		Gtk.main_quit();
96	}
97
98	static int main (string[] args)
99	{
100		Gtk.init (ref args);
101		var app = new Main ();
102
103		Gtk.main ();
104
105		return 0;
106	}
107}]]></code>
108    </item>
109  </steps>
110</section>
111
112<section id="build">
113  <title>Build the code for the first time</title>
114  <p>The code loads an (empty) window from the user interface description file and shows it.
115  More details are given below; skip this list if you understand the basics:</p>
116
117  <list>
118    <item>
119      <p>The two <code>using</code> lines at the top import namespaces so we don't have to name them explicitly.</p>
120    </item>
121    <item>
122      <p>The constructor of the <code>Main</code> class creates a new (empty) window and connects a <link href="https://live.gnome.org/Vala/SignalsAndCallbacks">signal</link> to exit the application when that window is closed.</p>
123      <p>Connecting signals is how you define what happens when you push a button, or when some other event happens.
124      Here, the <code>destroy</code> function is called (and quits the app) when you close the window.</p>
125    </item>
126    <item>
127      <p>The <code>static main</code> function is run by default when you start a Vala application.
128      It calls a few functions which create the <code>Main</code> class, set up and then run the application.
129      The <link href="http://valadoc.org/gtk+-3.0/Gtk.main.html"><code>Gtk.main</code></link> function starts the GTK <link href="http://en.wikipedia.org/wiki/Event_loop">main loop</link>, which runs the user interface and starts listening for events (like clicks and key presses).</p>
130    </item>
131  </list>
132
133  <p>This code is ready to be used, so you can compile it by clicking <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> (or press <keyseq><key>Shift</key><key>F7</key></keyseq>).</p>
134  <p>Change the <gui>Configuration</gui> to <gui>Default</gui> and then press <gui>Execute</gui> to configure the build directory.
135  You only need to do this once, for the first build.</p>
136</section>
137
138<section id="ui">
139  <title>Creating the user interface</title>
140  <p>Now we will bring life into the empty window.
141  GTK organizes the user interface with <link href="http://www.valadoc.org/gtk+-2.0/Gtk.Container.html"><code>Gtk.Container</code></link>s that can contain other widgets and even other containers.
142  Here we will use the simplest available container, a <link href="http://unstable.valadoc.org/gtk+-2.0/Gtk.Box.html"><code>Gtk.Box</code></link>.</p>
143
144<p>Add the following lines to the top of the <code>Main</code> class:</p>
145  <code mime="text/x-csharp"><![CDATA[
146private Window window;
147private Image image;
148]]></code>
149
150<p>Now replace the current constructor with the one below:</p>
151<code mime="text/x-csharp"><![CDATA[
152
153public Main () {
154
155	window = new Window ();
156	window.set_title ("Image Viewer in Vala");
157
158	// Set up the UI
159	var box = new Box (Orientation.VERTICAL, 5);
160	var button = new Button.with_label ("Open image");
161	image = new Image ();
162
163	box.pack_start (image, true, true, 0);
164	box.pack_start (button, false, false, 0);
165	window.add (box);
166
167	// Show open dialog when opening a file
168	button.clicked.connect (on_open_image);
169
170	window.show_all ();
171	window.destroy.connect (main_quit);
172}
173]]></code>
174  <steps>
175    <item>
176      <p>The first two lines are the parts of the GUI that we will need to access from more than one method.
177      We declare them up here so that they are accessible throughout the class instead of only in the method where they are created.</p>
178    </item>
179    <item>
180      <p>The first lines of the constructor create the empty window.
181      The next lines create the widgets we want to use: a button for opening up an image, the image view widget itself and the box we will use as a container.</p>
182    </item>
183    <item>
184      <p>The calls to <link href="http://unstable.valadoc.org/gtk+-2.0/Gtk.Box.pack_start.html"><code>pack_start</code></link> add the two widgets to the box and define their behaviour.
185      The image will expand into any available space whereas the button will just be as big as needed.
186      You will notice that we don't set explicit sizes on the widgets.
187      In GTK this is usually not needed as it makes it much easier to have a layout that looks good in different window sizes.
188      Next, the box is added to the window.</p>
189    </item>
190    <item>
191      <p>We need to define what happens when the user clicks on the button. GTK uses the concept of <em>signals</em>.</p>
192      <p>
193      When the <link href="http://valadoc.org/gtk+-3.0/Gtk.Button.html">button</link> is clicked, it fires the <link href="http://valadoc.org/gtk+-3.0/Gtk.Button.clicked.html"><code>clicked</code></link> signal, which we can connect to some action (defined in a <link href="https://live.gnome.org/Vala/SignalsAndCallbacks">callback</link> method).
194      </p>
195      <p>
196      This is done using the <code>connect</code> method of the button's <code>clicked</code> signal, which in this case tells GTK to call the (yet undefined) <code>on_image_open</code> callback method when the button is clicked.
197      We will define the <em>callback</em> in the next section.
198      </p>
199      <p>
200      In the callback, we need to access the <code>window</code> and <code>image</code> widgets, which is why we defined them as private members at the top of our class.</p>
201    </item>
202    <item>
203      <p>The last <code>connect</code> call makes sure that the application exits when the window is closed.
204      The code generated by Anjuta called an <code>on_destroy</code> callback method which called <link href="http://www.valadoc.org/gtk+-2.0/Gtk.main_quit.html"><code>Gtk.main_quit</code></link>, but just connecting our signal to <code>main_quit</code> directly is easier. You can delete the <code>on_destroy</code> method.</p>
205    </item>
206  </steps>
207</section>
208
209<section id="image">
210  <title>Showing the image</title>
211  <p>We will now define the signal handler for the <code>clicked</code> signal for the
212button we mentioned before.
213  Add this code after the constructor:</p>
214  <code mime="text/x-csharp"><![CDATA[
215public void on_open_image (Button self) {
216	var filter = new FileFilter ();
217	var dialog = new FileChooserDialog ("Open image",
218	                                    window,
219	                                    FileChooserAction.OPEN,
220	                                    Stock.OK,     ResponseType.ACCEPT,
221	                                    Stock.CANCEL, ResponseType.CANCEL);
222	filter.add_pixbuf_formats ();
223	dialog.add_filter (filter);
224
225	switch (dialog.run ())
226	{
227		case ResponseType.ACCEPT:
228			var filename = dialog.get_filename ();
229			image.set_from_file (filename);
230			break;
231		default:
232			break;
233	}
234	dialog.destroy ();
235}
236]]></code>
237  <p>This is a bit complicated, so let's break it down:</p>
238  <note><p>A signal handler is a type of callback method that is called when a signal is emitted.  Here the terms are used interchangeably.</p></note>
239  <list>
240    <item>
241      <p>The first argument of the callback method is always the widget that sent the signal.
242      Sometimes other arguments related to the signal come after that, but <em>clicked</em> doesn't have any.</p>
243      <p>In this case the <code>button</code> sent the <code>clicked</code> signal, which is connected to the <code>on_open_image</code> callback method:</p>
244<code mime="text/x-csharp"><![CDATA[
245        button.clicked.connect (on_open_image);
246]]></code>
247
248  <p>The <code>on_open_image</code> method takes the button that emitted the signal as an argument:   </p>
249 <code mime="text/x-csharp"><![CDATA[
250        public void on_open_image (Button self)
251]]></code>
252    </item>
253    <item>
254      <p>The next interesting line is where the dialog for choosing the file is created.
255      <link href="http://www.valadoc.org/gtk+-3.0/Gtk.FileChooserDialog.html"><code>FileChooserDialog</code></link>'s constructor takes the title of the dialog, the parent window of the dialog and several options like the number of buttons and their corresponding values.</p>
256      <p>Notice that we are using <link href="http://unstable.valadoc.org/gtk+-3.0/Gtk.Stock.html"><em>stock</em></link> button names from Gtk, instead of manually typing "Cancel" or "Open".
257      The advantage of using stock names is that the button labels will already be translated into the user's language.</p>
258    </item>
259    <item>
260      <p>The next two lines restrict the <gui>Open</gui> dialog to only display files which can be opened by <em>GtkImage</em>. GtkImage is a widget which displays an image.
261      A filter object is created first; we then add all kinds of files supported by <link href="http://www.valadoc.org/gdk-pixbuf-2.0/Gdk.Pixbuf.html"><code>Gdk.Pixbuf</code></link> (which includes most image formats like PNG and JPEG) to the filter.
262      Finally, we set this filter to be the <gui>Open</gui> dialog's filter.</p>
263    </item>
264    <item>
265      <p><link href="http://www.valadoc.org/gtk+-3.0/Gtk.Dialog.run.html"><code>dialog.run</code></link> displays the <gui>Open</gui> dialog.
266      The dialog will wait for the user to choose an image; when they do, <code>dialog.run</code> will return the <link href="http://www.valadoc.org/gtk+-3.0/Gtk.ResponseType.html">ResponseType</link> value <code>ResponseType.ACCEPT</code> (it would return <code>ResponseType.CANCEL</code> if the user clicked <gui>Cancel</gui>).
267      The <code>switch</code> statement tests for this.</p>
268    </item>
269    <item>
270      <p>Assuming that the user did click <gui>Open</gui>, the next lines get the filename of the image selected by the user, and tell the <code>GtkImage</code> widget to load and display the selected image.</p>
271    </item>
272    <item>
273      <p>In the final line of this method, we destroy the <gui>Open</gui> dialog because we don't need it any more.</p>
274      <p>Destroying automatically hides the dialog.</p>
275    </item>
276  </list>
277</section>
278
279<section id="run">
280  <title>Build and run the application</title>
281  <p>All of the code should now be ready to go.
282  Click <guiseq><gui>Build</gui><gui>Build Project</gui></guiseq> to build everything again, and then <guiseq><gui>Run</gui><gui>Execute</gui></guiseq> to start the application.</p>
283  <p>If you haven't already done so, choose the <file>src/image-viewer</file> application in the dialog that appears.
284  Finally, hit <gui>Run</gui> and enjoy!</p>
285</section>
286
287<section id="impl">
288  <title>Reference Implementation</title>
289  <p>If you run into problems with the tutorial, compare your code with this <link href="image-viewer/image-viewer.vala">reference code</link>.</p>
290</section>
291
292<section id="next">
293  <title>Next steps</title>
294  <p>Here are some ideas for how you can extend this simple demonstration:</p>
295  <list>
296  <item><p>Set it up so that when the window opens it is of a specific size to start off with. For example, 200 X 200 pixels.</p></item>
297   <item>
298     <p>Have the user select a directory rather than a file, and provide controls to cycle through all of the images in a directory.</p>
299   </item>
300   <item>
301     <p>Apply random filters and effects to the image when it is loaded and allow the user to save the modified image.</p>
302     <p><link href="http://www.gegl.org/api.html">GEGL</link> provides powerful image manipulation capabilities.</p>
303   </item>
304   <item>
305     <p>Allow the user to load images from network shares, scanners, and other more complicated sources.</p>
306     <p>You can use <link href="http://library.gnome.org/devel/gio/unstable/">GIO</link> to handle network file transfers and the like, and <link href="http://library.gnome.org/devel/gnome-scan/unstable/">GNOME Scan</link> to handle scanning.</p>
307   </item>
308  </list>
309</section>
310
311</page>
312