[gtk/wip/otte/listview: 23/24] demo: Add a listview sections demo
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview: 23/24] demo: Add a listview sections demo
- Date: Sat, 26 Feb 2022 06:34:09 +0000 (UTC)
commit 00ffa349792feb4fe8620397d29be581184b793e
Author: Benjamin Otte <otte redhat com>
Date: Mon Feb 21 06:54:51 2022 +0100
demo: Add a listview sections demo
Just display the list of objects from GTK, and order them in some
made-up categories.
demos/gtk-demo/demo.gresource.xml | 1 +
demos/gtk-demo/listview_objects.c | 220 ++++++++++++++++++++++++++++++++++++++
demos/gtk-demo/meson.build | 9 +-
3 files changed, 226 insertions(+), 4 deletions(-)
---
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index f1caed2b8d..5cb524328f 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -305,6 +305,7 @@
<file>listview_clocks.c</file>
<file>listview_filebrowser.c</file>
<file>listview_minesweeper.c</file>
+ <file>listview_objects.c</file>
<file>listview_settings.c</file>
<file>listview_ucd.c</file>
<file>listview_weather.c</file>
diff --git a/demos/gtk-demo/listview_objects.c b/demos/gtk-demo/listview_objects.c
new file mode 100644
index 0000000000..57401a1ae1
--- /dev/null
+++ b/demos/gtk-demo/listview_objects.c
@@ -0,0 +1,220 @@
+/* Lists/Objects in GTK
+ * #Keywords: GtkListItemFactory, GtkSortListModel, GtkStringList
+ *
+ * This demo uses the GtkListView widget to show all the objects in GTK
+ * grouped by their type.
+ *
+ * It shows how to use sections in GtkListView
+ */
+
+#include <gtk/gtk.h>
+
+/* This is the function that creates the GListModel that we need.
+ */
+static GListModel *
+create_object_list (void)
+{
+ GtkStringList *strings;
+ const GType *types;
+ guint i, n;
+
+ /* We use a GtkStringList here, because it requires the smallest amount of
+ * code, not because it's a great fit.
+ */
+ strings = gtk_string_list_new (NULL);
+
+ /* This function is meant for testing, but we use it here to get some data
+ * to operate on
+ */
+ gtk_test_register_all_types ();
+ types = gtk_test_list_all_types (&n);
+
+ for (i = 0; i < n; i++)
+ {
+ /* Add all the names of the object types in GTK */
+ if (g_type_is_a (types[i], G_TYPE_OBJECT))
+ gtk_string_list_append (strings, g_type_name (types[i]));
+ }
+
+ return G_LIST_MODEL (strings);
+}
+
+/* Make a function that returns a section name for all our types.
+ * Do this by adding a few type checks and returning a made up
+ * section name for it.
+ */
+static char *
+get_section (GtkStringObject *object)
+{
+ GType type;
+
+ type = g_type_from_name (gtk_string_object_get_string (object));
+
+ if (g_type_is_a (type, GTK_TYPE_WIDGET))
+ return g_strdup ("Widget");
+ else if (g_type_is_a (type, GTK_TYPE_FILTER))
+ return g_strdup ("Filter");
+ else if (g_type_is_a (type, GTK_TYPE_SORTER))
+ return g_strdup ("Sorter");
+ else if (g_type_is_a (type, G_TYPE_LIST_MODEL))
+ return g_strdup ("ListModel");
+ else
+ return g_strdup ("Zzz..."); /* boring stuff, cleverly sorted at the end */
+}
+
+/* These functions set up the object names
+ */
+static void
+setup_section_listitem_cb (GtkListItemFactory *factory,
+ GtkListItem *list_item)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new ("");
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_widget_add_css_class (label, "heading");
+ gtk_widget_set_margin_top (label, 4);
+ gtk_widget_set_margin_bottom (label, 4);
+ gtk_list_item_set_child (list_item, label);
+}
+
+/* Here we need to prepare the listitem for displaying its item. We get the
+ * listitem already set up from the previous function, so we can reuse the
+ * GtkImage widget we set up above.
+ * We get the item - which we know is a GAppInfo because it comes out of
+ * the model we set up above, grab its icon and display it.
+ */
+static void
+bind_section_listitem_cb (GtkListItemFactory *factory,
+ GtkListItem *list_item)
+{
+ GtkWidget *label;
+ GtkStringObject *item;
+ char *text;
+
+ label = gtk_list_item_get_child (list_item);
+ item = gtk_list_item_get_item (list_item);
+
+ text = get_section (item);
+ gtk_label_set_label (GTK_LABEL (label), text);
+ g_free (text);
+}
+
+static void
+setup_listitem_cb (GtkListItemFactory *factory,
+ GtkListItem *list_item)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new ("");
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_list_item_set_child (list_item, label);
+}
+
+/* Here we need to prepare the listitem for displaying its item. We get the
+ * listitem already set up from the previous function, so we can reuse the
+ * GtkImage widget we set up above.
+ * We get the item - which we know is a GAppInfo because it comes out of
+ * the model we set up above, grab its icon and display it.
+ */
+static void
+bind_listitem_cb (GtkListItemFactory *factory,
+ GtkListItem *list_item)
+{
+ GtkWidget *label;
+ GtkStringObject *item;
+
+ label = gtk_list_item_get_child (list_item);
+ item = gtk_list_item_get_item (list_item);
+
+ gtk_label_set_label (GTK_LABEL (label), gtk_string_object_get_string (item));
+}
+
+/* In more complex code, we would also need functions to unbind and teardown
+ * the listitem, but this is simple code, so the default implementations are
+ * enough. If we had connected signals, this step would have been necessary.
+ *
+ * The GtkSignalListItemFactory documentation contains more information about
+ * this step.
+ */
+
+static GtkWidget *window = NULL;
+
+GtkWidget *
+do_listview_objects (GtkWidget *do_widget)
+{
+ if (window == NULL)
+ {
+ GtkWidget *list, *sw;
+ GListModel *model;
+ GtkListItemFactory *factory;
+ GtkSorter *sorter;
+
+ /* Create a window and set a few defaults */
+ window = gtk_window_new ();
+ gtk_window_set_default_size (GTK_WINDOW (window), 300, 400);
+ gtk_window_set_display (GTK_WINDOW (window),
+ gtk_widget_get_display (do_widget));
+ gtk_window_set_title (GTK_WINDOW (window), "Objects in GTK");
+ g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
+
+ /* The GtkListitemFactory is what is used to create GtkListItems
+ * to display the data from the model. So it is absolutely necessary
+ * to create one.
+ * We will use a GtkSignalListItemFactory because it is the simplest
+ * one to use. Different ones are available for different use cases.
+ * The most powerful one is GtkBuilderListItemFactory which uses
+ * GtkBuilder .ui files, so it requires little code.
+ */
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
+
+ /* And of course we need to set the data model. Here we call the function
+ * we wrote above that gives us the list of applications. Then we set
+ * it on the list widget.
+ * The list will now take items from the model and use the factory
+ * to create as many listitems as it needs to show itself to the user.
+ */
+ model = create_object_list ();
+
+ /* Wrap the model in a sort model that sorts the objects alphabetically.
+ */
+ sorter = GTK_SORTER (gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL,
"string")));
+ model = G_LIST_MODEL (gtk_sort_list_model_new (model, sorter));
+
+ /* Create a sorter for the sections and tell the sort model about it
+ */
+ sorter = GTK_SORTER (gtk_string_sorter_new (gtk_cclosure_expression_new (G_TYPE_STRING, NULL, 0, NULL,
G_CALLBACK (get_section), NULL, NULL)));
+ gtk_string_sorter_set_ignore_case (GTK_STRING_SORTER (sorter), FALSE);
+ gtk_sort_list_model_set_section_sorter (GTK_SORT_LIST_MODEL (model), sorter);
+ g_object_unref (sorter);
+
+ /* Create the list widget here.
+ */
+ list = gtk_list_view_new (GTK_SELECTION_MODEL (gtk_single_selection_new (model)), factory);
+
+ /* Set a factory for sections, otherwise the listview won't use sections.
+ */
+ factory = gtk_signal_list_item_factory_new ();
+ g_signal_connect (factory, "setup", G_CALLBACK (setup_section_listitem_cb), NULL);
+ g_signal_connect (factory, "bind", G_CALLBACK (bind_section_listitem_cb), NULL);
+ gtk_list_view_set_section_factory (GTK_LIST_VIEW (list), factory);
+ g_object_unref (factory);
+
+ /* List widgets should always be contained in a GtkScrolledWindow,
+ * because otherwise they might get too large or they might not
+ * be scrollable.
+ */
+ sw = gtk_scrolled_window_new ();
+ gtk_window_set_child (GTK_WINDOW (window), sw);
+ gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list);
+ }
+
+ if (!gtk_widget_get_visible (window))
+ gtk_widget_show (window);
+ else
+ gtk_window_destroy (GTK_WINDOW (window));
+
+ return window;
+}
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index f594cd59b2..cc18609f77 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -18,8 +18,9 @@ demos = files([
'css_shadows.c',
'cursors.c',
'dialog.c',
- 'drawingarea.c',
'dnd.c',
+ 'drawingarea.c',
+ 'dropdown.c',
'editable_cells.c',
'entry_completion.c',
'entry_undo.c',
@@ -28,6 +29,7 @@ demos = files([
'filtermodel.c',
'fishbowl.c',
'fixed.c',
+ 'flowbox.c',
'fontrendering.c',
'frames.c',
'gears.c',
@@ -46,20 +48,19 @@ demos = files([
'links.c',
'listbox.c',
'listbox_controls.c',
- 'menu.c',
- 'flowbox.c',
'list_store.c',
'listview_applauncher.c',
'listview_clocks.c',
'listview_colors.c',
'listview_filebrowser.c',
'listview_minesweeper.c',
- 'dropdown.c',
+ 'listview_objects.c',
'listview_settings.c',
'listview_ucd.c',
'listview_weather.c',
'listview_words.c',
'markup.c',
+ 'menu.c',
'overlay.c',
'overlay_decorative.c',
'paint.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]