[gtk/doc-chapters-markdown: 4/8] docs: Convert treeview and textview overview to markdown



commit 8898618ecb75d88b79947484be6aaed3a3566a15
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun May 24 11:42:52 2020 -0400

    docs: Convert treeview and textview overview to markdown

 docs/reference/gtk/gtk4-docs.xml          |   4 +-
 docs/reference/gtk/meson.build            |  10 +-
 docs/reference/gtk/section-text-widget.md | 157 +++++++++++++++
 docs/reference/gtk/section-tree-widget.md | 282 ++++++++++++++++++++++++++
 docs/reference/gtk/text_widget.xml        | 215 --------------------
 docs/reference/gtk/tree_widget.xml        | 321 ------------------------------
 6 files changed, 445 insertions(+), 544 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-docs.xml b/docs/reference/gtk/gtk4-docs.xml
index 9e12315a03..6629c184ec 100644
--- a/docs/reference/gtk/gtk4-docs.xml
+++ b/docs/reference/gtk/gtk4-docs.xml
@@ -178,7 +178,7 @@
 
     <chapter id="TextWidgetObjects">
       <title>Multiline Text Editor</title>
-      <xi:include href="xml/text_widget.xml" />
+      <xi:include href="section-text-widget.xml" />
       <xi:include href="xml/gtktextiter.xml" />
       <xi:include href="xml/gtktextmark.xml" />
       <xi:include href="xml/gtktextbuffer.xml" />
@@ -189,7 +189,7 @@
 
     <chapter id="TreeWidgetObjects">
       <title>Tree, List and Icon Grid Widgets</title>
-      <xi:include href="xml/tree_widget.xml" />
+      <xi:include href="section-tree-widget.xml" />
       <xi:include href="xml/gtktreemodel.xml" />
       <xi:include href="xml/gtktreeselection.xml" />
       <xi:include href="xml/gtktreeviewcolumn.xml" />
diff --git a/docs/reference/gtk/meson.build b/docs/reference/gtk/meson.build
index cdeaeec609..e96c7b6fee 100644
--- a/docs/reference/gtk/meson.build
+++ b/docs/reference/gtk/meson.build
@@ -352,15 +352,11 @@ content_files = [
   'gtk4-widget-factory.xml',
   'overview.xml',
   'question_index.xml',
-  'text_widget.xml',
-  'tree_widget.xml',
   'visual_index.xml',
 ]
 
 expand_content_files = [
   'question_index.xml',
-  'text_widget.xml',
-  'tree_widget.xml',
 ]
 
 expand_content_md_files = [
@@ -368,7 +364,7 @@ expand_content_md_files = [
   'osx.md',
   'wayland.md',
   'windows.md',
-: 'x11.md',
+  'x11.md',
   'getting_started.md',
   'resources.md',
   'building.md',
@@ -380,7 +376,9 @@ expand_content_md_files = [
   'input-handling.md',
   'drawing-model.md',
   'css-overview.md',
-  'css-properties.md'
+  'css-properties.md',
+  'section-text-widget.md',
+  'section-tree-widget.md',
 ]
 
 types_conf = configuration_data()
diff --git a/docs/reference/gtk/section-text-widget.md b/docs/reference/gtk/section-text-widget.md
new file mode 100644
index 0000000000..4184b88878
--- /dev/null
+++ b/docs/reference/gtk/section-text-widget.md
@@ -0,0 +1,157 @@
+# Text Widget Overview {#TextWidget}
+
+GTK has an extremely powerful framework for multiline text editing.  The
+primary objects involved in the process are #GtkTextBuffer, which represents the 
+text being edited, and #GtkTextView, a widget which can display a #GtkTextBuffer. 
+Each buffer can be displayed by any number of views.
+
+One of the important things to remember about text in GTK is that it's in
+the UTF-8 encoding. This means that one character can be encoded as multiple
+bytes. Character counts are usually referred to as _offsets_, while byte
+counts are called _indexes_. If you confuse these two, things will work fine
+with ASCII, but as soon as your buffer contains multibyte characters, bad 
+things will happen.
+
+Text in a buffer can be marked with _tags_. A tag is an attribute that can
+be applied to some range of text. For example, a tag might be called "bold"
+and make the text inside the tag bold. However, the tag concept is more
+general than that; tags don't have to affect appearance. They can instead
+affect the behavior of mouse and key presses, "lock" a range of text so the
+user can't edit it, or countless other things. A tag is represented by a
+#GtkTextTag object. One #GtkTextTag can be applied to any number of text
+ranges in any number of buffers.
+
+Each tag is stored in a #GtkTextTagTable. A tag table defines a set of
+tags that can be used together. Each buffer has one tag table associated with
+it; only tags from that tag table can be used with the buffer. A single tag
+table can be shared between multiple buffers, however.
+
+Tags can have names, which is convenient sometimes (for example, you can name
+your tag that makes things bold "bold"), but they can also be anonymous (which
+is convenient if you're creating tags on-the-fly).
+
+Most text manipulation is accomplished with _iterators_, represented by a
+#GtkTextIter. An iterator represents a position between two characters in
+the text buffer. #GtkTextIter is a struct designed to be allocated on the
+stack; it's guaranteed to be copiable by value and never contain any
+heap-allocated data. Iterators are not valid indefinitely; whenever the
+buffer is modified in a way that affects the number of characters in the
+buffer, all outstanding iterators become invalid. (Note that deleting 5
+characters and then reinserting 5 still invalidates iterators, though you 
+end up with the same number of characters you pass through a state with a 
+different number).
+
+Because of this, iterators can't be used to preserve positions across buffer
+modifications. To preserve a position, the #GtkTextMark object is ideal. You
+can think of a mark as an invisible cursor or insertion point; it floats in 
+the buffer, saving a position. If the text surrounding the mark is deleted, 
+the mark remains in the position the text once occupied; if text is inserted 
+at the mark, the mark ends up either to the left or to the right of the new 
+text, depending on its _gravity_. The standard text cursor in left-to-right
+languages is a mark with right gravity, because it stays to the right of
+inserted text.
+
+Like tags, marks can be either named or anonymous. There are two marks
+built-in to #GtkTextBuffer; these are named "insert" and "selection_bound"
+and refer to the insertion point and the boundary of the selection which
+is not the insertion point, respectively. If no text is selected, these
+two marks will be in the same position. You can manipulate what is selected
+and where the cursor appears by moving these marks around.
+
+If you want to place the cursor in response to a user action, be sure to use
+gtk_text_buffer_place_cursor(), which moves both at once without causing a 
+temporary selection (moving one then the other temporarily selects the range in 
+between the old and new positions).
+
+Text buffers always contain at least one line, but may be empty (that
+is, buffers can contain zero characters). The last line in the text
+buffer never ends in a line separator (such as newline); the other
+lines in the buffer always end in a line separator. Line separators
+count as characters when computing character counts and character
+offsets. Note that some Unicode line separators are represented with 
+multiple bytes in UTF-8, and the two-character sequence "\r\n" is also
+considered a line separator.
+
+Text buffers support undo and redo if gtk_text_buffer_set_enable_undo()
+has been set to %TRUE. Use gtk_text_buffer_undo() or gtk_text_buffer_redo()
+to perform the necessary action. Note that these operations are ignored if
+the buffer is not editable. Developers may want some operations to not be
+undoable. To do this, wrap your changes in
+gtk_text_buffer_begin_irreversible_action() and
+gtk_text_buffer_end_irreversible_action().
+
+## Simple Example
+
+The simplest usage of #GtkTextView  might look like this:
+
+``` {.c}
+GtkWidget *view;
+GtkTextBuffer *buffer;
+
+view = gtk_text_view_new ();
+
+buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+gtk_text_buffer_set_text (buffer, "Hello, this is some text", -1);
+
+/* Now you might put the view in a container and display it on the
+ * screen; when the user edits the text, signals on the buffer
+ * will be emitted, such as "changed", "insert_text", and so on.
+ */
+```
+
+In many cases it's also convenient to first create the buffer with 
+gtk_text_buffer_new(), then create a widget for that buffer with 
+gtk_text_view_new_with_buffer(). Or you can change the buffer the widget 
+displays after the widget is created with gtk_text_view_set_buffer().
+
+## Example of Changing Text Attributes
+
+The way to affect text attributes in #GtkTextView is to
+apply tags that change the attributes for a region of text.
+For text features that come from the theme &mdash; such as font and
+foreground color -- use CSS to override their default values.
+
+```
+GtkWidget *view;
+GtkTextBuffer *buffer;
+GtkTextIter start, end;
+PangoFontDescription *font_desc;
+GdkRGBA rgba;
+GtkTextTag *tag;
+GtkCssProvider *provider;
+GtkStyleContext *context;
+
+view = gtk_text_view_new ();
+
+buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+gtk_text_buffer_set_text (buffer, "Hello, this is some text", -1);
+
+/* Change default font and color throughout the widget */
+provider = gtk_css_provider_new ();
+gtk_css_provider_load_from_data (provider,
+                                 "textview {"
+                                 " font: 15 serif;"
+                                 "  color: green;"
+                                 "}",
+                                 -1);
+context = gtk_widget_get_style_context (view);
+gtk_style_context_add_provider (context,
+                                GTK_STYLE_PROVIDER (provider),
+                                GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+/* Change left margin throughout the widget */
+gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 30);
+
+/* Use a tag to change the color for just one part of the widget */
+tag = gtk_text_buffer_create_tag (buffer, "blue_foreground",
+                                  "foreground", "blue",
+                                  NULL);  
+gtk_text_buffer_get_iter_at_offset (buffer, &amp;start, 7);
+gtk_text_buffer_get_iter_at_offset (buffer, &amp;end, 12);
+gtk_text_buffer_apply_tag (buffer, tag, &amp;start, &amp;end);
+```
+
+The `gtk4-demo` application that comes with
+GTK contains more example code for #GtkTextView.
diff --git a/docs/reference/gtk/section-tree-widget.md b/docs/reference/gtk/section-tree-widget.md
new file mode 100644
index 0000000000..b51cd3fb7a
--- /dev/null
+++ b/docs/reference/gtk/section-tree-widget.md
@@ -0,0 +1,282 @@
+# Tree and List Widget Overview {#TreeWidget}
+
+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 and consists of four major parts:
+
+- The tree view widget (GtkTreeView)
+- The view column (GtkTreeViewColumn)
+- The cell renderers (GtkCellRenderer etc.)
+- The model interface (GtkTreeModel)
+
+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 #GtkListStore
+and the #GtkTreeStore. 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
+
+``` {.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 gtk_tree_store_set() or
+gtk_list_store_set(), depending upon which sort of model was
+created. To do this, a #GtkTreeIter must be acquired. The iterator
+points to the location where data will be added.
+
+Once an iterator has been acquired, gtk_tree_store_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 gtk_tree_store_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));
+```
+
+## Colums 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 #GtkCellRendererText, #GtkCellRendererPixbuf and
+the #GtkCellRendererToggle. It is relatively easy to write a
+custom renderer.
+
+A #GtkTreeViewColumn 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
+#GtkTreeSelection::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 &mdash; 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]