Merge branch 'text-actor-layout-height'
authorEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 15 Apr 2009 17:08:14 +0000 (18:08 +0100)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Wed, 15 Apr 2009 17:08:14 +0000 (18:08 +0100)
* text-actor-layout-height:
  [clutter-text] Fix ellipsizing
  Support pango_layout_set_height() in ClutterText

Conflicts:
clutter/clutter-text.c

1  2 
clutter/clutter-text.c

@@@ -242,82 -256,109 +246,105 @@@ clutter_text_create_layout_no_cache (Cl
    ClutterTextPrivate *priv = text->priv;
    PangoLayout *layout;
  
 -  layout = pango_layout_new (_context);
 -
 +  layout = clutter_actor_create_pango_layout (CLUTTER_ACTOR (text), NULL);
    pango_layout_set_font_description (layout, priv->font_desc);
  
 -  if (priv->effective_attrs)
 -    pango_layout_set_attributes (layout, priv->effective_attrs);
 -
 -  pango_layout_set_alignment (layout, priv->alignment);
 -  pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode);
 -  pango_layout_set_justify (layout, priv->justify);
 -
    if (priv->text)
      {
 -      if (!priv->use_markup)
 +      if (G_LIKELY (priv->password_char == 0))
 +        pango_layout_set_text (layout, priv->text, priv->n_bytes);
 +      else
          {
 -          if (priv->text_visible)
 -            pango_layout_set_text (layout, priv->text, priv->n_bytes);
 -          else
 -            {
 -              GString *str = g_string_sized_new (priv->n_bytes);
 -              gunichar invisible_char;
 -              gchar buf[7];
 -              gint char_len, i;
 +          GString *str = g_string_sized_new (priv->n_bytes);
 +          gunichar invisible_char;
 +          gchar buf[7];
 +          gint char_len, i;
  
 -              if (priv->priv_char != 0)
 -                invisible_char = priv->priv_char;
 -              else
 -                invisible_char = ' ';
 +          invisible_char = priv->password_char;
  
 -              /* we need to convert the string built of invisible
 -               * characters into UTF-8 for it to be fed to the Pango
 -               * layout
 -               */
 -              memset (buf, 0, sizeof (buf));
 -              char_len = g_unichar_to_utf8 (invisible_char, buf);
 +          /* we need to convert the string built of invisible
 +           * characters into UTF-8 for it to be fed to the Pango
 +           * layout
 +           */
 +          memset (buf, 0, sizeof (buf));
 +          char_len = g_unichar_to_utf8 (invisible_char, buf);
  
 -              for (i = 0; i < priv->n_chars; i++)
 -                g_string_append_len (str, buf, char_len);
 +          for (i = 0; i < priv->n_chars; i++)
 +            g_string_append_len (str, buf, char_len);
  
 -              pango_layout_set_text (layout, str->str, str->len);
 +          pango_layout_set_text (layout, str->str, str->len);
  
 -              g_string_free (str, TRUE);
 -            }
 +          g_string_free (str, TRUE);
          }
 -      else
 -        pango_layout_set_markup (layout, priv->text, -1);
      }
  
-   if (allocation_width > 0 &&
-       (priv->ellipsize != PANGO_ELLIPSIZE_NONE || priv->wrap))
 +  if (!priv->editable && priv->effective_attrs)
 +    pango_layout_set_attributes (layout, priv->effective_attrs);
 +
 +  pango_layout_set_alignment (layout, priv->alignment);
 +  pango_layout_set_single_paragraph_mode (layout, priv->single_line_mode);
 +  pango_layout_set_justify (layout, priv->justify);
 +
+   /* Cases, assuming ellipsize != NONE on actor:
+    *
+    * Width request: ellipsization can be set or not on layout,
+    * doesn't matter.
+    *
+    * Height request: ellipsization must never be set on layout
+    * if wrap=true, because we need to measure the wrapped
+    * height. It must always be set if wrap=false.
+    *
+    * Allocate: ellipsization must always be set.
+    *
+    * See http://bugzilla.gnome.org/show_bug.cgi?id=560931
+    */
+   if (priv->ellipsize != PANGO_ELLIPSIZE_NONE)
      {
-       int layout_width, layout_height;
+       if (allocation_height < 0 && priv->wrap)
+         ; /* must not set ellipsization on wrap=true height request */
+       else
 -        pango_layout_set_ellipsize (layout, priv->ellipsize);
++        {
++          if (!priv->editable)
++            pango_layout_set_ellipsize (layout, priv->ellipsize);
++        }
+     }
  
-       pango_layout_get_size (layout, &layout_width, &layout_height);
 -  if (priv->wrap)
 -    pango_layout_set_wrap (layout, priv->wrap_mode);
 -
 -  if (allocation_width > 0)
++  /* we only limit the layout when in multi-line mode since the
++   * single line mode will take care of scrolling to accomodate
++   * the allocation width
++   */
++  if (allocation_width > 0 && !priv->single_line_mode)
+     {
+       gint width;
  
-       /* no need to set ellipsize or wrap if we already have enough
-        * space, since we don't want to make the layout wider than it
-        * would be otherwise.
-        */
+       width = allocation_width > 0
+         ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
+         : -1;
  
-       if (CLUTTER_UNITS_FROM_PANGO_UNIT (layout_width) > allocation_width)
-         {
-           if (!priv->editable && priv->ellipsize != PANGO_ELLIPSIZE_NONE)
-             {
-               gint width;
-               width = allocation_width > 0
-                 ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
-                 : -1;
+       pango_layout_set_width (layout, width);
+     }
  
-               pango_layout_set_ellipsize (layout, priv->ellipsize);
-               pango_layout_set_width (layout, width);
-             }
-           else if (priv->wrap)
-             {
-               gint width;
+   /* Pango only uses height if ellipsization is enabled, so don't set
+    * height if ellipsize isn't set. Pango implicitly enables wrapping
+    * if height is set, so don't set height if wrapping is disabled.
+    * In other words, only set height if we want to both wrap then
 -   * ellipsize.
++   * ellipsize and we're not in single line mode.
+    *
+    * See http://bugzilla.gnome.org/show_bug.cgi?id=560931 if this
+    * seems odd.
+    */
+   if (allocation_height > 0 &&
+       priv->wrap &&
 -      priv->ellipsize != PANGO_ELLIPSIZE_NONE)
++      priv->ellipsize != PANGO_ELLIPSIZE_NONE &&
++      !priv->single_line_mode)
+     {
+       gint height;
  
-               width = allocation_width > 0
-                 ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
-                 : -1;
+       height = allocation_height > 0
+         ? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_height)
+         : -1;
  
-               pango_layout_set_wrap (layout, priv->wrap_mode);
-               pango_layout_set_width (layout, width);
-             }
-         }
+       pango_layout_set_height (layout, height);
      }
  
    return layout;
@@@ -1269,65 -1062,15 +1306,67 @@@ clutter_text_paint (ClutterActor *self
        return;
      }
  
 -  cursor_paint (text);
 -
 -  CLUTTER_NOTE (PAINT, "painting text (text:`%s')", priv->text);
 -
    clutter_actor_get_allocation_box (self, &alloc);
-   layout = clutter_text_create_layout (text, alloc.x2 - alloc.x1);
+   layout = clutter_text_create_layout (text,
+                                        alloc.x2 - alloc.x1,
+                                        alloc.y2 - alloc.y1);
  
 +  if (priv->editable && priv->cursor_visible)
 +    clutter_text_ensure_cursor_position (text);
 +
 +  if (priv->editable && priv->single_line_mode)
 +    {
 +      PangoRectangle logical_rect = { 0, };
 +      gint actor_width, text_width;
 +
 +      pango_layout_get_extents (layout, NULL, &logical_rect);
 +
 +      cogl_clip_push (0, 0,
 +                      CLUTTER_UNITS_TO_FLOAT (alloc.x2 - alloc.x1),
 +                      CLUTTER_UNITS_TO_FLOAT (alloc.y2 - alloc.y1));
 +      clip_set = TRUE;
 +
 +      actor_width = (CLUTTER_UNITS_TO_DEVICE (alloc.x2 - alloc.x1))
 +                  - 2 * TEXT_PADDING;
 +      text_width  = logical_rect.width / PANGO_SCALE;
 +
 +      if (actor_width < text_width)
 +        {
 +          gint cursor_x = priv->cursor_pos.x;
 +
 +          if (priv->position == -1)
 +            {
 +              text_x = actor_width - text_width;
 +              priv->cursor_pos.x += text_x + TEXT_PADDING;
 +            }
 +          else if (priv->position == 0)
 +            {
 +              text_x = 0;
 +            }
 +          else
 +            {
 +              if (text_x <= 0)
 +                {
 +                  gint diff = -1 * text_x;
 +
 +                  if (cursor_x < diff)
 +                    text_x += diff - cursor_x;
 +                  else if (cursor_x > (diff + actor_width))
 +                    text_x -= cursor_x - (diff - actor_width);
 +                }
 +            }
 +        }
 +      else
 +        {
 +          text_x = 0;
 +          priv->cursor_pos.x += text_x + TEXT_PADDING;
 +        }
 +    }
 +  else
 +    text_x = 0;
 +
 +  cursor_paint (text);
 +
    real_opacity = clutter_actor_get_paint_opacity (self)
                 * priv->text_color.alpha
                 / 255;