[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:
parent
f52744cfbc
commit
5331d3e360
@ -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);
|
||||||
|
156
src/st/st-bin.c
156
src/st/st-bin.c
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user