<sect1 id="TreeWidget">
  <title>Tree and List Widget Overview</title>
  <para>
    To create a tree or list in GTK, use the <link linkend="GtkTreeModel"><type>GtkTreeModel</type></link> interface in
    conjunction with the <link linkend="GtkTreeView"><type>GtkTreeView</type></link> widget. This widget is designed
    around a <emphasis>Model/View/Controller</emphasis> design and
    consists of four major parts:
  </para>
  <itemizedlist spacing="compact">
    <listitem>
      <para>
        The tree view widget (GtkTreeView)
      </para>
    </listitem>
    <listitem>
      <para>
        The view column (GtkTreeViewColumn)
      </para>
    </listitem>
    <listitem>
      <para>
        The cell renderers (GtkCellRenderer etc.)
      </para>
    </listitem>
    <listitem>
      <para>
        The model interface (GtkTreeModel)
      </para>
    </listitem>
  </itemizedlist>
  <para>
    The <emphasis>View</emphasis> is composed of the first three
    objects, while the last is the <emphasis>Model</emphasis>. One of
    the prime benefits of the MVC design is that multiple views can be
    created of a single model. For example, a model mapping the file
    system could be created for a file manager. Many views could be
    created to display various parts of the file system, but only one
    copy need be kept in memory.
  </para>
  <para>
    The purpose of the cell renderers is to provide extensibility to the
    widget and to allow multiple ways of rendering the same type of
    data. For example, consider how to render a boolean variable. Should
    it render it as a string of <quote>True</quote> or
    <quote>False</quote>, <quote>On</quote> or <quote>Off</quote>, or
    should it be rendered as a checkbox?
  </para>
  <sect2>
    <title>Creating a model</title>
    <para>
      GTK provides two simple models that can be used: the <link linkend="GtkListStore"><type>GtkListStore</type></link>
      and the <link linkend="GtkTreeStore"><type>GtkTreeStore</type></link>. GtkListStore is used to model list widgets,
      while the GtkTreeStore models trees. It is possible to develop a
      new type of model, but the existing models should be satisfactory
      for all but the most specialized of situations. Creating the model
      is quite
    </para>
    <programlisting language="c">
GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
</programlisting>
    <para>
      This creates a list store with two columns: a string column and a
      boolean column. Typically the 2 is never passed directly like
      that; usually an enum is created wherein the different columns are
      enumerated, followed by a token that represents the total number
      of columns. The next example will illustrate this, only using a
      tree store instead of a list store. Creating a tree store operates
      almost exactly the same.
    </para>
    <programlisting language="c">
enum
{
   TITLE_COLUMN,
   AUTHOR_COLUMN,
   CHECKED_COLUMN,
   N_COLUMNS
};

GtkTreeStore *store = gtk_tree_store_new (N_COLUMNS,       /* Total number of columns */
                                          G_TYPE_STRING,   /* Book title              */
                                          G_TYPE_STRING,   /* Author                  */
                                          G_TYPE_BOOLEAN); /* Is checked out?         */
</programlisting>
    <para>
      Adding data to the model is done using <link linkend="gtk-tree-store-set"><function>gtk_tree_store_set()</function></link> or
      <link linkend="gtk-list-store-set"><function>gtk_list_store_set()</function></link>, depending upon which sort of model was
      created. To do this, a <link linkend="GtkTreeIter"><type>GtkTreeIter</type></link> must be acquired. The iterator
      points to the location where data will be added.
    </para>
    <para>
      Once an iterator has been acquired, <link linkend="gtk-tree-store-set"><function>gtk_tree_store_set()</function></link> is used
      to apply data to the part of the model that the iterator points
      to. Consider the following example:
    </para>
    <programlisting language="c">
GtkTreeIter iter;

gtk_tree_store_append (store, &amp;iter, NULL);  /* Acquire an iterator */

gtk_tree_store_set (store, &amp;iter,
                    TITLE_COLUMN, &quot;The Principle of Reason&quot;,
                    AUTHOR_COLUMN, &quot;Martin Heidegger&quot;,
                    CHECKED_COLUMN, FALSE,
                    -1);
</programlisting>
    <para>
      Notice that the last argument is -1. This is always done because
      this is a variable-argument function and it needs to know when to
      stop processing arguments. It can be used to set the data in any
      or all columns in a given row.
    </para>
    <para>
      The third argument to <link linkend="gtk-tree-store-append"><function>gtk_tree_store_append()</function></link> is the parent
      iterator. It is used to add a row to a GtkTreeStore as a child of
      an existing row. This means that the new row will only be visible
      when its parent is visible and in its expanded state. Consider the
      following example:
    </para>
    <programlisting language="c">
GtkTreeIter iter1;  /* Parent iter */
GtkTreeIter iter2;  /* Child iter  */

gtk_tree_store_append (store, &amp;iter1, NULL);  /* Acquire a top-level iterator */
gtk_tree_store_set (store, &amp;iter1,
                    TITLE_COLUMN, &quot;The Art of Computer Programming&quot;,
                    AUTHOR_COLUMN, &quot;Donald E. Knuth&quot;,
                    CHECKED_COLUMN, FALSE,
                    -1);

gtk_tree_store_append (store, &amp;iter2, &amp;iter1);  /* Acquire a child iterator */
gtk_tree_store_set (store, &amp;iter2,
                    TITLE_COLUMN, &quot;Volume 1: Fundamental Algorithms&quot;,
                    -1);

gtk_tree_store_append (store, &amp;iter2, &amp;iter1);
gtk_tree_store_set (store, &amp;iter2,
                    TITLE_COLUMN, &quot;Volume 2: Seminumerical Algorithms&quot;,
                    -1);

gtk_tree_store_append (store, &amp;iter2, &amp;iter1);
gtk_tree_store_set (store, &amp;iter2,
                    TITLE_COLUMN, &quot;Volume 3: Sorting and Searching&quot;,
                    -1);
</programlisting>
  </sect2>
  <sect2>
    <title>Creating the view component</title>
    <para>
      While there are several different models to choose from, there is
      only one view widget to deal with. It works with either the list
      or the tree store. Setting up a <link linkend="GtkTreeView"><type>GtkTreeView</type></link> is not a difficult
      matter. It needs a <link linkend="GtkTreeModel"><type>GtkTreeModel</type></link> to know where to retrieve its
      data from.
    </para>
    <programlisting language="c">
GtkWidget *tree;

tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
</programlisting>
  </sect2>
  <sect2>
    <title>Columns and cell renderers</title>
    <para>
      Once the <link linkend="GtkTreeView"><type>GtkTreeView</type></link> widget has a model, it will need to know how
      to display the model. It does this with columns and cell
      renderers.
    </para>
    <para>
      Cell renderers are used to draw the data in the tree model in a
      way. There are a number of cell renderers that come with GTK,
      including the <link linkend="GtkCellRendererText"><type>GtkCellRendererText</type></link>, <link linkend="GtkCellRendererPixbuf"><type>GtkCellRendererPixbuf</type></link> and the
      <link linkend="GtkCellRendererToggle"><type>GtkCellRendererToggle</type></link>. It is relatively easy to write a custom
      renderer.
    </para>
    <para>
      A <link linkend="GtkTreeViewColumn"><type>GtkTreeViewColumn</type></link> is the object that GtkTreeView uses to
      organize the vertical columns in the tree view. It needs to know
      the name of the column to label for the user, what type of cell
      renderer to use, and which piece of data to retrieve from the
      model for a given row.
    </para>
    <programlisting language="c">
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;

renderer = gtk_cell_renderer_text_new (&lt;!-- --&gt;);
column = gtk_tree_view_column_new_with_attributes (&quot;Author&quot;,
                                                   renderer,
                                                   &quot;text&quot;, AUTHOR_COLUMN,
                                                   NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
</programlisting>
    <para>
      At this point, all the steps in creating a displayable tree have
      been covered. The model is created, data is stored in it, a tree
      view is created and columns are added to it.
    </para>
  </sect2>
  <sect2>
    <title>Selection handling</title>
    <para>
      Most applications will need to not only deal with displaying data,
      but also receiving input events from users. To do this, simply get
      a reference to a selection object and connect to the
      <link linkend="GtkTreeSelection-changed"><type>“changed”</type></link> signal.
    </para>
    <programlisting language="c">
/* Prototype for selection handler callback */
static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data);

/* Setup the selection handler */
GtkTreeSelection *select;

select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
g_signal_connect (G_OBJECT (select), &quot;changed&quot;,
                  G_CALLBACK (tree_selection_changed_cb),
                  NULL);
</programlisting>
    <para>
      Then to retrieve data for the row selected:
    </para>
    <programlisting language="c">
static void
tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
{
  GtkTreeIter iter;
  GtkTreeModel *model;
  char *author;

  if (gtk_tree_selection_get_selected (selection, &amp;model, &amp;iter))
    {
      gtk_tree_model_get (model, &amp;iter, AUTHOR_COLUMN, &amp;author, -1);

      g_print (&quot;You selected a book by <link linkend="s"><literal>s</literal></link>\n&quot;, author);

      g_free (author);
    }
}
</programlisting>
  </sect2>
  <sect2>
    <title>Simple Example</title>
    <para>
      Here is a simple example of using a <link linkend="GtkTreeView"><type>GtkTreeView</type></link> widget in context
      of the other widgets. It simply creates a simple model and view,
      and puts them together. Note that the model is never populated
      with data — that is left as an exercise for the reader. More
      information can be found on this in the <link linkend="GtkTreeModel"><type>GtkTreeModel</type></link> section.
    </para>
    <programlisting language="c">
enum
{
   TITLE_COLUMN,
   AUTHOR_COLUMN,
   CHECKED_COLUMN,
   N_COLUMNS
};

void
setup_tree (void)
{
   GtkTreeStore *store;
   GtkWidget *tree;
   GtkTreeViewColumn *column;
   GtkCellRenderer *renderer;

   /* Create a model.  We are using the store model for now, though we
    * could use any other GtkTreeModel */
   store = gtk_tree_store_new (N_COLUMNS,
                               G_TYPE_STRING,
                               G_TYPE_STRING,
                               G_TYPE_BOOLEAN);

   /* custom function to fill the model with data */
   populate_tree_model (store);

   /* Create a view */
   tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));

   /* The view now holds a reference.  We can get rid of our own
    * reference */
   g_object_unref (G_OBJECT (store));

   /* Create a cell render and arbitrarily make it red for demonstration
    * purposes */
   renderer = gtk_cell_renderer_text_new (&lt;!-- --&gt;);
   g_object_set (G_OBJECT (renderer),
                 &quot;foreground&quot;, &quot;red&quot;,
                 NULL);

   /* Create a column, associating the &quot;text&quot; attribute of the
    * cell_renderer to the first column of the model */
   column = gtk_tree_view_column_new_with_attributes (&quot;Author&quot;, renderer,
                                                      &quot;text&quot;, AUTHOR_COLUMN,
                                                      NULL);

   /* Add the column to the view. */
   gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);

   /* Second column.. title of the book. */
   renderer = gtk_cell_renderer_text_new (&lt;!-- --&gt;);
   column = gtk_tree_view_column_new_with_attributes (&quot;Title&quot;,
                                                      renderer,
                                                      &quot;text&quot;, TITLE_COLUMN,
                                                      NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);

   /* Last column.. whether a book is checked out. */
   renderer = gtk_cell_renderer_toggle_new (&lt;!-- --&gt;);
   column = gtk_tree_view_column_new_with_attributes (&quot;Checked out&quot;,
                                                      renderer,
                                                      &quot;active&quot;, CHECKED_COLUMN,
                                                      NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);

   /* Now we can manipulate the view just like any other GTK widget */
   ...
}
</programlisting>
  </sect2>
</sect1>
