[ease/themes] Greatly improved WelcomeActor, with side effects.



commit 84c36114b4ba8f018f7b3ea251377995714fb33a
Author: Nate Stedman <natesm gmail com>
Date:   Wed Jul 21 21:45:05 2010 -0400

    Greatly improved WelcomeActor, with side effects.
    
    WelcomeActor changes:
    
    - WelcomeActor now uses Cairo to render, bypassing the creation of
      SlideActors.
    - WelcomeActors now properly resize and reflow at different
      resolutions.
    - WelcomeActor now fills in some sample text for slides.
    - WelcomeActor has been documented (aside from some obvious constants)
    - WelcomeWindow now uses signal handlers to select different themes
    
    Other changes:
    
    - PDFExporter.write_slide becomes a Slide member, cairo_render.
    - Slide also gains cairo_render_sized, for rendering at a specific size
    - All uses of write_slide are updated to use cairo_render.

 data/theme-defaults.json     |    6 +-
 src/ease-pdf-exporter.vala   |   43 +----------
 src/ease-slide-button.vala   |    2 +-
 src/ease-slide.vala          |   53 +++++++++++++
 src/ease-welcome-actor.vala  |  177 ++++++++++++++++++++++++++++++------------
 src/ease-welcome-window.vala |   77 +++++++++---------
 6 files changed, 224 insertions(+), 134 deletions(-)
---
diff --git a/data/theme-defaults.json b/data/theme-defaults.json
index 4ac3147..464741a 100644
--- a/data/theme-defaults.json
+++ b/data/theme-defaults.json
@@ -29,13 +29,13 @@
 		"author-text" : {
 			"padding-top" : "0",
 			"height" : "100",
-			"text-size" : "18",
+			"text-size" : "32",
 			"text-align" : "center"
 		},
 		
 		"title-text" : {
-			"height" : "50",
-			"text-size" : "28",
+			"height" : "75",
+			"text-size" : "48",
 			"text-align" : "center",
 			"text-weight" : "600"
 		},
diff --git a/src/ease-pdf-exporter.vala b/src/ease-pdf-exporter.vala
index 4ffc97d..37049d6 100644
--- a/src/ease-pdf-exporter.vala
+++ b/src/ease-pdf-exporter.vala
@@ -16,7 +16,7 @@
 */
 
 /**
- * Renders { link Slide}s with Cairo.
+ * Exports { link Slide}s to PDF files with Cairo.
  */
 public static class Ease.PDFExporter : Object
 {
@@ -61,7 +61,7 @@ public static class Ease.PDFExporter : Object
 		
 			foreach (var s in document.slides)
 			{
-				write_slide(s, context);
+				s.cairo_render(context);
 				context.show_page();
 			}
 		
@@ -73,42 +73,5 @@ public static class Ease.PDFExporter : Object
 			error_dialog(_("Error Exporting to PDF"), e.message);
 		}
 	}
-	
-	/** 
-	 * Draws a { link Slide} to a Cairo.Context.
-	 *
-	 * @param s The { link Slide} to draw.
-	 * @param context The Cairo.Context to draw to.
-	 */
-	public static void write_slide(Slide s, Cairo.Context context) throws Error
-	{
-		// write the background color if there is no image
-		if (s.background_image == null)
-		{
-			context.rectangle(0, 0, s.parent.width, s.parent.height);
-			context.set_source_rgb(s.background_color.red / 255f,
-			                       s.background_color.green / 255f,
-			                       s.background_color.blue / 255f);
-			context.fill();
-		}
-		
-		// otherwise, write the image
-		else
-		{
-			var pixbuf = new Gdk.Pixbuf.from_file_at_scale(s.background_abs,
-			                                               s.parent.width,
-			                                               s.parent.height,
-			                                               false);
-		
-			Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0);
-		
-			context.rectangle(0, 0, s.parent.width, s.parent.height);
-			context.fill();
-		}
-		
-		foreach (var e in s.elements)
-		{
-			e.cairo_render(context);
-		}
-	}
 }
+
diff --git a/src/ease-slide-button.vala b/src/ease-slide-button.vala
index f793812..fab792c 100644
--- a/src/ease-slide-button.vala
+++ b/src/ease-slide-button.vala
@@ -123,7 +123,7 @@ public class Ease.SlideButton : Gtk.Button
 		              ((float)allocation.height) / slide.parent.height);
 		
 		// write the slide
-		try { PDFExporter.write_slide(slide, context); }
+		try { slide.cairo_render(context); }
 		catch (Error e)
 		{
 			log("", LogLevelFlags.LEVEL_WARNING, "%s\n", e.message);
diff --git a/src/ease-slide.vala b/src/ease-slide.vala
index 6c59161..e2c6729 100644
--- a/src/ease-slide.vala
+++ b/src/ease-slide.vala
@@ -227,6 +227,59 @@ public class Ease.Slide : GLib.Object
 		elements.insert(count, e);
 	}
 	
+	/** 
+	 * Draws the { link Slide} to a Cairo.Context.
+	 *
+	 * @param context The Cairo.Context to draw to.
+	 */
+	public void cairo_render(Cairo.Context context) throws GLib.Error
+	{
+		if (parent == null)
+			throw new GLib.Error(0, 0, "Slide must have a parent document");
+		
+		cairo_render_sized(context, parent.width, parent.height);
+	}
+	
+	/** 
+	 * Draws the { link Slide} to a Cairo.Context at a specified size.
+	 *
+	 * @param context The Cairo.Context to draw to.
+	 * @param w The width to render at.
+	 * @param h The height to render at.
+	 */
+	public void cairo_render_sized(Cairo.Context context,
+	                                int w, int h) throws GLib.Error
+	{
+		// write the background color if there is no image
+		if (background_image == null)
+		{
+			context.rectangle(0, 0, w, h);
+			context.set_source_rgb(background_color.red / 255f,
+			                       background_color.green / 255f,
+			                       background_color.blue / 255f);
+			context.fill();
+		}
+		
+		// otherwise, write the image
+		else
+		{
+			var pixbuf = new Gdk.Pixbuf.from_file_at_scale(background_abs,
+			                                                h,
+			                                                w,
+			                                                false);
+		
+			Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0);
+		
+			context.rectangle(0, 0, w, h);
+			context.fill();
+		}
+		
+		foreach (var e in elements)
+		{
+			e.cairo_render(context);
+		}
+	}
+	
 	/**
 	 * Creates HTML markup for this Slide.
 	 * 
diff --git a/src/ease-welcome-actor.vala b/src/ease-welcome-actor.vala
index 161488f..65bed68 100644
--- a/src/ease-welcome-actor.vala
+++ b/src/ease-welcome-actor.vala
@@ -16,20 +16,34 @@
 */
 
 /**
- * { link Theme} tiles on the { link WelcomeWindow}
+ * { link Theme} tiles within the { link WelcomeWindow}
  *
  * Each WelcomeActor is a preview of a { link Theme}. The user can
  * click on these to create a new { link Document} with that { link Theme}.
  */
 public class Ease.WelcomeActor : Clutter.Group
 {
-	private Gee.ArrayList<WelcomeActor> others;
+	/**
+	 * If this WelcomeActor is currently selected.
+	 */
 	private bool is_selected = false;
-	private Slide master;
-	private Slide slide;
-	private SlideActor slide_actor;
-	private float slide_height;
+	
+	/**
+	 * A CairoTexture used to render the slide preview.
+	 */
+	private Clutter.CairoTexture slide_actor;
+	
+	/**
+	 * A black background rectangle placed behind the slide preview.
+	 *
+	 * When the slide preview's opacity is lowered, this rectangle causes the
+	 * preview to appear dark, rather than translucent.
+	 */
 	private Clutter.Rectangle rect;
+	
+	/**
+	 * The theme previewed by this WelcomeActor.
+	 */
 	public Theme theme;
 	
 	// display the name of the theme
@@ -38,26 +52,43 @@ public class Ease.WelcomeActor : Clutter.Group
 	private const float TEXT_HEIGHT = 12;
 	private Clutter.Text text;
 	
-	// constants
+	// fade constants
 	private const int FADE_TIME = 200;
 	private const int FADE_INIT_TIME = 1000;
 	private const int FADE_EASE = Clutter.AnimationMode.EASE_IN_OUT_SINE;
-	private const int FADE_VALUE = 150;
-	private const float WIDTH = 1024;
+	private const int FADE_OPACITY = 150;
+	
+	/**
+	 * The slide identifier to display as a preview.
+	 */
+	private const string PREVIEW_SLIDE = Theme.TITLE;
+	
+	/**
+	 * Triggered when the slide preview is selected (single click).
+	 */
+	public signal void selected(WelcomeActor sender);
 	
-	public signal void selected();
+	/**
+	 * Triggered when the slide preview is double clicked.
+	 */
+	public signal void double_click(WelcomeActor sender);
 	
-	public WelcomeActor(Theme t, Gee.ArrayList<WelcomeActor> o, Slide m)
+	/**
+	 * Instantiates a WelcomeActor.
+	 *
+	 * @param t The theme that this WelcomeActor will display.
+	 */
+	public WelcomeActor(Theme t)
 	{
-		others = o;
-		slide_height = WIDTH * 3 / 4; // 4:3
-		master = m;
 		theme = t;
+		reactive = true;
 		
+		// create the background rectangle actor
 		rect = new Clutter.Rectangle();
 		rect.color = {0, 0, 0, 255};
 		add_actor(rect);
 		
+		// create the theme title actor
 		text = new Clutter.Text.full (FONT_NAME,
 									  theme.title,
 									  {255, 255, 255, 255});
@@ -65,34 +96,57 @@ public class Ease.WelcomeActor : Clutter.Group
 		text.line_alignment = Pango.Alignment.RIGHT;
 		add_actor(text);
 		
-		reactive = true;
+		// create the slide preview texture
+		slide_actor = new Clutter.CairoTexture(1024, 768);
+		add_actor(slide_actor);
 		
+		// fade the preview in
 		opacity = 0;
 		animate(FADE_EASE, FADE_INIT_TIME, "opacity", 255);
+		
+		// respond to click events
+		button_press_event.connect((self, event) => {
+            if (event.click_count == 2) {
+				double_click(this);
+				return false;
+			}
+			
+			if (!is_selected) selected(this);
+			return false;
+		});
 	}
 	
+	/**
+	 * Sets the slide preview size.
+	 *
+	 * @param w The width of the slide.
+	 * @param h The height of the slide.
+	 */
 	public void set_slide_size(int w, int h)
 	{
-		if (slide_actor != null)
+		// set the surface size
+		slide_actor.set_surface_size((uint)w, (uint)h);
+		
+		// render
+		try
 		{
-			remove_actor(slide_actor);
+			create_slide(w, h).cairo_render_sized(slide_actor.create(), w, h);
+		}
+		catch (GLib.Error e)
+		{
+			critical(_("Error rendering preview: %s"), e.message);
 		}
-		
-		slide = new Slide.from_master(master, null,
-		                              (int)WIDTH, (int)slide_height, false);
-		slide.theme = theme;
-		slide_actor = new SlideActor.with_dimensions(w, h, slide, true,
-		                                             ActorContext.PRESENTATION);
-		
-		slide_actor.scale_x = w / WIDTH;
-		slide_actor.scale_y = h / slide_height;
-		slide_actor.height = rect.height;
-		slide_actor.width = rect.width;
-		
-		add_actor(slide_actor);
 	}
 	
-	public void set_dims(float w, float h)
+	/**
+	 * Sets the size of the slide preview actor.
+	 *
+	 * This method does not redraw the preview, it simply scales it.
+	 *
+	 * @param w The width of the actor.
+	 * @param h The height of the actor.
+	 */
+	public void set_actor_size(float w, float h)
 	{
 		rect.width = w;
 		rect.height = h;
@@ -102,37 +156,58 @@ public class Ease.WelcomeActor : Clutter.Group
 		
 		if (slide_actor != null)
 		{
-			slide_actor.scale_x = w / WIDTH;
-			slide_actor.scale_y = h / slide_height;
-			slide_actor.height = rect.height;
 			slide_actor.width = rect.width;
+			slide_actor.height = rect.height;
 		}
 	}
 	
-	public void clicked()
+	/**
+	 * Brings the preview to full brightness.
+	 */
+	public void fade()
 	{
-		if (!is_selected)
-		{
-			// unfade the others
-			foreach (var a in others)
-			{
-				a.fade();
-			}
-			unfade();
-			selected();
-		}
+		is_selected = false;
+		animate(FADE_EASE, FADE_TIME, "opacity", FADE_OPACITY);
 	}
 	
-	private void fade()
+	/**
+	 * Dims the preview.
+	 */
+	public void unfade()
 	{
-		is_selected = false;
-		this.animate(FADE_EASE, FADE_TIME, "opacity", FADE_VALUE);
+		is_selected = true;
+		animate(FADE_EASE, FADE_TIME, "opacity", 255);
 	}
 	
-	private void unfade()
+	/**
+	 * Creates a slide for preview of the given width and height.
+	 *
+	 * This method creates a slide from the WelcomeActor's { link Theme},
+	 * and substitutes some appropriate "preview" properties for specified
+	 * elements. For example, the user's "real name" is placed in the "author"
+	 * field.
+	 *
+	 * @param w The width of the slide to create.
+	 * @param h The height of the slide to create.
+	 */
+	private Slide create_slide(int w, int h)
 	{
-		is_selected = true;
-		this.animate(FADE_EASE, FADE_TIME, "opacity", 255);
+		var slide = theme.create_slide(PREVIEW_SLIDE, w, h);
+		
+		foreach (var element in slide.elements)
+		{
+			switch (element.identifier)
+			{
+				case Theme.TITLE_TEXT:
+					(element as TextElement).text = "Hello World!";
+					break;
+				case Theme.AUTHOR_TEXT:
+					(element as TextElement).text = Environment.get_real_name();
+					break;
+			}
+		}
+		
+		return slide;
 	}
 }
 
diff --git a/src/ease-welcome-window.vala b/src/ease-welcome-window.vala
index 0a7d4a5..5841a46 100644
--- a/src/ease-welcome-window.vala
+++ b/src/ease-welcome-window.vala
@@ -146,25 +146,25 @@ public class Ease.WelcomeWindow : Gtk.Window
 		y_res.set_range(RESOLUTIONS_Y[0],
 						RESOLUTIONS_Y[resolution_count-1]);
 
-		x_res.value_changed.connect(() =>
+		x_res.value_changed.connect(() => {
+			set_resolution_box((int)(x_res.get_value()),
+			                   (int)(y_res.get_value()));
+			foreach (var p in previews)
 			{
-				set_resolution_box((int)(x_res.get_value()),
-								   (int)(y_res.get_value()));
-				foreach (var p in previews)	{
-					p.set_slide_size((int)x_res.get_value(),
-									 (int)y_res.get_value());
-				}
-			});
+				p.set_slide_size((int)x_res.get_value(),
+				                 (int)y_res.get_value());
+			}
+		});
 
-		y_res.value_changed.connect(() =>
+		y_res.value_changed.connect(() => {
+			set_resolution_box((int)(x_res.get_value()),
+			                   (int)(y_res.get_value()));
+			foreach (var p in previews)
 			{
-				set_resolution_box((int)(x_res.get_value()),
-								   (int)(y_res.get_value()));
-				foreach (var p in previews)	{
-					p.set_slide_size((int)x_res.get_value(),
-									 (int)y_res.get_value());
-				}
-			});
+				p.set_slide_size((int)x_res.get_value(),
+			                     (int)y_res.get_value());
+			}
+		});
 
 		// buttons
 		new_pres_button.sensitive = false;
@@ -207,18 +207,30 @@ public class Ease.WelcomeWindow : Gtk.Window
 		}
 
 		// create the previews
-		foreach (var theme in themes) {
-			var master = theme.create_slide(PREVIEW_ID, 1024, 768);
-			if (master == null) continue;
-			
-			var act = new WelcomeActor (theme, previews, master);
+		foreach (var theme in themes)
+		{
+			// create a new actor
+			var act = new WelcomeActor(theme);
 			previews.add (act);
 			preview_container.add_actor (act);
 			
-			act.selected.connect( () =>
+			// handle the single click (selection) signal
+			act.selected.connect((sender) => {
+				new_pres_button.sensitive = true;
+				selected_theme = (sender as WelcomeActor).theme;
+				
+				foreach (var t in previews)
 				{
-					new_pres_button.sensitive = true;
-				});
+					if (t != sender) t.fade();
+				}
+				sender.unfade();
+			});
+			
+			// handle the double click signal
+			act.double_click.connect((sender) => {
+				selected_theme = (sender as WelcomeActor).theme;
+				create_new_document(null);
+			});
 		}
 
 		embed.contents.add_actor (preview_container);
@@ -236,19 +248,6 @@ public class Ease.WelcomeWindow : Gtk.Window
 			{
 				reflow_previews ();
 			});
-		
-		// click on previews
-		foreach (var a in previews)	{
-			a.button_press_event.connect ((act, event) =>
-                {
-                    if (event.click_count == 2) {
-						create_new_document (null);
-					}
-					(act as WelcomeActor).clicked ();
-					selected_theme = (act as WelcomeActor).theme;
-					return false;
-				});
-		}
 
 		// change the zoom of the previews when the zoom slider is moved
 		zoom_slider.value_changed.connect( () =>
@@ -272,7 +271,7 @@ public class Ease.WelcomeWindow : Gtk.Window
 	}
 
 	[CCode (instance_pos = -1)]
-	public void create_new_document (Gtk.Widget? sender)
+	public void create_new_document(Gtk.Widget? sender)
 	{
 		try
 		{
@@ -404,7 +403,7 @@ public class Ease.WelcomeWindow : Gtk.Window
 			}
 
 			// set the size of the preview
-			a.set_dims(preview_width, preview_width * preview_aspect);
+			a.set_actor_size(preview_width, preview_width * preview_aspect);
 
 			// go to the next line
 			if (++x_position >= per_line)



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