/* * Gem-graph OpenGL experiments * * Desc: User interface functions * * Copyright (C) 2023 Jean Sirmai * * This file is part of Gem-graph. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ /*----------------------------------------------------------------------------*/ /**************** 2024-01-06 À la chasse aux widgets ! ****************/ /* */ /* (1) Je recopie les fragments de code qui me semblent utiles */ /* tirés de demos/gtk-demo/main.c et de la liste suivante */ /*----------------------------------------------------------------------------*/ // https://www.gtk.org/ /******************************************************************************/ /* */ /* W I N D O W = D O _ S O M E _ A P P L I C A T I O N _ E X A M P L E */ /* */ // window = do_tree_store(NULL); // window = do_listview_words(NULL); // window = do_editable_cells(NULL); // window = do_dnd(NULL); // drag and drop // window = do_drawingarea(NULL); // window = do_entry_undo(NULL); // window = do_expander(NULL); // window = do_textundo(NULL); // window = do_search_entry2(NULL); // window = do_scale(NULL); // scale entries from bars // window = do_font_features(NULL); // window = do_hypertext(NULL); // window = do_iconview_edit(NULL); // drag and drop // window = do_image_scaling(NULL); // window = do_infobar(NULL); // window = do_links(NULL); // window = do_listbox_controls(NULL); // window = do_list_store(NULL); // window = do_listview_colors(NULL); // window = do_listview_selections(NULL); // window = do_mask(NULL); /* */ /******************************************************************************/ /* Old links ( deprec ? ) (To check before removing). https://blog.gtk.org/2020/06/08/more-on-lists-in-gtk-4/ https://docs.gtk.org/gtk4/section-list-widget.html https://en.wikibooks.org/wiki/GTK%2B_By_Example/Tree_View/Tree_Models https://stackoverflow.com/questions/74556059/how-to-build-a-tree-in-gtk4-4-10 https://en.wikibooks.org/wiki/GTK%2B_By_Example/Tree_View/Columns_and_Renderer */ /******************************************** The basic ideas behind list views: ************************************************/ /* */ /* The data for items is provided in the form of a model (containing objects) */ /* Widgets are created just for the viewable range of items */ /* Widgets can be recycled by binding them to different items */ /* Avoid iterating over all items in the model as much as possible, */ /* and just deal with the items in the visible range which are bound to widgets */ /* from https://blog.gtk.org/2020/06/07/scalable-lists-in-gtk-4/ */ /* */ /****************************************************************************************************************************************/ // GtkListItemFactory is the object that is tasked with creating widgets for the items in the model. // One implementations of this factory, GtkBuilderListItemFactory, is using ui files as templates for the list item widgets. // https://gitlab.gnome.org/GNOME/gtk/-/blob/main/demos/gtk-demo/listview_settings.ui /* Lists/Application launcher #Keywords: GtkListItemFactory, GListModel * This demo uses the GtkListView widget as a fancy application launcher. It is also a very small introduction to listviews. * https://gitlab.gnome.org/GNOME/gtk/-/blob/main/demos/gtk-demo/listview_applauncher.c */ /************************************************** 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 _ _ _ _ _ _ _ _ _ _ _ _ _ _ */ /* */ /* 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/ */ /* */ /****************************************************************************************************************************************/ // ? utile ? // gtk_tree_model_foreach (model, TRUE, my_user_data); https://developer-old.gnome.org/gtk4/stable/GtkTreeModel.html#GtkTreeModelForeachFunc /* ... Finally here’s 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 * are GObject instances; support “translatable”, “context” and “comments” * * * * Factory * Home * Subway * * * * 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. * * * GListModel is an interface that represents a mutable list of GObjects. * https://gnome.pages.gitlab.gnome.org/libsoup/gio/GListModel.html * https://docs.gtk.org/gio/iface.ListModel.html < +++ * https://blog.gtk.org/2020/09/08/on-list-models/ * *............................................................................*/ #include #include #include #include "../../include/base.h" #include "../../include/ui.h" #include #include //#include "config.h" //#include "custom-list.h" #include G_GNUC_BEGIN_IGNORE_DEPRECATIONS enum { STRING_COLUMN, NUM_COLUMNS }; /* TreeItem structure */ typedef struct _TreeItem TreeItem; struct _TreeItem { const char *label; TreeItem *children; }; // tree data 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 // TODO GtkTreeListModel ? GtkTreeModel ? (lines 238 & 270) static GListStore *create_node_recursive (GListStore *model, // GListStore* g_list_store_new (GType item_type) 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) { 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_STORE(model); // Should we cast to GtkTreeStore ? else return NULL; } GtkWidget *create_my_list_model(GtkBox *runlib_objects) { GtkWidget *my_tree_box; GtkWidget *my_scrolled_window; GListStore *my_list_model = NULL; GtkWidget *my_tree_view = NULL; GtkCellRenderer *renderer; my_list_model = create_node_recursive (my_list_model, O, NULL, 0); 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)), GTK_SELECTION_MULTIPLE); gtk_tree_view_set_reorderable (GTK_TREE_VIEW (my_tree_view), TRUE); g_object_unref (my_list_model); 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); 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), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_append (runlib_objects, my_scrolled_window); gtk_widget_show(my_tree_box); gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (my_scrolled_window), my_tree_view); /* expand all rows after the my_tree_view widget has been realized */ g_signal_connect (my_tree_view, "realize", G_CALLBACK (gtk_tree_view_expand_all), NULL); return my_tree_view; } static void print_hello (GtkWidget *widget, gpointer data) { static int nb; nb++; printf("From 'tree.c', > button clicked (n = %d)\n", nb); } GtkWidget *create_a_button(GtkBox *runlib_objects) { GtkWidget *button; const char *text = "Hello ! I'm the new button. Click me !"; button = gtk_button_new_with_label(text); gtk_box_append(runlib_objects, button); gtk_widget_show(button); g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL); printf("------------------------------------------ tree.c line 327\n\ The speed makefile bug has been fixed in branch [devel]\n\ NB Here, we are in branch [origin/dev/ui-simple-tree]\n\ TODO : 01/GTK4/tree (learning)/The_Gnome_way/demos/gtk-demo\n"); return button; }