[gnome-shell/nbtk-introduction] Centralize computations of border and padding into ShellThemeNode



commit e1390c7dd5f24bffb83e5953cc8375feb5bdac6b
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Sun Sep 20 13:41:13 2009 -0400

    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     |  170 ++++++++++++++++++++------------------
 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, 446 insertions(+), 384 deletions(-)
---
diff --git a/src/nbtk/nbtk-bin.c b/src/nbtk/nbtk-bin.c
index c0bde1c..928c183 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;
 
-      _nbtk_bin_get_align_factors (NBTK_BIN (self), &x_align, &y_align);
+      shell_theme_node_get_content_box (theme_node, box, &content_box);
 
-      nbtk_widget_get_padding (NBTK_WIDGET (self), &padding);
+      _nbtk_bin_get_align_factors (NBTK_BIN (self), &x_align, &y_align);
 
-      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, };
-
-  nbtk_widget_get_padding (NBTK_WIDGET (self), &padding);
+  ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self));
 
-  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 8df6fb5..8f9f246 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, };
-  gint n_children = 0;
-  GList *l;
+  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);
 
-  if (min_height_p)
-    *min_height_p = padding.top + padding.bottom;
+  get_content_preferred_width (NBTK_BOX_LAYOUT (actor), for_height,
+                               min_width_p, natural_width_p);
 
-  if (natural_height_p)
-    *natural_height_p = padding.top + padding.bottom;
+  shell_theme_node_adjust_preferred_width (theme_node,
+                                           min_width_p, natural_width_p);
+}
 
-  if (priv->children == NULL)
-    return;
+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;
+
+  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);
+
+  avail_width  = content_box.x2 - content_box.x1;
+  avail_height = content_box.y2 - content_box.y1;
 
-  nbtk_box_layout_get_preferred_height (actor, avail_width, NULL,
-                                        &pref_height);
-  nbtk_box_layout_get_preferred_width (actor, avail_height, NULL,
-                                       &pref_width);
+  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 286d4c1..dd1c864 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);
+
+  avail_h = content_box.y2 - content_box.y1;
 
-  child_box.x1 = padding.left;
-  child_box.x2 = box->x2 - box->x1 - padding.right;
+  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 a563bc3..ad6b7a1 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 8800f0f..34b4144 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 e57e1cf..f40e7a6 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 1f832d7..e3ac32d 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 bb7eee4..a72e604 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 7295afe..f917ed1 100644
--- a/src/nbtk/nbtk-widget.c
+++ b/src/nbtk/nbtk-widget.c
@@ -27,6 +27,7 @@
 #include "config.h"
 #endif
 
+#include <math.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -41,15 +42,13 @@
 #include "nbtk-tooltip.h"
 
 #include <toolkit/shell-theme-context.h>
+#include <big/rectangle.h>
 
 /*
  * 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);
 }
 
 /**
@@ -1121,25 +1121,6 @@ nbtk_widget_get_background_image (NbtkWidget *actor)
 }
 
 /**
- * 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
  * @has_tooltip: #TRUE if the widget should display a tooltip
diff --git a/src/nbtk/nbtk-widget.h b/src/nbtk/nbtk-widget.h
index cc303ad..849efc3 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 0e919fc..bb2f90c 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 <math.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -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 a05d68a..a2e2452 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__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]