[gtk+/extended-layout-jhs: 54/64] Filter feature set returned by the child to match the subset supported by



commit 087bde104636a35272ed86c5e087f5a6a42d6ed0
Author: Mathias Hasselmann <mathias hasselmann gmx de>
Date:   Sun Aug 12 22:00:23 2007 +0000

    Filter feature set returned by the child to match the subset supported by
    
    2007-08-12  Mathias Hasselmann  <mathias hasselmann gmx de>
    
    	* gtk/gtkbin.c: Filter feature set returned by the child to match
    	the subset supported by bins. Ensure natural size matches at least
    	the requested size.
    	* gtk/gtkextendedlayout.c: Ensure natural size matches at least
    	the requested size by considering explicit size requests.
    	* gtk/gtkhbox.c, gtk/gtkvbox.c, gtk/gtktable.c, gtk/gtktable.h:
    	Delegate natural size calculation to the (modified) size_request
    	method for more accurate resutls. This trick was developed already
    	for GtkLabel, but not recognized before working on GtkScrolledWindow.
    	* gtk/gtktreeview.c: Skip invisible columns for natural size.
    	* tests/autotestextendedlayout.c: Test natural size properties
    	for all classes implementing GtkExtendLayout.
    
    svn path=/branches/extended-layout/; revision=18606

 ChangeLog.gtk-extended-layout  |   15 +++
 gtk/gtkbin.c                   |   17 +++-
 gtk/gtkextendedlayout.c        |   17 ++++
 gtk/gtkhbox.c                  |   46 +++------
 gtk/gtktable.c                 |   69 +++++++-------
 gtk/gtktable.h                 |    2 +-
 gtk/gtktreeview.c              |    4 +
 gtk/gtkvbox.c                  |   46 +++------
 tests/autotestextendedlayout.c |  205 +++++++++++++++++++++++++++++++++++++--
 9 files changed, 311 insertions(+), 110 deletions(-)
---
diff --git a/ChangeLog.gtk-extended-layout b/ChangeLog.gtk-extended-layout
index f431a8a..a1262e8 100644
--- a/ChangeLog.gtk-extended-layout
+++ b/ChangeLog.gtk-extended-layout
@@ -1,3 +1,18 @@
+2007-08-12  Mathias Hasselmann  <mathias hasselmann gmx de>
+
+	* gtk/gtkbin.c: Filter feature set returned by the child to match
+	the subset supported by bins. Ensure natural size matches at least
+	the requested size.
+	* gtk/gtkextendedlayout.c: Ensure natural size matches at least
+	the requested size by considering explicit size requests.
+	* gtk/gtkhbox.c, gtk/gtkvbox.c, gtk/gtktable.c, gtk/gtktable.h: 
+	Delegate natural size calculation to the (modified) size_request
+	method for more accurate resutls. This trick was developed already
+	for GtkLabel, but not recognized before working on GtkScrolledWindow.
+	* gtk/gtktreeview.c: Skip invisible columns for natural size.
+	* tests/autotestextendedlayout.c: Test natural size properties
+	for all classes implementing GtkExtendLayout.
+
 2007-08-06  Mathias Hasselmann  <mathias hasselmann gmx de>
 
 	* gtk/gtklabel.c: Practice consistent pixel rounding to avoid GtkLabel
diff --git a/gtk/gtkbin.c b/gtk/gtkbin.c
index 068931a..f833633 100644
--- a/gtk/gtkbin.c
+++ b/gtk/gtkbin.c
@@ -161,7 +161,12 @@ gtk_bin_extended_layout_get_features (GtkExtendedLayout *layout)
   GtkBin *bin = GTK_BIN (layout);
 
   if (GTK_IS_EXTENDED_LAYOUT (bin->child))
-    return gtk_extended_layout_get_features (GTK_EXTENDED_LAYOUT (bin->child));
+      return
+        gtk_extended_layout_get_features (GTK_EXTENDED_LAYOUT (bin->child)) &
+        (GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH |
+         GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT |
+         GTK_EXTENDED_LAYOUT_NATURAL_SIZE |
+         GTK_EXTENDED_LAYOUT_BASELINES);
 
   return 0;
 }
@@ -195,12 +200,13 @@ gtk_bin_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                           GtkRequisition    *requisition)
 {
   GtkBin *bin = GTK_BIN (layout);
-  GtkExtendedLayout *child_layout;
+  GtkRequisition minimum_size;
 
   g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (bin->child));
 
-  child_layout = GTK_EXTENDED_LAYOUT (bin->child);
-  gtk_extended_layout_get_natural_size (child_layout, requisition);
+  gtk_widget_size_request (GTK_WIDGET (layout), &minimum_size);
+  gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (bin->child),
+                                        requisition);
 
   if (GTK_EXTENDED_LAYOUT_HAS_PADDING (layout))
     {
@@ -211,6 +217,9 @@ gtk_bin_extended_layout_get_natural_size (GtkExtendedLayout *layout,
       requisition->width += padding.left + padding.right;
       requisition->height += padding.top + padding.bottom;
     }
+
+  requisition->width = MAX (requisition->width, minimum_size.width);
+  requisition->height = MAX (requisition->height, minimum_size.height);
 }
 
 static gint
diff --git a/gtk/gtkextendedlayout.c b/gtk/gtkextendedlayout.c
index f53bd9f..1237ad2 100644
--- a/gtk/gtkextendedlayout.c
+++ b/gtk/gtkextendedlayout.c
@@ -127,6 +127,7 @@ void
 gtk_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                       GtkRequisition    *requisition)
 {
+  GtkWidgetAuxInfo *aux_info = NULL;
   GtkExtendedLayoutIface *iface;
 
   g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
@@ -136,6 +137,22 @@ gtk_extended_layout_get_natural_size (GtkExtendedLayout *layout,
 
   g_return_if_fail (iface->get_natural_size);
   iface->get_natural_size(layout, requisition);
+
+/* XXX The following hack is needed to ensure natural_size >= requested_size
+ *     even if GtkWidget and GtkSizeGroup tweak a widget's size requisition. */
+/* FIXME Should I just use gtk_widget_size_request? This would be more reliable
+ *       but also would hide bugs in natural_size implementations. */
+
+  if (GTK_IS_WIDGET (layout))
+    aux_info = _gtk_widget_get_aux_info (GTK_WIDGET (layout), FALSE);
+
+  if (aux_info)
+    {
+      if (aux_info->width > 0)
+	requisition->width = MAX (requisition->width, aux_info->width);
+      if (aux_info && aux_info->height > 0)
+	requisition->height = MAX (requisition->height, aux_info->height);
+    }
 }
 
 /**
diff --git a/gtk/gtkhbox.c b/gtk/gtkhbox.c
index cdd83d7..3fc8d85 100644
--- a/gtk/gtkhbox.c
+++ b/gtk/gtkhbox.c
@@ -148,8 +148,9 @@ gtk_hbox_get_property (GObject    *object,
 }
 
 static void
-gtk_hbox_size_request (GtkWidget      *widget,
-		       GtkRequisition *requisition)
+gtk_hbox_real_size_request (GtkWidget      *widget,
+		            GtkRequisition *requisition,
+                            gboolean        consider_natural_size)
 {
   GtkBox *box = GTK_BOX (widget);
 
@@ -219,7 +220,11 @@ gtk_hbox_size_request (GtkWidget      *widget,
               GtkRequisition child_requisition;
               gint width;
 
-              gtk_widget_size_request (child->widget, &child_requisition);
+              if (consider_natural_size && GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child->widget))
+                gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (child->widget), 
+                                                      &child_requisition);
+              else
+                gtk_widget_size_request (child->widget, &child_requisition);
 
               if (box->homogeneous)
                 {
@@ -254,6 +259,13 @@ gtk_hbox_size_request (GtkWidget      *widget,
 }
 
 static void
+gtk_hbox_size_request (GtkWidget      *widget,
+		       GtkRequisition *requisition)
+{
+  gtk_hbox_real_size_request (widget, requisition, FALSE);
+}
+
+static void
 gtk_hbox_size_allocate (GtkWidget     *widget,
 			GtkAllocation *allocation)
 {
@@ -530,33 +542,7 @@ static void
 gtk_hbox_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                            GtkRequisition    *requisition)
 {
-  GtkBox *box = GTK_BOX (layout);
-
-  GtkRequisition child_requisition;
-  GtkBoxChild *child;
-  GList *children;
-
-  requisition->width = GTK_CONTAINER (box)->border_width * 2;
-  requisition->height = GTK_CONTAINER (box)->border_width * 2;
-
-  children = box->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-
-      if (GTK_WIDGET_VISIBLE (child->widget))
-	{
-          if (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child->widget))
-            gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (child->widget),
-                                                  &child_requisition);
-          else
-            gtk_widget_size_request (child->widget, &child_requisition);
-
-          requisition->width += child_requisition.width;
-          requisition->height = MAX (child_requisition.height, requisition->height);
-	}
-    }
+  gtk_hbox_real_size_request (GTK_WIDGET (layout), requisition, TRUE);
 }
 
 static gint
diff --git a/gtk/gtktable.c b/gtk/gtktable.c
index 2a6ecb2..5f085d8 100644
--- a/gtk/gtktable.c
+++ b/gtk/gtktable.c
@@ -816,8 +816,9 @@ gtk_table_finalize (GObject *object)
 }
 
 static void
-gtk_table_size_request (GtkWidget      *widget,
-			GtkRequisition *requisition)
+gtk_table_real_size_request (GtkWidget      *widget,
+			     GtkRequisition *requisition,
+                             gboolean        consider_natural_size)
 {
   GtkTable *table;
   gint row, col;
@@ -835,14 +836,24 @@ gtk_table_size_request (GtkWidget      *widget,
   gtk_table_size_request_pass2 (table);
   gtk_table_size_request_pass3 (table);
   gtk_table_size_request_pass2 (table);
+
+  if (consider_natural_size)
+    {
+      for (col = 0; col < table->ncols; col++)
+        requisition->width += table->cols[col].natural_size;
+      for (row = 0; row < table->nrows; row++)
+        requisition->height += table->rows[row].natural_size;
+    }
+  else
+    {
+      for (col = 0; col < table->ncols; col++)
+        requisition->width += table->cols[col].requisition;
+      for (row = 0; row < table->nrows; row++)
+        requisition->height += table->rows[row].requisition;
+    }
   
-  for (col = 0; col < table->ncols; col++)
-    requisition->width += table->cols[col].requisition;
   for (col = 0; col + 1 < table->ncols; col++)
     requisition->width += table->cols[col].spacing;
-  
-  for (row = 0; row < table->nrows; row++)
-    requisition->height += table->rows[row].requisition;
   for (row = 0; row + 1 < table->nrows; row++)
     requisition->height += table->rows[row].spacing;
   
@@ -851,6 +862,13 @@ gtk_table_size_request (GtkWidget      *widget,
 }
 
 static void
+gtk_table_size_request (GtkWidget      *widget,
+			GtkRequisition *requisition)
+{
+  gtk_table_real_size_request (widget, requisition, FALSE);
+}
+
+static void
 gtk_table_size_allocate (GtkWidget     *widget,
 			 GtkAllocation *allocation)
 {
@@ -947,13 +965,13 @@ gtk_table_size_request_init (GtkTable *table)
   for (row = 0; row < table->nrows; row++)
     {
       table->rows[row].requisition = 0;
-      table->rows[row].natural = 0;
+      table->rows[row].natural_size = 0;
       table->rows[row].expand = FALSE;
     }
   for (col = 0; col < table->ncols; col++)
     {
       table->cols[col].requisition = 0;
-      table->cols[col].natural = 0;
+      table->cols[col].natural_size = 0;
       table->cols[col].expand = FALSE;
     }
   
@@ -1007,7 +1025,7 @@ gtk_table_size_request_pass1 (GtkTable *table)
 	      table->cols[child->left_attach].requisition = MAX (table->cols[child->left_attach].requisition, width);
 
 	      width = child_natural_size.width + child->xpadding * 2;
-              table->cols[child->left_attach].natural = MAX (table->cols[child->left_attach].natural, width);
+              table->cols[child->left_attach].natural_size = MAX (table->cols[child->left_attach].natural_size, width);
 	    }
 	  
 	  /* Child spans a single row.
@@ -1018,7 +1036,7 @@ gtk_table_size_request_pass1 (GtkTable *table)
 	      table->rows[child->top_attach].requisition = MAX (table->rows[child->top_attach].requisition, height);
 
 	      height = child_natural_size.height + child->ypadding * 2;
-              table->rows[child->top_attach].natural = MAX (table->rows[child->top_attach].natural, height);
+              table->rows[child->top_attach].natural_size = MAX (table->rows[child->top_attach].natural_size, height);
 	    }
 	}
     }
@@ -1433,7 +1451,7 @@ gtk_table_size_allocate_pass1 (GtkTable *table)
       for (col = 0; col < table->ncols; col++)
 	{
 	  width += table->cols[col].requisition;
-          delta = table->cols[col].natural - table->cols[col].requisition;
+          delta = table->cols[col].natural_size - table->cols[col].requisition;
 
 	  if (table->cols[col].expand)
 	    nexpand += 1;
@@ -1458,7 +1476,7 @@ gtk_table_size_allocate_pass1 (GtkTable *table)
             {
               if (natural_size)
                 {
-                  delta = table->cols[col].natural - table->cols[col].requisition;
+                  delta = table->cols[col].natural_size - table->cols[col].requisition;
                   delta = natural_size * delta / natural_delta;
                   table->cols[col].allocation += delta;
                 }
@@ -1542,13 +1560,13 @@ gtk_table_size_allocate_pass1 (GtkTable *table)
       for (row = 0; row < table->nrows; row++)
 	{
 	  height += table->rows[row].requisition;
-          delta = table->rows[row].natural - table->rows[row].requisition;
+          delta = table->rows[row].natural_size - table->rows[row].requisition;
 
 	  if (table->rows[row].expand)
 	    nexpand += 1;
 	  if (table->rows[row].shrink)
 	    nshrink += 1;
-	  if (table->rows[row].natural > table->rows[row].requisition)
+	  if (table->rows[row].natural_size > table->rows[row].requisition)
             natural_delta += delta;
 	}
       for (row = 0; row + 1 < table->nrows; row++)
@@ -1566,7 +1584,7 @@ gtk_table_size_allocate_pass1 (GtkTable *table)
             {
               if (natural_size)
                 {
-                  delta = table->rows[row].natural - table->rows[row].requisition;
+                  delta = table->rows[row].natural_size - table->rows[row].requisition;
                   delta = natural_size * delta / natural_delta;
                   table->rows[row].allocation += delta;
                 }
@@ -1707,24 +1725,7 @@ static void
 gtk_table_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                             GtkRequisition    *requisition)
 {
-  int width, height, i;
-  GtkTable *table;
-
-  /* update size requisition when needed */
-  _gtk_size_group_compute_requisition (GTK_WIDGET (layout), NULL);
-
-  table = GTK_TABLE (layout);
-
-  width = 0;
-  height = 0;
-
-  for (i = 0; i < table->ncols; i++)
-    width += table->cols[i].natural;
-  for (i = 0; i < table->nrows; i++)
-    height += table->rows[i].natural;
-
-  requisition->width = width;
-  requisition->height = height;
+  gtk_table_real_size_request (GTK_WIDGET (layout), requisition, TRUE);
 }
 
 static void
diff --git a/gtk/gtktable.h b/gtk/gtktable.h
index f816926..fb7cb3c 100644
--- a/gtk/gtktable.h
+++ b/gtk/gtktable.h
@@ -93,7 +93,7 @@ struct _GtkTableRowCol
   guint expand : 1;
   guint shrink : 1;
   guint empty : 1;
-  guint16 natural;
+  guint16 natural_size;
 };
 
 
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index a037dcc..0ca73bd 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -14996,6 +14996,10 @@ gtk_tree_view_extended_layout_get_natural_size (GtkExtendedLayout *layout,
   for (column_iter = tree_view->priv->columns; column_iter; column_iter = column_iter->next)
     {
       GtkTreeViewColumn *column = column_iter->data;
+
+      if (!column->visible)
+	continue;
+
       natural_width += gtk_tree_view_get_real_natural_width_from_column (tree_view, column);
     }
 
diff --git a/gtk/gtkvbox.c b/gtk/gtkvbox.c
index 987a16a..d0860c5 100644
--- a/gtk/gtkvbox.c
+++ b/gtk/gtkvbox.c
@@ -74,8 +74,9 @@ gtk_vbox_new (gboolean homogeneous,
 
 
 static void
-gtk_vbox_size_request (GtkWidget      *widget,
-		       GtkRequisition *requisition)
+gtk_vbox_real_size_request (GtkWidget      *widget,
+		            GtkRequisition *requisition,
+		            gboolean        consider_natural_size)
 {
   GtkBox *box;
   GtkBoxChild *child;
@@ -97,7 +98,11 @@ gtk_vbox_size_request (GtkWidget      *widget,
 
       if (GTK_WIDGET_VISIBLE (child->widget))
 	{
-	  gtk_widget_size_request (child->widget, &child_requisition);
+          if (consider_natural_size && GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child->widget))
+            gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (child->widget), 
+                                                  &child_requisition);
+          else
+	    gtk_widget_size_request (child->widget, &child_requisition);
 
 	  if (box->homogeneous)
 	    {
@@ -127,6 +132,13 @@ gtk_vbox_size_request (GtkWidget      *widget,
 }
 
 static void
+gtk_vbox_size_request (GtkWidget      *widget,
+		       GtkRequisition *requisition)
+{
+  gtk_vbox_real_size_request (widget, requisition, FALSE);
+}
+
+static void
 gtk_vbox_size_allocate (GtkWidget     *widget,
 			GtkAllocation *allocation)
 {
@@ -327,33 +339,7 @@ static void
 gtk_vbox_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                            GtkRequisition    *requisition)
 {
-  GtkBox *box = GTK_BOX (layout);
-
-  GtkRequisition child_requisition;
-  GtkBoxChild *child;
-  GList *children;
-
-  requisition->width = GTK_CONTAINER (box)->border_width * 2;
-  requisition->height = GTK_CONTAINER (box)->border_width * 2;
-
-  children = box->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-
-      if (GTK_WIDGET_VISIBLE (child->widget))
-	{
-          if (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child->widget))
-            gtk_extended_layout_get_natural_size (GTK_EXTENDED_LAYOUT (child->widget),
-                                                  &child_requisition);
-          else
-            gtk_widget_size_request (child->widget, &child_requisition);
-
-          requisition->width = MAX (child_requisition.width, requisition->width);
-          requisition->height += child_requisition.height;
-	}
-    }
+  gtk_vbox_real_size_request (GTK_WIDGET (layout), requisition, TRUE);
 }
 
 static void
diff --git a/tests/autotestextendedlayout.c b/tests/autotestextendedlayout.c
index b53acb8..6b47477 100644
--- a/tests/autotestextendedlayout.c
+++ b/tests/autotestextendedlayout.c
@@ -9,15 +9,19 @@
 #define log_test(condition) \
   log_test_impl(G_STRFUNC, __LINE__, (condition), #condition)
 #define log_testf(condition, format, ...) \
-  log_test_impl(G_STRFUNC, __LINE__, (condition), #condition " (" format ")", __VA_ARGS__)
+  log_test_impl(G_STRFUNC, __LINE__, (condition), \
+                #condition "\n      " format, __VA_ARGS__)
 #define log_testi(expected, number) G_STMT_START { \
     const gint i = (expected), j = (number); \
-    log_test_impl(G_STRFUNC, __LINE__, i == j, \
-                  #number " is " #expected " (actual number %d, expected: %d)", j, i); \
+    log_test_impl(G_STRFUNC, __LINE__, i == j, #number " is " #expected \
+                  "\n      actual number %d, expected: %d", j, i); \
+  } G_STMT_END
+
+#define log_info(format, ...) G_STMT_START { \
+  if (debug) \
+    g_print ("INFO: %s: " format "\n", G_STRFUNC, __VA_ARGS__); \
   } G_STMT_END
 
-#define log_info(format, ...) \
-  g_print ("INFO: %s: " format "\n", G_STRFUNC, __VA_ARGS__);
 #define log_int_array(values, length) \
   log_int_array_impl (G_STRFUNC, #values, (values), (length))
 #define log_int(value) \
@@ -37,6 +41,7 @@ static int num_failures = 0;
 static int num_warnings = 0;
 static int num_errors = 0;
 static int num_criticals = 0;
+static gboolean debug = FALSE;
 
 static GLogFunc default_log_handler;
 
@@ -48,7 +53,12 @@ log_int_array_impl (const gchar *function,
                     const gint  *values,
                     gsize        length)
 {
-  GString *tmp = g_string_new ("");
+  GString *tmp;
+
+  if (!debug)
+    return;
+
+  tmp = g_string_new ("");
   
   if (length--)
     {
@@ -68,7 +78,7 @@ log_int_array_impl (const gchar *function,
   g_string_free (tmp, TRUE);
 }
 
-static void
+static gboolean
 log_test_impl (const gchar *function,
                gint         lineno,
                gboolean     passed, 
@@ -84,11 +94,13 @@ log_test_impl (const gchar *function,
   str = g_strdup_vprintf (test_name, args);
   va_end (args);
 
-  g_printf ("%s: %s, line %d: %s\033[0m\n",
-            passed ? "PASS" : "\033[1;31mFAIL", 
-            function, lineno, str);
+  if (!passed || debug)
+    g_printf ("%s: %s, line %d: %s\033[0m\n",
+              passed ? "PASS" : "\033[1;31mFAIL", 
+              function, lineno, str);
 
   g_free (str);
+  return passed;
 }
 
 static void
@@ -204,7 +216,8 @@ gtk_label_test_height_for_width (void)
 
   for (i = 5; i >= 1; --i)
     {
-      cy = gtk_extended_layout_get_height_for_width (layout, cx = rcx * i);
+      cx = rcx * i;
+      cy = gtk_extended_layout_get_height_for_width (layout, cx);
       log_info ("scale is %d, so width is %d. results in height of %d.", i, cx, cy);
       log_testi (rcy, cy);
     }
@@ -499,6 +512,173 @@ gtk_table_test_extended_layout (void)
 
 /*****************************************************************************/
 
+static void
+extended_layout_check_child (GtkWidget *child,
+                             gpointer   data);
+
+static void
+extended_layout_natural_size_test (GtkExtendedLayout *layout)
+{
+  GtkRequisition natural_size;
+  GtkRequisition requisition;
+  GtkWidget *parent = NULL;
+  gboolean passed = TRUE;
+
+  g_return_if_fail (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (layout));
+
+  if (GTK_IS_WIDGET (layout))
+    {
+      parent = gtk_widget_get_parent (GTK_WIDGET (layout));
+      gtk_widget_size_request (GTK_WIDGET (layout), &requisition);
+    }
+  else if (GTK_IS_CELL_RENDERER (layout))
+    {
+      parent = gtk_cell_view_new ();
+      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (parent),
+                                  GTK_CELL_RENDERER (layout),
+                                  FALSE);
+      gtk_cell_renderer_get_size (GTK_CELL_RENDERER (layout),
+                                  parent, NULL, NULL, NULL,
+                                  &requisition.width,
+                                  &requisition.height);
+    }
+  else if (GTK_IS_TREE_VIEW_COLUMN (layout))
+    {
+      parent = gtk_tree_view_new ();
+      gtk_tree_view_append_column (GTK_TREE_VIEW (parent),
+                                   GTK_TREE_VIEW_COLUMN (layout));
+
+      requisition.width =
+        gtk_tree_view_column_get_width (
+        GTK_TREE_VIEW_COLUMN (layout));
+      requisition.height = 0;
+    }
+  else
+    {
+      g_warning ("%s: Unsupported object category: %s",
+                 G_STRFUNC, G_OBJECT_TYPE_NAME (layout));
+      return;
+    }
+
+  gtk_extended_layout_get_natural_size (layout, &natural_size);
+
+  passed &= log_testf (
+    natural_size.width >= requisition.width,
+    "parent=%s, item=%s(%p), natural-width=%d, requisition=%d",
+    parent ? G_OBJECT_TYPE_NAME (parent) : "(none)",
+    G_OBJECT_TYPE_NAME (layout), layout,
+    natural_size.width, requisition.width);
+  passed &= log_testf (
+    natural_size.height >= requisition.height,
+    "parent=%s, item=%s(%p), natural-height=%d, requisition=%d",
+    parent ? G_OBJECT_TYPE_NAME (parent) : "(none)",
+    G_OBJECT_TYPE_NAME (layout), layout,
+    natural_size.height, requisition.height);
+
+  if (!passed && GTK_IS_CONTAINER (layout))
+    gtk_container_foreach (GTK_CONTAINER (layout),
+                           extended_layout_check_child,
+                           NULL); 
+}
+
+static void
+extended_layout_check_child (GtkWidget *child,
+                             gpointer   data)
+{
+  if (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child))
+    extended_layout_natural_size_test (GTK_EXTENDED_LAYOUT (child));
+}
+
+static void
+introspective_test (const gchar *argv0)
+{
+  gint n_extended_layout_types = 0;
+  gint n_extended_layout_roots = 0;
+  GModule *module = NULL;
+  GError *error = NULL;
+  GIOChannel *file;
+
+  gchar *filename;
+  gchar *dirname;
+  gchar *line;
+
+  dirname = g_path_get_dirname (argv0);
+  filename = g_build_filename (dirname,
+                               "..", "..", "docs", "reference",
+                               "gtk", "gtk.types", NULL);
+  file = g_io_channel_new_file (filename, "r", &error);
+
+  g_free (dirname);
+
+  if (error)
+    goto cleanup;
+
+  module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
+
+  while (G_IO_STATUS_NORMAL ==
+         g_io_channel_read_line (file, &line, NULL, NULL, &error))
+    {
+      gpointer get_type_function;
+
+      line = g_strstrip (line);
+
+      if (g_str_has_suffix (line, "_get_type") &&
+          g_module_symbol (module, line, &get_type_function))
+        {
+          GType type = ((GType(*)()) get_type_function) ();
+
+          if (g_type_is_a (type, GTK_TYPE_EXTENDED_LAYOUT) &&
+              G_TYPE_IS_INSTANTIATABLE (type))
+            {
+              GtkExtendedLayoutIface *iface;
+              GtkExtendedLayout *object;
+              gpointer type_class;
+
+              type_class = g_type_class_ref (type);
+              iface = GTK_EXTENDED_LAYOUT_CLASS (type_class);
+
+              log_testf (NULL != iface->get_features, "%s", g_type_name (type));
+
+              if (!g_type_is_a (g_type_parent (type), GTK_TYPE_EXTENDED_LAYOUT))
+                ++n_extended_layout_roots;
+
+              if (!G_TYPE_IS_ABSTRACT (type))
+                {
+                  object = g_object_new (type, NULL);
+                  log_testf (NULL != object, "%s", g_type_name (type));
+
+                  if (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (object))
+                    extended_layout_natural_size_test (GTK_EXTENDED_LAYOUT (object));
+                }
+
+              g_type_class_unref (type_class);
+              ++n_extended_layout_types;
+            }
+        }
+
+      g_free (line);
+    }
+
+  log_testi (72, n_extended_layout_types);
+  log_testi (10, n_extended_layout_roots);
+
+cleanup:
+  if (error)
+    {
+      g_warning ("%s: %s", filename, error->message);
+      g_error_free (error);
+    }
+
+  if (module)
+    g_module_close (module);
+  if (file)
+    g_io_channel_unref (file);
+
+  g_free (filename);
+}
+
+/*****************************************************************************/
+
 int
 main(int argc, char **argv)
 {
@@ -506,9 +686,12 @@ main(int argc, char **argv)
 
   gtk_init (&argc, &argv);
 
+  debug = (NULL != g_getenv ("DEBUG"));
+
   gtk_label_test_extended_layout ();
   gtk_bin_test_extended_layout ();
   gtk_table_test_extended_layout ();
+  introspective_test (argv[0]);
 
   log_testi (0, num_warnings);
   log_testi (0, num_errors);



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