[gtk+/treeview-refactor] Fixed GtkCellAreaIter to notify invalidation of sizes on flush



commit 86fb6ab21617479d88a078889113fea37e09d6fe
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Sat Oct 30 21:40:22 2010 +0900

    Fixed GtkCellAreaIter to notify invalidation of sizes on flush
    
    Also fixed GtkCellAreaBox to track the iters it creates and flush
    them when the overall layout configuration changes (add/remove/reorder/
    spacing changed etc).

 gtk/gtkcellareabox.c  |   98 ++++++++++++++++++++++++++++++++++++++++---------
 gtk/gtkcellareaiter.c |   50 ++++++++++++++++++++++---
 2 files changed, 124 insertions(+), 24 deletions(-)
---
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index f1a7cc1..80b271e 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -97,7 +97,7 @@ static void      gtk_cell_area_box_layout_reorder                 (GtkCellLayout
 								   gint                position);
 
 
-/* CellInfo/CellGroup metadata handling */
+/* CellInfo/CellGroup metadata handling and convenience functions */
 typedef struct {
   GtkCellRenderer *renderer;
 
@@ -109,7 +109,7 @@ typedef struct {
 typedef struct {
   GList *cells;
 
-  guint  id : 16;
+  guint  id     : 16;
   guint  expand : 1;
 } CellGroup;
 
@@ -128,16 +128,20 @@ static GList     *list_consecutive_cells (GtkCellAreaBox  *box);
 static GList     *construct_cell_groups  (GtkCellAreaBox  *box);
 static gint       count_expand_groups    (GtkCellAreaBox  *box);
 static gint       count_expand_cells     (CellGroup       *group);
-
+static void       iter_weak_notify       (GtkCellAreaBox  *box,
+					  GtkCellAreaIter *dead_iter);
+static void       flush_iters            (GtkCellAreaBox  *box);
 
 struct _GtkCellAreaBoxPrivate
 {
-  GtkOrientation orientation;
+  GtkOrientation  orientation;
+
+  GList          *cells;
+  GList          *groups;
 
-  GList         *cells;
-  GList         *groups;
+  GSList         *iters;
 
-  gint           spacing;
+  gint            spacing;
 };
 
 enum {
@@ -168,6 +172,7 @@ gtk_cell_area_box_init (GtkCellAreaBox *box)
   priv->orientation = GTK_ORIENTATION_HORIZONTAL;
   priv->cells       = NULL;
   priv->groups      = NULL;
+  priv->iters       = NULL;
   priv->spacing     = 0;
 }
 
@@ -214,7 +219,7 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
 
 
 /*************************************************************
- *                CellInfo/CellGroup Basics                  *
+ *    CellInfo/CellGroup basics and convenience functions    *
  *************************************************************/
 static CellInfo *
 cell_info_new  (GtkCellRenderer *renderer, 
@@ -379,6 +384,31 @@ count_expand_cells (CellGroup *group)
   return expand_cells;
 }
 
+static void 
+iter_weak_notify (GtkCellAreaBox  *box,
+		  GtkCellAreaIter *dead_iter)
+{
+  GtkCellAreaBoxPrivate *priv = box->priv;
+
+  priv->iters = g_slist_remove (priv->iters, dead_iter);
+}
+
+static void
+flush_iters (GtkCellAreaBox *box)
+{
+  GtkCellAreaBoxPrivate *priv = box->priv;
+  GSList                *l;
+
+  /* When the box layout changes, iters need to
+   * be flushed and sizes for the box get requested again
+   */
+  for (l = priv->iters; l; l = l->next)
+    {
+      GtkCellAreaIter *iter = l->data;
+
+      gtk_cell_area_iter_flush (iter);
+    }
+}
 
 /*************************************************************
  *                      GObjectClass                         *
@@ -386,6 +416,15 @@ count_expand_cells (CellGroup *group)
 static void
 gtk_cell_area_box_finalize (GObject *object)
 {
+  GtkCellAreaBox        *box = GTK_CELL_AREA_BOX (object);
+  GtkCellAreaBoxPrivate *priv = box->priv;
+  GSList                *l;
+
+  for (l = priv->iters; l; l = l->next)
+    g_object_weak_unref (G_OBJECT (l->data), (GWeakNotify)iter_weak_notify, box);
+
+  g_slist_free (priv->iters);
+
   G_OBJECT_CLASS (gtk_cell_area_box_parent_class)->finalize (object);
 }
 
@@ -463,15 +502,13 @@ gtk_cell_area_box_remove (GtkCellArea        *area,
 
       priv->cells = g_list_delete_link (priv->cells, node);
 
-      /* Reconstruct cell groups
-       * XXX TODO: add a list of iters and weak_ref's on them, then
-       * flush the iters when we reconstruct groups, change spacing
-       * or child expand properties (i.e. notify size needs to be
-       * recalculated).
-       */
+      /* Reconstruct cell groups */
       g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
       g_list_free (priv->groups);
       priv->groups = construct_cell_groups (box);
+
+      /* Notify that size needs to be requested again */
+      flush_iters (box);
     }
   else
     g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
@@ -517,7 +554,16 @@ gtk_cell_area_box_render (GtkCellArea        *area,
 static GtkCellAreaIter *
 gtk_cell_area_box_create_iter (GtkCellArea *area)
 {
-  return (GtkCellAreaIter *)g_object_new (GTK_TYPE_CELL_AREA_BOX_ITER, NULL);
+  GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
+  GtkCellAreaBoxPrivate *priv = box->priv;
+  GtkCellAreaIter       *iter =
+    (GtkCellAreaIter *)g_object_new (GTK_TYPE_CELL_AREA_BOX_ITER, NULL);
+
+  priv->iters = g_slist_prepend (priv->iters, iter);
+
+  g_object_weak_ref (G_OBJECT (iter), (GWeakNotify)iter_weak_notify, box);
+
+  return iter;
 }
 
 static GtkSizeRequestMode 
@@ -1012,6 +1058,14 @@ gtk_cell_area_box_layout_reorder (GtkCellLayout      *cell_layout,
 
       priv->cells = g_list_delete_link (priv->cells, node);
       priv->cells = g_list_insert (priv->cells, info, position);
+
+      /* Reconstruct cell groups */
+      g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
+      g_list_free (priv->groups);
+      priv->groups = construct_cell_groups (box);
+      
+      /* Notify that size needs to be requested again */
+      flush_iters (box);
     }
 }
 
@@ -1049,10 +1103,13 @@ gtk_cell_area_box_pack_start  (GtkCellAreaBox  *box,
 
   priv->cells = g_list_append (priv->cells, info);
 
-  /* Reconstruct cell groups (TODO, notify created iters that size needs renegotiation) */
+  /* Reconstruct cell groups */
   g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
   g_list_free (priv->groups);
   priv->groups = construct_cell_groups (box);
+
+  /* Notify that size needs to be requested again */
+  flush_iters (box);
 }
 
 void
@@ -1080,10 +1137,13 @@ gtk_cell_area_box_pack_end (GtkCellAreaBox  *box,
 
   priv->cells = g_list_append (priv->cells, info);
 
-  /* Reconstruct cell groups (TODO, notify created iters that size needs renegotiation) */
+  /* Reconstruct cell groups */
   g_list_foreach (priv->groups, (GFunc)cell_group_free, NULL);
   g_list_free (priv->groups);
   priv->groups = construct_cell_groups (box);
+
+  /* Notify that size needs to be requested again */
+  flush_iters (box);
 }
 
 gint
@@ -1108,7 +1168,9 @@ gtk_cell_area_box_set_spacing (GtkCellAreaBox  *box,
     {
       priv->spacing = spacing;
 
-      /* TODO, notify created iters that size needs renegotiation */
       g_object_notify (G_OBJECT (box), "spacing");
+
+      /* Notify that size needs to be requested again */
+      flush_iters (box);
     }
 }
diff --git a/gtk/gtkcellareaiter.c b/gtk/gtkcellareaiter.c
index 4257f4b..4b31364 100644
--- a/gtk/gtkcellareaiter.c
+++ b/gtk/gtkcellareaiter.c
@@ -319,6 +319,18 @@ gtk_cell_area_iter_real_flush_preferred_width (GtkCellAreaIter *iter)
 }
 
 static void
+notify_invalid_height (gpointer         width_ptr,
+		       CachedSize      *size,
+		       GtkCellAreaIter *iter)
+{
+  gint width = GPOINTER_TO_INT (width_ptr);
+
+  /* Notify size invalidated */
+  g_signal_emit (iter, cell_area_iter_signals[SIGNAL_HEIGHT_CHANGED], 
+		 0, width, -1, -1);
+}
+
+static void
 gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter,
 							  gint             width)
 {
@@ -326,11 +338,18 @@ gtk_cell_area_iter_real_flush_preferred_height_for_width (GtkCellAreaIter *iter,
 
   /* Flush all sizes for special -1 value */
   if (width < 0)
-    g_hash_table_remove_all (priv->heights);
+    {
+      g_hash_table_foreach (priv->heights, (GHFunc)notify_invalid_height, iter);
+      g_hash_table_remove_all (priv->heights);
+    }
   else
-    g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
+    {
+      g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
 
-  /* XXX Should we bother signalling removed values as "size-changed" signals ? */
+      /* Notify size invalidated */
+      g_signal_emit (iter, cell_area_iter_signals[SIGNAL_HEIGHT_CHANGED], 
+		     0, width, -1, -1);
+    }
 }
 
 static void
@@ -348,6 +367,18 @@ gtk_cell_area_iter_real_flush_preferred_height (GtkCellAreaIter *iter)
 }
 
 static void
+notify_invalid_width (gpointer         height_ptr,
+		      CachedSize      *size,
+		      GtkCellAreaIter *iter)
+{
+  gint height = GPOINTER_TO_INT (height_ptr);
+
+  /* Notify size invalidated */
+  g_signal_emit (iter, cell_area_iter_signals[SIGNAL_WIDTH_CHANGED], 
+		 0, height, -1, -1);
+}
+
+static void
 gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter,
 							  gint             height)
 {
@@ -355,11 +386,18 @@ gtk_cell_area_iter_real_flush_preferred_width_for_height (GtkCellAreaIter *iter,
 
   /* Flush all sizes for special -1 value */
   if (height < 0)
-    g_hash_table_remove_all (priv->widths);
+    {
+      g_hash_table_foreach (priv->widths, (GHFunc)notify_invalid_width, iter);
+      g_hash_table_remove_all (priv->widths);
+    }
   else
-    g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
+    {
+      g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
 
-  /* XXX Should we bother signalling removed values as "size-changed" signals ? */
+      /* Notify size invalidated */
+      g_signal_emit (iter, cell_area_iter_signals[SIGNAL_WIDTH_CHANGED], 
+		     0, height, -1, -1);
+    }
 }
 
 /*************************************************************



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