[gnome-games] lightsoff: Implement "Use colors from GNOME theme" checkbox



commit 16abb3f1d9adf60890fcf4ab92638572511ca9f3
Author: Tim Horton <hortont424 gmail com>
Date:   Sun Oct 11 10:35:20 2009 -0400

    lightsoff: Implement "Use colors from GNOME theme" checkbox
    
    I'm not currently sure what the correct way to retrieve colors from Gtk is,
    but I recognize that what I'm doing now is almost certainly incorrect.
    
    Any alternative themes (which I assume do not exist) will have to be updated
    similar to the way I updated themes/up/theme.js in this patch.

 lightsoff/data/settings.ui           |    1 +
 lightsoff/data/themes/tango/theme.js |  128 ++++++++++++++++++++++++++++++++-
 lightsoff/data/themes/up/theme.js    |    5 ++
 lightsoff/lightsoff.schemas.in       |   13 ++++
 lightsoff/src/Game.js                |   28 ++++++++
 lightsoff/src/Settings.js            |   65 ++++++++++++++---
 lightsoff/src/ThemeLoader.js         |    3 +
 7 files changed, 228 insertions(+), 15 deletions(-)
---
diff --git a/lightsoff/data/settings.ui b/lightsoff/data/settings.ui
index 4d79883..934c18d 100644
--- a/lightsoff/data/settings.ui
+++ b/lightsoff/data/settings.ui
@@ -67,6 +67,7 @@
                             <property name="can_focus">True</property>
                             <property name="receives_default">False</property>
                             <property name="draw_indicator">True</property>
+                            <signal name="toggled" handler="set_use_theme_colors"/>
                           </object>
                           <packing>
                             <property name="expand">False</property>
diff --git a/lightsoff/data/themes/tango/theme.js b/lightsoff/data/themes/tango/theme.js
index 5e09714..bd515d4 100644
--- a/lightsoff/data/themes/tango/theme.js
+++ b/lightsoff/data/themes/tango/theme.js
@@ -1,15 +1,135 @@
+cairo = imports.cairo;
 Clutter = imports.gi.Clutter;
 ThemeLoader = imports.ThemeLoader;
+Gtk = imports.gi.Gtk;
+Settings = imports.Settings;
+main = imports.main;
 
 var name = "Tango";
+var theme_colorable = true;
+var tile_size = 75;
 
-var light = [ ThemeLoader.load_svg("tango", "off.svg"),
-              ThemeLoader.load_svg("tango", "on.svg") ];
+// TODO: catch GNOME-wide theme change, update tiles, recache them, etc.
+
+function rounded_rectangle(cr,x,y,w,h,r)
+{
+    cr.new_path();
+	cr.move_to(x+r,y);
+    cr.line_to(x+w-r,y);
+    cr.curve_to(x+w,y,x+w,y,x+w,y+r);
+    cr.line_to(x+w,y+h-r);
+    cr.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h);
+    cr.line_to(x+r,y+h);
+    cr.curve_to(x,y+h,x,y+h,x,y+h-r);
+    cr.line_to(x,y+r);
+    cr.curve_to(x,y,x,y,x+r,y);
+	cr.close_path();
+}
+
+function draw_tile(color)
+{
+	var tile = new Clutter.CairoTexture();
+	tile.set_surface_size(tile_size, tile_size);
+	var context = tile.create();
+	var cr = new cairo.Context.steal(context);
+	
+	var pattern = new cairo.LinearGradient(tile_size,0,0,0);
+	pattern.add_color_stop_rgba(0,
+	                            color.red / 255,
+	                            color.green / 255,
+	                            color.blue / 255,
+	                            color.alpha / 255);
+	pattern.add_color_stop_rgba(1,
+	                            color.red / 255 - 0.15,
+	                            color.green / 255 - 0.15,
+	                            color.blue / 255 - 0.15,
+	                            color.alpha / 255);
+	cr.set_source(pattern);
+	
+	rounded_rectangle(cr, 2, 2, tile_size - 4, tile_size - 4, 5);
+	cr.fill();
+	
+	cr.set_source_rgba(color.red / 255 + 0.05, color.green / 255 + 0.05, color.blue / 255 + 0.05, 1.0);
+	rounded_rectangle(cr, 2, 2, tile_size - 4, tile_size - 4, 5);
+	cr.line_width = 2.0;
+	cr.stroke();
+
+	cr.destroy();
+	
+	return tile;
+}
+
+function draw_glow(color)
+{
+	var tile = new Clutter.CairoTexture();
+	tile.set_surface_size(tile_size, tile_size);
+	var context = tile.create();
+	var cr = new cairo.Context.steal(context);
+	
+	var pattern = new cairo.LinearGradient(0,0,0,tile_size);
+	pattern.add_color_stop_rgba(0, 1.0, 1.0, 1.0, 0.3);
+	pattern.add_color_stop_rgba(1, 1.0, 1.0, 1.0, 0.1);
+	cr.set_source(pattern);
+	
+	cr.new_path();
+	cr.move_to(0, 0);
+	cr.line_to(0, tile_size);
+	cr.line_to(tile_size, tile_size);
+	cr.line_to(tile_size, 0);
+	cr.close_path();
+	cr.fill();
+	
+	cr.set_source_rgba(1.0,1.0,1.0,0.4);
+	
+	cr.new_path();
+	cr.move_to(3, 3);
+	cr.line_to(3, tile_size - 3);
+	cr.line_to(tile_size - 3, tile_size - 3);
+	cr.line_to(tile_size - 3, 3);
+	cr.close_path();
+	cr.stroke();
+	
+	cr.destroy();
+	
+	return tile;
+}
+
+function reload_theme()
+{
+    // TODO: there must be a better way to get the Gtk selection color
+    var gtk_settings = Gtk.Settings.get_default();
+    var gtk_color_scheme = gtk_settings.gtk_color_scheme;
+    var c = new Clutter.Color();
+    c.from_string(gtk_color_scheme.match(/selected_bg_color: (.*)/)[1]);
+    
+    // Remove the previous theme's cached lights
+    if(light.length > 0)
+    {
+        main.game.queue_actor_remove(light[0]);
+        main.game.queue_actor_remove(light[1]);
+    }
+
+    if(Settings.use_theme_colors)
+    {
+        light = [ draw_tile({red: 32, green: 32, blue: 32, alpha: 255}),
+                  draw_tile(c) ];
+    }
+    else
+    {
+        light = [ ThemeLoader.load_svg("tango", "off.svg"),
+                  ThemeLoader.load_svg("tango", "on.svg") ];
+    }
+    
+    textures = [light[0], light[1], arrow, backing, led_back, highlight];
+    loaded = false;
+}
+
+var light = [];
 var arrow = ThemeLoader.load_svg("tango", "arrow.svg");
 var backing = ThemeLoader.load_svg("tango", "backing.svg");
 var led_back = ThemeLoader.load_svg("tango", "led-back.svg");
 var highlight = ThemeLoader.load_svg("tango", "highlight.svg");
-
 var loaded = false;
-var textures = [light[0], light[1], arrow, backing, led_back, highlight];
+var textures = [];
 
+reload_theme();
diff --git a/lightsoff/data/themes/up/theme.js b/lightsoff/data/themes/up/theme.js
index e20b52a..f2ce6ab 100644
--- a/lightsoff/data/themes/up/theme.js
+++ b/lightsoff/data/themes/up/theme.js
@@ -2,6 +2,7 @@ Clutter = imports.gi.Clutter;
 ThemeLoader = imports.ThemeLoader;
 
 var name = "Shine";
+var theme_colorable = false;
 
 var light = [ ThemeLoader.load_svg("up", "off.svg"),
               ThemeLoader.load_svg("up", "on.svg") ];
@@ -13,3 +14,7 @@ var highlight = ThemeLoader.load_svg("up", "highlight.svg");
 var loaded = false;
 var textures = [light[0], light[1], arrow, backing, led_back, highlight];
 
+function reload_theme()
+{
+    // TODO: draw with Cairo
+}
diff --git a/lightsoff/lightsoff.schemas.in b/lightsoff/lightsoff.schemas.in
index d73622c..a9d6e54 100644
--- a/lightsoff/lightsoff.schemas.in
+++ b/lightsoff/lightsoff.schemas.in
@@ -24,6 +24,19 @@
           <long>The users's most recent score.</long>
         </locale>
       </schema>
+      
+      <schema>
+        <key>/schemas/apps/lightsoff/use_theme_colors</key>
+        <applyto>/apps/lightsoff/use_theme_colors</applyto>
+        <owner>lightsoff</owner>
+        <type>bool</type>
+        <default>0</default>
+        <locale name="C">
+          <short>Whether or not to use the GNOME theme colors</short>
+          <long>If enabled, the default background color from the user's 
+          default GNOME theme is used to draw the tiles.</long>
+        </locale>
+      </schema>
 
   </schemalist>
   
diff --git a/lightsoff/src/Game.js b/lightsoff/src/Game.js
index 3355adb..1d35859 100644
--- a/lightsoff/src/Game.js
+++ b/lightsoff/src/Game.js
@@ -4,6 +4,7 @@ Clutter = imports.gi.Clutter;
 LED = imports.LED;
 Board = imports.Board;
 Arrow = imports.Arrow;
+main = imports.main;
 
 var last_direction, last_sign;
 
@@ -15,6 +16,8 @@ GameView = new GType({
 		// Private
 		var self = this;
 		var current_level = 1;
+		var queue_theme_change = 0;
+		var actor_remove_queue = [];
 		var score_view = new LED.LEDView();
 		var board_view = new Board.BoardView();
 		var backing_view = new Clutter.Clone({source:Settings.theme.backing});
@@ -44,11 +47,28 @@ GameView = new GType({
 		// The boards have finished transitioning; delete the old one!
 		var board_transition_complete = function()
 		{
+		    queue_theme_change--;
+		    
 			self.remove_actor(board_view);
 			board_view = new_board_view;
 			board_view.set_playable(true);
 			keycursor_view.raise_top();
 			new_board_view = timeline = 0;
+			
+			if(queue_theme_change)
+			{
+			    queue_theme_change = 0;
+			    theme_changed();
+			}
+			
+			// Remove all of the queued-for-removal actors
+			while(actor_remove_queue.length > 0)
+			{
+			    act = actor_remove_queue.pop();
+
+			    if(act && act.get_parent())
+    			    act.get_parent().remove_actor(act);
+			}
 		}
 		
 		// The player won the game; create a new board, update the level count,
@@ -125,6 +145,8 @@ GameView = new GType({
 		// The player changed the theme from within the preferences window
 		var theme_changed = function()
 		{
+		    queue_theme_change++;
+		    
 			if(timeline)
 				return;
 			
@@ -162,6 +184,12 @@ GameView = new GType({
 		
 		// Public
 		
+		// Queue an actor to be removed after the board is finished reloading
+		this.queue_actor_remove = function (actor)
+		{
+		    actor_remove_queue.push(actor);
+		}
+		
 		this.reset_game = function ()
 		{
 			if(timeline && timeline.is_playing())
diff --git a/lightsoff/src/Settings.js b/lightsoff/src/Settings.js
index 30f580c..1a7de4d 100644
--- a/lightsoff/src/Settings.js
+++ b/lightsoff/src/Settings.js
@@ -8,40 +8,56 @@ ThemeLoader = imports.ThemeLoader;
 GConf.init(Seed.argv);
 
 // Defaults
-var theme, score;
-var default_theme = "Tango";
-
-// Map theme names to themes
-var themes = ThemeLoader.load_themes();
+var theme, score, use_theme_colors, theme_name;
+var themes;
+var default_theme_name = "Tango";
+var default_use_theme_colors = false;
 
+// Load settings from GConf
 try
 {
 	gconf_client = GConf.Client.get_default();
 	score = gconf_client.get_int("/apps/lightsoff/score");
-	theme = themes[gconf_client.get_string("/apps/lightsoff/theme")];
+	theme_name = gconf_client.get_string("/apps/lightsoff/theme")
+	use_theme_colors = gconf_client.get_bool("/apps/lightsoff/use_theme_colors");
 	
 	if(theme == null)
-		theme = themes[default_theme];
+		theme = default_theme_name;
 }
 catch(e)
 {
 	print("Couldn't load settings from GConf.");
-	theme = themes[default_theme];
+	theme_name = default_theme_name;
 	score = 1;
+	use_theme_colors = default_use_theme_colors;
 }
 
 // If (machine isn't restarted?) after schema is installed, defaults
 // from GConf aren't set, so revert to defaults...
+// TODO: this seems unacceptable and wrong
 if(score == 0)
 {
-	theme = themes[default_theme];
+	theme_name = default_theme_name;
 	score = 1;
 }
 
+try
+{
+    // Map theme names to themes
+    themes = ThemeLoader.load_themes();
+    
+    // Load selected theme
+    theme = themes[theme_name];
+}
+catch(e)
+{
+    print("Couldn't load selected theme...");
+}
+
 // Settings Event Handler
 
 SettingsWatcher = new GType({
-	parent: Gtk.Button.type, // TODO: Can I make something inherit directly from GObject?!
+	parent: Gtk.Button.type,
 	name: "SettingsWatcher",
 	signals: [{name: "theme_changed"}],
 	init: function()
@@ -65,16 +81,39 @@ handlers = {
 		theme = new_theme;
 		ThemeLoader.load_theme(main.stage, theme);
 		
+		b.get_object("use-gnome-theme-checkbox").sensitive = theme.theme_colorable;
+		
+		if(!theme.theme_colorable)
+		    b.get_object("use-gnome-theme-checkbox").active = false;
+		
 		try
 		{
 			gconf_client.set_string("/apps/lightsoff/theme", selector.get_active_text());
 		}
 		catch(e)
 		{
-			Seed.print("Couldn't save settings to GConf.");
+			print("Couldn't save settings to GConf.");
 		}
 	
 		Watcher.signal.theme_changed.emit();
+	},
+	set_use_theme_colors: function(widget, ud)
+	{
+	    use_theme_colors = widget.active;
+	    
+	    theme.reload_theme();
+	    ThemeLoader.load_theme(main.stage, theme);
+	    
+	    try
+	    {
+	        gconf_client.set_bool("/apps/lightsoff/use_theme_colors", use_theme_colors);
+        }
+        catch(e)
+        {
+            print("Couldn't save settings to GConf.");
+        }
+        
+        Watcher.signal.theme_changed.emit();
 	}
 };
 
@@ -88,6 +127,10 @@ function show_settings()
 
 	populate_theme_selector(b.get_object("theme-selector"));
 
+    // Set current values
+    b.get_object("use-gnome-theme-checkbox").active = use_theme_colors;
+    b.get_object("use-gnome-theme-checkbox").sensitive = theme.theme_colorable;
+
 	settings_dialog = b.get_object("dialog1");
 	settings_dialog.set_transient_for(main.window);
 	
diff --git a/lightsoff/src/ThemeLoader.js b/lightsoff/src/ThemeLoader.js
index 1367f69..a19bf9e 100644
--- a/lightsoff/src/ThemeLoader.js
+++ b/lightsoff/src/ThemeLoader.js
@@ -19,6 +19,9 @@ function load_theme(stage, theme)
 
 	for(actor in theme.textures)
 	{
+	    if(theme.textures[actor].get_parent())
+	        continue;
+	    
 		stage.add_actor(theme.textures[actor]);
 		theme.textures[actor].hide();
 	}



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