[gtk+/grid-widget: 5/20] More work



commit 32cb9951c5295ab14fc1c9e9c82310bd3efb8351
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Oct 6 01:53:39 2010 -0400

    More work
    
    Make it actually build.
    Implement GtkOrientable.

 gtk/gtkgrid.c |  729 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 641 insertions(+), 88 deletions(-)
---
diff --git a/gtk/gtkgrid.c b/gtk/gtkgrid.c
index ba8af15..1828746 100644
--- a/gtk/gtkgrid.c
+++ b/gtk/gtkgrid.c
@@ -1,7 +1,6 @@
 /* TODO
- * - size allocation
  * - wfh
- * - orientable
+ * - magic expand
  */
 
 /* GTK - The GIMP Toolkit
@@ -27,6 +26,8 @@
 #include "config.h"
 
 #include "gtkgrid.h"
+
+#include "gtkorientable.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 
@@ -49,7 +50,9 @@ struct _GtkGridRowCol
 {
   guint requisition;
   guint allocation;
+  gboolean need_expand;
   gboolean expand;
+  gboolean empty;
 };
 
 struct _GtkGridPrivate
@@ -66,6 +69,8 @@ struct _GtkGridPrivate
   gint16 row_spacing;
   gint16 column_spacing;
 
+  GtkOrientation orientation;
+
   guint row_homogeneous    : 1;
   guint column_homogeneous : 1;
 };
@@ -73,6 +78,7 @@ struct _GtkGridPrivate
 enum
 {
   PROP_0,
+  PROP_ORIENTATION,
   PROP_ROW_SPACING,
   PROP_COLUMN_SPACING,
   PROP_ROW_HOMOGENEOUS,
@@ -85,10 +91,13 @@ enum
   CHILD_PROP_LEFT_ATTACH,
   CHILD_PROP_TOP_ATTACH,
   CHILD_PROP_WIDTH,
-  CHILD_PROP_HEIGHT
+  CHILD_PROP_HEIGHT,
+  CHILD_PROP_HEXPAND,
+  CHILD_PROP_VEXPAND
 };
 
-G_DEFINE_TYPE (GtkGrid, gtk_grid, GTK_TYPE_CONTAINER);
+G_DEFINE_TYPE_WITH_CODE (GtkGrid, gtk_grid, GTK_TYPE_CONTAINER,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
 
 static void
 gtk_grid_finalize (GObject *object)
@@ -97,7 +106,7 @@ gtk_grid_finalize (GObject *object)
   GtkGridPrivate *priv = grid->priv;
 
   g_free (priv->rows);
-  g_free (priv->cols);
+  g_free (priv->columns);
 
   G_OBJECT_CLASS (gtk_grid_parent_class)->finalize (object);
 }
@@ -113,6 +122,10 @@ gtk_grid_get_property (GObject    *object,
 
   switch (prop_id)
     {
+    case PROP_ORIENTATION:
+      g_value_set_enum (value, priv->orientation);
+      break;
+
     case PROP_ROW_SPACING:
       g_value_set_int (value, priv->row_spacing);
       break;
@@ -136,6 +149,66 @@ gtk_grid_get_property (GObject    *object,
 }
 
 static void
+gtk_grid_resize (GtkGrid *grid)
+{
+  GtkGridPrivate *priv = grid->priv;
+
+  g_free (priv->rows);
+  g_free (priv->columns);
+  priv->rows = NULL;
+  priv->columns = NULL;
+}
+
+static void
+gtk_grid_set_orientation (GtkGrid        *grid,
+                          GtkOrientation  orientation)
+{
+  GtkGridPrivate *priv = grid->priv;
+  GList *list;
+  GtkGridChild *child;
+  gint left, top, width, height;
+
+  if (priv->orientation != orientation)
+    {
+      priv->orientation = orientation;
+
+      g_object_notify (G_OBJECT (grid), "orientation");
+
+      for (list = priv->children; list; list = list->next)
+        {
+          child = list->data;
+
+          left = child->left;
+          top = child->top;
+          width = child->width;
+          height = child->height;
+
+          if (orientation == GTK_ORIENTATION_VERTICAL)
+            {
+              child->top = left;
+              child->left = - (top + height);
+              child->width = height;
+              child->height = width;
+            }
+          else
+            {
+              child->left = top;
+              child->top = - (left + width);
+              child->width = height;
+              child->height = width;
+            }
+          gtk_widget_child_notify (child->widget, "left");
+          gtk_widget_child_notify (child->widget, "top");
+          gtk_widget_child_notify (child->widget, "width");
+          gtk_widget_child_notify (child->widget, "height");
+        }
+
+      gtk_grid_resize (grid);
+      gtk_widget_queue_resize (GTK_WIDGET (grid));
+    }
+}
+
+static void
 gtk_grid_set_property (GObject      *object,
                        guint         prop_id,
                        const GValue *value,
@@ -145,6 +218,10 @@ gtk_grid_set_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_ORIENTATION:
+      gtk_grid_set_orientation (grid, g_value_get_enum (value));
+      break;
+
     case PROP_ROW_SPACING:
       gtk_grid_set_row_spacing (grid, g_value_get_int (value));
       break;
@@ -222,6 +299,14 @@ gtk_grid_get_child_property (GtkContainer *container,
       g_value_set_int (value, grid_child->height);
       break;
 
+    case CHILD_PROP_HEXPAND:
+      g_value_set_boolean (value, grid_child->hexpand);
+      break;
+
+    case CHILD_PROP_VEXPAND:
+      g_value_set_boolean (value, grid_child->vexpand);
+      break;
+
     default:
       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
       break;
@@ -229,17 +314,6 @@ gtk_grid_get_child_property (GtkContainer *container,
 }
 
 static void
-gtk_grid_resize (GtkGrid *grid)
-{
-  GtkGridPrivate *priv = grid->priv;
-
-  g_free (priv->rows);
-  g_free (priv->cols);
-  priv->rows = NULL;
-  priv->cols = NULL;
-}
-
-static void
 gtk_grid_set_child_property (GtkContainer *container,
                              GtkWidget    *child,
                              guint         property_id,
@@ -247,9 +321,7 @@ gtk_grid_set_child_property (GtkContainer *container,
                              GParamSpec   *pspec)
 {
   GtkGrid *grid = GTK_GRID (container);
-  GtkGridPrivate *priv = grid->priv;
   GtkGridChild *grid_child;
-  gint right, bottom;
 
   grid_child = find_grid_child (grid, child);
 
@@ -281,6 +353,16 @@ gtk_grid_set_child_property (GtkContainer *container,
       gtk_grid_resize (grid);
       break;
 
+   case CHILD_PROP_HEXPAND:
+      grid_child->hexpand = g_value_get_boolean (value);
+      gtk_widget_queue_resize (GTK_WIDGET (grid));
+      break;
+
+   case CHILD_PROP_VEXPAND:
+      grid_child->vexpand = g_value_get_boolean (value);
+      gtk_widget_queue_resize (GTK_WIDGET (grid));
+      break;
+
     default:
       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
       break;
@@ -313,6 +395,7 @@ gtk_grid_init (GtkGrid *grid)
   priv->column_spacing = 0;
   priv->row_homogeneous = FALSE;
   priv->column_homogeneous = FALSE;
+  priv->orientation = GTK_ORIENTATION_HORIZONTAL;
 }
 
 static void grid_attach (GtkGrid   *grid,
@@ -330,19 +413,35 @@ gtk_grid_add (GtkContainer *container,
   GtkGridPrivate *priv = grid->priv;
   GtkGridChild *grid_child;
   GList *list;
-  gint right;
+  gint left, top;
 
-  /* stack horizontally */
-  right = 0;
-  for (list = priv->children; list; list = list->next)
+  left = 0;
+  top = 0;
+
+  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
     {
-      grid_child = list->data;
+      /* stack horizontally */
+      for (list = priv->children; list; list = list->next)
+        {
+          grid_child = list->data;
 
-      if (grid_child->top <= 0 && grid_child->top + grid_child->height > 0)
-        right = MAX (right, grid_child->left + grid_child->width);
+          if (grid_child->top <= 0 && grid_child->top + grid_child->height > 0)
+            left = MAX (left, grid_child->left + grid_child->width);
+        }
     }
+  else
+    {
+      /* stack vertically */
+      for (list = priv->children; list; list = list->next)
+        {
+          grid_child = list->data;
 
-  grid_attach (grid, child, right, 0, 1, 1);
+          if (grid_child->left <= 0 && grid_child->left + grid_child->width > 0)
+            top = MAX (top, grid_child->top + grid_child->height);
+        }
+    }
+
+  grid_attach (grid, child, left, top, 1, 1);
 }
 
 static void
@@ -408,7 +507,7 @@ gtk_grid_allocate_rowcols (GtkGrid *grid)
   GList *list;
   gint minrow, maxrow, mincol, maxcol;
 
-  if (priv->rows && priv->cols)
+  if (priv->rows && priv->columns)
     return;
 
   minrow = mincol = G_MAXINT;
@@ -439,12 +538,15 @@ gtk_grid_allocate_rowcols (GtkGrid *grid)
   priv->columns = g_new (GtkGridRowCol, maxcol - mincol);
 }
 
+/* set requisitions to 0, mark rows/cols as expand
+ * if they have a non-spanning exanding child
+ */
 static void
 gtk_grid_size_request_init (GtkGrid *grid)
 {
   GtkGridPrivate *priv = grid->priv;
   GtkGridChild *grid_child;
-  GtkList *list;
+  GList *list;
   gint i;
 
   for (i = 0; i < priv->max_row - priv->min_row; i++)
@@ -455,28 +557,28 @@ gtk_grid_size_request_init (GtkGrid *grid)
 
   for (i = 0; i < priv->max_column - priv->min_column; i++)
     {
-      priv->cols[i].requisition = 0;
-      priv->cols[i].expand = FALSE;
+      priv->columns[i].requisition = 0;
+      priv->columns[i].expand = FALSE;
     }
 
   for (list = priv->children; list; list = list->next)
     {
-      grid_child = children->data;
+      grid_child = list->data;
 
       if (gtk_widget_get_visible (grid_child->widget))
-        gtk_size_request_get_size (GTK_SIZE_REQUEST (grid_child->widget),
-                                   NULL, NULL);
+        gtk_widget_get_preferred_size (grid_child->widget, NULL, NULL);
 
       if (grid_child->width == 1 && grid_child->hexpand)
-        priv->cols[grid_child->left - priv->min_column].expand = TRUE;
+        priv->columns[grid_child->left - priv->min_column].expand = TRUE;
 
-      if (grid_child->height && child->vexpand)
+      if (grid_child->height == 1 && grid_child->vexpand)
         priv->rows[grid_child->top - priv->min_row].expand = TRUE;
     }
 }
 
+/* set requisition to max of non-spanning children */
 static void
-gtk_table_size_request_pass1 (GtkGrid *grid)
+gtk_grid_size_request_pass1 (GtkGrid *grid)
 {
   GtkGridPrivate *priv = grid->priv;
   GtkGridChild *child;
@@ -488,30 +590,30 @@ gtk_table_size_request_pass1 (GtkGrid *grid)
     {
       child = list->data;
 
-      if (gtk_widget_get_visible (child->widget))
-        {
-          GtkRequisition child_requisition;
+      if (!gtk_widget_get_visible (child->widget))
+        continue;
 
-          gtk_size_request_get_size (GTK_SIZE_REQUEST (child->widget),
-                                     &child_requisition, NULL);
+      GtkRequisition child_requisition;
 
-          /* Child spans a single column. */
-          if (child->width == 1)
-            {
-              width = child_requisition.width;
-              priv->cols[child->left - priv->min_column].requisition = MAX (priv->cols[child->left - priv->min_column].requisition, width);
-            }
+      gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
 
-          /* Child spans a single row. */
-          if (child->height == 1)
-            {
-              height = child_requisition.height;
-              priv->rows[child->top - priv->min_row].requisition = MAX (priv->rows[child->top - priv->min_row].requisition, height);
-            }
+      /* Child spans a single column. */
+      if (child->width == 1)
+        {
+          width = child_requisition.width;
+          priv->columns[child->left - priv->min_column].requisition = MAX (priv->columns[child->left - priv->min_column].requisition, width);
+        }
+
+      /* Child spans a single row. */
+      if (child->height == 1)
+        {
+          height = child_requisition.height;
+          priv->rows[child->top - priv->min_row].requisition = MAX (priv->rows[child->top - priv->min_row].requisition, height);
         }
     }
 }
 
+/* force homogeneous sizes */
 static void
 gtk_grid_size_request_pass2 (GtkGrid *grid)
 {
@@ -542,6 +644,113 @@ gtk_grid_size_request_pass2 (GtkGrid *grid)
     }
 }
 
+/* deal with spanning children */
+static void
+gtk_grid_size_request_pass3 (GtkGrid *grid)
+{
+  GtkGridPrivate *priv = grid->priv;
+  GList *list;
+  GtkGridChild *child;
+  GtkRequisition child_requisition;
+  gint expand;
+  gboolean force;
+  gint i;
+  gint row, col;
+  gint extra;
+  gint width, height;
+
+  for (list = priv->children; list; list = list->next)
+    {
+      child = list->data;
+
+      if (!gtk_widget_get_visible (child->widget))
+        continue;
+
+      if (child->width > 1)
+        {
+          gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
+          width = 0;
+          expand = 0;
+          for (i = 0; i < child->width; i++)
+            {
+              col = child->left - priv->min_column + i;
+              width += priv->columns[col].requisition;
+              if (i > 0)
+                width += priv->column_spacing;
+              if (priv->columns[col].expand)
+                expand += 1;
+            }
+
+          /* If we need to request more space for this child to fill
+           * its requisition, then divide up the needed space amongst the
+           * columns it spans, favoring expandable columns if any.
+           */
+         if (width < child_requisition.width)
+           {
+             force = FALSE;
+             width = child_requisition.width - width;
+             if (expand == 0)
+               {
+                 expand = child->width;
+                 force = TRUE;
+               }
+             for (i = 0; i < child->width; i++)
+               {
+                 col = child->left - priv->min_column + i;
+                 if (force || priv->columns[col].expand)
+                   {
+                     extra = width / expand;
+                     priv->columns[col].requisition += extra;
+                     width -= extra;
+                     expand -= 1;
+                   }
+               }
+           }
+        }
+
+      if (child->height > 1)
+        {
+          gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
+          height = 0;
+          expand = 0;
+          for (i = 0; i < child->height; i++)
+            {
+              row = child->top - priv->min_row + i;
+              height += priv->rows[row].requisition;
+              if (i > 0)
+                height += priv->row_spacing;
+              if (priv->rows[row].expand)
+                expand += 1;
+            }
+
+          /* If we need to request more space for this child to fill
+           * its requisition, then divide up the needed space amongst the
+           * columns it spans, favoring expandable columns if any.
+           */
+         if (height < child_requisition.height)
+           {
+             force = FALSE;
+             height = child_requisition.height - height;
+             if (expand == 0)
+               {
+                 expand = child->height;
+                 force = TRUE;
+               }
+             for (i = 0; i < child->height; i++)
+               {
+                 row = child->top - priv->min_row + i;
+                 if (force || priv->rows[row].expand)
+                   {
+                     extra = height / expand;
+                     priv->rows[row].requisition += extra;
+                     height -= extra;
+                     expand -= 1;
+                   }
+               }
+           }
+        }
+    }
+}
 
 static void
 gtk_grid_size_request (GtkWidget      *widget,
@@ -550,10 +759,6 @@ gtk_grid_size_request (GtkWidget      *widget,
   GtkGrid *grid = GTK_GRID (widget);
   GtkGridPrivate *priv = grid->priv;
   gint row, col;
-  guint border_width;
-
-  requisition->width = 0;
-  requisition->height = 0;
 
   gtk_grid_allocate_rowcols (grid);
 
@@ -563,18 +768,346 @@ gtk_grid_size_request (GtkWidget      *widget,
   gtk_grid_size_request_pass3 (grid);
   gtk_grid_size_request_pass2 (grid);
 
-  for (col = 0; col < priv->max_column - priv->min_column; col++)
+  requisition->width = priv->columns[0].requisition;
+
+  for (col = 1; col < priv->max_column - priv->min_column; col++)
     {
+      requisition->width += priv->column_spacing;
       requisition->width += priv->columns[col].requisition;
-      if (col > 0)
-        requisition->width += priv->column_spacing;
     }
 
-  for (row = 0; row < priv->max_row - priv->min_row; row++)
+  requisition->height =  priv->rows[0].requisition;
+
+  for (row = 1; row < priv->max_row - priv->min_row; row++)
     {
+      requisition->height += priv->row_spacing;
       requisition->height += priv->rows[row].requisition;
-      if (row > 0)
-        requisition->width += priv->row_spacing;
+    }
+}
+
+static void
+gtk_grid_size_allocate_init (GtkGrid *grid)
+{
+  GtkGridPrivate *priv = grid->priv;
+  GtkGridChild *child;
+  GList *list;
+  gint row, col;
+  gint i;
+
+  gtk_grid_allocate_rowcols (grid);
+
+  for (col = 0; col < priv->max_column - priv->min_column; col++)
+    {
+      priv->columns[col].allocation = priv->columns[col].requisition;
+      priv->columns[col].need_expand = FALSE;
+      priv->columns[col].expand = FALSE;
+      priv->columns[col].empty = TRUE;
+    }
+
+  for (row = 0; row < priv->max_row - priv->min_row; row++)
+    {
+      priv->rows[row].allocation = priv->rows[row].requisition;
+      priv->rows[row].need_expand = FALSE;
+      priv->rows[row].expand = FALSE;
+      priv->rows[row].empty = TRUE;
+    }
+
+  for (list = priv->children; list; list = list->next)
+    {
+      child = list->data;
+
+      if (!gtk_widget_get_visible (child->widget))
+        continue;
+
+      if (child->width == 1)
+        {
+          col = child->left - priv->min_column;
+          priv->columns[col].empty = FALSE;
+          if (child->hexpand)
+            priv->columns[col].expand = TRUE;
+        }
+
+      if (child->height == 1)
+        {
+          row = child->top - priv->min_row;
+          priv->rows[row].empty = FALSE;
+          if (child->vexpand)
+            priv->rows[row].expand = TRUE;
+        }
+    }
+
+  for (list = priv->children; list; list = list->next)
+    {
+      child = list->data;
+
+      if (!gtk_widget_get_visible (child->widget))
+        continue;
+
+      if (child->width > 1)
+        {
+          for (i = 0; i < child->width; i++)
+            {
+              col = child->left - priv->min_column + i;
+              priv->columns[col].empty = FALSE;
+            }
+          if (child->hexpand)
+            {
+              gboolean has_expand;
+
+              has_expand = FALSE;
+              for (i = 0; i < child->width; i++)
+                {
+                  col = child->left - priv->min_column + i;
+                  if (priv->columns[col].expand)
+                    {
+                      has_expand = TRUE;
+                      break;
+                    }
+                }
+              if (!has_expand)
+                for (i = 0; i < child->width; i++)
+                  {
+                    col = child->left - priv->min_column + i;
+                    priv->columns[col].need_expand = TRUE;
+                  }
+            }
+        }
+
+      if (child->height > 1)
+        {
+          for (i = 0; i < child->height; i++)
+            {
+              row = child->top - priv->min_row + i;
+              priv->rows[row].empty = FALSE;
+            }
+          if (child->vexpand)
+            {
+              gboolean has_expand;
+
+              has_expand = FALSE;
+              for (i = 0; i < child->height; i++)
+                {
+                  row = child->top - priv->min_row + i;
+                  if (priv->rows[row].expand)
+                    {
+                      has_expand = TRUE;
+                      break;
+                    }
+                }
+              if (!has_expand)
+                for (i = 0; i < child->height; i++)
+                  {
+                    row = child->top - priv->min_row + i;
+                    priv->rows[row].need_expand = TRUE;
+                  }
+            }
+        }
+    }
+
+  for (col = 0; col < priv->max_column - priv->min_column; col++)
+    {
+      if (priv->columns[col].empty)
+        priv->columns[col].expand = FALSE;
+      else if (priv->columns[col].need_expand)
+        priv->columns[col].expand = TRUE;
+    }
+
+  for (row = 0; row < priv->max_row - priv->min_row; row++)
+    {
+      if (priv->rows[row].empty)
+        priv->rows[row].expand = FALSE;
+      else if (priv->rows[row].need_expand)
+        priv->rows[row].expand = TRUE;
+    }
+}
+
+static void
+gtk_grid_size_allocate_pass1 (GtkGrid *grid)
+{
+  GtkGridPrivate *priv = grid->priv;
+  GtkAllocation allocation;
+  gint width, height;
+  gint extra;
+  gint row, col;
+  gint nonempty, expand;
+
+  gtk_widget_get_allocation (GTK_WIDGET (grid), &allocation);
+
+  if (priv->children == NULL)
+    return;
+
+  if (priv->column_homogeneous)
+    {
+      nonempty = 0;
+      expand = 0;
+      for (col = 0; col < priv->max_column - priv->min_column; col++)
+        {
+          if (!priv->columns[col].empty)
+            nonempty += 1;
+          if (priv->columns[col].expand)
+            expand += 1;
+        }
+      width = allocation.width - (nonempty - 1) * priv->column_spacing;
+      if (expand)
+        for (col = 0; col < priv->max_column - priv->min_column; col++)
+          {
+            extra = width / (priv->max_column - priv->min_column - col);
+            priv->columns[col].allocation = MAX (1, extra);
+            width -= extra;
+          }
+    }
+  else
+    {
+      width = 0;
+      expand = 0;
+      nonempty = 0;
+      for (col = 0; col < priv->max_column - priv->min_column; col++)
+        {
+          width += priv->columns[col].requisition;
+          if (!priv->columns[col].empty)
+            nonempty += 1;
+          if (priv->columns[col].expand)
+            expand += 1;
+        }
+      width += (nonempty - 1) * priv->column_spacing;
+
+      if (width < allocation.width && expand > 0)
+        {
+          width = allocation.width - width;
+          for (col = 0; col < priv->max_column - priv->min_column; col++)
+            {
+              if (priv->columns[col].expand)
+                {
+                  extra = width / expand;
+                  priv->columns[col].allocation += extra;
+                  width -= extra;
+                  expand -= 1;
+                }
+            }
+        }
+    }
+
+  if (priv->row_homogeneous)
+    {
+      nonempty = 0;
+      expand = 0;
+      for (row = 0; row < priv->max_row - priv->min_row; row++)
+        {
+          if (!priv->rows[row].empty)
+            nonempty += 1;
+          if (priv->rows[row].expand)
+            expand += 1;
+        }
+      height = allocation.height - (nonempty - 1) * priv->row_spacing;
+      if (expand)
+        for (row = 0; row < priv->max_row - priv->min_row; row++)
+          {
+            extra = height / (priv->max_row - priv->min_row - row);
+            priv->rows[row].allocation = MAX (1, extra);
+            height -= extra;
+          }
+    }
+  else
+    {
+      height = 0;
+      expand = 0;
+      nonempty = 0;
+      for (row = 0; row < priv->max_row - priv->min_row; row++)
+        {
+          height += priv->rows[row].requisition;
+          if (!priv->rows[row].empty)
+            nonempty += 1;
+          if (priv->rows[row].expand)
+            expand += 1;
+        }
+      height += (nonempty - 1) * priv->row_spacing;
+
+      if (height < allocation.height && expand > 0)
+        {
+          height = allocation.height - height;
+          for (row = 0; row < priv->max_row - priv->min_row; row++)
+            {
+              if (priv->rows[row].expand)
+                {
+                  extra = height / expand;
+                  priv->rows[row].allocation += extra;
+                  height -= extra;
+                  expand -= 1;
+                }
+            }
+        }
+    }
+}
+
+static void
+gtk_grid_size_allocate_pass2 (GtkGrid *grid)
+{
+  GtkGridPrivate *priv = grid->priv;
+  GtkGridChild *child;
+  GList *list;
+  GtkRequisition child_requisition;
+  GtkAllocation child_allocation;
+  GtkAllocation allocation;
+  gint x, y;
+  gint width, height;
+  gint row, col;
+  gint i;
+
+  gtk_widget_get_allocation (GTK_WIDGET (grid), &allocation);
+
+  for (list = priv->children; list; list = list->next)
+    {
+      child = list->data;
+
+      if (!gtk_widget_get_visible (child->widget))
+        continue;
+
+      gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
+
+      x = allocation.x;
+      for (col = 0; col < child->left - priv->min_column; col++)
+        {
+          if (!priv->columns[col].empty)
+            {
+              x += priv->columns[col].allocation;
+              x += priv->column_spacing;
+            }
+        }
+
+      width = 0;
+      for (i = 0; i < child->width; i++)
+        {
+          col = child->left - priv->min_column + i;
+          width += priv->columns[col].allocation;
+          if (i > 0)
+            width += priv->column_spacing;
+        }
+
+      y = allocation.y;
+      for (row = 0; row < child->top - priv->min_row; row++)
+        {
+          if (!priv->rows[row].empty)
+            {
+              y += priv->rows[row].allocation;
+              y += priv->row_spacing;
+            }
+        }
+
+      height = 0;
+      for (i = 0; i < child->height; i++)
+        {
+          row = child->top - priv->min_row + i;
+          height += priv->rows[row].allocation;
+          if (i > 0)
+            height += priv->row_spacing;
+        }
+
+      child_allocation.x = x;
+      child_allocation.y = y;
+      child_allocation.width = MAX (1, width);
+      child_allocation.height = MAX (1, height);
+
+      gtk_widget_size_allocate (child->widget, &child_allocation);
     }
 }
 
@@ -582,19 +1115,25 @@ static void
 gtk_grid_size_allocate (GtkWidget     *widget,
                         GtkAllocation *allocation)
 {
+  GtkGrid *grid = GTK_GRID (widget);
+
+  gtk_widget_set_allocation (widget, allocation);
+
+  gtk_grid_size_allocate_init (grid);
+  gtk_grid_size_allocate_pass1 (grid);
+  gtk_grid_size_allocate_pass2 (grid);
 }
 
 static void
 gtk_grid_class_init (GtkGridClass *class)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
 
-  gobject_class->finalize = gtk_grid_finalize;
-
-  gobject_class->get_property = gtk_grid_get_property;
-  gobject_class->set_property = gtk_grid_set_property;
+  object_class->finalize = gtk_grid_finalize;
+  object_class->get_property = gtk_grid_get_property;
+  object_class->set_property = gtk_grid_set_property;
 
   widget_class->size_request = gtk_grid_size_request;
   widget_class->size_allocate = gtk_grid_size_allocate;
@@ -607,28 +1146,30 @@ gtk_grid_class_init (GtkGridClass *class)
   container_class->get_child_property = gtk_grid_get_child_property;
   gtk_container_class_handle_border_width (container_class);
 
-  g_object_class_install_property (gobject_class, PROP_ROW_SPACING,
+  g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
+
+  g_object_class_install_property (object_class, PROP_ROW_SPACING,
     g_param_spec_int ("row-spacing",
                       P_("Row spacing"),
                       P_("The amount of space between two consecutive rows"),
                       0, G_MAXINT16, 0,
                       GTK_PARAM_READWRITE));
 
-  g_object_class_install_property (gobject_class, PROP_COLUMN_SPACING,
+  g_object_class_install_property (object_class, PROP_COLUMN_SPACING,
     g_param_spec_int ("column-spacing",
                       P_("Column spacing"),
                       P_("The amount of space between two consecutive columns"),
                       0, G_MAXINT16, 0,
                       GTK_PARAM_READWRITE));
 
-  g_object_class_install_property (gobject_class, PROP_ROW_HOMOGENEOUS,
+  g_object_class_install_property (object_class, PROP_ROW_HOMOGENEOUS,
     g_param_spec_boolean ("row-homogeneous",
                           P_("Row Homogeneous"),
                           P_("If TRUE, the rows are all the same height"),
                           FALSE,
                           GTK_PARAM_READWRITE));
 
-  g_object_class_install_property (gobject_class, PROP_COLUMN_HOMOGENEOUS,
+  g_object_class_install_property (object_class, PROP_COLUMN_HOMOGENEOUS,
     g_param_spec_boolean ("column-homogeneous",
                           P_("Column Homogeneous"),
                           P_("If TRUE, the columns are all the same width"),
@@ -663,6 +1204,20 @@ gtk_grid_class_init (GtkGridClass *class)
                       1, G_MAXINT, 1,
                       GTK_PARAM_READWRITE));
 
+  gtk_container_class_install_child_property (container_class, CHILD_PROP_HEXPAND,
+    g_param_spec_boolean ("hexpand",
+                      P_("Horizontal expand"),
+                      P_("Horizontal expand"),
+                      FALSE,
+                      GTK_PARAM_READWRITE));
+
+  gtk_container_class_install_child_property (container_class, CHILD_PROP_VEXPAND,
+    g_param_spec_boolean ("vexpand",
+                      P_("Vertical expand"),
+                      P_("Vertical expand"),
+                      FALSE,
+                      GTK_PARAM_READWRITE));
+
   g_type_class_add_private (class, sizeof (GtkGridPrivate));
 }
 
@@ -672,7 +1227,7 @@ gtk_grid_new (void)
   return (GtkWidget *)g_object_new (GTK_TYPE_GRID, NULL);
 }
 
-staic void
+static void
 grid_attach (GtkGrid   *grid,
              GtkWidget *child,
              gint       left,
@@ -689,6 +1244,8 @@ grid_attach (GtkGrid   *grid,
   grid_child->top = top;
   grid_child->width = width;
   grid_child->height = height;
+  grid_child->hexpand = FALSE;
+  grid_child->vexpand = FALSE;
 
   priv->children = g_list_prepend (priv->children, grid_child);
 
@@ -705,9 +1262,6 @@ gtk_grid_attach (GtkGrid   *grid,
                  gint       width,
                  gint       height)
 {
-  GtkGridPrivate *priv;
-  GtkGridChild *grid_child;
-
   g_return_if_fail (GTK_IS_GRID (grid));
   g_return_if_fail (GTK_IS_WIDGET (child));
   g_return_if_fail (gtk_widget_get_parent (child) == NULL);
@@ -725,14 +1279,13 @@ gtk_grid_attach_next_to (GtkGrid         *grid,
                          gint             width,
                          gint             height)
 {
-  GtkGridPrivate *priv;
   GtkGridChild *grid_sibling;
   gint left, top;
 
   g_return_if_fail (GTK_IS_GRID (grid));
   g_return_if_fail (GTK_IS_WIDGET (child));
   g_return_if_fail (gtk_widget_get_parent (child) == NULL);
-  g_return_if_fail (gtk_widget_get_parent (sibling) == grid);
+  g_return_if_fail (gtk_widget_get_parent (sibling) == (GtkWidget*)grid);
   g_return_if_fail (width > 0);
   g_return_if_fail (height > 0);
 
@@ -741,20 +1294,20 @@ gtk_grid_attach_next_to (GtkGrid         *grid,
   switch (side)
     {
     case GTK_POS_LEFT:
-      left = grid_sibling->left_attach - width;
+      left = grid_sibling->left - width;
       top = grid_sibling->top;
       break;
     case GTK_POS_RIGHT:
-      left = grid_sibling->left_attach + grid_sibling->width;
-      top - grid_sibling->top;
+      left = grid_sibling->left + grid_sibling->width;
+      top = grid_sibling->top;
       break;
     case GTK_POS_TOP:
-      left = grid_sibling->left_attach;
-      top = grid_sibling->top_attach - height;
+      left = grid_sibling->left;
+      top = grid_sibling->top - height;
       break;
     case GTK_POS_BOTTOM:
-      left = grid_sibling->left_attach;
-      top = grid_sibling->top_attach + grid_sibling->height;
+      left = grid_sibling->left;
+      top = grid_sibling->top + grid_sibling->height;
       break;
     default:
       g_assert_not_reached ();
@@ -800,9 +1353,9 @@ gtk_grid_set_column_homogeneous (GtkGrid  *grid,
 
   priv = grid->priv;
 
-  if (priv->col_homogeneous != homogeneous)
+  if (priv->column_homogeneous != homogeneous)
     {
-      priv->col_homogeneous = homogeneous;
+      priv->column_homogeneous = homogeneous;
 
       if (gtk_widget_get_visible (GTK_WIDGET (grid)))
         gtk_widget_queue_resize (GTK_WIDGET (grid));
@@ -860,7 +1413,7 @@ gtk_grid_set_column_spacing (GtkGrid *grid,
 
   if (priv->column_spacing != spacing)
     {
-      priv->col_spacing = spacing;
+      priv->column_spacing = spacing;
 
       if (gtk_widget_get_visible (GTK_WIDGET (grid)))
         gtk_widget_queue_resize (GTK_WIDGET (grid));



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