[gtk+/native-layout] Fixed GtkExtendedLayout interaction with sizegroups plus cleanups



commit 9247bc8d6dae3b9d2b4a46338f5b1303862bfa78
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Sat Apr 17 01:51:10 2010 -0400

    Fixed GtkExtendedLayout interaction with sizegroups plus cleanups
    
    Fixed GtkExtendedLayout to interact with sizegroups, "size-requsts"
    and caching the values all in the same code segment.
    
    Migrated the cache code to be internal to gtkextendedlayout.c

 gtk/gtkextendedlayout.c |  444 ++++++++++++++++++++---------------------------
 gtk/gtkwidget.h         |   17 --
 2 files changed, 192 insertions(+), 269 deletions(-)
---
diff --git a/gtk/gtkextendedlayout.c b/gtk/gtkextendedlayout.c
index dcc3e6c..0ca1658 100644
--- a/gtk/gtkextendedlayout.c
+++ b/gtk/gtkextendedlayout.c
@@ -31,6 +31,28 @@
 
 #define DEBUG_EXTENDED_LAYOUT 0
 
+/* With extended layout, a widget may be requested
+ * its width for 2 or 3 heights in one resize
+ */
+#define N_CACHED_SIZES 3
+
+typedef struct 
+{
+  guint  age;
+  gint   for_size;
+  gint   minimum_size;
+  gint   natural_size;
+} DesiredSize;
+
+typedef struct {
+  DesiredSize desired_widths[N_CACHED_SIZES];
+  DesiredSize desired_heights[N_CACHED_SIZES];
+  guint cached_width_age;
+  guint cached_height_age;
+} ExtendedLayoutCache;
+
+static GQuark quark_cache = 0;
+
 
 GType
 gtk_extended_layout_get_type (void)
@@ -45,28 +67,27 @@ gtk_extended_layout_get_type (void)
 				       NULL, 0, NULL, 0);
 
       g_type_interface_add_prerequisite (extended_layout_type, GTK_TYPE_WIDGET);
+
+      quark_cache = g_quark_from_static_string ("gtk-extended-layout-cache");
     }
 
   return extended_layout_type;
 }
 
-
-
-
 /* looks for a cached size request for this for_size. If not
  * found, returns the oldest entry so it can be overwritten */
 static gboolean
-_gtk_extended_layout_get_cached_desired_size (gfloat            for_size,
-					      GtkDesiredSize   *cached_sizes,
-					      GtkDesiredSize  **result)
+get_cached_desired_size (gfloat         for_size,
+			 DesiredSize   *cached_sizes,
+			 DesiredSize  **result)
 {
   guint i;
 
   *result = &cached_sizes[0];
 
-  for (i = 0; i < GTK_N_CACHED_SIZES; i++)
+  for (i = 0; i < N_CACHED_SIZES; i++)
     {
-      GtkDesiredSize *cs;
+      DesiredSize *cs;
 
       cs = &cached_sizes[i];
 
@@ -85,6 +106,165 @@ _gtk_extended_layout_get_cached_desired_size (gfloat            for_size,
   return FALSE;
 }
 
+static void 
+destroy_cache (ExtendedLayoutCache *cache)
+{
+  g_slice_free (ExtendedLayoutCache, cache);
+}
+
+ExtendedLayoutCache *
+get_cache (GtkExtendedLayout *layout, gboolean create)
+{
+  ExtendedLayoutCache *cache;
+  
+  cache = g_object_get_qdata (G_OBJECT (layout), quark_cache);
+  if (!cache && create)
+    {
+      cache = g_slice_new0 (ExtendedLayoutCache);
+
+      cache->cached_width_age  = 1;
+      cache->cached_height_age = 1;
+
+      g_object_set_qdata_full (G_OBJECT (layout), quark_cache, cache, 
+			       (GDestroyNotify)destroy_cache);
+    }
+  
+  return cache;
+}
+
+static void
+do_size_request (GtkWidget *widget)
+{
+  if (GTK_WIDGET_REQUEST_NEEDED (widget))
+    {
+      gtk_widget_ensure_style (widget);      
+      GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
+      g_signal_emit_by_name (widget,
+			     "size-request",
+			     &widget->requisition);
+    }
+}
+
+static void
+compute_size_for_orientation (GtkExtendedLayout *layout,
+			      GtkSizeGroupMode   orientation,
+			      gint               for_size,
+			      gint              *minimum_size,
+			      gint              *natural_size)
+{
+  ExtendedLayoutCache *cache;
+  DesiredSize         *cached_size;
+  GtkWidget           *widget;
+  gboolean             found_in_cache = FALSE;
+
+  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
+  g_return_if_fail (minimum_size != NULL || natural_size != NULL);
+
+  widget = GTK_WIDGET (layout);
+  cache  = get_cache (layout, TRUE);
+
+  if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
+    {
+      cached_size = &cache->desired_widths[0];
+      
+      if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
+	found_in_cache = get_cached_desired_size (for_size, cache->desired_widths, &cached_size);
+    }
+  else
+    {
+      cached_size = &cache->desired_heights[0];
+      
+      if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
+	found_in_cache = get_cached_desired_size (for_size, cache->desired_heights, &cached_size);
+    }
+    
+  if (!found_in_cache)
+    {
+      gint min_size = 0, nat_size = 0;
+      gint group_size, requisition_size;
+
+      /* Unconditional size request runs but is often unhandled. */
+      do_size_request (widget);
+
+      if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
+	{
+	  requisition_size = widget->requisition.width;
+
+	  if (for_size < 0)
+	    GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->
+	      get_desired_width (layout, &min_size, &nat_size);
+	  else
+	    GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->
+	      get_width_for_height (layout, for_size, &min_size, &nat_size);
+	}
+      else
+	{
+	  requisition_size = widget->requisition.height;
+
+	  if (for_size < 0)
+	      GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->
+		get_desired_height (layout, &min_size, &nat_size);
+	  else
+	    GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->
+	      get_height_for_width (layout, for_size, &min_size, &nat_size);
+	}
+
+      /* Support for dangling "size-request" signals and forward derived
+       * classes that will not default to a ->get_desired_width() that
+       * returns the values in the ->requisition cache.
+       */
+      min_size = MAX (min_size, requisition_size);
+      nat_size = MAX (nat_size, requisition_size);
+
+      cached_size->minimum_size = min_size;
+      cached_size->natural_size = nat_size;
+      cached_size->for_size     = for_size;
+
+      if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
+	{
+	  cached_size->age = cache->cached_width_age;
+	  cache->cached_width_age++;
+
+	  GTK_PRIVATE_UNSET_FLAG (layout, GTK_WIDTH_REQUEST_NEEDED);
+	}
+      else
+	{
+	  cached_size->age = cache->cached_height_age;
+	  cache->cached_height_age++;
+
+	  GTK_PRIVATE_UNSET_FLAG (layout, GTK_HEIGHT_REQUEST_NEEDED);
+	}
+
+      /* Get size groups to compute the base requisition once one of the values have been cached,
+       * then go ahead and update the cache with the sizegroup computed value.
+       */
+      group_size = 
+	_gtk_size_group_bump_requisition (GTK_WIDGET (layout), 
+					  orientation, cached_size->minimum_size);
+      cached_size->minimum_size = MAX (cached_size->minimum_size, group_size);
+      cached_size->natural_size = MAX (cached_size->natural_size, group_size);
+    }
+
+  /* Output the MAX()s of the cached size and the size computed by GtkSizeGroup. */
+  if (minimum_size)
+    *minimum_size = cached_size->minimum_size;
+  
+  if (natural_size)
+    *natural_size = cached_size->natural_size;
+
+  g_assert (cached_size->minimum_size <= cached_size->natural_size);
+
+#if DEBUG_EXTENDED_LAYOUT
+  g_message ("%s size for orientation %s: %d is minimum %d and natural: %d",
+	     G_OBJECT_TYPE_NAME (layout), 
+	     orientation == GTK_SIZE_GROUP_HORIZONTAL ? "horizontal" : "vertical",
+	     height,
+	     cached_size->minimum_size,
+	     cached_size->natural_size);
+#endif
+
+}
+
 /**
  * gtk_extended_layout_is_height_for_width:
  * @layout: a #GtkExtendedLayout instance
@@ -127,66 +307,7 @@ gtk_extended_layout_get_desired_width (GtkExtendedLayout *layout,
 				       gint              *minimum_width,
 				       gint              *natural_width)
 {
-  GtkWidgetAuxInfo       *aux_info;
-  gboolean                found_in_cache = FALSE;
-  GtkDesiredSize         *cached_size;
-
-  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
-  g_return_if_fail (minimum_width != NULL || natural_width != NULL);
-
-  aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
-
-  cached_size = &aux_info->desired_widths[0];
-
-  if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
-    found_in_cache = _gtk_extended_layout_get_cached_desired_size (-1, aux_info->desired_widths, 
-								   &cached_size);
-
-  if (!found_in_cache)
-    {
-      GtkRequisition requisition;
-      gint minimum_width = 0, natural_width = 0;
-
-      /* Unconditionally envoke size-request and use those return values as 
-       * the base end of our values */
-      _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
-
-      /* Envoke this after, default GtkWidgetClass will simply copy over widget->requisition
-       */
-      GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_width (layout, 
-								 &minimum_width, 
-								 &natural_width);
-
-      minimum_width = MAX (minimum_width, requisition.width);
-      natural_width = MAX (natural_width, requisition.width);
-
-      /* XXX Possibly we should update this with minimum values instead */
-      _gtk_size_group_bump_requisition (GTK_WIDGET (layout), GTK_SIZE_GROUP_HORIZONTAL, natural_width);
-
-      cached_size->minimum_size = minimum_width;
-      cached_size->natural_size = natural_width;
-      cached_size->for_size     = -1;
-      cached_size->age          = aux_info->cached_width_age;
-
-      aux_info->cached_width_age ++;
-
-      GTK_PRIVATE_UNSET_FLAG (layout, GTK_WIDTH_REQUEST_NEEDED);
-    }
-
-  if (minimum_width)
-    *minimum_width = cached_size->minimum_size;
-
-  if (natural_width)
-    *natural_width = cached_size->natural_size;
-
-  g_assert (!minimum_width || !natural_width || *minimum_width <= *natural_width);
-
-#if DEBUG_EXTENDED_LAYOUT
-  g_message ("%s returning minimum width: %d and natural width: %d",
-	     G_OBJECT_TYPE_NAME (layout), 
-	     cached_size->minimum_size,
-	     cached_size->natural_size);
-#endif
+  compute_size_for_orientation (layout, GTK_SIZE_GROUP_HORIZONTAL, -1, minimum_width, natural_width);
 }
 
 
@@ -205,66 +326,7 @@ gtk_extended_layout_get_desired_height (GtkExtendedLayout *layout,
 					gint              *minimum_height,
 					gint              *natural_height)
 {
-  GtkWidgetAuxInfo       *aux_info;
-  gboolean                found_in_cache = FALSE;
-  GtkDesiredSize         *cached_size;
-
-  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
-  g_return_if_fail (minimum_height != NULL || natural_height != NULL);
-
-  aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
-
-  cached_size = &aux_info->desired_heights[0];
-
-  if (GTK_WIDGET_HEIGHT_REQUEST_NEEDED (layout) == FALSE)
-    found_in_cache = _gtk_extended_layout_get_cached_desired_size (-1, aux_info->desired_heights, 
-								   &cached_size);
-
-  if (!found_in_cache)
-    {
-      GtkRequisition requisition;
-      gint minimum_height = 0, natural_height = 0;
-
-      /* Unconditionally envoke size-request and use those return values as 
-       * the base end of our values */
-      _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
-
-      /* Envoke this after, default GtkWidgetClass will simply copy over widget->requisition
-       */
-      GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_desired_height (layout, 
-								  &minimum_height, 
-								  &natural_height);
-
-      minimum_height = MAX (minimum_height, requisition.height);
-      natural_height = MAX (natural_height, requisition.height);
-
-      /* XXX Possibly we should update this with minimum values instead */
-      _gtk_size_group_bump_requisition (GTK_WIDGET (layout), GTK_SIZE_GROUP_VERTICAL, natural_height);
-
-      cached_size->minimum_size = minimum_height;
-      cached_size->natural_size = natural_height;
-      cached_size->for_size     = -1;
-      cached_size->age          = aux_info->cached_height_age;
-
-      aux_info->cached_height_age ++;
-
-      GTK_PRIVATE_UNSET_FLAG (layout, GTK_HEIGHT_REQUEST_NEEDED);
-    }
-
-  if (minimum_height)
-    *minimum_height = cached_size->minimum_size;
-
-  if (natural_height)
-    *natural_height = cached_size->natural_size;
-
-  g_assert (!minimum_height || !natural_height || *minimum_height <= *natural_height);
-
-#if DEBUG_EXTENDED_LAYOUT
-  g_message ("%s returning minimum height: %d and natural height: %d",
-	     G_OBJECT_TYPE_NAME (layout), 
-	     cached_size->minimum_size,
-	     cached_size->natural_size);
-#endif
+  compute_size_for_orientation (layout, GTK_SIZE_GROUP_VERTICAL, -1, minimum_height, natural_height);
 }
 
 
@@ -287,67 +349,7 @@ gtk_extended_layout_get_width_for_height (GtkExtendedLayout *layout,
                                           gint              *minimum_width,
                                           gint              *natural_width)
 {
-  GtkWidgetAuxInfo       *aux_info;
-  gboolean                found_in_cache = FALSE;
-  GtkDesiredSize         *cached_size;
-
-  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
-  g_return_if_fail (minimum_width != NULL || natural_width != NULL);
-
-  aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
-
-  cached_size = &aux_info->desired_widths[0];
-
-  if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
-    found_in_cache = _gtk_extended_layout_get_cached_desired_size (height, aux_info->desired_widths, 
-								   &cached_size);
-
-  if (!found_in_cache)
-    {
-      GtkRequisition requisition;
-      gint minimum_width = 0, natural_width = 0;
-
-      /* Unconditionally envoke size-request and use those return values as 
-       * the base end of our values */
-      _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
-
-      GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_width_for_height (layout, 
-								    height,
-								    &minimum_width, 
-								    &natural_width);
-
-      minimum_width = MAX (minimum_width, requisition.width);
-      natural_width = MAX (natural_width, requisition.width);
-
-      /* XXX Possibly we should update this with minimum values instead */
-      _gtk_size_group_bump_requisition (GTK_WIDGET (layout), GTK_SIZE_GROUP_HORIZONTAL, natural_width);
-      
-      cached_size->minimum_size = minimum_width;
-      cached_size->natural_size = natural_width;
-      cached_size->for_size     = height;
-      cached_size->age          = aux_info->cached_width_age;
-
-      aux_info->cached_width_age++;
-
-      GTK_PRIVATE_UNSET_FLAG (layout, GTK_WIDTH_REQUEST_NEEDED);
-    }
-
-
-  if (minimum_width)
-    *minimum_width = cached_size->minimum_size;
-
-  if (natural_width)
-    *natural_width = cached_size->natural_size;
-
-  g_assert (!minimum_width || !natural_width || *minimum_width <= *natural_width);
-
-#if DEBUG_EXTENDED_LAYOUT
-  g_message ("%s width for height: %d is minimum %d and natural: %d",
-	     G_OBJECT_TYPE_NAME (layout), height,
-	     cached_size->minimum_size,
-	     cached_size->natural_size);
-#endif
-
+  compute_size_for_orientation (layout, GTK_SIZE_GROUP_HORIZONTAL, height, minimum_width, natural_width);
 }
 
 /**
@@ -368,71 +370,9 @@ gtk_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
                                           gint              *minimum_height,
                                           gint              *natural_height)
 {
-  GtkWidgetAuxInfo       *aux_info;
-  gboolean                found_in_cache = FALSE;
-  GtkDesiredSize         *cached_size;
-
-  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
-  g_return_if_fail (minimum_height != NULL || natural_height != NULL);
-
-  aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), TRUE);
-
-  cached_size = &aux_info->desired_heights[0];
-
-  if (GTK_WIDGET_HEIGHT_REQUEST_NEEDED (layout) == FALSE)
-    found_in_cache = _gtk_extended_layout_get_cached_desired_size (width, aux_info->desired_heights, 
-								   &cached_size);
-
-  if (!found_in_cache)
-    {
-      GtkRequisition requisition;
-      gint minimum_height = 0, natural_height = 0;
-
-      /* Unconditionally envoke size-request and use those return values as 
-       * the base end of our values */
-      _gtk_size_group_compute_requisition (GTK_WIDGET (layout), &requisition);
-
-      GTK_EXTENDED_LAYOUT_GET_IFACE (layout)->get_height_for_width (layout, 
-								    width,
-								    &minimum_height, 
-								    &natural_height);
-
-      minimum_height = MAX (minimum_height, requisition.height);
-      natural_height = MAX (natural_height, requisition.height);
-
-      /* XXX Possibly we should update this with minimum values instead */
-      _gtk_size_group_bump_requisition (GTK_WIDGET (layout), GTK_SIZE_GROUP_VERTICAL, natural_height);
-
-      cached_size->minimum_size = minimum_height;
-      cached_size->natural_size = natural_height;
-      cached_size->for_size     = width;
-      cached_size->age          = aux_info->cached_height_age;
-
-      aux_info->cached_height_age++;
-
-      GTK_PRIVATE_UNSET_FLAG (layout, GTK_HEIGHT_REQUEST_NEEDED);
-    }
-
-
-  if (minimum_height)
-    *minimum_height = cached_size->minimum_size;
-
-  if (natural_height)
-    *natural_height = cached_size->natural_size;
-
-  g_assert (!minimum_height || !natural_height || *minimum_height <= *natural_height);
-
-#if DEBUG_EXTENDED_LAYOUT
-  g_message ("%s height for width: %d is minimum %d and natural: %d",
-	     G_OBJECT_TYPE_NAME (layout), width,
-	     cached_size->minimum_size,
-	     cached_size->natural_size);
-#endif
+  compute_size_for_orientation (layout, GTK_SIZE_GROUP_VERTICAL, width, minimum_height, natural_height);
 }
 
-
-
-
 /**
  * gtk_extended_layout_get_desired_size:
  * @layout: a #GtkExtendedLayout instance
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 92c2b80..1d71f72 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -459,16 +459,12 @@ typedef enum
 
 #define GTK_TYPE_REQUISITION              (gtk_requisition_get_type ())
 
-/* Size of the width-for-height/height-for-width caches */
-#define GTK_N_CACHED_SIZES 3
-
 /* forward declaration to avoid excessive includes (and concurrent includes)
  */
 typedef struct _GtkRequisition	   GtkRequisition;
 typedef struct _GtkSelectionData   GtkSelectionData;
 typedef struct _GtkWidgetClass	   GtkWidgetClass;
 typedef struct _GtkWidgetAuxInfo   GtkWidgetAuxInfo;
-typedef struct _GtkDesiredSize     GtkDesiredSize;
 typedef struct _GtkWidgetShapeInfo GtkWidgetShapeInfo;
 typedef struct _GtkClipboard	   GtkClipboard;
 typedef struct _GtkTooltip         GtkTooltip;
@@ -804,14 +800,6 @@ struct _GtkWidgetClass
   void (*_gtk_reserved7) (void);
 };
 
-struct _GtkDesiredSize
-{
-  guint  age;
-  gint   for_size;
-  gint   minimum_size;
-  gint   natural_size;
-};
-
 struct _GtkWidgetAuxInfo
 {
   gint x;
@@ -821,11 +809,6 @@ struct _GtkWidgetAuxInfo
 
   guint x_set : 1;
   guint y_set : 1;
-
-  GtkDesiredSize desired_widths[GTK_N_CACHED_SIZES];
-  GtkDesiredSize desired_heights[GTK_N_CACHED_SIZES];
-  guint cached_width_age;
-  guint cached_height_age;
 };
 
 struct _GtkWidgetShapeInfo



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