[gtk+/widget-expand: 1/3] Add horizontal and vertical expand flags, compute_expand() to GtkWidget



commit 6f3c6caadaf9b8c015572c69857b1e241cdc5d26
Author: Havoc Pennington <hp pobox com>
Date:   Mon Sep 6 12:26:32 2010 -0400

    Add horizontal and vertical expand flags, compute_expand() to GtkWidget
    
    GtkWidget now has flags for horizontal and vertical expand, and
    a compute_expand() method. compute_expand() is used by containers
    to set a default expand flag. (If a widget has expand set explicitly,
    it always overrides the results of compute_expand.)
    
    GtkContainer has a default implementation of compute_expand which
    simply walks over all child widgets and sets expand=TRUE
    if any child is expanding.
    
    The overall effect is that you only have to set expand on
    leaf nodes in the widget tree, while previously you had to
    set expand all the way up the tree as you packed every
    container. Also, now containers need not have their own child
    properties for expand.
    
    For old containers which do have "expand" child properties,
    they should override compute_expand and include the child
    properties in whether the container is expand=TRUE.
    Also, the old container should use
    "child_prop_expand || gtk_widget_compute_expand()" everywhere
    it previously used simply "child_prop_expand"
    
    https://bugzilla.gnome.org/show_bug.cgi?id=628902

 gtk/gtkcontainer.c |   51 +++++
 gtk/gtkwidget.c    |  583 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkwidget.h    |   35 +++-
 3 files changed, 666 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 85198bb..1bab539 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -91,6 +91,9 @@ static void     gtk_container_add_unimplemented    (GtkContainer      *container
 static void     gtk_container_remove_unimplemented (GtkContainer      *container,
 						    GtkWidget         *widget);
 static void     gtk_container_real_check_resize    (GtkContainer      *container);
+static void     gtk_container_compute_expand       (GtkWidget         *widget,
+                                                    gboolean          *h_expand_p,
+                                                    gboolean          *v_expand_p);
 static gboolean gtk_container_focus                (GtkWidget         *widget,
 						    GtkDirectionType   direction);
 static void     gtk_container_real_set_focus_child (GtkContainer      *container,
@@ -234,6 +237,7 @@ gtk_container_class_init (GtkContainerClass *class)
 
   object_class->destroy = gtk_container_destroy;
 
+  widget_class->compute_expand = gtk_container_compute_expand;
   widget_class->show_all = gtk_container_show_all;
   widget_class->hide_all = gtk_container_hide_all;
   widget_class->expose_event = gtk_container_expose;
@@ -1829,6 +1833,53 @@ _gtk_container_child_composite_name (GtkContainer *container,
   return NULL;
 }
 
+typedef struct {
+  gboolean h_expand;
+  gboolean v_expand;
+} ComputeExpandData;
+
+static void
+gtk_container_compute_expand_callback (GtkWidget *widget,
+				       gpointer   client_data)
+{
+  ComputeExpandData *data = client_data;
+
+  /* note that we don't get_expand on the child if we already know we
+   * have to expand, so we only recurse into children until we find
+   * one that expands and then we basically don't do any more
+   * work. This means that we can leave some children in a
+   * need_compute_expand state, which is fine, as long as GtkWidget
+   * doesn't rely on an invariant that "if a child has
+   * need_compute_expand, its parents also do"
+   *
+   * gtk_widget_compute_expand() always returns FALSE if the
+   * child is !visible so that's taken care of.
+   */
+  data->h_expand = data->h_expand ||
+    gtk_widget_compute_expand (widget, GTK_ORIENTATION_HORIZONTAL);
+
+  data->v_expand = data->v_expand ||
+    gtk_widget_compute_expand (widget, GTK_ORIENTATION_VERTICAL);
+}
+
+static void
+gtk_container_compute_expand (GtkWidget         *widget,
+                              gboolean          *h_expand_p,
+                              gboolean          *v_expand_p)
+{
+  ComputeExpandData data;
+
+  data.h_expand = FALSE;
+  data.v_expand = FALSE;
+
+  gtk_container_forall (GTK_CONTAINER (widget),
+                        gtk_container_compute_expand_callback,
+                        &data);
+
+  *h_expand_p = data.h_expand;
+  *v_expand_p = data.v_expand;
+}
+
 static void
 gtk_container_real_set_focus_child (GtkContainer     *container,
 				    GtkWidget        *child)
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index b04f99a..c4cf822 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -234,7 +234,12 @@ enum {
   PROP_PADDING_RIGHT,
   PROP_PADDING_TOP,
   PROP_PADDING_BOTTOM,
-  PROP_PADDING_ALL_SIDES
+  PROP_PADDING_ALL_SIDES,
+  PROP_H_EXPAND,
+  PROP_V_EXPAND,
+  PROP_H_EXPAND_SET,
+  PROP_V_EXPAND_SET,
+  PROP_EXPAND
 };
 
 typedef	struct	_GtkStateData	 GtkStateData;
@@ -954,6 +959,81 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                                                      GTK_PARAM_READWRITE));
 
   /**
+   * GtkWidget:h-expand
+   *
+   * Whether to expand horizontally. See gtk_widget_set_h_expand().
+   *
+   * Since: 3.0
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_H_EXPAND,
+                                   g_param_spec_boolean ("h-expand",
+                                                         P_("Horizontal Expand"),
+                                                         P_("Whether widget wants more horizontal space"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWidget:h-expand-set
+   *
+   * Whether to use the GtkWidget:h-expand property. See gtk_widget_get_h_expand_set().
+   *
+   * Since: 3.0
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_H_EXPAND_SET,
+                                   g_param_spec_boolean ("h-expand-set",
+                                                         P_("Horizontal Expand Set"),
+                                                         P_("Whether to use the h-expand property"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWidget:v-expand
+   *
+   * Whether to expand vertically. See gtk_widget_set_v_expand().
+   *
+   * Since: 3.0
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_V_EXPAND,
+                                   g_param_spec_boolean ("v-expand",
+                                                         P_("Vertical Expand"),
+                                                         P_("Whether widget wants more vertical space"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWidget:v-expand-set
+   *
+   * Whether to use the GtkWidget:v-expand property. See gtk_widget_get_v_expand_set().
+   *
+   * Since: 3.0
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_V_EXPAND_SET,
+                                   g_param_spec_boolean ("v-expand-set",
+                                                         P_("Vertical Expand Set"),
+                                                         P_("Whether to use the v-expand property"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWidget:expand
+   *
+   * Whether to expand in both directions. Setting this sets both GtkWidget:h-expand and GtkWidget:v-expand
+   *
+   * Since: 3.0
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_EXPAND,
+                                   g_param_spec_boolean ("expand",
+                                                         P_("Expand Both"),
+                                                         P_("Whether widget wants to expand in both directions"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  /**
    * GtkWidget::show:
    * @widget: the object which received the signal.
    */
@@ -2914,6 +2994,24 @@ gtk_widget_set_property (GObject         *object,
       gtk_widget_set_padding_bottom (widget, g_value_get_int (value));
       g_object_thaw_notify (G_OBJECT (widget));
       break;
+    case PROP_H_EXPAND:
+      gtk_widget_set_h_expand (widget, g_value_get_boolean (value));
+      break;
+    case PROP_H_EXPAND_SET:
+      gtk_widget_set_h_expand_set (widget, g_value_get_boolean (value));
+      break;
+    case PROP_V_EXPAND:
+      gtk_widget_set_v_expand (widget, g_value_get_boolean (value));
+      break;
+    case PROP_V_EXPAND_SET:
+      gtk_widget_set_v_expand_set (widget, g_value_get_boolean (value));
+      break;
+    case PROP_EXPAND:
+      g_object_freeze_notify (G_OBJECT (widget));
+      gtk_widget_set_h_expand (widget, g_value_get_boolean (value));
+      gtk_widget_set_v_expand (widget, g_value_get_boolean (value));
+      g_object_thaw_notify (G_OBJECT (widget));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -3057,6 +3155,23 @@ gtk_widget_get_property (GObject         *object,
           }
       }
       break;
+    case PROP_H_EXPAND:
+      g_value_set_boolean (value, gtk_widget_get_h_expand (widget));
+      break;
+    case PROP_H_EXPAND_SET:
+      g_value_set_boolean (value, gtk_widget_get_h_expand_set (widget));
+      break;
+    case PROP_V_EXPAND:
+      g_value_set_boolean (value, gtk_widget_get_v_expand (widget));
+      break;
+    case PROP_V_EXPAND_SET:
+      g_value_set_boolean (value, gtk_widget_get_v_expand_set (widget));
+      break;
+    case PROP_EXPAND:
+      g_value_set_boolean (value,
+                           gtk_widget_get_h_expand (widget) &&
+                           gtk_widget_get_v_expand (widget));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -3090,6 +3205,15 @@ gtk_widget_init (GtkWidget *widget)
   GTK_PRIVATE_SET_FLAG (widget, GTK_HEIGHT_REQUEST_NEEDED);
   GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
 
+  /* this will be set to TRUE if the widget gets a child or if the
+   * expand flag is set on the widget, but until one of those happen
+   * we know the expand is already properly FALSE.
+   *
+   * We really want to default FALSE here to avoid computing expand
+   * all over the place while initially building a widget tree.
+   */
+  widget->need_compute_expand = FALSE;
+
   widget->style = gtk_widget_get_default_style ();
   g_object_ref (widget->style);
 }
@@ -3316,13 +3440,26 @@ gtk_widget_unparent (GtkWidget *widget)
   old_parent = widget->parent;
   widget->parent = NULL;
   gtk_widget_set_parent_window (widget, NULL);
+
+  /* parent may no longer expand if the removed
+   * child was expand=TRUE and could therefore
+   * be forcing it to.
+   */
+  if (gtk_widget_get_visible (widget) &&
+      (widget->need_compute_expand ||
+       widget->computed_h_expand ||
+       widget->computed_v_expand))
+    {
+      gtk_widget_queue_compute_expand (old_parent);
+    }
+
   g_signal_emit (widget, widget_signals[PARENT_SET], 0, old_parent);
   if (toplevel)
     {
       _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
       g_object_unref (toplevel);
     }
-      
+
   g_object_notify (G_OBJECT (widget), "parent");
   g_object_thaw_notify (G_OBJECT (widget));
   if (!widget->parent)
@@ -3409,6 +3546,17 @@ gtk_widget_show (GtkWidget *widget)
       g_object_ref (widget);
       if (!gtk_widget_is_toplevel (widget))
 	gtk_widget_queue_resize (widget);
+
+      /* see comment in set_parent() for why this should and can be
+       * conditional
+       */
+      if (widget->need_compute_expand ||
+          widget->computed_h_expand ||
+          widget->computed_v_expand)
+        {
+          gtk_widget_queue_compute_expand (widget);
+        }
+
       g_signal_emit (widget, widget_signals[SHOW], 0);
       g_object_notify (G_OBJECT (widget), "visible");
       g_object_unref (widget);
@@ -3493,6 +3641,14 @@ gtk_widget_hide (GtkWidget *widget)
       if (toplevel != widget && gtk_widget_is_toplevel (toplevel))
 	_gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
 
+      /* a parent may now be expand=FALSE since we're hidden. */
+      if (widget->need_compute_expand ||
+          widget->computed_h_expand ||
+          widget->computed_v_expand)
+        {
+          gtk_widget_queue_compute_expand (widget);
+        }
+
       g_signal_emit (widget, widget_signals[HIDE], 0);
       if (!gtk_widget_is_toplevel (widget))
 	gtk_widget_queue_resize (widget);
@@ -6711,6 +6867,24 @@ gtk_widget_set_parent (GtkWidget *widget,
 
       gtk_widget_queue_resize (widget);
     }
+
+  /* child may cause parent's expand to change, if the child is
+   * expanded. If child is not expanded, then it can't modify the
+   * parent's expand. If the child becomes expanded later then it will
+   * queue compute_expand then. This optimization plus defaulting
+   * newly-constructed widgets to need_compute_expand=FALSE should
+   * mean that initially building a widget tree doesn't have to keep
+   * walking up setting need_compute_expand on parents over and over.
+   *
+   * We can't change a parent to need to expand unless we're visible.
+   */
+  if (gtk_widget_get_visible (widget) &&
+      (widget->need_compute_expand ||
+       widget->computed_h_expand ||
+       widget->computed_v_expand))
+    {
+      gtk_widget_queue_compute_expand (parent);
+    }
 }
 
 /**
@@ -10711,6 +10885,411 @@ gtk_widget_ref_accessible (AtkImplementor *implementor)
 }
 
 /*
+ * Expand flag management
+ */
+
+static void
+gtk_widget_update_computed_expand (GtkWidget *widget)
+{
+  if (widget->need_compute_expand)
+    {
+      gboolean h, v;
+
+      if (widget->h_expand_set)
+        h = widget->h_expand;
+      else
+        h = FALSE;
+
+      if (widget->v_expand_set)
+        v = widget->v_expand;
+      else
+        v = FALSE;
+
+      /* we don't need to use compute_expand if both expands are
+       * forced by the app
+       */
+      if (!(widget->h_expand_set && widget->v_expand_set))
+        {
+          if (GTK_WIDGET_GET_CLASS (widget)->compute_expand != NULL)
+            {
+              gboolean ignored;
+
+              GTK_WIDGET_GET_CLASS (widget)->compute_expand (widget,
+                                                             widget->h_expand_set ? &ignored : &h,
+                                                             widget->v_expand_set ? &ignored : &v);
+            }
+        }
+
+      widget->need_compute_expand = FALSE;
+      widget->computed_h_expand = h != FALSE;
+      widget->computed_v_expand = v != FALSE;
+    }
+}
+
+void
+gtk_widget_queue_compute_expand (GtkWidget *widget)
+{
+  GtkWidget *parent;
+  gboolean changed_anything;
+
+  if (widget->need_compute_expand)
+    return;
+
+  changed_anything = FALSE;
+  parent = widget;
+  while (parent != NULL)
+    {
+      if (!parent->need_compute_expand)
+        {
+          parent->need_compute_expand = TRUE;
+          changed_anything = TRUE;
+        }
+
+      /* Note: if we had an invariant that "if a child needs to
+       * compute expand, its parents also do" then we could stop going
+       * up when we got to a parent that already needed to
+       * compute. However, in general we compute expand lazily (as
+       * soon as we see something in a subtree that is expand, we know
+       * we're expanding) and so this invariant does not hold and we
+       * have to always walk all the way up in case some ancestor
+       * is not currently need_compute_expand.
+       */
+
+      parent = parent->parent;
+    }
+
+  /* recomputing expand always requires
+   * a relayout as well
+   */
+  if (changed_anything)
+    gtk_widget_queue_resize (widget);
+}
+
+/**
+ * gtk_widget_compute_expand:
+ * @widget: the widget
+ * @orientation: expand direction
+ *
+ * Computes whether a container should give this widget extra space
+ * when possible. Containers should check this, rather than
+ * looking at gtk_widget_get_h_expand() or gtk_widget_get_v_expand().
+ *
+ * This function already checks whether the widget is visible, so
+ * visibility does not need to be checked separately. Non-visible
+ * widgets are not expanded.
+ *
+ * The computed expand value uses either the expand setting explicitly
+ * set on the widget itself, or, if none has been explicitly set,
+ * the widget will expand if any of its children wants to expand.
+ *
+ * Return value: whether widget tree rooted here should be expanded
+ */
+gboolean
+gtk_widget_compute_expand (GtkWidget     *widget,
+                           GtkOrientation orientation)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  /* We never make a widget expand if not even showing. */
+  if (!gtk_widget_get_visible (widget))
+    return FALSE;
+
+  gtk_widget_update_computed_expand (widget);
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      return widget->computed_h_expand;
+    }
+  else
+    {
+      return widget->computed_v_expand;
+    }
+}
+
+static void
+gtk_widget_set_expand (GtkWidget     *widget,
+                       GtkOrientation orientation,
+                       gboolean       expand)
+{
+  const char *expand_prop;
+  const char *expand_set_prop;
+  gboolean was_both;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  expand = expand != FALSE;
+
+  was_both = widget->h_expand && widget->v_expand;
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      if (widget->h_expand_set &&
+          widget->h_expand == expand)
+        return;
+
+      widget->h_expand_set = TRUE;
+      widget->h_expand = expand;
+
+      expand_prop = "h-expand";
+      expand_set_prop = "h-expand-set";
+    }
+  else
+    {
+      if (widget->v_expand_set &&
+          widget->v_expand == expand)
+        return;
+
+      widget->v_expand_set = TRUE;
+      widget->v_expand = expand;
+
+      expand_prop = "v-expand";
+      expand_set_prop = "v-expand-set";
+    }
+
+  gtk_widget_queue_compute_expand (widget);
+
+  g_object_freeze_notify (G_OBJECT (widget));
+  g_object_notify (G_OBJECT (widget), expand_prop);
+  g_object_notify (G_OBJECT (widget), expand_set_prop);
+  if (was_both != (widget->h_expand && widget->v_expand))
+    g_object_notify (G_OBJECT (widget), "expand");
+  g_object_thaw_notify (G_OBJECT (widget));
+}
+
+static void
+gtk_widget_set_expand_set (GtkWidget      *widget,
+                           GtkOrientation  orientation,
+                           gboolean        set)
+{
+  const char *prop;
+
+  set = set != FALSE;
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      if (set == widget->h_expand_set)
+        return;
+
+      widget->h_expand_set = set;
+      prop = "h-expand-set";
+    }
+  else
+    {
+      if (set == widget->v_expand_set)
+        return;
+
+      widget->v_expand_set = set;
+      prop = "v-expand-set";
+    }
+
+  gtk_widget_queue_compute_expand (widget);
+
+  g_object_notify (G_OBJECT (widget), prop);
+}
+
+/**
+ * gtk_widget_get_h_expand:
+ * @widget: the widget
+ *
+ * Gets whether the widget would like any available extra horizontal
+ * space. When a user resizes a #GtkWindow, widgets with expand=TRUE
+ * generally receive the extra space. For example, a list or
+ * scrollable area or document in your window would often be set to
+ * expand.
+ *
+ * Containers should use gtk_widget_compute_expand() rather than
+ * this function, to see whether a widget, or any of its children,
+ * has the expand flag set. If any child of a widget needs to
+ * expand, the parent needs to expand also.
+ *
+ * This function only looks at the widget's own h-expand flag, rather
+ * than computing whether the entire widget tree rooted at this widget
+ * needs to expand.
+ *
+ * Return value: whether h-expand flag is set
+ */
+gboolean
+gtk_widget_get_h_expand (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return widget->h_expand;
+}
+
+/**
+ * gtk_widget_set_h_expand:
+ * @widget: the widget
+ * @expand: whether to expand
+ *
+ * Sets whether the widget would like any available extra horizontal
+ * space. When a user resizes a #GtkWindow, widgets with expand=TRUE
+ * generally receive the extra space. For example, a list or
+ * scrollable area or document in your window would often be set to
+ * expand.
+ *
+ * Call this function to set the expand flag if you would like your
+ * widget to become larger horizontally when the window has extra
+ * room.
+ *
+ * By default, widgets automatically expand if any of their children
+ * want to expand. (To see if a widget will automatically expand
+ * given its current children and state, call gtk_widget_compute_expand()).
+ *
+ * Setting h-expand explicitly with this function will override
+ * the automatic expand behavior.
+ *
+ * This function forces the widget to expand or not to expand,
+ * regardless of children.  The override occurs because
+ * gtk_widget_set_h_expand() sets the h-expand-set property (see
+ * gtk_widget_set_h_expand_set()) which causes the widget's h-expand
+ * value to be used, rather than looking at children and widget state.
+ */
+void
+gtk_widget_set_h_expand (GtkWidget      *widget,
+                         gboolean        expand)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  gtk_widget_set_expand (widget, GTK_ORIENTATION_HORIZONTAL, expand);
+}
+
+/**
+ * gtk_widget_get_h_expand_set:
+ * @widget: the widget
+ *
+ * Gets whether gtk_widget_set_h_expand() has been used to
+ * explicitly set the expand flag on this widget.
+ *
+ * If h-expand is set, then it overrides any computed
+ * expand value based on child widgets. If h-expand is not
+ * set, then the expand value depends on whether any
+ * children of the widget would like to expand.
+ *
+ * There are few reasons to use this function, but it's here
+ * for completeness and consistency.
+ *
+ * Return value: whether h-expand has been explicitly set
+ */
+gboolean
+gtk_widget_get_h_expand_set (GtkWidget      *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return widget->h_expand_set;
+}
+
+/**
+ * gtk_widget_set_h_expand_set:
+ * @widget: the widget
+ * @set: value for h-expand-set property
+ *
+ * Sets whether the h-expand flag (see gtk_widget_get_h_expand()) will
+ * be used.
+ *
+ * The h-expand-set property will be set automatically when you call
+ * gtk_widget_set_h_expand() to set h-expand, so the most likely
+ * reason to use this function would be to unset an explicit expand
+ * flag.
+ *
+ * If h-expand is set, then it overrides any computed
+ * expand value based on child widgets. If h-expand is not
+ * set, then the expand value depends on whether any
+ * children of the widget would like to expand.
+ *
+ * There are few reasons to use this function, but it's here
+ * for completeness and consistency.
+ *
+ * Return value: whether h-expand has been explicitly set
+ */
+void
+gtk_widget_set_h_expand_set (GtkWidget      *widget,
+                             gboolean        set)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  gtk_widget_set_expand_set (widget, GTK_ORIENTATION_HORIZONTAL, set);
+}
+
+
+/**
+ * gtk_widget_get_v_expand:
+ * @widget: the widget
+ *
+ * Gets whether the widget would like any available extra vertical
+ * space.
+ *
+ * See gtk_widget_get_h_expand() for more detail.
+ *
+ * Return value: whether v-expand flag is set
+ */
+gboolean
+gtk_widget_get_v_expand (GtkWidget *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return widget->v_expand;
+}
+
+/**
+ * gtk_widget_set_v_expand:
+ * @widget: the widget
+ * @expand: whether to expand
+ *
+ * Sets whether the widget would like any available extra vertical
+ * space.
+ *
+ * See gtk_widget_set_h_expand() for more detail.
+ */
+void
+gtk_widget_set_v_expand (GtkWidget      *widget,
+                         gboolean        expand)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  gtk_widget_set_expand (widget, GTK_ORIENTATION_VERTICAL, expand);
+}
+
+/**
+ * gtk_widget_get_v_expand_set:
+ * @widget: the widget
+ *
+ * Gets whether gtk_widget_set_v_expand() has been used to
+ * explicitly set the expand flag on this widget.
+ *
+ * See gtk_widget_get_h_expand_set() for more detail.
+ *
+ * Return value: whether v-expand has been explicitly set
+ */
+gboolean
+gtk_widget_get_v_expand_set (GtkWidget      *widget)
+{
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return widget->v_expand_set;
+}
+
+/**
+ * gtk_widget_set_v_expand_set:
+ * @widget: the widget
+ * @set: value for v-expand-set property
+ *
+ * Sets whether the v-expand flag (see gtk_widget_get_v_expand()) will
+ * be used.
+ *
+ * See gtk_widget_set_h_expand_set() for more detail.
+ *
+ * Return value: whether v-expand has been explicitly set
+ */
+void
+gtk_widget_set_v_expand_set (GtkWidget      *widget,
+                             gboolean        set)
+{
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  gtk_widget_set_expand_set (widget, GTK_ORIENTATION_VERTICAL, set);
+}
+
+/*
  * GtkBuildable implementation
  */
 static GQuark		 quark_builder_has_default = 0;
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 3f41333..e34e12d 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -274,8 +274,18 @@ struct _GtkWidget
    */
   guint GSEAL (saved_state) : 3;
 
+  /* Expand-related flags */
+
+  guint GSEAL (need_compute_expand) : 1; /* Need to recompute computed_[hv]_expand */
+  guint GSEAL (computed_h_expand) : 1;   /* computed results (composite of child flags) */
+  guint GSEAL (computed_v_expand) : 1;
+  guint GSEAL (h_expand) : 1;            /* application-forced expand */
+  guint GSEAL (v_expand) : 1;
+  guint GSEAL (h_expand_set) : 1;        /* whether to use application-forced  */
+  guint GSEAL (v_expand_set) : 1;        /* instead of computing from children */
+
   /* unused bits in our 32-bit block */
-  guint GSEAL (reserved) : 10;
+  guint GSEAL (reserved) : 3;
 
   /* The widget's name. If the widget does not have a name
    *  (the name is NULL), then its name (as returned by
@@ -523,6 +533,10 @@ struct _GtkWidgetClass
 				       gboolean    keyboard_tooltip,
 				       GtkTooltip *tooltip);
 
+  void         (* compute_expand)     (GtkWidget  *widget,
+                                       gboolean   *h_expand_p,
+                                       gboolean   *v_expand_p);
+
   void         (* adjust_size_request)    (GtkWidget         *widget,
                                            GtkOrientation     orientation,
                                            gint               for_size,
@@ -789,6 +803,25 @@ GtkClipboard *gtk_widget_get_clipboard   (GtkWidget *widget,
 GdkPixmap *   gtk_widget_get_snapshot    (GtkWidget    *widget,
                                           GdkRectangle *clip_rect);
 
+
+/* Expand flags and related support */
+gboolean gtk_widget_get_h_expand         (GtkWidget      *widget);
+void     gtk_widget_set_h_expand         (GtkWidget      *widget,
+                                          gboolean        expand);
+gboolean gtk_widget_get_h_expand_set     (GtkWidget      *widget);
+void     gtk_widget_set_h_expand_set     (GtkWidget      *widget,
+                                          gboolean        set);
+gboolean gtk_widget_get_v_expand         (GtkWidget      *widget);
+void     gtk_widget_set_v_expand         (GtkWidget      *widget,
+                                          gboolean        expand);
+gboolean gtk_widget_get_v_expand_set     (GtkWidget      *widget);
+void     gtk_widget_set_v_expand_set     (GtkWidget      *widget,
+                                          gboolean        set);
+void     gtk_widget_queue_compute_expand (GtkWidget      *widget);
+gboolean gtk_widget_compute_expand       (GtkWidget      *widget,
+                                          GtkOrientation  orientation);
+
+
 /* Multidevice support */
 gboolean         gtk_widget_get_support_multidevice (GtkWidget      *widget);
 void             gtk_widget_set_support_multidevice (GtkWidget      *widget,



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