[St] Make allocation handling more consistent

In StBin, StBoxLayout, and StTable, if a child has a potential
allocation that is larger than its preferred size, we give it its
preferred size instead. However, the corresponding
get_preferred_height/width methods were not making the same
assumption, which meant that if we had more width than the widget
wanted, we would allocate it its preferred width, but with the height
that corresponded to the larger width.

Fix this by defining new helpers _st_actor_get_preferred_width() and
_st_actor_get_preferred_height() and using them everywhere. Also, make
StBin and StTable use _st_allocate_fill() rather than having
nearly-identical duplicate copies of the code.

https://bugzilla.gnome.org/show_bug.cgi?id=609848
This commit is contained in:
Dan Winship 2010-02-13 11:24:25 -05:00
parent f52744cfbc
commit 5331d3e360
6 changed files with 291 additions and 342 deletions

View File

@ -37,9 +37,9 @@ shell_slicer_get_preferred_width (ClutterActor *self,
} }
else else
{ {
clutter_actor_get_preferred_width (child, for_height, _st_actor_get_preferred_width (child, for_height, FALSE,
NULL, NULL,
natural_width_p); natural_width_p);
} }
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
@ -66,9 +66,9 @@ shell_slicer_get_preferred_height (ClutterActor *self,
} }
else else
{ {
clutter_actor_get_preferred_height (child, for_width, _st_actor_get_preferred_height (child, for_width, FALSE,
NULL, NULL,
natural_height_p); natural_height_p);
} }
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
@ -97,14 +97,17 @@ shell_slicer_paint_child (ShellSlicer *self)
ClutterActorBox self_box; ClutterActorBox self_box;
ClutterActorBox child_box; ClutterActorBox child_box;
float width, height, child_width, child_height; float width, height, child_width, child_height;
double x_align, y_align; StAlign x_align, y_align;
double x_align_factor, y_align_factor;
child = st_bin_get_child (ST_BIN (self)); child = st_bin_get_child (ST_BIN (self));
if (!child) if (!child)
return; return;
_st_bin_get_align_factors (ST_BIN (self), &x_align, &y_align); st_bin_get_alignment (ST_BIN (self), &x_align, &y_align);
_st_get_align_factors (ST_WIDGET (self), x_align, y_align,
&x_align_factor, &y_align_factor);
clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &self_box); clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &self_box);
clutter_actor_get_allocation_box (child, &child_box); clutter_actor_get_allocation_box (child, &child_box);
@ -117,8 +120,8 @@ shell_slicer_paint_child (ShellSlicer *self)
cogl_push_matrix (); cogl_push_matrix ();
cogl_clip_push (0, 0, width, height); cogl_clip_push (0, 0, width, height);
cogl_translate ((int)(0.5 + x_align * (width - child_width)), cogl_translate ((int)(0.5 + x_align_factor * (width - child_width)),
(int)(0.5 + y_align * (height - child_height)), (int)(0.5 + y_align_factor * (height - child_height)),
0); 0);
clutter_actor_paint (child); clutter_actor_paint (child);

View File

@ -71,59 +71,6 @@ G_DEFINE_TYPE_WITH_CODE (StBin, st_bin, ST_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
clutter_container_iface_init)); clutter_container_iface_init));
void
_st_bin_get_align_factors (StBin *bin,
gdouble *x_align,
gdouble *y_align)
{
StBinPrivate *priv = bin->priv;
gdouble factor;
switch (priv->x_align)
{
case ST_ALIGN_START:
factor = 0.0;
break;
case ST_ALIGN_MIDDLE:
factor = 0.5;
break;
case ST_ALIGN_END:
factor = 1.0;
break;
default:
factor = 0.0;
break;
}
if (x_align)
*x_align = factor;
switch (priv->y_align)
{
case ST_ALIGN_START:
factor = 0.0;
break;
case ST_ALIGN_MIDDLE:
factor = 0.5;
break;
case ST_ALIGN_END:
factor = 1.0;
break;
default:
factor = 0.0;
break;
}
if (y_align)
*y_align = factor;
}
static void static void
st_bin_add (ClutterContainer *container, st_bin_add (ClutterContainer *container,
ClutterActor *actor) ClutterActor *actor)
@ -199,92 +146,13 @@ st_bin_allocate (ClutterActor *self,
if (priv->child) if (priv->child)
{ {
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
gfloat natural_width, natural_height; ClutterActorBox childbox;
gfloat min_width, min_height;
gfloat child_width, child_height;
gfloat available_width, available_height;
ClutterRequestMode request;
ClutterActorBox content_box;
ClutterActorBox allocation = { 0, };
gdouble x_align, y_align;
st_theme_node_get_content_box (theme_node, box, &content_box); st_theme_node_get_content_box (theme_node, box, &childbox);
_st_allocate_fill (ST_WIDGET (self), priv->child, &childbox,
_st_bin_get_align_factors (ST_BIN (self), &x_align, &y_align); priv->x_align, priv->y_align,
priv->x_fill, priv->y_fill);
available_width = content_box.x2 - content_box.x1; clutter_actor_allocate (priv->child, &childbox, flags);
available_height = content_box.y2 - content_box.y1;
if (available_width < 0)
available_width = 0;
if (available_height < 0)
available_height = 0;
if (priv->x_fill)
{
allocation.x1 = (int) content_box.x1;
allocation.x2 = (int) content_box.x2;
}
if (priv->y_fill)
{
allocation.y1 = (int) content_box.y1;
allocation.y2 = (int) content_box.y2;
}
/* if we are filling horizontally and vertically then we're done */
if (priv->x_fill && priv->y_fill)
{
clutter_actor_allocate (priv->child, &allocation, flags);
return;
}
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
g_object_get (G_OBJECT (priv->child), "request-mode", &request, NULL);
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
{
clutter_actor_get_preferred_width (priv->child, available_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
clutter_actor_get_preferred_height (priv->child, child_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
}
else
{
clutter_actor_get_preferred_height (priv->child, available_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
clutter_actor_get_preferred_width (priv->child, child_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
}
if (!priv->x_fill)
{
allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align);
allocation.x2 = allocation.x1 + child_width;
}
if (!priv->y_fill)
{
allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align);
allocation.y2 = allocation.y1 + child_height;
}
clutter_actor_allocate (priv->child, &allocation, flags);
} }
} }
@ -309,9 +177,9 @@ st_bin_get_preferred_width (ClutterActor *self,
} }
else else
{ {
clutter_actor_get_preferred_width (priv->child, for_height, _st_actor_get_preferred_width (priv->child, for_height, priv->y_fill,
min_width_p, min_width_p,
natural_width_p); natural_width_p);
} }
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
@ -338,9 +206,9 @@ st_bin_get_preferred_height (ClutterActor *self,
} }
else else
{ {
clutter_actor_get_preferred_height (priv->child, for_width, _st_actor_get_preferred_height (priv->child, for_width, priv->x_fill,
min_height_p, min_height_p,
natural_height_p); natural_height_p);
} }
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);

View File

@ -528,6 +528,7 @@ get_content_preferred_width (StBoxLayout *self,
{ {
ClutterActor *child = l->data; ClutterActor *child = l->data;
gfloat child_min = 0, child_nat = 0; gfloat child_min = 0, child_nat = 0;
gboolean child_fill;
if (!CLUTTER_ACTOR_IS_VISIBLE (child)) if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue; continue;
@ -540,18 +541,20 @@ get_content_preferred_width (StBoxLayout *self,
continue; continue;
} }
clutter_actor_get_preferred_width (child,
(!priv->is_vertical) ? for_height : -1,
&child_min,
&child_nat);
if (priv->is_vertical) if (priv->is_vertical)
{ {
_st_actor_get_preferred_width (child, -1, FALSE,
&child_min, &child_nat);
min_width = MAX (child_min, min_width); min_width = MAX (child_min, min_width);
natural_width = MAX (child_nat, natural_width); natural_width = MAX (child_nat, natural_width);
} }
else else
{ {
clutter_container_child_get ((ClutterContainer*) self, child,
"y-fill", &child_fill,
NULL);
_st_actor_get_preferred_width (child, for_height, child_fill,
&child_min, &child_nat);
min_width += child_min; min_width += child_min;
natural_width += child_nat; natural_width += child_nat;
} }
@ -606,6 +609,7 @@ get_content_preferred_height (StBoxLayout *self,
{ {
ClutterActor *child = l->data; ClutterActor *child = l->data;
gfloat child_min = 0, child_nat = 0; gfloat child_min = 0, child_nat = 0;
gboolean child_fill = FALSE;
if (!CLUTTER_ACTOR_IS_VISIBLE (child)) if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue; continue;
@ -618,10 +622,17 @@ get_content_preferred_height (StBoxLayout *self,
continue; continue;
} }
clutter_actor_get_preferred_height (child, if (priv->is_vertical)
(priv->is_vertical) ? for_width : -1, {
&child_min, clutter_container_child_get ((ClutterContainer*) self, child,
&child_nat); "x-fill", &child_fill,
NULL);
}
_st_actor_get_preferred_height (child,
(priv->is_vertical) ? for_width : -1,
child_fill,
&child_min,
&child_nat);
if (!priv->is_vertical) if (!priv->is_vertical)
{ {
@ -713,6 +724,7 @@ compute_shrinks (StBoxLayout *self,
{ {
ClutterActor *child = l->data; ClutterActor *child = l->data;
gfloat child_min, child_nat; gfloat child_min, child_nat;
gboolean child_fill;
gboolean fixed; gboolean fixed;
child = (ClutterActor*) l->data; child = (ClutterActor*) l->data;
@ -722,13 +734,23 @@ compute_shrinks (StBoxLayout *self,
if (CLUTTER_ACTOR_IS_VISIBLE (child) && !fixed) if (CLUTTER_ACTOR_IS_VISIBLE (child) && !fixed)
{ {
if (priv->is_vertical) if (priv->is_vertical)
clutter_actor_get_preferred_height (child, {
for_length, clutter_container_child_get ((ClutterContainer*) self, child,
&child_min, &child_nat); "x-fill", &child_fill,
NULL);
_st_actor_get_preferred_height (child,
for_length, child_fill,
&child_min, &child_nat);
}
else else
clutter_actor_get_preferred_width (child, {
for_length, clutter_container_child_get ((ClutterContainer*) self, child,
&child_min, &child_nat); "y-fill", &child_fill,
NULL);
_st_actor_get_preferred_width (child,
for_length, child_fill,
&child_min, &child_nat);
}
shrinks[i].shrink_amount = MAX (0., child_nat - child_min); shrinks[i].shrink_amount = MAX (0., child_nat - child_min);
n_possible_shrink_children++; n_possible_shrink_children++;
@ -943,13 +965,13 @@ st_box_layout_allocate (ClutterActor *actor,
if (priv->is_vertical) if (priv->is_vertical)
{ {
clutter_actor_get_preferred_height (child, avail_width, _st_actor_get_preferred_height (child, avail_width, xfill,
&child_min, &child_nat); &child_min, &child_nat);
} }
else else
{ {
clutter_actor_get_preferred_width (child, avail_height, _st_actor_get_preferred_width (child, avail_height, yfill,
&child_min, &child_nat); &child_min, &child_nat);
} }
child_allocated = child_nat; child_allocated = child_nat;
@ -973,7 +995,8 @@ st_box_layout_allocate (ClutterActor *actor,
else else
child_box.x2 = content_box.x2; child_box.x2 = content_box.x2;
_st_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill); _st_allocate_fill (ST_WIDGET (actor), child, &child_box,
xalign, yalign, xfill, yfill);
clutter_actor_allocate (child, &child_box, flags); clutter_actor_allocate (child, &child_box, flags);
} }
@ -996,7 +1019,8 @@ st_box_layout_allocate (ClutterActor *actor,
else else
child_box.y2 = content_box.y2; child_box.y2 = content_box.y2;
_st_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill); _st_allocate_fill (ST_WIDGET (actor), child, &child_box,
xalign, yalign, xfill, yfill);
clutter_actor_allocate (child, &child_box, flags); clutter_actor_allocate (child, &child_box, flags);
} }

View File

@ -1,12 +1,114 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include "st-private.h" #include "st-private.h"
/* Utility function to modify a child allocation box with respect to the /**
* x/y-fill child properties. Expects childbox to contain the available * _st_actor_get_preferred_width:
* allocation space. * @actor: a #ClutterActor
* @for_height: as with clutter_actor_get_preferred_width()
* @y_fill: %TRUE if @actor will fill its allocation vertically
* @min_width_p: as with clutter_actor_get_preferred_width()
* @natural_width_p: as with clutter_actor_get_preferred_width()
*
* Like clutter_actor_get_preferred_width(), but if @y_fill is %FALSE,
* then it will compute a width request based on the assumption that
* @actor will be given an allocation no taller than its natural
* height.
*/ */
void void
_st_allocate_fill (ClutterActor *child, _st_actor_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gboolean y_fill,
gfloat *min_width_p,
gfloat *natural_width_p)
{
if (!y_fill && for_height != -1)
{
ClutterRequestMode mode;
gfloat natural_height;
g_object_get (G_OBJECT (actor), "request-mode", &mode, NULL);
if (mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT)
{
clutter_actor_get_preferred_height (actor, -1, NULL, &natural_height);
if (for_height > natural_height)
for_height = natural_height;
}
}
clutter_actor_get_preferred_width (actor, for_height, min_width_p, natural_width_p);
}
/**
* _st_actor_get_preferred_height:
* @actor: a #ClutterActor
* @for_width: as with clutter_actor_get_preferred_height()
* @x_fill: %TRUE if @actor will fill its allocation horizontally
* @min_height_p: as with clutter_actor_get_preferred_height()
* @natural_height_p: as with clutter_actor_get_preferred_height()
*
* Like clutter_actor_get_preferred_height(), but if @x_fill is
* %FALSE, then it will compute a height request based on the
* assumption that @actor will be given an allocation no wider than
* its natural width.
*/
void
_st_actor_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gboolean x_fill,
gfloat *min_height_p,
gfloat *natural_height_p)
{
if (!x_fill && for_width != -1)
{
ClutterRequestMode mode;
gfloat natural_width;
g_object_get (G_OBJECT (actor), "request-mode", &mode, NULL);
if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
{
clutter_actor_get_preferred_width (actor, -1, NULL, &natural_width);
if (for_width > natural_width)
for_width = natural_width;
}
}
clutter_actor_get_preferred_height (actor, for_width, min_height_p, natural_height_p);
}
/**
* _st_allocate_fill:
* @parent: the parent #StWidget
* @child: the child (not necessarily an #StWidget)
* @childbox: total space that could be allocated to @child
* @x_alignment: horizontal alignment within @childbox
* @y_alignment: vertical alignment within @childbox
* @x_fill: whether or not to fill @childbox horizontally
* @y_fill: whether or not to fill @childbox vertically
*
* Given @childbox, containing the initial allocation of @child, this
* adjusts the horizontal allocation if @x_fill is %FALSE, and the
* vertical allocation if @y_fill is %FALSE, by:
*
* - reducing the allocation if it is larger than @child's natural
* size.
*
* - adjusting the position of the child within the allocation
* according to @x_alignment/@y_alignment (and flipping
* @x_alignment if @parent has %ST_TEXT_DIRECTION_RTL)
*
* If @x_fill and @y_fill are both %TRUE, or if @child's natural size
* is larger than the initial allocation in @childbox, then @childbox
* will be unchanged.
*
* If you are allocating children with _st_allocate_fill(), you should
* determine their preferred sizes using
* _st_actor_get_preferred_width() and
* _st_actor_get_preferred_height(), not with the corresponding
* Clutter methods.
*/
void
_st_allocate_fill (StWidget *parent,
ClutterActor *child,
ClutterActorBox *childbox, ClutterActorBox *childbox,
StAlign x_alignment, StAlign x_alignment,
StAlign y_alignment, StAlign y_alignment,
@ -18,51 +120,36 @@ _st_allocate_fill (ClutterActor *child,
gfloat child_width, child_height; gfloat child_width, child_height;
gfloat available_width, available_height; gfloat available_width, available_height;
ClutterRequestMode request; ClutterRequestMode request;
ClutterActorBox allocation = { 0, };
gdouble x_align, y_align; gdouble x_align, y_align;
if (x_alignment == ST_ALIGN_START)
x_align = 0.0;
else if (x_alignment == ST_ALIGN_MIDDLE)
x_align = 0.5;
else
x_align = 1.0;
if (y_alignment == ST_ALIGN_START)
y_align = 0.0;
else if (y_alignment == ST_ALIGN_MIDDLE)
y_align = 0.5;
else
y_align = 1.0;
available_width = childbox->x2 - childbox->x1; available_width = childbox->x2 - childbox->x1;
available_height = childbox->y2 - childbox->y1; available_height = childbox->y2 - childbox->y1;
if (available_width < 0) if (available_width < 0)
available_width = 0; {
available_width = 0;
childbox->x2 = childbox->x1;
}
if (available_height < 0) if (available_height < 0)
available_height = 0;
if (x_fill)
{ {
allocation.x1 = childbox->x1; available_height = 0;
allocation.x2 = (int)(allocation.x1 + available_width); childbox->y2 = childbox->y1;
} }
if (y_fill) /* If we are filling both horizontally and vertically then we don't
{ * need to do anything else.
allocation.y1 = childbox->y1; */
allocation.y2 = (int)(allocation.y1 + available_height);
}
/* if we are filling horizontally and vertically then we're done */
if (x_fill && y_fill) if (x_fill && y_fill)
{ return;
*childbox = allocation;
return;
}
_st_get_align_factors (parent, x_alignment, y_alignment,
&x_align, &y_align);
/* The following is based on clutter_actor_get_preferred_size(), but
* modified to cope with the fact that the available size may be
* less than the preferred size.
*/
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH; request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
g_object_get (G_OBJECT (child), "request-mode", &request, NULL); g_object_get (G_OBJECT (child), "request-mode", &request, NULL);
@ -97,18 +184,82 @@ _st_allocate_fill (ClutterActor *child,
if (!x_fill) if (!x_fill)
{ {
allocation.x1 = childbox->x1 + (int)((available_width - child_width) * x_align); childbox->x1 += (int)((available_width - child_width) * x_align);
allocation.x2 = allocation.x1 + (int) child_width; childbox->x2 = childbox->x1 + (int) child_width;
} }
if (!y_fill) if (!y_fill)
{ {
allocation.y1 = childbox->y1 + (int)((available_height - child_height) * y_align); childbox->y1 += (int)((available_height - child_height) * y_align);
allocation.y2 = allocation.y1 + (int) child_height; childbox->y2 = childbox->y1 + (int) child_height;
}
}
/**
* _st_get_align_factors:
* @widget: an #StWidget
* @x_align: an #StAlign
* @y_align: an #StAlign
* @x_align_out: (out) (allow-none): @x_align as a #gdouble
* @y_align_out: (out) (allow-none): @y_align as a #gdouble
*
* Converts @x_align and @y_align to #gdouble values. If @widget has
* %ST_TEXT_DIRECTION_RTL, the @x_align_out value will be flipped
* relative to @x_align.
*/
void
_st_get_align_factors (StWidget *widget,
StAlign x_align,
StAlign y_align,
gdouble *x_align_out,
gdouble *y_align_out)
{
if (x_align_out)
{
switch (x_align)
{
case ST_ALIGN_START:
*x_align_out = 0.0;
break;
case ST_ALIGN_MIDDLE:
*x_align_out = 0.5;
break;
case ST_ALIGN_END:
*x_align_out = 1.0;
break;
default:
g_warn_if_reached ();
break;
}
if (st_widget_get_direction (widget) == ST_TEXT_DIRECTION_RTL)
*x_align_out = 1.0 - *x_align_out;
} }
*childbox = allocation; if (y_align_out)
{
switch (y_align)
{
case ST_ALIGN_START:
*y_align_out = 0.0;
break;
case ST_ALIGN_MIDDLE:
*y_align_out = 0.5;
break;
case ST_ALIGN_END:
*y_align_out = 1.0;
break;
default:
g_warn_if_reached ();
break;
}
}
} }
/** /**

View File

@ -44,11 +44,25 @@ G_END_DECLS
ClutterActor *_st_widget_get_dnd_clone (StWidget *widget); ClutterActor *_st_widget_get_dnd_clone (StWidget *widget);
void _st_bin_get_align_factors (StBin *bin, void _st_get_align_factors (StWidget *widget,
gdouble *x_align, StAlign x_align,
gdouble *y_align); StAlign y_align,
gdouble *x_align_out,
gdouble *y_align_out);
void _st_allocate_fill (ClutterActor *child, void _st_actor_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gboolean y_fill,
gfloat *min_width_p,
gfloat *natural_width_p);
void _st_actor_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gboolean x_fill,
gfloat *min_height_p,
gfloat *natural_height_p);
void _st_allocate_fill (StWidget *parent,
ClutterActor *child,
ClutterActorBox *childbox, ClutterActorBox *childbox,
StAlign x_align, StAlign x_align,
StAlign y_align, StAlign y_align,

View File

@ -278,120 +278,6 @@ st_table_dispose (GObject *gobject)
G_OBJECT_CLASS (st_table_parent_class)->dispose (gobject); G_OBJECT_CLASS (st_table_parent_class)->dispose (gobject);
} }
#define CLAMP_TO_PIXEL(x) ((float)((int)(x)))
/* Utility function to modify a child allocation box with respect to the
* x/y-fill child properties. Expects childbox to contain the available
* allocation space.
*/
static void
st_table_allocate_fill (ClutterActor *child,
ClutterActorBox *childbox,
gdouble x_align,
gdouble y_align,
gboolean x_fill,
gboolean y_fill,
gboolean ltr)
{
gfloat natural_width, natural_height;
gfloat min_width, min_height;
gfloat child_width, child_height;
gfloat available_width, available_height;
ClutterRequestMode request;
ClutterActorBox allocation = { 0, };
available_width = childbox->x2 - childbox->x1;
available_height = childbox->y2 - childbox->y1;
if (available_width < 0)
available_width = 0;
if (available_height < 0)
available_height = 0;
if (x_fill)
{
if (ltr)
{
allocation.x1 = childbox->x1;
allocation.x2 = (int)(allocation.x1 + available_width);
}
else
{
allocation.x2 = childbox->x2;
allocation.x1 = (int)(allocation.x2 - available_width);
}
}
if (y_fill)
{
allocation.y1 = childbox->y1;
allocation.y2 = (int)(allocation.y1 + available_height);
}
/* if we are filling horizontally and vertically then we're done */
if (x_fill && y_fill)
{
*childbox = allocation;
return;
}
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
g_object_get (G_OBJECT (child), "request-mode", &request, NULL);
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
{
clutter_actor_get_preferred_width (child, available_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
clutter_actor_get_preferred_height (child, child_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
}
else
{
clutter_actor_get_preferred_height (child, available_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
clutter_actor_get_preferred_width (child, child_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
}
if (!x_fill)
{
if (ltr)
{
allocation.x1 = childbox->x1 + (int)((available_width - child_width) * x_align);
allocation.x2 = allocation.x1 + (int) child_width;
}
else
{
allocation.x2 = childbox->x2 - (int)((available_width - child_width) * x_align);
allocation.x1 = allocation.x2 - (int) child_width;
}
}
if (!y_fill)
{
allocation.y1 = childbox->y1 + (int)((available_height - child_height) * y_align);
allocation.y2 = allocation.y1 + (int) child_height;
}
*childbox = allocation;
}
static void static void
st_table_homogeneous_allocate (ClutterActor *self, st_table_homogeneous_allocate (ClutterActor *self,
const ClutterActorBox *content_box, const ClutterActorBox *content_box,
@ -453,7 +339,8 @@ st_table_homogeneous_allocate (ClutterActor *self,
childbox.y1 = content_box->y1 + (row_height + row_spacing) * row; childbox.y1 = content_box->y1 + (row_height + row_spacing) * row;
childbox.y2 = childbox.y1 + (row_height * row_span) + (row_spacing * (row_span - 1)); childbox.y2 = childbox.y1 + (row_height * row_span) + (row_spacing * (row_span - 1));
st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill, ltr); _st_allocate_fill (ST_WIDGET (self), child, &childbox,
x_align, y_align, x_fill, y_fill);
clutter_actor_allocate (child, &childbox, flags); clutter_actor_allocate (child, &childbox, flags);
} }
@ -510,7 +397,7 @@ st_table_calculate_col_widths (StTable *table,
if (x_expand) if (x_expand)
is_expand_col[col] = TRUE; is_expand_col[col] = TRUE;
clutter_actor_get_preferred_width (child, -1, &w_min, &w_pref); _st_actor_get_preferred_width (child, -1, meta->y_fill, &w_min, &w_pref);
if (col_span == 1 && w_pref > pref_widths[col]) if (col_span == 1 && w_pref > pref_widths[col])
{ {
pref_widths[col] = w_pref; pref_widths[col] = w_pref;
@ -630,11 +517,12 @@ st_table_calculate_row_heights (StTable *table,
if (!meta->x_fill) if (!meta->x_fill)
{ {
gfloat width; gfloat width;
clutter_actor_get_preferred_width (child, -1, NULL, &width); _st_actor_get_preferred_width (child, -1, meta->y_fill, NULL, &width);
cell_width = MIN (cell_width, width); cell_width = MIN (cell_width, width);
} }
clutter_actor_get_preferred_height (child, cell_width, &h_min, &h_pref); _st_actor_get_preferred_height (child, cell_width, meta->x_fill,
&h_min, &h_pref);
if (row_span == 1 && h_pref > pref_heights[row]) if (row_span == 1 && h_pref > pref_heights[row])
{ {
@ -874,7 +762,8 @@ st_table_preferred_allocate (ClutterActor *self,
childbox.y2 = (float) MAX (0, child_y + row_height); childbox.y2 = (float) MAX (0, child_y + row_height);
st_table_allocate_fill (child, &childbox, x_align, y_align, x_fill, y_fill, ltr); _st_allocate_fill (ST_WIDGET (self), child, &childbox,
x_align, y_align, x_fill, y_fill);
clutter_actor_allocate (child, &childbox, flags); clutter_actor_allocate (child, &childbox, flags);
} }
@ -954,7 +843,7 @@ st_table_get_preferred_width (ClutterActor *self,
col = meta->col; col = meta->col;
col_span = meta->col_span; col_span = meta->col_span;
clutter_actor_get_preferred_width (child, -1, &w_min, &w_pref); _st_actor_get_preferred_width (child, -1, meta->y_fill, &w_min, &w_pref);
if (col_span == 1 && w_min > min_widths[col]) if (col_span == 1 && w_min > min_widths[col])
min_widths[col] = w_min; min_widths[col] = w_min;
@ -1041,8 +930,8 @@ st_table_get_preferred_height (ClutterActor *self,
for (i = 0; i < col_span && col + i < priv->n_cols; i++) for (i = 0; i < col_span && col + i < priv->n_cols; i++)
cell_width += min_widths[col + i]; cell_width += min_widths[col + i];
clutter_actor_get_preferred_height (child, _st_actor_get_preferred_height (child, (float) cell_width, meta->x_fill,
(float) cell_width, &min, &pref); &min, &pref);
if (row_span == 1 && min > min_heights[row]) if (row_span == 1 && min > min_heights[row])
min_heights[row] = min; min_heights[row] = min;