[gtk+/extended-layout-jhs: 34/64] Implement and test natural size support for GtkVBox. Cleanup issues found



commit 9e57247d9a930e2a5e30d80ded4a17bd4a1da026
Author: Mathias Hasselmann <mathias hasselmann gmx de>
Date:   Wed Jul 18 12:57:09 2007 +0000

    Implement and test natural size support for GtkVBox. Cleanup issues found
    
    2007-07-16  Mathias Hasselmann  <mathias hasselmann gmx de>
    
    	* gtk/gtkvbox.c, tests/testextendedlayout.c:
    	Implement and test natural size support for GtkVBox.
    	* gtk/gtkhbox.c: Cleanup issues found when implementing
    	natural size for GtkVBox.
    
    svn path=/branches/extended-layout/; revision=18492

 ChangeLog.gtk-extended-layout |    7 +
 gtk/gtkhbox.c                 |   17 +--
 gtk/gtkvbox.c                 |  301 +++++++++++++++++++++++++----------------
 tests/testextendedlayout.c    |   85 ++++++++----
 4 files changed, 255 insertions(+), 155 deletions(-)
---
diff --git a/ChangeLog.gtk-extended-layout b/ChangeLog.gtk-extended-layout
index 277e5b8..22391f2 100644
--- a/ChangeLog.gtk-extended-layout
+++ b/ChangeLog.gtk-extended-layout
@@ -1,3 +1,10 @@
+2007-07-16  Mathias Hasselmann  <mathias hasselmann gmx de>
+
+	* gtk/gtkvbox.c, tests/testextendedlayout.c:
+	Implement and test natural size support for GtkVBox.
+	* gtk/gtkhbox.c: Cleanup issues found when implementing
+	natural size for GtkVBox.
+
 2007-07-15  Mathias Hasselmann  <mathias hasselmann gmx de>
 
 	* tests/testextendedlayout.c: Improve test result grouping.
diff --git a/gtk/gtkhbox.c b/gtk/gtkhbox.c
index 6ce6d41..1775cf9 100644
--- a/gtk/gtkhbox.c
+++ b/gtk/gtkhbox.c
@@ -290,19 +290,15 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
       GtkHBoxPrivate *priv = GTK_HBOX_GET_PRIVATE (widget);
 
       GtkPackType packing;
-
       GtkTextDirection direction;
       gint border_width;
 
       GtkAllocation child_allocation;
-
       gint *natural_requisitions;
       gint *minimum_requisitions;
 
-      gint natural_width;
-      gint minimum_width;
-
       gint available, natural, extra;
+      gint natural_width;
       gint i;
 
       direction = gtk_widget_get_direction (widget);
@@ -312,8 +308,8 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
       natural_requisitions = g_newa (gint, nvis_children);
       minimum_requisitions = g_newa (gint, nvis_children);
 
-      children = box->children;
       i = 0;
+      children = box->children;
 
       while (children)
         {
@@ -344,13 +340,10 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
             }
         }
 
-      minimum_width = widget->requisition.width - border_width * 2 - 
-                      (nvis_children - 1) * box->spacing;
-
       if (box->homogeneous)
 	{
 	  available = (allocation->width - border_width * 2 -
-		       (nvis_children - 1) * box->spacing);
+		      (nvis_children - 1) * box->spacing);
 	  extra = available / nvis_children;
           natural = 0;
 	}
@@ -390,7 +383,7 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
 
               if (GTK_WIDGET_VISIBLE (child->widget))
                 {
-                  if ((child->pack == packing))
+                  if (child->pack == packing)
                     {
                       gint child_width;
 
@@ -425,7 +418,7 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
 
                       if (child->fill)
                         {
-                          child_allocation.width = MAX (1, (gint) child_width - (gint) child->padding * 2);
+                          child_allocation.width = MAX (1, child_width - (gint)child->padding * 2);
                           child_allocation.x = x + child->padding;
                         }
                       else
diff --git a/gtk/gtkvbox.c b/gtk/gtkvbox.c
index 65633d8..e84911e 100644
--- a/gtk/gtkvbox.c
+++ b/gtk/gtkvbox.c
@@ -26,6 +26,7 @@
 
 #include <config.h>
 #include "gtkvbox.h"
+#include "gtkextendedlayout.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
@@ -35,7 +36,11 @@ static void gtk_vbox_size_request  (GtkWidget      *widget,
 static void gtk_vbox_size_allocate (GtkWidget      *widget,
 				    GtkAllocation  *allocation);
 
-G_DEFINE_TYPE (GtkVBox, gtk_vbox, GTK_TYPE_BOX)
+static void gtk_vbox_extended_layout_interface_init (GtkExtendedLayoutIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkVBox, gtk_vbox, GTK_TYPE_BOX,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
+						gtk_vbox_extended_layout_interface_init))
 
 static void
 gtk_vbox_class_init (GtkVBoxClass *class)
@@ -126,15 +131,11 @@ gtk_vbox_size_allocate (GtkWidget     *widget,
 			GtkAllocation *allocation)
 {
   GtkBox *box;
-  GtkBoxChild *child;
-  GList *children;
-  GtkAllocation child_allocation;
+
   gint nvis_children;
   gint nexpand_children;
-  gint child_height;
-  gint height;
-  gint extra;
-  gint y;
+  GtkBoxChild *child;
+  GList *children;
 
   box = GTK_BOX (widget);
   widget->allocation = *allocation;
@@ -158,142 +159,206 @@ gtk_vbox_size_allocate (GtkWidget     *widget,
 
   if (nvis_children > 0)
     {
+      GtkPackType packing;
+      gint border_width;
+
+      GtkAllocation child_allocation;
+      gint *natural_requisitions;
+      gint *minimum_requisitions;
+
+      gint available, natural, extra;
+      gint natural_height;
+      gint i;
+
+      border_width = GTK_CONTAINER (box)->border_width;
+
+      natural_height = 0;
+      natural_requisitions = g_newa (gint, nvis_children);
+      minimum_requisitions = g_newa (gint, nvis_children);
+
+      i = 0;
+      children = box->children;
+
+      while (children)
+        {
+          child = children->data;
+          children = children->next;
+
+          if (GTK_WIDGET_VISIBLE (child->widget))
+            {
+              GtkRequisition child_requisition;
+
+              gtk_widget_size_request (child->widget, &child_requisition);
+              minimum_requisitions[i] = child_requisition.height;
+
+              if (GTK_IS_EXTENDED_LAYOUT (child->widget) &&
+                  GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child->widget))
+                {
+                  gtk_extended_layout_get_natural_size (
+                    GTK_EXTENDED_LAYOUT (child->widget), 
+                    &child_requisition);
+                  natural_requisitions[i] =
+                    child_requisition.height - 
+                    minimum_requisitions[i];
+                }
+              else
+                natural_requisitions[i] = 0;
+
+              natural_height += natural_requisitions[i++];
+            }
+        }
+
       if (box->homogeneous)
 	{
-	  height = (allocation->height -
-		   GTK_CONTAINER (box)->border_width * 2 -
-		   (nvis_children - 1) * box->spacing);
-	  extra = height / nvis_children;
+	  available = (allocation->height - border_width * 2 -
+		      (nvis_children - 1) * box->spacing);
+	  extra = available / nvis_children;
+          natural = 0;
 	}
       else if (nexpand_children > 0)
 	{
-	  height = (gint) allocation->height - (gint) widget->requisition.height;
-	  extra = height / nexpand_children;
+	  available = (gint)allocation->height - widget->requisition.height;
+          natural = MAX (0, MIN (available, natural_height));
+          available -= natural;
+
+	  extra = MAX (0, available / nexpand_children);
 	}
       else
 	{
-	  height = 0;
+	  available = 0;
+          natural = 0;
 	  extra = 0;
 	}
 
-      y = allocation->y + GTK_CONTAINER (box)->border_width;
-      child_allocation.x = allocation->x + GTK_CONTAINER (box)->border_width;
-      child_allocation.width = MAX (1, (gint) allocation->width - (gint) GTK_CONTAINER (box)->border_width * 2);
-
-      children = box->children;
-      while (children)
-	{
-	  child = children->data;
-	  children = children->next;
-
-	  if ((child->pack == GTK_PACK_START) && GTK_WIDGET_VISIBLE (child->widget))
-	    {
-	      if (box->homogeneous)
-		{
-		  if (nvis_children == 1)
-		    child_height = height;
-		  else
-		    child_height = extra;
-
-		  nvis_children -= 1;
-		  height -= extra;
-		}
-	      else
-		{
-		  GtkRequisition child_requisition;
-
-		  gtk_widget_get_child_requisition (child->widget, &child_requisition);
-		  child_height = child_requisition.height + child->padding * 2;
-
-		  if (child->expand)
-		    {
-		      if (nexpand_children == 1)
-			child_height += height;
-		      else
-			child_height += extra;
-
-		      nexpand_children -= 1;
-		      height -= extra;
-		    }
-		}
-
-	      if (child->fill)
-		{
-		  child_allocation.height = MAX (1, child_height - (gint)child->padding * 2);
-		  child_allocation.y = y + child->padding;
-		}
-	      else
-		{
-		  GtkRequisition child_requisition;
-
-		  gtk_widget_get_child_requisition (child->widget, &child_requisition);
-		  child_allocation.height = child_requisition.height;
-		  child_allocation.y = y + (child_height - child_allocation.height) / 2;
-		}
-
-	      gtk_widget_size_allocate (child->widget, &child_allocation);
-
-	      y += child_height + box->spacing;
-	    }
-	}
+      child_allocation.x = allocation->x + border_width;
+      child_allocation.width = MAX (1, (gint) allocation->width - (gint) border_width * 2);
 
-      y = allocation->y + allocation->height - GTK_CONTAINER (box)->border_width;
+      for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
+        {
+          gint y;
 
-      children = box->children;
-      while (children)
-	{
-	  child = children->data;
-	  children = children->next;
+          if (GTK_PACK_START == packing)
+            y = allocation->y + border_width;
+          else
+            y = allocation->y + allocation->height - border_width;
 
-	  if ((child->pack == GTK_PACK_END) && GTK_WIDGET_VISIBLE (child->widget))
-	    {
-	      GtkRequisition child_requisition;
-	      gtk_widget_get_child_requisition (child->widget, &child_requisition);
+          i = 0;
+          children = box->children;
+          while (children)
+            {
+              child = children->data;
+              children = children->next;
 
-              if (box->homogeneous)
+              if (GTK_WIDGET_VISIBLE (child->widget))
                 {
-                  if (nvis_children == 1)
-                    child_height = height;
-                  else
-                    child_height = extra;
+                  if (child->pack == packing)
+                    {
+                      gint child_height;
+
+                      if (box->homogeneous)
+                        {
+                          if (nvis_children == 1)
+                            child_height = available;
+                          else
+                            child_height = extra;
+
+                          nvis_children -= 1;
+                          available -= extra;
+                        }
+                      else
+                        {
+                          child_height = minimum_requisitions[i] + child->padding * 2;
+
+                          if (child->expand)
+                            {
+                              if (nexpand_children == 1)
+                                child_height += available;
+                              else
+                                child_height += extra;
+
+                              nexpand_children -= 1;
+                              available -= extra;
+                            }
+                        }
+
+		      if (natural_height > 0)
+                        child_height += natural * natural_requisitions[i] / natural_height;
+
+                      if (child->fill)
+                        {
+                          child_allocation.height = MAX (1, child_height - (gint)child->padding * 2);
+                          child_allocation.y = y + child->padding;
+                        }
+                      else
+                        {
+                          child_allocation.height = minimum_requisitions[i];
+                          child_allocation.y = y + (child_height - child_allocation.height) / 2;
+                        }
 
-                  nvis_children -= 1;
-                  height -= extra;
-                }
-              else
-                {
-		  child_height = child_requisition.height + child->padding * 2;
+                      if (GTK_PACK_END == packing)
+                        child_allocation.y -= child_height;
 
-                  if (child->expand)
-                    {
-                      if (nexpand_children == 1)
-                        child_height += height;
+                      gtk_widget_size_allocate (child->widget, &child_allocation);
+
+                      if (GTK_PACK_START == packing)
+	                y += child_height + box->spacing;
                       else
-                        child_height += extra;
+                        y -= child_height + box->spacing;
+                    } /* packing */
+
+                  ++i;
+                } /* visible */
+            } /* while children */
+        } /* for packing */
+    } /* nvis_children */
+}
 
-                      nexpand_children -= 1;
-                      height -= extra;
-                    }
-                }
+static GtkExtendedLayoutFeatures
+gtk_vbox_extended_layout_get_features (GtkExtendedLayout *layout)
+{
+  return GTK_EXTENDED_LAYOUT_NATURAL_SIZE;
+}
 
-              if (child->fill)
-                {
-                  child_allocation.height = MAX (1, child_height - (gint)child->padding * 2);
-                  child_allocation.y = y + child->padding - child_height;
-                }
-              else
-                {
-		  child_allocation.height = child_requisition.height;
-                  child_allocation.y = y + (child_height - child_allocation.height) / 2 - child_height;
-                }
+static void
+gtk_vbox_extended_layout_get_natural_size (GtkExtendedLayout *layout,
+                                           GtkRequisition    *requisition)
+{
+  GtkBox *box = GTK_BOX (layout);
 
-              gtk_widget_size_allocate (child->widget, &child_allocation);
+  GtkRequisition child_requisition;
+  GtkBoxChild *child;
+  GList *children;
 
-              y -= (child_height + box->spacing);
-	    }
+  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_IS_EXTENDED_LAYOUT (child->widget) &&
+              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;
 	}
     }
 }
 
+static void
+gtk_vbox_extended_layout_interface_init (GtkExtendedLayoutIface *iface)
+{
+  iface->get_features = gtk_vbox_extended_layout_get_features;
+  iface->get_natural_size = gtk_vbox_extended_layout_get_natural_size;
+}
+
 #define __GTK_VBOX_C__
 #include "gtkaliasdef.c"
diff --git a/tests/testextendedlayout.c b/tests/testextendedlayout.c
index d2bc53e..d5d3421 100644
--- a/tests/testextendedlayout.c
+++ b/tests/testextendedlayout.c
@@ -214,34 +214,53 @@ test_case_append_guide (TestCase  *self,
 
 static void
 append_natural_size_box (TestCase           *test,
-                         GtkWidget          *vbox,
+                         GtkWidget          *parent,
+                         gboolean            vertical,
                          const gchar        *caption,
                          PangoEllipsizeMode  ellipsize)
 {
-  GtkWidget *hbox;
+  GtkWidget *box;
   GtkWidget *button;
   GtkWidget *label;
 
-  hbox = gtk_hbox_new (FALSE, 12);
+  box = vertical ?
+    gtk_vbox_new (FALSE, 12):
+    gtk_hbox_new (FALSE, 12);
 
   label = gtk_label_new ("The small Button");
+  gtk_label_set_angle (GTK_LABEL (label), vertical ? 90 : 0);
   gtk_label_set_ellipsize (GTK_LABEL (label), ellipsize);
 
   button = gtk_button_new ();
   gtk_container_add (GTK_CONTAINER (button), label);
-  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
   test_case_append_guide (test, button, GUIDE_EXTERIOUR_VERTICAL, 0);
+  test_case_append_guide (test, label, GUIDE_EXTERIOUR_VERTICAL, -1);
+
+  label = gtk_label_new ("The large Button");
+  gtk_label_set_angle (GTK_LABEL (label), vertical ? 90 : 0);
 
-  button = gtk_button_new_with_label ("The large Button");
-  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+  button = gtk_button_new ();
+  gtk_container_add (GTK_CONTAINER (button), label);
+  gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);
   test_case_append_guide (test, button, GUIDE_EXTERIOUR_VERTICAL, 1);
 
   label = gtk_label_new (NULL);
   gtk_label_set_markup (GTK_LABEL (label), caption); 
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 
-  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+  if (vertical)
+    {
+      gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0);
+      gtk_label_set_angle (GTK_LABEL (label), 90);
+    }
+  else
+    {
+      gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+      gtk_label_set_angle (GTK_LABEL (label), 0);
+    }
+
+  gtk_box_pack_start (GTK_BOX (parent), label, FALSE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (parent), box, FALSE, TRUE, 0);
 }
 
 static gboolean
@@ -298,36 +317,49 @@ shrink_paned (GtkWidget *button,
 }
 
 static TestCase*
-create_natural_size_test (TestSuite *suite)
+create_natural_size_test (TestSuite *suite,
+                          gboolean   vertical)
 {
-  GtkWidget *vbox, *hint, *button;
+  GtkWidget *box, *hint, *button;
 
-  TestCase *test = test_case_new (suite, "Natural Size", NULL,
-                                  gtk_hpaned_new ());
+  TestCase *test = test_case_new (suite, "Natural Size",
+                                  vertical ? "GtkVBox" : "GtkHBox",
+                                  vertical ? gtk_vpaned_new () : gtk_hpaned_new ());
   gtk_container_set_border_width (GTK_CONTAINER (test->widget), 6);
 
-  vbox = gtk_vbox_new (FALSE, 12);
-  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
-  gtk_paned_pack1 (GTK_PANED (test->widget), vbox, TRUE, TRUE);
+  box = vertical ?
+    gtk_hbox_new (FALSE, 12): 
+    gtk_vbox_new (FALSE, 12);
 
-  append_natural_size_box (test, vbox,
+  gtk_container_set_border_width (GTK_CONTAINER (box), 6);
+  gtk_paned_pack1 (GTK_PANED (test->widget), box, TRUE, TRUE);
+
+  append_natural_size_box (test, box, vertical,
                            "<b>No ellipsizing</b>",
                            PANGO_ELLIPSIZE_NONE);
-  append_natural_size_box (test, vbox,
+  append_natural_size_box (test, box, vertical,
                            "<b>Ellipsizing at start</b>",
                            PANGO_ELLIPSIZE_START);
-  append_natural_size_box (test, vbox,
+  append_natural_size_box (test, box, vertical,
                            "<b>Ellipsizing in the middle</b>",
                            PANGO_ELLIPSIZE_MIDDLE);
-  append_natural_size_box (test, vbox,
+  append_natural_size_box (test, box, vertical,
                            "<b>Ellipsizing at end</b>",
                            PANGO_ELLIPSIZE_END);
 
   button = gtk_button_new_with_label ("Shrink to check ellipsing");
-  gtk_label_set_angle (GTK_LABEL (GTK_BIN (button)->child), -90);
   g_signal_connect (button, "clicked", G_CALLBACK (shrink_paned), test->widget);
 
-  hint = gtk_alignment_new (1.0, 0.5, 0.0, 1.0);
+  if (vertical) 
+    {
+      hint = gtk_alignment_new (0.5, 1.0, 1.0, 0.0);
+    }
+  else
+    {
+      hint = gtk_alignment_new (1.0, 0.5, 0.0, 1.0);
+      gtk_label_set_angle (GTK_LABEL (GTK_BIN (button)->child), -90);
+    }
+
   gtk_container_set_border_width (GTK_CONTAINER (hint), 6);
   gtk_container_add (GTK_CONTAINER (hint), button);
   gtk_paned_pack2 (GTK_PANED (test->widget), hint, FALSE, FALSE);
@@ -1418,11 +1450,13 @@ update_status (TestSuite *suite,
     g_string_append_printf (status, " (%s)", widget_name);
 
   g_string_append_printf (status,
-                          ":\npos=%dx%d; size=%dx%d",
+                          ":\npos=%dx%d; size=%dx%d req=%dx%d",
                           child->allocation.x,
                           child->allocation.y,
                           child->allocation.width,
-                          child->allocation.height);
+                          child->allocation.height,
+                          child->requisition.width,
+                          child->requisition.height);
 
   if (GTK_IS_EXTENDED_LAYOUT (child))
     {
@@ -1694,7 +1728,8 @@ test_suite_new ()
   TestSuite* self = g_new0 (TestSuite, 1);
 
   test_suite_setup_ui (self);
-  test_suite_append (self, create_natural_size_test (self));
+  test_suite_append (self, create_natural_size_test (self, FALSE));
+  test_suite_append (self, create_natural_size_test (self, TRUE));
   test_suite_append (self, create_height_for_width_test (self));
   test_suite_append (self, create_baseline_test (self));
   test_suite_append (self, create_baseline_test_bin (self));



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