clutter 1.0 document:
http://docs.clutter-project.org/docs/clutter-cookbook/1.0/
meego-panel-myzone/penge/penge-block-container.c source:
static void penge_block_container_class_init (PengeBlockContainerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GParamSpec *pspec; g_type_class_add_private (klass, sizeof (PengeBlockContainerPrivate)); object_class->get_property = penge_block_container_get_property; object_class->set_property = penge_block_container_set_property; object_class->dispose = penge_block_container_dispose; object_class->finalize = penge_block_container_finalize; actor_class->get_preferred_width = penge_block_container_get_preferred_width; actor_class->get_preferred_height = penge_block_container_get_preferred_height; actor_class->allocate = penge_block_container_allocate; actor_class->paint = penge_block_container_paint; actor_class->pick = penge_block_container_pick; ... ... }
/* These are needed since the layout manager allocates {0, 0, 0, 0} for * children it can't lay out. */ static void _paint_foreach_cb (ClutterActor *actor, gpointer data) { ClutterActorBox actor_box; gfloat w, h; clutter_actor_get_allocation_box (actor, &actor_box); clutter_actor_box_get_size (&actor_box, &w, &h); if (w > 0 && h > 0) { clutter_actor_paint (actor); } } static void penge_block_container_paint (ClutterActor *actor) { clutter_container_foreach (CLUTTER_CONTAINER (actor), (ClutterCallback)_paint_foreach_cb, actor); }
static void penge_block_container_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { PengeBlockContainer *pbc = PENGE_BLOCK_CONTAINER (actor); PengeBlockContainerPrivate *priv = GET_PRIVATE (actor); GList *l, *children; gfloat width, height; gint col_span; gint y_count, x_count; ClutterActor *child; ClutterActorBox child_box; gboolean fit_found = FALSE; width = box->x2 - box->x1; height = box->y2 - box->y1; CLUTTER_ACTOR_CLASS (penge_block_container_parent_class)->allocate (actor, box, flags); if (priv->prev_width != width || priv->prev_height != height) { penge_block_container_generate_counts (pbc, width, height); } children = g_list_copy (priv->children); if (!children) return; children = g_list_reverse (children); for (y_count = 0; y_count < priv->row_count; y_count++) { for (x_count = 0; x_count < priv->column_count; /* nop */) { /* Find first that can fit */ fit_found = FALSE; for (l = children; l; l = l->next) { child = (ClutterActor *)l->data; col_span = penge_block_container_get_child_column_span (pbc, child); /* Check if it fits */ if (x_count + col_span <= priv->column_count) { child_box.x1 = x_count * priv->actual_tile_width + x_count * priv->spacing + priv->padding; child_box.x2 = child_box.x1 + priv->actual_tile_width * col_span + priv->spacing * (col_span - 1); child_box.y1 = y_count * priv->actual_tile_height + y_count * priv->spacing + priv->padding; child_box.y2 = child_box.y1 + priv->actual_tile_height; clutter_actor_allocate (child, &child_box, flags); children = g_list_remove (children, child); /* Increment with the col-span to take into consideration how many * "blocks" we are occupying */ x_count += col_span; fit_found = TRUE; break; } } /* If we didn't find something that fits then we just leave a gap. This * is basically fine. */ if (!fit_found) { /* We couldn't find something that fitted */ break; } } if (!children) break; } /* Allocate all children we don't get round to with {0,0,0,0}. We skip such * children in the paint. */ for (l = children; l; l = l->next) { ClutterActor *actor = CLUTTER_ACTOR (l->data); ClutterActorBox zero_box = { 0, }; clutter_actor_allocate (actor, &zero_box, flags); } g_list_free (children); }