[gtk/docs-gtk-org] gtk3: Add the GtkTreeView overview section



commit 66d18687785992596c94c0f6bfee27de470c979b
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Aug 18 18:13:02 2021 +0100

    gtk3: Add the GtkTreeView overview section

 gtk3/gtk/gtk3.toml.in            |   1 +
 gtk3/gtk/meson.build             |   1 +
 gtk3/gtk/tree-widget-overview.md | 289 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 291 insertions(+)
---
diff --git a/gtk3/gtk/gtk3.toml.in b/gtk3/gtk/gtk3.toml.in
index 69bc8d98d6..13024c638f 100644
--- a/gtk3/gtk/gtk3.toml.in
+++ b/gtk3/gtk/gtk3.toml.in
@@ -46,6 +46,7 @@ content_files = [
   "input-handling.md",
   "key-bindings.md",
   "text-widget-overview.md",
+  "tree-widget-overview.md",
   "treeview-tutorial.md",
 
   "x11.md",
diff --git a/gtk3/gtk/meson.build b/gtk3/gtk/meson.build
index 2be5d83edb..7dbf4365b6 100644
--- a/gtk3/gtk/meson.build
+++ b/gtk3/gtk/meson.build
@@ -11,6 +11,7 @@ expand_content_files = [
   'migrating-themes.md',
   'running.md',
   'text-widget-overview.md',
+  'tree-widget-overview.md',
   'treeview-tutorial.md',
   'wayland.md',
   'windows.md',
diff --git a/gtk3/gtk/tree-widget-overview.md b/gtk3/gtk/tree-widget-overview.md
new file mode 100644
index 0000000000..ca8da064b3
--- /dev/null
+++ b/gtk3/gtk/tree-widget-overview.md
@@ -0,0 +1,289 @@
+Title: Tree and List Widget Overview
+
+An overview of GtkTreeModel, GtkTreeView, and friends
+       
+## Overview
+
+To create a tree or list in GTK, use the `GtkTreeModel` interface in
+conjunction with the `GtkTreeView` widget. This widget is designed around a
+[Model/View/Controller
+design](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)
+and consists of four major parts:
+
+- The tree view widget ([class@Gtk.TreeView])
+- The view column ([class@Gtk.TreeViewColumn])
+- The cell renderers ([class@Gtk.CellRenderer] and its derived classes)
+- The model interface ([iface@Gtk.TreeModel] and its implementations)
+
+The View is composed of the first three objects, while the last is the
+Model. 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.
+
+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 "True" or "False", "On" or "Off", or should it be rendered as a checkbox?
+
+## Creating a model
+
+GTK provides two simple models that can be used: the [class@Gtk.ListStore]
+and the [class@Gtk.TreeStore]. `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 simple:
+
+```c
+GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+```
+
+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.
+
+```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?         */
+```
+
+Adding data to the model is done using [method Gtk TreeStore set] or
+[method Gtk ListStore set], depending upon which sort of model was created.
+To do this, a [struct@Gtk.TreeIter] must be acquired. The iterator points to
+the location where data will be added.
+
+Once an iterator has been acquired, [method Gtk TreeStore set] is used to
+apply data to the part of the model that the iterator points to. Consider
+the following example:
+
+```c
+GtkTreeIter iter;
+
+gtk_tree_store_append (store, &iter, NULL);  /* Acquire an iterator */
+
+gtk_tree_store_set (store, &iter,
+                    TITLE_COLUMN, "The Principle of Reason",
+                    AUTHOR_COLUMN, "Martin Heidegger",
+                    CHECKED_COLUMN, FALSE,
+                    -1);
+```
+
+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.
+
+The third argument to [`method@Gtk.TreeStore.append`] 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:
+
+```c
+GtkTreeIter iter1;  /* Parent iter */
+GtkTreeIter iter2;  /* Child iter  */
+
+gtk_tree_store_append (store, &iter1, NULL);  /* Acquire a top-level iterator */
+gtk_tree_store_set (store, &iter1,
+                    TITLE_COLUMN, "The Art of Computer Programming",
+                    AUTHOR_COLUMN, "Donald E. Knuth",
+                    CHECKED_COLUMN, FALSE,
+                    -1);
+
+gtk_tree_store_append (store, &iter2, &iter1);  /* Acquire a child iterator */
+gtk_tree_store_set (store, &iter2,
+                    TITLE_COLUMN, "Volume 1: Fundamental Algorithms",
+                    -1);
+
+gtk_tree_store_append (store, &iter2, &iter1);
+gtk_tree_store_set (store, &iter2,
+                    TITLE_COLUMN, "Volume 2: Seminumerical Algorithms",
+                    -1);
+
+gtk_tree_store_append (store, &iter2, &iter1);
+gtk_tree_store_set (store, &iter2,
+                    TITLE_COLUMN, "Volume 3: Sorting and Searching",
+                    -1);
+```
+
+## Creating the view component
+
+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 `GtkTreeView` is not a difficult matter. It needs a `GtkTreeModel`
+to know where to retrieve its data from.
+
+```c
+GtkWidget *tree;
+
+tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+```
+
+### Columns and cell renderers
+
+Once the `GtkTreeView` widget has a model, it will need to know how to
+display the model. It does this with columns and cell renderers.
+
+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
+[class@Gtk.CellRendererText], [class@Gtk.CellRendererPixbuf] and the
+[class@Gtk.CellRendererToggle]. It is relatively easy to write a custom
+renderer.
+
+A [class@Gtk.TreeViewColumn] 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.
+
+```c
+GtkCellRenderer *renderer;
+GtkTreeViewColumn *column;
+
+renderer = gtk_cell_renderer_text_new ();
+column = gtk_tree_view_column_new_with_attributes ("Author",
+                                                   renderer,
+                                                   "text", AUTHOR_COLUMN,
+                                                   NULL);
+gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
+```
+
+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.
+
+### Selection handling
+
+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 [signal@Gtk.TreeSelection::changed]
+signal.
+
+```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), "changed",
+                  G_CALLBACK (tree_selection_changed_cb),
+                  NULL);
+```
+
+Then to retrieve data for the row selected:
+
+```c
+static void
+tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
+{
+  GtkTreeIter iter;
+  GtkTreeModel *model;
+  gchar *author;
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+    {
+      gtk_tree_model_get (model, &iter, AUTHOR_COLUMN, &author, -1);
+
+      g_print ("You selected a book by %s\n", author);
+
+      g_free (author);
+    }
+}
+```
+
+## Simple Example
+
+Here is a simple example of using a `GtkTreeView` 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
+`GtkTreeModel` section.
+
+```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 ();
+  g_object_set (G_OBJECT (renderer),
+                "foreground", "red",
+                NULL);
+
+  /* Create a column, associating the "text" attribute of the
+   * cell_renderer to the first column of the model
+   */
+  column = gtk_tree_view_column_new_with_attributes ("Author", renderer,
+                                                     "text", 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 ();
+  column = gtk_tree_view_column_new_with_attributes ("Title",
+                                                     renderer,
+                                                     "text", 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 ();
+  column = gtk_tree_view_column_new_with_attributes ("Checked out",
+                                                     renderer,
+                                                     "active", 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... */
+}
+```


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]