[PATCH] Fix a number of GtkLabel extended layout issues



This is my first patch, so sorry if I get the submission process wrong.
 This patch is meant for extended-layout branch, which hasn't been
merged in a year.

It fixes a number of issues with GtkLabel's extended layout support
which are uncovered by my next patch:

1) the height_for_width/width_for_height implementations worked by
computing the height in a separate PangoLayout object.  However, they
did not record the desired wrapping width anywhere.  This patch fixes it
by recording it in GtkLabelPrivate.

A side issue is that layout could be done before realizing.  Then, upon
realizing, gtk_label_style_set is called and it invalidates the wrapping
with.  This patch fixes it by not invalidating the wrapping width if it
was set by height_for_width/width_for_height.

2) For wrapping labels, gtk_label_extended_layout_get_natural_size was
destroying the wrapping width set by height_for_width/width_for_height.
 This happened because it uses gtk_label_size_request which in turn
clears the layout in the case of a wrapping label.

This patch fixes it by preserving priv->wrap_width around
get_natural_size.  I also modified a little the code to make it more
explicit that gtk_label_size_request computes a fresh layout for
wrapping labels.

However, I'm actually thinking of disabling completely
height_for_width/width_for_height for non-wrapping labels (right now
it's accepted for elliipsizing labels), as well as disabling
get_natural_size for wrapping labels.  In the meanwhile, this patch
makes things work properly.

Ok?  (I obviously require someone to commit it for me if accepted).

Paolo
2008-09-04  Paolo Bonzini  <bonzini gnu org>

	* gtk/gtklabel.c: Set priv->wrap_width in the extended-layout
	height_for_width code.  Preserve it in get_natural_size
	because when label->wrap is set, gtk_label_size_request will
	invalidate the layout and hence modify priv->wrap_width; for
	the same reason, don't bother setting the layout's width to -1
	if the label is wrapping.  Add priv->wrap_at_container_size
	so that changing the style (e.g.  upon realization) does not
	invalidate the layout.
---
 ChangeLog.gtk-extended-layout |   11 +++++++++
 gtk/gtklabel.c                |   48 ++++++++++++++++++++++++++++++++++------
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 2082d6a..fac4b7f 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -60,7 +60,9 @@ typedef struct
   gint width_chars;
   gint max_width_chars;
   gint baseline_offset;
-  gboolean full_size;
+
+  guint full_size : 1;
+  guint wrap_at_container_size : 1;
 }
 GtkLabelPrivate;
 
@@ -826,6 +828,8 @@ gtk_label_init (GtkLabel *label)
   priv->width_chars = -1;
   priv->max_width_chars = -1;
   priv->wrap_width = -1;
+  priv->wrap_at_container_size = FALSE;
+
   label->label = NULL;
 
   label->jtype = GTK_JUSTIFY_LEFT;
@@ -1987,6 +1991,7 @@ gtk_label_invalidate_wrap_width (GtkLabel *label)
   priv = GTK_LABEL_GET_PRIVATE (label);
 
   priv->wrap_width = -1;
+  priv->wrap_at_container_size = FALSE;
 }
 
 static gint
@@ -2366,6 +2371,7 @@ gtk_label_style_set (GtkWidget *widget,
 		     GtkStyle  *previous_style)
 {
   GtkLabel *label;
+  GtkLabelPrivate *priv;
   
   g_return_if_fail (GTK_IS_LABEL (widget));
   
@@ -2373,7 +2379,10 @@ gtk_label_style_set (GtkWidget *widget,
 
   /* We have to clear the layout, fonts etc. may have changed */
   gtk_label_clear_layout (label);
-  gtk_label_invalidate_wrap_width (label);
+
+  priv = GTK_LABEL_GET_PRIVATE (label);
+  if (!priv->wrap_at_container_size)
+    gtk_label_invalidate_wrap_width (label);
 }
 
 static void 
@@ -4379,19 +4388,26 @@ static gint
 gtk_label_extended_layout_get_size_for_allocation (GtkExtendedLayout *layout,
                                                    gint               size)
 {
-  GtkLabel *label = GTK_LABEL (layout);
-  gdouble angle = gtk_label_get_angle (label);
+  GtkLabel *label;
+  GtkLabelPrivate *priv;
+  gdouble angle;
   PangoLayout *tmp;
 
-  // this test is slightly more tolerant than the get_features test
+  label = GTK_LABEL (layout);
+  priv = GTK_LABEL_GET_PRIVATE (label);
+
+  /* This test is valid for both width_for_height, and height_for_width.  */
+  angle = gtk_label_get_angle (label);
   g_assert (0 == (((gint)angle) % 90));
 
   gtk_label_ensure_layout (label);
   tmp = pango_layout_copy (label->layout);
   pango_layout_set_width (tmp, PANGO_SCALE * size);
+  priv->wrap_width = PANGO_SCALE * size;
+  priv->wrap_at_container_size = TRUE;
+
   pango_layout_get_pixel_size (tmp, NULL, &size);
   g_object_unref (tmp);
-
   return size;
 }
 
@@ -4400,24 +4416,40 @@ gtk_label_extended_layout_get_natural_size (GtkExtendedLayout *layout,
                                             GtkRequisition    *requisition)
 {
   GtkLabel *label;
+  GtkLabelPrivate *priv;
   gboolean ellipsize;
+  gint wrap_width;
   PangoLayout *tmp;
 
   label = GTK_LABEL (layout);
+  priv = GTK_LABEL_GET_PRIVATE (label);
   gtk_label_ensure_layout (label);
 
   ellipsize = label->ellipsize;
   label->ellipsize = PANGO_ELLIPSIZE_NONE;
 
+  wrap_width = priv->wrap_width;
   tmp = label->layout;
-  label->layout = pango_layout_copy (tmp);
 
-  pango_layout_set_width (label->layout, -1);
+  /* See comment in gtk_label_size_request.  */
+
+  if (label->wrap)
+    {
+      g_object_ref (label->layout);
+      gtk_label_clear_layout (label);
+    }
+  else
+    {
+      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;
+  priv->wrap_width = wrap_width;
 }
 
 static gint
-- 
1.5.5



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