[gnome-themes-standard: 3/26] adwaita: render regular radios and checkboxes like in mockups



commit d0175e83cdcdeb779252989219430bc159129a39
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Tue Mar 1 17:58:23 2011 -0500

    adwaita: render regular radios and checkboxes like in mockups
    
    This is implemented by importing the SVG elements in the theme as assets
    and rendering them instead of drawing them manually.
    Icon names are hardcoded, and the past code path is kept as a fallback
    in case the icons are not found.

 configure.ac                       |    1 +
 src/Makefile.am                    |    9 +-
 src/adwaita_engine.c               |  207 +++++++++++++++++++++++++++++++++++-
 themes/Adwaita/gtk-3.0/Makefile.am |    2 +
 themes/Adwaita/gtk-3.0/gtk.css     |    5 +-
 5 files changed, 216 insertions(+), 8 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 76f4949..192eefb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,6 +49,7 @@ themes/Adwaita/backgrounds/Makefile
 themes/Adwaita/cursors/Makefile
 themes/Adwaita/gtk-2.0/Makefile
 themes/Adwaita/gtk-3.0/Makefile
+themes/Adwaita/gtk-3.0/assets/Makefile
 themes/Adwaita/metacity-1/Makefile
 themes/AdwaitaLowContrast/Makefile
 themes/AdwaitaLowContrast/gtk-3.0/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 9dbd028..90b3990 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,9 +1,12 @@
-
-INCLUDES = $(GTK_CFLAGS)
-
 enginedir = $(libdir)/gtk-3.0/$(GTK_VERSION)/theming-engines
 engine_LTLIBRARIES = libadwaita.la
 
+assetsdir = $(datadir)/themes/Adwaita/gtk-3.0/assets
+
+INCLUDES = \
+	-DASSETS_DIR=\""$(assetsdir)"\" \
+	$(GTK_CFLAGS)
+
 libadwaita_la_SOURCES =			\
 	adwaita_engine.c
 
diff --git a/src/adwaita_engine.c b/src/adwaita_engine.c
index fdc9fe3..ebb8b17 100644
--- a/src/adwaita_engine.c
+++ b/src/adwaita_engine.c
@@ -31,6 +31,8 @@ typedef struct _AdwaitaEngineClass AdwaitaEngineClass;
 struct _AdwaitaEngine
 {
   GtkThemingEngine parent_object;
+
+  GHashTable *assets;
 };
 
 struct _AdwaitaEngineClass
@@ -48,19 +50,75 @@ struct _AdwaitaEngineClass
 GType adwaita_engine_get_type	    (void) G_GNUC_CONST;
 void  adwaita_engine_register_types (GTypeModule *module);
 
-
 G_DEFINE_DYNAMIC_TYPE (AdwaitaEngine, adwaita_engine, GTK_TYPE_THEMING_ENGINE)
 
+typedef struct {
+	gchar *data;
+	gsize length;
+} AssetData;
+
+static void
+asset_data_free (gpointer user_data)
+{
+	AssetData *data = user_data;
+
+	g_free (data->data);
+	g_slice_free (AssetData, data);
+}
+
+static const AssetData *
+cache_asset_data (AdwaitaEngine *self,
+		  const gchar *asset_name)
+{
+	gchar *path, *name;
+	gboolean res;
+	GError *error = NULL;
+	AssetData *asset;
+
+	name = g_strconcat (asset_name, ".svg", NULL);
+	path = g_build_filename (ASSETS_DIR, name, NULL);
+
+	asset = g_slice_new0 (AssetData);
+	res = g_file_get_contents (path, &asset->data, &asset->length, &error);
+
+	if (res) {
+		g_hash_table_insert (self->assets, g_strdup (asset_name), asset);
+	}
+
+	g_free (name);
+	g_free (path);
+
+	return asset;
+}
+
+static const AssetData *
+lookup_asset_data (AdwaitaEngine *self,
+		   const gchar *asset_name)
+{
+	const AssetData *retval;
+
+	retval = g_hash_table_lookup (self->assets, asset_name);
+
+	if (retval != NULL) {
+		return retval;
+	}
+
+	retval = cache_asset_data (self, asset_name);
+
+	return retval;
+}
 
 void
 adwaita_engine_register_types (GTypeModule *module)
 {
-  adwaita_engine_register_type (module);
+	adwaita_engine_register_type (module);
 }
 
 static void
-adwaita_engine_init (AdwaitaEngine *clearlooks_engine)
+adwaita_engine_init (AdwaitaEngine *self)
 {
+	self->assets = g_hash_table_new_full (g_str_hash, g_str_equal,
+					      g_free, asset_data_free);
 }
 
 static void
@@ -159,6 +217,129 @@ adwaita_engine_render_focus (GtkThemingEngine *engine,
 	gdk_rgba_free (border_color);
 }
 
+static gchar *
+option_asset_name_from_state (GtkStateFlags state)
+{
+	GString *string;
+
+	string = g_string_new ("radio-");
+
+	if (state & GTK_STATE_FLAG_ACTIVE) {
+		g_string_append (string, "selected");
+	} else {
+		g_string_append (string, "unselected");
+	}
+
+	if (state & GTK_STATE_FLAG_INSENSITIVE) {
+		g_string_append (string, "-insensitive");
+	}
+
+	return g_string_free (string, FALSE);
+}
+
+static gchar *
+check_asset_name_from_state (GtkStateFlags state)
+{
+	GString *string;
+
+	string = g_string_new ("checkbox-");
+
+	if (state & GTK_STATE_FLAG_ACTIVE) {
+		g_string_append (string, "checked");
+	} else {
+		g_string_append (string, "unchecked");
+	}
+
+	if (state & GTK_STATE_FLAG_INSENSITIVE) {
+		g_string_append (string, "-insensitive");
+	}
+
+	return g_string_free (string, FALSE);
+}
+
+static gboolean
+render_from_assets_common (GtkThemingEngine *engine,
+			   cairo_t *cr,
+			   const gchar *asset_name,
+			   gdouble x,
+			   gdouble y,
+			   gdouble width,
+			   gdouble height)
+{
+	GdkPixbuf *asset;
+	GInputStream *stream;
+	const AssetData *asset_data;
+	gboolean retval = FALSE;
+
+	asset_data = lookup_asset_data (ADWAITA_ENGINE (engine), asset_name);
+
+	if (asset_data == NULL) {
+		goto out;
+	}
+
+	stream = g_memory_input_stream_new_from_data (asset_data->data, asset_data->length,
+						      NULL);
+	asset = gdk_pixbuf_new_from_stream_at_scale (stream, width, height, TRUE,
+						     NULL, NULL);
+
+	if (asset != NULL) {		      
+		cairo_save (cr);
+
+		cairo_translate (cr, x, y);
+		gdk_cairo_set_source_pixbuf (cr, asset, 0, 0);
+		cairo_rectangle (cr, 0, 0, width, height);
+
+		cairo_fill (cr);
+
+		cairo_restore (cr);
+
+		g_object_unref (asset);
+
+		retval = TRUE;
+	}
+
+	g_object_unref (stream);
+	
+ out:
+	return retval;
+}
+
+static gboolean
+render_check_from_assets (GtkThemingEngine *engine,
+			  cairo_t *cr,
+			  gdouble x,
+			  gdouble y,
+			  gdouble width,
+			  gdouble height)
+{
+	gchar *asset_name;
+	gboolean retval;
+
+	asset_name = check_asset_name_from_state (gtk_theming_engine_get_state (engine));
+	retval = render_from_assets_common (engine, cr, asset_name,
+					    x, y, width, height);
+
+	return retval;
+}
+
+static gboolean
+render_option_from_assets (GtkThemingEngine *engine,
+			   cairo_t *cr,
+			   gdouble x,
+			   gdouble y,
+			   gdouble width,
+			   gdouble height)
+{
+	gchar *asset_name;
+	gboolean retval;
+
+	asset_name = option_asset_name_from_state (gtk_theming_engine_get_state (engine));
+	retval = render_from_assets_common (engine, cr, asset_name,
+					    x, y, width, height);
+
+	return retval;
+}
+
 static void
 adwaita_engine_render_check (GtkThemingEngine *engine,
 			     cairo_t	      *cr,
@@ -173,6 +354,17 @@ adwaita_engine_render_check (GtkThemingEngine *engine,
 	GtkStateFlags state;
 	gint radius;
 
+	if (!gtk_theming_engine_has_class (engine,
+					   GTK_STYLE_CLASS_MENUITEM) &&
+	    !gtk_theming_engine_has_class (engine,
+					   GTK_STYLE_CLASS_CELL) &&
+	    render_check_from_assets (engine, cr,
+				      x, y, width, height)) {
+		return;
+	}
+
+	cairo_save (cr);
+
 	state = gtk_theming_engine_get_state (engine);
 	inconsistent = (state & GTK_STATE_FLAG_INCONSISTENT) != 0;
 	draw_bullet = (state & GTK_STATE_FLAG_ACTIVE);
@@ -301,6 +493,15 @@ adwaita_engine_render_option (GtkThemingEngine *engine,
 	gdouble cx, cy, radius;
 	GtkStateFlags state;
 
+	if (!gtk_theming_engine_has_class (engine,
+					   GTK_STYLE_CLASS_MENUITEM) &&
+	    !gtk_theming_engine_has_class (engine,
+					   GTK_STYLE_CLASS_CELL) &&
+	    render_option_from_assets (engine, cr,
+				       x, y, width, height)) {
+		return;
+	}
+	
 	cx = width / 2.0;
 	cy = height / 2.0;
 	radius = MIN (width, height) / 2.0;
diff --git a/themes/Adwaita/gtk-3.0/Makefile.am b/themes/Adwaita/gtk-3.0/Makefile.am
index b34f3d2..95e8520 100644
--- a/themes/Adwaita/gtk-3.0/Makefile.am
+++ b/themes/Adwaita/gtk-3.0/Makefile.am
@@ -1,3 +1,5 @@
+SUBDIRS = assets
+
 themedir = $(datadir)/themes/Adwaita/gtk-3.0
 theme_DATA = 		\
 	gtk.css 	\
diff --git a/themes/Adwaita/gtk-3.0/gtk.css b/themes/Adwaita/gtk-3.0/gtk.css
index e2b7bca..429d58f 100644
--- a/themes/Adwaita/gtk-3.0/gtk.css
+++ b/themes/Adwaita/gtk-3.0/gtk.css
@@ -81,11 +81,10 @@
     -GtkToolButton-icon-spacing: 4;
     -GtkWidget-focus-padding: 2;
 
-    -GtkCheckButton-indicator-size: 14;
-
     -GtkTextView-error-underline-color: @error_color;
 
     -GtkPaned-handle-size: 6;
+    -GtkCheckButton-indicator-size: 16;
 
     /* The size for scrollbars. The slider is 2px smaller, but we keep it
      * up so that the whole area is sensitive to button presses for the
@@ -426,6 +425,7 @@ GtkCheckButton:prelight,
 GtkRadioButton:prelight,
 GtkCheckButton:selected,
 GtkRadioButton:selected {
+    color: shade (@theme_selected_bg_color, 0.84);
     background-color: shade (@theme_bg_color, 1.1);
 }
 
@@ -435,6 +435,7 @@ GtkRadioButton:selected {
 .menu .check, .menu .radio,
 .menu .check:active, .menu .radio:active,
 .menu .check:hover, .menu .radio:hover {
+    color: shade (@theme_selected_bg_color, 0.84);
     border-color: shade (@frame_color, 1.035);
     color: @menu_fg_color;
     background-color: mix (shade (@highlighted_border, 1.345), @theme_base_color, 0.9);



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