[gnome-shell/nbtk-introduction] Port our imported parts of Nbtk to ShellTheme



commit db0c2b5959ac8a326e27430fede4c198b72bce65
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Sat Sep 19 21:10:15 2009 -0400

    Port our imported parts of Nbtk to ShellTheme
    
    ShellTheme replaces both NbtkStyle and ccss_stylesheet_t.
    
    The interface NbtkStylable is replaced by usage of ShellThemeNode.
    A concrete node class allows some significant optimizations of property
    inheritance that would have been much more difficult to achieve with
    the highly abstract pair of NbtkStylable and ccss_node_t.
    
    Some operations that were previously on NbtkStylable (like the
    ::style-changed signal) are directly on NtkWidget.
    
    Custom properties are no longer registered as param-specs; instead you
    call directly into shell theme node to look up a length or color:
    
    shell_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing);
    
    The dependency on libccss is dropped, while preserving all existing
    functionality and adding proper parsing and inheritance of font properties
    and proper inheritance for the 'color' property.
    
    Some more javascript tests for CSS functionality are added; workarounds for
    a CSS bug where *.some-class was needed instead of .some-class are removed.

 configure.ac                   |    2 +-
 data/theme/gnome-shell.css     |   16 +-
 js/ui/main.js                  |    5 +-
 src/Makefile-nbtk.am           |    4 -
 src/Makefile.am                |   28 ++-
 src/nbtk/nbtk-bin.c            |    1 -
 src/nbtk/nbtk-button.c         |  131 ++-----
 src/nbtk/nbtk-entry.c          |  102 +----
 src/nbtk/nbtk-label.c          |   53 +--
 src/nbtk/nbtk-scroll-bar.c     |   62 +---
 src/nbtk/nbtk-scroll-view.c    |   88 ++---
 src/nbtk/nbtk-stylable.c       |  849 ----------------------------------------
 src/nbtk/nbtk-stylable.h       |  123 ------
 src/nbtk/nbtk-style.c          |  742 -----------------------------------
 src/nbtk/nbtk-style.h          |   94 -----
 src/nbtk/nbtk-tooltip.c        |   49 +--
 src/nbtk/nbtk-types.h          |    3 -
 src/nbtk/nbtk-widget.c         |  536 ++++++++++---------------
 src/nbtk/nbtk-widget.h         |   10 +
 tests/Makefile.am              |    1 +
 tests/interactive/css-fonts.js |   39 ++
 tests/interactive/scrolling.js |   28 ++
 tests/run-test.sh.in           |    2 +-
 tests/testcommon/test.css      |   26 ++-
 tests/testcommon/ui.js         |    7 +-
 25 files changed, 495 insertions(+), 2506 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index ad6b87a..30b26a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,7 +57,7 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin
                                  gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
                                  gobject-introspection-1.0 >= 0.6.5)
 PKG_CHECK_MODULES(TIDY, clutter-1.0)
-PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 libccss-1 >= 0.3.1 clutter-imcontext-0.1)
+PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1)
 PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
 PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
 PKG_CHECK_MODULES(TOOLKIT, clutter-1.0 libcroco-0.6)
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 5c8f523..d89d6f5 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -25,38 +25,38 @@ NbtkScrollBar
 
 NbtkScrollView
 {
-  scrollbar-width: 16;
-  scrollbar-height: 16;
+  scrollbar-width: 16px;
+  scrollbar-height: 16px;
 }
 
 NbtkButton#up-stepper
 {
-  border-image: url("file://scroll-button-up.png") 5;
+  -shell-background-image: url("scroll-button-up.png") 5px;
 }
 
 NbtkButton#up-stepper:hover,
 NbtkButton#up-stepper:active
 {
-  border-image: url("file://scroll-button-up-hover.png") 5;
+  -shell-background-image: url("scroll-button-up-hover.png") 5px;
 }
 
 NbtkButton#down-stepper
 {
-  border-image: url("file://scroll-button-down.png") 5;
+  -shell-background-image: url("scroll-button-down.png") 5px;
 }
 
 NbtkButton#down-stepper:hover,
 NbtkButton#down-stepper:active
 {
-  border-image: url("file://scroll-button-down-hover.png") 5;
+  -shell-background-image: url("scroll-button-down-hover.png") 5px;
 }
 
 NbtkScrollBar NbtkButton#vhandle
 {
-  border-image: url("file://scroll-vhandle.png") 5;
+  -shell-background-image: url("scroll-vhandle.png") 5px;
 }
 
 NbtkScrollBar NbtkButton#vhandle:hover
 {
-  border-image: url("file://scroll-vhandle.png") 5;
+  -shell-background-image: url("scroll-vhandle.png") 5px;
 }
diff --git a/js/ui/main.js b/js/ui/main.js
index 56dfeff..c39e3c3 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -67,9 +67,10 @@ function start() {
     for (let i = 0; i < children.length; i++)
         children[i].destroy();
 
-    let style = Nbtk.Style.get_default();
+    let themeContext = Shell.ThemeContext.get_for_stage (global.stage);
     let stylesheetPath = global.datadir + "/theme/gnome-shell.css";
-    style.load_from_file(stylesheetPath);
+    let theme = new Shell.Theme ({ application_stylesheet: stylesheetPath });
+    themeContext.set_theme (theme);
 
     global.connect('panel-run-dialog', function(panel) {
         // Make sure not more than one run dialog is shown.
diff --git a/src/Makefile-nbtk.am b/src/Makefile-nbtk.am
index b690cf7..685473d 100644
--- a/src/Makefile-nbtk.am
+++ b/src/Makefile-nbtk.am
@@ -76,8 +76,6 @@ nbtk_source_h =                  \
     nbtk/nbtk-scrollable.h            \
     nbtk/nbtk-scroll-bar.h            \
     nbtk/nbtk-scroll-view.h           \
-    nbtk/nbtk-stylable.h              \
-    nbtk/nbtk-style.h                 \
     nbtk/nbtk-subtexture.h            \
     nbtk/nbtk-texture-cache.h         \
     nbtk/nbtk-texture-frame.h         \
@@ -101,8 +99,6 @@ nbtk_source_c =                  \
     nbtk/nbtk-scrollable.c            \
     nbtk/nbtk-scroll-bar.c            \
     nbtk/nbtk-scroll-view.c           \
-    nbtk/nbtk-stylable.c              \
-    nbtk/nbtk-style.c                 \
     nbtk/nbtk-subtexture.c            \
     nbtk/nbtk-texture-cache.c         \
     nbtk/nbtk-texture-frame.c         \
diff --git a/src/Makefile.am b/src/Makefile.am
index dfa827c..6ec7d4d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -212,12 +212,35 @@ Big-1.0.typelib: libbig-1.0.la Big-1.0.gir
 	$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@
 CLEANFILES += Big-1.0.typelib
 
+toolkit_gir_sources = \
+	$(filter-out $(non_gir_toolkit_sources), $(toolkit_sources))
+
+# Since the Shell namepace includes both the code in toolkit/ that our fork of
+# NBTK depends upon and the code in this directory that depends on NBTK, We have a
+# circular dependency when generating the girs and typelibs. We work around this
+# by generating a Toolkit gir, using it to build the Nbtk gir then sed'ing the
+# reference out of the generated gir.
+Toolkit-0.1.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libshell-toolkit.la Makefile
+	$(AM_V_GEN) $(G_IR_SCANNER)						\
+	        --namespace=Shell						\
+		--nsversion=0.1							\
+	        --include=Clutter-1.0						\
+	        --libtool="$(LIBTOOL)"						\
+	        --program=mutter						\
+		--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la	\
+	        $(addprefix $(srcdir)/,$(toolkit_gir_sources))			\
+	        $(TOOLKIT_CFLAGS)						\
+	        -o $@
+CLEANFILES += Toolkit-1.0.gir
+
 Nbtk-1.0.gir: $(mutter) $(G_IR_SCANNER) Toolkit-0.1.gir libgnome-shell.la libnbtk-1.0.la Makefile
 	$(AM_V_GEN) $(G_IR_SCANNER)						\
 	        --namespace=Nbtk						\
 	        --nsversion=1.0							\
 	        --include=Clutter-1.0						\
+	        --include=Gtk-2.0						\
 		--add-include-path=$(builddir)     				\
+		--include=Toolkit-0.1						\
 	        --libtool="$(LIBTOOL)"						\
 	        --program=mutter						\
 		--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la	\
@@ -226,11 +249,14 @@ Nbtk-1.0.gir: $(mutter) $(G_IR_SCANNER) Toolkit-0.1.gir libgnome-shell.la libnbt
 	        $(addprefix $(srcdir)/,$(nbtk_source_c))			\
 	        $(srcdir)/nbtk-enum-types.h					\
 	        $(NBTK_CFLAGS)							\
-	        -o $@
+	        -o $  tmp &&							\
+	sed -e '/"Toolkit"/d' < $  tmp > $@
 CLEANFILES += Nbtk-1.0.gir
 
 Nbtk-1.0.typelib: Nbtk-1.0.gir
 	$(AM_V_GEN) $(G_IR_COMPILER)						\
+		--includedir=.							\
+		--includedir=$(MUTTER_LIB_DIR)/mutter/				\
 		$< -o $@
 
 CLEANFILES += Nbtk-1.0.typelib
diff --git a/src/nbtk/nbtk-bin.c b/src/nbtk/nbtk-bin.c
index 03ad68c..c0bde1c 100644
--- a/src/nbtk/nbtk-bin.c
+++ b/src/nbtk/nbtk-bin.c
@@ -39,7 +39,6 @@
 #include "nbtk-bin.h"
 #include "nbtk-enum-types.h"
 #include "nbtk-private.h"
-#include "nbtk-stylable.h"
 
 #define NBTK_BIN_GET_PRIVATE(obj)       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_BIN, NbtkBinPrivate))
 
diff --git a/src/nbtk/nbtk-button.c b/src/nbtk/nbtk-button.c
index 558852d..812377d 100644
--- a/src/nbtk/nbtk-button.c
+++ b/src/nbtk/nbtk-button.c
@@ -1,8 +1,6 @@
-/*
- * nbtk-button.c: Plain button actor
- *
+/*-button.c: Plain button actor
  * Copyright 2007 OpenedHand
- * Copyright 2008, 2009 Intel Corporation.
+ * Copyright , 2009 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU Lesser General Public License,
@@ -34,6 +32,7 @@
 #include "config.h"
 #endif
 
+#include <math.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -44,8 +43,6 @@
 #include "nbtk-button.h"
 
 #include "nbtk-marshal.h"
-#include "nbtk-stylable.h"
-#include "nbtk-style.h"
 #include "nbtk-texture-frame.h"
 #include "nbtk-texture-cache.h"
 #include "nbtk-private.h"
@@ -93,51 +90,16 @@ struct _NbtkButtonPrivate
 
 static guint button_signals[LAST_SIGNAL] = { 0, };
 
-static void nbtk_stylable_iface_init (NbtkStylableIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (NbtkButton, nbtk_button, NBTK_TYPE_BIN,
-                         G_IMPLEMENT_INTERFACE (NBTK_TYPE_STYLABLE,
-                                                nbtk_stylable_iface_init));
-
-static void
-nbtk_stylable_iface_init (NbtkStylableIface *iface)
-{
-  static gboolean is_initialized = FALSE;
-
-  if (G_UNLIKELY (!is_initialized))
-    {
-      ClutterColor bg_color = { 0xcc, 0xcc, 0xcc, 0x00 };
-      GParamSpec *pspec;
-
-      is_initialized = TRUE;
-
-      pspec = g_param_spec_int ("border-spacing",
-                                "Border Spacing",
-                                "Spacing between internal elements",
-                                0, G_MAXINT, 6,
-                                G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_BUTTON, pspec);
-
-
-      is_initialized = TRUE;
-
-      pspec = clutter_param_spec_color ("background-color",
-                                        "Background Color",
-                                        "The background color of an actor",
-                                        &bg_color,
-                                        G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_BUTTON, pspec);
-    }
-}
+G_DEFINE_TYPE (NbtkButton, nbtk_button, NBTK_TYPE_BIN);
 
 static void
 nbtk_button_update_label_style (NbtkButton *button)
 {
-  ClutterColor *real_color = NULL;
-  gchar *font_string = NULL;
-  gchar *font_name = NULL;
-  gint font_size = 0;
   ClutterActor *label;
+  ShellThemeNode *theme_node;
+  ClutterColor color;
+  const PangoFontDescription *font;
+  gchar *font_string = NULL;
 
   label = nbtk_bin_get_child ((NbtkBin*) button);
 
@@ -145,37 +107,15 @@ nbtk_button_update_label_style (NbtkButton *button)
   if (!CLUTTER_IS_TEXT (label))
     return;
 
-  nbtk_stylable_get (NBTK_STYLABLE (button),
-                     "color", &real_color,
-                     "font-family", &font_name,
-                     "font-size", &font_size,
-                     NULL);
-
-  if (font_name || font_size)
-    {
-      if (font_name && font_size)
-        font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
-      else
-        {
-          if (font_size)
-            font_string = g_strdup_printf ("%dpx", font_size);
-          else
-            font_string = font_name;
-        }
-
-      clutter_text_set_font_name (CLUTTER_TEXT (label), font_string);
-
-      if (font_string != font_name)
-        g_free (font_string);
-    }
+  theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button));
 
-  g_free (font_name);
+  shell_theme_node_get_foreground_color (theme_node, &color);
+  clutter_text_set_color (CLUTTER_TEXT (label), &color);
 
-  if (real_color)
-    {
-      clutter_text_set_color (CLUTTER_TEXT (label), real_color);
-      clutter_color_free (real_color);
-    }
+  font = shell_theme_node_get_font (theme_node);
+  font_string = pango_font_description_to_string (font);
+  clutter_text_set_font_name (CLUTTER_TEXT (label), font_string);
+  g_free (font_string);
 }
 
 static void
@@ -196,19 +136,6 @@ nbtk_button_dispose_old_bg (NbtkButton *button)
 }
 
 static void
-nbtk_button_stylable_changed (NbtkStylable *stylable)
-{
-  NbtkButton *button = NBTK_BUTTON (stylable);
-  ClutterActor *bg_image;
-
-  nbtk_button_dispose_old_bg (button);
-
-  bg_image = nbtk_widget_get_border_image ((NbtkWidget*) button);
-  if (bg_image)
-    button->priv->old_bg = g_object_ref (bg_image);
-}
-
-static void
 nbtk_animation_completed (ClutterAnimation  *animation,
                           NbtkButton        *button)
 {
@@ -221,11 +148,21 @@ nbtk_button_style_changed (NbtkWidget *widget)
   NbtkButton *button = NBTK_BUTTON (widget);
   NbtkButtonPrivate *priv = button->priv;
   NbtkButtonClass *button_class = NBTK_BUTTON_GET_CLASS (button);
+  ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button));
+  ClutterActor *bg_image;
+  double spacing;
+
+  nbtk_button_dispose_old_bg (button);
+
+  bg_image = nbtk_widget_get_border_image ((NbtkWidget*) button);
+  if (bg_image)
+    button->priv->old_bg = g_object_ref (bg_image);
 
-  /* get the spacing value */
-  nbtk_stylable_get (NBTK_STYLABLE (widget),
-                     "border-spacing", &priv->spacing,
-                     NULL);
+  NBTK_WIDGET_CLASS (nbtk_button_parent_class)->style_changed (widget);
+
+  spacing = 6;
+  shell_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing);
+  priv->spacing = round (spacing);
 
   /* update the label styling */
   nbtk_button_update_label_style (button);
@@ -526,6 +463,7 @@ nbtk_button_class_init (NbtkButtonClass *klass)
   actor_class->unmap = nbtk_button_unmap;
 
   widget_class->draw_background = nbtk_button_draw_background;
+  widget_class->style_changed = nbtk_button_style_changed;
 
   pspec = g_param_spec_string ("label",
                                "Label",
@@ -579,12 +517,6 @@ nbtk_button_init (NbtkButton *button)
   button->priv->spacing = 6;
 
   clutter_actor_set_reactive ((ClutterActor *) button, TRUE);
-
-  g_signal_connect (button, "style-changed",
-                    G_CALLBACK (nbtk_button_style_changed), NULL);
-
-  g_signal_connect (button, "stylable-changed",
-                    G_CALLBACK (nbtk_button_stylable_changed), NULL);
 }
 
 /**
@@ -672,7 +604,8 @@ nbtk_button_set_label (NbtkButton  *button,
       nbtk_bin_set_child ((NbtkBin*) button, label);
     }
 
-  nbtk_stylable_changed ((NbtkStylable*) button);
+  /* Fake a style change so that we reset the style properties on the label */
+  nbtk_widget_style_changed (NBTK_WIDGET (button));
 
   g_object_notify (G_OBJECT (button), "label");
 }
diff --git a/src/nbtk/nbtk-entry.c b/src/nbtk/nbtk-entry.c
index e71efac..286d4c1 100644
--- a/src/nbtk/nbtk-entry.c
+++ b/src/nbtk/nbtk-entry.c
@@ -57,7 +57,6 @@
 #include "nbtk-entry.h"
 
 #include "nbtk-widget.h"
-#include "nbtk-stylable.h"
 #include "nbtk-texture-cache.h"
 #include "nbtk-marshal.h"
 #include "nbtk-clipboard.h"
@@ -100,11 +99,7 @@ struct _NbtkEntryPrivate
 
 static guint entry_signals[LAST_SIGNAL] = { 0, };
 
-static void nbtk_stylable_iface_init (NbtkStylableIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (NbtkEntry, nbtk_entry, NBTK_TYPE_WIDGET,
-                         G_IMPLEMENT_INTERFACE (NBTK_TYPE_STYLABLE,
-                                                nbtk_stylable_iface_init));
+G_DEFINE_TYPE (NbtkEntry, nbtk_entry, NBTK_TYPE_WIDGET);
 
 static void
 nbtk_entry_set_property (GObject      *gobject,
@@ -175,90 +170,31 @@ nbtk_entry_finalize (GObject *object)
 }
 
 static void
-nbtk_stylable_iface_init (NbtkStylableIface *iface)
-{
-  static gboolean is_initialized = FALSE;
-
-  if (!is_initialized)
-    {
-      GParamSpec *pspec;
-      static const ClutterColor default_color
-        = { 0x0, 0x9c, 0xcf, 0xff };
-
-      is_initialized = TRUE;
-
-      pspec = clutter_param_spec_color ("caret-color",
-                                        "Caret Color",
-                                        "Color of the entry's caret",
-                                        &default_color,
-                                        G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_ENTRY, pspec);
-
-      pspec = clutter_param_spec_color ("selection-background-color",
-                                        "Selection Background Color",
-                                        "Color of the entry's selection",
-                                        &default_color,
-                                        G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_ENTRY, pspec);
-    }
-}
-
-static void
 nbtk_entry_style_changed (NbtkWidget *self)
 {
   NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (self);
-  ClutterColor *color = NULL;
-  ClutterColor *caret_color = NULL;
-  ClutterColor *selection_background_color = NULL;
-  gchar *font_name;
+  ShellThemeNode *theme_node;
+  ClutterColor color;
+  const PangoFontDescription *font;
   gchar *font_string;
-  gint font_size;
 
-  nbtk_stylable_get (NBTK_STYLABLE (self),
-                     "color", &color,
-                     "caret-color", &caret_color,
-                     "selection-background-color", &selection_background_color,
-                     "font-family", &font_name,
-                     "font-size", &font_size,
-                     NULL);
+  theme_node = nbtk_widget_get_theme_node (self);
 
-  if (color)
-    {
-      clutter_text_set_color (CLUTTER_TEXT (priv->entry), color);
-      clutter_color_free (color);
-    }
+  shell_theme_node_get_foreground_color (theme_node, &color);
+  clutter_text_set_color (CLUTTER_TEXT (priv->entry), &color);
 
-  if (caret_color)
-    {
-      clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), caret_color);
-      clutter_color_free (caret_color);
-    }
+  if (shell_theme_node_get_color (theme_node, "caret-color", FALSE, &color))
+      clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), &color);
 
-  if (selection_background_color)
-    {
-      clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry),
-                                        selection_background_color);
-      clutter_color_free (selection_background_color);
-    }
+  if (shell_theme_node_get_color (theme_node, "selection-background-color", FALSE, &color))
+    clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry), &color);
 
-  if (font_name || font_size)
-    {
-      if (font_name && font_size)
-        {
-          font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
-          g_free (font_name);
-        }
-      else
-        {
-          if (font_size)
-            font_string = g_strdup_printf ("%dpx", font_size);
-          else
-            font_string = font_name;
-        }
+  font = shell_theme_node_get_font (theme_node);
+  font_string = pango_font_description_to_string (font);
+  clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string);
+  g_free (font_string);
 
-      clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string);
-      g_free (font_string);
-    }
+  NBTK_WIDGET_CLASS (nbtk_entry_parent_class)->style_changed (self);
 }
 
 static void
@@ -635,6 +571,7 @@ nbtk_entry_class_init (NbtkEntryClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass);
   GParamSpec *pspec;
 
   g_type_class_add_private (klass, sizeof (NbtkEntryPrivate));
@@ -655,6 +592,8 @@ nbtk_entry_class_init (NbtkEntryClass *klass)
   actor_class->key_press_event = nbtk_entry_key_press_event;
   actor_class->key_focus_in = nbtk_entry_key_focus_in;
 
+  widget_class->style_changed = nbtk_entry_style_changed;
+
   pspec = g_param_spec_string ("text",
                                "Text",
                                "Text of the entry",
@@ -724,9 +663,6 @@ nbtk_entry_init (NbtkEntry *entry)
 
   /* set cursor hidden until we receive focus */
   clutter_text_set_cursor_visible ((ClutterText *) priv->entry, FALSE);
-
-  g_signal_connect (entry, "style-changed",
-                    G_CALLBACK (nbtk_entry_style_changed), NULL);
 }
 
 /**
diff --git a/src/nbtk/nbtk-label.c b/src/nbtk/nbtk-label.c
index 1a4a63b..a563bc3 100644
--- a/src/nbtk/nbtk-label.c
+++ b/src/nbtk/nbtk-label.c
@@ -44,7 +44,6 @@
 #include "nbtk-label.h"
 
 #include "nbtk-widget.h"
-#include "nbtk-stylable.h"
 
 enum
 {
@@ -105,43 +104,23 @@ nbtk_label_get_property (GObject    *gobject,
 static void
 nbtk_label_style_changed (NbtkWidget *self)
 {
-  NbtkLabelPrivate *priv = NBTK_LABEL (self)->priv;
-  ClutterColor *color = NULL;
-  gchar *font_name;
+  NbtkLabelPrivate *priv;
+  ShellThemeNode *theme_node;
+  ClutterColor color;
+  const PangoFontDescription *font;
   gchar *font_string;
-  gint font_size;
-
-  nbtk_stylable_get (NBTK_STYLABLE (self),
-                     "color", &color,
-                     "font-family", &font_name,
-                     "font-size", &font_size,
-                     NULL);
 
-  if (color)
-    {
-      clutter_text_set_color (CLUTTER_TEXT (priv->label), color);
-      clutter_color_free (color);
-    }
+  priv = NBTK_LABEL (self)->priv;
+  theme_node = nbtk_widget_get_theme_node (self);
+  shell_theme_node_get_foreground_color (theme_node, &color);
+  clutter_text_set_color (CLUTTER_TEXT (priv->label), &color);
 
-  if (font_name || font_size)
-    {
-      if (font_name && font_size)
-        {
-          font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
-          g_free (font_name);
-        }
-      else
-        {
-          if (font_size)
-            font_string = g_strdup_printf ("%dpx", font_size);
-          else
-            font_string = font_name;
-        }
-
-      clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string);
-      g_free (font_string);
-    }
+  font = shell_theme_node_get_font (theme_node);
+  font_string = pango_font_description_to_string (font);
+  clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string);
+  g_free (font_string);
 
+  NBTK_WIDGET_CLASS (nbtk_label_parent_class)->style_changed (self);
 }
 
 static void
@@ -248,6 +227,7 @@ nbtk_label_class_init (NbtkLabelClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass);
   GParamSpec *pspec;
 
   g_type_class_add_private (klass, sizeof (NbtkLabelPrivate));
@@ -262,6 +242,8 @@ nbtk_label_class_init (NbtkLabelClass *klass)
   actor_class->map = nbtk_label_map;
   actor_class->unmap = nbtk_label_unmap;
 
+  widget_class->style_changed = nbtk_label_style_changed;
+
   pspec = g_param_spec_string ("text",
                                "Text",
                                "Text of the label",
@@ -282,9 +264,6 @@ nbtk_label_init (NbtkLabel *label)
                                      NULL);
 
   clutter_actor_set_parent (priv->label, CLUTTER_ACTOR (label));
-
-  g_signal_connect (label, "style-changed",
-                    G_CALLBACK (nbtk_label_style_changed), NULL);
 }
 
 /**
diff --git a/src/nbtk/nbtk-scroll-bar.c b/src/nbtk/nbtk-scroll-bar.c
index 3215844..8800f0f 100644
--- a/src/nbtk/nbtk-scroll-bar.c
+++ b/src/nbtk/nbtk-scroll-bar.c
@@ -31,16 +31,11 @@
 #include "nbtk-scroll-bar.h"
 #include "nbtk-bin.h"
 #include "nbtk-marshal.h"
-#include "nbtk-stylable.h"
 #include "nbtk-enum-types.h"
 #include "nbtk-private.h"
 #include "nbtk-button.h"
 
-static void nbtk_stylable_iface_init (NbtkStylableIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (NbtkScrollBar, nbtk_scroll_bar, NBTK_TYPE_BIN,
-                         G_IMPLEMENT_INTERFACE (NBTK_TYPE_STYLABLE,
-                                                nbtk_stylable_iface_init))
+G_DEFINE_TYPE (NbtkScrollBar, nbtk_scroll_bar, NBTK_TYPE_BIN)
 
 #define NBTK_SCROLL_BAR_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_SCROLL_BAR, NbtkScrollBarPrivate))
 
@@ -336,10 +331,10 @@ nbtk_scroll_bar_allocate (ClutterActor          *actor,
 
   if (priv->adjustment)
     {
+      ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor));
       gfloat handle_size, position, avail_size;
-      gdouble value, lower, upper, page_size, increment;
+      gdouble value, lower, upper, page_size, increment, min_size, max_size;
       ClutterActorBox handle_box = { 0, };
-      guint min_size, max_size;
 
       nbtk_adjustment_get_values (priv->adjustment,
                                   &value,
@@ -355,10 +350,10 @@ nbtk_scroll_bar_allocate (ClutterActor          *actor,
       else
         increment = page_size / (upper - lower);
 
-      nbtk_stylable_get (NBTK_STYLABLE (actor),
-                         "min-size", &min_size,
-                         "max-size", &max_size,
-                         NULL);
+      min_size = 32.;
+      shell_theme_node_get_length (theme_node, "min-size", FALSE, &min_size);
+      max_size = G_MAXINT16;
+      shell_theme_node_get_length (theme_node, "max-size", FALSE, &max_size);
 
       if (upper - lower - page_size <= 0)
         position = 0;
@@ -407,11 +402,12 @@ nbtk_scroll_bar_style_changed (NbtkWidget *widget)
 {
   NbtkScrollBarPrivate *priv = NBTK_SCROLL_BAR (widget)->priv;
 
-  nbtk_stylable_changed ((NbtkStylable *) priv->bw_stepper);
-  nbtk_stylable_changed ((NbtkStylable *) priv->fw_stepper);
-  nbtk_stylable_changed ((NbtkStylable *) priv->trough);
-  nbtk_stylable_changed ((NbtkStylable *) priv->handle);
+  nbtk_widget_style_changed (NBTK_WIDGET (priv->bw_stepper));
+  nbtk_widget_style_changed (NBTK_WIDGET (priv->fw_stepper));
+  nbtk_widget_style_changed (NBTK_WIDGET (priv->trough));
+  nbtk_widget_style_changed (NBTK_WIDGET (priv->handle));
 
+  NBTK_WIDGET_CLASS (nbtk_scroll_bar_parent_class)->style_changed (widget);
 }
 
 static void
@@ -494,6 +490,7 @@ nbtk_scroll_bar_class_init (NbtkScrollBarClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass);
   GParamSpec *pspec;
 
   g_type_class_add_private (klass, sizeof (NbtkScrollBarPrivate));
@@ -510,6 +507,8 @@ nbtk_scroll_bar_class_init (NbtkScrollBarClass *klass)
   actor_class->map            = nbtk_scroll_bar_map;
   actor_class->unmap          = nbtk_scroll_bar_unmap;
 
+  widget_class->style_changed = nbtk_scroll_bar_style_changed;
+
   g_object_class_install_property
            (object_class,
             PROP_ADJUSTMENT,
@@ -546,35 +545,6 @@ nbtk_scroll_bar_class_init (NbtkScrollBarClass *klass)
 }
 
 static void
-nbtk_stylable_iface_init (NbtkStylableIface *iface)
-{
-  static gboolean is_initialized = FALSE;
-
-  if (!is_initialized)
-    {
-      GParamSpec *pspec;
-
-      is_initialized = TRUE;
-
-      pspec = g_param_spec_uint ("min-size",
-                                 "Minimum grabber size",
-                                 "Minimum size of the scroll grabber, in px",
-                                 0, G_MAXUINT, 32,
-                                 G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface,
-                                            NBTK_TYPE_SCROLL_BAR, pspec);
-
-      pspec = g_param_spec_uint ("max-size",
-                                 "Maximum grabber size",
-                                 "Maximum size of the scroll grabber, in px",
-                                 0, G_MAXINT16, G_MAXINT16,
-                                 G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface,
-                                            NBTK_TYPE_SCROLL_BAR, pspec);
-    }
-}
-
-static void
 move_slider (NbtkScrollBar *bar, gfloat x, gfloat y)
 {
   NbtkScrollBarPrivate *priv = bar->priv;
@@ -1035,8 +1005,6 @@ nbtk_scroll_bar_init (NbtkScrollBar *self)
 
   clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
 
-  g_signal_connect (self, "style-changed",
-                    G_CALLBACK (nbtk_scroll_bar_style_changed), NULL);
   g_signal_connect (self, "notify::reactive",
                     G_CALLBACK (nbtk_scroll_bar_notify_reactive), NULL);
 }
diff --git a/src/nbtk/nbtk-scroll-view.c b/src/nbtk/nbtk-scroll-view.c
index 22919a8..e57e1cf 100644
--- a/src/nbtk/nbtk-scroll-view.c
+++ b/src/nbtk/nbtk-scroll-view.c
@@ -26,24 +26,23 @@
 #include "nbtk-marshal.h"
 #include "nbtk-scroll-bar.h"
 #include "nbtk-scrollable.h"
-#include "nbtk-stylable.h"
 #include <clutter/clutter.h>
 
 static void clutter_container_iface_init (ClutterContainerIface *iface);
-static void nbtk_stylable_iface_init (NbtkStylableIface *iface);
 
 static ClutterContainerIface *nbtk_scroll_view_parent_iface = NULL;
 
 G_DEFINE_TYPE_WITH_CODE (NbtkScrollView, nbtk_scroll_view, NBTK_TYPE_BIN,
                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
-                                                clutter_container_iface_init)
-                         G_IMPLEMENT_INTERFACE (NBTK_TYPE_STYLABLE,
-                                                nbtk_stylable_iface_init))
+                                                clutter_container_iface_init))
 
 #define SCROLL_VIEW_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
                                 NBTK_TYPE_SCROLL_VIEW, \
                                 NbtkScrollViewPrivate))
 
+/* Default width (or height - the narrow dimension) for the scrollbars*/
+#define DEFAULT_SCROLLBAR_WIDTH 24
+
 struct _NbtkScrollViewPrivate
 {
   /* a pointer to the child; this is actually stored
@@ -165,6 +164,28 @@ nbtk_scroll_view_pick (ClutterActor *actor, const ClutterColor *color)
     clutter_actor_paint (priv->vscroll);
 }
 
+static double
+get_scrollbar_width (NbtkScrollView *scroll_view)
+{
+  ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (scroll_view));
+  double result = DEFAULT_SCROLLBAR_WIDTH;
+
+  shell_theme_node_get_length (theme_node, "scrollbar-width", FALSE, &result);
+
+  return result;
+}
+
+static double
+get_scrollbar_height (NbtkScrollView *scroll_view)
+{
+  ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (scroll_view));
+  double result = DEFAULT_SCROLLBAR_WIDTH;
+
+  shell_theme_node_get_length (theme_node, "scrollbar-height", FALSE, &result);
+
+  return result;
+}
+
 static void
 nbtk_scroll_view_get_preferred_width (ClutterActor *actor,
                                       gfloat        for_height,
@@ -172,7 +193,6 @@ nbtk_scroll_view_get_preferred_width (ClutterActor *actor,
                                       gfloat       *natural_width_p)
 {
   NbtkPadding padding;
-  guint xthickness;
 
   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv;
 
@@ -180,9 +200,6 @@ nbtk_scroll_view_get_preferred_width (ClutterActor *actor,
     return;
 
   nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
-  nbtk_stylable_get (NBTK_STYLABLE (actor),
-                     "scrollbar-width", &xthickness,
-                     NULL);
 
   /* Our natural width is the natural width of the child */
   clutter_actor_get_preferred_width (priv->child,
@@ -199,7 +216,7 @@ nbtk_scroll_view_get_preferred_width (ClutterActor *actor,
                                           NULL,
                                           &natural_height);
       if (for_height < natural_height)
-        *natural_width_p += xthickness;
+        *natural_width_p += get_scrollbar_width (NBTK_SCROLL_VIEW (actor));
     }
 
   /* Add space for padding */
@@ -217,7 +234,6 @@ nbtk_scroll_view_get_preferred_height (ClutterActor *actor,
                                        gfloat       *natural_height_p)
 {
   NbtkPadding padding;
-  guint ythickness;
 
   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (actor)->priv;
 
@@ -225,9 +241,6 @@ nbtk_scroll_view_get_preferred_height (ClutterActor *actor,
     return;
 
   nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
-  nbtk_stylable_get (NBTK_STYLABLE (actor),
-                     "scrollbar-height", &ythickness,
-                     NULL);
 
   /* Our natural height is the natural height of the child */
   clutter_actor_get_preferred_height (priv->child,
@@ -244,7 +257,7 @@ nbtk_scroll_view_get_preferred_height (ClutterActor *actor,
                                          NULL,
                                          &natural_width);
       if (for_width < natural_width)
-        *natural_height_p += ythickness;
+        *natural_height_p += get_scrollbar_height (NBTK_SCROLL_VIEW (actor));
     }
 
   /* Add space for padding */
@@ -285,10 +298,8 @@ nbtk_scroll_view_allocate (ClutterActor          *actor,
   avail_width = (box->x2 - box->x1) - padding.left - padding.right;
   avail_height = (box->y2 - box->y1) - padding.top - padding.bottom;
 
-  nbtk_stylable_get (NBTK_STYLABLE (actor),
-                     "scrollbar-width", &sb_width,
-                     "scrollbar-height", &sb_height,
-                     NULL);
+  sb_width = get_scrollbar_width (NBTK_SCROLL_VIEW (actor));
+  sb_height = get_scrollbar_width (NBTK_SCROLL_VIEW (actor));
 
   if (!CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll))
     sb_width = 0;
@@ -334,8 +345,10 @@ nbtk_scroll_view_style_changed (NbtkWidget *widget)
 {
   NbtkScrollViewPrivate *priv = NBTK_SCROLL_VIEW (widget)->priv;
 
-  nbtk_stylable_changed ((NbtkStylable *) priv->hscroll);
-  nbtk_stylable_changed ((NbtkStylable *) priv->vscroll);
+  nbtk_widget_style_changed (NBTK_WIDGET (priv->hscroll));
+  nbtk_widget_style_changed (NBTK_WIDGET (priv->vscroll));
+
+  NBTK_WIDGET_CLASS (nbtk_scroll_view_parent_class)->style_changed (widget);
 }
 
 static gboolean
@@ -418,6 +431,7 @@ nbtk_scroll_view_class_init (NbtkScrollViewClass *klass)
   GParamSpec *pspec;
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (NbtkScrollViewPrivate));
 
@@ -433,6 +447,8 @@ nbtk_scroll_view_class_init (NbtkScrollViewClass *klass)
   actor_class->allocate = nbtk_scroll_view_allocate;
   actor_class->scroll_event = nbtk_scroll_view_scroll_event;
 
+  widget_class->style_changed = nbtk_scroll_view_style_changed;
+
   g_object_class_install_property (object_class,
                                    PROP_HSCROLL,
                                    g_param_spec_object ("hscroll",
@@ -461,33 +477,6 @@ nbtk_scroll_view_class_init (NbtkScrollViewClass *klass)
 }
 
 static void
-nbtk_stylable_iface_init (NbtkStylableIface *iface)
-{
-  static gboolean is_initialized = FALSE;
-
-  if (!is_initialized)
-    {
-      GParamSpec *pspec;
-
-      is_initialized = TRUE;
-
-      pspec = g_param_spec_uint ("scrollbar-width",
-                                  "Vertical scroll-bar thickness",
-                                  "Thickness of vertical scrollbar, in px",
-                                  0, G_MAXUINT, 24,
-                                  G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_SCROLL_VIEW, pspec);
-
-      pspec = g_param_spec_uint ("scrollbar-height",
-                                  "Horizontal scroll-bar thickness",
-                                  "Thickness of horizontal scrollbar, in px",
-                                  0, G_MAXUINT, 24,
-                                  G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_SCROLL_VIEW, pspec);
-    }
-}
-
-static void
 child_adjustment_changed_cb (NbtkAdjustment *adjustment,
                              ClutterActor   *bar)
 {
@@ -594,9 +583,6 @@ nbtk_scroll_view_init (NbtkScrollView *self)
   priv->mouse_scroll = TRUE;
   g_object_set (G_OBJECT (self), "reactive", TRUE, "clip-to-allocation", TRUE,
                 NULL);
-
-  g_signal_connect (self, "style-changed",
-                    G_CALLBACK (nbtk_scroll_view_style_changed), NULL);
 }
 
 static void
diff --git a/src/nbtk/nbtk-tooltip.c b/src/nbtk/nbtk-tooltip.c
index 4bae527..1f832d7 100644
--- a/src/nbtk/nbtk-tooltip.c
+++ b/src/nbtk/nbtk-tooltip.c
@@ -44,7 +44,6 @@
 #include "nbtk-tooltip.h"
 
 #include "nbtk-widget.h"
-#include "nbtk-stylable.h"
 #include "nbtk-private.h"
 
 enum
@@ -120,44 +119,24 @@ nbtk_tooltip_get_property (GObject    *gobject,
 static void
 nbtk_tooltip_style_changed (NbtkWidget *self)
 {
-  ClutterColor *color = NULL;
   NbtkTooltipPrivate *priv;
-  gchar *font_name;
+  ShellThemeNode *theme_node;
+  ClutterColor color;
+  const PangoFontDescription *font;
   gchar *font_string;
-  gint font_size;
 
   priv = NBTK_TOOLTIP (self)->priv;
+  theme_node = nbtk_widget_get_theme_node (self);
 
-  nbtk_stylable_get (NBTK_STYLABLE (self),
-                     "color", &color,
-                     "font-family", &font_name,
-                     "font-size", &font_size,
-                     NULL);
+  shell_theme_node_get_foreground_color (theme_node, &color);
+  clutter_text_set_color (CLUTTER_TEXT (priv->label), &color);
 
-  if (color)
-    {
-      clutter_text_set_color (CLUTTER_TEXT (priv->label), color);
-      clutter_color_free (color);
-    }
-
-  if (font_name || font_size)
-    {
-      if (font_name && font_size)
-        {
-          font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
-          g_free (font_name);
-        }
-      else
-        if (font_size)
-          font_string = g_strdup_printf ("%dpx", font_size);
-        else
-          font_string = font_name;
-
-      clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string);
-
-      g_free (font_string);
-    }
+  font = shell_theme_node_get_font (theme_node);
+  font_string = pango_font_description_to_string (font);
+  clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string);
+  g_free (font_string);
 
+  NBTK_WIDGET_CLASS (nbtk_tooltip_parent_class)->style_changed (self);
 }
 
 static void
@@ -405,6 +384,7 @@ nbtk_tooltip_class_init (NbtkTooltipClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass);
   GParamSpec *pspec;
 
   g_type_class_add_private (klass, sizeof (NbtkTooltipPrivate));
@@ -419,6 +399,8 @@ nbtk_tooltip_class_init (NbtkTooltipClass *klass)
   actor_class->map = nbtk_tooltip_map;
   actor_class->unmap = nbtk_tooltip_unmap;
 
+  widget_class->style_changed = nbtk_tooltip_style_changed;
+
   pspec = g_param_spec_string ("label",
                                "Label",
                                "Label of the tooltip",
@@ -452,9 +434,6 @@ nbtk_tooltip_init (NbtkTooltip *tooltip)
   g_object_set (tooltip, "show-on-set-parent", FALSE, NULL);
 
   clutter_actor_set_reactive (CLUTTER_ACTOR (tooltip), FALSE);
-
-  g_signal_connect (tooltip, "style-changed",
-                    G_CALLBACK (nbtk_tooltip_style_changed), NULL);
 }
 
 static void
diff --git a/src/nbtk/nbtk-types.h b/src/nbtk/nbtk-types.h
index 77acfad..bb7eee4 100644
--- a/src/nbtk/nbtk-types.h
+++ b/src/nbtk/nbtk-types.h
@@ -28,13 +28,10 @@
 
 G_BEGIN_DECLS
 
-#define NBTK_TYPE_BORDER_IMAGE          (nbtk_border_image_get_type ())
 #define NBTK_TYPE_PADDING               (nbtk_padding_get_type ())
 
 typedef struct _NbtkPadding             NbtkPadding;
 
-GType nbtk_border_image_get_type (void) G_GNUC_CONST;
-
 /**
  * NbtkPadding:
  * @top: padding from the top
diff --git a/src/nbtk/nbtk-widget.c b/src/nbtk/nbtk-widget.c
index bc6cc9c..4cc6c42 100644
--- a/src/nbtk/nbtk-widget.c
+++ b/src/nbtk/nbtk-widget.c
@@ -31,18 +31,16 @@
 #include <string.h>
 
 #include <clutter/clutter.h>
-#include <ccss/ccss.h>
 
 #include "nbtk-widget.h"
 
 #include "nbtk-marshal.h"
 #include "nbtk-private.h"
-#include "nbtk-stylable.h"
 #include "nbtk-texture-cache.h"
 #include "nbtk-texture-frame.h"
 #include "nbtk-tooltip.h"
 
-typedef ccss_border_image_t             NbtkBorderImage;
+#include <toolkit/shell-theme-context.h>
 
 /*
  * Forward declaration for sake of NbtkWidgetChild
@@ -52,13 +50,14 @@ struct _NbtkWidgetPrivate
   NbtkPadding border;
   NbtkPadding padding;
 
-  NbtkStyle *style;
+  ShellTheme *theme;
+  ShellThemeNode *theme_node;
   gchar *pseudo_class;
   gchar *style_class;
 
   ClutterActor *border_image;
   ClutterActor *background_image;
-  ClutterColor *bg_color;
+  ClutterColor bg_color;
 
   gboolean is_stylable : 1;
   gboolean has_tooltip : 1;
@@ -82,7 +81,7 @@ enum
 {
   PROP_0,
 
-  PROP_STYLE,
+  PROP_THEME,
   PROP_PSEUDO_CLASS,
   PROP_STYLE_CLASS,
 
@@ -92,12 +91,16 @@ enum
   PROP_TOOLTIP_TEXT
 };
 
-static void nbtk_stylable_iface_init (NbtkStylableIface *iface);
+enum
+{
+  STYLE_CHANGED,
 
+  LAST_SIGNAL
+};
 
-G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NbtkWidget, nbtk_widget, CLUTTER_TYPE_ACTOR,
-                                  G_IMPLEMENT_INTERFACE (NBTK_TYPE_STYLABLE,
-                                                         nbtk_stylable_iface_init));
+static guint signals[LAST_SIGNAL] = { 0, };
+
+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))
 
@@ -111,9 +114,8 @@ nbtk_widget_set_property (GObject      *gobject,
 
   switch (prop_id)
     {
-    case PROP_STYLE:
-      nbtk_stylable_set_style (NBTK_STYLABLE (actor),
-                               g_value_get_object (value));
+    case PROP_THEME:
+      nbtk_widget_set_theme (actor, g_value_get_object (value));
       break;
 
     case PROP_PSEUDO_CLASS:
@@ -157,8 +159,8 @@ nbtk_widget_get_property (GObject    *gobject,
 
   switch (prop_id)
     {
-    case PROP_STYLE:
-      g_value_set_object (value, priv->style);
+    case PROP_THEME:
+      g_value_set_object (value, priv->theme);
       break;
 
     case PROP_PSEUDO_CLASS:
@@ -193,10 +195,10 @@ nbtk_widget_dispose (GObject *gobject)
   NbtkWidget *actor = NBTK_WIDGET (gobject);
   NbtkWidgetPrivate *priv = NBTK_WIDGET (actor)->priv;
 
-  if (priv->style)
+  if (priv->theme)
     {
-      g_object_unref (priv->style);
-      priv->style = NULL;
+      g_object_unref (priv->theme);
+      priv->theme = NULL;
     }
 
   if (priv->border_image)
@@ -205,12 +207,6 @@ nbtk_widget_dispose (GObject *gobject)
       priv->border_image = NULL;
     }
 
-  if (priv->bg_color)
-    {
-      clutter_color_free (priv->bg_color);
-      priv->bg_color = NULL;
-    }
-
   if (priv->tooltip)
     {
       ClutterContainer *parent;
@@ -386,7 +382,7 @@ nbtk_widget_paint (ClutterActor *self)
 
   klass->draw_background (NBTK_WIDGET (self),
                           priv->border_image,
-                          priv->bg_color);
+                          &priv->bg_color);
 
   if (priv->background_image != NULL)
     clutter_actor_paint (priv->background_image);
@@ -407,7 +403,7 @@ nbtk_widget_parent_set (ClutterActor *widget,
 
   /* don't send the style changed signal if we no longer have a parent actor */
   if (new_parent)
-    nbtk_stylable_changed ((NbtkStylable*) widget);
+    nbtk_widget_style_changed (NBTK_WIDGET (widget));
 }
 
 static void
@@ -446,69 +442,67 @@ nbtk_widget_unmap (ClutterActor *actor)
     clutter_actor_unmap ((ClutterActor *) priv->tooltip);
 }
 
+static void notify_children_of_style_change (ClutterContainer *container);
+
 static void
-nbtk_widget_style_changed (NbtkStylable *self)
+notify_children_of_style_change_foreach (ClutterActor *actor,
+					 gpointer      user_data)
+{
+  if (NBTK_IS_WIDGET (actor))
+    nbtk_widget_style_changed (NBTK_WIDGET (actor));
+  else if (CLUTTER_IS_CONTAINER (actor))
+    notify_children_of_style_change ((ClutterContainer *)actor);
+}
+
+static void
+notify_children_of_style_change (ClutterContainer *container)
+{
+  /* notify our children that their parent stylable has changed */
+  clutter_container_foreach (container,
+			     notify_children_of_style_change_foreach,
+			     NULL);
+}
+
+static void
+nbtk_widget_real_style_changed (NbtkWidget *self)
 {
   NbtkWidgetPrivate *priv = NBTK_WIDGET (self)->priv;
-  NbtkBorderImage *border_image = NULL;
+  ShellThemeNode *theme_node;
+  ShellThemeImage *theme_image;
   NbtkTextureCache *texture_cache;
   ClutterTexture *texture;
-  gchar *bg_file = NULL;
-  NbtkPadding *padding = NULL;
+  const char *bg_file = NULL;
   gboolean relayout_needed = FALSE;
   gboolean has_changed = FALSE;
-  ClutterColor *color;
+  NbtkPadding padding;
+  ClutterColor color;
 
   /* application has request this widget is not stylable */
   if (!priv->is_stylable)
     return;
 
-  /* cache these values for use in the paint function */
-  nbtk_stylable_get (self,
-                    "background-color", &color,
-                    "background-image", &bg_file,
-                    "border-image", &border_image,
-                    "padding", &padding,
-                    NULL);
+  theme_node = nbtk_widget_get_theme_node (self);
 
-  if (color)
+  shell_theme_node_get_background_color (theme_node, &color);
+  if (!clutter_color_equal (&color, &priv->bg_color))
     {
-      if (priv->bg_color && clutter_color_equal (color, priv->bg_color))
-        {
-          /* color is the same ... */
-          clutter_color_free (color);
-        }
-      else
-        {
-          clutter_color_free (priv->bg_color);
-          priv->bg_color = color;
-          has_changed = TRUE;
-        }
+      priv->bg_color = color;
+      has_changed = TRUE;
     }
-  else
-    if (priv->bg_color)
-      {
-        clutter_color_free (priv->bg_color);
-        priv->bg_color = NULL;
-        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 (padding)
+  if (priv->padding.top != padding.top ||
+      priv->padding.left != padding.left ||
+      priv->padding.right != padding.right ||
+      priv->padding.bottom != padding.bottom)
     {
-      if (priv->padding.top != padding->top ||
-          priv->padding.left != padding->left ||
-          priv->padding.right != padding->right ||
-          priv->padding.bottom != padding->bottom)
-      {
-        /* Padding changed. Need to relayout. */
-        has_changed = TRUE;
-        relayout_needed = TRUE;
-      }
-
-      priv->padding = *padding;
-      g_boxed_free (NBTK_TYPE_PADDING, padding);
+      priv->padding = padding;
+      has_changed = TRUE;
+      relayout_needed = TRUE;
     }
 
   if (priv->border_image)
@@ -525,26 +519,27 @@ nbtk_widget_style_changed (NbtkStylable *self)
 
   texture_cache = nbtk_texture_cache_get_default ();
 
-  /* Check if the URL is actually present, not garbage in the property */
-  if (border_image && border_image->uri)
+  theme_image = shell_theme_node_get_background_theme_image (theme_node);
+  if (theme_image)
     {
+      const char *filename;
       gint border_left, border_right, border_top, border_bottom;
       gint width, height;
 
+      filename = shell_theme_image_get_filename (theme_image);
+
       /* `border-image' takes precedence over `background-image'.
        * Firefox lets the background-image shine thru when border-image has
        * alpha an channel, maybe that would be an option for the future. */
       texture = nbtk_texture_cache_get_texture (texture_cache,
-                                                border_image->uri,
+                                                filename,
                                                 FALSE);
 
       clutter_texture_get_base_size (CLUTTER_TEXTURE (texture),
                                      &width, &height);
 
-      border_left = ccss_position_get_size (&border_image->left, width);
-      border_top = ccss_position_get_size (&border_image->top, height);
-      border_right = ccss_position_get_size (&border_image->right, width);
-      border_bottom = ccss_position_get_size (&border_image->bottom, height);
+      shell_theme_image_get_borders (theme_image,
+				     &border_left, &border_right, &border_top, &border_bottom);
 
       priv->border_image = nbtk_texture_frame_new (texture,
                                                    border_top,
@@ -552,14 +547,13 @@ nbtk_widget_style_changed (NbtkStylable *self)
                                                    border_bottom,
                                                    border_left);
       clutter_actor_set_parent (priv->border_image, CLUTTER_ACTOR (self));
-      g_boxed_free (NBTK_TYPE_BORDER_IMAGE, border_image);
 
       has_changed = TRUE;
       relayout_needed = TRUE;
     }
 
-  if (bg_file != NULL &&
-      strcmp (bg_file, "none"))
+  bg_file = shell_theme_node_get_background_image (theme_node);
+  if (bg_file != NULL)
     {
       texture = nbtk_texture_cache_get_texture (texture_cache,
                                                 bg_file,
@@ -577,7 +571,6 @@ nbtk_widget_style_changed (NbtkStylable *self)
       has_changed = TRUE;
       relayout_needed = TRUE;
     }
-    g_free (bg_file);
 
   /* If there are any properties above that need to cause a relayout thay
    * should set this flag.
@@ -590,37 +583,89 @@ nbtk_widget_style_changed (NbtkStylable *self)
         clutter_actor_queue_redraw ((ClutterActor *) self);
     }
 
-  priv->is_style_dirty = FALSE;
+  if (CLUTTER_IS_CONTAINER (self))
+    notify_children_of_style_change ((ClutterContainer *)self);
 }
 
-static void
-nbtk_widget_stylable_child_notify (ClutterActor *actor,
-                                   gpointer      user_data)
+void
+nbtk_widget_style_changed (NbtkWidget *widget)
 {
-  if (NBTK_IS_STYLABLE (actor))
-    nbtk_stylable_changed ((NbtkStylable*) actor);
+  widget->priv->is_style_dirty = TRUE;
+  if (widget->priv->theme_node)
+    {
+      g_object_unref (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;
+
+  nbtk_widget_ensure_style (widget);
 }
 
 static void
-nbtk_widget_stylable_changed (NbtkStylable *stylable)
+on_theme_context_changed (ShellThemeContext *context,
+			  ClutterStage      *stage)
 {
+  notify_children_of_style_change (CLUTTER_CONTAINER (stage));
+}
 
-  NBTK_WIDGET (stylable)->priv->is_style_dirty = TRUE;
+static ShellThemeNode *
+get_root_theme_node (ClutterStage *stage)
+{
+  ShellThemeContext *context = shell_theme_context_get_for_stage (stage);
 
-  /* update the style only if we are mapped */
-  if (!CLUTTER_ACTOR_IS_MAPPED ((ClutterActor *) stylable))
-    return;
+  if (!g_object_get_data (G_OBJECT (context), "nbtk-theme-initialized"))
+    {
+      g_object_set_data (G_OBJECT (context), "nbtk-theme-initialized", GUINT_TO_POINTER (1));
+      g_signal_connect (G_OBJECT (context), "changed",
+			G_CALLBACK (on_theme_context_changed), stage);
+    }
 
-  g_signal_emit_by_name (stylable, "style-changed", 0);
+  return shell_theme_context_get_root_node (context);
+}
 
+ShellThemeNode *
+nbtk_widget_get_theme_node (NbtkWidget *widget)
+{
+  NbtkWidgetPrivate *priv = widget->priv;
 
-  if (CLUTTER_IS_CONTAINER (stylable))
+  if (priv->theme_node == NULL)
     {
-      /* notify our children that their parent stylable has changed */
-      clutter_container_foreach ((ClutterContainer *) stylable,
-                                 nbtk_widget_stylable_child_notify,
-                                 NULL);
+      ShellThemeNode *parent_node = NULL;
+      ClutterStage *stage = NULL;
+      ClutterActor *parent;
+
+      parent = clutter_actor_get_parent (CLUTTER_ACTOR (widget));
+      while (parent != NULL)
+	{
+	  if (parent_node == NULL && NBTK_IS_WIDGET (parent))
+	    parent_node = nbtk_widget_get_theme_node (NBTK_WIDGET (parent));
+	  else if (CLUTTER_IS_STAGE (parent))
+	    stage = CLUTTER_STAGE (parent);
+
+	  parent = clutter_actor_get_parent (parent);
+	}
+
+      if (stage == NULL)
+	{
+	  g_warning ("nbtk_widget_get_theme_node called on a widget not in a stage");
+	  stage = CLUTTER_STAGE (clutter_stage_get_default ());
+	}
+
+      if (parent_node == NULL)
+	parent_node = get_root_theme_node (CLUTTER_STAGE (stage));
+
+      priv->theme_node = shell_theme_node_new (shell_theme_context_get_for_stage (stage),
+					       parent_node, priv->theme,
+					       G_OBJECT_TYPE (widget),
+					       clutter_actor_get_name (CLUTTER_ACTOR (widget)),
+					       priv->style_class,
+					       priv->pseudo_class);
     }
+
+  return priv->theme_node;
 }
 
 static gboolean
@@ -693,6 +738,7 @@ nbtk_widget_class_init (NbtkWidgetClass *klass)
   actor_class->hide = nbtk_widget_hide;
 
   klass->draw_background = nbtk_widget_real_draw_background;
+  klass->style_changed = nbtk_widget_real_style_changed;
 
   /**
    * NbtkWidget:pseudo-class:
@@ -720,7 +766,19 @@ nbtk_widget_class_init (NbtkWidgetClass *klass)
                                                         "",
                                                         NBTK_PARAM_READWRITE));
 
-  g_object_class_override_property (gobject_class, PROP_STYLE, "style");
+  /**
+   * NbtkWidget:theme
+   *
+   * A theme set on this actor overriding the global theming for this actor
+   * and its descendants
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_THEME,
+                                   g_param_spec_object ("theme",
+                                                        "Theme",
+                                                        "Theme override",
+                                                        SHELL_TYPE_THEME,
+                                                        NBTK_PARAM_READWRITE));
 
   /**
    * NbtkWidget:stylable:
@@ -764,108 +822,66 @@ nbtk_widget_class_init (NbtkWidgetClass *klass)
                                NBTK_PARAM_READWRITE);
   g_object_class_install_property (gobject_class, PROP_TOOLTIP_TEXT, pspec);
 
+  /**
+   * NbtkWidget::style-changed:
+   *
+   * Emitted when the style information that the widget derives from the
+   * theme changes
+   */
+  signals[STYLE_CHANGED] =
+    g_signal_new ("style-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (NbtkWidgetClass, style_changed),
+                  NULL, NULL,
+                  _nbtk_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
 }
 
-static NbtkStyle *
-nbtk_widget_get_style (NbtkStylable *stylable)
-{
-  NbtkWidgetPrivate *priv = NBTK_WIDGET (stylable)->priv;
-
-  return priv->style;
-}
-
-static void
-nbtk_style_changed_cb (NbtkStyle    *style,
-                       NbtkStylable *stylable)
-{
-  nbtk_stylable_changed (stylable);
-}
-
-
-static void
-nbtk_widget_set_style (NbtkStylable *stylable,
-                       NbtkStyle    *style)
-{
-  NbtkWidgetPrivate *priv = NBTK_WIDGET (stylable)->priv;
-
-  if (priv->style)
-    g_object_unref (priv->style);
-
-  priv->style = g_object_ref_sink (style);
-
-  g_signal_connect (priv->style,
-                    "changed",
-                    G_CALLBACK (nbtk_style_changed_cb),
-                    stylable);
-}
-
-static NbtkStylable*
-nbtk_widget_get_container (NbtkStylable *stylable)
-{
-  ClutterActor *parent;
-
-  g_return_val_if_fail (NBTK_IS_WIDGET (stylable), NULL);
-
-  parent = clutter_actor_get_parent (CLUTTER_ACTOR (stylable));
-
-  if (NBTK_IS_STYLABLE (parent))
-    return NBTK_STYLABLE (parent);
-  else
-    return NULL;
-}
-
-static NbtkStylable*
-nbtk_widget_get_base_style (NbtkStylable *stylable)
-{
-  return NULL;
-}
-
-static const gchar*
-nbtk_widget_get_style_id (NbtkStylable *stylable)
+/**
+ * nbtk_widget_set_theme:
+ * @actor: a #NbtkWidget
+ * @theme: a new style class string
+ *
+ * Overrides the theme that would be inherited from the actor's parent
+ * or the stage with an entirely new theme (set of stylesheets).
+ */
+void
+nbtk_widget_set_theme (NbtkWidget  *actor,
+		       ShellTheme  *theme)
 {
-  g_return_val_if_fail (NBTK_IS_WIDGET (stylable), NULL);
-
-  return clutter_actor_get_name (CLUTTER_ACTOR (stylable));
-}
+  NbtkWidgetPrivate *priv = actor->priv;
 
-static const gchar*
-nbtk_widget_get_style_type (NbtkStylable *stylable)
-{
-  return G_OBJECT_TYPE_NAME (stylable);
-}
+  g_return_if_fail (NBTK_IS_WIDGET (actor));
 
-static const gchar*
-nbtk_widget_get_style_class (NbtkStylable *stylable)
-{
-  g_return_val_if_fail (NBTK_IS_WIDGET (stylable), NULL);
+  priv = actor->priv;
 
-  return NBTK_WIDGET (stylable)->priv->style_class;
-}
+  if (theme !=priv->theme)
+    {
+      if (priv->theme)
+	g_object_unref (priv->theme);
+      priv->theme = g_object_ref (priv->theme);
 
-static const gchar*
-nbtk_widget_get_pseudo_class (NbtkStylable *stylable)
-{
-  g_return_val_if_fail (NBTK_IS_WIDGET (stylable), NULL);
+      nbtk_widget_style_changed (actor);
 
-  return NBTK_WIDGET (stylable)->priv->pseudo_class;
+      g_object_notify (G_OBJECT (actor), "theme");
+    }
 }
 
-static gboolean
-nbtk_widget_get_viewport (NbtkStylable *stylable,
-                          gint *x,
-                          gint *y,
-                          gint *width,
-                          gint *height)
+/**
+ * nbtk_widget_get_theme:
+ * @actor: a #NbtkWidget
+ *
+ * Gets the overriding theme set on the actor. See nbtk_widget_set_theme()
+ *
+ * Return value: (transfer none): the overriding theme, or %NULL
+ */
+ShellTheme *
+nbtk_widget_get_theme (NbtkWidget *actor)
 {
-  g_return_val_if_fail (NBTK_IS_WIDGET (stylable), FALSE);
-
-  *x = 0;
-  *y = 0;
-
-  *width = clutter_actor_get_width (CLUTTER_ACTOR (stylable));
-  *height = clutter_actor_get_height (CLUTTER_ACTOR (stylable));
+  g_return_val_if_fail (NBTK_IS_WIDGET (actor), NULL);
 
-  return TRUE;
+  return actor->priv->theme;
 }
 
 /**
@@ -881,7 +897,7 @@ nbtk_widget_set_style_class_name (NbtkWidget  *actor,
 {
   NbtkWidgetPrivate *priv = actor->priv;
 
-  g_return_if_fail (NBTK_WIDGET (actor));
+  g_return_if_fail (NBTK_IS_WIDGET (actor));
 
   priv = actor->priv;
 
@@ -890,7 +906,7 @@ nbtk_widget_set_style_class_name (NbtkWidget  *actor,
       g_free (priv->style_class);
       priv->style_class = g_strdup (style_class);
 
-      nbtk_stylable_changed ((NbtkStylable*) actor);
+      nbtk_widget_style_changed (actor);
 
       g_object_notify (G_OBJECT (actor), "style-class");
     }
@@ -909,7 +925,7 @@ nbtk_widget_set_style_class_name (NbtkWidget  *actor,
 const gchar*
 nbtk_widget_get_style_class_name (NbtkWidget *actor)
 {
-  g_return_val_if_fail (NBTK_WIDGET (actor), NULL);
+  g_return_val_if_fail (NBTK_IS_WIDGET (actor), NULL);
 
   return actor->priv->style_class;
 }
@@ -926,7 +942,7 @@ nbtk_widget_get_style_class_name (NbtkWidget *actor)
 const gchar*
 nbtk_widget_get_style_pseudo_class (NbtkWidget *actor)
 {
-  g_return_val_if_fail (NBTK_WIDGET (actor), NULL);
+  g_return_val_if_fail (NBTK_IS_WIDGET (actor), NULL);
 
   return actor->priv->pseudo_class;
 }
@@ -944,7 +960,7 @@ nbtk_widget_set_style_pseudo_class (NbtkWidget  *actor,
 {
   NbtkWidgetPrivate *priv;
 
-  g_return_if_fail (NBTK_WIDGET (actor));
+  g_return_if_fail (NBTK_IS_WIDGET (actor));
 
   priv = actor->priv;
 
@@ -953,99 +969,18 @@ nbtk_widget_set_style_pseudo_class (NbtkWidget  *actor,
       g_free (priv->pseudo_class);
       priv->pseudo_class = g_strdup (pseudo_class);
 
-      nbtk_stylable_changed ((NbtkStylable*) actor);
+      nbtk_widget_style_changed (actor);
 
       g_object_notify (G_OBJECT (actor), "pseudo-class");
     }
 }
 
-
-static void
-nbtk_stylable_iface_init (NbtkStylableIface *iface)
-{
-  static gboolean is_initialized = FALSE;
-
-  if (!is_initialized)
-    {
-      GParamSpec *pspec;
-      ClutterColor color = { 0x00, 0x00, 0x00, 0xff };
-      ClutterColor bg_color = { 0xff, 0xff, 0xff, 0x00 };
-
-      is_initialized = TRUE;
-
-      pspec = clutter_param_spec_color ("background-color",
-                                  "Background Color",
-                                  "The background color of an actor",
-                                  &bg_color,
-                                  G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_WIDGET, pspec);
-
-      pspec = clutter_param_spec_color ("color",
-                                  "Text Color",
-                                  "The color of the text of an actor",
-                                  &color,
-                                  G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_WIDGET, pspec);
-
-      pspec = g_param_spec_string ("background-image",
-                                   "Background Image",
-                                   "Background image filename",
-                                   NULL,
-                                   G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_WIDGET, pspec);
-
-      pspec = g_param_spec_string ("font-family",
-                                   "Font Family",
-                                   "Name of the font to use",
-                                   "Sans",
-                                   G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_WIDGET, pspec);
-
-      pspec = g_param_spec_int ("font-size",
-                                "Font Size",
-                                "Size of the font to use in pixels",
-                                0, G_MAXINT, 12,
-                                G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_WIDGET, pspec);
-
-      pspec = g_param_spec_boxed ("border-image",
-                                  "Border image",
-                                  "9-slice image to use for drawing borders and background",
-                                  NBTK_TYPE_BORDER_IMAGE,
-                                  G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_WIDGET, pspec);
-
-      pspec = g_param_spec_boxed ("padding",
-                                  "Padding",
-                                  "Padding between the widget's borders "
-                                  "and its content",
-                                  NBTK_TYPE_PADDING,
-                                  G_PARAM_READWRITE);
-      nbtk_stylable_iface_install_property (iface, NBTK_TYPE_WIDGET, pspec);
-
-      iface->style_changed = nbtk_widget_style_changed;
-      iface->stylable_changed = nbtk_widget_stylable_changed;
-
-      iface->get_style = nbtk_widget_get_style;
-      iface->set_style = nbtk_widget_set_style;
-      iface->get_base_style = nbtk_widget_get_base_style;
-      iface->get_container = nbtk_widget_get_container;
-      iface->get_style_id = nbtk_widget_get_style_id;
-      iface->get_style_type = nbtk_widget_get_style_type;
-      iface->get_style_class = nbtk_widget_get_style_class;
-      iface->get_pseudo_class = nbtk_widget_get_pseudo_class;
-      /* iface->get_attribute = nbtk_widget_get_attribute; */
-      iface->get_viewport = nbtk_widget_get_viewport;
-    }
-}
-
-
 static void
 nbtk_widget_name_notify (NbtkWidget *widget,
                          GParamSpec *pspec,
                          gpointer data)
 {
-  nbtk_stylable_changed ((NbtkStylable*) widget);
+  nbtk_widget_style_changed (widget);
 }
 
 static void
@@ -1058,44 +993,6 @@ nbtk_widget_init (NbtkWidget *actor)
 
   /* connect style changed */
   g_signal_connect (actor, "notify::name", G_CALLBACK (nbtk_widget_name_notify), NULL);
-
-  /* set the default style */
-  nbtk_widget_set_style (NBTK_STYLABLE (actor), nbtk_style_get_default ());
-
-}
-
-static NbtkBorderImage *
-nbtk_border_image_copy (const NbtkBorderImage *border_image)
-{
-  NbtkBorderImage *copy;
-
-  g_return_val_if_fail (border_image != NULL, NULL);
-
-  copy = g_slice_new (NbtkBorderImage);
-  *copy = *border_image;
-
-  return copy;
-}
-
-static void
-nbtk_border_image_free (NbtkBorderImage *border_image)
-{
-  if (G_LIKELY (border_image))
-    g_slice_free (NbtkBorderImage, border_image);
-}
-
-GType
-nbtk_border_image_get_type (void)
-{
-  static GType our_type = 0;
-
-  if (G_UNLIKELY (our_type == 0))
-    our_type =
-      g_boxed_type_register_static (I_("NbtkBorderImage"),
-                                    (GBoxedCopyFunc) nbtk_border_image_copy,
-                                    (GBoxedFreeFunc) nbtk_border_image_free);
-
-  return our_type;
 }
 
 /**
@@ -1112,11 +1009,11 @@ nbtk_widget_ensure_style (NbtkWidget *widget)
 
   if (widget->priv->is_style_dirty)
     {
-      g_signal_emit_by_name (widget, "style-changed", 0);
+      g_signal_emit (widget, signals[STYLE_CHANGED], 0);
+      widget->priv->is_style_dirty = FALSE;
     }
 }
 
-
 /**
  * nbtk_widget_get_border_image:
  * @actor: A #NbtkWidget
@@ -1349,6 +1246,5 @@ nbtk_widget_draw_background (NbtkWidget *self)
   klass = NBTK_WIDGET_GET_CLASS (self);
   klass->draw_background (NBTK_WIDGET (self),
                           priv->border_image,
-                          priv->bg_color);
-
+                          &priv->bg_color);
 }
diff --git a/src/nbtk/nbtk-widget.h b/src/nbtk/nbtk-widget.h
index 1f5fe66..8d367b0 100644
--- a/src/nbtk/nbtk-widget.h
+++ b/src/nbtk/nbtk-widget.h
@@ -29,6 +29,8 @@
 
 #include <clutter/clutter.h>
 #include <nbtk/nbtk-types.h>
+#include <toolkit/shell-theme.h>
+#include <toolkit/shell-theme-node.h>
 
 G_BEGIN_DECLS
 
@@ -72,6 +74,7 @@ struct _NbtkWidgetClass
   void (* draw_background) (NbtkWidget         *self,
                             ClutterActor       *background,
                             const ClutterColor *color);
+  void (* style_changed)   (NbtkWidget         *self);
 };
 
 GType nbtk_widget_get_type (void) G_GNUC_CONST;
@@ -83,6 +86,9 @@ void                  nbtk_widget_set_style_class_name   (NbtkWidget   *actor,
                                                           const gchar  *style_class);
 G_CONST_RETURN gchar *nbtk_widget_get_style_class_name   (NbtkWidget   *actor);
 
+void        nbtk_widget_set_theme (NbtkWidget *actor,
+				   ShellTheme *theme);
+ShellTheme *nbtk_widget_get_theme (NbtkWidget *actor);
 
 void     nbtk_widget_set_has_tooltip (NbtkWidget *widget, gboolean has_tooltip);
 gboolean nbtk_widget_get_has_tooltip (NbtkWidget *widget);
@@ -96,6 +102,10 @@ void nbtk_widget_ensure_style (NbtkWidget *widget);
 
 
 /* Only to be used by sub-classes of NbtkWidget */
+void          nbtk_widget_style_changed        (NbtkWidget  *widget);
+
+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,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 35ba1c7..ee86ec5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,5 +16,6 @@ run-test.sh: run-test.sh.in
 	$(AM_V_GEN) sed \
 	    -e "s|@GJS_JS_DIR[ ]|$(GJS_JS_DIR)|" \
 	    -e "s|@GJS_JS_NATIVE_DIR[ ]|$(GJS_JS_NATIVE_DIR)|" \
+	    -e "s|@MUTTER_LIB_DIR[ ]|$(MUTTER_LIB_DIR)|" \
 	    -e "s|@srcdir[ ]|$(srcdir)|" \
 	    $< > $@ && chmod a+x $@
diff --git a/tests/interactive/css-fonts.js b/tests/interactive/css-fonts.js
new file mode 100644
index 0000000..f0525bb
--- /dev/null
+++ b/tests/interactive/css-fonts.js
@@ -0,0 +1,39 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Clutter = imports.gi.Clutter;
+const Nbtk = imports.gi.Nbtk;
+
+const UI = imports.testcommon.ui;
+
+UI.init();
+let stage = Clutter.Stage.get_default();
+
+let b = new Nbtk.BoxLayout({ vertical: true,
+			     width: stage.width,
+			     height: stage.height });
+stage.add_actor(b);
+
+let t;
+
+t = new Nbtk.Label({ "text": "Bold", style_class: "bold" });
+b.add(t);
+t = new Nbtk.Label({ "text": "Monospace", style_class: "monospace" });
+b.add(t);
+t = new Nbtk.Label({ "text": "Italic", style_class: "italic" });
+b.add(t);
+t = new Nbtk.Label({ "text": "Bold Italic", style_class: "bold italic" });
+b.add(t);
+t = new Nbtk.Label({ "text": "Big Italic", style_class: "big italic" });
+b.add(t);
+t = new Nbtk.Label({ "text": "Big Bold", style_class: "big bold" });
+b.add(t);
+
+let b2 = new Nbtk.BoxLayout({ vertical: true, style_class: "monospace" });
+b.add(b2);
+t = new Nbtk.Label({ "text": "Big Monospace", style_class: "big" });
+b2.add(t);
+t = new Nbtk.Label({ "text": "Italic Monospace", style_class: "italic" });
+b2.add(t);
+
+stage.show();
+Clutter.main();
diff --git a/tests/interactive/scrolling.js b/tests/interactive/scrolling.js
new file mode 100644
index 0000000..c1e3d56
--- /dev/null
+++ b/tests/interactive/scrolling.js
@@ -0,0 +1,28 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Clutter = imports.gi.Clutter;
+const Nbtk = imports.gi.Nbtk;
+
+const UI = imports.testcommon.ui;
+
+UI.init();
+let stage = Clutter.Stage.get_default();
+
+let v = new Nbtk.ScrollView({});
+stage.add_actor(v);
+let b = new Nbtk.BoxLayout({ vertical: true,
+			     width: stage.width,
+			     height: stage.height });
+v.add_actor(b);
+
+let cc_a = "a".charCodeAt(0);
+let s = "";
+for (let i = 0; i < 26 * 3; i++) {
+    s += String.fromCharCode(cc_a + i % 26);
+
+    let t = new Nbtk.Label({ "text": s});
+    b.add(t);
+}
+
+stage.show();
+Clutter.main();
diff --git a/tests/run-test.sh.in b/tests/run-test.sh.in
index ce1ce3e..4436187 100644
--- a/tests/run-test.sh.in
+++ b/tests/run-test.sh.in
@@ -26,7 +26,7 @@ builddir=`cd $builddir && pwd`
 srcdir=$builddir/@srcdir@
 srcdir=`cd $srcdir && pwd`
 
-GI_TYPELIB_PATH="$builddir/../src"
+GI_TYPELIB_PATH="@MUTTER_LIB_DIR@/mutter:$builddir/../src"
 GJS_DEBUG_OUTPUT=stderr
 $verbose || GJS_DEBUG_TOPICS="JS ERROR;JS LOG"
 GNOME_SHELL_TESTSDIR="$srcdir/"
diff --git a/tests/testcommon/test.css b/tests/testcommon/test.css
index 0e1b3ac..6ce3d5d 100644
--- a/tests/testcommon/test.css
+++ b/tests/testcommon/test.css
@@ -1,13 +1,33 @@
 @import "../../data/theme/gnome-shell.css";
 
-*.red {
+stage {
+    font: 16pt serif;
+}
+
+.red {
     background-color: red;
 }
 
-*.green {
+.green {
     background-color: green;
 }
 
-*.blue {
+.blue {
     background-color: blue;
 }
+
+.bold {
+    font-weight: bold;
+}
+
+.italic {
+    font-style: italic;
+}
+
+.big {
+    font-size: 150%;
+}
+
+.monospace {
+    font-family: monospace;
+}
diff --git a/tests/testcommon/ui.js b/tests/testcommon/ui.js
index e6ea34e..fdae57f 100644
--- a/tests/testcommon/ui.js
+++ b/tests/testcommon/ui.js
@@ -3,6 +3,7 @@
 const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
 const Nbtk = imports.gi.Nbtk;
+const Shell = imports.gi.Shell;
 
 const Environment = imports.ui.environment;
 
@@ -10,7 +11,9 @@ function init() {
     Clutter.init(null, null);
     Environment.init();
 
-    let style = Nbtk.Style.get_default();
+    let stage = Clutter.Stage.get_default();
+    let context = Shell.ThemeContext.get_for_stage (stage);
     let stylesheetPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/test.css";
-    style.load_from_file(stylesheetPath);
+    let theme = new Shell.Theme ({ application_stylesheet: stylesheetPath });
+    context.set_theme (theme);
 }



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