From e1390c7dd5f24bffb83e5953cc8375feb5bdac6b Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Sun, 20 Sep 2009 13:41:13 -0400 Subject: [PATCH] Centralize computations of border and padding into ShellThemeNode Rather than repeating the computation of borders in many different widget subclasses, add helper functions: shell_theme_node_adjust_for_height() shell_theme_node_adjust_preferred_width() shell_theme_node_adjust_for_width() shell_theme_node_adjust_preferred_height() shell_theme_node_get_content_box() That are used in get_preferred_width()/get_preferred_height() and allocate() methods to consistently apply the necessary adjustments. This allows removing the NbtkPadding type. Queueing a relayout when the borders/padding change is moved from nbtk_widget_real_style_changed() to the invoking code to allow access to the old ShellThemeNode for comparison. (Should this be added as a parameter to the signal?) Borders are included in the geometry adjustments, but borders are not yet drawn. --- src/nbtk/nbtk-bin.c | 91 +++++------------ src/nbtk/nbtk-box-layout.c | 172 ++++++++++++++++--------------- src/nbtk/nbtk-entry.c | 48 ++++----- src/nbtk/nbtk-label.c | 33 ++---- src/nbtk/nbtk-scroll-bar.c | 74 +++++++------- src/nbtk/nbtk-scroll-view.c | 56 +++++----- src/nbtk/nbtk-tooltip.c | 61 ++++------- src/nbtk/nbtk-types.h | 21 ---- src/nbtk/nbtk-widget.c | 73 +++++-------- src/nbtk/nbtk-widget.h | 2 - src/toolkit/shell-theme-node.c | 181 +++++++++++++++++++++++++++++++++ src/toolkit/shell-theme-node.h | 20 ++++ 12 files changed, 447 insertions(+), 385 deletions(-) diff --git a/src/nbtk/nbtk-bin.c b/src/nbtk/nbtk-bin.c index c0bde1c1d..928c18355 100644 --- a/src/nbtk/nbtk-bin.c +++ b/src/nbtk/nbtk-bin.c @@ -197,23 +197,22 @@ nbtk_bin_allocate (ClutterActor *self, if (priv->child) { + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); gfloat natural_width, natural_height; gfloat min_width, min_height; gfloat child_width, child_height; gfloat available_width, available_height; ClutterRequestMode request; + ClutterActorBox content_box; ClutterActorBox allocation = { 0, }; - NbtkPadding padding = { 0, }; gdouble x_align, y_align; + shell_theme_node_get_content_box (theme_node, box, &content_box); + _nbtk_bin_get_align_factors (NBTK_BIN (self), &x_align, &y_align); - nbtk_widget_get_padding (NBTK_WIDGET (self), &padding); - - available_width = box->x2 - box->x1 - - padding.left - padding.right; - available_height = box->y2 - box->y1 - - padding.top - padding.bottom; + available_width = content_box.x2 - content_box.x1; + available_height = content_box.y2 - content_box.y1; if (available_width < 0) available_width = 0; @@ -223,14 +222,14 @@ nbtk_bin_allocate (ClutterActor *self, if (priv->x_fill) { - allocation.x1 = (int) padding.top; - allocation.x2 = (int) (allocation.x1 + available_width); + allocation.x1 = (int) content_box.x1; + allocation.x2 = (int) content_box.x2; } if (priv->y_fill) { - allocation.y1 = (int) padding.right; - allocation.y2 = (int) (allocation.y1 + available_height); + allocation.y1 = (int) content_box.y1; + allocation.y2 = (int) content_box.y2; } /* if we are filling horizontally and vertically then we're done */ @@ -274,15 +273,13 @@ nbtk_bin_allocate (ClutterActor *self, if (!priv->x_fill) { - allocation.x1 = (int) ((available_width - child_width) * x_align - + padding.left); + allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align); allocation.x2 = allocation.x1 + child_width; } if (!priv->y_fill) { - allocation.y1 = (int) ((available_height - child_height) * y_align - + padding.top); + allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align); allocation.y2 = allocation.y1 + child_height; } @@ -297,33 +294,26 @@ nbtk_bin_get_preferred_width (ClutterActor *self, gfloat *natural_width_p) { NbtkBinPrivate *priv = NBTK_BIN (self)->priv; - gfloat min_width, natural_width; - NbtkPadding padding = { 0, }; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); - nbtk_widget_get_padding (NBTK_WIDGET (self), &padding); - - min_width = natural_width = padding.left + padding.right; + shell_theme_node_adjust_for_height (theme_node, &for_height); if (priv->child == NULL) { if (min_width_p) - *min_width_p = min_width; + *min_width_p = 0; if (natural_width_p) - *natural_width_p = natural_width; + *natural_width_p = 0; } else { clutter_actor_get_preferred_width (priv->child, for_height, min_width_p, natural_width_p); - - if (min_width_p) - *min_width_p += min_width; - - if (natural_width_p) - *natural_width_p += natural_width; } + + shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); } static void @@ -333,33 +323,26 @@ nbtk_bin_get_preferred_height (ClutterActor *self, gfloat *natural_height_p) { NbtkBinPrivate *priv = NBTK_BIN (self)->priv; - gfloat min_height, natural_height; - NbtkPadding padding = { 0, }; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); - nbtk_widget_get_padding (NBTK_WIDGET (self), &padding); - - min_height = natural_height = padding.top + padding.bottom; + shell_theme_node_adjust_for_width (theme_node, &for_width); if (priv->child == NULL) { if (min_height_p) - *min_height_p = min_height; + *min_height_p = 0; if (natural_height_p) - *natural_height_p = natural_height; + *natural_height_p = 0; } else { clutter_actor_get_preferred_height (priv->child, for_width, min_height_p, natural_height_p); - - if (min_height_p) - *min_height_p += min_height; - - if (natural_height_p) - *natural_height_p += natural_height; } + + shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); } static void @@ -754,29 +737,3 @@ nbtk_bin_get_fill (NbtkBin *bin, if (y_fill) *y_fill = bin->priv->y_fill; } - -static gpointer -nbtk_padding_copy (gpointer data) -{ - return g_slice_dup (NbtkPadding, data); -} - -static void -nbtk_padding_free (gpointer data) -{ - if (G_LIKELY (data)) - g_slice_free (NbtkPadding, data); -} - -GType -nbtk_padding_get_type (void) -{ - static GType our_type = 0; - - if (G_UNLIKELY (our_type == 0)) - our_type = g_boxed_type_register_static (I_("NbtkPadding"), - nbtk_padding_copy, - nbtk_padding_free); - - return our_type; -} diff --git a/src/nbtk/nbtk-box-layout.c b/src/nbtk/nbtk-box-layout.c index 8df6fb5a4..8f9f24689 100644 --- a/src/nbtk/nbtk-box-layout.c +++ b/src/nbtk/nbtk-box-layout.c @@ -405,26 +405,18 @@ nbtk_box_layout_dispose (GObject *object) } static void -nbtk_box_layout_get_preferred_width (ClutterActor *actor, - gfloat for_height, - gfloat *min_width_p, - gfloat *natural_width_p) +get_content_preferred_width (NbtkBoxLayout *self, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) { - NbtkBoxLayoutPrivate *priv = NBTK_BOX_LAYOUT (actor)->priv; - NbtkPadding padding = { 0, }; + NbtkBoxLayoutPrivate *priv = self->priv; gint n_children = 0; + gfloat min_width, natural_width; GList *l; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); - - if (min_width_p) - *min_width_p = padding.left + padding.right; - - if (natural_width_p) - *natural_width_p = padding.left + padding.right; - - if (priv->children == NULL) - return; + min_width = 0; + natural_width = 0; for (l = priv->children; l; l = g_list_next (l)) { @@ -442,55 +434,59 @@ nbtk_box_layout_get_preferred_width (ClutterActor *actor, if (priv->is_vertical) { - if (min_width_p) - *min_width_p = MAX (child_min, *min_width_p); - - if (natural_width_p) - *natural_width_p = MAX (child_nat, *natural_width_p); + min_width = MAX (child_min, min_width); + natural_width = MAX (child_nat, natural_width); } else { - if (min_width_p) - *min_width_p += child_min; - - if (natural_width_p) - *natural_width_p += child_nat; - + min_width += child_min; + natural_width += child_nat; } } - if (!priv->is_vertical && n_children > 1) { - if (min_width_p) - *min_width_p += priv->spacing * (n_children - 1); - - if (natural_width_p) - *natural_width_p += priv->spacing * (n_children - 1); + min_width += priv->spacing * (n_children - 1); + natural_width += priv->spacing * (n_children - 1); } + + if (min_width_p) + *min_width_p = min_width; + + if (natural_width_p) + *natural_width_p = natural_width; } static void -nbtk_box_layout_get_preferred_height (ClutterActor *actor, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p) +nbtk_box_layout_get_preferred_width (ClutterActor *actor, + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) { - NbtkBoxLayoutPrivate *priv = NBTK_BOX_LAYOUT (actor)->priv; - NbtkPadding padding = { 0, }; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); + + shell_theme_node_adjust_for_height (theme_node, &for_height); + + get_content_preferred_width (NBTK_BOX_LAYOUT (actor), for_height, + min_width_p, natural_width_p); + + shell_theme_node_adjust_preferred_width (theme_node, + min_width_p, natural_width_p); +} + +static void +get_content_preferred_height (NbtkBoxLayout *self, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + NbtkBoxLayoutPrivate *priv = self->priv; gint n_children = 0; + gfloat min_height, natural_height; GList *l; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); - - if (min_height_p) - *min_height_p = padding.top + padding.bottom; - - if (natural_height_p) - *natural_height_p = padding.top + padding.bottom; - - if (priv->children == NULL) - return; + min_height = 0; + natural_height = 0; for (l = priv->children; l; l = g_list_next (l)) { @@ -508,30 +504,44 @@ nbtk_box_layout_get_preferred_height (ClutterActor *actor, if (!priv->is_vertical) { - if (min_height_p) - *min_height_p = MAX (child_min, *min_height_p); - - if (natural_height_p) - *natural_height_p = MAX (child_nat, *natural_height_p); + min_height = MAX (child_min, min_height); + natural_height = MAX (child_nat, natural_height); } else { - if (min_height_p) - *min_height_p += child_min; - - if (natural_height_p) - *natural_height_p += child_nat; + min_height += child_min; + natural_height += child_nat; } } if (priv->is_vertical && n_children > 1) { - if (min_height_p) - *min_height_p += priv->spacing * (n_children - 1); - - if (natural_height_p) - *natural_height_p += priv->spacing * (n_children - 1); + min_height += priv->spacing * (n_children - 1); + natural_height += priv->spacing * (n_children - 1); } + + if (min_height_p) + *min_height_p = min_height; + + if (natural_height_p) + *natural_height_p = natural_height; +} + +static void +nbtk_box_layout_get_preferred_height (ClutterActor *actor, + gfloat for_width, + gfloat *min_height_p, + gfloat *natural_height_p) +{ + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); + + shell_theme_node_adjust_for_width (theme_node, &for_width); + + get_content_preferred_height (NBTK_BOX_LAYOUT (actor), for_width, + min_height_p, natural_height_p); + + shell_theme_node_adjust_preferred_height (theme_node, + min_height_p, natural_height_p); } static void @@ -540,8 +550,9 @@ nbtk_box_layout_allocate (ClutterActor *actor, ClutterAllocationFlags flags) { NbtkBoxLayoutPrivate *priv = NBTK_BOX_LAYOUT (actor)->priv; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); + ClutterActorBox content_box; gfloat avail_width, avail_height, pref_width, pref_height; - NbtkPadding padding = { 0, }; gfloat position = 0; GList *l; gint n_expand_children, extra_space; @@ -552,18 +563,15 @@ nbtk_box_layout_allocate (ClutterActor *actor, if (priv->children == NULL) return; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); - avail_width = box->x2 - box->x1 - - padding.left - - padding.right; - avail_height = box->y2 - box->y1 - - padding.top - - padding.bottom; + shell_theme_node_get_content_box (theme_node, box, &content_box); - nbtk_box_layout_get_preferred_height (actor, avail_width, NULL, - &pref_height); - nbtk_box_layout_get_preferred_width (actor, avail_height, NULL, - &pref_width); + avail_width = content_box.x2 - content_box.x1; + avail_height = content_box.y2 - content_box.y1; + + get_content_preferred_height (NBTK_BOX_LAYOUT (actor), avail_width, + NULL, &pref_height); + get_content_preferred_width (NBTK_BOX_LAYOUT (actor), avail_height, + NULL, &pref_width); /* update adjustments for scrolling */ if (priv->vadjustment) @@ -629,9 +637,9 @@ nbtk_box_layout_allocate (ClutterActor *actor, } if (priv->is_vertical) - position = padding.top; + position = content_box.y1; else - position = padding.left; + position = content_box.x1; if (priv->is_pack_start) l = g_list_last (priv->children); @@ -669,8 +677,8 @@ nbtk_box_layout_allocate (ClutterActor *actor, child_box.y2 = position + child_nat + extra_space; else child_box.y2 = position + child_nat; - child_box.x1 = padding.left; - child_box.x2 = avail_width; + child_box.x1 = content_box.x1; + child_box.x2 = content_box.x2; _nbtk_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill); clutter_actor_allocate (child, &child_box, flags); @@ -693,8 +701,8 @@ nbtk_box_layout_allocate (ClutterActor *actor, else child_box.x2 = position + child_nat; - child_box.y1 = padding.top; - child_box.y2 = avail_height; + child_box.y1 = content_box.y1; + child_box.y2 = content_box.y2; _nbtk_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill); clutter_actor_allocate (child, &child_box, flags); diff --git a/src/nbtk/nbtk-entry.c b/src/nbtk/nbtk-entry.c index 286d4c143..dd1c864a5 100644 --- a/src/nbtk/nbtk-entry.c +++ b/src/nbtk/nbtk-entry.c @@ -204,12 +204,10 @@ nbtk_entry_get_preferred_width (ClutterActor *actor, gfloat *natural_width_p) { NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); - NbtkPadding padding; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); gfloat icon_w; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); - - for_height -= padding.top + padding.bottom; + shell_theme_node_adjust_for_height (theme_node, &for_height); clutter_actor_get_preferred_width (priv->entry, for_height, min_width_p, @@ -238,11 +236,7 @@ nbtk_entry_get_preferred_width (ClutterActor *actor, *natural_width_p += icon_w + priv->spacing; } - if (min_width_p) - *min_width_p += padding.left + padding.right; - - if (natural_width_p) - *natural_width_p += padding.left + padding.right; + shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); } static void @@ -252,12 +246,10 @@ nbtk_entry_get_preferred_height (ClutterActor *actor, gfloat *natural_height_p) { NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); - NbtkPadding padding; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); gfloat icon_h; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); - - for_width -= padding.left + padding.right; + shell_theme_node_adjust_for_width (theme_node, &for_width); clutter_actor_get_preferred_height (priv->entry, for_width, min_height_p, @@ -287,11 +279,7 @@ nbtk_entry_get_preferred_height (ClutterActor *actor, *natural_height_p = icon_h; } - if (min_height_p) - *min_height_p += padding.top + padding.bottom; - - if (natural_height_p) - *natural_height_p += padding.top + padding.bottom; + shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); } static void @@ -300,21 +288,21 @@ nbtk_entry_allocate (ClutterActor *actor, ClutterAllocationFlags flags) { NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor); + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); ClutterActorClass *parent_class; - ClutterActorBox child_box, icon_box; - NbtkPadding padding; + ClutterActorBox content_box, child_box, icon_box; gfloat icon_w, icon_h; gfloat entry_h, min_h, pref_h, avail_h; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); - parent_class = CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class); parent_class->allocate (actor, box, flags); - avail_h = (box->y2 - box->y1) - padding.top - padding.bottom; + shell_theme_node_get_content_box (theme_node, box, &content_box); - child_box.x1 = padding.left; - child_box.x2 = box->x2 - box->x1 - padding.right; + avail_h = content_box.y2 - content_box.y1; + + child_box.x1 = content_box.x1; + child_box.x2 = content_box.x2; if (priv->primary_icon) { @@ -323,10 +311,10 @@ nbtk_entry_allocate (ClutterActor *actor, clutter_actor_get_preferred_height (priv->primary_icon, -1, NULL, &icon_h); - icon_box.x1 = padding.left; + icon_box.x1 = content_box.x1; icon_box.x2 = icon_box.x1 + icon_w; - icon_box.y1 = (int) (padding.top + avail_h / 2 - icon_h / 2); + icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2); icon_box.y2 = icon_box.y1 + icon_h; clutter_actor_allocate (priv->primary_icon, @@ -344,10 +332,10 @@ nbtk_entry_allocate (ClutterActor *actor, clutter_actor_get_preferred_height (priv->secondary_icon, -1, NULL, &icon_h); - icon_box.x2 = (box->x2 - box->x1) - padding.right; + icon_box.x2 = content_box.x2; icon_box.x1 = icon_box.x2 - icon_w; - icon_box.y1 = (int) (padding.top + avail_h / 2 - icon_h / 2); + icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2); icon_box.y2 = icon_box.y1 + icon_h; clutter_actor_allocate (priv->secondary_icon, @@ -363,7 +351,7 @@ nbtk_entry_allocate (ClutterActor *actor, entry_h = CLAMP (pref_h, min_h, avail_h); - child_box.y1 = (int) (padding.top + avail_h / 2 - entry_h / 2); + child_box.y1 = (int) (content_box.y1 + avail_h / 2 - entry_h / 2); child_box.y2 = child_box.y1 + entry_h; clutter_actor_allocate (priv->entry, &child_box, flags); diff --git a/src/nbtk/nbtk-label.c b/src/nbtk/nbtk-label.c index a563bc377..ad6b7a181 100644 --- a/src/nbtk/nbtk-label.c +++ b/src/nbtk/nbtk-label.c @@ -130,19 +130,15 @@ nbtk_label_get_preferred_width (ClutterActor *actor, gfloat *natural_width_p) { NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; - NbtkPadding padding = { 0, }; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); + shell_theme_node_adjust_for_height (theme_node, &for_height); clutter_actor_get_preferred_width (priv->label, for_height, min_width_p, natural_width_p); - if (min_width_p) - *min_width_p += padding.left + padding.right; - - if (natural_width_p) - *natural_width_p += padding.left + padding.right; + shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); } static void @@ -152,19 +148,15 @@ nbtk_label_get_preferred_height (ClutterActor *actor, gfloat *natural_height_p) { NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; - NbtkPadding padding = { 0, }; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); + shell_theme_node_adjust_for_width (theme_node, &for_width); clutter_actor_get_preferred_height (priv->label, for_width, min_height_p, natural_height_p); - if (min_height_p) - *min_height_p += padding.top + padding.bottom; - - if (natural_height_p) - *natural_height_p += padding.top + padding.bottom; + shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); } static void @@ -173,21 +165,16 @@ nbtk_label_allocate (ClutterActor *actor, ClutterAllocationFlags flags) { NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); ClutterActorClass *parent_class; - ClutterActorBox child_box; - NbtkPadding padding = { 0, }; + ClutterActorBox content_box; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); + shell_theme_node_get_content_box (theme_node, box, &content_box); parent_class = CLUTTER_ACTOR_CLASS (nbtk_label_parent_class); parent_class->allocate (actor, box, flags); - child_box.x1 = padding.left; - child_box.y1 = padding.top; - child_box.x2 = box->x2 - box->x1 - padding.right; - child_box.y2 = box->y2 - box->y1 - padding.bottom; - - clutter_actor_allocate (priv->label, &child_box, flags); + clutter_actor_allocate (priv->label, &content_box, flags); } static void diff --git a/src/nbtk/nbtk-scroll-bar.c b/src/nbtk/nbtk-scroll-bar.c index 8800f0f0d..34b414413 100644 --- a/src/nbtk/nbtk-scroll-bar.c +++ b/src/nbtk/nbtk-scroll-bar.c @@ -260,71 +260,65 @@ nbtk_scroll_bar_allocate (ClutterActor *actor, ClutterAllocationFlags flags) { NbtkScrollBarPrivate *priv = NBTK_SCROLL_BAR (actor)->priv; - NbtkPadding padding; - ClutterActorBox bw_box, fw_box, trough_box; - gfloat x, y, width, height, stepper_size; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); + ClutterActorBox content_box, bw_box, fw_box, trough_box; + gfloat stepper_size; /* Chain up */ CLUTTER_ACTOR_CLASS (nbtk_scroll_bar_parent_class)-> allocate (actor, box, flags); - nbtk_widget_get_padding (NBTK_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; + shell_theme_node_get_content_box (theme_node, box, &content_box); if (priv->vertical) { - stepper_size = width; + stepper_size = content_box.x2 - content_box.x1; /* Backward stepper */ - bw_box.x1 = x; - bw_box.y1 = y; - bw_box.x2 = bw_box.x1 + stepper_size; + bw_box.x1 = content_box.x1; + bw_box.y1 = content_box.y1; + bw_box.x2 = content_box.x2; 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; + fw_box.x1 = content_box.x1; + fw_box.y1 = content_box.y2 - 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 = x; - trough_box.y1 = y + stepper_size; - trough_box.x2 = x + width; - trough_box.y2 = y + height - stepper_size; + trough_box.x1 = content_box.x1; + trough_box.y1 = content_box.y1 + stepper_size; + trough_box.x2 = content_box.x2; + trough_box.y2 = content_box.y2 - stepper_size; clutter_actor_allocate (priv->trough, &trough_box, flags); } else { - stepper_size = height; + stepper_size = content_box.y2 - content_box.y1; /* Backward stepper */ - bw_box.x1 = x; - bw_box.y1 = y; + bw_box.x1 = content_box.x1; + bw_box.y1 = content_box.y1; bw_box.x2 = bw_box.x1 + stepper_size; - bw_box.y2 = bw_box.y1 + stepper_size; + bw_box.y2 = content_box.y2; 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; + fw_box.x1 = content_box.x2 - 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 = x + stepper_size; - trough_box.y1 = y; - trough_box.x2 = x + width - stepper_size; - trough_box.y2 = y + height; + trough_box.x1 = content_box.x1 + stepper_size; + trough_box.y1 = content_box.y1; + trough_box.x2 = content_box.x2 - stepper_size; + trough_box.y2 = content_box.y2; clutter_actor_allocate (priv->trough, &trough_box, flags); } @@ -362,27 +356,27 @@ nbtk_scroll_bar_allocate (ClutterActor *actor, if (priv->vertical) { - avail_size = height - stepper_size * 2; + avail_size = content_box.y2 - content_box.y1 - stepper_size * 2; handle_size = increment * avail_size; handle_size = CLAMP (handle_size, min_size, max_size); - handle_box.x1 = x; + handle_box.x1 = content_box.x1; handle_box.y1 = bw_box.y2 + position * (avail_size - handle_size); - handle_box.x2 = handle_box.x1 + width; + handle_box.x2 = content_box.x2; handle_box.y2 = handle_box.y1 + handle_size; } else { - avail_size = width - stepper_size * 2; + avail_size = content_box.x2 - content_box.x1 - stepper_size * 2; 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 = y; + handle_box.y1 = content_box.y1; handle_box.x2 = handle_box.x1 + handle_size; - handle_box.y2 = handle_box.y1 + height; + handle_box.y2 = content_box.y2; } /* snap to pixel */ diff --git a/src/nbtk/nbtk-scroll-view.c b/src/nbtk/nbtk-scroll-view.c index e57e1cf02..f40e7a670 100644 --- a/src/nbtk/nbtk-scroll-view.c +++ b/src/nbtk/nbtk-scroll-view.c @@ -192,14 +192,13 @@ nbtk_scroll_view_get_preferred_width (ClutterActor *actor, gfloat *min_width_p, gfloat *natural_width_p) { - NbtkPadding padding; - NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); if (!priv->child) return; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); + shell_theme_node_adjust_for_height (theme_node, &for_height); /* Our natural width is the natural width of the child */ clutter_actor_get_preferred_width (priv->child, @@ -219,12 +218,10 @@ nbtk_scroll_view_get_preferred_width (ClutterActor *actor, *natural_width_p += get_scrollbar_width (NBTK_SCROLL_VIEW (actor)); } - /* Add space for padding */ if (min_width_p) - *min_width_p = padding.left + padding.right; + *min_width_p = 0; - if (natural_width_p) - *natural_width_p += padding.left + padding.right; + shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); } static void @@ -233,14 +230,13 @@ nbtk_scroll_view_get_preferred_height (ClutterActor *actor, gfloat *min_height_p, gfloat *natural_height_p) { - NbtkPadding padding; - NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); if (!priv->child) return; - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); + shell_theme_node_adjust_for_width (theme_node, &for_width); /* Our natural height is the natural height of the child */ clutter_actor_get_preferred_height (priv->child, @@ -260,12 +256,10 @@ nbtk_scroll_view_get_preferred_height (ClutterActor *actor, *natural_height_p += get_scrollbar_height (NBTK_SCROLL_VIEW (actor)); } - /* Add space for padding */ if (min_height_p) - *min_height_p = padding.top + padding.bottom; + *min_height_p = 0; - if (natural_height_p) - *natural_height_p += padding.top + padding.bottom; + shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); } static void @@ -273,12 +267,12 @@ nbtk_scroll_view_allocate (ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags) { - NbtkPadding padding; - ClutterActorBox child_box; + ClutterActorBox content_box, child_box; ClutterActorClass *parent_parent_class; gfloat avail_width, avail_height, sb_width, sb_height; NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor)); /* Chain up to the parent's parent class * @@ -293,10 +287,10 @@ nbtk_scroll_view_allocate (ClutterActor *actor, allocate (actor, box, flags); - nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding); + shell_theme_node_get_content_box (theme_node, box, &content_box); - avail_width = (box->x2 - box->x1) - padding.left - padding.right; - avail_height = (box->y2 - box->y1) - padding.top - padding.bottom; + avail_width = content_box.x2 - content_box.x1; + avail_height = content_box.y2 - content_box.y1; sb_width = get_scrollbar_width (NBTK_SCROLL_VIEW (actor)); sb_height = get_scrollbar_width (NBTK_SCROLL_VIEW (actor)); @@ -310,10 +304,10 @@ nbtk_scroll_view_allocate (ClutterActor *actor, /* Vertical scrollbar */ if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll)) { - child_box.x1 = avail_width - sb_width; - child_box.y1 = padding.top; - child_box.x2 = avail_width; - child_box.y2 = child_box.y1 + avail_height - sb_height; + child_box.x1 = content_box.x2 - sb_width; + child_box.y1 = content_box.y1; + child_box.x2 = content_box.x2; + child_box.y2 = content_box.y2 - sb_height; clutter_actor_allocate (priv->vscroll, &child_box, flags); } @@ -321,20 +315,20 @@ nbtk_scroll_view_allocate (ClutterActor *actor, /* Horizontal scrollbar */ if (CLUTTER_ACTOR_IS_VISIBLE (priv->hscroll)) { - child_box.x1 = padding.left; - child_box.x2 = child_box.x1 + avail_width - sb_width; - child_box.y1 = avail_height - sb_height; - child_box.y2 = avail_height; + child_box.x1 = content_box.x1; + child_box.y1 = content_box.y2 - sb_height; + child_box.x2 = content_box.x2 - sb_width; + child_box.y2 = content_box.y2; clutter_actor_allocate (priv->hscroll, &child_box, flags); } /* Child */ - child_box.x1 = padding.left; - child_box.x2 = avail_width - sb_width; - child_box.y1 = padding.top; - child_box.y2 = avail_height - sb_height; + child_box.x1 = content_box.x1; + child_box.y1 = content_box.y1; + child_box.x2 = content_box.x2 - sb_width; + child_box.y2 = content_box.y2 - sb_height; if (priv->child) clutter_actor_allocate (priv->child, &child_box, flags); diff --git a/src/nbtk/nbtk-tooltip.c b/src/nbtk/nbtk-tooltip.c index 1f832d70d..e3ac32d0e 100644 --- a/src/nbtk/nbtk-tooltip.c +++ b/src/nbtk/nbtk-tooltip.c @@ -146,12 +146,12 @@ nbtk_tooltip_get_preferred_width (ClutterActor *self, gfloat *natural_width_p) { NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); gfloat min_label_w, natural_label_w; gfloat label_height, arrow_height; ClutterActor *arrow_image; - NbtkPadding padding; - nbtk_widget_get_padding (NBTK_WIDGET (self), &padding); + shell_theme_node_adjust_for_height (theme_node, &for_height); arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); if (arrow_image) @@ -168,7 +168,7 @@ nbtk_tooltip_get_preferred_width (ClutterActor *self, if (for_height > -1) { - label_height = for_height - arrow_height - padding.top - padding.bottom; + label_height = for_height - arrow_height; } else { @@ -188,16 +188,7 @@ nbtk_tooltip_get_preferred_width (ClutterActor *self, natural_label_w = 0; } - - if (min_width_p) - { - *min_width_p = padding.left + padding.right + min_label_w; - } - - if (natural_width_p) - { - *natural_width_p = padding.left + padding.right + natural_label_w; - } + shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p); } static void @@ -207,11 +198,12 @@ nbtk_tooltip_get_preferred_height (ClutterActor *self, gfloat *natural_height_p) { NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); gfloat arrow_height; gfloat min_label_h, natural_label_h; - gfloat label_width; ClutterActor *arrow_image; - NbtkPadding padding; + + shell_theme_node_adjust_for_width (theme_node, &for_width); arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); @@ -226,21 +218,11 @@ nbtk_tooltip_get_preferred_height (ClutterActor *self, { arrow_height = 0; } - nbtk_widget_get_padding (NBTK_WIDGET (self), &padding); - - if (for_width > -1) - { - label_width = for_width - padding.left - padding.right; - } - else - { - label_width = -1; - } if (priv->label) { clutter_actor_get_preferred_height (priv->label, - label_width, + for_width, &min_label_h, &natural_label_h); } @@ -251,16 +233,12 @@ nbtk_tooltip_get_preferred_height (ClutterActor *self, } if (min_height_p) - { - *min_height_p = padding.top + padding.bottom - + arrow_height + min_label_h; - } + *min_height_p = arrow_height + min_label_h; if (natural_height_p) - { - *natural_height_p = padding.top + padding.bottom - + arrow_height + natural_label_h; - } + *natural_height_p = arrow_height + natural_label_h; + + shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p); } static void @@ -269,16 +247,16 @@ nbtk_tooltip_allocate (ClutterActor *self, ClutterAllocationFlags flags) { NbtkTooltipPrivate *priv = NBTK_TOOLTIP (self)->priv; - ClutterActorBox child_box, arrow_box; + ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self)); + ClutterActorBox content_box, child_box, arrow_box; gfloat arrow_height, arrow_width; ClutterActor *border_image, *arrow_image; - NbtkPadding padding; CLUTTER_ACTOR_CLASS (nbtk_tooltip_parent_class)->allocate (self, box, flags); - nbtk_widget_get_padding (NBTK_WIDGET (self), &padding); + shell_theme_node_get_content_box (theme_node, box, &content_box); arrow_image = nbtk_widget_get_background_image (NBTK_WIDGET (self)); @@ -313,11 +291,8 @@ nbtk_tooltip_allocate (ClutterActor *self, if (priv->label) { - /* now remove the padding */ - child_box.y1 += padding.top; - child_box.x1 += padding.left; - child_box.x2 -= padding.right; - child_box.y2 -= padding.bottom; + child_box = content_box; + child_box.y1 += arrow_height; clutter_actor_allocate (priv->label, &child_box, flags); } @@ -455,7 +430,7 @@ nbtk_tooltip_update_position (NbtkTooltip *tooltip) return; } - /* we need to have a style in case there are padding values to take into + /* we need to have a style in case there are padding/border values to take into * account when calculating width/height */ nbtk_widget_ensure_style ((NbtkWidget *) tooltip); diff --git a/src/nbtk/nbtk-types.h b/src/nbtk/nbtk-types.h index bb7eee427..a72e604ad 100644 --- a/src/nbtk/nbtk-types.h +++ b/src/nbtk/nbtk-types.h @@ -30,27 +30,6 @@ G_BEGIN_DECLS #define NBTK_TYPE_PADDING (nbtk_padding_get_type ()) -typedef struct _NbtkPadding NbtkPadding; - -/** - * NbtkPadding: - * @top: padding from the top - * @right: padding from the right - * @bottom: padding from the bottom - * @left: padding from the left - * - * The padding from the internal border of the parent container. - */ -struct _NbtkPadding -{ - gfloat top; - gfloat right; - gfloat bottom; - gfloat left; -}; - -GType nbtk_padding_get_type (void) G_GNUC_CONST; - /** * NbtkAlignment: * @NBTK_ALIGN_TOP: align to the top (vertically) diff --git a/src/nbtk/nbtk-widget.c b/src/nbtk/nbtk-widget.c index 7295afe6d..f917ed166 100644 --- a/src/nbtk/nbtk-widget.c +++ b/src/nbtk/nbtk-widget.c @@ -27,6 +27,7 @@ #include "config.h" #endif +#include #include #include @@ -41,15 +42,13 @@ #include "nbtk-tooltip.h" #include +#include /* * Forward declaration for sake of NbtkWidgetChild */ struct _NbtkWidgetPrivate { - NbtkPadding border; - NbtkPadding padding; - ShellTheme *theme; ShellThemeNode *theme_node; gchar *pseudo_class; @@ -106,6 +105,9 @@ G_DEFINE_ABSTRACT_TYPE (NbtkWidget, nbtk_widget, CLUTTER_TYPE_ACTOR); #define NBTK_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_WIDGET, NbtkWidgetPrivate)) +static void nbtk_widget_recompute_style (NbtkWidget *widget, + ShellThemeNode *old_theme_node); + static void nbtk_widget_set_property (GObject *gobject, guint prop_id, @@ -484,7 +486,6 @@ nbtk_widget_real_style_changed (NbtkWidget *self) const char *bg_file = NULL; gboolean relayout_needed = FALSE; gboolean has_changed = FALSE; - NbtkPadding padding; ClutterColor color; /* application has request this widget is not stylable */ @@ -500,21 +501,6 @@ nbtk_widget_real_style_changed (NbtkWidget *self) has_changed = TRUE; } - padding.top = shell_theme_node_get_padding (theme_node, SHELL_SIDE_TOP); - padding.right = shell_theme_node_get_padding (theme_node, SHELL_SIDE_RIGHT); - padding.bottom = shell_theme_node_get_padding (theme_node, SHELL_SIDE_BOTTOM); - padding.left = shell_theme_node_get_padding (theme_node, SHELL_SIDE_LEFT); - - if (priv->padding.top != padding.top || - priv->padding.left != padding.left || - priv->padding.right != padding.right || - priv->padding.bottom != padding.bottom) - { - priv->padding = padding; - has_changed = TRUE; - relayout_needed = TRUE; - } - if (priv->border_image) { clutter_actor_unparent (priv->border_image); @@ -600,18 +586,21 @@ nbtk_widget_real_style_changed (NbtkWidget *self) void nbtk_widget_style_changed (NbtkWidget *widget) { + ShellThemeNode *old_theme_node = NULL; + widget->priv->is_style_dirty = TRUE; if (widget->priv->theme_node) { - g_object_unref (widget->priv->theme_node); + old_theme_node = widget->priv->theme_node; widget->priv->theme_node = NULL; } /* update the style only if we are mapped */ - if (!CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (widget))) - return; + if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (widget))) + nbtk_widget_recompute_style (widget, old_theme_node); - nbtk_widget_ensure_style (widget); + if (old_theme_node) + g_object_unref (old_theme_node); } static void @@ -1067,6 +1056,20 @@ nbtk_widget_init (NbtkWidget *actor) g_signal_connect (actor, "notify::name", G_CALLBACK (nbtk_widget_name_notify), NULL); } +static void +nbtk_widget_recompute_style (NbtkWidget *widget, + ShellThemeNode *old_theme_node) +{ + ShellThemeNode *new_theme_node = nbtk_widget_get_theme_node (widget); + + if (!old_theme_node || + !shell_theme_node_geometry_equal (old_theme_node, new_theme_node)) + clutter_actor_queue_relayout ((ClutterActor *) widget); + + g_signal_emit (widget, signals[STYLE_CHANGED], 0); + widget->priv->is_style_dirty = FALSE; +} + /** * nbtk_widget_ensure_style: * @widget: A #NbtkWidget @@ -1080,10 +1083,7 @@ nbtk_widget_ensure_style (NbtkWidget *widget) g_return_if_fail (NBTK_IS_WIDGET (widget)); if (widget->priv->is_style_dirty) - { - g_signal_emit (widget, signals[STYLE_CHANGED], 0); - widget->priv->is_style_dirty = FALSE; - } + nbtk_widget_recompute_style (widget, NULL); } /** @@ -1120,25 +1120,6 @@ nbtk_widget_get_background_image (NbtkWidget *actor) return priv->background_image; } -/** - * nbtk_widget_get_padding: - * @widget: A #NbtkWidget - * @padding: A pointer to an #NbtkPadding to fill - * - * Gets the padding of the widget, set using the "padding" CSS property. This - * function should normally only be used by subclasses. - * - */ -void -nbtk_widget_get_padding (NbtkWidget *widget, - NbtkPadding *padding) -{ - g_return_if_fail (NBTK_IS_WIDGET (widget)); - g_return_if_fail (padding != NULL); - - *padding = widget->priv->padding; -} - /** * nbtk_widget_set_has_tooltip: * @widget: A #NbtkWidget diff --git a/src/nbtk/nbtk-widget.h b/src/nbtk/nbtk-widget.h index cc303ad2a..849efc348 100644 --- a/src/nbtk/nbtk-widget.h +++ b/src/nbtk/nbtk-widget.h @@ -111,8 +111,6 @@ ShellThemeNode *nbtk_widget_get_theme_node (NbtkWidget *widget); ClutterActor *nbtk_widget_get_background_image (NbtkWidget *actor); ClutterActor *nbtk_widget_get_border_image (NbtkWidget *actor); -void nbtk_widget_get_padding (NbtkWidget *widget, - NbtkPadding *padding); void nbtk_widget_draw_background (NbtkWidget *widget); G_END_DECLS diff --git a/src/toolkit/shell-theme-node.c b/src/toolkit/shell-theme-node.c index 0e919fcd3..bb2f90c4c 100644 --- a/src/toolkit/shell-theme-node.c +++ b/src/toolkit/shell-theme-node.c @@ -1,5 +1,6 @@ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +#include #include #include @@ -1919,3 +1920,183 @@ shell_theme_node_get_background_theme_image (ShellThemeNode *node) return NULL; } + +static float +get_width_inc (ShellThemeNode *node) +{ + return (round (node->border_width[SHELL_SIDE_LEFT]) + node->padding[SHELL_SIDE_LEFT] + + round (node->border_width[SHELL_SIDE_RIGHT]) + node->padding[SHELL_SIDE_RIGHT]); +} + +static float +get_height_inc (ShellThemeNode *node) +{ + return (round (node->border_width[SHELL_SIDE_TOP]) + node->padding[SHELL_SIDE_TOP] + + round (node->border_width[SHELL_SIDE_BOTTOM]) + node->padding[SHELL_SIDE_BOTTOM]); +} + +/** + * shell_theme_node_adjust_for_height: + * @node: a #ShellThemeNode + * @for_height: (inout): the "for height" to adjust + * + * Adjusts a "for height" passed to clutter_actor_get_preferred_width() to + * account for borders and padding. This is a convenience function meant + * to be called from a get_preferred_width() method of a #ClutterActor + * subclass. The value after adjustment is the height available for the actor's + * content. + */ +void +shell_theme_node_adjust_for_height (ShellThemeNode *node, + float *for_height) +{ + g_return_if_fail (SHELL_IS_THEME_NODE (node)); + g_return_if_fail (for_height != NULL); + + if (*for_height >= 0) + { + float height_inc = get_height_inc (node); + *for_height = MAX (0, *for_height - height_inc); + } +} + +/** + * shell_theme_node_adjust_preferred_width: + * @node: a #ShellThemeNode + * @min_width_p: (inout) (allow-none): the width to adjust + * @for_height: (inout): the height to adjust + * + * Adjusts the minimum and natural width computed for an actor by + * adding on the necessary space for borders and padding. This is a + * convenience function meant to be called from the get_preferred_width() + * method of a #ClutterActor subclass + */ +void +shell_theme_node_adjust_preferred_width (ShellThemeNode *node, + float *min_width_p, + float *natural_width_p) +{ + float width_inc; + + g_return_if_fail (SHELL_IS_THEME_NODE (node)); + + ensure_borders (node); + + width_inc = get_width_inc (node); + + if (min_width_p) + *min_width_p += width_inc; + if (natural_width_p) + *natural_width_p += width_inc; +} + +/** + * shell_theme_node_adjust_for_width: + * @node: a #ShellThemeNode + * @for_width: (inout): the "for width" to adjust + * + * Adjusts a "for width" passed to clutter_actor_get_preferred_height() to + * account for borders and padding. This is a convenience function meant + * to be called from a get_preferred_height() method of a #ClutterActor + * subclass. The value after adjustmnet is the width available for the actor's + * content. + */ +void +shell_theme_node_adjust_for_width (ShellThemeNode *node, + float *for_width) +{ + g_return_if_fail (SHELL_IS_THEME_NODE (node)); + g_return_if_fail (for_width != NULL); + + if (*for_width >= 0) + { + float width_inc = get_width_inc (node); + *for_width = MAX (0, *for_width - width_inc); + } +} + +/** + * shell_theme_node_adjust_preferred_height: + * @node: a #ShellThemeNode + * @min_height_p: (inout) (allow-none): the height to adjust + * @for_height: (inout): the height to adjust + * + * Adjusts the minimum and natural height computed for an actor by + * adding on the necessary space for borders and padding. This is a + * convenience function meant to be called from the get_preferred_height() + * method of a #ClutterActor subclass + */ +void +shell_theme_node_adjust_preferred_height (ShellThemeNode *node, + float *min_height_p, + float *natural_height_p) +{ + float height_inc; + + g_return_if_fail (SHELL_IS_THEME_NODE (node)); + + ensure_borders (node); + + height_inc = get_height_inc (node); + + if (min_height_p) + *min_height_p += height_inc; + if (natural_height_p) + *natural_height_p += height_inc; +} + +/** + * shell_theme_node_get_content_box: + * @node: a #ShellThemeNode + * @allocation: the box allocated to a #ClutterAlctor + * @content_box: (out): computed box occupied by the actor's content + * + * Gets the box within an actor's allocation that contents the content + * of an actor (excluding borders and padding). This is a convenience function + * meant to be used from the allocate() or paint() methods of a #ClutterActor + * subclass. + */ +void +shell_theme_node_get_content_box (ShellThemeNode *node, + const ClutterActorBox *allocation, + ClutterActorBox *content_box) +{ + g_return_if_fail (SHELL_IS_THEME_NODE (node)); + + ensure_borders (node); + + content_box->x1 = round (node->border_width[SHELL_SIDE_LEFT]) + node->padding[SHELL_SIDE_LEFT]; + content_box->y1 = round (node->border_width[SHELL_SIDE_TOP]) + node->padding[SHELL_SIDE_TOP]; + content_box->x2 = allocation->x2 - allocation->x1 - (round (node->border_width[SHELL_SIDE_RIGHT]) + node->padding[SHELL_SIDE_RIGHT]); + content_box->y2 = allocation->y2 - allocation->y1 - (round (node->border_width[SHELL_SIDE_BOTTOM]) + node->padding[SHELL_SIDE_BOTTOM]); +} + + +/** + * shell_theme_node_geometry_equal: + * @node: a #ShellThemeNode + * @node: a different #ShellThemeNode + * + * Tests if two theme nodes have the same borders and padding; this can be + * used to optimize having to relayout when the style applied to a Clutter + * actor changes colors without changing the geometry. + */ +gboolean +shell_theme_node_geometry_equal (ShellThemeNode *node, + ShellThemeNode *other) +{ + ShellSide side; + + ensure_borders (node); + ensure_borders (other); + + for (side = SHELL_SIDE_TOP; side <= SHELL_SIDE_LEFT; side++) + { + if (node->border_width[side] != other->border_width[side]) + return FALSE; + if (node->padding[side] != other->padding[side]) + return FALSE; + } + + return TRUE; +} diff --git a/src/toolkit/shell-theme-node.h b/src/toolkit/shell-theme-node.h index a05d68af5..a2e2452a3 100644 --- a/src/toolkit/shell-theme-node.h +++ b/src/toolkit/shell-theme-node.h @@ -121,6 +121,26 @@ const PangoFontDescription *shell_theme_node_get_font (ShellThemeNode *node); */ ShellThemeImage *shell_theme_node_get_background_theme_image (ShellThemeNode *node); +/* Helpers for get_preferred_width()/get_preferred_height() ClutterActor vfuncs */ +void shell_theme_node_adjust_for_height (ShellThemeNode *node, + float *for_height); +void shell_theme_node_adjust_preferred_width (ShellThemeNode *node, + float *min_width_p, + float *natural_width_p); +void shell_theme_node_adjust_for_width (ShellThemeNode *node, + float *for_width); +void shell_theme_node_adjust_preferred_height (ShellThemeNode *node, + float *min_height_p, + float *natural_height_p); + +/* Helper for allocate() ClutterActor vfunc */ +void shell_theme_node_get_content_box (ShellThemeNode *node, + const ClutterActorBox *actor_box, + ClutterActorBox *content_box); + +gboolean shell_theme_node_geometry_equal (ShellThemeNode *node, + ShellThemeNode *other); + G_END_DECLS #endif /* __SHELL_THEME_NODE_H__ */