/* Re-layout and allocate children of container we manage */ static void _xfdashboard_box_layout_allocate(ClutterLayoutManager *inLayoutManager, ClutterContainer *inContainer, const ClutterActorBox *inAllocation, ClutterAllocationFlags inFlags) { ClutterTextDirection textDirection; ClutterActor *child; ClutterActorIter iter; ClutterActorBox childBox; gfloat containerWidth; g_return_if_fail(XFDASHBOARD_IS_BOX_LAYOUT(inLayoutManager)); g_return_if_fail(CLUTTER_IS_CONTAINER(inContainer)); /* Chain up to calculate and store the allocation of children */ CLUTTER_LAYOUT_MANAGER_CLASS(xfdashboard_box_layout_parent_class)->allocate(inLayoutManager, inContainer, inAllocation, inFlags); /* Right-to-left text direction only affects horizontal orientation. * If orientation is not horizontal or text direction is not right-to-left * then there is nothing to do. */ if(clutter_box_layout_get_orientation(CLUTTER_BOX_LAYOUT(inLayoutManager))!=CLUTTER_ORIENTATION_HORIZONTAL) { return; } textDirection=clutter_actor_get_text_direction(CLUTTER_ACTOR(inContainer)); if(textDirection==CLUTTER_TEXT_DIRECTION_DEFAULT) textDirection=clutter_get_default_text_direction(); if(textDirection!=CLUTTER_TEXT_DIRECTION_RTL) { return; } /* Iterate through children and recalculate x-coordination of each * children allocation by "mirroring" x-coordinate. */ containerWidth=clutter_actor_box_get_width(inAllocation); clutter_actor_iter_init(&iter, CLUTTER_ACTOR(inContainer)); while(clutter_actor_iter_next(&iter, &child)) { gfloat x1, x2; /* Get position and size of child */ clutter_actor_get_allocation_box(child, &childBox); /* Set new allocation of child */ x1=containerWidth-childBox.x2; x2=containerWidth-childBox.x1; childBox.x1=x1; childBox.x2=x2; clutter_actor_allocate(child, &childBox, inFlags); } }
static void st_table_preferred_allocate (ClutterActor *self, const ClutterActorBox *content_box, gboolean flags) { gint row_spacing, col_spacing; gint i; gint *col_widths, *row_heights; StTable *table; StTablePrivate *priv; gboolean ltr; ClutterActor *child; table = ST_TABLE (self); priv = ST_TABLE (self)->priv; col_spacing = (priv->col_spacing); row_spacing = (priv->row_spacing); col_widths = st_table_calculate_col_widths (table, (int) (content_box->x2 - content_box->x1)); row_heights = st_table_calculate_row_heights (table, (int) (content_box->y2 - content_box->y1), col_widths); ltr = (clutter_actor_get_text_direction (self) == CLUTTER_TEXT_DIRECTION_LTR); for (child = clutter_actor_get_first_child (self); child != NULL; child = clutter_actor_get_next_sibling (child)) { gint row, col, row_span, col_span; gint col_width, row_height; StTableChild *meta; ClutterActorBox childbox; gint child_x, child_y; gdouble x_align_f, y_align_f; 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; _st_get_align_factors (meta->x_align, meta->y_align, &x_align_f, &y_align_f); /* initialise the width and height */ col_width = col_widths[col]; row_height = row_heights[row]; /* 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: col-span exceeds number of columns"); #if 0 if (row + row_span > priv->n_rows) g_warning ("StTable: row-span exceeds number of rows"); #endif if (col_span > 1) { for (i = col + 1; i < col + col_span && i < priv->n_cols; i++) { col_width += col_widths[i]; 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 += row_heights[i]; 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 += col_widths[i]; } else { child_x = (int) content_box->x2 - col_spacing * col; for (i = 0; i < col; i++) child_x -= col_widths[i]; } /* calculate child y */ child_y = (int) content_box->y1 + row_spacing * row; for (i = 0; i < row; i++) child_y += row_heights[i]; /* 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); clutter_actor_allocate_align_fill (child, &childbox, x_align_f, y_align_f, meta->x_fill, meta->y_fill, flags); } }
static void st_table_homogeneous_allocate (ClutterActor *self, const ClutterActorBox *content_box, gboolean flags) { gfloat col_width, row_height; gint row_spacing, col_spacing; StTablePrivate *priv = ST_TABLE (self)->priv; gboolean ltr = clutter_actor_get_text_direction (self) == CLUTTER_TEXT_DIRECTION_LTR; ClutterActor *child; 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); for (child = clutter_actor_get_first_child (self); child != NULL; child = clutter_actor_get_next_sibling (child)) { gint row, col, row_span, col_span; StTableChild *meta; ClutterActorBox childbox; gdouble x_align_f, y_align_f; 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; _st_get_align_factors (meta->x_align, meta->y_align, &x_align_f, &y_align_f); 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)); clutter_actor_allocate_align_fill (child, &childbox, x_align_f, y_align_f, meta->x_fill, meta->y_fill, 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 st_scroll_view_fade_paint_target (ClutterOffscreenEffect *effect) { StScrollViewFade *self = ST_SCROLL_VIEW_FADE (effect); ClutterOffscreenEffectClass *parent; CoglHandle material; gdouble value, lower, upper, page_size; ClutterActor *vscroll = st_scroll_view_get_vscroll_bar (ST_SCROLL_VIEW (self->actor)); ClutterActor *hscroll = st_scroll_view_get_hscroll_bar (ST_SCROLL_VIEW (self->actor)); gboolean h_scroll_visible, v_scroll_visible; ClutterActorBox allocation, content_box, paint_box; /* * Used to pass the fade area to the shader * * [0][0] = x1 * [0][1] = y1 * [1][0] = x2 * [1][1] = y2 * */ float fade_area[2][2]; ClutterVertex verts[4]; if (self->program == COGL_INVALID_HANDLE) goto out; clutter_actor_get_paint_box (self->actor, &paint_box); clutter_actor_get_abs_allocation_vertices (self->actor, verts); clutter_actor_get_allocation_box (self->actor, &allocation); st_theme_node_get_content_box (st_widget_get_theme_node (ST_WIDGET (self->actor)), (const ClutterActorBox *)&allocation, &content_box); /* * The FBO is based on the paint_volume's size which can be larger then the actual * allocation, so we have to account for that when passing the positions */ fade_area[0][0] = content_box.x1 + (verts[0].x - paint_box.x1); fade_area[0][1] = content_box.y1 + (verts[0].y - paint_box.y1); fade_area[1][0] = content_box.x2 + (verts[3].x - paint_box.x2); fade_area[1][1] = content_box.y2 + (verts[3].y - paint_box.y2); g_object_get (ST_SCROLL_VIEW (self->actor), "hscrollbar-visible", &h_scroll_visible, "vscrollbar-visible", &v_scroll_visible, NULL); if (v_scroll_visible) { if (clutter_actor_get_text_direction (self->actor) == CLUTTER_TEXT_DIRECTION_RTL) fade_area[0][0] += clutter_actor_get_width (vscroll); fade_area[1][0] -= clutter_actor_get_width (vscroll); } if (h_scroll_visible) fade_area[1][1] -= clutter_actor_get_height (hscroll); st_adjustment_get_values (self->vadjustment, &value, &lower, &upper, NULL, NULL, &page_size); if (self->offset_top_uniform > -1) { if (value > lower + 0.1) cogl_program_set_uniform_1f (self->program, self->offset_top_uniform, self->vfade_offset); else cogl_program_set_uniform_1f (self->program, self->offset_top_uniform, 0.0f); } if (self->offset_bottom_uniform > -1) { if (value < upper - page_size - 0.1) cogl_program_set_uniform_1f (self->program, self->offset_bottom_uniform, self->vfade_offset); else cogl_program_set_uniform_1f (self->program, self->offset_bottom_uniform, 0.0f); } st_adjustment_get_values (self->hadjustment, &value, &lower, &upper, NULL, NULL, &page_size); if (self->offset_left_uniform > -1) { if (value > lower + 0.1) cogl_program_set_uniform_1f (self->program, self->offset_left_uniform, self->hfade_offset); else cogl_program_set_uniform_1f (self->program, self->offset_left_uniform, 0.0f); } if (self->offset_right_uniform > -1) { if (value < upper - page_size - 0.1) cogl_program_set_uniform_1f (self->program, self->offset_right_uniform, self->hfade_offset); else cogl_program_set_uniform_1f (self->program, self->offset_right_uniform, 0.0f); } if (self->tex_uniform > -1) cogl_program_set_uniform_1i (self->program, self->tex_uniform, 0); if (self->height_uniform > -1) cogl_program_set_uniform_1f (self->program, self->height_uniform, clutter_actor_get_height (self->actor)); if (self->width_uniform > -1) cogl_program_set_uniform_1f (self->program, self->width_uniform, clutter_actor_get_width (self->actor)); if (self->fade_area_uniform > -1) cogl_program_set_uniform_matrix (self->program, self->fade_area_uniform, 2, 1, FALSE, (const float *)fade_area); material = clutter_offscreen_effect_get_target (effect); cogl_material_set_user_program (material, self->program); out: parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (st_scroll_view_fade_parent_class); parent->paint_target (effect); }
static void clutter_bin_layout_allocate (ClutterLayoutManager *manager, ClutterContainer *container, const ClutterActorBox *allocation, ClutterAllocationFlags flags) { gfloat allocation_x, allocation_y; gfloat available_w, available_h; ClutterActor *actor, *child; ClutterActorIter iter; clutter_actor_box_get_origin (allocation, &allocation_x, &allocation_y); clutter_actor_box_get_size (allocation, &available_w, &available_h); actor = CLUTTER_ACTOR (container); clutter_actor_iter_init (&iter, actor); while (clutter_actor_iter_next (&iter, &child)) { ClutterLayoutMeta *meta; ClutterBinLayer *layer; ClutterActorBox child_alloc = { 0, }; gdouble x_align, y_align; gboolean x_fill, y_fill, is_fixed_position_set; float fixed_x, fixed_y; if (!clutter_actor_is_visible (child)) continue; meta = clutter_layout_manager_get_child_meta (manager, container, child); layer = CLUTTER_BIN_LAYER (meta); fixed_x = fixed_y = 0.f; g_object_get (child, "fixed-position-set", &is_fixed_position_set, "fixed-x", &fixed_x, "fixed-y", &fixed_y, NULL); /* XXX:2.0 - remove the FIXED alignment, and just use the fixed position * of the actor if one is set */ if (is_fixed_position_set || layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED) { if (is_fixed_position_set) child_alloc.x1 = fixed_x; else child_alloc.x1 = clutter_actor_get_x (child); } else child_alloc.x1 = allocation_x; if (is_fixed_position_set || layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED) { if (is_fixed_position_set) child_alloc.y1 = fixed_y; else child_alloc.y1 = clutter_actor_get_y (child); } else child_alloc.y1 = allocation_y; child_alloc.x2 = allocation_x + available_w; child_alloc.y2 = allocation_y + available_h; if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL)) { ClutterActorAlign align; align = clutter_actor_get_x_align (child); x_fill = align == CLUTTER_ACTOR_ALIGN_FILL; x_align = get_actor_align_factor (align); } else { ClutterTextDirection text_dir; x_fill = (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL); text_dir = clutter_actor_get_text_direction (child); if (!is_fixed_position_set) x_align = get_bin_alignment_factor (layer->x_align, text_dir); else x_align = 0.0; } if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL)) { ClutterActorAlign align; align = clutter_actor_get_y_align (child); y_fill = align == CLUTTER_ACTOR_ALIGN_FILL; y_align = get_actor_align_factor (align); } else { y_fill = (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL); if (!is_fixed_position_set) y_align = get_bin_alignment_factor (layer->y_align, CLUTTER_TEXT_DIRECTION_LTR); else y_align = 0.0; } clutter_actor_allocate_align_fill (child, &child_alloc, x_align, y_align, x_fill, y_fill, flags); } }