]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkbox.c
Modify the gettext translation domain for the gtk3 rename
[~andy/gtk] / gtk / gtkbox.c
index 27c4de118ca0e4546f00363cbcc95771fefbd6e9..b9f5321c48156a21f9cd8220a3c04e944dd6dcd0 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
+/**
+ * SECTION:gtkbox
+ * @Short_description: Base class for box containers
+ * @Title: GtkBox
+ * @See_also:i #GtkHBox, #GtkVBox, #GtkFrame, #GtkTable, #GtkLayout
+ *
+ * GtkBox is an abstract widget which encapsulates functionality for a
+ * particular kind of container, one that organizes a variable number of
+ * widgets into a rectangular area.  GtkBox has a number of derived
+ * classes, e.g. #GtkHBox and #GtkVBox.
+ *
+ * The rectangular area of a GtkBox is organized into either a single row
+ * or a single column of child widgets depending upon whether the box is
+ * of type #GtkHBox or #GtkVBox, respectively.  Thus, all children of a
+ * GtkBox are allocated one dimension in common, which is the height of a
+ * row, or the width of a column.
+ *
+ * GtkBox uses a notion of <emphasis>packing</emphasis>.  Packing refers to
+ * adding widgets with reference to a particular position in a
+ * #GtkContainer.  For a GtkBox, there are two reference positions: the
+ * <emphasis>start</emphasis> and the <emphasis>end</emphasis> of the box.
+ * For a #GtkVBox, the start is defined as the top of the box and the end is
+ * defined as the bottom.  For a #GtkHBox the start is defined as the
+ * left side and the end is defined as the right side.
+ *
+ * Use repeated calls to gtk_box_pack_start() to pack widgets into a
+ * GtkBox from start to end.  Use gtk_box_pack_end() to add widgets from
+ * end to start.  You may intersperse these calls and add widgets from
+ * both ends of the same GtkBox.
+ *
+ * Use gtk_box_pack_start_defaults() or gtk_box_pack_end_defaults()
+ * to pack widgets into a GtkBox if you do not need to specify the
+ * #GtkBox:expand, #GtkBox:fill, or #GtkBox:padding child properties
+ * for the child to be added.
+ *
+ * Because GtkBox is a #GtkContainer, you may also use
+ * gtk_container_add() to insert widgets into the box, and they will be
+ * packed as if with gtk_box_pack_start_defaults().  Use
+ * gtk_container_remove() to remove widgets from the GtkBox.
+ *
+ * Use gtk_box_set_homogeneous() to specify whether or not all children
+ * of the GtkBox are forced to get the same amount of space.
+ *
+ * Use gtk_box_set_spacing() to determine how much space will be
+ * minimally placed between all children in the GtkBox.
+ *
+ * Use gtk_box_reorder_child() to move a GtkBox child to a different
+ * place in the box.
+ *
+ * Use gtk_box_set_child_packing() to reset the #GtkBox:expand,
+ * #GtkBox:fill and #GtkBox:padding child properties.
+ * Use gtk_box_query_child_packing() to query these fields.
+ */
+
 #include "config.h"
 
 #include "gtkbox.h"
@@ -109,19 +163,22 @@ static void gtk_box_get_child_property (GtkContainer   *container,
 static GType gtk_box_child_type        (GtkContainer   *container);
 
 
-static void gtk_box_extended_layout_init  (GtkExtendedLayoutIface *iface);
-static void gtk_box_get_desired_size      (GtkExtendedLayout      *layout,
-                                           GtkRequisition         *minimum_size,
-                                           GtkRequisition         *natural_size);
-static gboolean gtk_box_is_height_for_width (GtkExtendedLayout      *layout);
-static void gtk_box_get_width_for_height  (GtkExtendedLayout      *layout,
-                                          gint                    height,
-                                          gint                   *minimum_width,
-                                          gint                   *natural_width);
-static void gtk_box_get_height_for_width  (GtkExtendedLayout      *layout,
-                                          gint                    width,
-                                          gint                   *minimum_height,
-                                          gint                   *natural_height);
+static void     gtk_box_extended_layout_init (GtkExtendedLayoutIface *iface);
+static gboolean gtk_box_is_height_for_width  (GtkExtendedLayout      *layout);
+static void     gtk_box_get_desired_width    (GtkExtendedLayout      *layout,
+                                             gint                   *minimum_size,
+                                             gint                   *natural_size);
+static void     gtk_box_get_desired_height   (GtkExtendedLayout      *layout,
+                                             gint                   *minimum_size,
+                                             gint                   *natural_size);
+static void     gtk_box_get_width_for_height (GtkExtendedLayout      *layout,
+                                             gint                    height,
+                                             gint                   *minimum_width,
+                                             gint                   *natural_width);
+static void     gtk_box_get_height_for_width (GtkExtendedLayout      *layout,
+                                             gint                    width,
+                                             gint                   *minimum_height,
+                                             gint                   *natural_height);
 
 static GtkExtendedLayoutIface *parent_extended_layout_iface;
 
@@ -282,6 +339,27 @@ gtk_box_get_property (GObject    *object,
 }
 
 
+static void
+count_expand_children (GtkBox *box, gint *visible_children, gint *expand_children)
+{
+  GList       *children;
+  GtkBoxChild *child;
+
+  *visible_children = *expand_children = 0;
+
+  for (children = box->children; children; children = children->next)
+    {
+      child = children->data;
+
+      if (gtk_widget_get_visible (child->widget))
+       {
+         *visible_children += 1;
+         if (child->expand)
+           *expand_children += 1;
+       }
+    }
+}
+
 static gint
 gtk_box_compare_gap (gconstpointer p1,
                       gconstpointer p2,
@@ -306,7 +384,6 @@ gtk_box_compare_gap (gconstpointer p1,
   return delta;
 }
 
-
 static void
 gtk_box_size_allocate (GtkWidget     *widget,
                        GtkAllocation *allocation)
@@ -320,20 +397,7 @@ gtk_box_size_allocate (GtkWidget     *widget,
 
   widget->allocation = *allocation;
 
-  nvis_children = 0;
-  nexpand_children = 0;
-
-  for (children = box->children; children; children = children->next)
-    {
-      child = children->data;
-
-      if (gtk_widget_get_visible (child->widget))
-       {
-         nvis_children += 1;
-         if (child->expand)
-           nexpand_children += 1;
-       }
-    }
+  count_expand_children (box, &nvis_children, &nexpand_children);
 
   if (nvis_children > 0)
     {
@@ -347,7 +411,7 @@ gtk_box_size_allocate (GtkWidget     *widget,
 
       gint size;
       gint extra;
-      gint x, y, i;
+      gint x = 0, y = 0, i;
       gint child_size;
 
       if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -362,7 +426,7 @@ gtk_box_size_allocate (GtkWidget     *widget,
        {
          child = children->data;
          children = children->next;
-         
+
          if (gtk_widget_get_visible (child->widget))
            {
              if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -378,8 +442,22 @@ gtk_box_size_allocate (GtkWidget     *widget,
              
              
              /* Assert the api is working properly */
-             g_assert (sizes[i].minimum_size >= 0);
-             g_assert (sizes[i].natural_size >= sizes[i].minimum_size);
+             if (sizes[i].minimum_size < 0)
+               g_error ("GtkBox child %s minimum %s: %d < 0 for %s %d",
+                        gtk_widget_get_name (GTK_WIDGET (child->widget)),
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? "width" : "height",
+                        sizes[i].minimum_size,
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? "height" : "width",
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? allocation->height : allocation->width);
+
+             if (sizes[i].natural_size < sizes[i].minimum_size)
+               g_error ("GtkBox child %s natural %s: %d < minimum %d for %s %d",
+                        gtk_widget_get_name (GTK_WIDGET (child->widget)),
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? "width" : "height",
+                        sizes[i].natural_size, 
+                        sizes[i].minimum_size,
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? "height" : "width",
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? allocation->height : allocation->width);
              
              size -= sizes[i].minimum_size;
              size -= child->padding * 2;
@@ -531,9 +609,6 @@ gtk_box_size_allocate (GtkWidget     *widget,
                              child_allocation.width = sizes[i].minimum_size;
                               child_allocation.x = x + (child_size - child_allocation.width) / 2;
                            }
-                         
-                         if (direction == GTK_TEXT_DIR_RTL)
-                            child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
 
                           if (packing == GTK_PACK_START)
                            {
@@ -543,8 +618,12 @@ gtk_box_size_allocate (GtkWidget     *widget,
                            {
                              x -= child_size + box->spacing;
 
-                             child_allocation.x -= child_allocation.width;
+                             child_allocation.x -= child_size;
                            }
+
+                         if (direction == GTK_TEXT_DIR_RTL)
+                            child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
+
                         }
                       else /* (private->orientation == GTK_ORIENTATION_VERTICAL) */
                         {
@@ -567,11 +646,10 @@ gtk_box_size_allocate (GtkWidget     *widget,
                           {
                             y -= child_size + box->spacing;
 
-                            child_allocation.y -= child_allocation.height;
+                            child_allocation.y -= child_size;
                           }
                         }
                      gtk_widget_size_allocate (child->widget, &child_allocation);
-
                     }
 
                  i += 1;
@@ -742,285 +820,330 @@ gtk_box_pack (GtkBox      *box,
 }
 
 
-
 static void
 gtk_box_extended_layout_init (GtkExtendedLayoutIface *iface)
 {
   parent_extended_layout_iface = g_type_interface_peek_parent (iface);
 
   iface->is_height_for_width  = gtk_box_is_height_for_width;
-  iface->get_desired_size     = gtk_box_get_desired_size;
+  iface->get_desired_width    = gtk_box_get_desired_width;
+  iface->get_desired_height   = gtk_box_get_desired_height;
   iface->get_height_for_width = gtk_box_get_height_for_width;
   iface->get_width_for_height = gtk_box_get_width_for_height;
 }
 
 static gboolean 
-gtk_box_is_height_for_width (GtkExtendedLayout      *layout)
+gtk_box_is_height_for_width  (GtkExtendedLayout      *layout)
 {
   GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (layout);
 
-  return (private->orientation == GTK_ORIENTATION_HORIZONTAL);
+  return (private->orientation == GTK_ORIENTATION_VERTICAL);
 }
 
 static void
-gtk_box_get_desired_size (GtkExtendedLayout *layout,
-                          GtkRequisition    *minimum_size,
-                          GtkRequisition    *natural_size)
+gtk_box_get_desired_size (GtkExtendedLayout      *layout,
+                         GtkOrientation          orientation,
+                         gint                   *minimum_size,
+                         gint                   *natural_size)
 {
   GtkBox *box;
   GtkBoxPrivate *private;
   GList *children;
   gint nvis_children;
   gint border_width;
+  gint minimum, natural;
 
   box = GTK_BOX (layout);
   private = GTK_BOX_GET_PRIVATE (box);
   border_width = GTK_CONTAINER (box)->border_width;
 
-  minimum_size->width = minimum_size->height = 0;
-  natural_size->width = natural_size->height = 0;
+  minimum = natural = 0;
 
   nvis_children = 0;
-  children = box->children;
-  while (children)
-    {
-      GtkBoxChild *child;
 
-      child = children->data;
-      children = children->next;
+  for (children = box->children; children; children = children->next)
+    {
+      GtkBoxChild *child = children->data;
 
       if (gtk_widget_get_visible (child->widget))
         {
-          GtkRequisition child_minimum_size;
-          GtkRequisition child_natural_size;
-
-          gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (child->widget),
-                                               &child_minimum_size,
-                                               &child_natural_size);
-
-          if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
-            {
-              if (box->homogeneous)
-                {
-                  gint width;
-
-                  width = child_minimum_size.width + child->padding * 2;
-                  minimum_size->width = MAX (minimum_size->width, width);
+          gint child_minimum, child_natural;
 
-                  width = child_natural_size.width + child->padding * 2;
-                  natural_size->width = MAX (natural_size->width, width);
-                }
-              else
-                {
-                  minimum_size->width += child_minimum_size.width + child->padding * 2;
-                  natural_size->width += child_natural_size.width + child->padding * 2;
-                }
+         if (orientation == GTK_ORIENTATION_HORIZONTAL)
+           gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (child->widget),
+                                                  &child_minimum, &child_natural);
+         else
+           gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (child->widget),
+                                                   &child_minimum, &child_natural);
 
-              minimum_size->height = MAX (minimum_size->height, child_minimum_size.height);
-              natural_size->height = MAX (natural_size->height, child_natural_size.height);
-            }
-          else
-            {
+          if (private->orientation == orientation)
+           {
               if (box->homogeneous)
                 {
-                  gint height;
+                  gint largest;
 
-                  height = child_minimum_size.height + child->padding * 2;
-                  minimum_size->height = MAX (minimum_size->height, height);
+                  largest = child_minimum + child->padding * 2;
+                  minimum = MAX (minimum, largest);
 
-                  height = child_natural_size.height + child->padding * 2;
-                  natural_size->height = MAX (natural_size->height, height);
+                  largest = child_natural + child->padding * 2;
+                  natural = MAX (natural, largest);
                 }
               else
                 {
-                  minimum_size->height += child_minimum_size.height + child->padding * 2;
-                  natural_size->height += child_natural_size.height + child->padding * 2;
+                  minimum += child_minimum + child->padding * 2;
+                  natural += child_natural + child->padding * 2;
                 }
-
-              minimum_size->width = MAX (minimum_size->width, child_minimum_size.width);
-              natural_size->width = MAX (natural_size->width, child_natural_size.width);
-            }
-
+           }
+         else
+           {
+             /* The biggest mins and naturals in the opposing orientation */
+              minimum = MAX (minimum, child_minimum);
+              natural = MAX (natural, child_natural);
+           }
 
           nvis_children += 1;
         }
     }
-  if (nvis_children > 0)
+
+  if (nvis_children > 0 && private->orientation == orientation)
     {
-      if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
-        {
-          if (box->homogeneous)
-            {
-             minimum_size->width *= nvis_children;
-             natural_size->width *= nvis_children;
-            }
+      if (box->homogeneous)
+       {
+         minimum *= nvis_children;
+         natural *= nvis_children;
+       }
+      minimum += (nvis_children - 1) * box->spacing;
+      natural += (nvis_children - 1) * box->spacing;
+    }
 
-          minimum_size->width += (nvis_children - 1) * box->spacing;
-          natural_size->width += (nvis_children - 1) * box->spacing;
-        }
-      else
-        {
-          if (box->homogeneous)
-            {
-             minimum_size->height *= nvis_children;
-             natural_size->height *= nvis_children;
-            }
+  minimum += border_width * 2;
+  natural += border_width * 2;
 
-          minimum_size->height += (nvis_children - 1) * box->spacing;
-          natural_size->height += (nvis_children - 1) * box->spacing;
-        }
-    }
+  if (minimum_size)
+    *minimum_size = minimum;
 
-  minimum_size->width += border_width * 2;
-  minimum_size->height += border_width * 2;
+  if (natural_size)
+    *natural_size = natural;
+}
 
-  natural_size->width += border_width * 2;
-  natural_size->height += border_width * 2;
+static void
+gtk_box_get_desired_width (GtkExtendedLayout      *layout,
+                          gint                   *minimum_size,
+                          gint                   *natural_size)
+{
+  gtk_box_get_desired_size (layout, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
 }
 
+static void
+gtk_box_get_desired_height (GtkExtendedLayout      *layout,
+                           gint                   *minimum_size,
+                           gint                   *natural_size)
+{
+  gtk_box_get_desired_size (layout, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
+}
 
-/**
- * size_fits_for_dimension:
- * @box: a GtkBox
- * @avail_size: the allocated size in @box's opposing orientation
- * @check_size: the size in @box's orientation to check
- * @check_natural: whether to check natural sizes or minimum sizes.
- *
- * This checks if the required size of @box and its children fit into @avail_size
- * in @box's opposing orientation if @box were given @check_size as an allocation
- * in @box's orientation.
- *
- * In context: A GtkVBox will check if it fits into the available allocated height
- * if it were given the @check_size in width.
- *
- */
-static gboolean
-size_fits_for_dimension (GtkBox  *box,
-                        gint     avail_size,
-                        gint     check_size,
-                        gboolean check_natural)
+static void 
+gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
+                                              gint    avail_size,
+                                              gint   *minimum_size,
+                                              gint   *natural_size)
 {
   GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (box);
+  GtkBoxChild   *child;
   GList         *children;
-  gint           nvis_children = 0;
-  gint           required_size = 0, child_size;
-  gint           largest_child = 0;
+  gint           nvis_children;
+  gint           nexpand_children;
+  gint           computed_minimum = 0, computed_natural = 0;
+  gint           border_width = GTK_CONTAINER (box)->border_width;
 
-  avail_size -= GTK_CONTAINER (box)->border_width * 2;
+  count_expand_children (box, &nvis_children, &nexpand_children);
 
-  for (children = box->children; children != NULL; 
-       children = children->next, nvis_children++)
+  if (nvis_children > 0)
     {
-      GtkBoxChild *child = children->data;
+      GtkBoxSpreading     *spreading    = g_newa (GtkBoxSpreading, nvis_children);
+      GtkBoxDesiredSizes  *sizes        = g_newa (GtkBoxDesiredSizes, nvis_children);
+      GtkPackType          packing;
+      gint                 size;
+      gint                 extra, i;
+      gint                 child_size, child_minimum, child_natural;
 
-      if (gtk_widget_get_visible (child->widget))
-        {
+      size = avail_size - border_width * 2 - (nvis_children - 1) * box->spacing;
 
-          if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
-           {
-             if (check_natural)
-               gtk_extended_layout_get_width_for_height (GTK_EXTENDED_LAYOUT (child->widget),
-                                                         avail_size, NULL, &child_size);
-             else
-               gtk_extended_layout_get_width_for_height (GTK_EXTENDED_LAYOUT (child->widget),
-                                                         avail_size, &child_size, NULL);
-           }
-         else
+      /* Retrieve desired size for visible children */
+      for (i = 0, children = box->children; children; children = children->next)
+       {
+         child = children->data;
+         
+         if (gtk_widget_get_visible (child->widget))
            {
-             if (check_natural)
-               gtk_extended_layout_get_height_for_width (GTK_EXTENDED_LAYOUT (child->widget),
-                                                         avail_size, NULL, &child_size);
+             if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
+               gtk_extended_layout_get_desired_width (GTK_EXTENDED_LAYOUT (child->widget),
+                                                      &sizes[i].minimum_size,
+                                                      &sizes[i].natural_size);
              else
-               gtk_extended_layout_get_height_for_width (GTK_EXTENDED_LAYOUT (child->widget),
-                                                         avail_size, &child_size, NULL);
+               gtk_extended_layout_get_desired_height (GTK_EXTENDED_LAYOUT (child->widget),
+                                                       &sizes[i].minimum_size,
+                                                       &sizes[i].natural_size);
+             
+             /* Assert the api is working properly */
+             if (sizes[i].minimum_size < 0)
+               g_error ("GtkBox child %s minimum %s: %d < 0",
+                        gtk_widget_get_name (GTK_WIDGET (child->widget)),
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? "width" : "height",
+                        sizes[i].minimum_size);
+
+             if (sizes[i].natural_size < sizes[i].minimum_size)
+               g_error ("GtkBox child %s natural %s: %d < minimum %d",
+                        gtk_widget_get_name (GTK_WIDGET (child->widget)),
+                        (private->orientation == GTK_ORIENTATION_HORIZONTAL) ? "width" : "height",
+                        sizes[i].natural_size, 
+                        sizes[i].minimum_size);
+
+             size -= sizes[i].minimum_size;
+             size -= child->padding * 2;
+             
+             spreading[i].index = i;
+             spreading[i].child = child;
+             
+             i += 1;
            }
+       }
 
-         child_size += child->padding * 2;
+      if (box->homogeneous)
+       {
+         /* If were homogenous we still need to run the above loop to get the minimum sizes
+          * for children that are not going to fill 
+          */
+         size = avail_size - border_width * 2 - (nvis_children - 1) * box->spacing;
+          extra = size / nvis_children;
+        }
+      else
+       {
 
-         if (child_size > largest_child)
-           largest_child = child_size;
+          /* Distribute the container's extra space c_gap. We want to assign
+           * this space such that the sum of extra space assigned to children
+           * (c^i_gap) is equal to c_cap. The case that there's not enough
+           * space for all children to take their natural size needs some
+           * attention. The goals we want to achieve are:
+           *
+           *   a) Maximize number of children taking their natural size.
+           *   b) The allocated size of children should be a continuous
+           *   function of c_gap.  That is, increasing the container size by
+           *   one pixel should never make drastic changes in the distribution.
+           *   c) If child i takes its natural size and child j doesn't,
+           *   child j should have received at least as much gap as child i.
+           *
+           * The following code distributes the additional space by following
+           * this rules.
+           */
 
-         required_size += child_size;
-        }
-    }
+          /* Sort descending by gap and position. */
 
-  if (nvis_children > 0)
-    {
-      if (box->homogeneous)
-       required_size = largest_child * nvis_children;
+          g_qsort_with_data (spreading,
+                             nvis_children, sizeof (GtkBoxSpreading),
+                             gtk_box_compare_gap, sizes);
 
-      required_size += (nvis_children - 1) * box->spacing;
-    }
+          /* Distribute available space.
+           * This master piece of a loop was conceived by Behdad Esfahbod.
+           */
+          for (i = nvis_children - 1; i >= 0; --i)
+            {
+              /* Divide remaining space by number of remaining children.
+               * Sort order and reducing remaining space by assigned space
+               * ensures that space is distributed equally.
+               */
+              gint glue = (size + i) / (i + 1);
+              gint gap = sizes[spreading[i].index].natural_size
+                       - sizes[spreading[i].index].minimum_size;
 
-  required_size += GTK_CONTAINER (box)->border_width * 2;
+              extra = MIN (glue, gap);
+              sizes[spreading[i].index].minimum_size += extra;
 
-  return required_size <= check_size;
-}
+              size -= extra;
+            }
 
+          /* Calculate space which hasn't distributed yet,
+           * and is available for expanding children.
+           */
+          if (nexpand_children > 0)
+            extra = size / nexpand_children;
+          else
+            extra = 0;
+        }
 
-static void 
-gtk_box_bisect_for_size_in_opposing_orientation (GtkBox   *box,
-                                                gboolean  check_natural,
-                                                gint      avail_size,
-                                                gint      floor,
-                                                gint      ceiling,
-                                                gint     *size)
-{
-  if (ceiling - floor <= 1)
-    *size = ceiling;
-  else
-    {
-      gint check_size = floor + (ceiling - floor) / 2;
+      /* Allocate child positions. */
+      for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
+        {
+          for (i = 0, children = box->children; children; children = children->next)
+           {
+             child = children->data;
+
+             if (gtk_widget_get_visible (child->widget))
+               {
+                  if (child->pack == packing)
+                    {
+                      /* Assign the child's size. */
+                     if (box->homogeneous)
+                       {
+                         if (nvis_children == 1)
+                            child_size = size;
+                         else
+                            child_size = extra;
+
+                         nvis_children -= 1;
+                         size -= extra;
+                       }
+                     else
+                       {
+                         child_size = sizes[i].minimum_size + child->padding * 2;
+
+                         if (child->expand)
+                           {
+                             if (nexpand_children == 1)
+                                child_size += size;
+                             else
+                                child_size += extra;
 
-      if (size_fits_for_dimension (box, avail_size, check_size, check_natural))
+                             nexpand_children -= 1;
+                             size -= extra;
+                           }
+                       }
 
-       /* If check_size is large enough for box to fit into avail_size, we go on
-        * to check between the given floor and check_size as the new ceiling
-        */
+                     if (child->fill)
+                       {
+                         child_size = MAX (1, child_size - child->padding * 2);
+                       }
+                     else
+                       {
+                         child_size = sizes[i].minimum_size;
+                       }
 
-       gtk_box_bisect_for_size_in_opposing_orientation (box, check_natural, avail_size,
-                                                        floor, check_size, size);
-      else
-       gtk_box_bisect_for_size_in_opposing_orientation (box, check_natural, avail_size,
-                                                        check_size, ceiling, size);
 
+                      /* Assign the child's position. */
+                      if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
+                       gtk_extended_layout_get_height_for_width (GTK_EXTENDED_LAYOUT (child->widget),
+                                                                 child_size, &child_minimum, &child_natural);
+                      else /* (private->orientation == GTK_ORIENTATION_VERTICAL) */
+                       gtk_extended_layout_get_width_for_height (GTK_EXTENDED_LAYOUT (child->widget),
+                                                                 child_size, &child_minimum, &child_natural);
+
+                     
+                     computed_minimum = MAX (computed_minimum, child_minimum);
+                     computed_natural = MAX (computed_natural, child_natural);
+                    }
+                 i += 1;
+                }
+           }
+       }
     }
-}
 
-static void 
-gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
-                                              gint    avail_size,
-                                              gint   *minimum_size,
-                                              gint   *natural_size)
-{
-  gint minimum, natural;
-  gint min_ceiling, nat_ceiling;
-  gint step = 200;
-
-  /* First a large gap to search inside of
-   */
-  for (min_ceiling = (step + 1); !size_fits_for_dimension (box, avail_size, min_ceiling, FALSE); min_ceiling += step);
-
-  /* This will find the minimum sizes by halfing the guesses until they are found
-   */
-  gtk_box_bisect_for_size_in_opposing_orientation (box, FALSE, avail_size,
-                                                  min_ceiling - step,
-                                                  min_ceiling,
-                                                  &minimum);
-
-  /* Basing the natural size on the found minimum, do the same operation for the natural size */
-  for (nat_ceiling = minimum + step; !size_fits_for_dimension (box, avail_size, nat_ceiling, TRUE); nat_ceiling += step);
-  gtk_box_bisect_for_size_in_opposing_orientation (box, TRUE, avail_size,
-                                                  nat_ceiling - step,
-                                                  nat_ceiling,
-                                                  &natural);
+  computed_minimum += border_width * 2;
+  computed_natural += border_width * 2;
 
   if (minimum_size)
-    *minimum_size = minimum;
-
+    *minimum_size = computed_minimum;
   if (natural_size)
-    *natural_size = natural;
-
+    *natural_size = computed_natural;
 }  
 
 static void 
@@ -1099,14 +1222,7 @@ gtk_box_get_width_for_height (GtkExtendedLayout *layout,
   GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (layout);
 
   if (private->orientation == GTK_ORIENTATION_VERTICAL)
-    {
-#if 0
     gtk_box_compute_size_for_opposing_orientation (box, height, minimum_width, natural_width); 
-#else
-    /* Have the base class return the values previously computed by get_desired_size() */  
-    parent_extended_layout_iface->get_width_for_height (layout, height, minimum_width, natural_width);
-#endif
-    }
   else
     gtk_box_compute_size_for_orientation (box, height, minimum_width, natural_width);
 }
@@ -1121,14 +1237,7 @@ gtk_box_get_height_for_width (GtkExtendedLayout *layout,
   GtkBoxPrivate *private = GTK_BOX_GET_PRIVATE (layout);
 
   if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
-    {
-#if 0
-      gtk_box_compute_size_for_opposing_orientation (box, width, minimum_height, natural_height);
-#else
-      /* Have the base class return the values previously computed by get_desired_size() */
-      parent_extended_layout_iface->get_height_for_width (layout, width, minimum_height, natural_height);
-#endif
-    }
+    gtk_box_compute_size_for_opposing_orientation (box, width, minimum_height, natural_height);
   else
     gtk_box_compute_size_for_orientation (box, width, minimum_height, natural_height);
 }
@@ -1221,50 +1330,6 @@ gtk_box_pack_end (GtkBox    *box,
   gtk_box_pack (box, child, expand, fill, padding, GTK_PACK_END);
 }
 
-/**
- * gtk_box_pack_start_defaults:
- * @box: a #GtkBox
- * @widget: the #GtkWidget to be added to @box
- *
- * Adds @widget to @box, packed with reference to the start of @box.
- * The child is packed after any other child packed with reference 
- * to the start of @box. 
- * 
- * Parameters for how to pack the child @widget, #GtkBox:expand, 
- * #GtkBox:fill and #GtkBox:padding, are given their default
- * values, %TRUE, %TRUE, and 0, respectively.
- *
- * Deprecated: 2.14: Use gtk_box_pack_start()
- */
-void
-gtk_box_pack_start_defaults (GtkBox    *box,
-                            GtkWidget *child)
-{
-  gtk_box_pack_start (box, child, TRUE, TRUE, 0);
-}
-
-/**
- * gtk_box_pack_end_defaults:
- * @box: a #GtkBox
- * @widget: the #GtkWidget to be added to @box
- *
- * Adds @widget to @box, packed with reference to the end of @box.
- * The child is packed after any other child packed with reference 
- * to the start of @box. 
- * 
- * Parameters for how to pack the child @widget, #GtkBox:expand, 
- * #GtkBox:fill and #GtkBox:padding, are given their default
- * values, %TRUE, %TRUE, and 0, respectively.
- *
- * Deprecated: 2.14: Use gtk_box_pack_end()
- */
-void
-gtk_box_pack_end_defaults (GtkBox    *box,
-                          GtkWidget *child)
-{
-  gtk_box_pack_end (box, child, TRUE, TRUE, 0);
-}
-
 /**
  * gtk_box_set_homogeneous:
  * @box: a #GtkBox