[ease/themes] Extract theme archives to /tmp. Introduces dependency on libarchive.



commit a05a33d5c6c187dc66cb92739cbbe95bf8062070
Author: Nate Stedman <natesm gmail com>
Date:   Fri Jun 4 17:08:32 2010 -0400

    Extract theme archives to /tmp. Introduces dependency on libarchive.

 Makefile.am              |    2 +
 README                   |    1 +
 configure.ac             |    4 +-
 src/EditorEmbed.vala     |   42 +++++++++++++++++++++++++--
 src/EditorWindow.vala    |    3 --
 src/JSONParser.vala      |   37 +++++++++++++++++++++++-
 src/ScrollableEmbed.vala |   56 ++++++++++++++++++++++++++++++++++--
 src/Temp.vala            |   70 ++++++++++++++++++++++++++++++++++++++++++++++
 src/WelcomeWindow.vala   |   18 ++++++++++--
 src/ZoomSlider.vala      |   25 ++++++++++++++++
 10 files changed, 241 insertions(+), 17 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ea9c8fe..ea295c1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,7 @@ ease_SOURCES = \
 	src/SlidePane.vala \
 	src/SlideSet.vala \
 	src/Slide.vala \
+	src/Temp.vala \
 	src/TextActor.vala \
 	src/Theme.vala \
 	src/TransitionPane.vala \
@@ -63,6 +64,7 @@ VALAFLAGS = --pkg glib-2.0 \
 		--pkg gio-2.0 \
 		--pkg clutter-gst-1.0\
 		--pkg json-glib-1.0\
+		--pkg libarchive\
 		$(NULL)
 
 SUBDIRS = po
diff --git a/README b/README
index 4809f8e..287e2d2 100644
--- a/README
+++ b/README
@@ -19,6 +19,7 @@ As well as these dependencies:
 - cogl-1.0
 - gio-2.0
 - json-glib-1.0
+- libarchive
 
 Remember to install the introspection packages as well, which
 look like this :
diff --git a/configure.ac b/configure.ac
index 38bd8d6..2134bb6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,9 +27,9 @@ GNOME_COMPILE_WARNINGS([maximum])
 GNOME_MAINTAINER_MODE_DEFINES
 
 dnl FIXME
-pkg_modules="clutter-gtk-0.10 >= 0.10 gee-1.0 >= 0.5.0 clutter-gst-1.0 >= 1.0.0 json-glib-1.0 >= 0.7.6"
+pkg_modules="clutter-gtk-0.10 >= 0.10 gee-1.0 >= 0.5.0 clutter-gst-1.0 >= 1.0.0 json-glib-1.0 >= 0.7.6 libarchive"
 
-EASE_PACKAGES="--pkg glib-2.0 --pkg gtk+-2.0 --pkg clutter-1.0 --pkg gdk-2.0 --pkg libxml-2.0 --pkg gee-1.0 --pkg clutter-gtk-0.10 --pkg cogl-1.0 --pkg gio-2.0 --pkg clutter-gst-1.0"
+EASE_PACKAGES="--pkg glib-2.0 --pkg gtk+-2.0 --pkg clutter-1.0 --pkg gdk-2.0 --pkg libxml-2.0 --pkg gee-1.0 --pkg clutter-gtk-0.10 --pkg cogl-1.0 --pkg gio-2.0 --pkg clutter-gst-1.0 --pkg libarchive"
 
 PKG_CHECK_MODULES(EASE, [$pkg_modules])
 
diff --git a/src/EditorEmbed.vala b/src/EditorEmbed.vala
index 3a5f469..b0fde05 100644
--- a/src/EditorEmbed.vala
+++ b/src/EditorEmbed.vala
@@ -53,12 +53,18 @@ public class Ease.EditorEmbed : ScrollableEmbed
 	private float mouse_x;
 	private float mouse_y;
 	
-	// the origin position of a dragged element
+	// the original position of a dragged element
 	private float orig_x;
 	private float orig_y;
 	private float orig_w;
 	private float orig_h;
 	
+	// constants
+	private const string SPLIT = "\n;";
+	private const string BG_COLOR = "bg_color:";
+	private const string PREFIX = "#";
+	private const double SHADE_FACTOR = 0.9;
+	
 	private Document document;
 	public float zoom;
 	public bool zoom_fit;
@@ -77,7 +83,7 @@ public class Ease.EditorEmbed : ScrollableEmbed
 	 */
 	public EditorEmbed(Document d, EditorWindow w)
 	{
-		base(true);
+		base(true, true);
 		win = w;
 		
 		// don't fade actors out when zoomed out
@@ -85,7 +91,37 @@ public class Ease.EditorEmbed : ScrollableEmbed
 
 		// set up the background
 		view_background = new Clutter.Rectangle();
-		view_background.color = {200, 200, 200, 255};
+		
+		// find the appropriate color
+		var settings = Gtk.Settings.get_default();
+		var colors = settings.gtk_color_scheme.split_set(SPLIT);
+		for (int i = 0; i < colors.length; i++)
+		{
+			colors[i] = colors[i].strip();
+			
+			if (colors[i].has_prefix(BG_COLOR))
+			{
+				for (; !colors[i].has_prefix(PREFIX) && colors[i].length > 3;
+			         colors[i] = colors[i].substring(1, colors[i].length - 1));
+				
+				Gdk.Color gdk_color;
+				Gdk.Color.parse(colors[i], out gdk_color);
+				
+				Clutter.Color clutter_color = { (uchar)(gdk_color.red / 256),
+				                                (uchar)(gdk_color.green / 256),
+				                                (uchar)(gdk_color.blue / 256),
+				                                255};
+				
+				Clutter.Color out_color;
+				
+				clutter_color.shade(SHADE_FACTOR, out out_color);
+				
+				view_background.color = out_color;
+				
+				break;
+			}
+		}
+		
 		contents.add_actor(view_background);
 		
 		document = d;
diff --git a/src/EditorWindow.vala b/src/EditorWindow.vala
index 82b3c01..8a24aa4 100644
--- a/src/EditorWindow.vala
+++ b/src/EditorWindow.vala
@@ -85,7 +85,6 @@ public class Ease.EditorWindow : Gtk.Window
 		// assemble middle contents			
 		var hbox = new Gtk.HBox(false, 0);
 		hbox.pack_start(slide_button_panel, false, false, 0);
-		hbox.pack_start(new Gtk.VSeparator(), false, false, 0);
 		hbox.pack_start(embed, true, true, 0);
 		hbox.pack_start(inspector, false, false, 0);
 		
@@ -94,7 +93,6 @@ public class Ease.EditorWindow : Gtk.Window
 		vbox.pack_start(create_menu_bar(), false, false, 0);
 		main_toolbar = new MainToolbar();
 		vbox.pack_start(main_toolbar, false, false, 0);
-		vbox.pack_start(new Gtk.HSeparator(), false, false, 0);
 		vbox.pack_start(hbox, true, true, 0);
 		vbox.pack_end(create_bottom_bar(), false, false, 0);
 		
@@ -352,7 +350,6 @@ public class Ease.EditorWindow : Gtk.Window
 		hbox.pack_start(zoom_slider, false, false, 0);
 		
 		var vbox = new Gtk.VBox(false, 0);
-		vbox.pack_start(new Gtk.HSeparator(), false, false, 0);
 		vbox.pack_start(hbox, true, true, 2);
 		
 		var align = new Gtk.Alignment(1, 1, 1, 1);
diff --git a/src/JSONParser.vala b/src/JSONParser.vala
index 300134d..c21ba7b 100644
--- a/src/JSONParser.vala
+++ b/src/JSONParser.vala
@@ -20,6 +20,8 @@
  */
 public static class Ease.JSONParser
 {
+	private const int ARCHIVE_BUFFER = 4096;
+	
 	/**
 	 * Parses a document JSON file, creating a { link Document}.
 	 *
@@ -61,13 +63,44 @@ public static class Ease.JSONParser
 	 */
 	public static Theme theme(string filename) throws GLib.Error
 	{
+		// initialize the .easetheme archive
+		var archive = new Archive.Read();
+		
+		// automatically detect archive type
+		archive.support_compression_all();
+		archive.support_format_all();
+		
+		// open the archive
+		archive.open_filename(filename, ARCHIVE_BUFFER);
+		
+		// extract the archive
+		string path = Temp.request();
+		
+		weak Archive.Entry entry;
+		while (archive.next_header(out entry) == Archive.Result.OK)
+		{
+			var fpath = Path.build_path("/", path, entry.pathname());
+			var file = GLib.File.new_for_path(fpath);
+			if (Posix.S_ISDIR(entry.mode()))
+			{
+				file.make_directory_with_parents(null);
+			}
+			else
+			{
+				file.create(FileCreateFlags.REPLACE_DESTINATION, null);
+				int fd = Posix.open(fpath, Posix.O_WRONLY, 0644);
+				archive.read_data_into_fd(fd);
+				Posix.close(fd);
+			}
+		}
+		
 		var theme = new Theme();
-		theme.path = filename;
+		theme.path = path;
 	
 		var parser = new Json.Parser();
 		
 		// attempt to load the file
-		parser.load_from_file(Path.build_path("/", filename, "Theme.json"));
+		parser.load_from_file(Path.build_path("/", path, "Theme.json"));
 		
 		// grab the root object
 		var root = parser.get_root().get_object();
diff --git a/src/ScrollableEmbed.vala b/src/ScrollableEmbed.vala
index eb5aa07..4b5b888 100644
--- a/src/ScrollableEmbed.vala
+++ b/src/ScrollableEmbed.vala
@@ -32,10 +32,15 @@ public class Ease.ScrollableEmbed : Gtk.HBox
 	// scrolling
 	private Gtk.HScrollbar h_scrollbar;
 	private Gtk.VScrollbar v_scrollbar;
+	private Gtk.Alignment h_padder;
+	private Gtk.Alignment v_padder;
 	private Gtk.Adjustment h_adjust;
 	private Gtk.Adjustment v_adjust;
 	private Gtk.Adjustment z_adjust;
 	
+	// constants
+	private const int FRAME_PADDING = 2;
+	
 	public bool has_horizontal { get; private set; }
 
 	public float width
@@ -62,8 +67,9 @@ public class Ease.ScrollableEmbed : Gtk.HBox
 	 *
 	 * @param horizontal If true, the ScrollableEmbed has a horizontal
 	 * scrollbar in addition to the vertical scrollbar.
+	 * @param has_frame If the EditorEmbed should have a frame around its stage.
 	 */
-	public ScrollableEmbed(bool horizontal)
+	public ScrollableEmbed(bool horizontal, bool has_frame)
 	{
 		has_horizontal = horizontal;
 		
@@ -83,16 +89,58 @@ public class Ease.ScrollableEmbed : Gtk.HBox
 		stage.add_actor(viewport);
 		viewport.child = contents;
 
+		// add the embed to a frame if requested
 		var vbox = new Gtk.VBox(false, 0);
-		vbox.pack_start(embed, true, true, 0);
+		if (has_frame)
+		{
+			// create the frame
+			var frame = new Gtk.Frame(null);
+			frame.shadow_type = Gtk.ShadowType.IN;
+			frame.add(embed);
+			
+			// add the frame to padded alignment
+			var align = new Gtk.Alignment(0, 0, 1, 1);
+			align.set_padding(0, horizontal ? FRAME_PADDING : 0,
+			                  0, FRAME_PADDING);
+			align.add(frame);
+			
+			vbox.pack_start(align, true, true, 0);
+		}
+		else
+		{
+			vbox.pack_start(embed, true, true, 0);
+		}
 		
 		if (has_horizontal)
 		{
-			vbox.pack_start(h_scrollbar, false, false, 0);
+			// this widget shifts the scrollbar to line up with the frame
+			h_padder = new Gtk.Alignment(0, 0, 0, 0);
+			
+			var hscroll_box = new Gtk.HBox(false, 0);
+			hscroll_box.pack_start(h_scrollbar, true, true, 0);
+			hscroll_box.pack_start(h_padder, false, false, 0);
+			vbox.pack_start(hscroll_box, false, false, 0);
+			
+			// so that the vertical scrollbar doesn't extend to the bottom
+			// of the horizontal scrollbar, a padding widget is added
+			v_padder = new Gtk.Alignment(0, 0, 0, 0);
+			
+			var vscroll_box = new Gtk.VBox(false, 0);
+			vscroll_box.pack_start(v_scrollbar, true, true, 0);
+			vscroll_box.pack_start(v_padder, false, false, 0);
+			pack_end(vscroll_box, false, false, 0);
+			
+			h_scrollbar.size_allocate.connect((sender, rect) => {
+				h_padder.width_request = FRAME_PADDING;
+				v_padder.height_request = rect.height + FRAME_PADDING;
+			});
+		}
+		else
+		{
+			pack_end(v_scrollbar, false, false, 0);
 		}
 
 		pack_start(vbox, true, true, 0);
-		pack_start(v_scrollbar, false, false, 0);
 		
 		stage.show_all();
 		
diff --git a/src/Temp.vala b/src/Temp.vala
new file mode 100644
index 0000000..699dd14
--- /dev/null
+++ b/src/Temp.vala
@@ -0,0 +1,70 @@
+/*  Ease, a GTK presentation application
+    Copyright (C) 2010 Nate Stedman
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * Creates temporary directories for use by Ease.
+ */
+public static class Ease.Temp : Object
+{
+	private static int index = 0;
+	
+	/**
+	 * Requests a temporary directory.
+	 *
+	 * request() creates a temporary directory (typically under /tmp/ease).
+	 * Each directory has a integer name, incrementing by one for each new
+	 * directory.
+	 */
+	public static string request() throws GLib.Error
+	{
+		// remove any temporary directories from previous runs of Ease
+		if (index == 0)
+		{
+			string tmp = Environment.get_tmp_dir();
+			var file =
+				GLib.File.new_for_path(Path.build_path("/", tmp, "ease"));
+			
+			if (file.query_exists(null))
+			{
+				// TODO: not this
+				Posix.system("rm -rf /tmp/ease");
+//				var enumerator = file.enumerate_children("standard::", 0, null);
+//				
+//				var info = enumerator.next_file(null);
+//				while (info != null)
+//				{
+//					stdout.printf("%s\n", info.get_display_name());
+//					info = enumerator.next_file(null);
+//				}
+//				
+//				file.delete(null);
+			}
+		}
+		
+		index++;
+		
+		// build the path
+		string tmp = Environment.get_tmp_dir();
+		tmp = Path.build_path("/", tmp, "ease", index.to_string());
+		
+		// make the directory
+		var file = GLib.File.new_for_path(tmp);
+		file.make_directory_with_parents(null);
+		
+		return tmp;
+	}
+}
diff --git a/src/WelcomeWindow.vala b/src/WelcomeWindow.vala
index 27c589d..6cfd585 100644
--- a/src/WelcomeWindow.vala
+++ b/src/WelcomeWindow.vala
@@ -35,6 +35,7 @@ public class Ease.WelcomeWindow : Gtk.Window
 	// themes
 	private Gee.ArrayList<Theme> themes = new Gee.ArrayList<Theme>();
 	private Theme selected_theme;
+	private const string THEME_DIR = "/usr/local/share/ease/themes";
 
 	// clutter view
 	private ScrollableEmbed embed;
@@ -138,7 +139,7 @@ public class Ease.WelcomeWindow : Gtk.Window
 		hbox.pack_end(align, false, false, 0);
 		
 		// create the upper UI - the embed
-		embed = new ScrollableEmbed(false);
+		embed = new ScrollableEmbed(false, false);
 		embed.get_stage().use_fog = false;
 
 		// create the preview container
@@ -150,8 +151,19 @@ public class Ease.WelcomeWindow : Gtk.Window
 		preview_container.add_actor(preview_background);
 		
 		// load themes
-		for (int i = 0; i < 20; i++)
-			themes.add(JSONParser.theme("themes/White.easetheme"));
+		try
+		{
+			var dir = GLib.Dir.open(THEME_DIR, 0);
+			
+			string name = dir.read_name();
+			while (name != null)
+			{
+				var path = Path.build_path("/", THEME_DIR, name);
+				themes.add(JSONParser.theme(path));
+				name = dir.read_name();
+			}
+		}
+		catch (Error e) { error_dialog("Error Loading Themes", e.message); }
 		
 		// create the previews
 		foreach (var theme in themes)
diff --git a/src/ZoomSlider.vala b/src/ZoomSlider.vala
index f4ebfe5..d420dba 100644
--- a/src/ZoomSlider.vala
+++ b/src/ZoomSlider.vala
@@ -17,6 +17,9 @@
 
 /**
  * A zoom widget containing a Gtk.HScale and two (+/-) buttons.
+ *
+ * ZoomSlider uses ClutterAnimation to smoothly adjust the slider when th
+ * zoom in or zoom out button is clicked.
  */
 public class Ease.ZoomSlider : Gtk.Alignment, Clutter.Animatable
 {
@@ -56,6 +59,20 @@ public class Ease.ZoomSlider : Gtk.Alignment, Clutter.Animatable
 		set { zoom_slider.set_value(value); }
 	}
 	
+	private bool buttons_shown_priv = true;
+	public bool buttons_shown
+	{
+		get { return buttons_shown; }
+		set
+		{
+			if (value == buttons_shown_priv) return;
+			
+			buttons_shown_priv = value;
+			zoom_in.visible = value;
+			zoom_out.visible = value;
+		}
+	}
+	
 	/** 
 	 * Creates a new ZoomSlider.
 	 *
@@ -125,11 +142,19 @@ public class Ease.ZoomSlider : Gtk.Alignment, Clutter.Animatable
 			}
 		});
 		
+		zoom_in.show.connect(buttons_show_handler);
+		zoom_out.show.connect(buttons_show_handler);
+		
 		zoom_slider.format_value.connect(val => {
 			return "%i%%".printf((int)val);
 		});
 	}
 	
+	private void buttons_show_handler(Gtk.Widget sender)
+	{
+		buttons_shown_priv = true;
+	}
+	
 	/** 
 	 * Returns the value of the zoom slider.
 	 */



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