[gtk+] GtkWidget: add adjust_size_request adjust_size_allocation virtual funcs



commit cd2a19a68dbd646ae120f110ef9a051fef7f49bf
Author: Havoc Pennington <hp pobox com>
Date:   Sun Sep 5 12:19:14 2010 -0400

    GtkWidget: add adjust_size_request adjust_size_allocation virtual funcs
    
    Use these new methods to handle set_size_request (aka aux_info)
    inside gtkwidget.c, instead of having external code mess with it.
    
    The virtual functions can be used for other purposes in the
    future. For example, GtkContainer::border_width could be
    automatically implemented for all container subclasses.

 gtk/gtksizegroup.c   |   49 ++++++-----------------------
 gtk/gtksizerequest.c |   40 ++++++++++++++++++++++--
 gtk/gtkwidget.c      |   83 ++++++++++++++++++++++++++++++++++++++++++++++++--
 gtk/gtkwidget.h      |    9 +++++
 4 files changed, 136 insertions(+), 45 deletions(-)
---
diff --git a/gtk/gtksizegroup.c b/gtk/gtksizegroup.c
index 59ddc6e..cc16476 100644
--- a/gtk/gtksizegroup.c
+++ b/gtk/gtksizegroup.c
@@ -666,35 +666,23 @@ static gint
 get_base_dimension (GtkWidget        *widget,
 		    GtkSizeGroupMode  mode)
 {
-  GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (widget, FALSE);
-
   if (mode == GTK_SIZE_GROUP_HORIZONTAL)
     {
-      if (aux_info && aux_info->width > 0)
-	return aux_info->width;
-      else
-	{
-	  /* XXX Possibly we should be using natural values and not minimums here. */
-	  gint width;
+      /* XXX Possibly we should be using natural values and not minimums here. */
+      gint width;
 
-	  gtk_size_request_get_width (GTK_SIZE_REQUEST (widget), &width, NULL);
+      gtk_size_request_get_width (GTK_SIZE_REQUEST (widget), &width, NULL);
 
-	  return width;
-	}
+      return width;
     }
   else
     {
-      if (aux_info && aux_info->height > 0)
-	return aux_info->height;
-      else
-	{
-	  /* XXX Possibly we should be using natural values and not minimums here. */
-	  gint height;
+      /* XXX Possibly we should be using natural values and not minimums here. */
+      gint height;
 
-	  gtk_size_request_get_height (GTK_SIZE_REQUEST (widget), &height, NULL);
+      gtk_size_request_get_height (GTK_SIZE_REQUEST (widget), &height, NULL);
 
-	  return height;
-	}
+      return height;
     }
 }
 
@@ -801,31 +789,14 @@ _gtk_size_group_bump_requisition (GtkWidget        *widget,
 
   if (!is_bumping (widget))
     {
-      GtkWidgetAuxInfo *aux_info = 
-	_gtk_widget_get_aux_info (widget, FALSE);
-
       /* Avoid recursion here */
       mark_bumping (widget, TRUE);
 
       if (get_size_groups (widget))
 	{
-	  if (aux_info)
-	    {
-	      if (mode == GTK_SIZE_GROUP_HORIZONTAL)
-		result = compute_dimension (widget, mode, MAX (aux_info->width, widget_requisition));
-	      else 
-		result = compute_dimension (widget, mode, MAX (aux_info->height, widget_requisition));
-	    }
-	  else
-	    result = compute_dimension (widget, mode, widget_requisition);
-	}
-      else if (aux_info)
-	{
-	  if (mode == GTK_SIZE_GROUP_HORIZONTAL)
-	    result = MAX (aux_info->width, widget_requisition);
-	  else 
-	    result = MAX (aux_info->height, widget_requisition);
+          result = compute_dimension (widget, mode, widget_requisition);
 	}
+
       mark_bumping (widget, FALSE);
     }
   return result;
diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c
index 827265e..543bbc1 100644
--- a/gtk/gtksizerequest.c
+++ b/gtk/gtksizerequest.c
@@ -217,6 +217,7 @@ compute_size_for_orientation (GtkSizeRequest    *request,
   SizeRequest      *cached_size;
   GtkWidget        *widget;
   gboolean          found_in_cache = FALSE;
+  int adjusted_min, adjusted_natural;
 
   g_return_if_fail (GTK_IS_SIZE_REQUEST (request));
   g_return_if_fail (minimum_size != NULL || natural_size != NULL);
@@ -312,12 +313,45 @@ compute_size_for_orientation (GtkSizeRequest    *request,
           GTK_PRIVATE_UNSET_FLAG (request, GTK_HEIGHT_REQUEST_NEEDED);
         }
 
+      adjusted_min = cached_size->minimum_size;
+      adjusted_natural = cached_size->natural_size;
+      GTK_WIDGET_GET_CLASS (request)->adjust_size_request (GTK_WIDGET (request),
+                                                           orientation == GTK_SIZE_GROUP_HORIZONTAL ?
+                                                           GTK_ORIENTATION_HORIZONTAL :
+                                                           GTK_ORIENTATION_VERTICAL,
+                                                           cached_size->for_size,
+                                                           &adjusted_min,
+                                                           &adjusted_natural);
+
+      if (adjusted_min < cached_size->minimum_size ||
+          adjusted_natural < cached_size->natural_size)
+        {
+          g_warning ("%s %p adjusted size %s min %d natural %d must not decrease below min %d natural %d",
+                     G_OBJECT_TYPE_NAME (request), request,
+                     orientation == GTK_SIZE_GROUP_VERTICAL ? "vertical" : "horizontal",
+                     adjusted_min, adjusted_natural,
+                     cached_size->minimum_size, cached_size->natural_size);
+          /* don't use the adjustment */
+        }
+      else if (adjusted_min > adjusted_natural)
+        {
+          g_warning ("%s %p adjusted size %s min %d natural %d original min %d natural %d has min greater than natural",
+                     G_OBJECT_TYPE_NAME (request), request,
+                     orientation == GTK_SIZE_GROUP_VERTICAL ? "vertical" : "horizontal",
+                     adjusted_min, adjusted_natural,
+                     cached_size->minimum_size, cached_size->natural_size);
+          /* don't use the adjustment */
+        }
+      else
+        {
+          /* adjustment looks good */
+          cached_size->minimum_size = adjusted_min;
+          cached_size->natural_size = adjusted_natural;
+        }
+
       /* 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.
-       *
-       * Note this is also where values from gtk_widget_set_size_request()
-       * are considered.
        */
       group_size =
         _gtk_size_group_bump_requisition (GTK_WIDGET (request),
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index cbb568f..874be7e 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -315,7 +315,7 @@ static void	gtk_widget_real_unrealize	 (GtkWidget	    *widget);
 static void	gtk_widget_real_size_request	 (GtkWidget	    *widget,
 						  GtkRequisition    *requisition);
 static void	gtk_widget_real_size_allocate	 (GtkWidget	    *widget,
-						  GtkAllocation	    *allocation);
+                                                  GtkAllocation	    *allocation);
 static void	gtk_widget_real_style_set        (GtkWidget         *widget,
                                                   GtkStyle          *previous_style);
 static void	gtk_widget_real_direction_changed(GtkWidget         *widget,
@@ -408,7 +408,16 @@ static void             gtk_widget_real_get_height              (GtkSizeRequest
                                                                  gint              *natural_size);
 
 static void             gtk_widget_queue_tooltip_query          (GtkWidget *widget);
-     
+
+
+static void             gtk_widget_real_adjust_size_request     (GtkWidget         *widget,
+                                                                 GtkOrientation     orientation,
+                                                                 gint               for_size,
+                                                                 gint              *minimum_size,
+                                                                 gint              *natural_size);
+static void             gtk_widget_real_adjust_size_allocation  (GtkWidget         *widget,
+                                                                 GtkAllocation     *allocation);
+
 static void gtk_widget_set_usize_internal (GtkWidget *widget,
 					   gint       width,
 					   gint       height);
@@ -622,6 +631,9 @@ gtk_widget_class_init (GtkWidgetClass *klass)
 
   klass->no_expose_event = NULL;
 
+  klass->adjust_size_request = gtk_widget_real_adjust_size_request;
+  klass->adjust_size_allocation = gtk_widget_real_adjust_size_allocation;
+
   g_object_class_install_property (gobject_class,
 				   PROP_NAME,
 				   g_param_spec_string ("name",
@@ -3969,7 +3981,11 @@ gtk_widget_queue_shallow_draw (GtkWidget *widget)
  * @allocation: (inout): position and size to be allocated to @widget
  *
  * This function is only used by #GtkContainer subclasses, to assign a size
- * and position to their child widgets. 
+ * and position to their child widgets.
+ *
+ * In this function, the allocation may be adjusted. It will be forced
+ * to a 1x1 minimum size, and the adjust_size_allocation virtual method
+ * on the child will be used to adjust the allocation.
  **/
 void
 gtk_widget_size_allocate (GtkWidget	*widget,
@@ -3978,6 +3994,7 @@ gtk_widget_size_allocate (GtkWidget	*widget,
   GtkWidgetPrivate *priv;
   GdkRectangle real_allocation;
   GdkRectangle old_allocation;
+  GdkRectangle adjusted_allocation;
   gboolean alloc_needed;
   gboolean size_changed;
   gboolean position_changed;
@@ -4016,6 +4033,27 @@ gtk_widget_size_allocate (GtkWidget	*widget,
   old_allocation = priv->allocation;
   real_allocation = *allocation;
 
+  adjusted_allocation = real_allocation;
+  GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget, &adjusted_allocation);
+
+  if (adjusted_allocation.x < real_allocation.x ||
+      adjusted_allocation.y < real_allocation.y ||
+      (adjusted_allocation.x + adjusted_allocation.width) >
+      (real_allocation.x + real_allocation.width) ||
+      (adjusted_allocation.y + adjusted_allocation.height >
+       real_allocation.y + real_allocation.height))
+    {
+      g_warning ("%s %p attempted to adjust its size allocation from %d,%d %dx%d to %d,%d %dx%d. adjust_size_allocation must keep allocation inside original bounds",
+                 G_OBJECT_TYPE_NAME (widget), widget,
+                 real_allocation.x, real_allocation.y, real_allocation.width, real_allocation.height,
+                 adjusted_allocation.x, adjusted_allocation.y, adjusted_allocation.width, adjusted_allocation.height);
+      adjusted_allocation = real_allocation; /* veto it */
+    }
+  else
+    {
+      real_allocation = adjusted_allocation;
+    }
+
   if (real_allocation.width < 0 || real_allocation.height < 0)
     {
       g_warning ("gtk_widget_size_allocate(): attempt to allocate widget with width %d and height %d",
@@ -4270,6 +4308,16 @@ gtk_widget_real_size_allocate (GtkWidget     *widget,
      }
 }
 
+static void
+gtk_widget_real_adjust_size_allocation (GtkWidget         *widget,
+                                        GtkAllocation     *allocation)
+{
+  /* We have no adjustments by default for now, but we have this empty
+   * function here so subclasses can chain up in case we do add
+   * something.
+   */
+}
+
 static gboolean
 gtk_widget_real_can_activate_accel (GtkWidget *widget,
                                     guint      signal_id)
@@ -9054,6 +9102,35 @@ gtk_widget_real_size_request (GtkWidget         *widget,
   requisition->height = 0;
 }
 
+static void
+gtk_widget_real_adjust_size_request (GtkWidget         *widget,
+                                     GtkOrientation     orientation,
+                                     gint               for_size,
+                                     gint              *minimum_size,
+                                     gint              *natural_size)
+{
+  const GtkWidgetAuxInfo *aux_info;
+
+  aux_info =_gtk_widget_get_aux_info_or_defaults (widget);
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL &&
+      aux_info->width > 0)
+    {
+      *minimum_size = MAX (*minimum_size, aux_info->width);
+    }
+  else if (orientation == GTK_ORIENTATION_VERTICAL &&
+           aux_info->height > 0)
+    {
+      *minimum_size = MAX (*minimum_size, aux_info->height);
+    }
+
+  /* Fix it if set_size_request made natural size smaller than min size.
+   * This would also silently fix broken widgets, but we warn about them
+   * in gtksizerequest.c when calling their size request vfuncs.
+   */
+  *natural_size = MAX (*natural_size, *minimum_size);
+}
+
 /**
  * _gtk_widget_peek_colormap:
  * 
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index b413e0d..66d3f27 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -473,6 +473,15 @@ struct _GtkWidgetClass
 				       gint        y,
 				       gboolean    keyboard_tooltip,
 				       GtkTooltip *tooltip);
+
+  void         (* adjust_size_request)    (GtkWidget         *widget,
+                                           GtkOrientation     orientation,
+                                           gint               for_size,
+                                           gint              *minimum_size,
+                                           gint              *natural_size);
+  void         (* adjust_size_allocation) (GtkWidget         *widget,
+                                           GtkAllocation     *allocation);
+
   /* Signals without a C default handler class slot:
    * gboolean	(*damage_event)	(GtkWidget      *widget,
    *                             GdkEventExpose *event);



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