mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
[text] Merge the attributes with markup enabled
ClutterText should merge the PangoAttributes set by using clutter_text_set_attributes() with the attributes generated by parsing Pango markup. For this to work we must parse the markup and merge the attributes we get out of pango_parse_markup() with the attributes set by the user. Setting the markup or the attributes on an editable text should not work for the time being.
This commit is contained in:
parent
e8ef5153b1
commit
488de99fc6
@ -221,7 +221,6 @@ offset_to_bytes (const gchar *text,
|
||||
|
||||
#define bytes_to_offset(t,p) (g_utf8_pointer_to_offset ((t), (t) + (p)))
|
||||
|
||||
|
||||
static inline void
|
||||
clutter_text_clear_selection (ClutterText *self)
|
||||
{
|
||||
@ -243,47 +242,42 @@ clutter_text_create_layout_no_cache (ClutterText *text,
|
||||
|
||||
pango_layout_set_font_description (layout, priv->font_desc);
|
||||
|
||||
if (priv->effective_attrs)
|
||||
if (priv->text)
|
||||
{
|
||||
if (G_LIKELY (priv->password_char == 0))
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
g_string_free (str, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (priv->text)
|
||||
{
|
||||
if (priv->use_markup && !priv->editable)
|
||||
pango_layout_set_markup (layout, priv->text, -1);
|
||||
else
|
||||
{
|
||||
if (G_LIKELY (priv->password_char == 0))
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
g_string_free (str, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allocation_width > 0 &&
|
||||
(priv->ellipsize != PANGO_ELLIPSIZE_NONE || priv->wrap))
|
||||
{
|
||||
@ -2114,11 +2108,44 @@ clutter_text_init (ClutterText *self)
|
||||
|
||||
priv->cursor_size = DEFAULT_CURSOR_SIZE;
|
||||
|
||||
priv->font_changed_id
|
||||
= g_signal_connect_swapped (clutter_get_default_backend (),
|
||||
"font-changed",
|
||||
G_CALLBACK (clutter_text_font_changed_cb),
|
||||
self);
|
||||
priv->font_changed_id =
|
||||
g_signal_connect_swapped (clutter_get_default_backend (),
|
||||
"font-changed",
|
||||
G_CALLBACK (clutter_text_font_changed_cb),
|
||||
self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_text_merge_attributes (ClutterText *self)
|
||||
{
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
PangoAttrIterator *iter;
|
||||
GSList *attributes, *l;
|
||||
|
||||
if (!priv->attrs)
|
||||
return;
|
||||
|
||||
if (!priv->effective_attrs)
|
||||
{
|
||||
priv->effective_attrs = pango_attr_list_ref (priv->attrs);
|
||||
return;
|
||||
}
|
||||
|
||||
iter = pango_attr_list_get_iterator (priv->attrs);
|
||||
do
|
||||
{
|
||||
attributes = pango_attr_iterator_get_attrs (iter);
|
||||
|
||||
for (l = attributes; l != NULL; l = l->next)
|
||||
{
|
||||
PangoAttribute *attr = l->data;
|
||||
|
||||
pango_attr_list_insert (priv->effective_attrs, attr);
|
||||
}
|
||||
|
||||
g_slist_free (attributes);
|
||||
}
|
||||
while (pango_attr_iterator_next (iter));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2752,27 +2779,25 @@ clutter_text_get_text (ClutterText *self)
|
||||
return self->priv->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_text_set_text:
|
||||
* @self: a #ClutterText
|
||||
* @text: the text to set
|
||||
*
|
||||
* Sets the contents of a #ClutterText actor. The @text string
|
||||
* must not be %NULL; to unset the current contents of the
|
||||
* #ClutterText actor simply pass "" (an empty string).
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_text_set_text (ClutterText *self,
|
||||
const gchar *text)
|
||||
static inline void
|
||||
clutter_text_set_use_markup_internal (ClutterText *self,
|
||||
gboolean use_markup)
|
||||
{
|
||||
ClutterTextPrivate *priv;
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
||||
g_return_if_fail (text != NULL);
|
||||
if (priv->use_markup != use_markup)
|
||||
{
|
||||
priv->use_markup = use_markup;
|
||||
|
||||
priv = self->priv;
|
||||
g_object_notify (G_OBJECT (self), "use-markup");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_text_set_text_internal (ClutterText *self,
|
||||
const gchar *text)
|
||||
{
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
|
||||
if (priv->max_length > 0)
|
||||
{
|
||||
@ -2808,13 +2833,115 @@ clutter_text_set_text (ClutterText *self,
|
||||
priv->n_chars = g_utf8_strlen (text, -1);
|
||||
}
|
||||
|
||||
g_signal_emit (self, text_signals[TEXT_CHANGED], 0);
|
||||
g_object_notify (G_OBJECT (self), "text");
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_text_set_markup_internal (ClutterText *self,
|
||||
const gchar *str)
|
||||
{
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
GError *error;
|
||||
gchar *text = NULL;
|
||||
PangoAttrList *attrs = NULL;
|
||||
gboolean res;
|
||||
|
||||
error = NULL;
|
||||
res = pango_parse_markup (str, -1, 0,
|
||||
&attrs,
|
||||
&text,
|
||||
NULL,
|
||||
&error);
|
||||
if (!res)
|
||||
{
|
||||
if (G_LIKELY (error))
|
||||
{
|
||||
g_warning ("Failed to set the markup of the actor of class `%s': %s",
|
||||
G_OBJECT_TYPE_NAME (self),
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
g_warning ("Failed to set the markup of the actor of class `%s'",
|
||||
G_OBJECT_TYPE_NAME (self));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (text)
|
||||
{
|
||||
clutter_text_set_text_internal (self, text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
if (attrs)
|
||||
{
|
||||
if (priv->effective_attrs)
|
||||
pango_attr_list_ref (priv->effective_attrs);
|
||||
|
||||
priv->effective_attrs = attrs;
|
||||
}
|
||||
|
||||
clutter_text_merge_attributes (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_text_set_text:
|
||||
* @self: a #ClutterText
|
||||
* @text: the text to set
|
||||
*
|
||||
* Sets the contents of a #ClutterText actor. The @text string
|
||||
* must not be %NULL; to unset the current contents of the
|
||||
* #ClutterText actor simply pass "" (an empty string).
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_text_set_text (ClutterText *self,
|
||||
const gchar *text)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
||||
g_return_if_fail (text != NULL);
|
||||
|
||||
clutter_text_set_use_markup_internal (self, FALSE);
|
||||
clutter_text_set_text_internal (self, text);
|
||||
|
||||
clutter_text_dirty_cache (self);
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
g_signal_emit (self, text_signals[TEXT_CHANGED], 0);
|
||||
/**
|
||||
* clutter_text_set_markup:
|
||||
* @self: a #ClutterText
|
||||
* @markup: a string containing Pango markup
|
||||
*
|
||||
* Sets @markup as the contents of a #ClutterText.
|
||||
*
|
||||
* This is a convenience function for setting a string containing
|
||||
* Pango markup, and it is logically equivalent to:
|
||||
*
|
||||
* |[
|
||||
* clutter_text_set_use_markup (CLUTTER_TEXT (actor), TRUE);
|
||||
* clutter_text_set_text (CLUTTER_TEXT (actor), markup);
|
||||
* ]|
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_text_set_markup (ClutterText *self,
|
||||
const gchar *markup)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
||||
g_return_if_fail (markup != NULL);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "text");
|
||||
clutter_text_set_use_markup_internal (self, TRUE);
|
||||
clutter_text_set_markup_internal (self, markup);
|
||||
|
||||
clutter_text_dirty_cache (self);
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3060,9 +3187,7 @@ clutter_text_get_line_wrap_mode (ClutterText *self)
|
||||
* @attrs: a #PangoAttrList or %NULL to unset the attributes
|
||||
*
|
||||
* Sets the attributes list that are going to be applied to the
|
||||
* #ClutterText contents. The attributes set with this function
|
||||
* will be ignored if the #ClutterText:use_markup property is
|
||||
* set to %TRUE.
|
||||
* #ClutterText contents.
|
||||
*
|
||||
* The #ClutterText actor will take a reference on the #PangoAttrList
|
||||
* passed to this function.
|
||||
@ -3085,6 +3210,8 @@ clutter_text_set_attributes (ClutterText *self,
|
||||
if (priv->attrs)
|
||||
pango_attr_list_unref (priv->attrs);
|
||||
|
||||
priv->attrs = attrs;
|
||||
|
||||
if (!priv->use_markup)
|
||||
{
|
||||
if (attrs)
|
||||
@ -3095,8 +3222,8 @@ clutter_text_set_attributes (ClutterText *self,
|
||||
|
||||
priv->effective_attrs = attrs;
|
||||
}
|
||||
|
||||
priv->attrs = attrs;
|
||||
else
|
||||
clutter_text_set_markup_internal (self, priv->text);
|
||||
|
||||
clutter_text_dirty_cache (self);
|
||||
|
||||
@ -3187,8 +3314,8 @@ clutter_text_get_alignment (ClutterText *self)
|
||||
* Sets whether the contents of the #ClutterText actor contains markup
|
||||
* in <link linkend="PangoMarkupFormat">Pango's text markup language</link>.
|
||||
*
|
||||
* Calling this function on an editable #ClutterText will not cause
|
||||
* the actor to parse any markup.
|
||||
* Setting #ClutterText:use-markup on an editable #ClutterText will
|
||||
* make the actor discard any markup.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
@ -3196,22 +3323,14 @@ void
|
||||
clutter_text_set_use_markup (ClutterText *self,
|
||||
gboolean setting)
|
||||
{
|
||||
ClutterTextPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
||||
|
||||
priv = self->priv;
|
||||
clutter_text_set_use_markup_internal (self, setting);
|
||||
clutter_text_set_markup_internal (self, self->priv->text);
|
||||
|
||||
if (priv->use_markup != setting)
|
||||
{
|
||||
priv->use_markup = setting;
|
||||
clutter_text_dirty_cache (self);
|
||||
|
||||
clutter_text_dirty_cache (self);
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
|
||||
g_object_notify (G_OBJECT (self), "use-markup");
|
||||
}
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,6 +106,8 @@ ClutterActor * clutter_text_new_with_text (const gchar *fon
|
||||
G_CONST_RETURN gchar *clutter_text_get_text (ClutterText *self);
|
||||
void clutter_text_set_text (ClutterText *self,
|
||||
const gchar *text);
|
||||
void clutter_text_set_markup (ClutterText *self,
|
||||
const gchar *markup);
|
||||
PangoLayout * clutter_text_get_layout (ClutterText *self);
|
||||
void clutter_text_set_color (ClutterText *self,
|
||||
const ClutterColor *color);
|
||||
|
Loading…
Reference in New Issue
Block a user