[gtk+/extended-layout-jhs: 57/64] Start real testing of height-for-width and width-for-height. Add



commit 79c40197a05d6c3319f69d4fa803972af1d960b5
Author: Mathias Hasselmann <mathias hasselmann gmx de>
Date:   Mon Aug 20 17:59:44 2007 +0000

    Start real testing of height-for-width and width-for-height. Add
    
    2007-08-20  Mathias Hasselmann  <mathias hasselmann gmx de>
    
    	* tests/testextendedlayout.c: Start real testing of height-for-width
    	and width-for-height.
    	* gtk/gtklabel.c, gtk/gtklabel.h, gtk/gtk.symbols: Add "full-size"
    	property to be able to provide a meaningfull implementation of
    	height-for-width and width-for-height.
    	* gtk/gtkvbox.c: Consider height-for-width information.
    
    svn path=/branches/extended-layout/; revision=18657

 ChangeLog.gtk-extended-layout |    9 ++++
 gtk/gtk.symbols               |    2 +
 gtk/gtklabel.c                |  105 +++++++++++++++++++++++++++++++----------
 gtk/gtklabel.h                |    3 +
 gtk/gtkvbox.c                 |   75 +++++++++++++++++++++--------
 tests/testextendedlayout.c    |   79 +++++++++++++++++++++---------
 6 files changed, 203 insertions(+), 70 deletions(-)
---
diff --git a/ChangeLog.gtk-extended-layout b/ChangeLog.gtk-extended-layout
index 89810f1..aaed61f 100644
--- a/ChangeLog.gtk-extended-layout
+++ b/ChangeLog.gtk-extended-layout
@@ -1,3 +1,12 @@
+2007-08-20  Mathias Hasselmann  <mathias hasselmann gmx de>
+
+	* tests/testextendedlayout.c: Start real testing of height-for-width
+	and width-for-height.
+	* gtk/gtklabel.c, gtk/gtklabel.h, gtk/gtk.symbols: Add "full-size"
+	property to be able to provide a meaningfull implementation of
+	height-for-width and width-for-height.
+	* gtk/gtkvbox.c: Consider height-for-width information.
+
 2007-08-13  Mathias Hasselmann  <mathias hasselmann gmx de>
 
 	* tests/testextendedlayout.c: Provide context menu to directly select
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index dcca18e..1824706 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -2032,6 +2032,7 @@ gtk_label_get_type G_GNUC_CONST
 gtk_label_get_use_markup
 gtk_label_get_use_underline
 gtk_label_get_width_chars
+gtk_label_get_full_size
 gtk_label_new
 gtk_label_new_with_mnemonic
 gtk_label_select_region
@@ -2054,6 +2055,7 @@ gtk_label_set_text_with_mnemonic
 gtk_label_set_use_markup
 gtk_label_set_use_underline
 gtk_label_set_width_chars
+gtk_label_set_full_size
 #endif
 #endif
 
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 58e15cd..e738235 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -50,7 +50,7 @@
 
 #define GTK_LABEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_LABEL, GtkLabelPrivate))
 
-#ifndef INFINITY /* Why don't we use C99 again? */
+#ifndef INFINITY /* Why again don't we use C99? */
 #define INFINITY HUGE_VAL
 #endif
 
@@ -60,6 +60,7 @@ typedef struct
   gint width_chars;
   gint max_width_chars;
   gint baseline_offset;
+  gboolean full_size;
 }
 GtkLabelPrivate;
 
@@ -102,7 +103,8 @@ enum {
   PROP_WIDTH_CHARS,
   PROP_SINGLE_LINE_MODE,
   PROP_ANGLE,
-  PROP_MAX_WIDTH_CHARS
+  PROP_MAX_WIDTH_CHARS,
+  PROP_FULL_SIZE
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -524,6 +526,23 @@ gtk_label_class_init (GtkLabelClass *class)
                                                      G_MAXINT,
                                                      -1,
                                                      GTK_PARAM_READWRITE));
+
+  /**
+   * GtkLabel:full-size:
+   *
+   * Use the entire space the widget got assigned for text wrapping. Overrides
+   * any #GtkLabel:width-chars, #GtkLabel:max-width-chars and screen size based
+   * constraints. Requires #GtkLabel:angle to be 0°, 90°, 180° or 270°.
+   *
+   * Since: 2.14
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FULL_SIZE,
+                                   g_param_spec_boolean ("full-size",
+							 P_("Full size"),
+							 P_("Use the entire size of the widget to wrap text"),
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE));
   /*
    * Key bindings
    */
@@ -700,6 +719,9 @@ gtk_label_set_property (GObject      *object,
     case PROP_MAX_WIDTH_CHARS:
       gtk_label_set_max_width_chars (label, g_value_get_int (value));
       break;
+    case PROP_FULL_SIZE:
+      gtk_label_set_full_size (label, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -783,6 +805,9 @@ gtk_label_get_property (GObject     *object,
     case PROP_MAX_WIDTH_CHARS:
       g_value_set_int (value, gtk_label_get_max_width_chars (label));
       break;
+    case PROP_FULL_SIZE:
+      g_value_set_int (value, gtk_label_get_full_size (label));
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1966,7 +1991,7 @@ get_label_wrap_width (GtkLabel *label)
   GtkLabelPrivate *priv;
 
   priv = GTK_LABEL_GET_PRIVATE (label);
-  
+
   if (priv->wrap_width < 0)
     {
       if (priv->width_chars > 0 || priv->max_width_chars > 0)
@@ -2080,14 +2105,14 @@ gtk_label_ensure_layout (GtkLabel *label)
 
 	      wrap_width = get_label_wrap_width (label);
 	      width = MIN (width, wrap_width);
-	      width = MIN (width,
+ 	      width = MIN (width,
 			   PANGO_SCALE * (gdk_screen_get_width (screen) + 1) / 2);
-	      
+
 	      pango_layout_set_width (label->layout, width);
 	      pango_layout_get_extents (label->layout, NULL, &logical_rect);
 	      width = logical_rect.width;
 	      height = logical_rect.height;
-	      
+
 	      /* Unfortunately, the above may leave us with a very unbalanced looking paragraph,
 	       * so we try short search for a narrower width that leaves us with the same height
 	       */
@@ -2212,13 +2237,11 @@ static void
 gtk_label_size_allocate (GtkWidget     *widget,
                          GtkAllocation *allocation)
 {
-  GtkLabel *label;
-
-  label = GTK_LABEL (widget);
+  GtkLabel *label = GTK_LABEL (widget);
 
   (* GTK_WIDGET_CLASS (gtk_label_parent_class)->size_allocate) (widget, allocation);
 
-  if (label->ellipsize)
+  if (label->ellipsize || GTK_LABEL_GET_PRIVATE (label)->full_size)
     {
       if (label->layout)
 	{
@@ -2383,7 +2406,7 @@ get_layout_location (GtkLabel  *label,
   else
     xalign = 1.0 - misc->xalign;
 
-  if (label->ellipsize || priv->width_chars > 0)
+  if (label->ellipsize || priv->width_chars > 0 || GTK_LABEL_GET_PRIVATE (label)->full_size)
     {
       int width;
       PangoRectangle logical;
@@ -3737,6 +3760,32 @@ gtk_label_set_use_underline (GtkLabel *label,
     gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
 }
 
+gboolean
+gtk_label_get_full_size (GtkLabel *label)
+{
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  return GTK_LABEL_GET_PRIVATE (label)->full_size;
+}
+
+void
+gtk_label_set_full_size (GtkLabel *label,
+			 gboolean  setting)
+{
+  GtkLabelPrivate *priv;
+
+  g_return_if_fail (GTK_IS_LABEL (label));
+  priv = GTK_LABEL_GET_PRIVATE (label);
+
+  if (priv->full_size != setting)
+    {
+      priv->full_size = setting;
+
+      g_object_notify (G_OBJECT (label), "full-size");
+      gtk_label_invalidate_wrap_width (label);
+      gtk_widget_queue_resize (GTK_WIDGET (label));
+    }
+}
+
 /**
  * gtk_label_get_use_underline:
  * @label: a #GtkLabel
@@ -4301,39 +4350,44 @@ gtk_label_do_popup (GtkLabel       *label,
 static GtkExtendedLayoutFeatures
 gtk_label_extended_layout_get_features (GtkExtendedLayout *layout)
 {
+  GtkLabel *label = GTK_LABEL (layout);
   GtkExtendedLayoutFeatures features;
-  GtkLabel *label;
 
   features =
     GTK_EXTENDED_LAYOUT_NATURAL_SIZE |
     GTK_EXTENDED_LAYOUT_BASELINES;
-  label = GTK_LABEL (layout);
 
   if (label->wrap)
-    features |= GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH;
+    {
+      gdouble angle = gtk_label_get_angle (label);
+
+      if (0 == angle || 180 == angle)
+        features |= GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH;
+      else if (90 == angle || 270 == angle)
+        features |= GTK_EXTENDED_LAYOUT_WIDTH_FOR_HEIGHT;
+    }
 
   return features;
 }
 
 static gint
-gtk_label_extended_layout_get_height_for_width (GtkExtendedLayout *layout,
-                                                gint               width)
+gtk_label_extended_layout_get_size_for_other (GtkExtendedLayout *layout,
+                                              gint               size)
 {
+  GtkLabel *label = GTK_LABEL (layout);
+  gdouble angle = gtk_label_get_angle (label);
   PangoLayout *tmp;
-  GtkLabel *label;
-  gint height;
-
-  label = GTK_LABEL (layout);
 
-  g_return_val_if_fail (label->wrap, -1);
+  // this test is slightly more tolerant than the get_features test
+  g_assert (0 == (((gint)angle) % 90));
 
   gtk_label_ensure_layout (label);
   tmp = pango_layout_copy (label->layout);
-  pango_layout_set_width (tmp, PANGO_SCALE * width);
-  pango_layout_get_pixel_size (tmp, NULL, &height);
+  pango_layout_set_width (tmp, PANGO_SCALE * size);
+  pango_layout_get_pixel_size (tmp, NULL, &size);
   g_object_unref (tmp);
 
-  return height;
+  return size;
 }
 
 static void
@@ -4406,7 +4460,8 @@ static void
 gtk_label_extended_layout_interface_init (GtkExtendedLayoutIface *iface)
 {
   iface->get_features = gtk_label_extended_layout_get_features;
-  iface->get_height_for_width = gtk_label_extended_layout_get_height_for_width;
+  iface->get_height_for_width = gtk_label_extended_layout_get_size_for_other;
+  iface->get_width_for_height = gtk_label_extended_layout_get_size_for_other;
   iface->get_natural_size = gtk_label_extended_layout_get_natural_size;
   iface->get_baselines = gtk_label_extended_layout_get_baselines;
   iface->set_baseline_offset = gtk_label_extended_layout_set_baseline_offset;
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index e13a716..18a970e 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -118,6 +118,9 @@ gboolean              gtk_label_get_use_markup    (GtkLabel      *label);
 void                  gtk_label_set_use_underline (GtkLabel      *label,
 						   gboolean       setting);
 gboolean              gtk_label_get_use_underline (GtkLabel      *label);
+void                  gtk_label_set_full_size     (GtkLabel      *label,
+						   gboolean       setting);
+gboolean              gtk_label_get_full_size     (GtkLabel      *label);
 
 void     gtk_label_set_markup_with_mnemonic       (GtkLabel         *label,
 						   const gchar      *str);
diff --git a/gtk/gtkvbox.c b/gtk/gtkvbox.c
index d0860c5..e8d90d0 100644
--- a/gtk/gtkvbox.c
+++ b/gtk/gtkvbox.c
@@ -72,11 +72,38 @@ gtk_vbox_new (gboolean homogeneous,
   return GTK_WIDGET (vbox);
 }
 
+typedef void (*GtkChildSizeRequest) (GtkWidget      *child,
+			             GtkRequisition *requisition,
+                                     GtkWidget      *widget);
 
 static void
-gtk_vbox_real_size_request (GtkWidget      *widget,
-		            GtkRequisition *requisition,
-		            gboolean        consider_natural_size)
+gtk_vbox_natural_size_request (GtkWidget      *child,
+			       GtkRequisition *requisition,
+                               GtkWidget      *widget)
+{
+  GtkExtendedLayoutFeatures features = 0;
+
+  if (GTK_IS_EXTENDED_LAYOUT (child))
+    features = gtk_extended_layout_get_features ((GtkExtendedLayout*) child);
+
+  if (features & GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH)
+    {
+      requisition->width = widget->allocation.width;
+      requisition->height = gtk_extended_layout_get_height_for_width (
+        (GtkExtendedLayout*) child, widget->allocation.width);
+    }
+  else if (features & GTK_EXTENDED_LAYOUT_NATURAL_SIZE)
+    gtk_extended_layout_get_natural_size ((GtkExtendedLayout*) child, requisition);
+  else 
+    gtk_widget_size_request (child, requisition);
+
+g_print ("%s: %dx%d (%dx%d)\n", G_OBJECT_TYPE_NAME (child), requisition->width, requisition->height, child->allocation.width, child->allocation.height);
+}
+
+static void
+gtk_vbox_real_size_request (GtkWidget           *widget,
+		            GtkRequisition      *requisition,
+                            GtkChildSizeRequest  size_request_func)
 {
   GtkBox *box;
   GtkBoxChild *child;
@@ -98,11 +125,7 @@ gtk_vbox_real_size_request (GtkWidget      *widget,
 
       if (GTK_WIDGET_VISIBLE (child->widget))
 	{
-          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);
+          size_request_func (child->widget, &child_requisition, widget);
 
 	  if (box->homogeneous)
 	    {
@@ -135,7 +158,7 @@ static void
 gtk_vbox_size_request (GtkWidget      *widget,
 		       GtkRequisition *requisition)
 {
-  gtk_vbox_real_size_request (widget, requisition, FALSE);
+  gtk_vbox_real_size_request (widget, requisition, (GtkChildSizeRequest)gtk_widget_size_request);
 }
 
 static void
@@ -179,12 +202,14 @@ gtk_vbox_size_allocate (GtkWidget     *widget,
       gint *minimum_requisitions;
 
       gint available, natural, extra;
-      gint natural_height;
+      gint minimum_height, natural_height;
       gint i;
 
       border_width = GTK_CONTAINER (box)->border_width;
 
+      minimum_height = 0;
       natural_height = 0;
+
       natural_requisitions = g_newa (gint, nvis_children);
       minimum_requisitions = g_newa (gint, nvis_children);
 
@@ -202,19 +227,27 @@ gtk_vbox_size_allocate (GtkWidget     *widget,
 
               gtk_widget_size_request (child->widget, &child_requisition);
               minimum_requisitions[i] = child_requisition.height;
+              natural_requisitions[i] = 0;
 
-              if (GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child->widget))
+              if (GTK_IS_EXTENDED_LAYOUT (child->widget))
                 {
-                  gtk_extended_layout_get_natural_size (
-                    GTK_EXTENDED_LAYOUT (child->widget), 
-                    &child_requisition);
-                  natural_requisitions[i] =
-                    child_requisition.height - 
-                    minimum_requisitions[i];
+                  GtkExtendedLayout *layout = (GtkExtendedLayout*)child->widget;
+                  GtkExtendedLayoutFeatures features = gtk_extended_layout_get_features (layout);
+              
+                  if (features & GTK_EXTENDED_LAYOUT_HEIGHT_FOR_WIDTH)
+                    {
+                      gint height = gtk_extended_layout_get_height_for_width (layout, allocation->width);
+                      minimum_requisitions[i] = MIN (minimum_requisitions[i], height);
+                    }
+                  else if (features & GTK_EXTENDED_LAYOUT_NATURAL_SIZE)
+                    {
+                      gtk_extended_layout_get_natural_size (layout, &child_requisition);
+                      natural_requisitions[i] = child_requisition.height - minimum_requisitions[i];
+                    }
+
                 }
-              else
-                natural_requisitions[i] = 0;
 
+              minimum_height += minimum_requisitions[i];
               natural_height += natural_requisitions[i++];
             }
         }
@@ -230,7 +263,7 @@ gtk_vbox_size_allocate (GtkWidget     *widget,
 	{
           if (nexpand_children > 0 || natural_height > 0)
             {
-	      available = (gint)allocation->height - widget->requisition.height;
+	      available = (gint)allocation->height - minimum_height;
               natural = MAX (0, MIN (available, natural_height));
               available -= natural;
             }
@@ -339,7 +372,7 @@ static void
 gtk_vbox_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                            GtkRequisition    *requisition)
 {
-  gtk_vbox_real_size_request (GTK_WIDGET (layout), requisition, TRUE);
+  gtk_vbox_real_size_request (GTK_WIDGET (layout), requisition, gtk_vbox_natural_size_request);
 }
 
 static void
diff --git a/tests/testextendedlayout.c b/tests/testextendedlayout.c
index ddb9a5e..5dd0f30 100644
--- a/tests/testextendedlayout.c
+++ b/tests/testextendedlayout.c
@@ -920,37 +920,67 @@ natural_size_test_misc_new (TestSuite *suite,
 }
 
 static TestCase*
-height_for_width_test_new (TestSuite *suite)
+height_for_width_test_new (TestSuite *suite,
+                           gboolean   vertical)
 {
-  PangoLayout *layout;
-  PangoRectangle log;
-  GtkWidget *child;
+  GtkWidget *box, *child;
+  TestCase *test;
+  int i;
 
-  TestCase *test = test_case_new (suite, "Height for Width", NULL,
-                                  gtk_hbox_new (FALSE, 12));
+  if (vertical)
+    {
+      test = test_case_new (suite, "Height for Width", NULL, gtk_hpaned_new ());
+      box = gtk_vbox_new (FALSE, 6);
 
-  gtk_container_set_border_width (GTK_CONTAINER (test->widget), 12);
+      child = gtk_label_new ("Move the handle to test\n"
+                             "height-for-width requests");
 
-  child = gtk_label_new (lorem_ipsum);
-  gtk_label_set_line_wrap (GTK_LABEL (child), TRUE);
-  gtk_label_set_use_markup (GTK_LABEL (child), TRUE);
-  gtk_box_pack_start (GTK_BOX (test->widget), child, TRUE, TRUE, 0);
-  layout = gtk_label_get_layout (GTK_LABEL (child));
+      gtk_label_set_angle (GTK_LABEL (child), 90);
+    }
+  else
+    {
+      test = test_case_new (suite, "Width for Height", NULL, gtk_vpaned_new ());
+      box = gtk_hbox_new (FALSE, 6);
 
-  pango_layout_get_pixel_extents (layout, NULL, &log);
-  gtk_widget_set_size_request (test->widget, log.width * 3 / 2, -1);
+      child = gtk_label_new ("Move the handle to test\n"
+                             "width-for-height requests");
+    }
 
-  test_case_append_guide (test, child, GUIDE_INTERIOUR_BOTH, 0);
-  test_case_append_guide (test, child, GUIDE_EXTERIOUR_BOTH, 0);
-  test_case_append_guide (test, child, GUIDE_BASELINE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (test->widget), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (box), 6);
+  gtk_misc_set_padding (GTK_MISC (child), 6, 6);
 
-  child = gtk_button_new ();
-  gtk_container_add (GTK_CONTAINER (child),
-                     gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO,
-                                               GTK_ICON_SIZE_DIALOG));
-  gtk_box_pack_start (GTK_BOX (test->widget), child, FALSE, TRUE, 0);
+  gtk_paned_pack1 (GTK_PANED (test->widget), box, TRUE, FALSE);
+  gtk_paned_pack2 (GTK_PANED (test->widget), child, FALSE, FALSE);
 
-  test_case_append_guide (test, child, GUIDE_EXTERIOUR_BOTH, 1);
+  for (i = 0; i < 4; ++i)
+    {
+      if (2 != i)
+        {       
+          child = gtk_label_new (lorem_ipsum);
+          gtk_label_set_line_wrap (GTK_LABEL (child), TRUE);
+          gtk_label_set_use_markup (GTK_LABEL (child), TRUE);
+          test_case_append_guide (test, child, GUIDE_EXTERIOUR_BOTH, -1);
+          test_case_append_guide (test, child, GUIDE_INTERIOUR_BOTH, -1);
+          gtk_box_pack_start (GTK_BOX (box), child, FALSE, TRUE, 0);
+
+          if (i > 0)
+            gtk_label_set_full_size (GTK_LABEL (child), TRUE);
+
+          if (i > 2)
+            gtk_label_set_angle (GTK_LABEL (child), vertical ? 180 : 270);
+          else if (!vertical)
+            gtk_label_set_angle (GTK_LABEL (child), 90);
+        }
+      else
+        {       
+          child = gtk_button_new ();
+          gtk_container_add (GTK_CONTAINER (child),
+                             gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO,
+                                                       GTK_ICON_SIZE_DIALOG));
+          gtk_box_pack_start (GTK_BOX (box), child, TRUE, TRUE, 0);
+        }
+    }
 
   return test;
 }
@@ -2429,7 +2459,8 @@ test_suite_new (gchar *arg0)
   test_suite_append (self, natural_size_test_new (self, FALSE, TRUE));
   test_suite_append (self, natural_size_test_new (self, TRUE, TRUE));
   test_suite_append (self, natural_size_test_misc_new (self, arg0));
-  test_suite_append (self, height_for_width_test_new (self));
+  test_suite_append (self, height_for_width_test_new (self, TRUE));
+  test_suite_append (self, height_for_width_test_new (self, FALSE));
   test_suite_append (self, baseline_test_new (self));
   test_suite_append (self, baseline_test_bin_new (self));
   test_suite_append (self, baseline_test_hbox_new (self, FALSE));



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