1 <refentry id="TreeWidget" revision="20 Mar 2002">
3 <refentrytitle>Tree and List Widget Overview</refentrytitle>
4 <manvolnum>3</manvolnum>
5 <refmiscinfo>GTK Library</refmiscinfo>
9 <refname>Tree and List Widget Overview</refname>
10 <refpurpose>Overview of <link
11 linkend="GtkTreeModel">GtkTreeModel</link>, <link
12 linkend="GtkTreeView">GtkTreeView</link>, and other associated widgets</refpurpose>
16 <title>Overview</title>
18 To create a tree or list in GTK+, use the <link
19 linkend="GtkTreeModel">GtkTreeModel</link> interface in
20 conjunction with the <link
21 linkend="GtkTreeView">GtkTreeView</link> widget. This widget is
22 designed around a <firstterm>Model/View/Controller</firstterm>
23 design and consists of four major parts:
25 <member>The tree view widget (<structname>GtkTreeView</structname>)</member>
26 <member>The view column (<structname>GtkTreeViewColumn</structname>)</member>
27 <member>The cell renderers (<structname>GtkCellRenderer</structname> etc.)</member>
28 <member>The model interface (<structname>GtkTreeModel</structname>)</member>
30 The <emphasis>View</emphasis> is composed of the first three
31 objects, while the last is the <emphasis>Model</emphasis>. One
32 of the prime benefits of the MVC design is that multiple views
33 can be created of a single model. For example, a model mapping
34 the file system could be created for a file manager. Many views
35 could be created to display various parts of the file system,
36 but only one copy need be kept in memory.
39 The purpose of the cell renderers is to provide extensibility to the
40 widget and to allow multiple ways of rendering the same type of data.
41 For example, consider how to render a boolean variable. Should it
42 render it as a string of "True" or "False", "On" or "Off", or should
43 it be rendered as a checkbox?
47 <title>Creating a model</title>
49 GTK+ provides two simple models that can be used: the <link
50 linkend="GtkListStore">GtkListStore</link> and the <link
51 linkend="GtkTreeStore">GtkTreeStore</link>. GtkListStore is used
52 to model list widgets, while the GtkTreeStore models trees. It
53 is possible to develop a new type of model, but the existing
54 models should be satisfactory for all but the most specialized of
55 situations. Creating the model is quite simple:
57 <informalexample><programlisting><![CDATA[
58 GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
59 ]]></programlisting></informalexample>
61 This creates a list store with two columns: a string column and a boolean
62 column. Typically the 2 is never passed directly like that; usually an
63 enum is created wherein the different columns are enumerated, followed by
64 a token that represents the total number of columns. The next example will
65 illustrate this, only using a tree store instead of a list store. Creating
66 a tree store operates almost exactly the same.
68 <informalexample><programlisting><![CDATA[
77 GtkTreeStore *store = gtk_tree_store_new (N_COLUMNS, /* Total number of columns */
78 G_TYPE_STRING, /* Book title */
79 G_TYPE_STRING, /* Author */
80 G_TYPE_BOOLEAN); /* Is checked out? */
81 ]]></programlisting></informalexample>
83 Adding data to the model is done using <link linkend="gtk-tree-store-set">
84 gtk_tree_store_set()</link> or <link linkend="gtk-list-store-set">
85 gtk_list_store_set()</link>, depending upon which sort of model was
86 created. To do this, a <link linkend="GtkTreeIter">GtkTreeIter</link> must
87 be acquired. The iterator points to the location where data will be added.
90 Once an iterator has been acquired, <link linkend="gtk-tree-store-set">
91 gtk_tree_store_set()</link> is used to apply data to the part of the model
92 that the iterator points to. Consider the following example:
94 <informalexample><programlisting><![CDATA[
97 gtk_tree_store_append (store, &iter, NULL); /* Acquire an iterator */
99 gtk_tree_store_set (store, &iter,
100 TITLE_COLUMN, "The Principle of Reason",
101 AUTHOR_COLUMN, "Martin Heidegger",
102 CHECKED_COLUMN, FALSE,
104 ]]></programlisting></informalexample>
107 Notice that the last argument is -1. This is always done because
108 this is a variable-argument function and it needs to know when to stop
109 processing arguments. It can be used to set the data in any or all
110 columns in a given row.
113 The third argument to <link linkend="gtk-tree-store-append">gtk_tree_store_append()</link> is the parent iterator. It
114 is used to add a row to a GtkTreeStore as a child of an existing row. This
115 means that the new row will only be visible when its parent is visible and
116 in its expanded state. Consider the following example:
118 <informalexample><programlisting><![CDATA[
119 GtkTreeIter iter1; /* Parent iter */
120 GtkTreeIter iter2; /* Child iter */
122 gtk_tree_store_append (store, &iter1, NULL); /* Acquire a top-level iterator */
123 gtk_tree_store_set (store, &iter1,
124 TITLE_COLUMN, "The Art of Computer Programming",
125 AUTHOR_COLUMN, "Donald E. Knuth",
126 CHECKED_COLUMN, FALSE,
129 gtk_tree_store_append (store, &iter2, &iter1); /* Acquire a child iterator */
130 gtk_tree_store_set (store, &iter2,
131 TITLE_COLUMN, "Volume 1: Fundamental Algorithms",
134 gtk_tree_store_append (store, &iter2, &iter1);
135 gtk_tree_store_set (store, &iter2,
136 TITLE_COLUMN, "Volume 2: Seminumerical Algorithms",
139 gtk_tree_store_append (store, &iter2, &iter1);
140 gtk_tree_store_set (store, &iter2,
141 TITLE_COLUMN, "Volume 3: Sorting and Searching",
143 ]]></programlisting></informalexample>
147 <title>Creating the view component</title>
149 While there are several different models to choose from, there is
150 only one view widget to deal with. It works with either the list
151 or the tree store. Setting up a <link
152 linkend="GtkTreeView">GtkTreeView</link> is not a difficult
153 matter. It needs a <link
154 linkend="GtkTreeModel">GtkTreeModel</link> to know where to
155 retrieve its data from.
157 <informalexample><programlisting><![CDATA[
160 tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
161 ]]></programlisting></informalexample>
164 <title>Columns and cell renderers</title>
166 Once the <link linkend="GtkTreeView">GtkTreeView</link> widget
167 has a model, it will need to know how to display the model. It
168 does this with columns and cell renderers.
171 Cell renderers are used to draw the data in the tree model in a
172 way. There are a number of cell renderers that come with GTK+ 2.x,
174 linkend="GtkCellRendererText">GtkCellRendererText</link>, <link
175 linkend="GtkCellRendererPixbuf">GtkCellRendererPixbuf</link> and
177 linkend="GtkCellRendererToggle">GtkCellRendererToggle</link>.
178 It is relatively easy to write a custom renderer.
181 A <link linkend="GtkTreeViewColumn">GtkTreeViewColumn</link> is the
182 object that GtkTreeView uses to organize the vertical columns in
183 the tree view. It needs to know the name of the column to label
184 for the user, what type of cell renderer to use, and which piece of
185 data to retrieve from the model for a given row.
187 <informalexample><programlisting><![CDATA[
188 GtkCellRenderer *renderer;
189 GtkTreeViewColumn *column;
191 renderer = gtk_cell_renderer_text_new ();
192 column = gtk_tree_view_column_new_with_attributes ("Author",
194 "text", AUTHOR_COLUMN,
196 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
197 ]]></programlisting></informalexample>
199 At this point, all the steps in creating a displayable tree have been
200 covered. The model is created, data is stored in it, a tree view is
201 created and columns are added to it.
206 <title>Selection handling</title>
208 Most applications will need to not only deal with displaying data, but also
209 receiving input events from users. To do this, simply get a reference to
210 a selection object and connect to the "changed" signal.
212 <informalexample><programlisting><![CDATA[
213 /* Prototype for selection handler callback */
214 static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data);
216 /* Setup the selection handler */
217 GtkTreeSelection *select;
219 select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
220 gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
221 g_signal_connect (G_OBJECT (select), "changed",
222 G_CALLBACK (tree_selection_changed_cb),
224 ]]></programlisting></informalexample>
226 Then to retrieve data for the row selected:
228 <informalexample><programlisting><![CDATA[
230 tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
236 if (gtk_tree_selection_get_selected (selection, &model, &iter))
238 gtk_tree_model_get (model, &iter, AUTHOR_COLUMN, &author, -1);
240 g_print ("You selected a book by %s\n", author);
245 ]]></programlisting></informalexample>
250 <title>Simple Example</title>
252 Here is a simple example of using a <link
253 linkend="GtkTreeView">GtkTreeView</link> widget in context of the
254 other widgets. It simply creates a simple model and view, and
255 puts them together. Note that the model is never populated with
256 data — that is left as an exercise for the reader. More
257 information can be found on this in the <link
258 linkend="GtkTreeStore">GtkTreeModel</link> section.
259 <informalexample><programlisting><![CDATA[
273 GtkTreeViewColumn *column;
274 GtkCellRenderer *renderer;
276 /* Create a model. We are using the store model for now, though we
277 * could use any other GtkTreeModel */
278 store = gtk_tree_store_new (N_COLUMNS,
283 /* custom function to fill the model with data */
284 populate_tree_model (store);
287 tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
289 /* The view now holds a reference. We can get rid of our own
291 g_object_unref (G_OBJECT (store));
293 /* Create a cell render and arbitrarily make it red for demonstration
295 renderer = gtk_cell_renderer_text_new ();
296 g_object_set (G_OBJECT (renderer),
300 /* Create a column, associating the "text" attribute of the
301 * cell_renderer to the first column of the model */
302 column = gtk_tree_view_column_new_with_attributes ("Author", renderer,
303 "text", AUTHOR_COLUMN,
306 /* Add the column to the view. */
307 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
309 /* Second column.. title of the book. */
310 renderer = gtk_cell_renderer_text_new ();
311 column = gtk_tree_view_column_new_with_attributes ("Title",
313 "text", TITLE_COLUMN,
315 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
317 /* Last column.. whether a book is checked out. */
318 renderer = gtk_cell_renderer_toggle_new ();
319 column = gtk_tree_view_column_new_with_attributes ("Checked out",
321 "active", CHECKED_COLUMN,
323 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
325 /* Now we can manipulate the view just like any other GTK widget */
329 </programlisting></informalexample>