[gnome-shell] [St] Make allocation handling more consistent



commit 5331d3e360d08a109c98a1f6f072c12787eb4088
Author: Dan Winship <danw gnome org>
Date:   Sat Feb 13 11:24:25 2010 -0500

    [St] Make allocation handling more consistent
    
    In StBin, StBoxLayout, and StTable, if a child has a potential
    allocation that is larger than its preferred size, we give it its
    preferred size instead. However, the corresponding
    get_preferred_height/width methods were not making the same
    assumption, which meant that if we had more width than the widget
    wanted, we would allocate it its preferred width, but with the height
    that corresponded to the larger width.
    
    Fix this by defining new helpers _st_actor_get_preferred_width() and
    _st_actor_get_preferred_height() and using them everywhere. Also, make
    StBin and StTable use _st_allocate_fill() rather than having
    nearly-identical duplicate copies of the code.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=609848

 src/shell-slicer.c     |   23 +++--
 src/st/st-bin.c        |  158 +++------------------------------
 src/st/st-box-layout.c |   66 +++++++++-----
 src/st/st-private.c    |  231 +++++++++++++++++++++++++++++++++++++++--------
 src/st/st-private.h    |   22 ++++-
 src/st/st-table.c      |  133 +++-------------------------
 6 files changed, 291 insertions(+), 342 deletions(-)
---
diff --git a/src/shell-slicer.c b/src/shell-slicer.c
index db59df8..bcc27de 100644
--- a/src/shell-slicer.c
+++ b/src/shell-slicer.c
@@ -37,9 +37,9 @@ shell_slicer_get_preferred_width (ClutterActor *self,
     }
   else
     {
-      clutter_actor_get_preferred_width (child, for_height,
-                                         NULL,
-                                         natural_width_p);
+      _st_actor_get_preferred_width (child, for_height, FALSE,
+                                     NULL,
+                                     natural_width_p);
     }
 
   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
@@ -66,9 +66,9 @@ shell_slicer_get_preferred_height (ClutterActor *self,
     }
   else
     {
-      clutter_actor_get_preferred_height (child, for_width,
-                                          NULL,
-                                          natural_height_p);
+      _st_actor_get_preferred_height (child, for_width, FALSE,
+                                      NULL,
+                                      natural_height_p);
     }
 
   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
@@ -97,14 +97,17 @@ shell_slicer_paint_child (ShellSlicer *self)
   ClutterActorBox self_box;
   ClutterActorBox child_box;
   float width, height, child_width, child_height;
-  double x_align, y_align;
+  StAlign x_align, y_align;
+  double x_align_factor, y_align_factor;
 
   child = st_bin_get_child (ST_BIN (self));
 
   if (!child)
     return;
 
-  _st_bin_get_align_factors (ST_BIN (self), &x_align, &y_align);
+  st_bin_get_alignment (ST_BIN (self), &x_align, &y_align);
+  _st_get_align_factors (ST_WIDGET (self), x_align, y_align,
+                         &x_align_factor, &y_align_factor);
 
   clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &self_box);
   clutter_actor_get_allocation_box (child, &child_box);
@@ -117,8 +120,8 @@ shell_slicer_paint_child (ShellSlicer *self)
   cogl_push_matrix ();
 
   cogl_clip_push (0, 0, width, height);
-  cogl_translate ((int)(0.5 + x_align * (width - child_width)),
-                  (int)(0.5 + y_align * (height - child_height)),
+  cogl_translate ((int)(0.5 + x_align_factor * (width - child_width)),
+                  (int)(0.5 + y_align_factor * (height - child_height)),
                   0);
 
   clutter_actor_paint (child);
diff --git a/src/st/st-bin.c b/src/st/st-bin.c
index 48347b6..3039297 100644
--- a/src/st/st-bin.c
+++ b/src/st/st-bin.c
@@ -71,59 +71,6 @@ G_DEFINE_TYPE_WITH_CODE (StBin, st_bin, ST_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
                                                 clutter_container_iface_init));
 
-void
-_st_bin_get_align_factors (StBin   *bin,
-                           gdouble *x_align,
-                           gdouble *y_align)
-{
-  StBinPrivate *priv = bin->priv;
-  gdouble factor;
-
-  switch (priv->x_align)
-    {
-    case ST_ALIGN_START:
-      factor = 0.0;
-      break;
-
-    case ST_ALIGN_MIDDLE:
-      factor = 0.5;
-      break;
-
-    case ST_ALIGN_END:
-      factor = 1.0;
-      break;
-
-    default:
-      factor = 0.0;
-      break;
-    }
-
-  if (x_align)
-    *x_align = factor;
-
-  switch (priv->y_align)
-    {
-    case ST_ALIGN_START:
-      factor = 0.0;
-      break;
-
-    case ST_ALIGN_MIDDLE:
-      factor = 0.5;
-      break;
-
-    case ST_ALIGN_END:
-      factor = 1.0;
-      break;
-
-    default:
-      factor = 0.0;
-      break;
-    }
-
-  if (y_align)
-    *y_align = factor;
-}
-
 static void
 st_bin_add (ClutterContainer *container,
             ClutterActor     *actor)
@@ -199,92 +146,13 @@ st_bin_allocate (ClutterActor          *self,
   if (priv->child)
     {
       StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
-      gfloat natural_width, natural_height;
-      gfloat min_width, min_height;
-      gfloat child_width, child_height;
-      gfloat available_width, available_height;
-      ClutterRequestMode request;
-      ClutterActorBox content_box;
-      ClutterActorBox allocation = { 0, };
-      gdouble x_align, y_align;
-
-      st_theme_node_get_content_box (theme_node, box, &content_box);
-
-      _st_bin_get_align_factors (ST_BIN (self), &x_align, &y_align);
-
-      available_width  = content_box.x2 - content_box.x1;
-      available_height = content_box.y2 - content_box.y1;
-
-      if (available_width < 0)
-        available_width = 0;
-
-      if (available_height < 0)
-        available_height = 0;
-
-      if (priv->x_fill)
-        {
-          allocation.x1 = (int) content_box.x1;
-          allocation.x2 = (int) content_box.x2;
-        }
-
-      if (priv->y_fill)
-        {
-          allocation.y1 = (int) content_box.y1;
-          allocation.y2 = (int) content_box.y2;
-        }
-
-      /* if we are filling horizontally and vertically then we're done */
-      if (priv->x_fill && priv->y_fill)
-        {
-          clutter_actor_allocate (priv->child, &allocation, flags);
-          return;
-        }
-
-      request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
-      g_object_get (G_OBJECT (priv->child), "request-mode", &request, NULL);
-
-      if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
-        {
-          clutter_actor_get_preferred_width (priv->child, available_height,
-                                             &min_width,
-                                             &natural_width);
-
-          child_width = CLAMP (natural_width, min_width, available_width);
-
-          clutter_actor_get_preferred_height (priv->child, child_width,
-                                              &min_height,
-                                              &natural_height);
-
-          child_height = CLAMP (natural_height, min_height, available_height);
-        }
-      else
-        {
-          clutter_actor_get_preferred_height (priv->child, available_width,
-                                              &min_height,
-                                              &natural_height);
-
-          child_height = CLAMP (natural_height, min_height, available_height);
-
-          clutter_actor_get_preferred_width (priv->child, child_height,
-                                             &min_width,
-                                             &natural_width);
-
-          child_width = CLAMP (natural_width, min_width, available_width);
-        }
-
-      if (!priv->x_fill)
-        {
-          allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align);
-          allocation.x2 = allocation.x1 + child_width;
-        }
-
-      if (!priv->y_fill)
-        {
-          allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align);
-          allocation.y2 = allocation.y1 + child_height;
-        }
-
-      clutter_actor_allocate (priv->child, &allocation, flags);
+      ClutterActorBox childbox;
+
+      st_theme_node_get_content_box (theme_node, box, &childbox);
+      _st_allocate_fill (ST_WIDGET (self), priv->child, &childbox,
+                         priv->x_align, priv->y_align,
+                         priv->x_fill, priv->y_fill);
+      clutter_actor_allocate (priv->child, &childbox, flags);
     }
 }
 
@@ -309,9 +177,9 @@ st_bin_get_preferred_width (ClutterActor *self,
     }
   else
     {
-      clutter_actor_get_preferred_width (priv->child, for_height,
-                                         min_width_p,
-                                         natural_width_p);
+      _st_actor_get_preferred_width (priv->child, for_height, priv->y_fill,
+                                     min_width_p,
+                                     natural_width_p);
     }
 
   st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
@@ -338,9 +206,9 @@ st_bin_get_preferred_height (ClutterActor *self,
     }
   else
     {
-      clutter_actor_get_preferred_height (priv->child, for_width,
-                                          min_height_p,
-                                          natural_height_p);
+      _st_actor_get_preferred_height (priv->child, for_width, priv->x_fill,
+                                      min_height_p,
+                                      natural_height_p);
     }
 
   st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c
index d23226a..5062c07 100644
--- a/src/st/st-box-layout.c
+++ b/src/st/st-box-layout.c
@@ -528,6 +528,7 @@ get_content_preferred_width (StBoxLayout *self,
     {
       ClutterActor *child = l->data;
       gfloat child_min = 0, child_nat = 0;
+      gboolean child_fill;
 
       if (!CLUTTER_ACTOR_IS_VISIBLE (child))
         continue;
@@ -540,18 +541,20 @@ get_content_preferred_width (StBoxLayout *self,
           continue;
         }
 
-      clutter_actor_get_preferred_width (child,
-                                         (!priv->is_vertical) ? for_height : -1,
-                                         &child_min,
-                                         &child_nat);
-
       if (priv->is_vertical)
         {
+          _st_actor_get_preferred_width (child, -1, FALSE,
+                                         &child_min, &child_nat);
           min_width = MAX (child_min, min_width);
           natural_width = MAX (child_nat, natural_width);
         }
       else
         {
+          clutter_container_child_get ((ClutterContainer*) self, child,
+                                       "y-fill", &child_fill,
+                                       NULL);
+          _st_actor_get_preferred_width (child, for_height, child_fill,
+                                         &child_min, &child_nat);
           min_width += child_min;
           natural_width += child_nat;
         }
@@ -606,6 +609,7 @@ get_content_preferred_height (StBoxLayout *self,
     {
       ClutterActor *child = l->data;
       gfloat child_min = 0, child_nat = 0;
+      gboolean child_fill = FALSE;
 
       if (!CLUTTER_ACTOR_IS_VISIBLE (child))
         continue;
@@ -618,10 +622,17 @@ get_content_preferred_height (StBoxLayout *self,
           continue;
         }
 
-      clutter_actor_get_preferred_height (child,
-                                          (priv->is_vertical) ? for_width : -1,
-                                          &child_min,
-                                          &child_nat);
+      if (priv->is_vertical)
+        {
+          clutter_container_child_get ((ClutterContainer*) self, child,
+                                       "x-fill", &child_fill,
+                                       NULL);
+        }
+      _st_actor_get_preferred_height (child,
+                                      (priv->is_vertical) ? for_width : -1,
+                                      child_fill,
+                                      &child_min,
+                                      &child_nat);
 
       if (!priv->is_vertical)
         {
@@ -713,6 +724,7 @@ compute_shrinks (StBoxLayout *self,
     {
       ClutterActor *child = l->data;
       gfloat child_min, child_nat;
+      gboolean child_fill;
       gboolean fixed;
 
       child = (ClutterActor*) l->data;
@@ -722,13 +734,23 @@ compute_shrinks (StBoxLayout *self,
       if (CLUTTER_ACTOR_IS_VISIBLE (child) && !fixed)
         {
           if (priv->is_vertical)
-            clutter_actor_get_preferred_height (child,
-                                                for_length,
-                                                &child_min, &child_nat);
+            {
+              clutter_container_child_get ((ClutterContainer*) self, child,
+                                           "x-fill", &child_fill,
+                                           NULL);
+              _st_actor_get_preferred_height (child,
+                                              for_length, child_fill,
+                                              &child_min, &child_nat);
+            }
           else
-            clutter_actor_get_preferred_width (child,
-                                               for_length,
-                                               &child_min, &child_nat);
+            {
+              clutter_container_child_get ((ClutterContainer*) self, child,
+                                           "y-fill", &child_fill,
+                                           NULL);
+              _st_actor_get_preferred_width (child,
+                                             for_length, child_fill,
+                                             &child_min, &child_nat);
+            }
 
           shrinks[i].shrink_amount = MAX (0., child_nat - child_min);
           n_possible_shrink_children++;
@@ -943,13 +965,13 @@ st_box_layout_allocate (ClutterActor          *actor,
 
       if (priv->is_vertical)
         {
-          clutter_actor_get_preferred_height (child, avail_width,
-                                              &child_min, &child_nat);
+          _st_actor_get_preferred_height (child, avail_width, xfill,
+                                          &child_min, &child_nat);
         }
       else
         {
-          clutter_actor_get_preferred_width (child, avail_height,
-                                             &child_min, &child_nat);
+          _st_actor_get_preferred_width (child, avail_height, yfill,
+                                         &child_min, &child_nat);
         }
 
       child_allocated = child_nat;
@@ -973,7 +995,8 @@ st_box_layout_allocate (ClutterActor          *actor,
           else
             child_box.x2 = content_box.x2;
 
-          _st_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill);
+          _st_allocate_fill (ST_WIDGET (actor), child, &child_box,
+                             xalign, yalign, xfill, yfill);
           clutter_actor_allocate (child, &child_box, flags);
 
         }
@@ -996,7 +1019,8 @@ st_box_layout_allocate (ClutterActor          *actor,
           else
             child_box.y2 = content_box.y2;
 
-          _st_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill);
+          _st_allocate_fill (ST_WIDGET (actor), child, &child_box,
+                             xalign, yalign, xfill, yfill);
           clutter_actor_allocate (child, &child_box, flags);
         }
 
diff --git a/src/st/st-private.c b/src/st/st-private.c
index 182e36d..7586e2b 100644
--- a/src/st/st-private.c
+++ b/src/st/st-private.c
@@ -1,12 +1,114 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 #include "st-private.h"
 
-/* Utility function to modify a child allocation box with respect to the
- * x/y-fill child properties. Expects childbox to contain the available
- * allocation space.
+/**
+ * _st_actor_get_preferred_width:
+ * @actor: a #ClutterActor
+ * @for_height: as with clutter_actor_get_preferred_width()
+ * @y_fill: %TRUE if @actor will fill its allocation vertically
+ * @min_width_p: as with clutter_actor_get_preferred_width()
+ * @natural_width_p: as with clutter_actor_get_preferred_width()
+ *
+ * Like clutter_actor_get_preferred_width(), but if @y_fill is %FALSE,
+ * then it will compute a width request based on the assumption that
+ * @actor will be given an allocation no taller than its natural
+ * height.
  */
 void
-_st_allocate_fill (ClutterActor    *child,
+_st_actor_get_preferred_width  (ClutterActor *actor,
+                                gfloat        for_height,
+                                gboolean      y_fill,
+                                gfloat       *min_width_p,
+                                gfloat       *natural_width_p)
+{
+  if (!y_fill && for_height != -1)
+    {
+      ClutterRequestMode mode;
+      gfloat natural_height;
+
+      g_object_get (G_OBJECT (actor), "request-mode", &mode, NULL);
+      if (mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT)
+        {
+          clutter_actor_get_preferred_height (actor, -1, NULL, &natural_height);
+          if (for_height > natural_height)
+            for_height = natural_height;
+        }
+    }
+
+  clutter_actor_get_preferred_width (actor, for_height, min_width_p, natural_width_p);
+}
+
+/**
+ * _st_actor_get_preferred_height:
+ * @actor: a #ClutterActor
+ * @for_width: as with clutter_actor_get_preferred_height()
+ * @x_fill: %TRUE if @actor will fill its allocation horizontally
+ * @min_height_p: as with clutter_actor_get_preferred_height()
+ * @natural_height_p: as with clutter_actor_get_preferred_height()
+ *
+ * Like clutter_actor_get_preferred_height(), but if @x_fill is
+ * %FALSE, then it will compute a height request based on the
+ * assumption that @actor will be given an allocation no wider than
+ * its natural width.
+ */
+void
+_st_actor_get_preferred_height (ClutterActor *actor,
+                                gfloat        for_width,
+                                gboolean      x_fill,
+                                gfloat       *min_height_p,
+                                gfloat       *natural_height_p)
+{
+  if (!x_fill && for_width != -1)
+    {
+      ClutterRequestMode mode;
+      gfloat natural_width;
+
+      g_object_get (G_OBJECT (actor), "request-mode", &mode, NULL);
+      if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
+        {
+          clutter_actor_get_preferred_width (actor, -1, NULL, &natural_width);
+          if (for_width > natural_width)
+            for_width = natural_width;
+        }
+    }
+
+  clutter_actor_get_preferred_height (actor, for_width, min_height_p, natural_height_p);
+}
+
+/**
+ * _st_allocate_fill:
+ * @parent: the parent #StWidget
+ * @child: the child (not necessarily an #StWidget)
+ * @childbox: total space that could be allocated to @child
+ * @x_alignment: horizontal alignment within @childbox
+ * @y_alignment: vertical alignment within @childbox
+ * @x_fill: whether or not to fill @childbox horizontally
+ * @y_fill: whether or not to fill @childbox vertically
+ *
+ * Given @childbox, containing the initial allocation of @child, this
+ * adjusts the horizontal allocation if @x_fill is %FALSE, and the
+ * vertical allocation if @y_fill is %FALSE, by:
+ *
+ *     - reducing the allocation if it is larger than @child's natural
+ *       size.
+ *
+ *     - adjusting the position of the child within the allocation
+ *       according to @x_alignment/@y_alignment (and flipping
+ *       @x_alignment if @parent has %ST_TEXT_DIRECTION_RTL)
+ *
+ * If @x_fill and @y_fill are both %TRUE, or if @child's natural size
+ * is larger than the initial allocation in @childbox, then @childbox
+ * will be unchanged.
+ *
+ * If you are allocating children with _st_allocate_fill(), you should
+ * determine their preferred sizes using
+ * _st_actor_get_preferred_width() and
+ * _st_actor_get_preferred_height(), not with the corresponding
+ * Clutter methods.
+ */
+void
+_st_allocate_fill (StWidget        *parent,
+                   ClutterActor    *child,
                    ClutterActorBox *childbox,
                    StAlign          x_alignment,
                    StAlign          y_alignment,
@@ -18,51 +120,36 @@ _st_allocate_fill (ClutterActor    *child,
   gfloat child_width, child_height;
   gfloat available_width, available_height;
   ClutterRequestMode request;
-  ClutterActorBox allocation = { 0, };
   gdouble x_align, y_align;
 
-  if (x_alignment == ST_ALIGN_START)
-    x_align = 0.0;
-  else if (x_alignment == ST_ALIGN_MIDDLE)
-    x_align = 0.5;
-  else
-    x_align = 1.0;
-
-  if (y_alignment == ST_ALIGN_START)
-    y_align = 0.0;
-  else if (y_alignment == ST_ALIGN_MIDDLE)
-    y_align = 0.5;
-  else
-    y_align = 1.0;
-
   available_width  = childbox->x2 - childbox->x1;
   available_height = childbox->y2 - childbox->y1;
 
   if (available_width < 0)
-    available_width = 0;
-
-  if (available_height < 0)
-    available_height = 0;
-
-  if (x_fill)
     {
-      allocation.x1 = childbox->x1;
-      allocation.x2 = (int)(allocation.x1 + available_width);
+      available_width = 0;
+      childbox->x2 = childbox->x1;
     }
 
-  if (y_fill)
+  if (available_height < 0)
     {
-      allocation.y1 = childbox->y1;
-      allocation.y2 = (int)(allocation.y1 + available_height);
+      available_height = 0;
+      childbox->y2 = childbox->y1;
     }
 
-  /* if we are filling horizontally and vertically then we're done */
+  /* If we are filling both horizontally and vertically then we don't
+   * need to do anything else.
+   */
   if (x_fill && y_fill)
-    {
-      *childbox = allocation;
-      return;
-    }
+    return;
 
+  _st_get_align_factors (parent, x_alignment, y_alignment,
+                         &x_align, &y_align);
+
+  /* The following is based on clutter_actor_get_preferred_size(), but
+   * modified to cope with the fact that the available size may be
+   * less than the preferred size.
+   */
   request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
   g_object_get (G_OBJECT (child), "request-mode", &request, NULL);
 
@@ -97,18 +184,82 @@ _st_allocate_fill (ClutterActor    *child,
 
   if (!x_fill)
     {
-      allocation.x1 = childbox->x1 + (int)((available_width - child_width) * x_align);
-      allocation.x2 = allocation.x1 + (int) child_width;
+      childbox->x1 += (int)((available_width - child_width) * x_align);
+      childbox->x2 = childbox->x1 + (int) child_width;
     }
 
   if (!y_fill)
     {
-      allocation.y1 = childbox->y1 + (int)((available_height - child_height) * y_align);
-      allocation.y2 = allocation.y1 + (int) child_height;
+      childbox->y1 += (int)((available_height - child_height) * y_align);
+      childbox->y2 = childbox->y1 + (int) child_height;
     }
+}
 
-  *childbox = allocation;
+/**
+ * _st_get_align_factors:
+ * @widget: an #StWidget
+ * @x_align: an #StAlign
+ * @y_align: an #StAlign
+ * @x_align_out: (out) (allow-none): @x_align as a #gdouble
+ * @y_align_out: (out) (allow-none): @y_align as a #gdouble
+ *
+ * Converts @x_align and @y_align to #gdouble values. If @widget has
+ * %ST_TEXT_DIRECTION_RTL, the @x_align_out value will be flipped
+ * relative to @x_align.
+ */
+void
+_st_get_align_factors (StWidget *widget,
+                       StAlign   x_align,
+                       StAlign   y_align,
+                       gdouble  *x_align_out,
+                       gdouble  *y_align_out)
+{
+  if (x_align_out)
+    {
+      switch (x_align)
+        {
+        case ST_ALIGN_START:
+          *x_align_out = 0.0;
+          break;
+
+        case ST_ALIGN_MIDDLE:
+          *x_align_out = 0.5;
+          break;
+
+        case ST_ALIGN_END:
+          *x_align_out = 1.0;
+          break;
+
+        default:
+          g_warn_if_reached ();
+          break;
+        }
 
+      if (st_widget_get_direction (widget) == ST_TEXT_DIRECTION_RTL)
+        *x_align_out = 1.0 - *x_align_out;
+    }
+
+  if (y_align_out)
+    {
+      switch (y_align)
+        {
+        case ST_ALIGN_START:
+          *y_align_out = 0.0;
+          break;
+
+        case ST_ALIGN_MIDDLE:
+          *y_align_out = 0.5;
+          break;
+
+        case ST_ALIGN_END:
+          *y_align_out = 1.0;
+          break;
+
+        default:
+          g_warn_if_reached ();
+          break;
+        }
+    }
 }
 
 /**
diff --git a/src/st/st-private.h b/src/st/st-private.h
index 42ac824..8368665 100644
--- a/src/st/st-private.h
+++ b/src/st/st-private.h
@@ -44,11 +44,25 @@ G_END_DECLS
 
 ClutterActor *_st_widget_get_dnd_clone (StWidget *widget);
 
-void _st_bin_get_align_factors (StBin   *bin,
-                                gdouble *x_align,
-                                gdouble *y_align);
+void _st_get_align_factors (StWidget *widget,
+                            StAlign   x_align,
+                            StAlign   y_align,
+                            gdouble  *x_align_out,
+                            gdouble  *y_align_out);
 
-void _st_allocate_fill (ClutterActor    *child,
+void _st_actor_get_preferred_width  (ClutterActor *actor,
+                                     gfloat        for_height,
+                                     gboolean      y_fill,
+                                     gfloat       *min_width_p,
+                                     gfloat       *natural_width_p);
+void _st_actor_get_preferred_height (ClutterActor *actor,
+                                     gfloat        for_width,
+                                     gboolean      x_fill,
+                                     gfloat       *min_height_p,
+                                     gfloat       *natural_height_p);
+
+void _st_allocate_fill (StWidget        *parent,
+                        ClutterActor    *child,
                         ClutterActorBox *childbox,
                         StAlign          x_align,
                         StAlign          y_align,
diff --git a/src/st/st-table.c b/src/st/st-table.c
index a2c16a4..878af0f 100644
--- a/src/st/st-table.c
+++ b/src/st/st-table.c
@@ -278,120 +278,6 @@ st_table_dispose (GObject *gobject)
   G_OBJECT_CLASS (st_table_parent_class)->dispose (gobject);
 }
 
-#define CLAMP_TO_PIXEL(x) ((float)((int)(x)))
-
-/* Utility function to modify a child allocation box with respect to the
- * x/y-fill child properties. Expects childbox to contain the available
- * allocation space.
- */
-static void
-st_table_allocate_fill (ClutterActor    *child,
-                        ClutterActorBox *childbox,
-                        gdouble          x_align,
-                        gdouble          y_align,
-                        gboolean         x_fill,
-                        gboolean         y_fill,
-                        gboolean         ltr)
-{
-  gfloat natural_width, natural_height;
-  gfloat min_width, min_height;
-  gfloat child_width, child_height;
-  gfloat available_width, available_height;
-  ClutterRequestMode request;
-  ClutterActorBox allocation = { 0, };
-
-  available_width  = childbox->x2 - childbox->x1;
-  available_height = childbox->y2 - childbox->y1;
-
-  if (available_width < 0)
-    available_width = 0;
-
-  if (available_height < 0)
-    available_height = 0;
-
-  if (x_fill)
-    {
-      if (ltr)
-        {
-          allocation.x1 = childbox->x1;
-          allocation.x2 = (int)(allocation.x1 + available_width);
-        }
-      else
-        {
-          allocation.x2 = childbox->x2;
-          allocation.x1 = (int)(allocation.x2 - available_width);
-        }
-    }
-
-  if (y_fill)
-    {
-      allocation.y1 = childbox->y1;
-      allocation.y2 = (int)(allocation.y1 + available_height);
-    }
-
-  /* if we are filling horizontally and vertically then we're done */
-  if (x_fill && y_fill)
-    {
-      *childbox = allocation;
-      return;
-    }
-
-  request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
-  g_object_get (G_OBJECT (child), "request-mode", &request, NULL);
-
-  if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
-    {
-      clutter_actor_get_preferred_width (child, available_height,
-                                         &min_width,
-                                         &natural_width);
-
-      child_width = CLAMP (natural_width, min_width, available_width);
-
-      clutter_actor_get_preferred_height (child, child_width,
-                                          &min_height,
-                                          &natural_height);
-
-      child_height = CLAMP (natural_height, min_height, available_height);
-    }
-  else
-    {
-      clutter_actor_get_preferred_height (child, available_width,
-                                          &min_height,
-                                          &natural_height);
-
-      child_height = CLAMP (natural_height, min_height, available_height);
-
-      clutter_actor_get_preferred_width (child, child_height,
-                                         &min_width,
-                                         &natural_width);
-
-      child_width = CLAMP (natural_width, min_width, available_width);
-    }
-
-  if (!x_fill)
-    {
-      if (ltr)
-        {
-          allocation.x1 = childbox->x1 + (int)((available_width - child_width) * x_align);
-          allocation.x2 = allocation.x1 + (int) child_width;
-        }
-      else
-        {
-          allocation.x2 = childbox->x2 - (int)((available_width - child_width) * x_align);
-          allocation.x1 = allocation.x2 - (int) child_width;
-        }
-    }
-
-  if (!y_fill)
-    {
-      allocation.y1 = childbox->y1 + (int)((available_height - child_height) * y_align);
-      allocation.y2 = allocation.y1 + (int) child_height;
-    }
-
-  *childbox = allocation;
-
-}
-
 static void
 st_table_homogeneous_allocate (ClutterActor          *self,
                                const ClutterActorBox *content_box,
@@ -453,7 +339,8 @@ st_table_homogeneous_allocate (ClutterActor          *self,
       childbox.y1 = content_box->y1 + (row_height + row_spacing) * row;
       childbox.y2 = childbox.y1 + (row_height * row_span) + (row_spacing * (row_span - 1));
 
-      st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill, ltr);
+      _st_allocate_fill (ST_WIDGET (self), child, &childbox,
+                         x_align, y_align, x_fill, y_fill);
 
       clutter_actor_allocate (child, &childbox, flags);
     }
@@ -510,7 +397,7 @@ st_table_calculate_col_widths (StTable *table,
       if (x_expand)
         is_expand_col[col] = TRUE;
 
-      clutter_actor_get_preferred_width (child, -1, &w_min, &w_pref);
+      _st_actor_get_preferred_width (child, -1, meta->y_fill, &w_min, &w_pref);
       if (col_span == 1 && w_pref > pref_widths[col])
         {
           pref_widths[col] = w_pref;
@@ -630,11 +517,12 @@ st_table_calculate_row_heights (StTable *table,
       if (!meta->x_fill)
         {
           gfloat width;
-          clutter_actor_get_preferred_width (child, -1, NULL, &width);
+          _st_actor_get_preferred_width (child, -1, meta->y_fill, NULL, &width);
           cell_width = MIN (cell_width, width);
         }
 
-      clutter_actor_get_preferred_height (child, cell_width, &h_min, &h_pref);
+      _st_actor_get_preferred_height (child, cell_width, meta->x_fill,
+                                      &h_min, &h_pref);
 
       if (row_span == 1 && h_pref > pref_heights[row])
         {
@@ -874,7 +762,8 @@ st_table_preferred_allocate (ClutterActor          *self,
       childbox.y2 = (float) MAX (0, child_y + row_height);
 
 
-      st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill, ltr);
+      _st_allocate_fill (ST_WIDGET (self), child, &childbox,
+                         x_align, y_align, x_fill, y_fill);
 
       clutter_actor_allocate (child, &childbox, flags);
     }
@@ -954,7 +843,7 @@ st_table_get_preferred_width (ClutterActor *self,
       col = meta->col;
       col_span = meta->col_span;
 
-      clutter_actor_get_preferred_width (child, -1, &w_min, &w_pref);
+      _st_actor_get_preferred_width (child, -1, meta->y_fill, &w_min, &w_pref);
 
       if (col_span == 1 && w_min > min_widths[col])
         min_widths[col] = w_min;
@@ -1041,8 +930,8 @@ st_table_get_preferred_height (ClutterActor *self,
       for (i = 0; i < col_span && col + i < priv->n_cols; i++)
         cell_width += min_widths[col + i];
 
-      clutter_actor_get_preferred_height (child,
-                                          (float) cell_width, &min, &pref);
+      _st_actor_get_preferred_height (child, (float) cell_width, meta->x_fill,
+                                      &min, &pref);
 
       if (row_span == 1 && min > min_heights[row])
         min_heights[row] = min;



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