[gtk/wip/otte/listview: 70/76] demo: Use a listview as sidebar
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview: 70/76] demo: Use a listview as sidebar
- Date: Wed, 16 Oct 2019 19:51:59 +0000 (UTC)
commit 61d02e6fb8372165e656935680739e28cf2aca5f
Author: Timm Bäder <mail baedert org>
Date: Tue Oct 15 15:39:59 2019 +0200
demo: Use a listview as sidebar
demos/gtk-demo/geninclude.py | 17 ++-
demos/gtk-demo/main.c | 335 +++++++++++++++++++++----------------------
demos/gtk-demo/main.ui | 29 +---
3 files changed, 174 insertions(+), 207 deletions(-)
---
diff --git a/demos/gtk-demo/geninclude.py b/demos/gtk-demo/geninclude.py
index cd0af14e0d..878308648e 100755
--- a/demos/gtk-demo/geninclude.py
+++ b/demos/gtk-demo/geninclude.py
@@ -13,17 +13,16 @@ in_files = sys.argv[2:]
file_output = """
typedef GtkWidget *(*GDoDemoFunc) (GtkWidget *do_widget);
-typedef struct _Demo Demo;
+typedef struct _DemoData DemoData;
-struct _Demo
+struct _DemoData
{
- gchar *name;
- gchar *title;
- gchar *filename;
+ char *name;
+ char *title;
+ char *filename;
GDoDemoFunc func;
- Demo *children;
+ DemoData *children;
};
-
"""
# Demo = namedtuple('Demo', ['name', 'title', 'file', 'func'])
@@ -67,7 +66,7 @@ for demo in demos:
i = 0
for parent in parents:
id = parent_ids[i]
- file_output += "\nDemo child" + str(id) + "[] = {\n"
+ file_output += "\nDemoData child" + str(id) + "[] = {\n"
# iterate over all demos and check if the name starts with the given parent name
for child in demos:
if child[1].startswith(parent + "/"):
@@ -82,7 +81,7 @@ for parent in parents:
# Sort demos by title
demos = sorted(demos, key=lambda x: x[1])
-file_output += "\nDemo gtk_demos[] = {\n"
+file_output += "\nDemoData gtk_demos[] = {\n"
for demo in demos:
# Do not generate one of these for demos with a parent demo
if "/" not in demo[1]:
diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c
index e8af585472..6b802564ee 100644
--- a/demos/gtk-demo/main.c
+++ b/demos/gtk-demo/main.c
@@ -16,19 +16,32 @@ static GtkWidget *source_view;
static gchar *current_file = NULL;
+static GtkWidget *window;
static GtkWidget *notebook;
-static GtkWidget *treeview;
+static GtkWidget *listview;
+static GtkSingleSelection *selection;
static GtkWidget *headerbar;
-enum {
- NAME_COLUMN,
- TITLE_COLUMN,
- FILENAME_COLUMN,
- FUNC_COLUMN,
- STYLE_COLUMN,
- NUM_COLUMNS
+typedef struct _GtkDemo GtkDemo;
+struct _GtkDemo
+{
+ GObject parent_instance;
+
+ const char *name;
+ const char *title;
+ const char *filename;
+ GDoDemoFunc func;
+ GListModel *children_model;
};
+# define GTK_TYPE_DEMO (gtk_demo_get_type ())
+G_DECLARE_FINAL_TYPE (GtkDemo, gtk_demo, GTK, DEMO, GObject);
+
+G_DEFINE_TYPE (GtkDemo, gtk_demo, G_TYPE_OBJECT);
+
+static void gtk_demo_init (GtkDemo *self) {}
+static void gtk_demo_class_init (GtkDemoClass *klass) {}
+
typedef struct _CallbackData CallbackData;
struct _CallbackData
{
@@ -36,6 +49,27 @@ struct _CallbackData
GtkTreePath *path;
};
+static gboolean
+gtk_demo_run (GtkDemo *self,
+ GtkWidget *window)
+{
+ GtkWidget *result;
+
+ if (!self->func)
+ return FALSE;
+
+ result = self->func (window);
+ if (result == NULL)
+ return FALSE;
+
+ if (GTK_IS_WINDOW (result))
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (result), GTK_WINDOW (window));
+ gtk_window_set_modal (GTK_WINDOW (result), TRUE);
+ }
+ return TRUE;
+}
+
static void
activate_about (GSimpleAction *action,
GVariant *parameter,
@@ -115,82 +149,15 @@ activate_inspector (GSimpleAction *action,
award ("demo-inspector");
}
-static void
-window_closed_cb (GtkWidget *window, gpointer data)
-{
- CallbackData *cbdata = data;
- GtkTreeIter iter;
- PangoStyle style;
-
- gtk_tree_model_get_iter (cbdata->model, &iter, cbdata->path);
- gtk_tree_model_get (GTK_TREE_MODEL (cbdata->model), &iter,
- STYLE_COLUMN, &style,
- -1);
- if (style == PANGO_STYLE_ITALIC)
- gtk_tree_store_set (GTK_TREE_STORE (cbdata->model), &iter,
- STYLE_COLUMN, PANGO_STYLE_NORMAL,
- -1);
-
- gtk_tree_path_free (cbdata->path);
- g_free (cbdata);
-}
-
-static void
-run_example_for_row (GtkWidget *window,
- GtkTreeModel *model,
- GtkTreeIter *iter)
-{
- PangoStyle style;
- GDoDemoFunc func;
- GtkWidget *demo;
-
- gtk_tree_model_get (GTK_TREE_MODEL (model),
- iter,
- FUNC_COLUMN, &func,
- STYLE_COLUMN, &style,
- -1);
-
- if (func)
- {
- gtk_tree_store_set (GTK_TREE_STORE (model),
- iter,
- STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL :
PANGO_STYLE_ITALIC),
- -1);
- demo = (func) (window);
-
- if (demo != NULL)
- {
- CallbackData *cbdata;
-
- cbdata = g_new (CallbackData, 1);
- cbdata->model = model;
- cbdata->path = gtk_tree_model_get_path (model, iter);
-
- if (GTK_IS_WINDOW (demo))
- {
- gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
- gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
- }
-
- g_signal_connect (demo, "destroy",
- G_CALLBACK (window_closed_cb), cbdata);
- }
- }
-}
-
static void
activate_run (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
- GtkWidget *window = user_data;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
+ GtkTreeListRow *row = gtk_single_selection_get_selected_item (selection);
+ GtkDemo *demo = gtk_tree_list_row_get_item (row);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- run_example_for_row (window, model, &iter);
+ gtk_demo_run (demo, window);
}
/* Stupid syntax highlighting.
@@ -890,81 +857,72 @@ load_file (const gchar *demoname,
}
static void
-selection_cb (GtkTreeSelection *selection,
- GtkTreeModel *model)
-{
- GtkTreeIter iter;
- char *name;
- char *filename;
- char *title;
-
- if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
- return;
- gtk_tree_model_get (model, &iter,
- NAME_COLUMN, &name,
- TITLE_COLUMN, &title,
- FILENAME_COLUMN, &filename,
- -1);
-
- if (filename)
- load_file (name, filename);
+selection_cb (GtkSingleSelection *selection,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GtkTreeListRow *row = gtk_single_selection_get_selected_item (selection);
+ GtkDemo *demo = gtk_tree_list_row_get_item (row);
- gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar), title);
+ if (demo->filename)
+ load_file (demo->name, demo->filename);
- g_free (name);
- g_free (title);
- g_free (filename);
+ gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar), demo->title);
}
-static void
-populate_model (GtkTreeModel *model)
+static GListModel *
+create_demo_model (void)
{
- Demo *d = gtk_demos;
+ GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
+ DemoData *demo = gtk_demos;
- /* this code only supports 1 level of children. If we
- * want more we probably have to use a recursing function.
- */
- while (d->title)
+ while (demo->title)
{
- Demo *children = d->children;
- GtkTreeIter iter;
+ GtkDemo *d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
+ DemoData *children = demo->children;
- gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
-
- gtk_tree_store_set (GTK_TREE_STORE (model),
- &iter,
- NAME_COLUMN, d->name,
- TITLE_COLUMN, d->title,
- FILENAME_COLUMN, d->filename,
- FUNC_COLUMN, d->func,
- STYLE_COLUMN, PANGO_STYLE_NORMAL,
- -1);
-
- d++;
+ d->name = demo->name;
+ d->title = demo->title;
+ d->filename = demo->filename;
+ d->func = demo->func;
- if (!children)
- continue;
+ g_list_store_append (store, d);
- while (children->title)
+ if (children)
{
- GtkTreeIter child_iter;
+ d->children_model = G_LIST_MODEL (g_list_store_new (GTK_TYPE_DEMO));
- gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &iter);
+ while (children->title)
+ {
+ GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
- gtk_tree_store_set (GTK_TREE_STORE (model),
- &child_iter,
- NAME_COLUMN, children->name,
- TITLE_COLUMN, children->title,
- FILENAME_COLUMN, children->filename,
- FUNC_COLUMN, children->func,
- STYLE_COLUMN, PANGO_STYLE_NORMAL,
- -1);
+ child->name = children->name;
+ child->title = children->title;
+ child->filename = children->filename;
+ child->func = children->func;
- children++;
+ g_list_store_append (G_LIST_STORE (d->children_model), child);
+ children++;
+ }
}
+
+ demo++;
}
+ return G_LIST_MODEL (store);
+}
+
+static GListModel *
+get_child_model (gpointer item,
+ gpointer user_data)
+{
+ GtkDemo *demo = item;
+
+ if (demo->children_model)
+ return g_object_ref (G_LIST_MODEL (demo->children_model));
+
+ return NULL;
}
static void
@@ -984,22 +942,6 @@ startup (GApplication *app)
g_object_unref (builder);
}
-static void
-row_activated_cb (GtkWidget *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column)
-{
- GtkTreeIter iter;
- GtkWidget *window;
- GtkTreeModel *model;
-
- window = GTK_WIDGET (gtk_widget_get_root (tree_view));
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
- gtk_tree_model_get_iter (model, &iter, path);
-
- run_example_for_row (window, model, &iter);
-}
-
static void
start_cb (GtkMenuItem *item, GtkWidget *scrollbar)
{
@@ -1026,34 +968,78 @@ scrollbar_popup (GtkWidget *scrollbar, GtkWidget *menu)
return TRUE;
}
+static void
+listview_activate_cb (GtkListView *listview,
+ guint position,
+ gpointer user_data)
+{
+ GtkTreeListRow *row = g_list_model_get_item (gtk_list_view_get_model (listview), position);
+ GtkDemo *demo = gtk_tree_list_row_get_item (row);
+
+ gtk_demo_run (demo, window);
+}
+
+static void
+setup_demo_row_func (GtkListItem *list_item,
+ gpointer user_data)
+{
+ GtkWidget *label;
+ GtkWidget *expander;
+
+ expander = gtk_tree_expander_new ();
+
+ label = gtk_label_new ("");
+ gtk_widget_set_halign (label, GTK_ALIGN_START);
+
+ gtk_tree_expander_set_child (GTK_TREE_EXPANDER (expander), label);
+ gtk_container_add (GTK_CONTAINER (list_item), expander);
+}
+
+static void
+bind_demo_row_func (GtkListItem *list_item,
+ gpointer user_data)
+{
+ GtkWidget *label, *expander;
+ GtkTreeListRow *row;
+ GtkDemo *demo;
+
+ row = gtk_list_item_get_item (list_item);
+ demo = gtk_tree_list_row_get_item (row);
+ expander = gtk_bin_get_child (GTK_BIN (list_item));
+ gtk_tree_expander_set_list_row (GTK_TREE_EXPANDER (expander), row);
+ label = gtk_tree_expander_get_child (GTK_TREE_EXPANDER (expander));
+
+ gtk_label_set_label (GTK_LABEL (label), demo->title);
+}
+
static void
activate (GApplication *app)
{
GtkBuilder *builder;
- GtkWindow *window;
- GtkWidget *widget;
- GtkTreeModel *model;
- GtkTreeIter iter;
GError *error = NULL;
GtkWidget *sw;
GtkWidget *scrollbar;
GtkWidget *menu;
GtkWidget *item;
+ GListModel *listmodel;
+ GtkTreeListModel *treemodel;
static GActionEntry win_entries[] = {
{ "run", activate_run, NULL, NULL, NULL }
};
builder = gtk_builder_new ();
+ gtk_builder_add_callback_symbol (builder, "listview_activate_cb", G_CALLBACK (listview_activate_cb));
gtk_builder_add_from_resource (builder, "/ui/main.ui", &error);
if (error != NULL)
{
g_critical ("%s", error->message);
exit (1);
}
+ gtk_builder_connect_signals (builder, NULL);
- window = (GtkWindow *)gtk_builder_get_object (builder, "window");
- gtk_application_add_window (GTK_APPLICATION (app), window);
+ window = (GtkWidget *)gtk_builder_get_object (builder, "window");
+ gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (window));
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
window);
@@ -1063,8 +1049,7 @@ activate (GApplication *app)
info_view = (GtkWidget *)gtk_builder_get_object (builder, "info-textview");
source_view = (GtkWidget *)gtk_builder_get_object (builder, "source-textview");
headerbar = (GtkWidget *)gtk_builder_get_object (builder, "headerbar");
- treeview = (GtkWidget *)gtk_builder_get_object (builder, "treeview");
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
+ listview = (GtkWidget *)gtk_builder_get_object (builder, "listview");
sw = (GtkWidget *)gtk_builder_get_object (builder, "source-scrolledwindow");
scrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (sw));
@@ -1083,17 +1068,23 @@ activate (GApplication *app)
load_file (gtk_demos[0].name, gtk_demos[0].filename);
- populate_model (model);
-
- g_signal_connect (treeview, "row-activated", G_CALLBACK (row_activated_cb), model);
-
- widget = (GtkWidget *)gtk_builder_get_object (builder, "treeview-selection");
- g_signal_connect (widget, "changed", G_CALLBACK (selection_cb), model);
-
- gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)), &iter);
- gtk_tree_selection_select_iter (GTK_TREE_SELECTION (widget), &iter);
-
- gtk_tree_view_collapse_all (GTK_TREE_VIEW (treeview));
+ listmodel = create_demo_model ();
+ treemodel = gtk_tree_list_model_new (FALSE,
+ G_LIST_MODEL (listmodel),
+ FALSE,
+ get_child_model,
+ NULL,
+ NULL);
+
+ gtk_list_view_set_factory (GTK_LIST_VIEW (listview),
+ gtk_functions_list_item_factory_new (setup_demo_row_func,
+ bind_demo_row_func,
+ NULL,
+ NULL));
+ selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
+ g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
+ gtk_list_view_set_model (GTK_LIST_VIEW (listview),
+ G_LIST_MODEL (selection));
award ("demo-start");
@@ -1112,7 +1103,7 @@ auto_quit (gpointer data)
static void
list_demos (void)
{
- Demo *d, *c;
+ DemoData *d, *c;
d = gtk_demos;
@@ -1139,7 +1130,7 @@ command_line (GApplication *app,
const gchar *name = NULL;
gboolean autoquit = FALSE;
gboolean list = FALSE;
- Demo *d, *c;
+ DemoData *d, *c;
GDoDemoFunc func = 0;
GtkWidget *window, *demo;
diff --git a/demos/gtk-demo/main.ui b/demos/gtk-demo/main.ui
index bf70a37be6..6c3d71f527 100644
--- a/demos/gtk-demo/main.ui
+++ b/demos/gtk-demo/main.ui
@@ -28,7 +28,6 @@
<property name="default-width">800</property>
<property name="default-height">600</property>
<property name="title">GTK Demo</property>
- <signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerbar">
<property name="show-title-buttons">1</property>
@@ -66,32 +65,10 @@
<property name="can-focus">1</property>
<property name="hscrollbar-policy">never</property>
<property name="min-content-width">150</property>
+
<child>
- <object class="GtkTreeView" id="treeview">
- <property name="can-focus">1</property>
- <property name="model">treestore</property>
- <property name="headers-visible">0</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection">
- <property name="mode">browse</property>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn">
- <child>
- <object class="GtkCellRendererText"/>
- <attributes>
- <attribute name="style">4</attribute>
- <attribute name="text">1</attribute>
- </attributes>
- </child>
- <child>
- <object class="GtkCellRendererText">
- <property name="text"> </property>
- </object>
- </child>
- </object>
- </child>
+ <object class="GtkListView" id="listview">
+ <signal name="activate" handler="listview_activate_cb" swapped="no" />
</object>
</child>
</object>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]