From f854619bc976775af7c2a7ab7d52cec7cc0c490c Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 14 Feb 2012 15:39:15 +0000 Subject: [PATCH] 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 --- clutter/clutter-box-layout.c | 67 +++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/clutter/clutter-box-layout.c b/clutter/clutter-box-layout.c index f8c11ccaf..4d18585b5 100644 --- a/clutter/clutter-box-layout.c +++ b/clutter/clutter-box-layout.c @@ -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; } }