Learning_GTK4_tree/demos/gtk-demo/tree_store.c

250 lines
13 KiB
C
Raw Normal View History

/*************************************************** R E M E M B E R ! *******************************************************/
/* */
/* jean@Project:~/Gem-Graph/gem-graph-client/tree (learning)/The_Gnome_way/gtk$ guix shell -m manifest.scm --check */
/* guix shell: vérification des variables d'environnement visibles depuis le shell « /gnu/store/ --- (a commit) --- /bin/bash »… */
/* guix shell: Tout va bien ! Le shell a les bonnes variables d'environnement. */
/* jean@Project:~/Gem-Graph/gem-graph-client/tree (learning)/The_Gnome_way/gtk [env] $ cd builddir/ */
/* jean@Project:~/Gem-Graph/gem-graph-client/tree...way/gtk/builddir [env] $ clear && meson compile && demos/gtk-demo/gtk4-demo */
/* */
/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- A Session -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
/* */
/* jean@Project:~/Gem-Graph/gem-graph-client/tree (learning)/The_Gnome_way/gtk/builddir [env] $ ctrl D (avant de fermer builder) */
/* */
/****************************************************************************************************************************************/
/************************************************** W I D G E T S ********************************************************/
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
/* _ _ _ _ _ _ _ _ _ _ _ _ _ E D I T A B L E _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
/* */
/* https://developer-old.gnome.org/gtk4/stable/ch03s02.html Which widget should I use ?... */
/* https://developer-old.gnome.org/gtk4/stable/GtkCellEditable.html#GtkCellEditable-struct */
/* The GtkCellEditable interface must be implemented for widgets to be usable to edit the contents of a GtkTreeView cell. */
/* It provides a way to specify how temporary widgets should be configured for editing, get the new value, etc. */
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ T R E E _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
2024-01-01 23:39:56 +01:00
/* https://toshiocp.github.io/Gtk4-tutorial/sec29.html <<< TODO */
/* https://docs.gtk.org/gtk4/ */
/* https://docs.gtk.org/gtk4/section-list-widget.html << (see below the "quick comparison chart of equivalent functionalities") */
/* https://docs.gtk.org/gtk4/class.TreeListModel.html */
/* */
/* */
/* https://developer-old.gnome.org/gtk4/stable/GtkTreeView.html */
/* https://en.wikibooks.org/wiki/GTK%2B_By_Example/Tree_View/Custom_Models */
/* https://developer-old.gnome.org/gtk4/stable/GtkTreeSelection.html#GtkTreeSelection-struct */
/* https://developer-old.gnome.org/gtk4/stable/GtkTreeView.html#gtk-tree-view-get-path-at-pos << get-path-at-pos */
/* Finds the path at the point (x , y ), relative to bin_window coordinates. Use gtk_tree_view_convert_widget_to_bin_window_coords(). */
/* https://www.gnu.org/software/guile-gnome/docs/gtk/html/GtkCellRenderer.html */
/* GtkTreeSelection, GtkTreeView drag-and-drop, GtkTreeSortable, GtkTreeModelSort, GtkCellEditable, GtkCellRendererText,... */
/* gtk_tree_view_get_search_entry (treeview) https://blog.gtk.org/2020/09/08/on-list-models/ */
/* */
/****************************************************************************************************************************************/
2024-01-01 23:39:56 +01:00
// ? utile ?
// gtk_tree_model_foreach (model, TRUE, my_user_data); https://developer-old.gnome.org/gtk4/stable/GtkTreeModel.html#GtkTreeModelForeachFunc
2023-12-12 11:36:42 +01:00
/* ... Finally heres a quick comparison chart of equivalent functionalitqy
to look for when transitioning code:
Old New
..................................................................
GtkTreeModel GListModel
GtkTreePath guint position, GtkTreeListRow
GtkTreeIter guint position
GtkTreeRowReference GObject item
GtkListStore GListStore
GtkTreeStore GtkTreeListModel, GtkTreeExpander
GtkTreeSelection GtkSelectionModel
GtkTreeViewColumn GtkColumnView
GtkTreeView GtkListView, GtkColumnView
GtkCellView GtkListItem
GtkComboBox GtkDropDown
GtkIconView GtkGridView
GtkTreeSortable GtkColumnView
GtkTreeModelSort GtkSortListModel
GtkTreeModelFilter GtkFilterListModel
GtkCellLayout GtkListItemFactory
GtkCellArea GtkWidget
GtkCellRenderer GtkWidget
..............................................................................*/
/*..............................................................................
*
* >>> GtkStringList <<<
*
* GtkStringList is a list model that wraps an array of strings.
* The objects in the model are of type GtkStringObject
* and have a string property that can be used inside expressions.
* Use it where/when you would typically use a char*[], but need a list model.
*
* implements GtkBuildable interface
* <item> are GObject instances; support translatable, context and comments
*
* <object class="GtkStringList">
* <items>
* <item translatable="yes">Factory</item>
* <item translatable="yes">Home</item>
* <item translatable="yes">Subway</item>
* </items>
* </object>
*
* Every item in a model has a position (= unsigned integer)
* "factories" takes care of mapping the items of the model
* to widgets that can be shown in the view
* by creating a listitem for each item that is currently in use.
* List items are always GtkListItem instances. Widgets can be recycled.
*
* GtkStringList can only handle strings. It is backed by a dynamically allocated array.
* GListStore is backed by a balanced tree.
*
* GTK provides functionality to make lists look and behave like trees
* by using the GtkTreeListModel and the GtkTreeExpander widget.
*
* Widgets are styleable using GTK CSS. Use the .rich-list style class.
*
2024-01-01 23:39:56 +01:00
*
* GListModel is an interface that represents a mutable list of GObjects.
* https://gnome.pages.gitlab.gnome.org/libsoup/gio/GListModel.html
*
*............................................................................*/
2023-12-12 11:36:42 +01:00
#include <gtk/gtk.h>
#include <stdio.h>
#include "config.h"
#include "custom-list.h"
2024-01-01 23:39:56 +01:00
#include <gio/gio.h>
2023-12-12 11:36:42 +01:00
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
enum
{
STRING_COLUMN,
NUM_COLUMNS
};
2023-12-12 11:36:42 +01:00
/* TreeItem structure */
typedef struct _TreeItem TreeItem;
struct _TreeItem
{
const char *label;
TreeItem *children;
};
/* tree data */
2023-12-18 18:48:14 +01:00
static TreeItem E[] = {NULL}, F[] = {NULL}, G[] = {NULL}, H[] = {NULL};
static TreeItem I[] = {NULL}, K[] = {NULL}, N[] = {NULL}, M[] = {NULL};
static TreeItem L[] = {{"M", M}, {"N", N}, {NULL }}, J[] = {{"L", L}, {NULL}};
static TreeItem D[] = {{"I", I}, {"J", J}, {"K", K}, {NULL}};
static TreeItem C[] = {{"F", F}, {"G", G}, {"H", H}, {NULL}};
static TreeItem A[] = {{"D", D}, {NULL}}, B[] = {{"E", E}, {NULL}};
static TreeItem R[] = {{"A", A}, {"B", B}, {"C", C}, {NULL}};
static TreeItem O[] = {{"ROOT", R}, {NULL}}; // Artefact added for symmetry
2023-12-12 11:36:42 +01:00
static GListModel *create_node_recursive (GtkTreeStore *model,
TreeItem *current_item,
GtkTreeIter *iter_parent,
int depth)
{
GtkTreeIter iter;
if (model == NULL)
model = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING);
while (current_item->label) {
if (0) printf("[%d] Current label : %s\n", depth, current_item->label);
gtk_tree_store_append (model, &iter, iter_parent);
gtk_tree_store_set (model, &iter, STRING_COLUMN, current_item->label, -1);
if (current_item->children)
create_node_recursive (model, current_item->children, &iter, depth + 1);
else
break;
current_item++;
}
if (depth == 0)
return G_LIST_MODEL(model); // cast from GtkTreeModel to GListModel or GtkTreeStore
else
return NULL;
}
2023-12-12 11:36:42 +01:00
GtkWidget *
do_tree_store (GtkWidget *do_widget)
{
static GtkWidget *my_window = NULL;
2023-12-12 11:36:42 +01:00
if (! my_window)
2023-12-12 11:36:42 +01:00
{
GtkWidget *my_tree_box;
GtkWidget *my_scrolled_window;
GtkWidget *my_tree_view;
GListModel *my_list_model = NULL;
2023-12-12 11:36:42 +01:00
/* create window, etc */
my_window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (my_window), "Tree Store");
g_object_add_weak_pointer (G_OBJECT (my_window), (gpointer *)&my_window);
2023-12-12 11:36:42 +01:00
my_tree_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_widget_set_margin_start (my_tree_box, 8);
gtk_widget_set_margin_end (my_tree_box, 8);
gtk_widget_set_margin_top (my_tree_box, 8);
gtk_widget_set_margin_bottom (my_tree_box, 8);
gtk_window_set_child (GTK_WINDOW (my_window), my_tree_box);
2023-12-12 11:36:42 +01:00
gtk_box_append (GTK_BOX (my_tree_box), gtk_label_new ("Learning GTK trees"));
2023-12-12 11:36:42 +01:00
my_scrolled_window = gtk_scrolled_window_new ();
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (my_scrolled_window), TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (my_scrolled_window),
2023-12-12 11:36:42 +01:00
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_box_append (GTK_BOX (my_tree_box), my_scrolled_window);
2023-12-12 11:36:42 +01:00
/* create tree_model */
my_list_model = create_node_recursive (my_list_model, O, NULL, 0);
2023-12-12 11:36:42 +01:00
/* create tree view */
my_tree_view = gtk_tree_view_new_with_model (my_list_model);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (my_tree_view), FALSE);
gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (my_tree_view), TRUE);
gtk_widget_set_vexpand (my_tree_view, TRUE);
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (my_tree_view)),
2023-12-12 11:36:42 +01:00
GTK_SELECTION_MULTIPLE);
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (my_tree_view), TRUE);
g_object_unref (my_list_model);
2023-12-12 11:36:42 +01:00
GtkCellRenderer *renderer;
renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "xalign", 0.0, NULL);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (my_tree_view), -1,
"Col 0", renderer, "text", STRING_COLUMN, NULL);
2023-12-12 11:36:42 +01:00
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (my_scrolled_window), my_tree_view);
2023-12-12 11:36:42 +01:00
/* expand all rows after the my_tree_view widget has been realized */
g_signal_connect (my_tree_view, "realize",
2023-12-12 11:36:42 +01:00
G_CALLBACK (gtk_tree_view_expand_all), NULL);
gtk_window_set_default_size (GTK_WINDOW (my_window), 200, 400);
2023-12-12 11:36:42 +01:00
}
if (!gtk_widget_get_visible (my_window))
gtk_widget_set_visible (my_window, TRUE);
2023-12-12 11:36:42 +01:00
else
gtk_window_destroy (GTK_WINDOW (my_window));
return my_window;
2023-12-12 11:36:42 +01:00
}
2024-01-01 23:39:56 +01:00