[gtk/wip/otte/listview: 15/15] listview: Change how binding is done



commit 1eb72f918eb4b903ee44926a45171aee157171a0
Author: Benjamin Otte <otte redhat com>
Date:   Mon Sep 24 04:42:15 2018 +0200

    listview: Change how binding is done
    
    We now don't let the functions create widgets for the item from the
    listmodel, instead we hand out a GtkListItem for them to add a widget
    to.
    
    GtkListItems are created in advance and can only be filled in by the
    binding code by gtk_container_add()ing a widget.
    However, they are GObjects, so they can provide properties that the
    binding code can make use of - either via notify signals or GBinding.

 gtk/gtklistitem.c               | 11 -----------
 gtk/gtklistitemfactory.c        | 27 +++++++++++++--------------
 gtk/gtklistitemfactoryprivate.h |  4 ++--
 gtk/gtklistitemprivate.h        |  3 ---
 gtk/gtklistview.c               | 15 +++++++--------
 gtk/gtklistview.h               | 33 ++++++++++++++++-----------------
 tests/testlistview-animating.c  | 40 ++++++++++++++++++++++++++++------------
 tests/testlistview.c            | 23 +++++++++++------------
 8 files changed, 77 insertions(+), 79 deletions(-)
---
diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c
index 8b0d5ca7de..e72067b48b 100644
--- a/gtk/gtklistitem.c
+++ b/gtk/gtklistitem.c
@@ -208,17 +208,6 @@ gtk_list_item_get_position (GtkListItem *self)
   return self->position;
 }
 
-void
-gtk_list_item_set_child (GtkListItem *self,
-                         GtkWidget   *child)
-{
-  g_return_if_fail (GTK_IS_LIST_ITEM (self));
-  g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
-
-  _gtk_bin_set_child (GTK_BIN (self), child);
-  gtk_widget_insert_after (child, GTK_WIDGET (self), NULL);
-}
-
 void
 gtk_list_item_set_item (GtkListItem *self,
                         gpointer     item)
diff --git a/gtk/gtklistitemfactory.c b/gtk/gtklistitemfactory.c
index ba1f0c81cd..c8e60bc163 100644
--- a/gtk/gtklistitemfactory.c
+++ b/gtk/gtklistitemfactory.c
@@ -27,8 +27,8 @@ struct _GtkListItemFactory
 {
   GObject parent_instance;
 
-  GtkListCreateWidgetFunc create_func;
-  GtkListBindWidgetFunc bind_func;
+  GtkListItemSetupFunc setup_func;
+  GtkListItemBindFunc bind_func;
   gpointer user_data;
   GDestroyNotify user_destroy;
 };
@@ -65,20 +65,19 @@ gtk_list_item_factory_init (GtkListItemFactory *self)
 }
 
 GtkListItemFactory *
-gtk_list_item_factory_new (GtkListCreateWidgetFunc create_func,
-                           GtkListBindWidgetFunc   bind_func,
-                           gpointer                user_data,
-                           GDestroyNotify          user_destroy)
+gtk_list_item_factory_new (GtkListItemSetupFunc setup_func,
+                           GtkListItemBindFunc  bind_func,
+                           gpointer             user_data,
+                           GDestroyNotify       user_destroy)
 {
   GtkListItemFactory *self;
 
-  g_return_val_if_fail (create_func, NULL);
-  g_return_val_if_fail (bind_func, NULL);
+  g_return_val_if_fail (setup_func || bind_func, NULL);
   g_return_val_if_fail (user_data != NULL || user_destroy == NULL, NULL);
 
   self = g_object_new (GTK_TYPE_LIST_ITEM_FACTORY, NULL);
 
-  self->create_func = create_func;
+  self->setup_func = setup_func;
   self->bind_func = bind_func;
   self->user_data = user_data;
   self->user_destroy = user_destroy;
@@ -89,15 +88,14 @@ gtk_list_item_factory_new (GtkListCreateWidgetFunc create_func,
 GtkListItem *
 gtk_list_item_factory_create (GtkListItemFactory *self)
 {
-  GtkWidget *widget, *result;
+  GtkWidget *result;
 
   g_return_val_if_fail (GTK_IS_LIST_ITEM_FACTORY (self), NULL);
 
-  widget = self->create_func (self->user_data);
-
   result = gtk_list_item_new ("row");
 
-  gtk_list_item_set_child (GTK_LIST_ITEM (result), widget);
+  if (self->setup_func)
+    self->setup_func (GTK_LIST_ITEM (result), self->user_data);
 
   return GTK_LIST_ITEM (result);
 }
@@ -116,7 +114,8 @@ gtk_list_item_factory_bind (GtkListItemFactory *self,
   gtk_list_item_set_item (list_item, item);
   gtk_list_item_set_position (list_item, position);
 
-  self->bind_func (gtk_bin_get_child (GTK_BIN (list_item)), item, self->user_data);
+  if (self->bind_func)  
+    self->bind_func (list_item, self->user_data);
 
   g_object_thaw_notify (G_OBJECT (list_item));
 }
diff --git a/gtk/gtklistitemfactoryprivate.h b/gtk/gtklistitemfactoryprivate.h
index 21bc5b5586..779251344b 100644
--- a/gtk/gtklistitemfactoryprivate.h
+++ b/gtk/gtklistitemfactoryprivate.h
@@ -38,8 +38,8 @@ typedef struct _GtkListItemFactoryClass GtkListItemFactoryClass;
 
 GType                   gtk_list_item_factory_get_type          (void) G_GNUC_CONST;
 
-GtkListItemFactory *    gtk_list_item_factory_new               (GtkListCreateWidgetFunc create_func,
-                                                                 GtkListBindWidgetFunc   bind_func,
+GtkListItemFactory *    gtk_list_item_factory_new               (GtkListItemSetupFunc    setup_func,
+                                                                 GtkListItemBindFunc     bind_func,
                                                                  gpointer                user_data,
                                                                  GDestroyNotify          user_destroy);
 
diff --git a/gtk/gtklistitemprivate.h b/gtk/gtklistitemprivate.h
index a4bcd9218a..f238685c76 100644
--- a/gtk/gtklistitemprivate.h
+++ b/gtk/gtklistitemprivate.h
@@ -26,9 +26,6 @@ G_BEGIN_DECLS
 
 GtkWidget *     gtk_list_item_new                               (const char             *css_name);
 
-void            gtk_list_item_set_child                         (GtkListItem            *item,
-                                                                 GtkWidget              *child);
-
 void            gtk_list_item_set_item                          (GtkListItem            *self,
                                                                  gpointer                item);
 void            gtk_list_item_set_position                      (GtkListItem            *self,
diff --git a/gtk/gtklistview.c b/gtk/gtklistview.c
index fdb81b43d0..454ca0ecd7 100644
--- a/gtk/gtklistview.c
+++ b/gtk/gtklistview.c
@@ -895,24 +895,23 @@ gtk_list_view_set_model (GtkListView *self,
 }
 
 void
-gtk_list_view_set_functions (GtkListView            *self,
-                             GtkListCreateWidgetFunc create_func,
-                             GtkListBindWidgetFunc   bind_func,
-                             gpointer                user_data,
-                             GDestroyNotify          user_destroy)
+gtk_list_view_set_functions (GtkListView          *self,
+                             GtkListItemSetupFunc  setup_func,
+                             GtkListItemBindFunc   bind_func,
+                             gpointer              user_data,
+                             GDestroyNotify        user_destroy)
 {
   GtkListItemFactory *factory;
   guint n_items;
 
   g_return_if_fail (GTK_IS_LIST_VIEW (self));
-  g_return_if_fail (create_func);
-  g_return_if_fail (bind_func);
+  g_return_if_fail (setup_func || bind_func);
   g_return_if_fail (user_data != NULL || user_destroy == NULL);
 
   n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
   gtk_list_view_remove_rows (self, NULL, 0, n_items);
 
-  factory = gtk_list_item_factory_new (create_func, bind_func, user_data, user_destroy);
+  factory = gtk_list_item_factory_new (setup_func, bind_func, user_data, user_destroy);
   gtk_list_item_manager_set_factory (self->item_manager, factory);
   g_object_unref (factory);
 
diff --git a/gtk/gtklistview.h b/gtk/gtklistview.h
index 541bf14874..55cc12f068 100644
--- a/gtk/gtklistview.h
+++ b/gtk/gtklistview.h
@@ -25,38 +25,37 @@
 #endif
 
 #include <gtk/gtkwidget.h>
+#include <gtk/gtklistitem.h>
 
 G_BEGIN_DECLS
 
 /**
- * GtkListCreateWidgetFunc:
+ * GtkListItemSetupFunc:
+ * @item: the #GtkListItem to set up
  * @user_data: (closure): user data
  *
- * Called whenever a new widget needs to be created for managing a row in
+ * Called whenever a new list item needs to be setup for managing a row in
  * the list.
  *
- * The widget will later be bound to an item via the #GtkListBindWidgetFunc.
- *
- * Returns: (transfer full): a #GtkWidget
+ * At this point, the list item is not bound yet, so gtk_list_item_get_item()
+ * will return %NULL.  
+ * The list item will later be bound to an item via the #GtkListItemBindFunc.
  */
-typedef GtkWidget * (* GtkListCreateWidgetFunc) (gpointer user_data);
+typedef void (* GtkListItemSetupFunc) (GtkListItem *item, gpointer user_data);
 
 /**
- * GtkListBindWidgetFunc:
- * @widget: The #GtkWidget to bind
- * @item: (type GObject) (allow-none): item to bind or %NULL to unbind
- *     the widget.
+ * GtkListItemBindFunc:
+ * @item: the #GtkListItem to bind
  * @user_data: (closure): user data
  *
- * Binds a widget previously created via a #GtkListCreateWidgetFunc to
+ * Binds a#GtkListItem previously set up via a #GtkListItemSetupFunc to
  * an @item.
  *
- * Rebinding a @widget to different @items is supported as well as
+ * Rebinding a @item to different @items is supported as well as
  * unbinding it by setting @item to %NULL.
  */
-typedef void (* GtkListBindWidgetFunc) (GtkWidget *widget,
-                                        gpointer   item,
-                                        gpointer   user_data);
+typedef void (* GtkListItemBindFunc) (GtkListItem *item,
+                                      gpointer   user_data);
 
 #define GTK_TYPE_LIST_VIEW         (gtk_list_view_get_type ())
 
@@ -73,8 +72,8 @@ void            gtk_list_view_set_model                         (GtkListView
                                                                  GListModel             *model);
 GDK_AVAILABLE_IN_ALL
 void            gtk_list_view_set_functions                     (GtkListView            *self,
-                                                                 GtkListCreateWidgetFunc create_func,
-                                                                 GtkListBindWidgetFunc   bind_func,
+                                                                 GtkListItemSetupFunc    setup_func,
+                                                                 GtkListItemBindFunc     bind_func,
                                                                  gpointer                user_data,
                                                                  GDestroyNotify          user_destroy);
 
diff --git a/tests/testlistview-animating.c b/tests/testlistview-animating.c
index b6ac405618..8a575d34d0 100644
--- a/tests/testlistview-animating.c
+++ b/tests/testlistview-animating.c
@@ -8,30 +8,46 @@
 #define VARIANCE 200
 #endif
 
-static GtkWidget *
-create_widget (gpointer unused)
+static void
+update_label (GtkListItem *list_item,
+              GParamSpec  *pspec,
+              GtkLabel    *label)
 {
-  return gtk_label_new ("");
+  gpointer item;
+  char *s;
+
+  item = gtk_list_item_get_item (list_item);
+
+  if (item)
+    s = g_strdup_printf ("%u: %s",
+                         gtk_list_item_get_position (list_item),
+                         (const char *) g_object_get_data (item, "message"));
+  else
+    s = NULL;
+
+  gtk_label_set_text (label, s);
+
+  g_free (s);
 }
 
 static void
-bind_widget (GtkWidget *widget,
-             gpointer   item,
-             gpointer   unused)
+setup_list_item (GtkListItem *list_item,
+                 gpointer     unused)
 {
-  const char *message = g_object_get_data (item, "message");
+  GtkWidget *label = gtk_label_new ("");
 
-  gtk_label_set_text (GTK_LABEL (widget), message);
+  g_signal_connect (list_item, "notify", G_CALLBACK (update_label), label);
+  gtk_container_add (GTK_CONTAINER (list_item), label);
 }
 
 static GtkWidget *
 create_widget_for_listbox (gpointer item,
                            gpointer unused)
 {
+  const char *message = g_object_get_data (item, "message");
   GtkWidget *widget;
   
-  widget = create_widget (unused);
-  bind_widget (widget, item, unused);
+  widget = gtk_label_new (message);
 
   return widget;
 }
@@ -138,8 +154,8 @@ main (int argc, char *argv[])
 
   listview = gtk_list_view_new ();
   gtk_list_view_set_functions (GTK_LIST_VIEW (listview),
-                               create_widget,
-                               bind_widget,
+                               setup_list_item,
+                               NULL,
                                NULL, NULL);
   gtk_container_add (GTK_CONTAINER (sw), listview);
 
diff --git a/tests/testlistview.c b/tests/testlistview.c
index 6871384b3b..9bc69947f8 100644
--- a/tests/testlistview.c
+++ b/tests/testlistview.c
@@ -161,25 +161,24 @@ create_list_model_for_directory (gpointer file)
   return G_LIST_MODEL (sort);
 }
 
-static GtkWidget *
-create_widget (gpointer unused)
-{
-  return gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
-}
-
 static void
-bind_widget (GtkWidget *box,
-             gpointer   item,
+bind_widget (GtkListItem *list_item,
              gpointer   unused)
 {
-  GtkWidget *child;
+  GtkWidget *box, *child;
   GFileInfo *info;
   GFile *file;
   guint depth;
   GIcon *icon;
+  gpointer item;
+
+  item = gtk_list_item_get_item (list_item);
 
-  while (gtk_widget_get_first_child (box))
-    gtk_container_remove (GTK_CONTAINER (box), gtk_widget_get_first_child (box));
+  child = gtk_bin_get_child (GTK_BIN (list_item));
+  if (child)
+    gtk_container_remove (GTK_CONTAINER (list_item), child);
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
+  gtk_container_add (GTK_CONTAINER (list_item), box);
 
   depth = gtk_tree_list_row_get_depth (item);
   if (depth > 0)
@@ -317,7 +316,7 @@ main (int argc, char *argv[])
 
   listview = gtk_list_view_new ();
   gtk_list_view_set_functions (GTK_LIST_VIEW (listview),
-                               create_widget,
+                               NULL,
                                bind_widget,
                                NULL, NULL);
   gtk_container_add (GTK_CONTAINER (sw), listview);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]