static void mex_column_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { ClutterActorBox child_box; MxPadding padding; GList *c; MexColumn *column = MEX_COLUMN (actor); MexColumnPrivate *priv = column->priv; CLUTTER_ACTOR_CLASS (mex_column_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); child_box.x1 = padding.left; child_box.x2 = box->x2 - box->x1 - padding.right; child_box.y1 = padding.top; child_box.y2 = box->y2 - box->y1 - padding.bottom; if (priv->n_items) { /* Calculate child height multiplier */ gfloat width, pref_height, avail_height, ratio, remainder; if (!priv->adjustment) { /* Find out the height available for each actor as a ratio of * their preferred height. */ clutter_actor_get_preferred_height (actor, box->x2 - box->x1, NULL, &pref_height); pref_height -= padding.top + padding.bottom; avail_height = child_box.y2 - child_box.y1; ratio = avail_height / pref_height; } else ratio = 1; /* Allocate children */ remainder = 0; width = child_box.x2 - child_box.x1; for (c = priv->children; c; c = c->next) { gfloat min_height, nat_height, height; ClutterActor *child = c->data; clutter_actor_get_preferred_height (child, width, &min_height, &nat_height); /* Calculate the allocatable height and keep an accumulator so * when we round to a pixel, we don't end up with a lot of * empty space at the end of the actor. */ height = MAX (min_height, nat_height / ratio); remainder += (height - (gint)height); height = (gint)height; while (remainder >= 1.f) { height += 1.f; remainder -= 1.f; } /* Allocate the child */ child_box.y2 = child_box.y1 + height; clutter_actor_allocate (child, &child_box, flags); /* Set the top position of the next child box */ child_box.y1 = child_box.y2; } } /* Make sure the adjustment reflects the column's allocation */ if (priv->adjustment) { gdouble page_size = box->y2 - box->y1 - padding.top - padding.bottom; mx_adjustment_set_values (priv->adjustment, mx_adjustment_get_value (priv->adjustment), 0.0, child_box.y2 - padding.top, 1.0, page_size, page_size); } }
void scroll_view_main (ClutterContainer *stage) { gint width, height; MxAdjustment *hadjust, *vadjust; ClutterActor *label, *elastic, *overshoot, *scroll, *kinetic, *view, *texture; scroll = mx_scroll_view_new (); /* Make sure something underneath the kinetic scroll view swallows events * so that we don't end up moving the window. */ g_signal_connect (scroll, "button-press-event", G_CALLBACK (true_cb), NULL); kinetic = mx_kinetic_scroll_view_new (); clutter_container_add_actor (stage, scroll); clutter_actor_set_position (scroll, 10, 10); clutter_actor_set_size (scroll, 300, 300); view = mx_viewport_new (); mx_viewport_set_sync_adjustments (MX_VIEWPORT (view), FALSE); clutter_container_add_actor (CLUTTER_CONTAINER (kinetic), view); clutter_container_add_actor (CLUTTER_CONTAINER (scroll), kinetic); texture = clutter_texture_new_from_file ("redhand.png", NULL); clutter_container_add_actor (CLUTTER_CONTAINER (view), texture); g_object_set (texture, "repeat-x", TRUE, "repeat-y", TRUE, NULL); clutter_actor_set_size (texture, 1280, 1280); clutter_texture_get_base_size (CLUTTER_TEXTURE (texture), &width, &height); mx_scrollable_get_adjustments (MX_SCROLLABLE (view), &hadjust, &vadjust); mx_adjustment_set_values (hadjust, 0, 0, 1280, width, width * 3, 300); mx_adjustment_set_values (vadjust, 0, 0, 1280, height, height * 3, 300); label = mx_label_new_with_text ("Toggle over-shooting:"); overshoot = mx_toggle_new (); clutter_actor_set_position (label, 320, 10); clutter_actor_set_position (overshoot, 330 + clutter_actor_get_width (label), 10); clutter_container_add (stage, label, overshoot, NULL); g_signal_connect (overshoot, "notify::active", G_CALLBACK (notify_overshoot_cb), kinetic); label = mx_label_new_with_text ("Toggle elasticity:"); elastic = mx_toggle_new (); clutter_actor_set_position (label, 320, 20 + clutter_actor_get_height (overshoot)); clutter_actor_set_position (elastic, clutter_actor_get_x (overshoot), clutter_actor_get_y (label)); clutter_container_add (stage, label, elastic, NULL); g_signal_connect (elastic, "notify::active", G_CALLBACK (notify_elastic_cb), kinetic); }