box-layout: Fix allocation brain farts

The allocation code for BoxLayout contains a sequence of brain farts
that make it barely working since the synchronization of the layout
algorithm to the one in GtkBox.

The origin of the layout is inverted, and it doesn't take into
consideration a modified allocation origin (for actors the provide
padding or margin).

The pack-start property is broken, and it only works because we walk the
children list backwards; this horribly breaks when a child changes
visibility. Plus, we count invisible children, which leads to
allocations getting insane origins (either close to -MAX_FLOAT or
MAX_FLOAT).

Finally, the allocation is applied twice even for non-animated cases.

https://bugzilla.gnome.org/show_bug.cgi?id=669291
This commit is contained in:
Emmanuele Bassi 2012-02-14 15:39:15 +00:00
parent dbd603c504
commit f854619bc9

View File

@ -474,9 +474,9 @@ clutter_box_layout_set_container (ClutterLayoutManager *layout,
/* we need to change the :request-mode of the container
* to match the orientation
*/
request_mode = (priv->is_vertical
? CLUTTER_REQUEST_HEIGHT_FOR_WIDTH
: CLUTTER_REQUEST_WIDTH_FOR_HEIGHT);
request_mode = priv->is_vertical
? CLUTTER_REQUEST_HEIGHT_FOR_WIDTH
: CLUTTER_REQUEST_WIDTH_FOR_HEIGHT;
clutter_actor_set_request_mode (CLUTTER_ACTOR (priv->container),
request_mode);
}
@ -655,6 +655,12 @@ allocate_box_child (ClutterBoxLayout *self,
child);
box_child = CLUTTER_BOX_CHILD (meta);
CLUTTER_NOTE (LAYOUT, "Allocation for %s { %.2f, %.2f, %.2f, %.2f }",
_clutter_actor_get_debug_name (child),
child_box->x1, child_box->y1,
child_box->x2 - child_box->x1,
child_box->y2 - child_box->y1);
clutter_actor_allocate_align_fill (child, child_box,
get_box_alignment_factor (box_child->x_align),
get_box_alignment_factor (box_child->y_align),
@ -684,7 +690,7 @@ allocate_box_child (ClutterBoxLayout *self,
box_child->last_allocation = final_child_box;
box_child->has_last_allocation = TRUE;
goto do_allocate;
return;
}
start = &box_child->last_allocation;
@ -704,16 +710,17 @@ allocate_box_child (ClutterBoxLayout *self,
final_child_box.x2, final_child_box.y2,
end.x1, end.y1,
end.x2, end.y2);
clutter_actor_allocate (child, &final_child_box, flags);
}
else
{
/* store the allocation for later animations */
box_child->last_allocation = final_child_box;
box_child->has_last_allocation = TRUE;
}
do_allocate:
clutter_actor_allocate (child, &final_child_box, flags);
return;
}
}
static void
@ -915,6 +922,11 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
count_expand_children (layout, container, &nvis_children, &nexpand_children);
CLUTTER_NOTE (LAYOUT, "BoxLayout for %s: visible=%d, expand=%d",
_clutter_actor_get_debug_name (CLUTTER_ACTOR (container)),
nvis_children,
nexpand_children);
/* If there is no visible child, simply return. */
if (nvis_children <= 0)
return;
@ -1016,33 +1028,30 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
/* Allocate child positions. */
if (priv->is_vertical)
{
child_allocation.x1 = 0.0;
child_allocation.x1 = box->x1;
child_allocation.x2 = MAX (1.0, box->x2 - box->x1);
if (priv->is_pack_start)
y = 0.0;
else
y = box->y2 - box->y1;
else
y = box->y1;
}
else
{
child_allocation.y1 = 0.0;
child_allocation.y1 = box->y1;
child_allocation.y2 = MAX (1.0, box->y2 - box->y1);
if (priv->is_pack_start)
x = 0.0;
x = box->x2 - box->x1;
else
x = 0.0 + box->x2 - box->x1;
x = box->x1;
}
i = clutter_actor_get_n_children (actor);
for (child = clutter_actor_get_last_child (actor);
child != NULL;
child = clutter_actor_get_previous_sibling (child))
i = 0;
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
ClutterLayoutMeta *meta;
ClutterBoxChild *box_child;
i -= 1;
/* If widget is not visible, skip it. */
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
@ -1094,23 +1103,23 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
}
if (priv->is_pack_start)
{
y += child_size + priv->spacing;
}
else
{
y -= child_size + priv->spacing;
child_allocation.y1 -= child_size;
child_allocation.y2 -= child_size;
}
else
{
y += child_size + priv->spacing;
}
}
else /* !priv->is_vertical */
{
if (box_child->x_fill)
{
child_allocation.x1 = x;
child_allocation.x2 = child_allocation.x1 + MAX (1, child_size);
child_allocation.x2 = child_allocation.x1 + MAX (1.0, child_size);
}
else
{
@ -1119,16 +1128,16 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
}
if (priv->is_pack_start)
{
x += child_size + priv->spacing;
}
else
{
x -= child_size + priv->spacing;
child_allocation.x1 -= child_size;
child_allocation.x2 -= child_size;
}
else
{
x += child_size + priv->spacing;
}
if (is_rtl)
{
@ -1147,6 +1156,8 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
child,
&child_allocation,
flags);
i += 1;
}
}