/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /** * SECTION:shell-stack * @short_description: Pure "Z-axis" container class * * A #ShellStack draws its children on top of each other, * aligned to the top left. It will be sized in width/height * according to the largest such dimension of its children, and * all children will be allocated that size. This differs * from #ClutterGroup which allocates its children their natural * size, even if that would overflow the size allocated to the stack. */ #include "config.h" #include "shell-stack.h" G_DEFINE_TYPE (ShellStack, shell_stack, CLUTTER_TYPE_GROUP); static void shell_stack_allocate (ClutterActor *self, const ClutterActorBox *box, ClutterAllocationFlags flags) { GList *children, *iter; float width, height; width = box->x2 - box->x1; height = box->y2 - box->y1; /* Chain up directly to ClutterActor to set actor->allocation. We explicitly skip our parent class * ClutterGroup here because we want to override the allocate function. */ (CLUTTER_ACTOR_CLASS (g_type_class_peek (clutter_actor_get_type ())))->allocate (self, box, flags); children = clutter_container_get_children (CLUTTER_CONTAINER (self)); for (iter = children; iter; iter = iter->next) { ClutterActor *actor = CLUTTER_ACTOR (iter->data); ClutterActorBox child_box; child_box.x1 = 0; child_box.x2 = width; child_box.y1 = 0; child_box.y2 = height; clutter_actor_allocate (actor, &child_box, flags); } g_list_free (children); } static void shell_stack_get_preferred_height (ClutterActor *actor, gfloat for_width, gfloat *min_height_p, gfloat *natural_height_p) { ShellStack *stack = SHELL_STACK (actor); gboolean first = TRUE; float min = 0, natural = 0; GList *children; GList *iter; children = clutter_container_get_children (CLUTTER_CONTAINER (stack)); for (iter = children; iter; iter = iter->next) { ClutterActor *child = iter->data; float child_min, child_natural; clutter_actor_get_preferred_height (child, for_width, &child_min, &child_natural); if (first) { first = FALSE; min = child_min; natural = child_natural; } else { if (child_min > min) min = child_min; if (child_natural > natural) natural = child_natural; } } if (min_height_p) *min_height_p = min; if (natural_height_p) *natural_height_p = natural; g_list_free (children); } static void shell_stack_get_preferred_width (ClutterActor *actor, gfloat for_height, gfloat *min_width_p, gfloat *natural_width_p) { ShellStack *stack = SHELL_STACK (actor); gboolean first = TRUE; float min = 0, natural = 0; GList *iter; GList *children; children = clutter_container_get_children (CLUTTER_CONTAINER (stack)); for (iter = children; iter; iter = iter->next) { ClutterActor *child = iter->data; float child_min, child_natural; clutter_actor_get_preferred_width (child, for_height, &child_min, &child_natural); if (first) { first = FALSE; min = child_min; natural = child_natural; } else { if (child_min > min) min = child_min; if (child_natural > natural) natural = child_natural; } } if (min_width_p) *min_width_p = min; if (natural_width_p) *natural_width_p = natural; g_list_free (children); } static void shell_stack_class_init (ShellStackClass *klass) { ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); actor_class->get_preferred_width = shell_stack_get_preferred_width; actor_class->get_preferred_height = shell_stack_get_preferred_height; actor_class->allocate = shell_stack_allocate; } static void shell_stack_init (ShellStack *actor) { }