[gtk+/icon-view-refactor] Added apis to GtkCellArea for GtkIconView purposes.



commit 8eec3b8bdd34ee6d372729d6daa39992852717c6
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Mon Dec 13 00:18:00 2010 +0900

    Added apis to GtkCellArea for GtkIconView purposes.
    
    Added a few apis,
    
      - GtkCellAreaContext get_preferred_height_for_width &
        width for height apis and vfuncs, this lets the icon view
        request the collective (and aligned) height for width for
        a said row.
    
      - gtk_cell_area_copy_context() this creates a duplicate of
        an already created and requested context, this way the icon
        view uses a global context to request the widths of all rows
        and then makes a copy with all the stored alignments and
        uses a separate copy to calculate the height and alignments
        of each row separately.

 gtk/gtkcellarea.c           |   40 ++++++++++++++
 gtk/gtkcellarea.h           |    4 ++
 gtk/gtkcellareabox.c        |   20 +++++++
 gtk/gtkcellareaboxcontext.c |  127 +++++++++++++++++++++++++++++++++++++++----
 gtk/gtkcellareaboxcontext.h |    4 ++
 gtk/gtkcellareacontext.c    |   60 ++++++++++++++++++++
 gtk/gtkcellareacontext.h    |   52 ++++++++++++------
 7 files changed, 277 insertions(+), 30 deletions(-)
---
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index c21fdcd..59a1d01 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -1924,6 +1924,46 @@ gtk_cell_area_create_context (GtkCellArea *area)
   return NULL;
 }
 
+/**
+ * gtk_cell_area_copy_context:
+ * @area: a #GtkCellArea
+ * @context: the #GtkCellAreaContext to copy
+ *
+ * This is sometimes needed for cases where rows need to share
+ * alignments in one orientation but may be separately grouped
+ * in the opposing orientation.
+ *
+ * For instance, #GtkIconView creates all icons (rows) to have
+ * the same width and the cells theirin to have the same
+ * horizontal alignments. However each row of icons may have
+ * a separate collective height. #GtkIconView uses this to
+ * request the heights of each row based on a context which
+ * was already used to request all the row widths that are
+ * to be displayed.
+ *
+ * Return value: (transfer full): a newly created #GtkCellAreaContext copy of @context.
+ *
+ * Since: 3.0
+ */
+GtkCellAreaContext *
+gtk_cell_area_copy_context (GtkCellArea        *area,
+			    GtkCellAreaContext *context)
+{
+  GtkCellAreaClass *class;
+
+  g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL);
+  g_return_val_if_fail (GTK_IS_CELL_AREA_CONTEXT (context), NULL);
+
+  class = GTK_CELL_AREA_GET_CLASS (area);
+
+  if (class->copy_context)
+    return class->copy_context (area, context);
+
+  g_warning ("GtkCellAreaClass::copy_context not implemented for `%s'", 
+	     g_type_name (G_TYPE_FROM_INSTANCE (area)));
+  
+  return NULL;
+}
 
 /**
  * gtk_cell_area_get_request_mode:
diff --git a/gtk/gtkcellarea.h b/gtk/gtkcellarea.h
index 8c54b05..6157922 100644
--- a/gtk/gtkcellarea.h
+++ b/gtk/gtkcellarea.h
@@ -202,6 +202,8 @@ struct _GtkCellAreaClass
 
   /* Geometry */
   GtkCellAreaContext *(* create_context)                 (GtkCellArea             *area);
+  GtkCellAreaContext *(* copy_context)                   (GtkCellArea             *area,
+							  GtkCellAreaContext      *context);
   GtkSizeRequestMode (* get_request_mode)                (GtkCellArea             *area);
   void               (* get_preferred_width)             (GtkCellArea             *area,
 							  GtkCellAreaContext      *context,
@@ -316,6 +318,8 @@ GtkCellRenderer      *gtk_cell_area_get_cell_at_position           (GtkCellArea
 
 /* Geometry */
 GtkCellAreaContext   *gtk_cell_area_create_context                 (GtkCellArea        *area);
+GtkCellAreaContext   *gtk_cell_area_copy_context                   (GtkCellArea        *area,
+								    GtkCellAreaContext *context);
 GtkSizeRequestMode    gtk_cell_area_get_request_mode               (GtkCellArea        *area);
 void                  gtk_cell_area_get_preferred_width            (GtkCellArea        *area,
 								    GtkCellAreaContext *context,
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index 286c670..56a856b 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -92,6 +92,8 @@ static void      gtk_cell_area_box_get_cell_property              (GtkCellArea
 								   GValue               *value,
 								   GParamSpec           *pspec);
 static GtkCellAreaContext *gtk_cell_area_box_create_context       (GtkCellArea          *area);
+static GtkCellAreaContext *gtk_cell_area_box_copy_context         (GtkCellArea          *area,
+								   GtkCellAreaContext   *context);
 static GtkSizeRequestMode  gtk_cell_area_box_get_request_mode     (GtkCellArea          *area);
 static void      gtk_cell_area_box_get_preferred_width            (GtkCellArea          *area,
 								   GtkCellAreaContext   *context,
@@ -273,6 +275,7 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
   area_class->get_cell_property   = gtk_cell_area_box_get_cell_property;
   
   area_class->create_context                 = gtk_cell_area_box_create_context;
+  area_class->copy_context                   = gtk_cell_area_box_copy_context;
   area_class->get_request_mode               = gtk_cell_area_box_get_request_mode;
   area_class->get_preferred_width            = gtk_cell_area_box_get_preferred_width;
   area_class->get_preferred_height           = gtk_cell_area_box_get_preferred_height;
@@ -1301,6 +1304,23 @@ gtk_cell_area_box_create_context (GtkCellArea *area)
   return context;
 }
 
+static GtkCellAreaContext *
+gtk_cell_area_box_copy_context (GtkCellArea        *area,
+				GtkCellAreaContext *context)
+{
+  GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
+  GtkCellAreaBoxPrivate *priv = box->priv;
+  GtkCellAreaContext    *copy = 
+    (GtkCellAreaContext *)gtk_cell_area_box_context_copy (GTK_CELL_AREA_BOX (area), 
+							  GTK_CELL_AREA_BOX_CONTEXT (context));
+
+  priv->contexts = g_slist_prepend (priv->contexts, copy);
+
+  g_object_weak_ref (G_OBJECT (copy), (GWeakNotify)context_weak_notify, box);
+
+  return copy;
+}
+
 static GtkSizeRequestMode 
 gtk_cell_area_box_get_request_mode (GtkCellArea *area)
 {
diff --git a/gtk/gtkcellareaboxcontext.c b/gtk/gtkcellareaboxcontext.c
index cc4c0b4..fbf6ffe 100644
--- a/gtk/gtkcellareaboxcontext.c
+++ b/gtk/gtkcellareaboxcontext.c
@@ -35,10 +35,23 @@ static void      gtk_cell_area_box_context_reset                 (GtkCellAreaCon
 static void      gtk_cell_area_box_context_allocate              (GtkCellAreaContext    *context,
 								  gint                   width,
 								  gint                   height);
+static void      gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+									   gint                width,
+									   gint               *minimum_height,
+									   gint               *natural_height);
+static void      gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+									   gint                height,
+									   gint               *minimum_width,
+									   gint               *natural_width);
+
+
 
 /* Internal functions */
-static void      gtk_cell_area_box_context_sum                   (GtkCellAreaBoxContext *context,
-								  GtkOrientation         orientation);
+static void      gtk_cell_area_box_context_sum                  (GtkCellAreaBoxContext  *context,
+								 GtkOrientation          orientation,
+								 gint                    for_size,
+								 gint                   *minimum_size,
+								 gint                   *natural_size);
 static void      free_cache_array                                (GArray                *array);
 static GArray   *group_array_new                                 (GtkCellAreaBoxContext *context);
 static GArray   *get_array                                       (GtkCellAreaBoxContext *context,
@@ -190,8 +203,10 @@ gtk_cell_area_box_context_class_init (GtkCellAreaBoxContextClass *class)
   /* GObjectClass */
   object_class->finalize = gtk_cell_area_box_context_finalize;
 
-  context_class->reset     = gtk_cell_area_box_context_reset;
-  context_class->allocate  = gtk_cell_area_box_context_allocate;
+  context_class->reset                          = gtk_cell_area_box_context_reset;
+  context_class->allocate                       = gtk_cell_area_box_context_allocate;
+  context_class->get_preferred_height_for_width = gtk_cell_area_box_context_get_preferred_height_for_width;
+  context_class->get_preferred_width_for_height = gtk_cell_area_box_context_get_preferred_width_for_height;
 
   g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxContextPrivate));
 }
@@ -402,7 +417,10 @@ gtk_cell_area_box_context_allocate (GtkCellAreaContext *context,
 
 static void
 gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
-			       GtkOrientation         orientation)
+			       GtkOrientation         orientation,
+			       gint                   for_size,
+			       gint                  *minimum_size,
+			       gint                  *natural_size)
 {
   GtkCellArea    *area;
   GtkOrientation  box_orientation;
@@ -413,7 +431,7 @@ gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
   area            = gtk_cell_area_context_get_area (GTK_CELL_AREA_CONTEXT (context));
   spacing         = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
   box_orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
-  array           = get_array (context, orientation, -1);
+  array           = get_array (context, orientation, for_size);
 
   for (i = 0; i < array->len; i++)
     {
@@ -440,15 +458,100 @@ gtk_cell_area_box_context_sum (GtkCellAreaBoxContext *context,
 	}
     }
 
-  if (orientation == GTK_ORIENTATION_HORIZONTAL)
-    gtk_cell_area_context_push_preferred_width (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
-  else
-    gtk_cell_area_context_push_preferred_height (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
+  if (for_size < 0)
+    {
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+	gtk_cell_area_context_push_preferred_width (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
+      else
+	gtk_cell_area_context_push_preferred_height (GTK_CELL_AREA_CONTEXT (context), min_size, nat_size);
+    }
+
+  if (minimum_size)
+    *minimum_size = min_size;
+  if (natural_size)
+    *natural_size = nat_size;
+}
+
+static void
+gtk_cell_area_box_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+							  gint                width,
+							  gint               *minimum_height,
+							  gint               *natural_height)
+{
+  gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_VERTICAL, 
+				 width, minimum_height, natural_height);
+}
+
+static void
+gtk_cell_area_box_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+							  gint                height,
+							  gint               *minimum_width,
+							  gint               *natural_width)
+{
+  gtk_cell_area_box_context_sum (GTK_CELL_AREA_BOX_CONTEXT (context), GTK_ORIENTATION_HORIZONTAL, 
+				 height, minimum_width, natural_width);
 }
 
 /*************************************************************
  *                            API                            *
  *************************************************************/
+static void
+copy_size_array (GArray *src_array,
+		 GArray *dest_array)
+{
+  gint i;
+
+  for (i = 0; i < src_array->len; i++)
+    {
+      CachedSize *src  = &g_array_index (src_array, CachedSize, i);
+      CachedSize *dest = &g_array_index (dest_array, CachedSize, i);
+
+      memcpy (dest, src, sizeof (CachedSize));
+    }
+}
+
+static void
+for_size_copy (gpointer    key,
+	       GArray     *size_array,
+	       GHashTable *dest_hash)
+{
+  GArray *new_array;
+
+  new_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+  g_array_set_size (new_array, size_array->len);
+
+  copy_size_array (size_array, new_array);
+
+  g_hash_table_insert (dest_hash, key, new_array);
+}
+
+GtkCellAreaBoxContext *
+gtk_cell_area_box_context_copy (GtkCellAreaBox        *box,
+				GtkCellAreaBoxContext *box_context)
+{
+  GtkCellAreaBoxContext *context;
+
+  context = g_object_new (GTK_TYPE_CELL_AREA_BOX_CONTEXT, 
+			  "area", box, NULL);
+
+  gtk_cell_area_box_init_groups (context, 
+				 box_context->priv->base_widths->len,
+				 box_context->priv->expand);
+
+  /* Copy all the arrays */
+  copy_size_array (box_context->priv->base_widths, 
+		   context->priv->base_widths);
+  copy_size_array (box_context->priv->base_heights, 
+		   context->priv->base_heights);
+
+  g_hash_table_foreach (box_context->priv->heights,
+			(GHFunc)for_size_copy, context->priv->heights);
+  g_hash_table_foreach (box_context->priv->widths,
+			(GHFunc)for_size_copy, context->priv->widths);
+
+  return context;
+}
+
 void
 gtk_cell_area_box_init_groups (GtkCellAreaBoxContext *box_context,
 			       guint                  n_groups,
@@ -500,7 +603,7 @@ gtk_cell_area_box_context_push_group_width (GtkCellAreaBoxContext *box_context,
     }
 
   if (grew)
-    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_HORIZONTAL);
+    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_HORIZONTAL, -1, NULL, NULL);
 }
 
 void
@@ -559,7 +662,7 @@ gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
     }
 
   if (grew)
-    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_VERTICAL);
+    gtk_cell_area_box_context_sum (box_context, GTK_ORIENTATION_VERTICAL, -1, NULL, NULL);
 }
 
 void
diff --git a/gtk/gtkcellareaboxcontext.h b/gtk/gtkcellareaboxcontext.h
index 7800b0f..1161d38 100644
--- a/gtk/gtkcellareaboxcontext.h
+++ b/gtk/gtkcellareaboxcontext.h
@@ -62,6 +62,10 @@ struct _GtkCellAreaBoxContextClass
 GType   gtk_cell_area_box_context_get_type                     (void) G_GNUC_CONST;
 
 
+/* Create a duplicate of the context */
+GtkCellAreaBoxContext *gtk_cell_area_box_context_copy          (GtkCellAreaBox        *box,
+								GtkCellAreaBoxContext *box_context);
+
 /* Initialize group array dimensions */
 void    gtk_cell_area_box_init_groups                          (GtkCellAreaBoxContext *box_context,
 								guint                  n_groups,
diff --git a/gtk/gtkcellareacontext.c b/gtk/gtkcellareacontext.c
index 087b590..f3c14b0 100644
--- a/gtk/gtkcellareacontext.c
+++ b/gtk/gtkcellareacontext.c
@@ -490,6 +490,66 @@ gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
 }
 
 /**
+ * gtk_cell_area_context_get_preferred_height_for_width:
+ * @context: a #GtkCellAreaContext
+ * @width: a proposed width for allocation
+ * @minimum_height: (out) (allow-none): location to store the minimum height, or %NULL
+ * @natural_height: (out) (allow-none): location to store the natural height, or %NULL
+ *
+ * Gets the accumulative preferred height for @width for all rows which have been 
+ * requested for the same said @width with this context.
+ *
+ * After gtk_cell_area_context_reset() is called and/or before ever requesting
+ * the size of a #GtkCellArea, the returned values are -1.
+ *
+ * Since: 3.0
+ */
+void
+gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+						      gint                width,
+						      gint               *minimum_height,
+						      gint               *natural_height)
+{
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width)
+    GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_height_for_width (context,
+									       width,
+									       minimum_height,
+									       natural_height);
+}
+
+/**
+ * gtk_cell_area_context_get_preferred_width_for_height:
+ * @context: a #GtkCellAreaContext
+ * @height: a proposed height for allocation
+ * @minimum_width: (out) (allow-none): location to store the minimum width, or %NULL
+ * @natural_width: (out) (allow-none): location to store the natural width, or %NULL
+ *
+ * Gets the accumulative preferred width for @height for all rows which have 
+ * been requested for the same said @height with this context.
+ *
+ * After gtk_cell_area_context_reset() is called and/or before ever requesting
+ * the size of a #GtkCellArea, the returned values are -1.
+ *
+ * Since: 3.0 
+ */
+void
+gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+						      gint                height,
+						      gint               *minimum_width,
+						      gint               *natural_width)
+{  
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  if (GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height)
+    GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->get_preferred_width_for_height (context,
+									       height,
+									       minimum_width,
+									       natural_width);
+}
+
+/**
  * gtk_cell_area_context_get_allocation:
  * @context: a #GtkCellAreaContext
  * @width: (out) (allow-none): location to store the allocated width, or %NULL.
diff --git a/gtk/gtkcellareacontext.h b/gtk/gtkcellareacontext.h
index 2731a73..d2b462c 100644
--- a/gtk/gtkcellareacontext.h
+++ b/gtk/gtkcellareacontext.h
@@ -65,10 +65,18 @@ struct _GtkCellAreaContextClass
   GObjectClass parent_class;
 
   /*< public >*/
-  void    (* allocate)               (GtkCellAreaContext *context,
-				      gint                width,
-				      gint                height);
-  void    (* reset)                  (GtkCellAreaContext *context);
+  void    (* allocate)                       (GtkCellAreaContext *context,
+					      gint                width,
+					      gint                height);
+  void    (* reset)                          (GtkCellAreaContext *context);
+  void    (* get_preferred_height_for_width) (GtkCellAreaContext *context,
+					      gint                width,
+					      gint               *minimum_height,
+					      gint               *natural_height);
+  void    (* get_preferred_width_for_height) (GtkCellAreaContext *context,
+					      gint                height,
+					      gint               *minimum_width,
+					      gint               *natural_width);
 
   /*< private >*/
   /* Padding for future expansion */
@@ -81,22 +89,30 @@ struct _GtkCellAreaContextClass
 GType        gtk_cell_area_context_get_type              (void) G_GNUC_CONST;
 
 /* Main apis */
-GtkCellArea *gtk_cell_area_context_get_area              (GtkCellAreaContext *context);
-void         gtk_cell_area_context_allocate              (GtkCellAreaContext *context,
-							  gint                width,
-							  gint                height);
-void         gtk_cell_area_context_reset                 (GtkCellAreaContext *context);
+GtkCellArea *gtk_cell_area_context_get_area                        (GtkCellAreaContext *context);
+void         gtk_cell_area_context_allocate                        (GtkCellAreaContext *context,
+								    gint                width,
+								    gint                height);
+void         gtk_cell_area_context_reset                           (GtkCellAreaContext *context);
 
 /* Apis for GtkCellArea clients to consult cached values for a series of GtkTreeModel rows */
-void         gtk_cell_area_context_get_preferred_width   (GtkCellAreaContext *context,
-							  gint               *minimum_width,
-							  gint               *natural_width);
-void         gtk_cell_area_context_get_preferred_height  (GtkCellAreaContext *context,
-							  gint               *minimum_height,
-							  gint               *natural_height);
-void         gtk_cell_area_context_get_allocation        (GtkCellAreaContext *context,
-							  gint               *width,
-							  gint               *height);
+void         gtk_cell_area_context_get_preferred_width            (GtkCellAreaContext *context,
+								   gint               *minimum_width,
+								   gint               *natural_width);
+void         gtk_cell_area_context_get_preferred_height           (GtkCellAreaContext *context,
+								   gint               *minimum_height,
+								   gint               *natural_height);
+void         gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+								   gint                width,
+								   gint               *minimum_height,
+								   gint               *natural_height);
+void         gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+								   gint                height,
+								   gint               *minimum_width,
+								   gint               *natural_width);
+void         gtk_cell_area_context_get_allocation                 (GtkCellAreaContext *context,
+								   gint               *width,
+								   gint               *height);
 
 /* Apis for GtkCellArea implementations to update cached values for multiple GtkTreeModel rows */
 void         gtk_cell_area_context_push_preferred_width  (GtkCellAreaContext *context,



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