2007-11-19 Emmanuele Bassi <ebassi@openedhand.com>
authorEmmanuele Bassi <ebassi@openedhand.com>
Mon, 19 Nov 2007 21:14:16 +0000 (21:14 +0000)
committerEmmanuele Bassi <ebassi@openedhand.com>
Mon, 19 Nov 2007 21:14:16 +0000 (21:14 +0000)
* clutter/clutter-label.[ch]: Fix ClutterLabel size allocation when
no bounding box has been provided, and store the box set by the
user so that it can be reused when recomputing the layout. (#600)

(clutter_label_class_init),
(clutter_label_init): Set the :wrap property default to FALSE.

* clutter/clutter-units.h: Add ClutterUnit-to-PangoUnit conversion
macro.

* tests/test-rotate.c: Fix string.

ChangeLog
clutter/clutter-label.c
clutter/clutter-label.h
clutter/clutter-units.h
doc/reference/ChangeLog
doc/reference/clutter-sections.txt
tests/test-rotate.c

index cd57c17..9eba65b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2007-11-19  Emmanuele Bassi  <ebassi@openedhand.com>
 
+       * clutter/clutter-label.[ch]: Fix ClutterLabel size allocation when
+       no bounding box has been provided, and store the box set by the
+       user so that it can be reused when recomputing the layout. (#600)
+
+       (clutter_label_class_init),
+       (clutter_label_init): Set the :wrap property default to FALSE.
+       
+       * clutter/clutter-units.h: Add ClutterUnit-to-PangoUnit conversion
+       macro.
+
+       * tests/test-rotate.c: Fix string.
+
+2007-11-19  Emmanuele Bassi  <ebassi@openedhand.com>
+
        * clutter/clutter-behaviour-bspline.c:
        * clutter/clutter-behaviour-depth.c:
        * clutter/clutter-behaviour-ellipse.c:
index 4d05639..797d772 100644 (file)
@@ -27,7 +27,7 @@
  * SECTION:clutter-label
  * @short_description: Actor for displaying text
  *
- * #ClutterLabel is a #ClutterTexture that displays text.
+ * #ClutterLabel is a #ClutterActor that displays text using Pango.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -66,11 +66,12 @@ enum
   PROP_COLOR,
   PROP_ATTRIBUTES,
   PROP_USE_MARKUP,
-  PROP_ALIGNMENT,              /* FIXME */
+  PROP_ALIGNMENT,
   PROP_WRAP,
   PROP_WRAP_MODE,
+  PROP_JUSTIFY,
   PROP_ELLIPSIZE,
-  PROP_LAYOUT_FLAGS,
+  PROP_LAYOUT_FLAGS
 };
 
 #define CLUTTER_LABEL_GET_PRIVATE(obj) \
@@ -79,11 +80,10 @@ enum
 struct _ClutterLabelPrivate
 {
   PangoContext         *context;
-  PangoFontDescription *desc;
+  PangoFontDescription *font_desc;
   
   ClutterColor          fgcol;
 
-  ClutterLayoutFlags    layout_flags;
   ClutterActorBox       allocation;
   
   gchar                *text;
@@ -99,120 +99,86 @@ struct _ClutterLabelPrivate
   guint                 ellipsize        : 3;
   guint                 single_line_mode : 1;
   guint                 wrap_mode        : 3;
+  guint                 justify          : 1;
 
   PangoAttrList        *attrs;
   PangoAttrList        *effective_attrs;
   PangoLayout          *layout;
   gint                  width_chars;
+  gint                  wrap_width;
 };
 
-
-static void
-clutter_label_set_property (GObject      *object, 
-                           guint         prop_id,
-                           const GValue *value, 
-                           GParamSpec   *pspec)
+static gint
+get_label_char_width (ClutterLabel *label)
 {
-  ClutterLabel        *label;
-  ClutterLabelPrivate *priv;
+  ClutterLabelPrivate *priv = label->priv;
+  PangoContext *context;
+  PangoFontMetrics *metrics;
+  gint char_width, digit_width, char_pixels, w;
+        
+  context = pango_layout_get_context (priv->layout);
+  metrics = pango_context_get_metrics (context, priv->font_desc, 
+                                       pango_context_get_language (context));
+  char_width = pango_font_metrics_get_approximate_char_width (metrics);
+  digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
+  char_pixels = MAX (char_width, digit_width);
+  pango_font_metrics_unref (metrics);
+
+  if (priv->width_chars < 0)
+    {
+      PangoRectangle rect;
 
-  label = CLUTTER_LABEL(object);
-  priv = label->priv;
+      pango_layout_set_width (priv->layout, -1);
+      pango_layout_get_extents (priv->layout, NULL, &rect);
 
-  switch (prop_id) 
+      w = char_pixels * 5;
+      w = MIN (rect.width, w);
+    }
+  else
     {
-    case PROP_FONT_NAME:
-      clutter_label_set_font_name (label, g_value_get_string (value));
-      break;
-    case PROP_TEXT:
-      clutter_label_set_text (label, g_value_get_string (value));
-      break;
-    case PROP_COLOR:
-      clutter_label_set_color (label, g_value_get_boxed (value));
-      break;
-    case PROP_ATTRIBUTES:
-      clutter_label_set_attributes (label, g_value_get_boxed (value));
-      break;
-    case PROP_ALIGNMENT:
-      clutter_label_set_alignment (label, g_value_get_enum (value));
-      break;
-    case PROP_USE_MARKUP:
-      clutter_label_set_use_markup (label, g_value_get_boolean (value));
-      break;
-    case PROP_WRAP:
-      clutter_label_set_line_wrap (label, g_value_get_boolean (value));
-      break;     
-    case PROP_WRAP_MODE:
-      clutter_label_set_line_wrap_mode (label, g_value_get_enum (value));
-      break;     
-    case PROP_ELLIPSIZE:
-      clutter_label_set_ellipsize (label, g_value_get_enum (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
+      /* enforce minimum width for ellipsized labels at ~5 chars */
+      w = char_pixels * MAX (priv->width_chars, 5);
+    }
+
+  return w;
 }
 
-static void
-clutter_label_get_property (GObject    *object, 
-                           guint       prop_id,
-                           GValue     *value, 
-                           GParamSpec *pspec)
+static gint
+get_label_wrap_width (ClutterLabel *label)
 {
-  ClutterLabel        *label;
-  ClutterLabelPrivate *priv;
-  ClutterColor         color;
-
-  label = CLUTTER_LABEL(object);
-  priv = label->priv;
+  ClutterLabelPrivate *priv = label->priv;
 
-  switch (prop_id) 
+  if (priv->wrap_width < 0)
     {
-    case PROP_FONT_NAME:
-      g_value_set_string (value, priv->font_name);
-      break;
-    case PROP_TEXT:
-      g_value_set_string (value, priv->text);
-      break;
-    case PROP_COLOR:
-      clutter_label_get_color (label, &color);
-      g_value_set_boxed (value, &color);
-      break;
-    case PROP_ATTRIBUTES:
-      g_value_set_boxed (value, priv->attrs);
-      break;
-    case PROP_ALIGNMENT:
-      g_value_set_enum (value, priv->alignment);
-      break;
-    case PROP_USE_MARKUP:
-      g_value_set_boolean (value, priv->use_markup);
-      break;
-    case PROP_WRAP:
-      g_value_set_boolean (value, priv->wrap);
-      break;
-    case PROP_WRAP_MODE:
-      g_value_set_enum (value, priv->wrap_mode);
-      break;
-    case PROP_ELLIPSIZE:
-      g_value_set_enum (value, priv->ellipsize);
-      break;
-    case PROP_LAYOUT_FLAGS:
-      g_value_set_flags (value, priv->layout_flags);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    } 
+      if (priv->width_chars > 0)
+        priv->wrap_width = get_label_char_width (label);
+      else
+        {
+          PangoLayout *tmp;
+
+          tmp = pango_layout_new (_context);
+          pango_layout_set_font_description (tmp, priv->font_desc);
+          pango_layout_set_text (tmp, "This is a very long string, which "
+                                      "should be enough for a wrap width.",
+                                 -1);
+          pango_layout_get_size (tmp, &priv->wrap_width, NULL);
+          g_object_unref (tmp);
+        }
+    }
+
+  return priv->wrap_width;
 }
 
 static void
-clutter_label_ensure_layout (ClutterLabel *label,
-                             gint          width)
+clutter_label_ensure_layout (ClutterLabel *label)
 {
-  ClutterLabelPrivate  *priv;
+  ClutterLabelPrivate *priv;
+  gint width;
 
-  priv   = label->priv;
+  priv  = label->priv;
+
+  /* use the last size requested, if any */
+  width = CLUTTER_UNITS_TO_INT (priv->allocation.x2 - priv->allocation.x1);
 
   if (!priv->layout)
     {
@@ -226,7 +192,8 @@ clutter_label_ensure_layout (ClutterLabel *label,
       pango_layout_set_single_paragraph_mode (priv->layout, 
                                              priv->single_line_mode);
       
-      pango_layout_set_font_description (priv->layout, priv->desc);
+      pango_layout_set_font_description (priv->layout, priv->font_desc);
+      pango_layout_set_justify (priv->layout, priv->justify);
      
       if (priv->text)
         { 
@@ -236,16 +203,79 @@ clutter_label_ensure_layout (ClutterLabel *label,
             pango_layout_set_markup (priv->layout, priv->text, -1);
         }
       
-      if (priv->wrap)
-       pango_layout_set_wrap  (priv->layout, priv->wrap_mode);
+      if (priv->ellipsize)
+        pango_layout_set_width (priv->layout, width > 0 ? width * PANGO_SCALE
+                                                        : -1);
+      else if (priv->wrap)
+        {
+          pango_layout_set_wrap  (priv->layout, priv->wrap_mode);
 
-      if ((priv->ellipsize || priv->wrap) && width > 0)
-       {
-         pango_layout_set_width (priv->layout, width * PANGO_SCALE);
+          if (width > 0)
+           pango_layout_set_width (priv->layout, width * PANGO_SCALE);
+          else
+            {
+              /* this was adapted from the GtkLabel code */
+              ClutterActor *stage = clutter_stage_get_default ();
+              gint stage_width = clutter_actor_get_width (stage);
+              gint longest_paragraph, height, wrap_width;
+              PangoRectangle logical_rect;
+
+              pango_layout_set_width (priv->layout, -1);
+              pango_layout_get_extents (priv->layout, NULL, &logical_rect);
+
+              width = logical_rect.width;
+
+              longest_paragraph = width;
+
+              wrap_width = get_label_wrap_width (label);
+              width = MAX (width, wrap_width);
+              width = MIN (width, PANGO_SCALE * (stage_width + 1) / 2);
+
+              pango_layout_set_width (priv->layout, width);
+              pango_layout_get_extents (priv->layout, NULL, &logical_rect);
+              width = logical_rect.width;
+              height = logical_rect.height;
+
+              if (longest_paragraph > 0)
+                {
+                  gint n_lines, perfect_width;
+
+                  n_lines = pango_layout_get_line_count (priv->layout);
+                  perfect_width = (longest_paragraph + n_lines - 1) / n_lines;
+
+                  if (perfect_width < width)
+                    {
+                      pango_layout_set_width (priv->layout, perfect_width);
+                      pango_layout_get_extents (priv->layout, NULL,
+                                                &logical_rect);
+
+                      if (logical_rect.height <= height)
+                        width = logical_rect.width = width;
+                      else
+                        {
+                          gint mid_width = (perfect_width + width) / 2;
+
+                          if (mid_width > perfect_width)
+                            {
+                              pango_layout_set_width (priv->layout, mid_width);
+                              pango_layout_get_extents (priv->layout, NULL,
+                                                        &logical_rect);
+
+                              if (logical_rect.height <= height);
+                                width = logical_rect.width;
+                            }
+                        }
+                    }
+                }
+
+              pango_layout_set_width (priv->layout, width);
+            }
        }
       else
        pango_layout_set_width (priv->layout, -1);
     }
+
+  CLUTTER_NOTE (ACTOR, "Label width set to %d pixels", width);
 }
 
 static void
@@ -258,45 +288,44 @@ clutter_label_clear_layout (ClutterLabel *label)
     }
 }
 
-void
+static void
 clutter_label_paint (ClutterActor *self)
 {
-  ClutterLabel         *label;
-  ClutterLabelPrivate  *priv;
+  ClutterLabel        *label = CLUTTER_LABEL (self);
+  ClutterLabelPrivate *priv = label->priv;
 
-  label  = CLUTTER_LABEL(self);
-  priv   = label->priv;
-  
-  if (priv->desc == NULL || priv->text == NULL)
+  if (priv->font_desc == NULL || priv->text == NULL)
     {
-      CLUTTER_NOTE (ACTOR, "layout: %p , desc: %p, text %p",
+      CLUTTER_NOTE (ACTOR, "layout: %p, desc: %p, text %p",
                    priv->layout,
-                   priv->desc,
-                   priv->text);
+                   priv->font_desc ? priv->font_desc : 0x0,
+                   priv->text ? priv->text : 0x0);
       return;
     }
 
-  CLUTTER_NOTE (PAINT, "painting label (text:`%s')",
-                priv->text);
+  CLUTTER_NOTE (PAINT, "painting label (text:`%s')", priv->text);
 
-  clutter_label_ensure_layout (label, clutter_actor_get_width (self));
+  clutter_label_ensure_layout (label);
 
-  priv->fgcol.alpha = clutter_actor_get_opacity(self);
+  priv->fgcol.alpha = clutter_actor_get_opacity (self);
 
   pango_clutter_render_layout (priv->layout, 0, 0, &priv->fgcol, 0);
 }
 
 static void
-clutter_label_query_coords (ClutterActor        *self,
-                           ClutterActorBox     *box)
+clutter_label_query_coords (ClutterActor    *self,
+                           ClutterActorBox *box)
 {
-  ClutterLabel         *label = CLUTTER_LABEL(self);
-  ClutterLabelPrivate  *priv;  
-  PangoRectangle        logical_rect;
+  ClutterLabel *label = CLUTTER_LABEL(self);
+  ClutterLabelPrivate *priv;  
+  PangoRectangle logical_rect;
 
   priv = label->priv;
 
-  clutter_label_ensure_layout (label, CLUTTER_UNITS_TO_INT (box->x2 - box->x1));
+  if (priv->wrap)
+    clutter_label_clear_layout (label);
+
+  clutter_label_ensure_layout (label);
 
   pango_layout_get_extents (priv->layout, NULL, &logical_rect);
 
@@ -307,8 +336,8 @@ clutter_label_query_coords (ClutterActor        *self,
 }
 
 static void
-clutter_label_request_coords (ClutterActor        *self,
-                             ClutterActorBox     *box)
+clutter_label_request_coords (ClutterActor    *self,
+                             ClutterActorBox *box)
 {
   ClutterLabel *label = CLUTTER_LABEL (self);
   ClutterLabelPrivate *priv = label->priv;
@@ -331,6 +360,8 @@ clutter_label_request_coords (ClutterActor        *self,
     }
   else
     clutter_label_clear_layout (label);
+
+  priv->allocation = *box;
 }
 
 static void 
@@ -340,7 +371,7 @@ clutter_label_dispose (GObject *object)
   ClutterLabelPrivate  *priv;  
 
   priv = self->priv;
-  
+
   if (priv->layout)
     {
       g_object_unref (priv->layout);
@@ -364,8 +395,8 @@ clutter_label_finalize (GObject *object)
 
   priv = self->priv;
   
-  if (priv->desc)
-    pango_font_description_free (priv->desc);    
+  if (priv->font_desc)
+    pango_font_description_free (priv->font_desc);
 
   g_free (priv->text);
   g_free (priv->font_name);
@@ -374,31 +405,205 @@ clutter_label_finalize (GObject *object)
 }
 
 static ClutterLayoutFlags
-clutter_layout_label_get_layout_flags (ClutterLayout *layout)
+clutter_label_get_layout_flags (ClutterLayout *layout)
 {
-  return CLUTTER_LABEL (layout)->priv->layout_flags;
+  ClutterLayoutFlags flags;
+  ClutterFixed angle;
+
+  flags = CLUTTER_LAYOUT_NATURAL;
+
+  angle = clutter_actor_get_rotationx (CLUTTER_ACTOR (layout),
+                                       CLUTTER_Z_AXIS,
+                                       NULL, NULL, NULL);
+
+  if (angle == 0 || angle == CLUTTER_INT_TO_FIXED (180))
+    flags |= CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH;
+  else if (angle == CLUTTER_INT_TO_FIXED (90) || angle == CLUTTER_INT_TO_FIXED (270))
+    flags |= CLUTTER_LAYOUT_WIDTH_FOR_HEIGHT;
+
+  return flags;
+}
+
+static void
+clutter_label_width_for_height (ClutterLayout *layout,
+                                ClutterUnit   *width,
+                                ClutterUnit    height)
+{
+  ClutterLabel *label = CLUTTER_LABEL (layout);
+  PangoLayout *tmp;
+  gint layout_height;
+
+  clutter_label_ensure_layout (label);
+
+  tmp = pango_layout_copy (label->priv->layout);
+  pango_layout_set_width (tmp, CLUTTER_UNITS_TO_PANGO_UNIT (height));
+  pango_layout_get_pixel_size (tmp, NULL, &layout_height);
+
+  if (width)
+    *width = CLUTTER_UNITS_FROM_INT (layout_height);
+
+  g_object_unref (tmp);
 }
 
 static void
-clutter_layout_label_height_for_width (ClutterLayout *layout,
-                                       ClutterUnit    width,
-                                       ClutterUnit   *height)
+clutter_label_height_for_width (ClutterLayout *layout,
+                                ClutterUnit    width,
+                                ClutterUnit   *height)
 {
   ClutterLabel *label = CLUTTER_LABEL (layout);
+  PangoLayout *tmp;
   gint layout_height;
 
-  clutter_label_ensure_layout (label, CLUTTER_UNITS_TO_INT (width));
-  pango_layout_get_pixel_size (label->priv->layout, NULL, &layout_height);
+  clutter_label_ensure_layout (label);
+
+  tmp = pango_layout_copy (label->priv->layout);
+  pango_layout_set_width (tmp, CLUTTER_UNITS_TO_PANGO_UNIT (width));
+  pango_layout_get_pixel_size (tmp, NULL, &layout_height);
 
   if (height)
     *height = CLUTTER_UNITS_FROM_INT (layout_height);
+
+  g_object_unref (tmp);
+}
+
+static void
+clutter_label_natural_request (ClutterLayout *layout,
+                               ClutterUnit   *width,
+                               ClutterUnit   *height)
+{
+  ClutterLabel *label = CLUTTER_LABEL (layout);
+  PangoLayout *tmp;
+  PangoRectangle logical_rect = { 0, };
+
+  clutter_label_ensure_layout (label);
+
+  tmp = pango_layout_copy (label->priv->layout);
+  pango_layout_set_width (tmp, -1);
+  pango_layout_set_ellipsize (tmp, PANGO_ELLIPSIZE_NONE);
+
+  pango_layout_get_extents (tmp, NULL, &logical_rect);
+
+  if (width)
+    *width = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_rect.width);
+  if (height)
+    *height = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_rect.height);
+
+  g_object_unref (tmp);
 }
 
 static void
 clutter_layout_iface_init (ClutterLayoutIface *iface)
 {
-  iface->get_layout_flags = clutter_layout_label_get_layout_flags;
-  iface->height_for_width = clutter_layout_label_height_for_width;
+  iface->get_layout_flags = clutter_label_get_layout_flags;
+  iface->height_for_width = clutter_label_height_for_width;
+  iface->width_for_height = clutter_label_width_for_height;
+  iface->natural_request  = clutter_label_natural_request;
+}
+
+static void
+clutter_label_set_property (GObject      *object, 
+                           guint         prop_id,
+                           const GValue *value, 
+                           GParamSpec   *pspec)
+{
+  ClutterLabel        *label;
+  ClutterLabelPrivate *priv;
+
+  label = CLUTTER_LABEL(object);
+  priv = label->priv;
+
+  switch (prop_id) 
+    {
+    case PROP_FONT_NAME:
+      clutter_label_set_font_name (label, g_value_get_string (value));
+      break;
+    case PROP_TEXT:
+      clutter_label_set_text (label, g_value_get_string (value));
+      break;
+    case PROP_COLOR:
+      clutter_label_set_color (label, g_value_get_boxed (value));
+      break;
+    case PROP_ATTRIBUTES:
+      clutter_label_set_attributes (label, g_value_get_boxed (value));
+      break;
+    case PROP_ALIGNMENT:
+      clutter_label_set_alignment (label, g_value_get_enum (value));
+      break;
+    case PROP_USE_MARKUP:
+      clutter_label_set_use_markup (label, g_value_get_boolean (value));
+      break;
+    case PROP_WRAP:
+      clutter_label_set_line_wrap (label, g_value_get_boolean (value));
+      break;
+    case PROP_JUSTIFY:
+      clutter_label_set_justify (label, g_value_get_boolean (value));
+      break;
+    case PROP_WRAP_MODE:
+      clutter_label_set_line_wrap_mode (label, g_value_get_enum (value));
+      break;     
+    case PROP_ELLIPSIZE:
+      clutter_label_set_ellipsize (label, g_value_get_enum (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+clutter_label_get_property (GObject    *object, 
+                           guint       prop_id,
+                           GValue     *value, 
+                           GParamSpec *pspec)
+{
+  ClutterLabel        *label;
+  ClutterLabelPrivate *priv;
+  ClutterColor         color;
+
+  label = CLUTTER_LABEL (object);
+  priv = label->priv;
+
+  switch (prop_id) 
+    {
+    case PROP_FONT_NAME:
+      g_value_set_string (value, priv->font_name);
+      break;
+    case PROP_TEXT:
+      g_value_set_string (value, priv->text);
+      break;
+    case PROP_COLOR:
+      clutter_label_get_color (label, &color);
+      g_value_set_boxed (value, &color);
+      break;
+    case PROP_ATTRIBUTES:
+      g_value_set_boxed (value, priv->attrs);
+      break;
+    case PROP_ALIGNMENT:
+      g_value_set_enum (value, priv->alignment);
+      break;
+    case PROP_USE_MARKUP:
+      g_value_set_boolean (value, priv->use_markup);
+      break;
+    case PROP_JUSTIFY:
+      g_value_set_boolean (value, priv->justify);
+      break;
+    case PROP_WRAP:
+      g_value_set_boolean (value, priv->wrap);
+      break;
+    case PROP_WRAP_MODE:
+      g_value_set_enum (value, priv->wrap_mode);
+      break;
+    case PROP_ELLIPSIZE:
+      g_value_set_enum (value, priv->ellipsize);
+      break;
+    case PROP_LAYOUT_FLAGS:
+      g_value_set_flags (value,
+                         clutter_label_get_layout_flags (CLUTTER_LAYOUT (label)));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    } 
 }
 
 static void
@@ -423,7 +628,6 @@ clutter_label_class_init (ClutterLabelClass *klass)
                          "Pango font description",
                          NULL,
                          G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property
     (gobject_class, PROP_TEXT,
      g_param_spec_string ("text",
@@ -431,7 +635,6 @@ clutter_label_class_init (ClutterLabelClass *klass)
                          "Text to render",
                          NULL,
                          G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property
     (gobject_class, PROP_COLOR,
      g_param_spec_boxed ("color",
@@ -439,7 +642,6 @@ clutter_label_class_init (ClutterLabelClass *klass)
                         "Font Colour",
                         CLUTTER_TYPE_COLOR,
                         CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property 
     (gobject_class, PROP_ATTRIBUTES,
      g_param_spec_boxed ("attributes",
@@ -448,7 +650,6 @@ clutter_label_class_init (ClutterLabelClass *klass)
                         "text of the label",
                         PANGO_TYPE_ATTR_LIST,
                         CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property 
     (gobject_class, PROP_USE_MARKUP,
      g_param_spec_boolean ("use-markup",
@@ -457,15 +658,13 @@ clutter_label_class_init (ClutterLabelClass *klass)
                           "See pango_parse_markup()",
                           FALSE,
                           CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property 
     (gobject_class, PROP_WRAP,
      g_param_spec_boolean ("wrap",
                           "Line wrap",
                           "If set, wrap lines if the text becomes too wide",
-                          TRUE,
+                          FALSE,
                           CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property 
     (gobject_class, PROP_WRAP_MODE,
      g_param_spec_enum ("wrap-mode",
@@ -474,7 +673,6 @@ clutter_label_class_init (ClutterLabelClass *klass)
                        PANGO_TYPE_WRAP_MODE,
                        PANGO_WRAP_WORD,
                        CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property 
     (gobject_class, PROP_ELLIPSIZE,
      g_param_spec_enum ( "ellipsize",
@@ -485,15 +683,29 @@ clutter_label_class_init (ClutterLabelClass *klass)
                         PANGO_TYPE_ELLIPSIZE_MODE,
                         PANGO_ELLIPSIZE_NONE,
                         CLUTTER_PARAM_READWRITE));
-
   g_object_class_install_property 
     (gobject_class, PROP_ALIGNMENT,
      g_param_spec_enum ( "alignment",
                         "Alignment",
-                        "The preferred alignment for the string,",
+                        "The preferred alignment for the string",
                         PANGO_TYPE_ALIGNMENT,
                         PANGO_ALIGN_LEFT,
                         CLUTTER_PARAM_READWRITE));
+  /**
+   * ClutterLabel:justify:
+   *
+   * Whether the contents of the label should be justified on both
+   * margins.
+   *
+   * Since: 0.6
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_JUSTIFY,
+                                   g_param_spec_boolean ("justify",
+                                                         "Justify",
+                                                         "Whether the contents of the label should be justified",
+                                                         FALSE,
+                                                         CLUTTER_PARAM_READWRITE));
 
   g_object_class_override_property (gobject_class,
                                     PROP_LAYOUT_FLAGS,
@@ -525,15 +737,19 @@ clutter_label_init (ClutterLabel *self)
     }
 
   priv->alignment     = PANGO_ALIGN_LEFT;
-  priv->wrap          = TRUE;
+  priv->wrap          = FALSE;
   priv->wrap_mode     = PANGO_WRAP_WORD;
   priv->ellipsize     = PANGO_ELLIPSIZE_NONE;
   priv->use_underline = FALSE;
   priv->use_markup    = FALSE;
+  priv->justify       = FALSE;
+
   priv->layout        = NULL;
   priv->text          = NULL;
   priv->attrs         = NULL;
-  priv->layout_flags  = CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH;
+
+  priv->width_chars   = -1;
+  priv->wrap_width    = -1;
 
   priv->fgcol.red     = 0;
   priv->fgcol.green   = 0;
@@ -541,7 +757,7 @@ clutter_label_init (ClutterLabel *self)
   priv->fgcol.alpha   = 255;
 
   priv->font_name     = g_strdup (DEFAULT_FONT_NAME);
-  priv->desc          = pango_font_description_from_string (priv->font_name);
+  priv->font_desc     = pango_font_description_from_string (priv->font_name);
 
   CLUTTER_MARK();
 }
@@ -559,16 +775,10 @@ ClutterActor*
 clutter_label_new_with_text (const gchar *font_name,
                             const gchar *text)
 {
-  ClutterActor *label;
-
-  CLUTTER_MARK();
-
-  label = clutter_label_new ();
-
-  clutter_label_set_font_name (CLUTTER_LABEL(label), font_name);
-  clutter_label_set_text (CLUTTER_LABEL(label), text);
-
-  return label;
+  return g_object_new (CLUTTER_TYPE_LABEL,
+                       "font-name", font_name,
+                       "text", text,
+                       NULL);
 }
 
 /**
@@ -587,13 +797,10 @@ clutter_label_new_full (const gchar        *font_name,
                        const gchar        *text,
                        const ClutterColor *color)
 {
-  /* FIXME: really new_with_text should take color argument... */
-  ClutterActor *label;
-
-  label = clutter_label_new_with_text (font_name, text);
-  clutter_label_set_color (CLUTTER_LABEL(label), color);
-
-  return label;
+  return g_object_new (CLUTTER_TYPE_LABEL,
+                       "font-name", font_name,
+                       "text", text,
+                       "color", color);
 }
 
 /**
@@ -718,17 +925,18 @@ clutter_label_set_font_name (ClutterLabel *label,
   g_free (priv->font_name);
   priv->font_name = g_strdup (font_name);
   
-  if (priv->desc)
-    pango_font_description_free (priv->desc);
+  if (priv->font_desc)
+    pango_font_description_free (priv->font_desc);
 
-  priv->desc = desc;
+  priv->font_desc = desc;
+  priv->wrap_width = -1;
 
   if (label->priv->text && label->priv->text[0] != '\0')
     {
       clutter_label_clear_layout (label);      
 
-      if (CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR(label)))
-       clutter_actor_queue_redraw (CLUTTER_ACTOR(label));
+      if (CLUTTER_ACTOR_IS_VISIBLE (label))
+       clutter_actor_queue_redraw (CLUTTER_ACTOR (label));
     }
   
   g_object_notify (G_OBJECT (label), "font-name");
@@ -988,7 +1196,7 @@ clutter_label_get_layout (ClutterLabel *label)
 {
   g_return_val_if_fail (CLUTTER_IS_LABEL (label), NULL);
 
-  clutter_label_ensure_layout (label, -1);
+  clutter_label_ensure_layout (label);
 
   return label->priv->layout;
 }
@@ -1170,3 +1378,54 @@ clutter_label_get_alignment (ClutterLabel *label)
   return label->priv->alignment;
 }
 
+/**
+ * clutter_label_set_justify:
+ * @label: a #ClutterLabel
+ * @justify: whether the text should be justified
+ *
+ * Sets whether the text of the @label actor should be justified
+ * on both margins. This setting is ignored if Clutter is compiled
+ * against Pango &gt; 1.18.
+ *
+ * Since: 0.6
+ */
+void
+clutter_label_set_justify (ClutterLabel *label,
+                           gboolean      justify)
+{
+  ClutterLabelPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_LABEL (label));
+
+  priv = label->priv;
+
+  if (priv->justify != justify)
+    {
+      priv->justify = justify;
+
+      clutter_label_clear_layout (label);
+
+      if (CLUTTER_ACTOR_IS_VISIBLE (label))
+       clutter_actor_queue_redraw (CLUTTER_ACTOR (label));
+
+      g_object_notify (G_OBJECT (label), "justify");
+    }
+}
+
+/**
+ * clutter_label_get_justify:
+ * @label: a #ClutterLabel
+ *
+ * Retrieves whether the label should justify the text on both margins.
+ *
+ * Return value: %TRUE if the text should be justified
+ *
+ * Since: 0.6
+ */
+gboolean
+clutter_label_get_justify (ClutterLabel *label)
+{
+  g_return_val_if_fail (CLUTTER_IS_LABEL (label), FALSE);
+
+  return label->priv->justify;
+}
index c7b86fc..d8352c1 100644 (file)
@@ -117,6 +117,9 @@ gboolean              clutter_label_get_use_markup     (ClutterLabel       *labe
 void                  clutter_label_set_alignment      (ClutterLabel       *label,
                                                         PangoAlignment      alignment);
 PangoAlignment        clutter_label_get_alignment      (ClutterLabel       *label);
+void                  clutter_label_set_justify        (ClutterLabel       *label,
+                                                        gboolean            justify);
+gboolean              clutter_label_get_justify        (ClutterLabel       *label);
 
 G_END_DECLS
 
index 6796600..845afdc 100644 (file)
@@ -81,7 +81,8 @@ typedef gint32 ClutterUnit;
 #define CLUTTER_UNITS_FROM_FIXED(x)      (x)
 #define CLUTTER_UNITS_TO_FIXED(x)        (x)
 
-#define CLUTTER_UNITS_FROM_PANGO_UNIT(x) (x << 6)
+#define CLUTTER_UNITS_FROM_PANGO_UNIT(x) ((x) << 6)
+#define CLUTTER_UNITS_TO_PANGO_UNIT(x)   ((x) >> 6)
 
 G_END_DECLS
 
index ef80767..785ac62 100644 (file)
@@ -1,5 +1,10 @@
 2007-11-19  Emmanuele Bassi  <ebassi@openedhand.com>
 
+       * clutter-sections.txt: Add ClutterScore symbols and
+       ClutterLabel:justify accessors.
+
+2007-11-19  Emmanuele Bassi  <ebassi@openedhand.com>
+
        * clutter-sections.txt: Remove clutter_behaviour_bspline_append() and
        add the new motion events settings API.
 
index 5b77cde..0c87d11 100644 (file)
@@ -29,16 +29,17 @@ clutter_media_get_type
 <TITLE>Unit conversion</TITLE>
 ClutterUnit
 CLUTTER_UNITS_FROM_DEVICE
+CLUTTER_UNITS_TO_DEVICE
 CLUTTER_UNITS_FROM_FIXED
+CLUTTER_UNITS_TO_FIXED
 CLUTTER_UNITS_FROM_FLOAT
+CLUTTER_UNITS_TO_FLOAT
 CLUTTER_UNITS_FROM_INT
+CLUTTER_UNITS_TO_INT
 CLUTTER_UNITS_FROM_PANGO_UNIT
+CLUTTER_UNITS_TO_PANGO_UNIT
 CLUTTER_UNITS_TMP_FROM_DEVICE
 CLUTTER_UNITS_TMP_TO_DEVICE
-CLUTTER_UNITS_TO_DEVICE
-CLUTTER_UNITS_TO_FIXED
-CLUTTER_UNITS_TO_FLOAT
-CLUTTER_UNITS_TO_INT
 </SECTION>
 
 <SECTION>
@@ -68,6 +69,9 @@ clutter_label_set_use_markup
 clutter_label_get_use_markup
 clutter_label_set_alignment
 clutter_label_get_alignment
+clutter_label_get_justify
+clutter_label_set_justify
+
 <SUBSECTION Standard>
 CLUTTER_LABEL
 CLUTTER_IS_LABEL
@@ -238,6 +242,11 @@ clutter_container_get_type
 ClutterLayout
 ClutterLayoutIface
 ClutterLayoutFlags
+CLUTTER_LAYOUT_HAS
+CLUTTER_LAYOUT_HAS_HEIGHT_FOR_WIDTH
+CLUTTER_LAYOUT_HAS_NATURAL_SIZE
+CLUTTER_LAYOUT_HAS_TUNABLE_SIZE
+CLUTTER_LAYOUT_HAS_WIDTH_FOR_HEIGHT
 clutter_layout_get_layout_flags
 clutter_layout_height_for_width
 clutter_layout_natural_request
@@ -307,6 +316,8 @@ clutter_actor_destroy
 clutter_actor_request_coords
 clutter_actor_query_coords
 clutter_actor_event
+clutter_actor_pick
+clutter_actor_should_pick_paint
 
 <SUBSECTION>
 clutter_actor_set_geometry
@@ -1243,3 +1254,36 @@ CLUTTER_MODEL_ITER_GET_CLASS
 ClutterModelIterPrivate
 clutter_model_iter_get_type
 </SECTION>
+
+<SECTION>
+<FILE>clutter-score</FILE>
+<TITLE>ClutterScore</TITLE>
+ClutterScore
+ClutterScoreClass
+clutter_score_new
+clutter_score_add
+clutter_score_append
+clutter_score_remove
+clutter_score_remove_all
+clutter_score_set_loop
+clutter_score_get_loop
+
+<SUBSECTION>
+clutter_score_start
+clutter_score_pause
+clutter_score_stop
+clutter_score_is_playing
+clutter_score_rewind
+
+<SUBSECTION Standard>
+CLUTTER_IS_SCORE
+CLUTTER_IS_SCORE_CLASS
+CLUTTER_SCORE
+CLUTTER_SCORE_CLASS
+CLUTTER_SCORE_GET_CLASS
+CLUTTER_TYPE_SCORE
+
+<SUBSECTION Private>
+ClutterScorePrivate
+clutter_score_get_type
+</SECTION>
index d30d918..39336de 100644 (file)
@@ -35,9 +35,7 @@ main (int argc, char *argv[])
   clutter_actor_show (hand);
   clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand);
 
-  label = clutter_label_new_with_text ("Mono 16",
-                                      "The Wonder of the Spinning Hand\n\n  ");
-  
+  label = clutter_label_new_with_text ("Mono 16", "The Wonder of the Spinning Hand");
   clutter_actor_set_position (label, 150, 150);
   clutter_actor_show (label);
   clutter_container_add_actor (CLUTTER_CONTAINER (stage), label);