From 07b01888baed28e5fb3f0831a2441218b469f846 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 10 Aug 2010 17:40:01 +0100 Subject: [PATCH] actor: Add allocate_align_fill() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layout managers are using the same code to allocate a child while taking into consideration: • horizontal and vertical alignment • horizontal and vertical fill • the preferred minimum and natural size, depending on the :request-mode property • the text direction for the horizontal alignment • an offset given by the fixed position properties Given the amount of code involved, and the amount of details that can go horribly wrong while copy and pasting such code in various classes - let alone various projects - Clutter should provide an allocate() variant that does the right thing in the right way. This way, we have a single point of failure. --- clutter/clutter-actor.c | 139 +++++++++++++++++++++ clutter/clutter-actor.h | 7 ++ doc/reference/clutter/clutter-sections.txt | 1 + 3 files changed, 147 insertions(+) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 645442297..8e6ab132b 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -9976,6 +9976,145 @@ clutter_actor_allocate_preferred_size (ClutterActor *self, clutter_actor_allocate (self, &actor_box, flags); } +/** + * clutter_actor_allocate_align_fill: + * @self: a #ClutterActor + * @box: a #ClutterActorBox, containing the available width and height + * @x_align: the horizontal alignment, between 0 and 1 + * @y_align: the vertical alignment, between 0 and 1 + * @x_fill: whether the actor should fill horizontally + * @y_fill: whether the actor should fill vertically + * @flags: allocation flags to be passed to clutter_actor_allocate() + * + * Allocates @self by taking into consideration the available allocation + * area; an alignment factor on either axis; and whether the actor should + * fill the allocation on either axis. + * + * The @box should contain the available allocation width and height; + * if the x1 and y1 members of #ClutterActorBox are not set to 0, the + * allocation will be offset by their value. + * + * This function takes into consideration the geometry request specified by + * the #ClutterActor:request-mode property, and the text direction. + * + * This function is useful for fluid layout managers, like #ClutterBinLayout + * or #ClutterTableLayout + * + * Since: 1.4 + */ +void +clutter_actor_allocate_align_fill (ClutterActor *self, + const ClutterActorBox *box, + gdouble x_align, + gdouble y_align, + gboolean x_fill, + gboolean y_fill, + ClutterAllocationFlags flags) +{ + ClutterActorPrivate *priv; + ClutterActorBox allocation = { 0, }; + gfloat x_offset, y_offset; + gfloat available_width, available_height; + gfloat child_width, child_height; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (box != NULL); + g_return_if_fail (x_align >= 0.0 && x_align <= 1.0); + g_return_if_fail (y_align >= 0.0 && y_align <= 1.0); + + priv = self->priv; + + clutter_actor_box_get_origin (box, &x_offset, &y_offset); + clutter_actor_box_get_size (box, &available_width, &available_height); + + if (available_width < 0) + available_width = 0; + + if (available_height < 0) + available_height = 0; + + if (x_fill) + { + allocation.x1 = x_offset; + allocation.x2 = allocation.x1 + available_width; + } + + if (y_fill) + { + allocation.y1 = y_offset; + allocation.y2 = allocation.y1 + available_height; + } + + /* if we are filling horizontally and vertically then we're done */ + if (x_fill && y_fill) + goto out; + + child_width = child_height = 0.0f; + + if (priv->request_mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + { + gfloat min_width, natural_width; + gfloat min_height, natural_height; + + clutter_actor_get_preferred_width (self, available_height, + &min_width, + &natural_width); + + child_width = CLAMP (natural_width, min_width, available_width); + + if (!y_fill) + { + clutter_actor_get_preferred_height (self, child_width, + &min_height, + &natural_height); + + child_height = CLAMP (natural_height, min_height, available_height); + } + } + else + { + gfloat min_width, natural_width; + gfloat min_height, natural_height; + + clutter_actor_get_preferred_height (self, available_width, + &min_height, + &natural_height); + + child_height = CLAMP (natural_height, min_height, available_height); + + if (!x_fill) + { + clutter_actor_get_preferred_width (self, child_height, + &min_width, + &natural_width); + + child_width = CLAMP (natural_width, min_width, available_width); + } + } + + /* invert the horizontal alignment for RTL languages */ + if (priv->text_direction == CLUTTER_TEXT_DIRECTION_RTL) + x_align = 1.0 - x_align; + + if (!x_fill) + { + allocation.x1 = box->x1 + + ((available_width - child_width) * x_align); + allocation.x2 = allocation.x1 + child_width; + } + + if (!y_fill) + { + allocation.y1 = box->y1 + + ((available_height - child_height) * y_align); + allocation.y2 = allocation.y1 + child_height; + } + +out: + clutter_actor_box_clamp_to_pixel (&allocation); + clutter_actor_allocate (self, &allocation, flags); +} + /** * clutter_actor_grab_key_focus: * @self: a #ClutterActor diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index 518c124e7..c4ede389e 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -361,6 +361,13 @@ void clutter_actor_allocate_available_size (ClutterActor gfloat available_width, gfloat available_height, ClutterAllocationFlags flags); +void clutter_actor_allocate_align_fill (ClutterActor *self, + const ClutterActorBox *box, + gdouble x_align, + gdouble y_align, + gboolean x_fill, + gboolean y_fill, + ClutterAllocationFlags flags); void clutter_actor_get_allocation_box (ClutterActor *self, ClutterActorBox *box); void clutter_actor_get_allocation_geometry (ClutterActor *self, diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index be64aa1de..d92816525 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -303,6 +303,7 @@ ClutterAllocationFlags clutter_actor_allocate clutter_actor_allocate_preferred_size clutter_actor_allocate_available_size +clutter_actor_allocate_align_fill clutter_actor_get_allocation_box clutter_actor_get_allocation_geometry clutter_actor_get_allocation_vertices