]> Pileus Git - ~andy/gtk/blob - docs/reference/gtk/tree_widget.sgml
Document im_module_file and settings assignments as toplevel statements.
[~andy/gtk] / docs / reference / gtk / tree_widget.sgml
1 <refentry id="TreeWidget" revision="20 Mar 2002">
2   <refmeta>
3     <refentrytitle>Tree and List Widget Overview</refentrytitle>
4     <manvolnum>3</manvolnum>
5     <refmiscinfo>GTK Library</refmiscinfo>
6   </refmeta>
7
8   <refnamediv>
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>
13   </refnamediv>
14
15   <refsect1>
16     <title>Overview</title>
17     <para>
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:
24       <simplelist>
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>
29       </simplelist>
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.
37     </para>
38     <para>
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?
44     </para>
45   </refsect1>
46   <refsect1>
47     <title>Creating a model</title>
48     <para>
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:
56     </para>
57       <informalexample><programlisting><![CDATA[
58 GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
59 ]]></programlisting></informalexample>
60     <para>
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.
67     </para>
68     <informalexample><programlisting><![CDATA[
69 enum
70 {
71    TITLE_COLUMN,
72    AUTHOR_COLUMN,
73    CHECKED_COLUMN,
74    N_COLUMNS
75 };
76
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>
82     <para>
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.
88     </para>
89     <para>
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:
93     </para>
94     <informalexample><programlisting><![CDATA[
95 GtkTreeIter   iter;
96
97 gtk_tree_store_append (store, &iter, NULL);  /* Acquire an iterator */
98
99 gtk_tree_store_set (store, &iter,
100                     TITLE_COLUMN, "The Principle of Reason",
101                     AUTHOR_COLUMN, "Martin Heidegger",
102                     CHECKED_COLUMN, FALSE,
103                     -1);
104 ]]></programlisting></informalexample>
105
106   <para>
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.
111   </para>
112   <para>
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:
117   </para>
118   <informalexample><programlisting><![CDATA[
119 GtkTreeIter iter1;  /* Parent iter */
120 GtkTreeIter iter2;  /* Child iter  */
121
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,
127                     -1);
128
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",
132                     -1);
133
134 gtk_tree_store_append (store, &iter2, &iter1);
135 gtk_tree_store_set (store, &iter2,
136                     TITLE_COLUMN, "Volume 2: Seminumerical Algorithms",
137                     -1);
138
139 gtk_tree_store_append (store, &iter2, &iter1);
140 gtk_tree_store_set (store, &iter2,
141                     TITLE_COLUMN, "Volume 3: Sorting and Searching",
142                     -1);
143 ]]></programlisting></informalexample>
144   </refsect1>
145
146   <refsect1>
147     <title>Creating the view component</title>
148     <para>
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.
156     </para>
157     <informalexample><programlisting><![CDATA[
158 GtkWidget *tree;
159
160 tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
161 ]]></programlisting></informalexample>
162
163     <refsect2>
164       <title>Columns and cell renderers</title>
165       <para>
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.
169       </para>
170       <para>
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,
173         including the <link
174         linkend="GtkCellRendererText">GtkCellRendererText</link>, <link
175         linkend="GtkCellRendererPixbuf">GtkCellRendererPixbuf</link> and
176         the <link
177         linkend="GtkCellRendererToggle">GtkCellRendererToggle</link>.
178         It is relatively easy to write a custom renderer.
179       </para>
180       <para>
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.
186       </para>
187       <informalexample><programlisting><![CDATA[
188 GtkCellRenderer *renderer;
189 GtkTreeViewColumn *column;
190
191 renderer = gtk_cell_renderer_text_new ();
192 column = gtk_tree_view_column_new_with_attributes ("Author",
193                                                    renderer,
194                                                    "text", AUTHOR_COLUMN,
195                                                    NULL);
196 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
197 ]]></programlisting></informalexample>
198       <para>
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.
202       </para>
203     </refsect2>
204
205     <refsect2>
206       <title>Selection handling</title>
207       <para>
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.
211       </para>
212       <informalexample><programlisting><![CDATA[
213 /* Prototype for selection handler callback */
214 static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data);
215
216 /* Setup the selection handler */
217 GtkTreeSelection *select;
218
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),
223                   NULL);
224 ]]></programlisting></informalexample>
225         <para>
226           Then to retrieve data for the row selected:
227         </para>
228         <informalexample><programlisting><![CDATA[
229 static void
230 tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
231 {
232         GtkTreeIter iter;
233         GtkTreeModel *model;
234         gchar *author;
235
236         if (gtk_tree_selection_get_selected (selection, &model, &iter))
237         {
238                 gtk_tree_model_get (model, &iter, AUTHOR_COLUMN, &author, -1);
239
240                 g_print ("You selected a book by %s\n", author);
241
242                 g_free (author);
243         }
244 }
245 ]]></programlisting></informalexample>
246     </refsect2>
247   </refsect1>
248
249   <refsect1>
250     <title>Simple Example</title>
251     <para>
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 &mdash; 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[
260 enum
261 {
262    TITLE_COLUMN,
263    AUTHOR_COLUMN,
264    CHECKED_COLUMN,
265    N_COLUMNS
266 };
267
268 void
269 setup_tree (void)
270 {
271    GtkTreeStore *store;
272    GtkWidget *tree;
273    GtkTreeViewColumn *column;
274    GtkCellRenderer *renderer;
275
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,
279                                G_TYPE_STRING,
280                                G_TYPE_STRING,
281                                G_TYPE_BOOLEAN);
282
283    /* custom function to fill the model with data */
284    populate_tree_model (store);
285
286    /* Create a view */
287    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
288
289    /* The view now holds a reference.  We can get rid of our own
290     * reference */
291    g_object_unref (G_OBJECT (store));
292
293    /* Create a cell render and arbitrarily make it red for demonstration
294     * purposes */
295    renderer = gtk_cell_renderer_text_new ();
296    g_object_set (G_OBJECT (renderer),
297                  "foreground", "red",
298                  NULL);
299
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,
304                                                       NULL);
305
306    /* Add the column to the view. */
307    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
308
309    /* Second column.. title of the book. */
310    renderer = gtk_cell_renderer_text_new ();
311    column = gtk_tree_view_column_new_with_attributes ("Title",
312                                                       renderer,
313                                                       "text", TITLE_COLUMN,
314                                                       NULL);
315    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
316
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",
320                                                       renderer,
321                                                       "active", CHECKED_COLUMN,
322                                                       NULL);
323    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
324
325    /* Now we can manipulate the view just like any other GTK widget */
326    ...
327 }
328 ]]>
329       </programlisting></informalexample>
330     </para>
331   </refsect1>
332 </refentry>