[gtk+] Split up GtkWrapBox:spreading property into two orientation specific properties.



commit e976abe825e5bff0772e1944dc13a11ebbc7d755
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Tue Sep 21 18:31:02 2010 +0900

    Split up GtkWrapBox:spreading property into two orientation specific properties.
    
    Now GtkWrapBox has "horizontal-spreading" and "vertical-spreading" options,
    before GtkWrapBox never spread out children across the opposing orientation
    (i.e. it never grew "lines" larger then their natural width, they would
    act as if set to GTK_WRAP_BOX_SPREAD_START, now they are completely configurable).

 gtk/gtkenums.h      |   25 ++---
 gtk/gtkwrapbox.c    |  353 +++++++++++++++++++++++++++++++++++++++------------
 gtk/gtkwrapbox.h    |   11 +-
 tests/testwrapbox.c |   41 +++++--
 4 files changed, 320 insertions(+), 110 deletions(-)
---
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index cfff9f4..5305791 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -560,26 +560,19 @@ typedef enum {
 /**
  * GtkWrapBoxSpreading:
  * @GTK_WRAP_BOX_SPREAD_START:  Children are allocated no more than their natural size
- *                              in the layout's orientation and any extra space is left trailing at 
- *                              the end of each line.
+ *                              in the given orientation and any extra space is left trailing at 
+ *                              the end of each row/column.
  * @GTK_WRAP_BOX_SPREAD_END:    Children are allocated no more than their natural size
- *                              in the layout's orientation and any extra space skipped at the beginning
- *                              of each line.
+ *                              in the given orientation and any extra space skipped at the beginning
+ *                              of each row/column.
  * @GTK_WRAP_BOX_SPREAD_EVEN:   Children are allocated no more than their natural size
- *                              in the layout's orientation and any extra space is evenly distributed
+ *                              in the given orientation and any extra space is evenly distributed
  *                              as empty space between children.
- * @GTK_WRAP_BOX_SPREAD_EXPAND: Items share the extra space evenly (or among children that 'expand' when
- *                              in %GTK_WRAP_ALLOCATE_FREE mode.
- *
- * Describes how an #GtkWrapBox deals with extra space when allocating children.
- *
- * The box always tries to fit as many children at their natural size 
- * in the given orentation as possible with the exception of fitting "minimum-line-children"
- * items into the available size. When the available size is larger than
- * the size needed to fit a given number of children at their natural size
- * then extra space is available to distribute among children. The
- * #GtkWrapBoxSpreading option describes what to do with this space.
+ * @GTK_WRAP_BOX_SPREAD_EXPAND: Extra space is given to children which asked to expand in the given
+ *                              orientation (or columns/rows which contain children who asked to expand).
+ *                              If no children asked to expand; extra space is distributed evenly.
  *
+ * Describes how a #GtkWrapBox deals with extra space in a given orientation when allocating children.
  */
 typedef enum {
   GTK_WRAP_BOX_SPREAD_START = 0,
diff --git a/gtk/gtkwrapbox.c b/gtk/gtkwrapbox.c
index 3ce9f39..bb60def 100644
--- a/gtk/gtkwrapbox.c
+++ b/gtk/gtkwrapbox.c
@@ -45,7 +45,8 @@ enum {
   PROP_0,
   PROP_ORIENTATION,
   PROP_ALLOCATION_MODE,
-  PROP_SPREADING,
+  PROP_HORIZONTAL_SPREADING,
+  PROP_VERTICAL_SPREADING,
   PROP_HORIZONTAL_SPACING,
   PROP_VERTICAL_SPACING,
   PROP_MINIMUM_LINE_CHILDREN,
@@ -62,7 +63,8 @@ struct _GtkWrapBoxPrivate
 {
   GtkOrientation        orientation;
   GtkWrapAllocationMode mode;
-  GtkWrapBoxSpreading   spreading;
+  GtkWrapBoxSpreading   horizontal_spreading;
+  GtkWrapBoxSpreading   vertical_spreading;
 
   guint16               vertical_spacing;
   guint16               horizontal_spacing;
@@ -141,6 +143,18 @@ G_DEFINE_TYPE_WITH_CODE (GtkWrapBox, gtk_wrap_box, GTK_TYPE_CONTAINER,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
 
 
+#define ORIENTATION_SPREADING(box)					\
+  (((GtkWrapBox *)(box))->priv->orientation == GTK_ORIENTATION_HORIZONTAL ? \
+   ((GtkWrapBox *)(box))->priv->horizontal_spreading :			\
+   ((GtkWrapBox *)(box))->priv->vertical_spreading)
+
+#define OPPOSING_ORIENTATION_SPREADING(box)				\
+  (((GtkWrapBox *)(box))->priv->orientation == GTK_ORIENTATION_HORIZONTAL ? \
+   ((GtkWrapBox *)(box))->priv->vertical_spreading :			\
+   ((GtkWrapBox *)(box))->priv->horizontal_spreading)
+
+
+
 static void
 gtk_wrap_box_class_init (GtkWrapBoxClass *class)
 {
@@ -179,16 +193,31 @@ gtk_wrap_box_class_init (GtkWrapBoxClass *class)
                                                       GTK_PARAM_READWRITE));
 
   /**
-   * GtkWrapBox:spreading:
+   * GtkWrapBox:horizontal-spreading:
    *
    * The #GtkWrapBoxSpreading to used to define what is done with extra
-   * space.
+   * space in a given orientation.
    */
   g_object_class_install_property (gobject_class,
-                                   PROP_SPREADING,
-                                   g_param_spec_enum ("spreading",
-                                                      P_("Spreading"),
-                                                      P_("The spreading mode to use"),
+                                   PROP_HORIZONTAL_SPREADING,
+                                   g_param_spec_enum ("horizontal-spreading",
+                                                      P_("Horizontal Spreading"),
+                                                      P_("The spreading mode to use horizontally"),
+                                                      GTK_TYPE_WRAP_BOX_SPREADING,
+                                                      GTK_WRAP_BOX_SPREAD_START,
+                                                      GTK_PARAM_READWRITE));
+
+  /**
+   * GtkWrapBox:vertical-spreading:
+   *
+   * The #GtkWrapBoxSpreading to used to define what is done with extra
+   * space in a given orientation.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_VERTICAL_SPREADING,
+                                   g_param_spec_enum ("vertical-spreading",
+                                                      P_("Vertical Spreading"),
+                                                      P_("The spreading mode to use vertically"),
                                                       GTK_TYPE_WRAP_BOX_SPREADING,
                                                       GTK_WRAP_BOX_SPREAD_START,
                                                       GTK_PARAM_READWRITE));
@@ -291,12 +320,13 @@ gtk_wrap_box_init (GtkWrapBox *box)
   box->priv = priv =
     G_TYPE_INSTANCE_GET_PRIVATE (box, GTK_TYPE_WRAP_BOX, GtkWrapBoxPrivate);
 
-  priv->orientation        = GTK_ORIENTATION_HORIZONTAL;
-  priv->mode               = GTK_WRAP_ALLOCATE_FREE;
-  priv->spreading          = GTK_WRAP_BOX_SPREAD_START;
-  priv->vertical_spacing   = 0;
-  priv->horizontal_spacing = 0;
-  priv->children           = NULL;
+  priv->orientation          = GTK_ORIENTATION_HORIZONTAL;
+  priv->mode                 = GTK_WRAP_ALLOCATE_FREE;
+  priv->horizontal_spreading = GTK_WRAP_BOX_SPREAD_START;
+  priv->vertical_spreading   = GTK_WRAP_BOX_SPREAD_START;
+  priv->horizontal_spacing   = 0;
+  priv->vertical_spacing     = 0;
+  priv->children             = NULL;
 
   gtk_widget_set_has_window (GTK_WIDGET (box), FALSE);
 }
@@ -321,15 +351,18 @@ gtk_wrap_box_get_property (GObject      *object,
     case PROP_ALLOCATION_MODE:
       g_value_set_enum (value, priv->mode);
       break;
-    case PROP_SPREADING:
-      g_value_set_enum (value, priv->spreading);
+    case PROP_HORIZONTAL_SPREADING:
+      g_value_set_enum (value, priv->horizontal_spreading);
       break;
-    case PROP_VERTICAL_SPACING:
-      g_value_set_uint (value, priv->vertical_spacing);
+    case PROP_VERTICAL_SPREADING:
+      g_value_set_enum (value, priv->vertical_spreading);
       break;
     case PROP_HORIZONTAL_SPACING:
       g_value_set_uint (value, priv->horizontal_spacing);
       break;
+    case PROP_VERTICAL_SPACING:
+      g_value_set_uint (value, priv->vertical_spacing);
+      break;
     case PROP_MINIMUM_LINE_CHILDREN:
       g_value_set_uint (value, priv->minimum_line_children);
       break;
@@ -362,15 +395,18 @@ gtk_wrap_box_set_property (GObject      *object,
     case PROP_ALLOCATION_MODE:
       gtk_wrap_box_set_allocation_mode (box, g_value_get_enum (value));
       break;
-    case PROP_SPREADING:
-      gtk_wrap_box_set_spreading (box, g_value_get_enum (value));
+    case PROP_HORIZONTAL_SPREADING:
+      gtk_wrap_box_set_horizontal_spreading (box, g_value_get_enum (value));
       break;
-    case PROP_VERTICAL_SPACING:
-      gtk_wrap_box_set_vertical_spacing (box, g_value_get_uint (value));
+    case PROP_VERTICAL_SPREADING:
+      gtk_wrap_box_set_vertical_spreading (box, g_value_get_enum (value));
       break;
     case PROP_HORIZONTAL_SPACING:
       gtk_wrap_box_set_horizontal_spacing (box, g_value_get_uint (value));
       break;
+    case PROP_VERTICAL_SPACING:
+      gtk_wrap_box_set_vertical_spacing (box, g_value_get_uint (value));
+      break;
     case PROP_MINIMUM_LINE_CHILDREN:
       gtk_wrap_box_set_minimum_line_children (box, g_value_get_uint (value));
       break;
@@ -530,11 +566,10 @@ get_largest_size_for_line_in_opposing_orientation (GtkWrapBox       *box,
                                                    gint             *min_item_size,
                                                    gint             *nat_item_size)
 {
-  GtkWrapBoxPrivate *priv   = box->priv;
-  GList             *list;
-  gint               max_min_size = 0;
-  gint               max_nat_size = 0;
-  gint               i;
+  GList  *list;
+  gint    max_min_size = 0;
+  gint    max_nat_size = 0;
+  gint    i;
 
   for (list = cursor, i = 0; list && i < line_length; list = list->next)
     {
@@ -547,8 +582,7 @@ get_largest_size_for_line_in_opposing_orientation (GtkWrapBox       *box,
       /* Distribute the extra pixels to the first children in the line
        * (could be fancier and spread them out more evenly) */
       this_item_size = item_sizes[i].minimum_size;
-      if (extra_pixels > 0 &&
-          priv->spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+      if (extra_pixels > 0 && ORIENTATION_SPREADING (box) == GTK_WRAP_BOX_SPREAD_EXPAND)
         {
           this_item_size++;
           extra_pixels--;
@@ -679,7 +713,7 @@ get_largest_size_for_free_line_in_opposing_orientation (GtkWrapBox      *box,
     *extra_pixels = size;
 
   /* Cut out any expand space if we're not distributing any */
-  if (priv->spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
+  if (ORIENTATION_SPREADING (box) != GTK_WRAP_BOX_SPREAD_EXPAND)
     size = 0;
 
   /* Count how many children are going to expand... */
@@ -819,7 +853,7 @@ gather_aligned_item_requests (GtkWrapBox       *box,
       /* Get the index and push it over for the last line when spreading to the end */
       position = i % line_length;
 
-      if (priv->spreading == GTK_WRAP_BOX_SPREAD_END && i >= n_children - extra_items)
+      if (ORIENTATION_SPREADING (box) == GTK_WRAP_BOX_SPREAD_END && i >= n_children - extra_items)
         position += line_length - extra_items;
 
       /* Round up the size of every column/row */
@@ -893,6 +927,8 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
   GtkWrapBox         *box  = GTK_WRAP_BOX (widget);
   GtkWrapBoxPrivate  *priv = box->priv;
   gint                avail_size, avail_other_size, min_items, item_spacing, line_spacing;
+  GtkWrapBoxSpreading item_spreading;
+  GtkWrapBoxSpreading line_spreading;
 
   gtk_widget_set_allocation (widget, allocation);
 
@@ -913,7 +949,14 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
       line_spacing     = priv->horizontal_spacing;
     }
 
+  item_spreading = ORIENTATION_SPREADING (box);
+  line_spreading    = OPPOSING_ORIENTATION_SPREADING (box);
+
 
+  /*********************************************************
+   * Deal with ALIGNED/HOMOGENEOUS modes first, start with * 
+   * initial guesses at item/line sizes                    *
+   *********************************************************/
   if (priv->mode == GTK_WRAP_ALLOCATE_ALIGNED ||
       priv->mode == GTK_WRAP_ALLOCATE_HOMOGENEOUS)
     {
@@ -926,7 +969,8 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
       gint   line_size = 0, min_fixed_line_size = 0, nat_fixed_line_size = 0;
       gint   line_offset, item_offset, n_children, n_lines, line_count;
       gint   extra_pixels, extra_per_item = 0, extra_extra = 0;
-      gint   i;
+      gint   extra_line_pixels, extra_per_line = 0, extra_line_extra = 0;
+      gint   i, this_line_size;
 
       get_average_item_size (box, priv->orientation, &min_item_size, &nat_item_size);
 
@@ -958,7 +1002,7 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
           item_size = (avail_size - (line_length - 1) * item_spacing) / line_length;
           
           /* Cut out the expand space if we're not distributing any */
-          if (priv->spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
+          if (item_spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
             item_size = MIN (item_size, nat_item_size);
           
           get_largest_size_for_opposing_orientation (box, priv->orientation, item_size,
@@ -967,10 +1011,13 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
 
           /* resolve a fixed 'line_size' */
           line_size = (avail_other_size - (n_lines - 1) * line_spacing) / n_lines;
-          line_size = MIN (line_size, nat_fixed_line_size);
+
+	  if (line_spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
+	    line_size = MIN (line_size, nat_fixed_line_size);
 
           /* Get the real extra pixels incase of GTK_WRAP_BOX_SPREAD_START lines */
-          extra_pixels = avail_size - (line_length - 1) * item_spacing - item_size * line_length;
+          extra_pixels      = avail_size       - (line_length - 1) * item_spacing - item_size * line_length;
+	  extra_line_pixels = avail_other_size - (n_lines - 1)     * line_spacing - line_size * n_lines;
         }
       else /* GTK_WRAP_ALLOCATE_ALIGNED */
         {
@@ -1028,31 +1075,79 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
             }
 
           /* Distribute space among lines naturally */
-          avail_other_size = gtk_distribute_natural_allocation (avail_other_size, n_lines, line_sizes);
+          extra_line_pixels = gtk_distribute_natural_allocation (avail_other_size, n_lines, line_sizes);
         }
 
-      /* Calculate expand space per item (used diferently depending on spreading mode) */
-      if (priv->spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+      /*********************************************************
+       * Initial sizes of items/lines guessed at this point,   * 
+       * go on to distribute expand space if needed.           *
+       *********************************************************/
+
+      /* FIXME: This portion needs to consider which columns
+       * and rows asked for expand space and distribute those
+       * accordingly for the case of ALIGNED allocation.
+       *
+       * If at least one child in a column/row asked for expand;
+       * we should make that row/column expand entirely.
+       */
+
+      /* Calculate expand space per item */
+      if (item_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
         {
           extra_per_item = extra_pixels / MAX (line_length -1, 1);
           extra_extra    = extra_pixels % MAX (line_length -1, 1);
         }
-      else if (priv->spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+      else if (item_spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
         {
           extra_per_item = extra_pixels / line_length;
           extra_extra    = extra_pixels % line_length;
         }
 
+      /* Calculate expand space per line */
+      if (line_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+        {
+          extra_per_line   = extra_line_pixels / MAX (n_lines -1, 1);
+          extra_line_extra = extra_line_pixels % MAX (n_lines -1, 1);
+        }
+      else if (line_spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+        {
+          extra_per_line   = extra_line_pixels / n_lines;
+          extra_line_extra = extra_line_pixels % n_lines;
+        }
+
+      /*********************************************************
+       * Prepare item/line initial offsets and jump into the   *
+       * real allocation loop.                                 *
+       *********************************************************/
       line_offset = item_offset = 0;
 
-      /* prepend extra space to item_offset for SPREAD_END */
-      if (priv->spreading == GTK_WRAP_BOX_SPREAD_END)
+      /* prepend extra space to item_offset/line_offset for SPREAD_END */
+      if (item_spreading == GTK_WRAP_BOX_SPREAD_END)
         item_offset += extra_pixels;
 
+      if (line_spreading == GTK_WRAP_BOX_SPREAD_END)
+	line_offset += extra_line_pixels;
+
+      /* Get the allocation size for the first line */
+      if (priv->mode == GTK_WRAP_ALLOCATE_HOMOGENEOUS)
+	this_line_size = line_size;
+      else 
+	{
+	  this_line_size  = line_sizes[0].minimum_size;
+
+          if (line_spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+	    {
+	      this_line_size += extra_per_line;
+
+	      if (extra_line_extra > 0)
+		this_line_size++;
+	    }
+	}
+
       for (i = 0, line_count = 0, list = priv->children; list; list = list->next)
         {
           GtkWrapBoxChild *child = list->data;
-          gint             position, this_line_size;
+          gint             position;
           gint             this_item_size;
 
           if (!gtk_widget_get_visible (child->widget))
@@ -1064,16 +1159,38 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
           /* adjust the line_offset/count at the beginning of each new line */
           if (i > 0 && position == 0)
             {
-              if (priv->mode == GTK_WRAP_ALLOCATE_HOMOGENEOUS)
-                line_offset += line_size + line_spacing;
-              else /* aligned mode */
-                line_offset += line_sizes[line_count].minimum_size + line_spacing;
+	      /* Push the line_offset */
+	      line_offset += this_line_size + line_spacing;
+
+	      if (line_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+		{
+		  line_offset += extra_per_line;
+		      
+		  if (line_count < extra_line_extra)
+		    line_offset++;
+		}
 
               line_count++;
 
+	      /* Get the new line size */
+	      if (priv->mode == GTK_WRAP_ALLOCATE_HOMOGENEOUS)
+		this_line_size = line_size;
+	      else
+		{
+		  this_line_size = line_sizes[line_count].minimum_size;
+
+		  if (line_spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+		    {
+		      this_line_size += extra_per_line;
+		      
+		      if (line_count < extra_line_extra)
+			this_line_size++;
+		    }
+		}
+
               item_offset = 0;
 
-              if (priv->spreading == GTK_WRAP_BOX_SPREAD_END)
+              if (item_spreading == GTK_WRAP_BOX_SPREAD_END)
                 {
                   item_offset += extra_pixels;
 
@@ -1103,7 +1220,7 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
             }
 
           /* Push the index along for the last line when spreading to the end */
-          if (priv->spreading == GTK_WRAP_BOX_SPREAD_END &&
+          if (item_spreading == GTK_WRAP_BOX_SPREAD_END &&
               line_count == n_lines -1)
             {
               gint extra_items = n_children % line_length;
@@ -1116,22 +1233,14 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
           else /* aligned mode */
             this_item_size = item_sizes[position].minimum_size;
 
-          if (priv->spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+          if (item_spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
             {
               this_item_size += extra_per_item;
 
-              /* We could be smarter here and distribute the extra pixels more
-               * evenly across the children */
               if (position < extra_extra)
                 this_item_size++;
             }
 
-          /* Get the allocation size for this line */
-          if (priv->mode == GTK_WRAP_ALLOCATE_HOMOGENEOUS)
-            this_line_size = line_size;
-          else
-            this_line_size = line_sizes[line_count].minimum_size;
-
           /* Do the actual allocation */
           allocate_child (box, child, item_offset, line_offset, this_item_size, this_line_size);
 
@@ -1139,7 +1248,7 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
           item_offset += item_spacing;
 
           /* deal with extra spacing here */
-          if (priv->spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+          if (item_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
             {
               item_offset += extra_per_item;
 
@@ -1163,6 +1272,7 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
       gboolean          first_line = TRUE;
       gint              i, line_count = 0;
       gint              line_offset, item_offset;
+      gint              extra_per_line = 0, extra_line_extra = 0;
       gint              extra_pixels;
       GArray           *array;
   
@@ -1201,12 +1311,28 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
             }
         }
 
-      /* Distribute space among lines naturally, dont give lines expand space just let them
-       * unwrap/wrap in and out of the allocated extra space */
+      /* Distribute space among lines naturally */
       sizes            = (GtkRequestedSize *)array->data;
       avail_other_size = gtk_distribute_natural_allocation (avail_other_size, array->len, sizes);
 
-      for (line_offset = 0, line_count = 0; line_count < array->len; line_count++)
+      /* Calculate expand space per line */
+      if (line_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+        {
+          extra_per_line   = avail_other_size / MAX (array->len -1, 1);
+          extra_line_extra = avail_other_size % MAX (array->len -1, 1);
+        }
+      else if (line_spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+        {
+          extra_per_line   = avail_other_size / array->len;
+          extra_line_extra = avail_other_size % array->len;
+        }
+
+      if (line_spreading == GTK_WRAP_BOX_SPREAD_END)
+	line_offset = avail_other_size;
+      else
+	line_offset = 0;
+
+      for (line_count = 0; line_count < array->len; line_count++)
         {
           AllocatedLine    *line       = (AllocatedLine *)sizes[line_count].data;
           GArray           *line_array = line->requested;
@@ -1218,9 +1344,17 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
           /* Set line start offset */
           item_offset = 0;
 
-          if (priv->spreading == GTK_WRAP_BOX_SPREAD_END)
+	  if (line_spreading == GTK_WRAP_BOX_SPREAD_EXPAND)
+	    {
+	      line_size += extra_per_line;
+
+	      if (line_count < extra_line_extra)
+		line_size++;
+	    }
+
+          if (item_spreading == GTK_WRAP_BOX_SPREAD_END)
             item_offset += line->extra_pixels;
-          else if (priv->spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+          else if (item_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
             {
               extra_per_item = line->extra_pixels / MAX (line_array->len -1, 1);
               extra_extra    = line->extra_pixels % MAX (line_array->len -1, 1);
@@ -1229,13 +1363,13 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
           for (i = 0; i < line_array->len; i++)
             {
               GtkWrapBoxChild *child     = line_sizes[i].data;
-              gint                item_size = line_sizes[i].minimum_size;
+              gint             item_size = line_sizes[i].minimum_size;
 
               /* Do the actual allocation */
               allocate_child (box, child, item_offset, line_offset, item_size, line_size);
 
               /* Add extra space evenly between children */
-              if (priv->spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+              if (item_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
                 {
                   item_offset += extra_per_item;
                   if (i < extra_extra)
@@ -1251,6 +1385,14 @@ gtk_wrap_box_size_allocate (GtkWidget     *widget,
           line_offset += line_spacing;
           line_offset += line_size;
 
+	  if (line_spreading == GTK_WRAP_BOX_SPREAD_EVEN)
+	    {
+	      line_offset += extra_per_line;
+
+	      if (line_count < extra_line_extra)
+		line_offset++;
+	    }
+
           /* Free the array for this line now its not needed anymore */
           g_array_free (line_array, TRUE);
           g_slice_free (AllocatedLine, line);
@@ -1679,7 +1821,7 @@ gtk_wrap_box_get_height_for_width (GtkSizeRequest      *widget,
           item_size = (avail_size - (line_length - 1) * priv->horizontal_spacing) / line_length;
 
           /* Cut out the expand space if we're not distributing any */
-          if (priv->spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
+          if (priv->horizontal_spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
             {
               item_size    = MIN (item_size, nat_item_width);
               extra_pixels = 0;
@@ -1860,7 +2002,7 @@ gtk_wrap_box_get_width_for_height (GtkSizeRequest      *widget,
           item_size = (avail_size - (line_length - 1) * priv->vertical_spacing) / line_length;
 
           /* Cut out the expand space if we're not distributing any */
-          if (priv->spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
+          if (priv->vertical_spreading != GTK_WRAP_BOX_SPREAD_EXPAND)
             {
               item_size    = MIN (item_size, nat_item_height);
               extra_pixels = 0;
@@ -1985,7 +2127,8 @@ gtk_wrap_box_get_width_for_height (GtkSizeRequest      *widget,
 /**
  * gtk_wrap_box_new:
  * @mode: The #GtkWrapAllocationMode to use
- * @spreading: The #GtkWrapBoxSpreading policy to use
+ * @horizontal_spreading: The horizontal #GtkWrapBoxSpreading policy to use
+ * @vertical_spreading: The vertical #GtkWrapBoxSpreading policy to use
  * @horizontal_spacing: The horizontal spacing to add between children
  * @vertical_spacing: The vertical spacing to add between children
  *
@@ -1995,13 +2138,15 @@ gtk_wrap_box_get_width_for_height (GtkSizeRequest      *widget,
  */
 GtkWidget *
 gtk_wrap_box_new (GtkWrapAllocationMode mode,
-                  GtkWrapBoxSpreading   spreading,
+                  GtkWrapBoxSpreading   horizontal_spreading,
+                  GtkWrapBoxSpreading   vertical_spreading,
                   guint                 horizontal_spacing,
                   guint                 vertical_spacing)
 {
   return (GtkWidget *)g_object_new (GTK_TYPE_WRAP_BOX,
                                     "allocation-mode", mode,
-                                    "spreading", spreading,
+                                    "horizontal-spreading", horizontal_spreading,
+                                    "vertical-spreading", vertical_spreading,
                                     "vertical-spacing", vertical_spacing,
                                     "horizontal-spacing", horizontal_spacing,
                                     NULL);
@@ -2052,15 +2197,59 @@ gtk_wrap_box_get_allocation_mode (GtkWrapBox *box)
 
 
 /**
- * gtk_wrap_box_set_spreading:
+ * gtk_wrap_box_set_horizontal_spreading:
+ * @box: An #GtkWrapBox
+ * @spreading: The #GtkWrapBoxSpreading to use.
+ *
+ * Sets the horizontal spreading mode for @box's children.
+ */
+void
+gtk_wrap_box_set_horizontal_spreading (GtkWrapBox          *box,
+				       GtkWrapBoxSpreading  spreading)
+{
+  GtkWrapBoxPrivate *priv;
+
+  g_return_if_fail (GTK_IS_WRAP_BOX (box));
+
+  priv = box->priv;
+
+  if (priv->horizontal_spreading != spreading)
+    {
+      priv->horizontal_spreading = spreading;
+
+      gtk_widget_queue_resize (GTK_WIDGET (box));
+
+      g_object_notify (G_OBJECT (box), "horizontal-spreading");
+    }
+}
+
+/**
+ * gtk_wrap_box_get_horizontal_spreading:
+ * @box: An #GtkWrapBox
+ *
+ * Gets the horizontal spreading mode.
+ *
+ * Returns: The horizontal #GtkWrapBoxSpreading for @box.
+ */
+GtkWrapBoxSpreading
+gtk_wrap_box_get_horizontal_spreading (GtkWrapBox *box)
+{
+  g_return_val_if_fail (GTK_IS_WRAP_BOX (box), FALSE);
+
+  return box->priv->horizontal_spreading;
+}
+
+
+/**
+ * gtk_wrap_box_set_vertical_spreading:
  * @box: An #GtkWrapBox
  * @spreading: The #GtkWrapBoxSpreading to use.
  *
- * Sets the spreading mode for @box's children.
+ * Sets the vertical spreading mode for @box's children.
  */
 void
-gtk_wrap_box_set_spreading (GtkWrapBox          *box,
-                            GtkWrapBoxSpreading  spreading)
+gtk_wrap_box_set_vertical_spreading (GtkWrapBox          *box,
+				     GtkWrapBoxSpreading  spreading)
 {
   GtkWrapBoxPrivate *priv;
 
@@ -2068,30 +2257,30 @@ gtk_wrap_box_set_spreading (GtkWrapBox          *box,
 
   priv = box->priv;
 
-  if (priv->spreading != spreading)
+  if (priv->vertical_spreading != spreading)
     {
-      priv->spreading = spreading;
+      priv->vertical_spreading = spreading;
 
       gtk_widget_queue_resize (GTK_WIDGET (box));
 
-      g_object_notify (G_OBJECT (box), "spreading");
+      g_object_notify (G_OBJECT (box), "vertical-spreading");
     }
 }
 
 /**
- * gtk_wrap_box_get_spreading:
+ * gtk_wrap_box_get_vertical_spreading:
  * @box: An #GtkWrapBox
  *
- * Gets the spreading mode.
+ * Gets the vertical spreading mode.
  *
- * Returns: The #GtkWrapBoxSpreading for @box.
+ * Returns: The vertical #GtkWrapBoxSpreading for @box.
  */
 GtkWrapBoxSpreading
-gtk_wrap_box_get_spreading (GtkWrapBox *box)
+gtk_wrap_box_get_vertical_spreading (GtkWrapBox *box)
 {
   g_return_val_if_fail (GTK_IS_WRAP_BOX (box), FALSE);
 
-  return box->priv->spreading;
+  return box->priv->vertical_spreading;
 }
 
 
diff --git a/gtk/gtkwrapbox.h b/gtk/gtkwrapbox.h
index 5263771..266a63f 100644
--- a/gtk/gtkwrapbox.h
+++ b/gtk/gtkwrapbox.h
@@ -55,16 +55,21 @@ struct _GtkWrapBoxClass
 GType                 gtk_wrap_box_get_type                  (void) G_GNUC_CONST;
 
 GtkWidget            *gtk_wrap_box_new                       (GtkWrapAllocationMode mode,
-                                                              GtkWrapBoxSpreading   spreading,
+                                                              GtkWrapBoxSpreading   horizontal_spreading,
+							      GtkWrapBoxSpreading   vertical_spreading,
                                                               guint                 horizontal_spacing,
                                                               guint                 vertical_spacing);
 void                  gtk_wrap_box_set_allocation_mode       (GtkWrapBox           *box,
                                                               GtkWrapAllocationMode mode);
 GtkWrapAllocationMode gtk_wrap_box_get_allocation_mode       (GtkWrapBox           *box);
 
-void                  gtk_wrap_box_set_spreading             (GtkWrapBox           *box,
+void                  gtk_wrap_box_set_horizontal_spreading  (GtkWrapBox           *box,
                                                               GtkWrapBoxSpreading   spreading);
-GtkWrapBoxSpreading   gtk_wrap_box_get_spreading             (GtkWrapBox           *box);
+GtkWrapBoxSpreading   gtk_wrap_box_get_horizontal_spreading  (GtkWrapBox           *box);
+
+void                  gtk_wrap_box_set_vertical_spreading    (GtkWrapBox           *box,
+                                                              GtkWrapBoxSpreading   spreading);
+GtkWrapBoxSpreading   gtk_wrap_box_get_vertical_spreading    (GtkWrapBox           *box);
 
 void                  gtk_wrap_box_set_vertical_spacing      (GtkWrapBox           *box,
                                                               guint                 spacing);
diff --git a/tests/testwrapbox.c b/tests/testwrapbox.c
index 89a6cef..0fb92e1 100644
--- a/tests/testwrapbox.c
+++ b/tests/testwrapbox.c
@@ -34,7 +34,7 @@ enum {
 #define INITIAL_HSPACING        2
 #define INITIAL_VSPACING        2
 
-static GtkWrapBox *the_wrapbox       = NULL;
+static GtkWrapBox    *the_wrapbox       = NULL;
 static gint           items_type       = SIMPLE_ITEMS;
 static GtkOrientation text_orientation = GTK_ORIENTATION_HORIZONTAL;
 static gboolean       items_xexpand    = TRUE;
@@ -165,12 +165,21 @@ mode_changed (GtkComboBox   *box,
 }
 
 static void
-spreading_changed (GtkComboBox   *box,
-                   GtkWrapBox    *wrapbox)
+horizontal_spreading_changed (GtkComboBox   *box,
+			      GtkWrapBox    *wrapbox)
 {
   GtkWrapBoxSpreading spreading = gtk_combo_box_get_active (box);
   
-  gtk_wrap_box_set_spreading (wrapbox, spreading);
+  gtk_wrap_box_set_horizontal_spreading (wrapbox, spreading);
+}
+
+static void
+vertical_spreading_changed (GtkComboBox   *box,
+			    GtkWrapBox    *wrapbox)
+{
+  GtkWrapBoxSpreading spreading = gtk_combo_box_get_active (box);
+  
+  gtk_wrap_box_set_vertical_spreading (wrapbox, spreading);
 }
 
 static void
@@ -260,8 +269,8 @@ create_window (void)
   gtk_widget_show (swindow);
   gtk_container_add (GTK_CONTAINER (frame), swindow);
 
-  wrapbox = gtk_wrap_box_new (INITIAL_ALLOCATION_MODE, INITIAL_SPREADING, 
-                              INITIAL_HSPACING, INITIAL_VSPACING);
+  wrapbox = gtk_wrap_box_new (INITIAL_ALLOCATION_MODE, INITIAL_SPREADING,
+			      INITIAL_SPREADING, INITIAL_HSPACING, INITIAL_VSPACING);
   the_wrapbox = (GtkWrapBox *)wrapbox;
   gtk_wrap_box_set_minimum_line_children (GTK_WRAP_BOX (wrapbox), INITIAL_MINIMUM_LENGTH);
   gtk_widget_show (wrapbox);
@@ -290,7 +299,21 @@ create_window (void)
   g_signal_connect (G_OBJECT (widget), "changed",
                     G_CALLBACK (mode_changed), wrapbox);
 
-  /* Add Spreading control */
+  /* Add Spreading controls */
+  widget = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Spread Start");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Spread End");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Spread Even");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Spread Expand");
+  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), INITIAL_SPREADING);
+  gtk_widget_show (widget);
+
+  gtk_widget_set_tooltip_text (widget, "Set the horizontal spreading mode");
+  gtk_box_pack_start (GTK_BOX (wrapbox_cntl), widget, FALSE, FALSE, 0);
+
+  g_signal_connect (G_OBJECT (widget), "changed",
+                    G_CALLBACK (horizontal_spreading_changed), wrapbox);
+
   widget = gtk_combo_box_new_text ();
   gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Spread Start");
   gtk_combo_box_append_text (GTK_COMBO_BOX (widget), "Spread End");
@@ -299,11 +322,11 @@ create_window (void)
   gtk_combo_box_set_active (GTK_COMBO_BOX (widget), INITIAL_SPREADING);
   gtk_widget_show (widget);
 
-  gtk_widget_set_tooltip_text (widget, "Set the wrapbox spread mode");
+  gtk_widget_set_tooltip_text (widget, "Set the vertical spreading mode");
   gtk_box_pack_start (GTK_BOX (wrapbox_cntl), widget, FALSE, FALSE, 0);
 
   g_signal_connect (G_OBJECT (widget), "changed",
-                    G_CALLBACK (spreading_changed), wrapbox);
+                    G_CALLBACK (vertical_spreading_changed), wrapbox);
 
   /* Add Orientation control */
   widget = gtk_combo_box_new_text ();



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