[gtk+/extended-layout-jhs: 30/64] Properly evaluate natural size. Consider natural size for child placement.



commit 5f033a2f4fab17347ecd4db1448cb6a0d6afb93c
Author: Mathias Hasselmann <mathias hasselmann gmx de>
Date:   Mon Jul 2 10:26:15 2007 +0000

    Properly evaluate natural size. Consider natural size for child placement.
    
    2007-07-02  Mathias Hasselmann  <mathias hasselmann gmx de>
    
    	* gtk/gtkbin.c: Properly evaluate natural size.
    	* gtk/gtkhbox.c: Consider natural size for child placement.
    	* gtk/gtklabel.c: Drop any PangoLayout width assigned during the
    	size allocation process to get proper natural size readings.
    	* tests/testextendedlayout.c: Add some GtkHPaned to the natural
    	size test for dynamic evaluation of the algorithm.
    
    svn path=/branches/extended-layout/; revision=18339

 ChangeLog.gtk-extended-layout |   11 ++++
 gtk/gtkbin.c                  |   23 ++++++---
 gtk/gtkhbox.c                 |  120 +++++++++++++++++++++++++++++------------
 gtk/gtklabel.c                |    7 +++
 tests/testextendedlayout.c    |   85 ++++++++++++++++++++++++++---
 5 files changed, 197 insertions(+), 49 deletions(-)
---
diff --git a/ChangeLog.gtk-extended-layout b/ChangeLog.gtk-extended-layout
index 608847d..524db8b 100644
--- a/ChangeLog.gtk-extended-layout
+++ b/ChangeLog.gtk-extended-layout
@@ -1,3 +1,14 @@
+2007-07-02  Mathias Hasselmann  <mathias hasselmann gmx de>
+
+	* gtk/gtkbin.c: Properly evaluate natural size.
+	* gtk/gtkhbox.c: Consider natural size for child placement.
+	* gtk/gtklabel.c: Drop any PangoLayout width assigned during the
+	size allocation process to get proper natural size readings.
+	* tests/testextendedlayout.c: Add some GtkHPaned to the natural
+	size test for dynamic evaluation of the algorithm. Create guides for
+	the button of the height-for-width test for debugging, as it is
+	affected by natural sizing of GtkHBox.
+
 2007-07-01  Mathias Hasselmann  <mathias hasselmann gmx de>
 
 	* gtk/gtk.symbols, gtk/gtkextendedlayout.c, gtk/gtkextendedlayout.h:
diff --git a/gtk/gtkbin.c b/gtk/gtkbin.c
index fdc7b21..a7ffce2 100644
--- a/gtk/gtkbin.c
+++ b/gtk/gtkbin.c
@@ -73,8 +73,8 @@ gtk_bin_child_type (GtkContainer *container)
 {
   if (!GTK_BIN (container)->child)
     return GTK_TYPE_WIDGET;
-  else
-    return G_TYPE_NONE;
+
+  return G_TYPE_NONE;
 }
 
 static void
@@ -195,11 +195,22 @@ gtk_bin_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                           GtkRequisition    *requisition)
 {
   GtkBin *bin = GTK_BIN (layout);
+  GtkExtendedLayout *child_layout;
 
   g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (bin->child));
 
-  layout = GTK_EXTENDED_LAYOUT (bin->child);
-  return gtk_extended_layout_get_natural_size (layout, requisition);
+  child_layout = GTK_EXTENDED_LAYOUT (bin->child);
+  gtk_extended_layout_get_natural_size (child_layout, requisition);
+
+  if (GTK_EXTENDED_LAYOUT_HAS_PADDING (layout))
+    {
+      GtkBorder padding;
+
+      gtk_extended_layout_get_padding (layout, &padding);
+
+      requisition->width += padding.left + padding.right;
+      requisition->height += padding.top + padding.bottom;
+    }
 }
 
 static gint
@@ -222,9 +233,7 @@ gtk_bin_extended_layout_get_baselines (GtkExtendedLayout  *layout,
       GtkBorder padding;
 
       if (GTK_EXTENDED_LAYOUT_HAS_PADDING (bin))
-        {
-          gtk_extended_layout_get_padding (layout, &padding);
-        }
+        gtk_extended_layout_get_padding (layout, &padding);
       else
         padding.top = GTK_CONTAINER (bin)->border_width;
 
diff --git a/gtk/gtkhbox.c b/gtk/gtkhbox.c
index b885185..683fd36 100644
--- a/gtk/gtkhbox.c
+++ b/gtk/gtkhbox.c
@@ -173,13 +173,12 @@ gtk_hbox_size_request (GtkWidget      *widget,
   if (nvis_children > 0)
     {
       GtkHBoxPrivate *priv = GTK_HBOX_GET_PRIVATE (widget);
-      gint effective_baseline, i;
+      gint effective_baseline = 0, i;
       gint *baselines = NULL;
 
       if (priv->baseline_policy != GTK_BASELINE_NONE)
         {
           baselines = g_newa (gint, nvis_children);
-          effective_baseline = 0;
 
           i = 0;
           children = box->children;
@@ -265,13 +264,9 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
   GtkBoxChild *child;
   GList *children;
 
-  GtkTextDirection direction;
-
   box = GTK_BOX (widget);
   widget->allocation = *allocation;
 
-  direction = gtk_widget_get_direction (widget);
-  
   nvis_children = 0;
   nexpand_children = 0;
   children = box->children;
@@ -292,46 +287,103 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
   if (nvis_children > 0)
     {
       GtkHBoxPrivate *priv = GTK_HBOX_GET_PRIVATE (widget);
-      GtkAllocation child_allocation;
-      gint effective_baseline, i;
+
+      gint effective_baseline;
       GtkPackType packing;
       gint *baselines;
 
-      gint width;
-      gint extra;
+      GtkTextDirection direction;
+      gint border_width;
 
-      baselines = g_newa (gint, nvis_children);
-      effective_baseline = 0;
+      GtkAllocation child_allocation;
+
+      gint *natural_requisitions;
+      gint *minimum_requisitions;
+
+      gint natural_width;
+      gint minimum_width;
+
+      gint available, natural, extra;
+      gint i;
+
+      direction = gtk_widget_get_direction (widget);
+      border_width = GTK_CONTAINER (box)->border_width;
+
+      natural_width = 0;
+      natural_requisitions = g_newa (gint, nvis_children);
+      minimum_requisitions = g_newa (gint, nvis_children);
+
+      children = box->children;
+      i = 0;
+
+      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.width;
+
+              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.width - 
+                    minimum_requisitions[i];
+                }
+              else
+                natural_requisitions[i] = 0;
+
+              natural_width += natural_requisitions[i++];
+            }
+        }
+
+      minimum_width = widget->requisition.width - border_width * 2 - 
+                      (nvis_children - 1) * box->spacing;
 
       if (box->homogeneous)
 	{
-	  width = (allocation->width -
-		   GTK_CONTAINER (box)->border_width * 2 -
-		   (nvis_children - 1) * box->spacing);
-	  extra = width / nvis_children;
+	  available = (allocation->width - border_width * 2 -
+		       (nvis_children - 1) * box->spacing);
+	  extra = available / nvis_children;
+          natural = 0;
 	}
       else if (nexpand_children > 0)
 	{
-	  width = (gint) allocation->width - (gint) widget->requisition.width;
-	  extra = width / nexpand_children;
+	  available = (gint)allocation->width - widget->requisition.width;
+          natural = MAX (0, MIN (available, natural_width));
+          available -= natural;
+
+	  extra = MAX (0, available / nexpand_children);
 	}
       else
 	{
-	  width = 0;
+	  available = 0;
+          natural = 0;
 	  extra = 0;
 	}
 
-      child_allocation.y = allocation->y + GTK_CONTAINER (box)->border_width;
-      child_allocation.height = MAX (1, (gint) allocation->height - (gint) GTK_CONTAINER (box)->border_width * 2);
+      effective_baseline = 0;
+      baselines = g_newa (gint, nvis_children);
+
+      child_allocation.y = allocation->y + border_width;
+      child_allocation.height = MAX (1, (gint) allocation->height - (gint) border_width * 2);
 
       for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
         {
           gint x;
 
           if (GTK_PACK_START == packing)
-            x = allocation->x + GTK_CONTAINER (box)->border_width;
+            x = allocation->x + border_width;
           else
-            x = allocation->x + allocation->width - GTK_CONTAINER (box)->border_width;
+            x = allocation->x + allocation->width - border_width;
 
           i = 0;
           children = box->children;
@@ -344,37 +396,37 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
                 {
                   if ((child->pack == packing))
                     {
-                      GtkRequisition child_requisition;
                       gint child_width;
 
-                      gtk_widget_get_child_requisition (child->widget, &child_requisition);
-
                       if (box->homogeneous)
                         {
                           if (nvis_children == 1)
-                            child_width = width;
+                            child_width = available;
                           else
                             child_width = extra;
 
                           nvis_children -= 1;
-                          width -= extra;
+                          available -= extra;
                         }
                       else
                         {
-                          child_width = child_requisition.width + child->padding * 2;
+                          child_width = minimum_requisitions[i] + child->padding * 2;
 
                           if (child->expand)
                             {
                               if (nexpand_children == 1)
-                                child_width += width;
+                                child_width += available;
                               else
                                 child_width += extra;
 
                               nexpand_children -= 1;
-                              width -= extra;
+                              available -= extra;
                             }
                         }
 
+		      if (natural_width > 0)
+                        child_width += natural * natural_requisitions[i] / natural_width;
+
                       if (child->fill)
                         {
                           child_allocation.width = MAX (1, (gint) child_width - (gint) child->padding * 2);
@@ -382,7 +434,7 @@ gtk_hbox_size_allocate (GtkWidget     *widget,
                         }
                       else
                         {
-                          child_allocation.width = child_requisition.width;
+                          child_allocation.width = minimum_requisitions[i];
                           child_allocation.x = x + (child_width - child_allocation.width) / 2;
                         }
 
@@ -498,8 +550,8 @@ gtk_hbox_extended_layout_get_natural_size (GtkExtendedLayout *layout,
   GtkBoxChild *child;
   GList *children;
 
-  requisition->width = 0;
-  requisition->height = 0;
+  requisition->width = GTK_CONTAINER (box)->border_width * 2;
+  requisition->height = GTK_CONTAINER (box)->border_width * 2;
 
   children = box->children;
   while (children)
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index ab304f6..28acb10 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -4272,14 +4272,21 @@ gtk_label_extended_layout_get_natural_size (GtkExtendedLayout *layout,
 {
   GtkLabel *label;
   gboolean ellipsize;
+  PangoLayout *tmp;
 
   label = GTK_LABEL (layout);
   ellipsize = label->ellipsize;
   label->ellipsize = PANGO_ELLIPSIZE_NONE;
 
+  tmp = label->layout;
+  label->layout = pango_layout_copy (tmp);
+
+  pango_layout_set_width (label->layout, -1);
   gtk_label_size_request (GTK_WIDGET (label), requisition);
 
+  g_object_unref (label->layout);
   label->ellipsize = ellipsize;
+  label->layout = tmp;
 }
 
 static gint
diff --git a/tests/testextendedlayout.c b/tests/testextendedlayout.c
index bfba766..3777cdf 100644
--- a/tests/testextendedlayout.c
+++ b/tests/testextendedlayout.c
@@ -193,6 +193,7 @@ test_case_append_guide (TestCase  *self,
 
 static void
 append_natural_size_box (TestCase           *test,
+                         GtkWidget          *vbox,
                          const gchar        *caption,
                          PangoEllipsizeMode  ellipsize)
 {
@@ -218,32 +219,98 @@ append_natural_size_box (TestCase           *test,
   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 (test->widget), label, FALSE, TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (test->widget), hbox, FALSE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+}
+
+static gboolean
+restore_paned (gpointer data)
+{
+  GtkPaned *paned;
+  GtkWidget *hint;
+  gint pos;
 
+
+  paned = GTK_PANED (data);
+  hint = gtk_paned_get_child2 (paned);
+  gtk_widget_set_sensitive (hint, TRUE);
+
+  pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (paned), "initial-position"));
+  gtk_paned_set_position (paned, pos);
+
+  return FALSE;
+}
+
+static gboolean
+shrink_paned_timeout (gpointer data)
+{
+  GtkPaned *paned;
+  gint pos;
+
+  paned = GTK_PANED (data);
+  pos = gtk_paned_get_position (paned);
+
+  if (pos < 20)
+    {
+      g_timeout_add (1000, restore_paned, paned);
+      return FALSE;
+    }
+
+  gtk_paned_set_position (paned, pos - 5);
+  return TRUE;
+}
+
+static void
+shrink_paned (GtkWidget *button,
+              gpointer   data)
+{
+  GtkPaned *paned;
+  GtkWidget *hint;
+
+  paned = GTK_PANED (data);
+  hint = gtk_paned_get_child2 (paned);
+  gtk_widget_set_sensitive (hint, FALSE);
+
+  g_object_set_data (G_OBJECT (paned), "initial-position",
+                     GINT_TO_POINTER (gtk_paned_get_position (paned)));
+  g_timeout_add (50, shrink_paned_timeout, paned);
 }
 
 static TestCase*
 create_natural_size_test (TestSuite *suite)
 {
+  GtkWidget *vbox, *hint, *button;
+
   TestCase *test = test_case_new (suite, "Natural Size", NULL,
-                                  gtk_vbox_new (FALSE, 12));
+                                  gtk_hpaned_new ());
+  gtk_container_set_border_width (GTK_CONTAINER (test->widget), 6);
 
-  gtk_container_set_border_width (GTK_CONTAINER (test->widget), 12);
+  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);
 
-  append_natural_size_box (test,
+  append_natural_size_box (test, vbox,
                            "<b>No ellipsizing</b>",
                            PANGO_ELLIPSIZE_NONE);
-  append_natural_size_box (test,
+  append_natural_size_box (test, vbox,
                            "<b>Ellipsizing at start</b>",
                            PANGO_ELLIPSIZE_START);
-  append_natural_size_box (test,
+  append_natural_size_box (test, vbox,
                            "<b>Ellipsizing in the middle</b>",
                            PANGO_ELLIPSIZE_MIDDLE);
-  append_natural_size_box (test,
+  append_natural_size_box (test, vbox,
                            "<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);
+  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);
+
   return test;
 }
 
@@ -278,6 +345,8 @@ create_height_for_width_test (TestSuite *suite)
                                                GTK_ICON_SIZE_DIALOG));
   gtk_box_pack_start (GTK_BOX (test->widget), child, FALSE, TRUE, 0);
 
+  test_case_append_guide (test, child, GUIDE_EXTERIOUR_BOTH, 1);
+
   return test;
 }
 



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