From 3958df4ff9b3aa800df2e0f1695fd143439d870a Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 6 Nov 2009 16:49:55 +0000 Subject: [PATCH 1/9] Add ClutterTextDirection enumeration The ClutterTextDirection is composed of three values: DEFAULT: a flag for returning the default text direction LTR: left to right RTL: right to left --- clutter/clutter-types.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h index 13f120307..ec7502310 100644 --- a/clutter/clutter-types.h +++ b/clutter/clutter-types.h @@ -382,6 +382,23 @@ typedef enum CLUTTER_FONT_HINTING = (1 << 1), } ClutterFontFlags; +/** + * ClutterTextDirection: + * @CLUTTER_TEXT_DIRECTION_DEFAULT: Use the default setting, as returned + * by clutter_get_default_text_direction() + * @CLUTTER_TEXT_DIRECTION_LTR: Use left-to-right text direction + * @CLUTTER_TEXT_DIRECTION_RTL: Use right-to-left text direction + * + * The text direction to be used by #ClutterActors + * + * Since: 1.2 + */ +typedef enum { + CLUTTER_TEXT_DIRECTION_DEFAULT, + CLUTTER_TEXT_DIRECTION_LTR, + CLUTTER_TEXT_DIRECTION_RTL +} ClutterTextDirection; + G_END_DECLS #endif /* __CLUTTER_TYPES_H__ */ From 53a9d0c637ee1ef07e9251b77f86f0cd42ab611e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 6 Nov 2009 16:50:53 +0000 Subject: [PATCH 2/9] Use the newly added ClutterTextDirection enumeration Instead of using PangoDirection directly we should use the ClutterTextDirection enumeration. We also need a pair of accessor functions for setting and getting the default text direction. --- clutter/clutter-main.c | 43 ++++++++++++++++++++++++++++++++---------- clutter/clutter-main.h | 3 +++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index d0b6b0420..4d7cc10b7 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -74,7 +74,7 @@ static gboolean clutter_use_fuzzy_picking = FALSE; static guint clutter_default_fps = 60; -static PangoDirection clutter_text_direction = PANGO_DIRECTION_LTR; +static PangoDirection clutter_text_direction = CLUTTER_TEXT_DIRECTION_LTR; static guint clutter_main_loop_level = 0; static GSList *main_loops = NULL; @@ -540,7 +540,7 @@ _clutter_do_pick (ClutterStage *stage, return clutter_get_actor_by_gid (id); } -static PangoDirection +static ClutterTextDirection clutter_get_text_direction (void) { PangoDirection dir = PANGO_DIRECTION_LTR; @@ -550,9 +550,9 @@ clutter_get_text_direction (void) if (direction && *direction != '\0') { if (strcmp (direction, "rtl") == 0) - dir = PANGO_DIRECTION_RTL; + dir = CLUTTER_TEXT_DIRECTION_RTL; else if (strcmp (direction, "ltr") == 0) - dir = PANGO_DIRECTION_LTR; + dir = CLUTTER_TEXT_DIRECTION_LTR; } else { @@ -565,9 +565,9 @@ clutter_get_text_direction (void) char *e = _("default:LTR"); if (strcmp (e, "default:RTL") == 0) - dir = PANGO_DIRECTION_RTL; + dir = CLUTTER_TEXT_DIRECTION_RTL; else if (strcmp (e, "default:LTR") == 0) - dir = PANGO_DIRECTION_LTR; + dir = CLUTTER_TEXT_DIRECTION_LTR; else g_warning ("Whoever translated default:LTR did so wrongly."); } @@ -582,10 +582,16 @@ update_pango_context (ClutterBackend *backend, PangoFontDescription *font_desc; const cairo_font_options_t *font_options; const gchar *font_name; + PangoDirection pango_dir; gdouble resolution; /* update the text direction */ - pango_context_set_base_dir (context, clutter_text_direction); + if (clutter_text_direction == CLUTTER_TEXT_DIRECTION_RTL) + pango_dir = PANGO_DIRECTION_RTL; + else + pango_dir = PANGO_DIRECTION_LTR; + + pango_context_set_base_dir (context, pango_dir); /* get the configuration for the PangoContext from the backend */ font_name = clutter_backend_get_font_name (backend); @@ -1236,8 +1242,8 @@ clutter_arg_direction_cb (const char *key, gpointer user_data) { clutter_text_direction = - (strcmp (value, "rtl") == 0) ? PANGO_DIRECTION_RTL - : PANGO_DIRECTION_LTR; + (strcmp (value, "rtl") == 0) ? CLUTTER_TEXT_DIRECTION_RTL + : CLUTTER_TEXT_DIRECTION_LTR; return TRUE; } @@ -1356,7 +1362,6 @@ clutter_init_real (GError **error) clutter_text_direction = clutter_get_text_direction (); - /* Figure out framebuffer masks used for pick */ cogl_get_bitmasks (&ctx->fb_r_mask, &ctx->fb_g_mask, &ctx->fb_b_mask, NULL); @@ -3027,3 +3032,21 @@ clutter_check_version (guint major, clutter_minor_version == minor && clutter_micro_version >= micro)); } + +void +clutter_set_default_text_direction (ClutterTextDirection text_dir) +{ + if (text_dir == CLUTTER_TEXT_DIRECTION_DEFAULT) + text_dir = clutter_get_text_direction (); + + if (text_dir != clutter_text_direction) + clutter_text_direction = text_dir; + + /* FIXME - queue a relayout on all stages */ +} + +ClutterTextDirection +clutter_get_default_text_direction (void) +{ + return clutter_text_direction; +} diff --git a/clutter/clutter-main.h b/clutter/clutter-main.h index d36f8f16f..c5f456219 100644 --- a/clutter/clutter-main.h +++ b/clutter/clutter-main.h @@ -164,6 +164,9 @@ void clutter_ungrab_pointer_for_device (gint id); PangoFontMap * clutter_get_font_map (void); +void clutter_set_default_text_direction (ClutterTextDirection text_dir); +ClutterTextDirection clutter_get_default_text_direction (void); + G_END_DECLS #endif /* _CLUTTER_MAIN_H__ */ From f94f7692a6836ed4a5f039e4c2a44966b47c77fc Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 6 Nov 2009 16:55:46 +0000 Subject: [PATCH 3/9] actor: Add :text-direction property Every actor should have a property for retrieving (and setting) the text direction. The text direction is used to provide a consisten behaviour in both left-to-right and right-to-left languages. For instance, ClutterText should perform key navigation following text direction. Layout managers should also take into account text direction to derive the right packing order for their children. --- clutter/clutter-actor.c | 116 +++++++++++++++++++++++++++++++++++++++- clutter/clutter-actor.h | 4 ++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 0b38fe4c8..efbce2752 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -332,6 +332,8 @@ struct _ClutterActorPrivate PangoContext *pango_context; ClutterActor *opacity_parent; + + ClutterTextDirection text_direction; }; enum @@ -409,7 +411,9 @@ enum PROP_ANCHOR_Y, PROP_ANCHOR_GRAVITY, - PROP_SHOW_ON_SET_PARENT + PROP_SHOW_ON_SET_PARENT, + + PROP_TEXT_DIRECTION }; enum @@ -2714,6 +2718,10 @@ clutter_actor_set_property (GObject *object, priv->show_on_set_parent = g_value_get_boolean (value); break; + case PROP_TEXT_DIRECTION: + clutter_actor_set_text_direction (actor, g_value_get_enum (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2967,6 +2975,10 @@ clutter_actor_get_property (GObject *object, g_value_set_boolean (value, priv->show_on_set_parent); break; + case PROP_TEXT_DIRECTION: + g_value_set_enum (value, priv->text_direction); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3778,6 +3790,16 @@ clutter_actor_class_init (ClutterActorClass *klass) PROP_CLIP_TO_ALLOCATION, pspec); + pspec = g_param_spec_enum ("text-direction", + "Text Direction", + "Direction of the text", + CLUTTER_TYPE_TEXT_DIRECTION, + CLUTTER_TEXT_DIRECTION_LTR, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (object_class, + PROP_TEXT_DIRECTION, + pspec); + /** * ClutterActor::destroy: * @actor: the object which received the signal @@ -9352,3 +9374,95 @@ clutter_actor_is_in_clone_paint (ClutterActor *self) return self->priv->opacity_parent != NULL && !self->priv->enable_model_view_transform; } + +static void +set_direction_recursive (ClutterActor *actor, + gpointer user_data) +{ + ClutterTextDirection text_dir = GPOINTER_TO_INT (user_data); + + clutter_actor_set_text_direction (actor, text_dir); +} + +/** + * clutter_actor_set_text_direction: + * @self: a #ClutterActor + * @text_dir: the text direction for @self + * + * Sets the #ClutterTextDirection for an actor + * + * The passed text direction must not be %CLUTTER_TEXT_DIRECTION_DEFAULT + * + * If @self implements #ClutterContainer then this function will recurse + * inside all the children of @self (including the internal ones). + * + * Composite actors not implementing #ClutterContainer, or actors requiring + * special handling when the text direction changes, should connect to + * the #GObject::notify signal for the #ClutterActor:text-direction property + * + * Since: 1.2 + */ +void +clutter_actor_set_text_direction (ClutterActor *self, + ClutterTextDirection text_dir) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (text_dir == CLUTTER_TEXT_DIRECTION_DEFAULT); + + priv = self->priv; + + if (priv->text_direction != text_dir) + { + priv->text_direction = text_dir; + + /* we need to emit the notify::text-direction first, so that + * the sub-classes can catch that and do specific handling of + * the text direction; see clutter_text_direction_changed_cb() + * inside clutter-text.c + */ + g_object_notify (G_OBJECT (self), "text-direction"); + + /* if this is a container we need to recurse */ + if (CLUTTER_IS_CONTAINER (self)) + { + ClutterContainer *container = CLUTTER_CONTAINER (self); + + clutter_container_foreach_with_internals (container, + set_direction_recursive, + GINT_TO_POINTER (text_dir)); + } + + clutter_actor_queue_relayout (self); + } +} + +/** + * clutter_actor_get_text_direction: + * @self: a #ClutterActor + * + * Retrieves the value set using clutter_actor_set_text_direction() + * + * If no text direction has been previously set, the default text + * direction will be returned + * + * Return value: the #ClutterTextDirection for the actor + * + * Since: 1.2 + */ +ClutterTextDirection +clutter_actor_get_text_direction (ClutterActor *self) +{ + ClutterActorPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), + CLUTTER_TEXT_DIRECTION_LTR); + + priv = self->priv; + + if (priv->text_direction == CLUTTER_TEXT_DIRECTION_DEFAULT) + return clutter_get_default_text_direction (); + + return priv->text_direction; +} diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index 4a5a38319..2f190a5ed 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -528,6 +528,10 @@ void clutter_actor_get_transformation_matrix (ClutterActor *self gboolean clutter_actor_is_in_clone_paint (ClutterActor *self); +void clutter_actor_set_text_direction (ClutterActor *self, + ClutterTextDirection text_dir); +ClutterTextDirection clutter_actor_get_text_direction (ClutterActor *self); + G_END_DECLS #endif /* __CLUTTER_ACTOR_H__ */ From adab87b520699892e012d601821a5aee11410125 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 10 Nov 2009 12:18:32 +0000 Subject: [PATCH 4/9] text: Dirty layout cache on text direction changes When the text direction changes we should evict the cached layouts to avoid stale entries in case the direction change produces a layout with the same size. --- clutter/clutter-text.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c index 04f24d5d8..69b1c3327 100644 --- a/clutter/clutter-text.c +++ b/clutter/clutter-text.c @@ -171,6 +171,9 @@ struct _ClutterTextPrivate /* Signal handler for when the backend changes its font settings */ guint font_changed_id; + + /* Signal handler for when the :text-direction changes */ + guint direction_changed_id; }; enum @@ -428,6 +431,15 @@ clutter_text_font_changed_cb (ClutterText *text) clutter_actor_queue_relayout (CLUTTER_ACTOR (text)); } +static void +clutter_text_direction_changed_cb (GObject *gobject, + GParamSpec *pspec) +{ + clutter_text_dirty_cache (CLUTTER_TEXT (gobject)); + + /* no need to queue a relayout: set_text_direction() will do that for us */ +} + /* * clutter_text_create_layout: * @text: a #ClutterText @@ -1098,6 +1110,12 @@ clutter_text_dispose (GObject *gobject) /* get rid of the entire cache */ clutter_text_dirty_cache (self); + if (priv->direction_changed_id) + { + g_signal_handler_disconnect (self, priv->direction_changed_id); + priv->direction_changed_id = 0; + } + if (priv->font_changed_id) { g_signal_handler_disconnect (clutter_get_default_backend (), @@ -2722,6 +2740,11 @@ clutter_text_init (ClutterText *self) "font-changed", G_CALLBACK (clutter_text_font_changed_cb), self); + + priv->direction_changed_id = + g_signal_connect (self, "notify::text-direction", + G_CALLBACK (clutter_text_direction_changed_cb), + NULL); } /** From 4bc3d02ebd928b4bc7c59811b9e90aae36750cfb Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 10 Nov 2009 12:20:14 +0000 Subject: [PATCH 5/9] box-layout: Honour :text-direction During size request and allocation a ClutterBoxLayout should honour the ClutterActor:text-direction property, and change the order of the children. --- clutter/clutter-box-layout.c | 206 ++++++++++++++++++++++++----------- 1 file changed, 142 insertions(+), 64 deletions(-) diff --git a/clutter/clutter-box-layout.c b/clutter/clutter-box-layout.c index a92b9218c..fb8d796eb 100644 --- a/clutter/clutter-box-layout.c +++ b/clutter/clutter-box-layout.c @@ -521,14 +521,16 @@ clutter_box_layout_set_container (ClutterLayoutManager *layout, static void get_preferred_width (ClutterBoxLayout *self, - const GList *children, + ClutterContainer *container, + GList *children, gfloat for_height, gfloat *min_width_p, gfloat *natural_width_p) { ClutterBoxLayoutPrivate *priv = self->priv; gint n_children = 0; - const GList *l; + gboolean is_rtl; + GList *l; if (min_width_p) *min_width_p = 0; @@ -536,7 +538,19 @@ get_preferred_width (ClutterBoxLayout *self, if (natural_width_p) *natural_width_p = 0; - for (l = children; l != NULL; l = l->next) + if (!priv->is_vertical) + { + ClutterTextDirection text_dir; + + text_dir = clutter_actor_get_text_direction (CLUTTER_ACTOR (container)); + is_rtl = (text_dir == CLUTTER_TEXT_DIRECTION_RTL) ? TRUE : FALSE; + } + else + is_rtl = FALSE; + + for (l = (is_rtl) ? g_list_last (children) : children; + l != NULL; + l = (is_rtl) ? l->prev : l->next) { ClutterActor *child = l->data; gfloat child_min = 0, child_nat = 0; @@ -584,14 +598,16 @@ get_preferred_width (ClutterBoxLayout *self, static void get_preferred_height (ClutterBoxLayout *self, - const GList *children, + ClutterContainer *container, + GList *children, gfloat for_height, gfloat *min_height_p, gfloat *natural_height_p) { ClutterBoxLayoutPrivate *priv = self->priv; gint n_children = 0; - const GList *l; + gboolean is_rtl; + GList *l; if (min_height_p) *min_height_p = 0; @@ -599,7 +615,19 @@ get_preferred_height (ClutterBoxLayout *self, if (natural_height_p) *natural_height_p = 0; - for (l = children; l != NULL; l = l->next) + if (!priv->is_vertical) + { + ClutterTextDirection text_dir; + + text_dir = clutter_actor_get_text_direction (CLUTTER_ACTOR (container)); + is_rtl = (text_dir == CLUTTER_TEXT_DIRECTION_RTL) ? TRUE : FALSE; + } + else + is_rtl = FALSE; + + for (l = (is_rtl) ? g_list_last (children) : children; + l != NULL; + l = (is_rtl) ? l->prev : l->next) { ClutterActor *child = l->data; gfloat child_min = 0, child_nat = 0; @@ -644,6 +672,78 @@ get_preferred_height (ClutterBoxLayout *self, } } +static void +allocate_box_child (ClutterBoxLayout *self, + ClutterContainer *container, + ClutterActor *child, + gfloat *position, + gfloat avail_width, + gfloat avail_height, + gfloat extra_space, + ClutterAllocationFlags flags) +{ + ClutterBoxLayoutPrivate *priv = self->priv; + ClutterActorBox child_box; + ClutterBoxChild *box_child; + ClutterLayoutMeta *meta; + gfloat child_nat; + + if (!CLUTTER_ACTOR_IS_VISIBLE (child)) + return; + + meta = clutter_layout_manager_get_child_meta (CLUTTER_LAYOUT_MANAGER (self), + container, + child); + box_child = CLUTTER_BOX_CHILD (meta); + + if (priv->is_vertical) + { + clutter_actor_get_preferred_height (child, avail_width, + NULL, &child_nat); + + child_box.y1 = floorf (*position + 0.5); + + if (box_child->expand) + child_box.y2 = floorf (*position + child_nat + extra_space + 0.5); + else + child_box.y2 = floorf (*position + child_nat + 0.5); + + child_box.x1 = 0; + child_box.x2 = floorf (avail_width + 0.5); + + allocate_fill (child, &child_box, box_child); + clutter_actor_allocate (child, &child_box, flags); + + if (box_child->expand) + *position += (child_nat + priv->spacing + extra_space); + else + *position += (child_nat + priv->spacing); + } + else + { + clutter_actor_get_preferred_width (child, avail_height, + NULL, &child_nat); + + child_box.x1 = floorf (*position + 0.5); + + if (box_child->expand) + child_box.x2 = floorf (*position + child_nat + extra_space + 0.5); + else + child_box.x2 = floorf (*position + child_nat + 0.5); + + child_box.y1 = 0; + child_box.y2 = floorf (avail_height + 0.5); + + allocate_fill (child, &child_box, box_child); + clutter_actor_allocate (child, &child_box, flags); + + if (box_child->expand) + *position += (child_nat + priv->spacing + extra_space); + else + *position += (child_nat + priv->spacing); + } +} + static void clutter_box_layout_get_preferred_width (ClutterLayoutManager *layout, ClutterContainer *container, @@ -656,7 +756,7 @@ clutter_box_layout_get_preferred_width (ClutterLayoutManager *layout, children = clutter_container_get_children (container); - get_preferred_width (self, children, for_height, + get_preferred_width (self, container, children, for_height, min_width_p, natural_width_p); @@ -675,7 +775,7 @@ clutter_box_layout_get_preferred_height (ClutterLayoutManager *layout, children = clutter_container_get_children (container); - get_preferred_height (self, children, for_width, + get_preferred_height (self, container, children, for_width, min_height_p, natural_height_p); @@ -690,9 +790,10 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout, { ClutterBoxLayoutPrivate *priv = CLUTTER_BOX_LAYOUT (layout)->priv; gfloat avail_width, avail_height, pref_width, pref_height; - GList *children, *l; gint n_expand_children, extra_space; + GList *children, *l; gfloat position; + gboolean is_rtl; children = clutter_container_get_children (container); if (children == NULL) @@ -703,6 +804,7 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout, if (priv->is_vertical) { get_preferred_height (CLUTTER_BOX_LAYOUT (layout), + container, children, avail_width, NULL, &pref_height); @@ -712,6 +814,7 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout, else { get_preferred_width (CLUTTER_BOX_LAYOUT (layout), + container, children, avail_height, NULL, &pref_width); @@ -752,69 +855,44 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout, position = 0; - for (l = (priv->is_pack_start) ? g_list_last (children) : children; - l != NULL; - l = (priv->is_pack_start) ? l->prev : l->next) + if (!priv->is_vertical) { - ClutterActor *child = l->data; - ClutterActorBox child_box; - ClutterBoxChild *box_child; - ClutterLayoutMeta *meta; - gfloat child_nat; + ClutterTextDirection text_dir; - if (!CLUTTER_ACTOR_IS_VISIBLE (child)) - continue; + text_dir = clutter_actor_get_text_direction (CLUTTER_ACTOR (container)); + is_rtl = (text_dir == CLUTTER_TEXT_DIRECTION_RTL) ? TRUE : FALSE; + } + else + is_rtl = FALSE; - meta = clutter_layout_manager_get_child_meta (layout, - container, - child); - box_child = CLUTTER_BOX_CHILD (meta); - - if (priv->is_vertical) + if (is_rtl) + { + for (l = (priv->is_pack_start) ? children : g_list_last (children); + l != NULL; + l = (priv->is_pack_start) ? l->next : l->prev) { - clutter_actor_get_preferred_height (child, avail_width, - NULL, &child_nat); + ClutterActor *child = l->data; - child_box.y1 = ceilf (position); - - if (box_child->expand) - child_box.y2 = ceilf (position + child_nat + extra_space); - else - child_box.y2 = ceilf (position + child_nat); - - child_box.x1 = 0; - child_box.x2 = ceilf (avail_width); - - allocate_fill (child, &child_box, box_child); - clutter_actor_allocate (child, &child_box, flags); - - if (box_child->expand) - position += (child_nat + priv->spacing + extra_space); - else - position += (child_nat + priv->spacing); + allocate_box_child (CLUTTER_BOX_LAYOUT (layout), container, child, + &position, + avail_width, + avail_height, + extra_space, flags); } - else + } + else + { + for (l = (priv->is_pack_start) ? g_list_last (children) : children; + l != NULL; + l = (priv->is_pack_start) ? l->prev : l->next) { - clutter_actor_get_preferred_width (child, avail_height, - NULL, &child_nat); + ClutterActor *child = l->data; - child_box.x1 = ceilf (position); - - if (box_child->expand) - child_box.x2 = ceilf (position + child_nat + extra_space); - else - child_box.x2 = ceilf (position + child_nat); - - child_box.y1 = 0; - child_box.y2 = ceilf (avail_height); - - allocate_fill (child, &child_box, box_child); - clutter_actor_allocate (child, &child_box, flags); - - if (box_child->expand) - position += (child_nat + priv->spacing + extra_space); - else - position += (child_nat + priv->spacing); + allocate_box_child (CLUTTER_BOX_LAYOUT (layout), container, child, + &position, + avail_width, + avail_height, + extra_space, flags); } } From 482e4e8d111fa76194a20ccd120eac41afa277d8 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 10 Nov 2009 12:21:26 +0000 Subject: [PATCH 6/9] tests: Display the index inside text-box-layout Since the rectangles packed inside the BoxLayout interactive test have random colors it's not easy to verify the ordering. By using the CoglPango API to print out the index in the middle of each rectangle. --- tests/interactive/test-box-layout.c | 41 ++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/tests/interactive/test-box-layout.c b/tests/interactive/test-box-layout.c index c22210deb..6d41ac8a5 100644 --- a/tests/interactive/test-box-layout.c +++ b/tests/interactive/test-box-layout.c @@ -22,8 +22,39 @@ #include #include +#include +#include "pango/cogl-pango.h" static ClutterActor *hover_actor = NULL; +static guint last_index = 0; + +static void +on_paint (ClutterActor *actor, + gpointer user_data) +{ + guint index_ = GPOINTER_TO_UINT (user_data); + gchar *text = g_strdup_printf ("%u", index_); + ClutterActorBox alloc = { 0, }; + CoglColor color; + gint layout_width, layout_height; + gfloat width, height; + PangoLayout *layout; + + clutter_actor_get_allocation_box (actor, &alloc); + clutter_actor_box_get_size (&alloc, &width, &height); + + layout = clutter_actor_create_pango_layout (actor, text); + pango_layout_get_size (layout, &layout_width, &layout_height); + + cogl_color_set_from_4ub (&color, 0, 0, 0, 255); + cogl_pango_render_layout (layout, + (width - (layout_width / 1024)) / 2, + (height - (layout_height / 1024)) / 2, + &color, 0); + + g_object_unref (layout); + g_free (text); +} static void enter_event (ClutterActor *actor, @@ -87,7 +118,8 @@ button_release_event (ClutterActor *actor, } static void -add_actor (ClutterBoxLayout *box) +add_actor (ClutterBoxLayout *box, + guint index_) { ClutterActor *rect; ClutterColor color = { 0xff, 0xff, 0xff, 255 }; @@ -107,6 +139,9 @@ add_actor (ClutterBoxLayout *box) CLUTTER_BOX_ALIGNMENT_CENTER); clutter_actor_set_reactive (rect, TRUE); + g_signal_connect_after (rect, "paint", + G_CALLBACK (on_paint), + GUINT_TO_POINTER (index_)); g_signal_connect (rect, "enter-event", G_CALLBACK (enter_event), NULL); g_signal_connect (rect, "leave-event", G_CALLBACK (leave_event), NULL); g_signal_connect (rect, "button-release-event", @@ -148,7 +183,7 @@ key_release_cb (ClutterActor *actor, break; case CLUTTER_plus: - add_actor (layout); + add_actor (layout, last_index++); break; default: @@ -190,7 +225,7 @@ test_box_layout_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), box); for (i = 0; i < 5; i++) - add_actor (CLUTTER_BOX_LAYOUT (layout)); + add_actor (CLUTTER_BOX_LAYOUT (layout), last_index++); g_signal_connect (stage, "key-release-event", G_CALLBACK (key_release_cb), From daeb3b2fecb3d740b6d84215928fc4477396dc71 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 30 Nov 2009 16:14:09 +0000 Subject: [PATCH 7/9] actor: Set text direction on parenting When setting the parent on an actor we should set the text direction to be the same as the parent's. --- clutter/clutter-actor.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index efbce2752..d7ef7d809 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -6618,6 +6618,7 @@ clutter_actor_set_parent (ClutterActor *self, ClutterActor *parent) { ClutterActorPrivate *priv; + ClutterTextDirection text_dir; g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (parent)); @@ -6656,13 +6657,15 @@ clutter_actor_set_parent (ClutterActor *self, */ clutter_actor_update_map_state (self, MAP_STATE_CHECK); + /* propagate the parent's text direction to the child */ + text_dir = clutter_actor_get_text_direction (parent); + clutter_actor_set_text_direction (self, text_dir); + if (priv->show_on_set_parent) clutter_actor_show (self); if (CLUTTER_ACTOR_IS_MAPPED (self)) - { - clutter_actor_queue_redraw (self); - } + clutter_actor_queue_redraw (self); /* maintain the invariant that if an actor needs layout, * its parents do as well @@ -9461,8 +9464,9 @@ clutter_actor_get_text_direction (ClutterActor *self) priv = self->priv; + /* if no direction has been set yet use the default */ if (priv->text_direction == CLUTTER_TEXT_DIRECTION_DEFAULT) - return clutter_get_default_text_direction (); + priv->text_direction = clutter_get_default_text_direction (); return priv->text_direction; } From 3cb974ee8be182944848b5e64dd4724f118bc8fa Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 30 Nov 2009 16:15:19 +0000 Subject: [PATCH 8/9] Set the default language on the Pango context When creating the Pango context we should also set the language to be the default Pango language. --- clutter/clutter-main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 4d7cc10b7..c0f140ab1 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -583,6 +583,7 @@ update_pango_context (ClutterBackend *backend, const cairo_font_options_t *font_options; const gchar *font_name; PangoDirection pango_dir; + PangoLanguage *lang; gdouble resolution; /* update the text direction */ @@ -640,6 +641,7 @@ _clutter_context_create_pango_context (ClutterMainContext *self) context = cogl_pango_font_map_create_context (self->font_map); update_pango_context (self->backend, context); + pango_context_set_language (context, pango_language_get_default ()); return context; } From 6e99c1aefe8f76cb3004a8cc89ae6f8b95d1f597 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 1 Dec 2009 14:55:01 +0000 Subject: [PATCH 9/9] docs: Add text-direction accessors --- doc/reference/clutter/clutter-sections.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 36b552dda..6d8481416 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -396,6 +396,8 @@ clutter_actor_get_pango_context clutter_actor_create_pango_context clutter_actor_create_pango_layout clutter_actor_is_in_clone_paint +clutter_actor_set_text_direction +clutter_actor_get_text_direction ClutterActorBox @@ -1014,6 +1016,8 @@ ClutterFontFlags clutter_set_font_flags clutter_get_font_flags clutter_get_font_map +clutter_set_default_text_direction +clutter_get_default_text_direction clutter_threads_set_lock_functions