static void penge_calendar_pane_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { PengeCalendarPanePrivate *priv = GET_PRIVATE (actor); gfloat events_nat_h, tasks_nat_h, events_header_nat_h, tasks_header_nat_h; gfloat width, height, remaining_height, last_y; gfloat tasks_available_h, events_available_h; ClutterActorBox child_box; MxPadding padding = { 0, }; if (CLUTTER_ACTOR_CLASS (penge_calendar_pane_parent_class)->allocate) CLUTTER_ACTOR_CLASS (penge_calendar_pane_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); width = box->x2 - box->x1; height = box->y2 - box->y1; clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->events_header_table), width, NULL, &events_header_nat_h); clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->events_pane), width, NULL, &events_nat_h); clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->tasks_header_table), width, NULL, &tasks_header_nat_h); clutter_actor_get_preferred_height (CLUTTER_ACTOR (priv->tasks_pane), width, NULL, &tasks_nat_h); child_box.x1 = padding.left; child_box.x2 = width - padding.right; child_box.y1 = padding.top; child_box.y2 = child_box.y1 + events_header_nat_h; last_y = child_box.y2; clutter_actor_allocate (CLUTTER_ACTOR (priv->events_header_table), &child_box, flags); remaining_height = height - padding.top - padding.bottom - events_header_nat_h - tasks_header_nat_h; if (tasks_nat_h <= (remaining_height / 2.0)) { tasks_available_h = tasks_nat_h; } else { tasks_available_h = (remaining_height / 2.0); } events_available_h = remaining_height - tasks_available_h; if (events_available_h > events_nat_h) { tasks_available_h += (tasks_available_h - events_nat_h); events_available_h = events_nat_h; } child_box.x1 = padding.left; child_box.x2 = width - padding.right; child_box.y1 = last_y; child_box.y2 = child_box.y1 + (int)events_available_h; last_y = child_box.y2; clutter_actor_allocate (CLUTTER_ACTOR (priv->events_pane), &child_box, flags); child_box.x1 = padding.left; child_box.x2 = width - padding.right; child_box.y1 = last_y; child_box.y2 = child_box.y1 + tasks_header_nat_h; last_y = child_box.y2; clutter_actor_allocate (CLUTTER_ACTOR (priv->tasks_header_table), &child_box, flags); child_box.x1 = padding.left; child_box.x2 = width - padding.right; child_box.y1 = last_y; child_box.y2 = child_box.y1 + (int)tasks_available_h; clutter_actor_allocate (CLUTTER_ACTOR (priv->tasks_pane), &child_box, flags); }
static void st_table_homogeneous_allocate (ClutterActor *self, const ClutterActorBox *content_box, gboolean flags) { GList *list, *children; gfloat col_width, row_height; gint row_spacing, col_spacing; StTablePrivate *priv = ST_TABLE (self)->priv; gboolean ltr = st_widget_get_direction (ST_WIDGET (self)) == ST_TEXT_DIRECTION_LTR; col_spacing = priv->col_spacing; row_spacing = priv->row_spacing; col_width = (int) ((content_box->x2 - content_box->x1 - (col_spacing * (priv->n_cols - 1))) / priv->n_cols + 0.5); row_height = (int) ((content_box->y2 - content_box->y1 - (row_spacing * (priv->n_rows - 1))) / priv->n_rows + 0.5); children = st_container_get_children_list (ST_CONTAINER (self)); for (list = children; list; list = list->next) { gint row, col, row_span, col_span; StTableChild *meta; ClutterActor *child; ClutterActorBox childbox; StAlign x_align, y_align; gboolean x_fill, y_fill; child = CLUTTER_ACTOR (list->data); meta = (StTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child); if (!meta->allocate_hidden && !CLUTTER_ACTOR_IS_VISIBLE (child)) continue; /* get child properties */ col = meta->col; row = meta->row; row_span = meta->row_span; col_span = meta->col_span; x_align = meta->x_align; y_align = meta->y_align; x_fill = meta->x_fill; y_fill = meta->y_fill; if (ltr) { childbox.x1 = content_box->x1 + (col_width + col_spacing) * col; childbox.x2 = childbox.x1 + (col_width * col_span) + (col_spacing * (col_span - 1)); } else { childbox.x2 = content_box->x2 - (col_width + col_spacing) * col; childbox.x1 = childbox.x2 - (col_width * col_span) - (col_spacing * (col_span - 1)); } childbox.y1 = content_box->y1 + (row_height + row_spacing) * row; childbox.y2 = childbox.y1 + (row_height * row_span) + (row_spacing * (row_span - 1)); _st_allocate_fill (ST_WIDGET (self), child, &childbox, x_align, y_align, x_fill, y_fill); clutter_actor_allocate (child, &childbox, flags); } }
static void mx_combo_box_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv; MxPadding padding; gfloat x, y, width, height; gfloat min_menu_h, nat_menu_h; gfloat label_h; gfloat nat_icon_h, icon_h, icon_w; gfloat nat_marker_h, marker_h, marker_w; ClutterActorBox childbox; ClutterActor *menu, *stage; CLUTTER_ACTOR_CLASS (mx_combo_box_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); x = padding.left; y = padding.top; width = box->x2 - box->x1 - padding.left - padding.right; height = box->y2 - box->y1 - padding.top - padding.bottom; icon_w = marker_w = 0; if (priv->icon) { /* Allocate the icon, if there is one, the space not used by the text */ clutter_actor_get_preferred_height (priv->icon, -1, NULL, &nat_icon_h); if (height >= nat_icon_h) { icon_h = nat_icon_h; clutter_actor_get_preferred_width (priv->icon, -1, NULL, &icon_w); } else { icon_h = height; clutter_actor_get_preferred_width (priv->icon, icon_h, NULL, &icon_w); } childbox.x1 = (int)(x); childbox.y1 = (int)(y + (height - icon_h) / 2); childbox.x2 = (int)(x + icon_w); childbox.y2 = (int)(childbox.y1 + icon_h); clutter_actor_allocate (priv->icon, &childbox, flags); icon_w += priv->spacing; } if (priv->marker) { clutter_actor_get_preferred_height (priv->marker, -1, NULL, &nat_marker_h); if (height >= nat_marker_h) { marker_h = nat_marker_h; clutter_actor_get_preferred_width (priv->marker, -1, NULL, &marker_w); } else { marker_h = height; clutter_actor_get_preferred_width (priv->marker, marker_h, NULL, &marker_w); } childbox.x2 = (int)(x + width); childbox.x1 = (int)(childbox.x2 - marker_w); childbox.y1 = (int)(y + (height - marker_h) / 2); childbox.y2 = (int)(childbox.y1 + marker_h); clutter_actor_allocate (priv->marker, &childbox, flags); marker_w += priv->spacing; } clutter_actor_get_preferred_height (priv->label, -1, NULL, &label_h); childbox.x1 = (int)(x + icon_w); childbox.y1 = (int)(y + (height / 2 - label_h / 2)); childbox.x2 = (int)(x + width - marker_w); childbox.y2 = (int)(childbox.y1 + label_h); clutter_actor_allocate (priv->label, &childbox, flags); menu = (ClutterActor*) mx_widget_get_menu (MX_WIDGET (actor)); clutter_actor_get_preferred_height (menu, (box->x2 - box->x1), &min_menu_h, &nat_menu_h); childbox.x1 = 0; childbox.x2 = (box->x2 - box->x1); childbox.y1 = (box->y2 - box->y1); childbox.y2 = childbox.y1 + nat_menu_h; stage = clutter_actor_get_stage (actor); if (stage != NULL) { ClutterVertex point = { 0, }; gfloat stage_w, stage_h, combo_h = box->y2 - box->y1; clutter_actor_get_size (stage, &stage_w, &stage_h); point.y = combo_h + nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); /* If the menu would appear off the stage, flip it around. */ if ((point.y < 0) || (point.y >= stage_h)) { childbox.y1 = -nat_menu_h; point.y = -nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); /* if the menu would still appear out of the stage, force * it to appear on the top of the stage. */ if (point.y < 0) { gfloat xactor, yactor; clutter_actor_get_transformed_position (actor, &xactor, &yactor); childbox.y1 = -yactor; } } point.y = childbox.y1 + nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); if (point.y >= stage_h) { gfloat xactor, yactor; clutter_actor_get_transformed_position (actor, &xactor, &yactor); /* * clamp so that the menu doesn't appear out of the screen */ clutter_actor_transform_stage_point (actor, xactor, stage_h, NULL, &childbox.y2); /* * The previous transformation can lead to negative height * allocation if the top-left corner of the menu is already * flipped around. This happens when you put a combobox deep * enough in a scrollview taller that the stage. */ childbox.y2 = MAX (childbox.y1, childbox.y2); } else { childbox.y2 = childbox.y1 + nat_menu_h; } } clutter_actor_allocate (menu, &childbox, flags); }
static void st_scroll_view_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { ClutterActorBox content_box, child_box; gfloat avail_width, avail_height, sb_width, sb_height; gboolean hscrollbar_visible, vscrollbar_visible; StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); clutter_actor_set_allocation (actor, box, flags); st_theme_node_get_content_box (theme_node, box, &content_box); avail_width = content_box.x2 - content_box.x1; avail_height = content_box.y2 - content_box.y1; if (clutter_actor_get_request_mode (actor) == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) { sb_width = get_scrollbar_width (ST_SCROLL_VIEW (actor), -1); sb_height = get_scrollbar_height (ST_SCROLL_VIEW (actor), sb_width); } else { sb_height = get_scrollbar_height (ST_SCROLL_VIEW (actor), -1); sb_width = get_scrollbar_width (ST_SCROLL_VIEW (actor), sb_height); } /* Determine what scrollbars are visible. The basic idea of the * handling of an automatic scrollbars is that we start off with the * assumption that we don't need any scrollbars, see if that works, * and if not add horizontal and vertical scrollbars until we are no * longer overflowing. */ if (priv->child) { gfloat child_min_width; gfloat child_min_height; clutter_actor_get_preferred_width (priv->child, -1, &child_min_width, NULL); if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC) { if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC) { /* Pass one, try without a vertical scrollbar */ clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL); vscrollbar_visible = child_min_height > avail_height; hscrollbar_visible = child_min_width > avail_width - (vscrollbar_visible ? sb_width : 0); vscrollbar_visible = child_min_height > avail_height - (hscrollbar_visible ? sb_height : 0); /* Pass two - if we needed a vertical scrollbar, get a new preferred height */ if (vscrollbar_visible) { clutter_actor_get_preferred_height (priv->child, MAX (avail_width - sb_width, 0), &child_min_height, NULL); hscrollbar_visible = child_min_width > avail_width - sb_width; } } else { hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER; /* try without a vertical scrollbar */ clutter_actor_get_preferred_height (priv->child, avail_width, &child_min_height, NULL); vscrollbar_visible = child_min_height > avail_height - (hscrollbar_visible ? sb_height : 0); } } else { vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER; if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC) hscrollbar_visible = child_min_width > avail_height - (vscrollbar_visible ? 0 : sb_width); else hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER; } } else { hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER; vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER; } /* Whether or not we show the scrollbars, if the scrollbars are visible * actors, we need to give them some allocation, so we unconditionally * give them the "right" allocation; that might overlap the child when * the scrollbars are not visible, but it doesn't matter because we * don't include them in pick or paint. */ /* Vertical scrollbar */ if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL) { child_box.x1 = content_box.x1; child_box.x2 = content_box.x1 + sb_width; } else { child_box.x1 = content_box.x2 - sb_width; child_box.x2 = content_box.x2; } child_box.y1 = content_box.y1; child_box.y2 = content_box.y2 - (hscrollbar_visible ? sb_height : 0); clutter_actor_allocate (priv->vscroll, &child_box, flags); /* Horizontal scrollbar */ if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL) { child_box.x1 = content_box.x1 + (vscrollbar_visible ? sb_width : 0); child_box.x2 = content_box.x2; } else { child_box.x1 = content_box.x1; child_box.x2 = content_box.x2 - (vscrollbar_visible ? sb_width : 0); } child_box.y1 = content_box.y2 - sb_height; child_box.y2 = content_box.y2; clutter_actor_allocate (priv->hscroll, &child_box, flags); /* In case the scrollbar policy is NEVER or scrollbars should be * overlayed, we don't trim the content box allocation by the * scrollbar size. * Fold this into the scrollbar sizes to simplify the rest of the * computations. */ if (priv->hscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars) sb_height = 0; if (priv->vscrollbar_policy == GTK_POLICY_NEVER || priv->overlay_scrollbars) sb_width = 0; /* Child */ if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL) { child_box.x1 = content_box.x1 + sb_width; child_box.x2 = content_box.x2; } else { child_box.x1 = content_box.x1; child_box.x2 = content_box.x2 - sb_width; } child_box.y1 = content_box.y1; child_box.y2 = content_box.y2 - sb_height; if (priv->child) clutter_actor_allocate (priv->child, &child_box, flags); if (priv->hscrollbar_visible != hscrollbar_visible) { g_object_freeze_notify (G_OBJECT (actor)); priv->hscrollbar_visible = hscrollbar_visible; g_object_notify (G_OBJECT (actor), "hscrollbar-visible"); g_object_thaw_notify (G_OBJECT (actor)); } if (priv->vscrollbar_visible != vscrollbar_visible) { g_object_freeze_notify (G_OBJECT (actor)); priv->vscrollbar_visible = vscrollbar_visible; g_object_notify (G_OBJECT (actor), "vscrollbar-visible"); g_object_thaw_notify (G_OBJECT (actor)); } }
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); } }
static void mx_scroll_bar_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxScrollBarPrivate *priv = MX_SCROLL_BAR (actor)->priv; MxPadding padding; ClutterActorBox bw_box, fw_box, trough_box; gfloat x, y, width, height, stepper_size; /* Chain up */ CLUTTER_ACTOR_CLASS (mx_scroll_bar_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); /* calculate the child area */ x = padding.left; y = padding.top; width = (box->x2 - box->x1) - padding.left - padding.right; height = (box->y2 - box->y1) - padding.top - padding.bottom; if (priv->orientation == MX_ORIENTATION_VERTICAL) { stepper_size = width; /* Backward stepper */ bw_box.x1 = x; bw_box.y1 = y; bw_box.x2 = bw_box.x1 + stepper_size; bw_box.y2 = bw_box.y1 + stepper_size; clutter_actor_allocate (priv->bw_stepper, &bw_box, flags); /* Forward stepper */ fw_box.x1 = x; fw_box.y1 = y + height - stepper_size; fw_box.x2 = fw_box.x1 + stepper_size; fw_box.y2 = fw_box.y1 + stepper_size; clutter_actor_allocate (priv->fw_stepper, &fw_box, flags); /* Trough */ trough_box.x1 = x; trough_box.y1 = y + stepper_size; trough_box.x2 = x + width; trough_box.y2 = y + height - stepper_size; clutter_actor_allocate (priv->trough, &trough_box, flags); } else { stepper_size = height; /* Backward stepper */ bw_box.x1 = x; bw_box.y1 = y; bw_box.x2 = bw_box.x1 + stepper_size; bw_box.y2 = bw_box.y1 + stepper_size; clutter_actor_allocate (priv->bw_stepper, &bw_box, flags); /* Forward stepper */ fw_box.x1 = x + width - stepper_size; fw_box.y1 = y; fw_box.x2 = fw_box.x1 + stepper_size; fw_box.y2 = fw_box.y1 + stepper_size; clutter_actor_allocate (priv->fw_stepper, &fw_box, flags); /* Trough */ trough_box.x1 = x + stepper_size; trough_box.y1 = y; trough_box.x2 = x + width - stepper_size; trough_box.y2 = y + height; clutter_actor_allocate (priv->trough, &trough_box, flags); } if (priv->adjustment) { gfloat handle_size, position, avail_size, handle_pos; gdouble value, lower, upper, page_size, increment; ClutterActorBox handle_box = { 0, }; guint min_size, max_size; mx_adjustment_get_values (priv->adjustment, &value, &lower, &upper, NULL, NULL, &page_size); value = mx_adjustment_get_value (priv->adjustment); if ((upper == lower) || (page_size >= (upper - lower))) increment = 1.0; else increment = page_size / (upper - lower); min_size = priv->handle_min_size; mx_stylable_get (MX_STYLABLE (actor), "mx-max-size", &max_size, NULL); if (upper - lower - page_size <= 0) position = 0; else position = (value - lower) / (upper - lower - page_size); if (priv->orientation == MX_ORIENTATION_VERTICAL) { avail_size = height - stepper_size * 2; handle_size = increment * avail_size; handle_size = CLAMP (handle_size, min_size, max_size); handle_box.x1 = x; handle_pos = bw_box.y2 + position * (avail_size - handle_size); handle_box.y1 = CLAMP (handle_pos, bw_box.y2, fw_box.y1 - min_size); handle_box.x2 = handle_box.x1 + width; handle_box.y2 = CLAMP (handle_pos + handle_size, bw_box.y2 + min_size, fw_box.y1); } else { avail_size = width - stepper_size * 2; handle_size = increment * avail_size; handle_size = CLAMP (handle_size, min_size, max_size); handle_pos = bw_box.x2 + position * (avail_size - handle_size); handle_box.x1 = CLAMP (handle_pos, bw_box.x2, fw_box.x1 - min_size); handle_box.y1 = y; handle_box.x2 = CLAMP (handle_pos + handle_size, bw_box.x2 + min_size, fw_box.x1); handle_box.y2 = handle_box.y1 + height; } /* snap to pixel */ handle_box.x1 = (int) handle_box.x1; handle_box.y1 = (int) handle_box.y1; handle_box.x2 = (int) handle_box.x2; handle_box.y2 = (int) handle_box.y2; clutter_actor_allocate (priv->handle, &handle_box, flags); } }
/* Re-layout and allocate children of container we manage */ static void _xfdashboard_fill_box_layout_allocate(ClutterLayoutManager *inLayoutManager, ClutterContainer *inContainer, const ClutterActorBox *inAllocation, ClutterAllocationFlags inFlags) { XfdashboardFillBoxLayout *self; XfdashboardFillBoxLayoutPrivate *priv; ClutterActor *child; ClutterActorIter iter; gfloat parentWidth, parentHeight; gfloat homogeneousSize; gfloat x, y, w, h; gfloat aspectRatio; ClutterActorBox childAllocation; g_return_if_fail(XFDASHBOARD_IS_FILL_BOX_LAYOUT(inLayoutManager)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); self=XFDASHBOARD_FILL_BOX_LAYOUT(inLayoutManager); priv=self->priv; /* Get dimension of allocation */ parentWidth=clutter_actor_box_get_width(inAllocation); parentHeight=clutter_actor_box_get_height(inAllocation); /* If homogeneous determine sizes for all children */ if(priv->isHomogeneous==TRUE) { if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { _xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, &homogeneousSize, NULL, NULL); } else { _xfdashboard_fill_box_layout_get_largest_sizes(self, inContainer, NULL, NULL, NULL, &homogeneousSize); } } /* Iterate through children and set their sizes */ x=y=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { /* Only set sizes on visible children */ if(!clutter_actor_is_visible(child)) continue; /* Calculate and set new allocation of child */ if(priv->isHomogeneous==FALSE) { clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &w, &h); if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { aspectRatio=w/h; h=parentHeight; w=h*aspectRatio; } else { aspectRatio=h/w; w=parentWidth; h=w*aspectRatio; } } else { if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) { w=homogeneousSize; h=parentHeight; } else { w=parentWidth; h=homogeneousSize; } } /* Set new allocation of child */ childAllocation.x1=ceil(x); childAllocation.y1=ceil(y); childAllocation.x2=ceil(childAllocation.x1+w); childAllocation.y2=ceil(childAllocation.y1+h); clutter_actor_allocate(child, &childAllocation, inFlags); /* Set up for next child */ if(priv->orientation==CLUTTER_ORIENTATION_HORIZONTAL) x+=(w+priv->spacing); else y+=(h+priv->spacing); } }
static void mx_label_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxLabelPrivate *priv = MX_LABEL (actor)->priv; gboolean label_did_fade = priv->label_should_fade; ClutterActorClass *parent_class; ClutterActorBox child_box; gboolean x_fill, y_fill; gfloat avail_width; parent_class = CLUTTER_ACTOR_CLASS (mx_label_parent_class); parent_class->allocate (actor, box, flags); mx_widget_get_available_area (MX_WIDGET (actor), box, &child_box); avail_width = child_box.x2 - child_box.x1; /* The default behaviour of ClutterText is to align to the * top-left when it gets more space than is needed. Because * of this behaviour, if we're aligning to the left, we can * assign all our horizontal space to the label without * measuring it (i.e. x-fill), and the same applies for * aligning to the top and vertical space. */ x_fill = (priv->x_align == MX_ALIGN_START) ? TRUE : FALSE; y_fill = (priv->y_align == MX_ALIGN_START) ? TRUE : FALSE; mx_allocate_align_fill (priv->label, &child_box, priv->x_align, priv->y_align, x_fill, y_fill); priv->label_should_fade = FALSE; if (priv->fade_out) { /* If we're fading out, make sure the label has its full width * allocated. This ensures that the offscreen effect has the full * label inside its texture. */ gfloat label_width; clutter_actor_get_preferred_width (priv->label, -1, NULL, &label_width); if (label_width > avail_width) { priv->label_should_fade = TRUE; child_box.x2 = child_box.x1 + label_width; } mx_fade_effect_set_bounds (MX_FADE_EFFECT (priv->fade_effect), 0, 0, MIN (label_width, avail_width), 0); } /* Allocate the label */ clutter_actor_allocate (priv->label, &child_box, flags); if (priv->show_tooltip) { PangoLayout *layout; const gchar *text; layout = clutter_text_get_layout (CLUTTER_TEXT (priv->label)); if (pango_layout_is_ellipsized (layout)) text = clutter_text_get_text (CLUTTER_TEXT (priv->label)); else text = NULL; mx_widget_set_tooltip_text (MX_WIDGET (actor), text); } /* Animate in/out the faded end of the label */ if (label_did_fade != priv->label_should_fade) { /* Begin/reverse the fading timeline when necessary */ if (priv->label_should_fade) clutter_timeline_set_direction (priv->fade_timeline, CLUTTER_TIMELINE_FORWARD); else clutter_timeline_set_direction (priv->fade_timeline, CLUTTER_TIMELINE_BACKWARD); if (!clutter_timeline_is_playing (priv->fade_timeline)) clutter_timeline_rewind (priv->fade_timeline); clutter_timeline_start (priv->fade_timeline); } }
static void mx_menu_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { gint i; MxPadding padding; ClutterActorBox child_box; MxMenuPrivate *priv = MX_MENU (actor)->priv; gfloat available_h = box->y2-box->y1; /* * first of all, we have to check if the allocated height is our * natural height... */ gfloat menu_nat_h; mx_menu_get_preferred_height (actor, box->x2-box->x1, NULL, &menu_nat_h); if (available_h < menu_nat_h) { /* * ...if not, we have to draw 2 buttons in order to let the * user be able to navigate in the whole menu. */ priv->scrolling_mode = TRUE; } else { priv->scrolling_mode = FALSE; } /* Allocate children */ mx_widget_get_padding (MX_WIDGET (actor), &padding); child_box.x1 = padding.left; child_box.y1 = padding.top; child_box.x2 = box->x2 - box->x1 - padding.right; gfloat down_but_height; clutter_actor_get_preferred_height (priv->down_button, child_box.x2 - child_box.x1, NULL, &down_but_height); if (priv->scrolling_mode) { clutter_actor_get_preferred_height (priv->up_button, child_box.x2 - child_box.x1, NULL, &child_box.y2); child_box.y2 += child_box.y1; clutter_actor_allocate (priv->up_button, &child_box, flags); child_box.y1 = child_box.y2 + 1; available_h -= down_but_height; } for (i = priv->id_offset; i < priv->children->len; i++) { gfloat natural_height; MxMenuChild *child = &g_array_index (priv->children, MxMenuChild, i); clutter_actor_get_preferred_height (CLUTTER_ACTOR (child->box), child_box.x2 - child_box.x1, NULL, &natural_height); child_box.y2 = child_box.y1 + natural_height; if (child_box.y2 >= available_h) { priv->last_shown_id = i-1; break; } clutter_actor_allocate (CLUTTER_ACTOR (child->box), &child_box, flags); child_box.y1 = child_box.y2 + 1; } if (priv->children->len == i) { priv->last_shown_id = i-1; } if (priv->scrolling_mode) { child_box.y2 = child_box.y1 + down_but_height; clutter_actor_allocate (priv->down_button, &child_box, flags); } /* Chain up and allocate background */ CLUTTER_ACTOR_CLASS (mx_menu_parent_class)->allocate (actor, box, flags); }
static void tidy_grid_allocate (ClutterActor *self, const ClutterActorBox *box, gboolean absolute_origin_changed) { TidyGrid *layout = (TidyGrid *) self; TidyGridPrivate *priv = layout->priv; ClutterUnit current_a; ClutterUnit current_b; ClutterUnit next_b; ClutterUnit agap; ClutterUnit bgap; gboolean homogenous_a; gboolean homogenous_b; gdouble aalign; gdouble balign; current_a = current_b = next_b = 0; GList *iter; /* chain up to set actor->allocation */ CLUTTER_ACTOR_CLASS (tidy_grid_parent_class) ->allocate (self, box, absolute_origin_changed); priv->alloc_width = box->x2 - box->x1; priv->alloc_height = box->y2 - box->y1; priv->absolute_origin_changed = absolute_origin_changed; /* Make sure we have calculated the preferred size */ /* what does this do? */ clutter_actor_get_preferred_size (self, NULL, NULL, NULL, NULL); if (priv->column_major) { priv->a_wrap = priv->alloc_height; homogenous_b = priv->homogenous_columns; homogenous_a = priv->homogenous_rows; aalign = priv->valign; balign = priv->halign; agap = priv->row_gap; bgap = priv->column_gap; } else { priv->a_wrap = priv->alloc_width; homogenous_a = priv->homogenous_columns; homogenous_b = priv->homogenous_rows; aalign = priv->halign; balign = priv->valign; agap = priv->column_gap; bgap = priv->row_gap; } priv->max_extent_a = 0; priv->max_extent_b = 0; priv->first_of_batch = TRUE; if (homogenous_a || homogenous_b) { for (iter = priv->list; iter; iter = iter->next) { ClutterActor *child = iter->data; ClutterUnit natural_width; ClutterUnit natural_height; /* each child will get as much space as they require */ clutter_actor_get_preferred_size (CLUTTER_ACTOR (child), NULL, NULL, &natural_width, &natural_height); if (natural_width > priv->max_extent_a) priv->max_extent_a = natural_width; if (natural_height > priv->max_extent_b) priv->max_extent_b = natural_width; } } if (priv->column_major) { ClutterUnit temp = priv->max_extent_a; priv->max_extent_a = priv->max_extent_b; priv->max_extent_b = temp; } for (iter = priv->list; iter; iter=iter->next) { ClutterActor *child = iter->data; ClutterUnit natural_a; ClutterUnit natural_b; /* each child will get as much space as they require */ clutter_actor_get_preferred_size (CLUTTER_ACTOR (child), NULL, NULL, &natural_a, &natural_b); if (priv->column_major) /* swap axes around if column is major */ { ClutterUnit temp = natural_a; natural_a = natural_b; natural_b = temp; } /* if the child is overflowing, we wrap to next line */ if (current_a + natural_a > priv->a_wrap || (homogenous_a && current_a + priv->max_extent_a > priv->a_wrap)) { current_b = next_b + bgap; current_a = 0; next_b = current_b + bgap; priv->first_of_batch = TRUE; } if (priv->end_align && priv->first_of_batch) { current_a = compute_row_start (iter, current_a, priv); priv->first_of_batch = FALSE; } if (next_b-current_b < natural_b) next_b = current_b + natural_b; { ClutterUnit row_height; ClutterActorBox child_box; if (homogenous_b) { row_height = priv->max_extent_b; } else { row_height = compute_row_height (iter, next_b-current_b, current_a, priv); } if (homogenous_a) { child_box.x1 = current_a + (priv->max_extent_a-natural_a) * aalign; child_box.x2 = child_box.x1 + natural_a; } else { child_box.x1 = current_a; child_box.x2 = child_box.x1 + natural_a; } child_box.y1 = current_b + (row_height-natural_b) * balign; child_box.y2 = child_box.y1 + natural_b; if (priv->column_major) { ClutterUnit temp = child_box.x1; child_box.x1 = child_box.y1; child_box.y1 = temp; temp = child_box.x2; child_box.x2 = child_box.y2; child_box.y2 = temp; } /* update the allocation */ clutter_actor_allocate (CLUTTER_ACTOR (child), &child_box, absolute_origin_changed); if (homogenous_a) { current_a += priv->max_extent_a + agap; } else { current_a += natural_a + agap; } } } }
static void clutter_table_layout_allocate (ClutterLayoutManager *layout, ClutterContainer *container, const ClutterActorBox *box, ClutterAllocationFlags flags) { ClutterTableLayout *self = CLUTTER_TABLE_LAYOUT (layout); ClutterTableLayoutPrivate *priv = self->priv; ClutterActor *actor, *child; gint row_spacing, col_spacing; gint i; DimensionData *rows, *columns; update_row_col (self, container); if (priv->n_cols < 1 || priv->n_rows < 1) return; actor = CLUTTER_ACTOR (container); if (clutter_actor_get_n_children (actor) == 0) return; col_spacing = (priv->col_spacing); row_spacing = (priv->row_spacing); calculate_table_dimensions (self, container, box->x2 - box->x1, box->y2 - box->y1); rows = (DimensionData *) (void *) priv->rows->data; columns = (DimensionData *) (void *) priv->columns->data; for (child = clutter_actor_get_first_child (actor); child != NULL; child = clutter_actor_get_next_sibling (child)) { gint row, col, row_span, col_span; gint col_width, row_height; ClutterTableChild *meta; ClutterActorBox childbox; gint child_x, child_y; if (!CLUTTER_ACTOR_IS_VISIBLE (child)) continue; meta = CLUTTER_TABLE_CHILD (clutter_layout_manager_get_child_meta (layout, container, child)); /* get child properties */ col = meta->col; row = meta->row; row_span = meta->row_span; col_span = meta->col_span; /* initialise the width and height */ col_width = columns[col].final_size; row_height = rows[row].final_size; /* Add the widths of the spanned columns: * * First check that we have a non-zero span. Then we loop over each of * the columns that we're spanning but we stop short if we go past the * number of columns in the table. This is necessary to avoid accessing * uninitialised memory. We add the spacing in here too since we only * want to add as much spacing as times we successfully span. */ if (col + col_span > priv->n_cols) g_warning (G_STRLOC ": column-span exceeds number of columns"); if (row + row_span > priv->n_rows) g_warning (G_STRLOC ": row-span exceeds number of rows"); if (col_span > 1) { for (i = col + 1; i < col + col_span && i < priv->n_cols; i++) { col_width += columns[i].final_size; col_width += col_spacing; } } /* add the height of the spanned rows */ if (row_span > 1) { for (i = row + 1; i < row + row_span && i < priv->n_rows; i++) { row_height += rows[i].final_size; row_height += row_spacing; } } /* calculate child x */ child_x = clutter_actor_box_get_x (box); for (i = 0; i < col; i++) { if (columns[i].visible) { child_x += columns[i].final_size; child_x += col_spacing; } } /* calculate child y */ child_y = clutter_actor_box_get_y (box); for (i = 0; i < row; i++) { if (rows[i].visible) { child_y += rows[i].final_size; child_y += row_spacing; } } /* set up childbox */ childbox.x1 = (float) child_x; childbox.x2 = (float) MAX (0, child_x + col_width); childbox.y1 = (float) child_y; childbox.y2 = (float) MAX (0, child_y + row_height); clutter_actor_allocate (child, &childbox, flags); } }
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); }
static void mx_table_preferred_allocate (ClutterActor *self, const ClutterActorBox *box, gboolean flags) { gint row_spacing, col_spacing; gint i; MxTable *table; MxTablePrivate *priv; MxPadding padding; DimensionData *rows, *columns; ClutterActorIter iter; ClutterActor *child; table = MX_TABLE (self); priv = MX_TABLE (self)->priv; mx_widget_get_padding (MX_WIDGET (self), &padding); col_spacing = (priv->col_spacing); row_spacing = (priv->row_spacing); mx_table_calculate_dimensions (table, box->x2 - box->x1, box->y2 - box->y1); rows = &g_array_index (priv->rows, DimensionData, 0); columns = &g_array_index (priv->columns, DimensionData, 0); clutter_actor_iter_init (&iter, self); while (clutter_actor_iter_next (&iter, &child)) { gint row, col, row_span, col_span; gint col_width, row_height; MxTableChild *meta; ClutterActorBox childbox; gint child_x, child_y; gdouble x_align_d, y_align_d; gboolean x_fill, y_fill; MxAlign x_align, y_align; meta = (MxTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child); if (!CLUTTER_ACTOR_IS_VISIBLE (child)) continue; /* get child properties */ col = meta->col; row = meta->row; row_span = meta->row_span; col_span = meta->col_span; x_align_d = meta->x_align; y_align_d = meta->y_align; x_fill = meta->x_fill; y_fill = meta->y_fill; /* Convert to MxAlign */ if (x_align_d < 1.0 / 3.0) x_align = MX_ALIGN_START; else if (x_align_d > 2.0 / 3.0) x_align = MX_ALIGN_END; else x_align = MX_ALIGN_MIDDLE; if (y_align_d < 1.0 / 3.0) y_align = MX_ALIGN_START; else if (y_align_d > 2.0 / 3.0) y_align = MX_ALIGN_END; else y_align = MX_ALIGN_MIDDLE; /* initialise the width and height */ col_width = columns[col].final_size; row_height = rows[row].final_size; /* Add the widths of the spanned columns: * * First check that we have a non-zero span. Then we loop over each of * the columns that we're spanning but we stop short if we go past the * number of columns in the table. This is necessary to avoid accessing * uninitialised memory. We add the spacing in here too since we only * want to add as much spacing as times we successfully span. */ if (col + col_span > priv->n_cols) g_warning ("MxTable: col-span exceeds number of columns"); if (row + row_span > priv->n_rows) g_warning ("MxTable: row-span exceeds number of rows"); if (col_span > 1) { for (i = col + 1; i < col + col_span && i < priv->n_cols; i++) { col_width += columns[i].final_size; col_width += col_spacing; } } /* add the height of the spanned rows */ if (row_span > 1) { for (i = row + 1; i < row + row_span && i < priv->n_rows; i++) { row_height += rows[i].final_size; row_height += row_spacing; } } /* calculate child x */ child_x = (int) padding.left; for (i = 0; i < col; i++) { if (columns[i].is_visible) { child_x += columns[i].final_size; child_x += col_spacing; } } /* calculate child y */ child_y = (int) padding.top; for (i = 0; i < row; i++) { if (rows[i].is_visible) { child_y += rows[i].final_size; child_y += row_spacing; } } /* set up childbox */ childbox.x1 = (float) child_x; childbox.x2 = (float) MAX (0, child_x + col_width); childbox.y1 = (float) child_y; childbox.y2 = (float) MAX (0, child_y + row_height); mx_allocate_align_fill (child, &childbox, x_align, y_align, x_fill, y_fill); clutter_actor_allocate (child, &childbox, flags); } }
static void st_table_preferred_allocate (ClutterActor *self, const ClutterActorBox *content_box, gboolean flags) { GList *list, *children; gint row_spacing, col_spacing; gint i; StTable *table; StTablePrivate *priv; gboolean ltr; DimensionData *rows, *columns; table = ST_TABLE (self); priv = ST_TABLE (self)->priv; col_spacing = (priv->col_spacing); row_spacing = (priv->row_spacing); st_table_calculate_dimensions (table, content_box->x2 - content_box->x1, content_box->y2 - content_box->y1); ltr = (st_widget_get_direction (ST_WIDGET (self)) == ST_TEXT_DIRECTION_LTR); rows = &g_array_index (priv->rows, DimensionData, 0); columns = &g_array_index (priv->columns, DimensionData, 0); children = st_container_get_children_list (ST_CONTAINER (self)); for (list = children; list; list = list->next) { gint row, col, row_span, col_span; gint col_width, row_height; StTableChild *meta; ClutterActor *child; ClutterActorBox childbox; gint child_x, child_y; StAlign x_align, y_align; gboolean x_fill, y_fill; child = CLUTTER_ACTOR (list->data); meta = (StTableChild *) clutter_container_get_child_meta (CLUTTER_CONTAINER (self), child); if (!meta->allocate_hidden && !CLUTTER_ACTOR_IS_VISIBLE (child)) continue; /* get child properties */ col = meta->col; row = meta->row; row_span = meta->row_span; col_span = meta->col_span; x_align = meta->x_align; y_align = meta->y_align; x_fill = meta->x_fill; y_fill = meta->y_fill; /* initialise the width and height */ col_width = columns[col].final_size; row_height = rows[row].final_size; /* Add the widths of the spanned columns: * * First check that we have a non-zero span. Then we loop over each of * the columns that we're spanning but we stop short if we go past the * number of columns in the table. This is necessary to avoid accessing * uninitialised memory. We add the spacing in here too since we only * want to add as much spacing as times we successfully span. */ if (col + col_span > priv->n_cols) g_warning ("StTable: the child at %d,%d's col-span, %d, exceeds number of columns, %d", col, row, col_span, priv->n_cols); if (row + row_span > priv->n_rows) g_warning ("StTable: the child at %d,%d's row-span, %d, exceeds number of rows, %d", col, row, row_span, priv->n_rows); if (col_span > 1) { for (i = col + 1; i < col + col_span && i < priv->n_cols; i++) { col_width += columns[i].final_size; col_width += col_spacing; } } /* add the height of the spanned rows */ if (row_span > 1) { for (i = row + 1; i < row + row_span && i < priv->n_rows; i++) { row_height += rows[i].final_size; row_height += row_spacing; } } /* calculate child x */ if (ltr) { child_x = (int) content_box->x1 + col_spacing * col; for (i = 0; i < col; i++) child_x += columns[i].final_size; } else { child_x = (int) content_box->x2 - col_spacing * col; for (i = 0; i < col; i++) child_x -= columns[i].final_size; } /* calculate child y */ child_y = (int) content_box->y1 + row_spacing * row; for (i = 0; i < row; i++) child_y += rows[i].final_size; /* set up childbox */ if (ltr) { childbox.x1 = (float) child_x; childbox.x2 = (float) MAX (0, child_x + col_width); } else { childbox.x2 = (float) child_x; childbox.x1 = (float) MAX (0, child_x - col_width); } childbox.y1 = (float) child_y; childbox.y2 = (float) MAX (0, child_y + row_height); _st_allocate_fill (ST_WIDGET (self), child, &childbox, x_align, y_align, x_fill, y_fill); clutter_actor_allocate (child, &childbox, flags); } }
static void scroll_bar_allocate_children (StScrollBar *bar, const ClutterActorBox *box, ClutterAllocationFlags flags) { StScrollBarPrivate *priv = bar->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (bar)); ClutterActorBox content_box, trough_box; st_theme_node_get_content_box (theme_node, box, &content_box); if (priv->vertical) { trough_box.x1 = content_box.x1; trough_box.y1 = content_box.y1; trough_box.x2 = content_box.x2; trough_box.y2 = content_box.y2; clutter_actor_allocate (priv->trough, &trough_box, flags); } else { trough_box.x1 = content_box.x1; trough_box.y1 = content_box.y1; trough_box.x2 = content_box.x2; trough_box.y2 = content_box.y2; clutter_actor_allocate (priv->trough, &trough_box, flags); } if (priv->adjustment) { float handle_size, position, avail_size; gdouble value, lower, upper, page_size, increment, min_size, max_size; ClutterActorBox handle_box = { 0, }; st_adjustment_get_values (priv->adjustment, &value, &lower, &upper, NULL, NULL, &page_size); if ((upper == lower) || (page_size >= (upper - lower))) increment = 1.0; else increment = page_size / (upper - lower); min_size = 32.; st_theme_node_lookup_length (theme_node, "min-size", FALSE, &min_size); max_size = G_MAXINT16; st_theme_node_lookup_length (theme_node, "max-size", FALSE, &max_size); if (upper - lower - page_size <= 0) position = 0; else position = (value - lower) / (upper - lower - page_size); if (priv->vertical) { avail_size = content_box.y2 - content_box.y1; handle_size = increment * avail_size; handle_size = CLAMP (handle_size, min_size, max_size); handle_box.x1 = content_box.x1; handle_box.y1 = content_box.y1 + position * (avail_size - handle_size); handle_box.x2 = content_box.x2; handle_box.y2 = handle_box.y1 + handle_size; } else { avail_size = content_box.x2 - content_box.x1; handle_size = increment * avail_size; handle_size = CLAMP (handle_size, min_size, max_size); handle_box.x1 = content_box.x1 + position * (avail_size - handle_size); handle_box.y1 = content_box.y1; handle_box.x2 = handle_box.x1 + handle_size; handle_box.y2 = content_box.y2; } clutter_actor_allocate (priv->handle, &handle_box, flags); } }
static void shell_overflow_list_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { ShellOverflowList *self = SHELL_OVERFLOW_LIST (actor); ShellOverflowListPrivate *priv = self->priv; GList *children, *iter; int n_pages; int n_children; int n_fits; float width; float curheight; float avail_height; gboolean overflow; /* chain up to set actor->allocation */ (CLUTTER_ACTOR_CLASS (g_type_class_peek (clutter_actor_get_type ())))->allocate (actor, box, flags); width = box->x2 - box->x1; curheight = 0; avail_height = box->y2 - box->y1; children = clutter_container_get_children (CLUTTER_CONTAINER (self)); n_children = g_list_length (children); n_fits = 0; n_pages = 1; overflow = FALSE; for (iter = children; iter; iter = iter->next) { ClutterActor *actor = CLUTTER_ACTOR (iter->data); ClutterActorBox child_box; if ((curheight + priv->item_height) > avail_height) { overflow = TRUE; curheight = 0; n_pages++; } else if (!overflow) n_fits++; child_box.x1 = 0; child_box.x2 = width; child_box.y1 = curheight; child_box.y2 = child_box.y1 + priv->item_height; clutter_actor_allocate (actor, &child_box, flags); curheight += priv->item_height; if (iter != children) curheight += priv->spacing; } priv->items_per_page = n_fits; if (n_pages != priv->n_pages) { priv->n_pages = n_pages; g_object_notify (G_OBJECT (self), "n-pages"); } g_list_free (children); }
/* Allocate position and size of actor and its children */ static void _xfdashboard_viewpad_allocate(ClutterActor *self, const ClutterActorBox *inBox, ClutterAllocationFlags inFlags) { XfdashboardViewpadPrivate *priv=XFDASHBOARD_VIEWPAD(self)->priv; ClutterActorClass *actorClass=CLUTTER_ACTOR_CLASS(xfdashboard_viewpad_parent_class); gfloat viewWidth, viewHeight; gfloat vScrollbarWidth, vScrollbarHeight; gfloat hScrollbarWidth, hScrollbarHeight; gboolean hScrollbarVisible, vScrollbarVisible; ClutterActorBox *box; gfloat x, y, w, h; /* Chain up to store the allocation of the actor */ if(actorClass->allocate) actorClass->allocate(self, inBox, inFlags); /* Initialize largest possible allocation for view and determine * real size of view to show. The real size is used to determine * scroll bar visibility if policy is automatic */ viewWidth=clutter_actor_box_get_width(inBox); viewHeight=clutter_actor_box_get_height(inBox); /* Determine visibility of scroll bars */ hScrollbarVisible=FALSE; if(priv->hScrollbarPolicy==XFDASHBOARD_POLICY_ALWAYS || (priv->hScrollbarPolicy==XFDASHBOARD_POLICY_AUTOMATIC && xfdashboard_scrollbar_get_range(XFDASHBOARD_SCROLLBAR(priv->hScrollbar))>viewWidth)) { hScrollbarVisible=TRUE; } if(xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_HORIZONTAL || xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_BOTH) { hScrollbarVisible=FALSE; } vScrollbarVisible=FALSE; if(priv->vScrollbarPolicy==XFDASHBOARD_POLICY_ALWAYS || (priv->vScrollbarPolicy==XFDASHBOARD_POLICY_AUTOMATIC && xfdashboard_scrollbar_get_range(XFDASHBOARD_SCROLLBAR(priv->vScrollbar))>viewHeight)) { vScrollbarVisible=TRUE; } if(xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_VERTICAL || xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))==XFDASHBOARD_FIT_MODE_BOTH) { vScrollbarVisible=FALSE; } /* Set allocation for visible scroll bars */ vScrollbarWidth=0.0f; vScrollbarHeight=viewHeight; clutter_actor_get_preferred_width(priv->vScrollbar, -1, NULL, &vScrollbarWidth); hScrollbarWidth=viewWidth; hScrollbarHeight=0.0f; clutter_actor_get_preferred_height(priv->hScrollbar, -1, NULL, &hScrollbarHeight); if(hScrollbarVisible && vScrollbarVisible) { vScrollbarHeight-=hScrollbarHeight; hScrollbarWidth-=vScrollbarWidth; } if(vScrollbarVisible==FALSE) box=clutter_actor_box_new(0, 0, 0, 0); else box=clutter_actor_box_new(viewWidth-vScrollbarWidth, 0, viewWidth, vScrollbarHeight); clutter_actor_allocate(priv->vScrollbar, box, inFlags); clutter_actor_box_free(box); if(hScrollbarVisible==FALSE) box=clutter_actor_box_new(0, 0, 0, 0); else box=clutter_actor_box_new(0, viewHeight-hScrollbarHeight, hScrollbarWidth, viewHeight); clutter_actor_allocate(priv->hScrollbar, box, inFlags); clutter_actor_box_free(box); /* Reduce allocation for view by any visible scroll bar * and set allocation and clipping of view */ if(priv->activeView) { /* Set allocation */ if(vScrollbarVisible) viewWidth-=vScrollbarWidth; if(hScrollbarVisible) viewHeight-=hScrollbarHeight; x=y=0.0f; if(clutter_actor_has_clip(CLUTTER_ACTOR(priv->activeView))) { clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, NULL, NULL); } switch(xfdashboard_view_get_fit_mode(XFDASHBOARD_VIEW(priv->activeView))) { case XFDASHBOARD_FIT_MODE_BOTH: w=viewWidth; h=viewHeight; break; case XFDASHBOARD_FIT_MODE_HORIZONTAL: w=viewWidth; clutter_actor_get_preferred_height(CLUTTER_ACTOR(priv->activeView), w, NULL, &h); break; case XFDASHBOARD_FIT_MODE_VERTICAL: h=viewHeight; clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->activeView), h, NULL, &w); break; default: clutter_actor_get_preferred_size(CLUTTER_ACTOR(priv->activeView), NULL, NULL, &w, &h); break; } box=clutter_actor_box_new(0, 0, w, h); clutter_actor_allocate(CLUTTER_ACTOR(priv->activeView), box, inFlags); clutter_actor_box_free(box); clutter_actor_set_clip(CLUTTER_ACTOR(priv->activeView), x, y, viewWidth, viewHeight); } /* Only set value if it changes */ if(priv->hScrollbarVisible!=hScrollbarVisible) { /* Set new value */ priv->hScrollbarVisible=hScrollbarVisible; /* Notify about property change */ g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_HSCROLLBAR_VISIBLE]); } if(priv->vScrollbarVisible!=vScrollbarVisible) { /* Set new value */ priv->vScrollbarVisible=vScrollbarVisible; /* Notify about property change */ g_object_notify_by_pspec(G_OBJECT(self), XfdashboardViewpadProperties[PROP_VSCROLLBAR_VISIBLE]); } }
static void mx_slider_allocate_fill_handle (MxSlider *self, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxSliderPrivate *priv = self->priv; MxPadding padding; ClutterActorBox bar_box; ClutterActorBox fill_box; ClutterActorBox buffer_box; ClutterActorBox handle_box; guint handle_width_2; if (box == NULL) { clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &bar_box); box = &bar_box; } mx_widget_get_padding (MX_WIDGET (self), &padding); handle_width_2 = priv->handle_width >> 1; /* fill */ fill_box.x1 = padding.left; fill_box.y1 = priv->trough_box_y1; fill_box.x2 = ((box->x2 - box->x1 - padding.left - padding.right - priv->handle_width) * priv->value) + padding.left + handle_width_2; fill_box.x2 = CLAMP (fill_box.x2, priv->handle_middle_start, priv->handle_middle_end); fill_box.y2 = priv->trough_box_y2; clutter_actor_allocate (priv->fill, &fill_box, flags); /* buffer */ buffer_box.x1 = padding.left; buffer_box.y1 = priv->trough_box_y1; buffer_box.x2 = buffer_box.x1 + ((box->x2 - box->x1 - padding.left - padding.right) * priv->buffer_value); buffer_box.y2 = priv->trough_box_y2; clutter_actor_allocate (priv->buffer, &buffer_box, flags); /* handle */ handle_box.x1 = fill_box.x2 - handle_width_2; handle_box.x2 = handle_box.x1 + priv->handle_width; /* If the handle height is unset, occupy all available space. * Otherwise we want it to be centred in the trough. */ if (priv->handle_height == 0) { handle_box.y1 = padding.top; handle_box.y2 = (box->y2 - box->y1) - padding.bottom; } else { handle_box.y1 = (box->y2 - box->y1 - priv->handle_height) / 2.f; handle_box.y2 = handle_box.y1 + priv->handle_height; } /* snap to pixel */ handle_box.x1 = (int) handle_box.x1; handle_box.y1 = (int) handle_box.y1; handle_box.x2 = (int) handle_box.x2; handle_box.y2 = (int) handle_box.y2; clutter_actor_allocate (priv->handle, &handle_box, flags); }
static void clutter_flow_layout_allocate (ClutterLayoutManager *manager, ClutterContainer *container, const ClutterActorBox *allocation, ClutterAllocationFlags flags) { ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; GList *l, *children = clutter_container_get_children (container); gfloat avail_width, avail_height; gfloat item_x, item_y; gint line_item_count; gint items_per_line; gint line_index; if (children == NULL) return; clutter_actor_box_get_size (allocation, &avail_width, &avail_height); items_per_line = compute_lines (CLUTTER_FLOW_LAYOUT (manager), avail_width, avail_height); item_x = item_y = 0; line_item_count = 0; line_index = 0; for (l = children; l != NULL; l = l->next) { ClutterActor *child = l->data; ClutterActorBox child_alloc; gfloat item_width, item_height; gfloat new_x, new_y; if (!CLUTTER_ACTOR_IS_VISIBLE (child)) continue; new_x = new_y = 0; if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) { if (line_item_count == items_per_line && line_item_count > 0) { item_y += g_array_index (priv->line_natural, gfloat, line_index); if (line_index >= 0) item_y += priv->row_spacing; line_item_count = 0; line_index += 1; item_x = 0; } new_x = ((line_item_count + 1) * (avail_width + priv->col_spacing)) / items_per_line; item_width = new_x - item_x - priv->col_spacing; item_height = g_array_index (priv->line_natural, gfloat, line_index); if (!priv->is_homogeneous) { gfloat child_min, child_natural; clutter_actor_get_preferred_width (child, item_height, &child_min, &child_natural); item_width = MIN (item_width, child_natural); clutter_actor_get_preferred_height (child, item_width, &child_min, &child_natural); item_height = MIN (item_height, child_natural); } } else { if (line_item_count == items_per_line && line_item_count > 0) { item_x += g_array_index (priv->line_natural, gfloat, line_index); if (line_index >= 0) item_x += priv->col_spacing; line_item_count = 0; line_index += 1; item_y = 0; } new_y = ((line_item_count + 1) * (avail_height + priv->row_spacing)) / items_per_line; item_height = new_y - item_y - priv->row_spacing; item_width = g_array_index (priv->line_natural, gfloat, line_index); if (!priv->is_homogeneous) { gfloat child_min, child_natural; clutter_actor_get_preferred_width (child, item_height, &child_min, &child_natural); item_width = MIN (item_width, child_natural); clutter_actor_get_preferred_height (child, item_width, &child_min, &child_natural); item_height = MIN (item_height, child_natural); } } CLUTTER_NOTE (LAYOUT, "flow[line:%d, item:%d/%d] =" "{ %.2f, %.2f, %.2f, %.2f }", line_index, line_item_count + 1, items_per_line, item_x, item_y, item_width, item_height); child_alloc.x1 = ceil (item_x); child_alloc.y1 = ceil (item_y); child_alloc.x2 = ceil (child_alloc.x1 + item_width); child_alloc.y2 = ceil (child_alloc.y1 + item_height); clutter_actor_allocate (child, &child_alloc, flags); if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) item_x = new_x; else item_y = new_y; line_item_count += 1; } g_list_free (children); }
static void mx_combo_box_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxComboBoxPrivate *priv = MX_COMBO_BOX (actor)->priv; MxPadding padding; gfloat x, y, width, height; gfloat min_menu_h, nat_menu_h; gfloat label_h; gfloat nat_icon_h, icon_h, icon_w; gfloat nat_marker_h, marker_h, marker_w; ClutterActorBox childbox; ClutterActor *menu, *stage; CLUTTER_ACTOR_CLASS (mx_combo_box_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); x = padding.left; y = padding.top; width = box->x2 - box->x1 - padding.left - padding.right; height = box->y2 - box->y1 - padding.top - padding.bottom; icon_w = marker_w = 0; if (priv->icon) { /* Allocate the icon, if there is one, the space not used by the text */ clutter_actor_get_preferred_height (priv->icon, -1, NULL, &nat_icon_h); if (height >= nat_icon_h) { icon_h = nat_icon_h; clutter_actor_get_preferred_width (priv->icon, -1, NULL, &icon_w); } else { icon_h = height; clutter_actor_get_preferred_width (priv->icon, icon_h, NULL, &icon_w); } childbox.x1 = (int)(x); childbox.y1 = (int)(y + (height - icon_h) / 2); childbox.x2 = (int)(x + icon_w); childbox.y2 = (int)(childbox.y1 + icon_h); clutter_actor_allocate (priv->icon, &childbox, flags); icon_w += priv->spacing; } if (priv->marker) { clutter_actor_get_preferred_height (priv->marker, -1, NULL, &nat_marker_h); if (height >= nat_marker_h) { marker_h = nat_marker_h; clutter_actor_get_preferred_width (priv->marker, -1, NULL, &marker_w); } else { marker_h = height; clutter_actor_get_preferred_width (priv->marker, marker_h, NULL, &marker_w); } childbox.x2 = (int)(x + width); childbox.x1 = (int)(childbox.x2 - marker_w); childbox.y1 = (int)(y + (height - marker_h) / 2); childbox.y2 = (int)(childbox.y1 + marker_h); clutter_actor_allocate (priv->marker, &childbox, flags); marker_w += priv->spacing; } clutter_actor_get_preferred_height (priv->label, -1, NULL, &label_h); childbox.x1 = (int)(x + icon_w); childbox.y1 = (int)(y + (height / 2 - label_h / 2)); childbox.x2 = (int)(x + width - marker_w); childbox.y2 = (int)(childbox.y1 + label_h); clutter_actor_allocate (priv->label, &childbox, flags); menu = (ClutterActor*) mx_widget_get_menu (MX_WIDGET (actor)); clutter_actor_get_preferred_height (menu, (box->x2 - box->x1), &min_menu_h, &nat_menu_h); childbox.x1 = 0; childbox.x2 = (box->x2 - box->x1); childbox.y1 = (box->y2 - box->y1); stage = clutter_actor_get_stage (actor); if (stage != NULL) { ClutterVertex point = { 0, }; gfloat stage_w, stage_h, combo_h = box->y2 - box->y1; clutter_actor_get_size (stage, &stage_w, &stage_h); point.y = combo_h + nat_menu_h; clutter_actor_apply_transform_to_point (actor, &point, &point); /* If the menu would appear off the stage, flip it around. */ if ((point.x < 0) || (point.x >= stage_w) || (point.y < 0) || (point.y >= stage_h)) { childbox.y1 = -nat_menu_h; } } childbox.y2 = childbox.y1 + nat_menu_h; clutter_actor_allocate (menu, &childbox, flags); }
static void scroll_bar_allocate_children (StScrollBar *bar, const ClutterActorBox *box, ClutterAllocationFlags flags) { StScrollBarPrivate *priv = bar->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (bar)); ClutterActorBox content_box, bw_box, fw_box, trough_box; gfloat bw_stepper_size, fw_stepper_size, min_size, natural_size; st_theme_node_get_content_box (theme_node, box, &content_box); if (priv->vertical) { gfloat width = content_box.x2 - content_box.x1; clutter_actor_get_preferred_height (priv->bw_stepper, width, &min_size, &natural_size); bw_stepper_size = MAX (min_size, natural_size); /* Backward stepper */ bw_box.x1 = content_box.x1; bw_box.y1 = content_box.y1; bw_box.x2 = content_box.x2; bw_box.y2 = bw_box.y1 + bw_stepper_size; clutter_actor_allocate (priv->bw_stepper, &bw_box, flags); clutter_actor_get_preferred_height (priv->fw_stepper, width, &min_size, &natural_size); fw_stepper_size = MAX (min_size, natural_size); /* Forward stepper */ fw_box.x1 = content_box.x1; fw_box.y1 = content_box.y2 - fw_stepper_size; fw_box.x2 = content_box.x2; fw_box.y2 = content_box.y2; clutter_actor_allocate (priv->fw_stepper, &fw_box, flags); /* Trough */ trough_box.x1 = content_box.x1; trough_box.y1 = content_box.y1 + bw_stepper_size; trough_box.x2 = content_box.x2; trough_box.y2 = content_box.y2 - fw_stepper_size; clutter_actor_allocate (priv->trough, &trough_box, flags); } else { gfloat height = content_box.y2 - content_box.y1; clutter_actor_get_preferred_width (priv->bw_stepper, height, &min_size, &natural_size); bw_stepper_size = MAX (min_size, natural_size); /* Backward stepper */ bw_box.x1 = content_box.x1; bw_box.y1 = content_box.y1; bw_box.x2 = bw_box.x1 + bw_stepper_size; bw_box.y2 = content_box.y2; clutter_actor_allocate (priv->bw_stepper, &bw_box, flags); clutter_actor_get_preferred_width (priv->fw_stepper, height, &min_size, &natural_size); fw_stepper_size = MAX (min_size, natural_size); /* Forward stepper */ fw_box.x1 = content_box.x2 - fw_stepper_size; fw_box.y1 = content_box.y1; fw_box.x2 = content_box.x2; fw_box.y2 = content_box.y2; clutter_actor_allocate (priv->fw_stepper, &fw_box, flags); /* Trough */ trough_box.x1 = content_box.x1 + bw_stepper_size; trough_box.y1 = content_box.y1; trough_box.x2 = content_box.x2 - fw_stepper_size; trough_box.y2 = content_box.y2; clutter_actor_allocate (priv->trough, &trough_box, flags); } if (priv->adjustment) { float handle_size, position, avail_size, stepper_size; gdouble value, lower, upper, page_size, increment, min_size, max_size; ClutterActorBox handle_box = { 0, }; stepper_size = bw_stepper_size + fw_stepper_size; st_adjustment_get_values (priv->adjustment, &value, &lower, &upper, NULL, NULL, &page_size); if ((upper == lower) || (page_size >= (upper - lower))) increment = 1.0; else increment = page_size / (upper - lower); min_size = 32.; st_theme_node_lookup_length (theme_node, "min-size", FALSE, &min_size); max_size = G_MAXINT16; st_theme_node_lookup_length (theme_node, "max-size", FALSE, &max_size); if (upper - lower - page_size <= 0) position = 0; else position = (value - lower) / (upper - lower - page_size); if (priv->vertical) { avail_size = content_box.y2 - content_box.y1 - stepper_size; handle_size = increment * avail_size; handle_size = CLAMP (handle_size, min_size, max_size); handle_box.x1 = content_box.x1; handle_box.y1 = bw_box.y2 + position * (avail_size - handle_size); handle_box.x2 = content_box.x2; handle_box.y2 = handle_box.y1 + handle_size; } else { avail_size = content_box.x2 - content_box.x1 - stepper_size; handle_size = increment * avail_size; handle_size = CLAMP (handle_size, min_size, max_size); handle_box.x1 = bw_box.x2 + position * (avail_size - handle_size); handle_box.y1 = content_box.y1; handle_box.x2 = handle_box.x1 + handle_size; handle_box.y2 = content_box.y2; } /* snap to pixel */ handle_box.x1 = (int) handle_box.x1; handle_box.y1 = (int) handle_box.y1; handle_box.x2 = (int) handle_box.x2; handle_box.y2 = (int) handle_box.y2; clutter_actor_allocate (priv->handle, &handle_box, flags); } }
static void mex_tile_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxPadding padding; ClutterActorBox child_box; gfloat available_width, available_height; ClutterEffect *fade; MexTilePrivate *priv = MEX_TILE (actor)->priv; CLUTTER_ACTOR_CLASS (mex_tile_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); available_width = box->x2 - box->x1 - padding.left - padding.right; available_height = box->y2 - box->y1 - padding.top - padding.bottom; if (priv->child) { gfloat child_width, full_width, full_height; clutter_actor_get_preferred_size (priv->child, NULL, NULL, &full_width, &full_height); child_box.y1 = padding.top; if (clutter_alpha_get_alpha (priv->important_alpha) < 0.5) { child_width = full_width * (available_height / full_height); if (child_width > available_width) child_width = available_width; child_box.y2 = child_box.y1 + available_height; /* When we're in unimportant state, make sure the label * doesn't overlap the image. */ if (available_height < full_height) available_width -= child_width * ((0.5 - clutter_alpha_get_alpha (priv->important_alpha)) * 2); } else { child_width = available_width; clutter_actor_set_clip_to_allocation ( actor, (full_height > available_height)); child_box.y2 = child_box.y1 + full_height; } child_box.x2 = box->x2 - box->x1 - padding.right; child_box.x1 = child_box.x2 - child_width; mx_allocate_align_fill (priv->child, &child_box, MX_ALIGN_MIDDLE, MX_ALIGN_MIDDLE, FALSE, FALSE); clutter_actor_allocate (priv->child, &child_box, flags); } /* Allocate Header */ if (priv->header_visible) { gfloat icon1_w, icon1_h, icon2_w, icon2_h, label_h, label_w, header_h; gfloat middle_w; if (priv->header_padding) { padding.top += priv->header_padding->top; padding.right += priv->header_padding->right; padding.bottom += priv->header_padding->bottom; padding.left += priv->header_padding->left; } clutter_actor_get_preferred_size (priv->box_layout, NULL, NULL, &label_w, &label_h); if (priv->icon1) clutter_actor_get_preferred_size (priv->icon1, NULL, NULL, &icon1_w, &icon1_h); else icon1_h = icon1_w = 0; if (priv->icon2) clutter_actor_get_preferred_size (priv->icon2, NULL, NULL, &icon2_w, &icon2_h); else icon2_h = icon2_w = 0; header_h = MAX (icon1_h, MAX (icon2_h, label_h)); /* primary icon */ if (priv->icon1) { child_box.y1 = padding.top + (header_h / 2.0) - (icon1_h / 2.0); child_box.x1 = padding.left; child_box.y2 = child_box.y1 + icon1_h; child_box.x2 = child_box.x1 + icon1_w; clutter_actor_allocate (priv->icon1, &child_box, flags); child_box.x1 += icon1_w + 8; } else child_box.x1 = padding.left; /* label */ child_box.x2 = child_box.x1 + label_w; child_box.y1 = (int) (padding.top + (header_h / 2.0) - (label_h / 2.0)); child_box.y2 = child_box.y1 + label_h; fade = clutter_actor_get_effect (priv->box_layout, "fade"); middle_w = available_width - icon1_w - icon2_w; if (priv->header_padding) middle_w -= priv->header_padding->left + priv->header_padding->right; clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (fade), !(middle_w > label_w)); mx_fade_effect_set_bounds (MX_FADE_EFFECT (fade), 0, 0, middle_w, 0); clutter_actor_allocate (priv->box_layout, &child_box, flags); /* secondary icon */ if (priv->icon2) { child_box.x2 = (box->x2 - box->x1) - padding.right; child_box.x1 = child_box.x2 - icon2_w; child_box.y1 = padding.top + (header_h / 2.0) - (icon2_h / 2.0); child_box.y2 = child_box.y1 + icon2_h; clutter_actor_allocate (priv->icon2, &child_box, flags); } priv->header_height = header_h; if (priv->header_padding) priv->header_height += priv->header_padding->top + priv->header_padding->bottom; } }
/* Re-layout and allocate children of container we manage */ static void _xfdashboard_scaled_table_layout_allocate(ClutterLayoutManager *self, ClutterContainer *inContainer, const ClutterActorBox *inAllocation, ClutterAllocationFlags inFlags) { XfdashboardScaledTableLayoutPrivate *priv; gint row, col; ClutterActor *child; ClutterActorIter iter; gfloat cellWidth, cellHeight; gfloat childWidth, childHeight; gfloat scaledChildWidth, scaledChildHeight; gfloat largestWidth, largestHeight; gfloat scaleWidth, scaleHeight; gfloat aspectRatio; gfloat x, y; ClutterActorBox childAllocation; g_return_if_fail(XFDASHBOARD_IS_SCALED_TABLE_LAYOUT(self)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); priv=XFDASHBOARD_SCALED_TABLE_LAYOUT(self)->priv; /* Get size of container holding children to layout and * determine size of a cell */ clutter_actor_get_size(CLUTTER_ACTOR(inContainer), &childWidth, &childHeight); cellWidth=childWidth-((priv->columns-1)*priv->columnSpacing); cellWidth=floor(cellWidth/priv->columns); cellHeight=childHeight-((priv->rows-1)*priv->rowSpacing); cellHeight=floor(cellHeight/priv->rows); /* Iterate through children and find largest one * if relative scale was set */ largestWidth=largestHeight=0.0f; if(priv->relativeScale==TRUE) { gfloat w, h; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { if(!CLUTTER_ACTOR_IS_VISIBLE(child)) continue; clutter_actor_get_preferred_size(child, NULL, NULL, &w, &h); if(w>largestWidth) largestWidth=w; if(h>largestHeight) largestHeight=h; } } /* Iterate through child actors and set their new allocation */ row=col=0; x=y=0.0f; clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { if(!CLUTTER_ACTOR_IS_VISIBLE(child)) continue; /* Get natural size of actor */ clutter_actor_get_preferred_size(child, NULL, NULL, &childWidth, &childHeight); /* If either width or height is 0 then it is visually hidden and we * skip expensive calculation. This also has the nice effect that * do not perform invalid divisions by zero ;) */ if(childWidth>0.0f && childHeight>0.0f) { /* Get scale factor needed to apply to width and height. * If no relative scaling should be performed the scale is always 1.0 * otherwise it is the scale factor for this actor to the largest one. */ if(priv->relativeScale==TRUE) { /* Get scale factors */ scaleWidth=childWidth/largestWidth; scaleHeight=childHeight/largestHeight; } else scaleWidth=scaleHeight=1.0f; /* Get aspect ratio factor */ aspectRatio=childHeight/childWidth; /* Calculate new size of child */ scaledChildWidth=cellWidth*scaleWidth; scaledChildHeight=scaledChildWidth*aspectRatio; if(scaledChildHeight>cellHeight) { scaledChildHeight=cellHeight*scaleHeight; scaledChildWidth=scaledChildHeight/aspectRatio; } /* If upscaling should be prevent check if we are upscaling now */ if(priv->preventUpscaling) { if(scaledChildWidth>childWidth) { scaledChildWidth=childWidth; scaledChildHeight=childWidth*aspectRatio; } if(scaledChildHeight>childHeight) { scaledChildHeight=childHeight; scaledChildWidth=childHeight/aspectRatio; } } } else { /* Visually hidden so do not allocate any space */ scaledChildWidth=0.0f; scaledChildHeight=0.0f; } /* Set new allocation of child */ childAllocation.x1=ceil(x+((cellWidth-scaledChildWidth)/2.0f)); childAllocation.y1=ceil(y+((cellHeight-scaledChildHeight)/2.0f)); childAllocation.x2=ceil(childAllocation.x1+scaledChildWidth); childAllocation.y2=ceil(childAllocation.y1+scaledChildHeight); clutter_actor_allocate(child, &childAllocation, inFlags); /* Set up for next child */ col=(col+1) % priv->columns; if(col==0) row++; x=col*(cellWidth+priv->columnSpacing); y=row*(cellHeight+priv->rowSpacing); } }
static void st_box_layout_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); ClutterActorBox content_box; gfloat avail_width, avail_height, min_width, natural_width, min_height, natural_height; gfloat position, next_position; GList *l, *children; gint n_expand_children = 0, i; gfloat expand_amount, shrink_amount; BoxChildShrink *shrinks = NULL; gboolean flip = (st_widget_get_direction (ST_WIDGET (actor)) == ST_TEXT_DIRECTION_RTL) && (!priv->is_vertical); CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->allocate (actor, box, flags); children = st_container_get_children_list (ST_CONTAINER (actor)); if (children == NULL) return; st_theme_node_get_content_box (theme_node, box, &content_box); avail_width = content_box.x2 - content_box.x1; avail_height = content_box.y2 - content_box.y1; get_content_preferred_width (ST_BOX_LAYOUT (actor), avail_height, &min_width, &natural_width); get_content_preferred_height (ST_BOX_LAYOUT (actor), MAX (avail_width, min_width), &min_height, &natural_height); /* update adjustments for scrolling */ if (priv->vadjustment) { gdouble prev_value; g_object_set (G_OBJECT (priv->vadjustment), "lower", 0.0, "upper", MAX (min_height, avail_height), "page-size", avail_height, "step-increment", avail_height / 6, "page-increment", avail_height - avail_height / 6, NULL); prev_value = st_adjustment_get_value (priv->vadjustment); st_adjustment_set_value (priv->vadjustment, prev_value); } if (priv->hadjustment) { gdouble prev_value; g_object_set (G_OBJECT (priv->hadjustment), "lower", 0.0, "upper", MAX (min_width, avail_width), "page-size", avail_width, "step-increment", avail_width / 6, "page-increment", avail_width - avail_width / 6, NULL); prev_value = st_adjustment_get_value (priv->hadjustment); st_adjustment_set_value (priv->hadjustment, prev_value); } if (avail_height < min_height) { avail_height = min_height; content_box.y2 = content_box.y1 + avail_height; } if (avail_width < min_width) { avail_width = min_width; content_box.x2 = content_box.x1 + avail_width; } if (priv->is_vertical) { expand_amount = MAX (0, avail_height - natural_height); shrink_amount = MAX (0, natural_height - avail_height); } else { expand_amount = MAX (0, avail_width - natural_width); shrink_amount = MAX (0, natural_width - avail_width); } if (expand_amount > 0) { /* count the number of children with expand set to TRUE */ n_expand_children = 0; for (l = children; l; l = l->next) { ClutterActor *child = l->data; gboolean expand; if (!CLUTTER_ACTOR_IS_VISIBLE (child) || clutter_actor_get_fixed_position_set (child)) continue; clutter_container_child_get ((ClutterContainer *) actor, child, "expand", &expand, NULL); if (expand) n_expand_children++; } if (n_expand_children == 0) expand_amount = 0; } else if (shrink_amount > 0) { shrinks = compute_shrinks (ST_BOX_LAYOUT (actor), priv->is_vertical ? avail_width : avail_height, shrink_amount); } if (priv->is_vertical) position = content_box.y1; else if (flip) position = content_box.x2; else position = content_box.x1; if (priv->is_pack_start) { l = g_list_last (children); i = g_list_length (children); } else { l = children; i = 0; } gboolean firstchild = TRUE; gfloat init_padding = (avail_width/2) - (natural_width/2); while (l) { ClutterActor *child = (ClutterActor*) l->data; ClutterActorBox child_box; gfloat child_min, child_nat, child_allocated; gboolean xfill, yfill, expand, fixed; StAlign xalign, yalign; if (!CLUTTER_ACTOR_IS_VISIBLE (child)) goto next_child; fixed = clutter_actor_get_fixed_position_set (child); if (fixed) { clutter_actor_allocate_preferred_size (child, flags); goto next_child; } clutter_container_child_get ((ClutterContainer*) actor, child, "x-fill", &xfill, "y-fill", &yfill, "x-align", &xalign, "y-align", &yalign, "expand", &expand, NULL); if (priv->is_vertical) { _st_actor_get_preferred_height (child, avail_width, xfill, &child_min, &child_nat); } else { _st_actor_get_preferred_width (child, avail_height, yfill, &child_min, &child_nat); } child_allocated = child_nat; if (expand_amount > 0 && expand) child_allocated += expand_amount / n_expand_children; else if (shrink_amount > 0) child_allocated -= shrinks[i].shrink_amount; if (flip) { next_position = position - child_allocated; if (xalign == ST_ALIGN_CENTER_SPECIAL && next_position < content_box.x1) next_position = content_box.x1; } else { next_position = position + child_allocated; if (xalign == ST_ALIGN_CENTER_SPECIAL && next_position > content_box.x2) next_position = content_box.x2; } if (priv->is_vertical) { child_box.y1 = (int)(0.5 + position); child_box.y2 = (int)(0.5 + next_position); child_box.x1 = content_box.x1; child_box.x2 = content_box.x2; _st_allocate_fill (ST_WIDGET (actor), child, &child_box, xalign, yalign, xfill, yfill); clutter_actor_allocate (child, &child_box, flags); } else { if (flip) { if (firstchild && xalign == ST_ALIGN_CENTER_SPECIAL) { position -= init_padding; next_position = position - child_allocated; firstchild = FALSE; } if (xalign == ST_ALIGN_CENTER_SPECIAL && position > content_box.x2) { position = content_box.x2; } child_box.x1 = (int)(0.5 + next_position); child_box.x2 = (int)(0.5 + position); } else { if (firstchild && xalign == ST_ALIGN_CENTER_SPECIAL) { position += init_padding; if (position < content_box.x1) { position = content_box.x1; } next_position = position + child_allocated; firstchild = FALSE; } if (xalign == ST_ALIGN_CENTER_SPECIAL && position < content_box.x1) { position = content_box.x1; } child_box.x1 = (int)(0.5 + position); child_box.x2 = (int)(0.5 + next_position); } child_box.y1 = content_box.y1; child_box.y2 = content_box.y2; _st_allocate_fill (ST_WIDGET (actor), child, &child_box, xalign, yalign, xfill, yfill); clutter_actor_allocate (child, &child_box, flags); } if (flip) position = next_position - priv->spacing; else position = next_position + priv->spacing; next_child: if (priv->is_pack_start) { l = l->prev; i--; } else { l = l->next; i++; } } if (shrinks) g_free (shrinks); }
static void mx_expander_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { MxExpanderPrivate *priv = MX_EXPANDER (actor)->priv; ClutterActorBox child_box; MxPadding padding; gfloat label_w, label_h; gfloat available_w, available_h, min_w, min_h, arrow_h, arrow_w; /* chain up to store allocation */ CLUTTER_ACTOR_CLASS (mx_expander_parent_class)->allocate (actor, box, flags); mx_widget_get_padding (MX_WIDGET (actor), &padding); available_w = (box->x2 - box->x1) - padding.left - padding.right; available_h = (box->y2 - box->y1) - padding.top - padding.bottom; /* arrow */ clutter_actor_get_preferred_width (priv->arrow, -1, NULL, &arrow_w); arrow_w = MIN (arrow_w, available_w); clutter_actor_get_preferred_height (priv->arrow, -1, NULL, &arrow_h); arrow_h = MIN (arrow_h, available_h); child_box.x1 = padding.left; child_box.x2 = child_box.x1 + arrow_w; child_box.y1 = padding.top; child_box.y2 = child_box.y1 + arrow_h; clutter_actor_allocate (priv->arrow, &child_box, flags); /* label */ min_h = 0; min_w = 0; clutter_actor_get_preferred_width (priv->label, available_h, &min_w, &label_w); label_w = CLAMP (label_w, min_w, available_w); clutter_actor_get_preferred_height (priv->label, label_w, &min_h, &label_h); label_h = CLAMP (label_h, min_h, available_h); /* TODO: make a style property for padding between arrow and label */ child_box.x1 = padding.left + arrow_w + 6.0f; child_box.x2 = child_box.x1 + label_w; child_box.y1 = padding.top; child_box.y2 = child_box.y1 + MAX (label_h, arrow_h); mx_allocate_align_fill (priv->label, &child_box, MX_ALIGN_START, MX_ALIGN_MIDDLE, FALSE, FALSE); clutter_actor_allocate (priv->label, &child_box, flags); /* remove label height and spacing for child calculations */ available_h -= MAX (label_h, arrow_h) + priv->spacing; /* child */ if (priv->expanded && priv->child && CLUTTER_ACTOR_IS_VISIBLE (priv->child)) { child_box.x1 = padding.left; child_box.x2 = child_box.x1 + available_w; child_box.y1 = padding.top + priv->spacing + MAX (label_h, arrow_h); child_box.y2 = child_box.y1 + available_h; clutter_actor_allocate (priv->child, &child_box, flags); } }
static void clutter_flow_layout_allocate (ClutterLayoutManager *manager, ClutterContainer *container, const ClutterActorBox *allocation, ClutterAllocationFlags flags) { ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; ClutterActor *actor, *child; ClutterActorIter iter; gfloat x_off, y_off; gfloat avail_width, avail_height; gfloat item_x, item_y; gint line_item_count; gint items_per_line; gint line_index; actor = CLUTTER_ACTOR (container); if (clutter_actor_get_n_children (actor) == 0) return; clutter_actor_box_get_origin (allocation, &x_off, &y_off); clutter_actor_box_get_size (allocation, &avail_width, &avail_height); /* blow the cached preferred size and re-compute with the given * available size in case the FlowLayout wasn't given the exact * size it requested */ if ((priv->req_width >= 0 && avail_width != priv->req_width) || (priv->req_height >= 0 && avail_height != priv->req_height)) { clutter_flow_layout_get_preferred_width (manager, container, avail_height, NULL, NULL); clutter_flow_layout_get_preferred_height (manager, container, avail_width, NULL, NULL); } items_per_line = compute_lines (CLUTTER_FLOW_LAYOUT (manager), avail_width, avail_height); item_x = x_off; item_y = y_off; line_item_count = 0; line_index = 0; clutter_actor_iter_init (&iter, actor); while (clutter_actor_iter_next (&iter, &child)) { ClutterActorBox child_alloc; gfloat item_width, item_height; gfloat new_x, new_y; gfloat child_min, child_natural; if (!CLUTTER_ACTOR_IS_VISIBLE (child)) continue; new_x = new_y = 0; if (!priv->snap_to_grid) clutter_actor_get_preferred_size (child, NULL, NULL, &item_width, &item_height); if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) { if ((priv->snap_to_grid && line_item_count == items_per_line && line_item_count > 0) || (!priv->snap_to_grid && item_x + item_width > avail_width)) { item_y += g_array_index (priv->line_natural, gfloat, line_index); if (line_index >= 0) item_y += priv->row_spacing; line_item_count = 0; line_index += 1; item_x = x_off; } if (priv->snap_to_grid) { new_x = x_off + ((line_item_count + 1) * (avail_width + priv->col_spacing)) / items_per_line; item_width = new_x - item_x - priv->col_spacing; } else { new_x = item_x + item_width + priv->col_spacing; } item_height = g_array_index (priv->line_natural, gfloat, line_index); } else { if ((priv->snap_to_grid && line_item_count == items_per_line && line_item_count > 0) || (!priv->snap_to_grid && item_y + item_height > avail_height)) { item_x += g_array_index (priv->line_natural, gfloat, line_index); if (line_index >= 0) item_x += priv->col_spacing; line_item_count = 0; line_index += 1; item_y = y_off; } if (priv->snap_to_grid) { new_y = y_off + ((line_item_count + 1) * (avail_height + priv->row_spacing)) / items_per_line; item_height = new_y - item_y - priv->row_spacing; } else { new_y = item_y + item_height + priv->row_spacing; } item_width = g_array_index (priv->line_natural, gfloat, line_index); } if (!priv->is_homogeneous && !clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL)) { clutter_actor_get_preferred_width (child, item_height, &child_min, &child_natural); item_width = MIN (item_width, child_natural); } if (!priv->is_homogeneous && !clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL)) { clutter_actor_get_preferred_height (child, item_width, &child_min, &child_natural); item_height = MIN (item_height, child_natural); } CLUTTER_NOTE (LAYOUT, "flow[line:%d, item:%d/%d] =" "{ %.2f, %.2f, %.2f, %.2f }", line_index, line_item_count + 1, items_per_line, item_x, item_y, item_width, item_height); child_alloc.x1 = ceil (item_x); child_alloc.y1 = ceil (item_y); child_alloc.x2 = ceil (child_alloc.x1 + item_width); child_alloc.y2 = ceil (child_alloc.y1 + item_height); clutter_actor_allocate (child, &child_alloc, flags); if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) item_x = new_x; else item_y = new_y; line_item_count += 1; } }