[ease] [backgrounds] Allow the user to change image scaling



commit e6ae21124505b2703c63daa571139803b5d24d14
Author: Nate Stedman <natesm gmail com>
Date:   Wed Jul 28 19:06:06 2010 -0400

    [backgrounds] Allow the user to change image scaling
    
    - User can select from scale, maintain original size,
      and maintain aspect ratio.

 data/ui/background.ui                 |   42 ++++++++++-
 ease-core/Makefile.am                 |   10 ++-
 ease-core/ease-background-widget.vala |   64 ++++++++++++++--
 ease-core/ease-background.vala        |   18 +++-
 ease-core/ease-image.vala             |  132 +++++++++++++++++++++++++++++++--
 ease-core/ease-slide.vala             |   28 ++-----
 ease-core/ease-theme.vala             |    6 ++
 7 files changed, 258 insertions(+), 42 deletions(-)
---
diff --git a/data/ui/background.ui b/data/ui/background.ui
index b12090d..b07b3c6 100644
--- a/data/ui/background.ui
+++ b/data/ui/background.ui
@@ -54,7 +54,6 @@
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="fill">False</property>
             <property name="position">0</property>
           </packing>
         </child>
@@ -258,6 +257,7 @@
         <child>
           <object class="GtkVBox" id="vbox-image">
             <property name="orientation">vertical</property>
+            <property name="spacing">4</property>
             <child>
               <object class="GtkHBox" id="hbox1">
                 <property name="visible">True</property>
@@ -292,6 +292,46 @@
                 <property name="position">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkHBox" id="hbox6">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkLabel" id="image-label1">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Fill Mode</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBox" id="image-fill">
+                <property name="height_request">30</property>
+                <property name="visible">True</property>
+                <signal name="changed" handler="ease_background_widget_on_image_fill_changed"/>
+                <child>
+                  <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                  <attributes>
+                    <attribute name="text">0</attribute>
+                  </attributes>
+                </child>
+              </object>
+              <packing>
+                <property name="position">3</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
diff --git a/ease-core/Makefile.am b/ease-core/Makefile.am
index 7ef729e..85bbba9 100644
--- a/ease-core/Makefile.am
+++ b/ease-core/Makefile.am
@@ -49,18 +49,26 @@ libease_core_0_3_la_SOURCES = \
 	$(NULL)
 
 # compiler flags
+
+# I don't _want_ to --disable-warnings, but the choices appear to be:
+#    - enable warnings, mark signal handlers for GtkBuilder as public
+#    - disable warnings, hide functionality properly \
+#    - enable warnings, hide functionality, get spammed with unused
+#      function warnings
+# Therefore, warnings are off.
+
 libease_core_0_3_la_VALAFLAGS = \
 	$(EASE_PACKAGES) \
 	--vapi=../vapi/ease-core-0.3.vapi \
 	--header=libease-core.h \
 	--thread \
+	--disable-warnings \
 	--vapidir=../vapi \
 	--pkg flutter-0.3 \
 	-g \
 	$(NULL)
 
 libease_core_0_3_la_LIBADD = ../flutter/libflutter-0.3.la
-
 libease_core_0_3_la_CFLAGS = $(EASE_CFLAGS)
 libease_core_0_3_la_LDFLAGS = $(EASE_LDFLAGS)
 
diff --git a/ease-core/ease-background-widget.vala b/ease-core/ease-background-widget.vala
index 0eb6725..90a1b85 100644
--- a/ease-core/ease-background-widget.vala
+++ b/ease-core/ease-background-widget.vala
@@ -29,6 +29,7 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 	private Gtk.VBox box_color;
 	private Gtk.VBox box_gradient;
 	private Gtk.VBox box_image;
+	private Gtk.ComboBox image_fill;
 	private Gtk.HScale grad_angle;
 	
 	private Gtk.ColorButton bg_color;
@@ -88,6 +89,7 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 		gradient_type =
 			builder.get_object("combo-gradient") as Gtk.ComboBox;
 		grad_angle = builder.get_object("hscale-angle") as Gtk.HScale;
+		image_fill = builder.get_object("image-fill") as Gtk.ComboBox;
 		
 		// display the correct UI
 		display_bg_ui(background.background_type);
@@ -95,6 +97,9 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 		// set up the gradient type combobox
 		gradient_type.model = GradientType.list_store();
 		
+		// set up the image fill type combobox
+		image_fill.model = ImageFillType.list_store();
+		
 		// get the combobox
 		background_type = builder.get_object("combobox-style") as Gtk.ComboBox;
 		
@@ -140,6 +145,19 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 			}
 		} while (gradient_type.model.iter_next(ref itr));
 		
+		// set the image fill box
+		ImageFillType img_type;
+		image_fill.model.get_iter_first(out itr);
+		do
+		{
+			image_fill.model.get(itr, 1, out img_type);
+			if (img_type == background.image.fill)
+			{
+				image_fill.set_active_iter(itr);
+				break;
+			}
+		} while (image_fill.model.iter_next(ref itr));
+		
 		
 		// connect signals
 		builder.connect_signals(this);
@@ -155,7 +173,7 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 	}
 	
 	[CCode (instance_pos = -1)]
-	public void on_background_changed(Gtk.Widget? sender)
+	internal void on_background_changed(Gtk.Widget? sender)
 	{
 		Gtk.TreeIter itr;
 		store.get_iter_first(out itr);
@@ -237,9 +255,14 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 	}
 	
 	[CCode (instance_pos = -1)]
-	public void on_gradient_type_changed(Gtk.ComboBox? sender)
+	internal void on_gradient_type_changed(Gtk.ComboBox? sender)
 	{
 		var action = new UndoAction(background.gradient, "mode");
+		
+		action.applied.connect((a) => {
+			display_bg_ui(background.background_type);
+		});
+		
 		GradientType type;
 		Gtk.TreeIter itr;
 		sender.model.get_iter_first(out itr);
@@ -253,7 +276,28 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 	}
 	
 	[CCode (instance_pos = -1)]
-	public void on_color_set(Gtk.ColorButton? sender)
+	internal void on_image_fill_changed(Gtk.ComboBox? sender)
+	{
+		var action = new UndoAction(background.image, "fill");
+		
+		action.applied.connect((a) => {
+			display_bg_ui(background.background_type);
+		});
+		
+		ImageFillType type;
+		Gtk.TreeIter itr;
+		sender.model.get_iter_first(out itr);
+		for (int i = 0; i < sender.get_active(); i++)
+		{
+			sender.model.iter_next(ref itr);
+		}
+		sender.model.get(itr, 1, out type);
+		background.image.fill = type;
+		emit_undo(action);
+	}
+	
+	[CCode (instance_pos = -1)]
+	internal void on_color_set(Gtk.ColorButton? sender)
 	{
 		UndoAction action = null;
 		if (sender == bg_color)
@@ -284,7 +328,7 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 	}
 	
 	[CCode (instance_pos = -1)]
-	public void on_file_set(Gtk.FileChooserButton? sender)
+	internal void on_file_set(Gtk.FileChooserButton? sender)
 	{
 		var action = new UndoAction(background, "image");
 		action.add(background, "image-source");
@@ -321,7 +365,7 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 	}
 	
 	[CCode (instance_pos = -1)]
-	public void on_reverse_gradient(Gtk.Widget? sender)
+	internal void on_reverse_gradient(Gtk.Widget? sender)
 	{
 		// create an undo action
 		var action = new UndoAction(background.gradient, "start");
@@ -345,7 +389,7 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 	}
 	
 	[CCode (instance_pos = -1)]
-	public void on_set_angle(Gtk.Widget? sender)
+	internal void on_set_angle(Gtk.Widget? sender)
 	{
 		var action = new UndoAction(background.gradient, "angle");
 		background.gradient.angle =
@@ -384,9 +428,11 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 				if (background.gradient == null)
 				{
 					background.gradient = new Gradient(Color.black,
-					                                         Color.white);
-					gradient_type.set_active(background.gradient.mode);
+					                                   Color.white);
 				}
+				
+				gradient_type.set_active(background.gradient.mode);
+				
 				background.background_type = BackgroundType.GRADIENT;
 				
 				grad_color1.set_color(background.gradient.start.gdk);
@@ -410,6 +456,8 @@ public class Ease.BackgroundWidget : Gtk.Alignment
 				{
 					bg_image.unselect_all();
 				}
+				
+				image_fill.set_active(background.image.fill);
 							
 				break;
 		}
diff --git a/ease-core/ease-background.vala b/ease-core/ease-background.vala
index f8104a6..7712693 100644
--- a/ease-core/ease-background.vala
+++ b/ease-core/ease-background.vala
@@ -24,7 +24,7 @@ public class Ease.Background : GLib.Object
 	/**
 	 * The background background_type of this element.
 	 */
-	public BackgroundType background_type { get; internal set; }
+	internal BackgroundType background_type { get; set; }
 	
 	/**
 	 * The background color, if this element uses a solid color for a
@@ -33,7 +33,7 @@ public class Ease.Background : GLib.Object
 	 * To use this property, { link background_type} must also be set to
 	 * { link BackgroundType.COLOR}.
 	 */
-	public Color color { get; internal set; default = Color.black; }
+	internal Color color { get; set; default = Color.black; }
 	
 	/**
 	 * The background gradient, if this slide uses a gradient for a background.
@@ -41,13 +41,16 @@ public class Ease.Background : GLib.Object
 	 * To use this property, { link background_type} must also be set to
 	 * { link BackgroundType.GRADIENT}.
 	 */
-	public Gradient gradient { get; internal set;
-	                           default = Gradient.default_background; }
+	internal Gradient gradient { get; set;
+	                             default = Gradient.default_background; }
 	
 	/**
+	 * The background image, if this slide uses an image for a background.
 	 *
+	 * To use this property, { link background_type} must also be set to
+	 * { link BackgroundType.IMAGE}.
 	 */
-	public Image image { get; internal set; default = new Image(); }
+	internal Image image { get; set; default = new Image(); }
 	
 	/**
 	 * Emitted when an image file is added to this background.
@@ -79,6 +82,8 @@ public class Ease.Background : GLib.Object
 			image.filename = obj.get_string_member(Theme.BACKGROUND_IMAGE);
 			image.source =
 				obj.get_string_member(Theme.BACKGROUND_IMAGE_SOURCE);
+			image.fill = ImageFillType.from_string(
+				obj.get_string_member(Theme.BACKGROUND_IMAGE_SOURCE));
 		}
 		if (obj.has_member(Theme.BACKGROUND_COLOR))
 		{
@@ -102,6 +107,8 @@ public class Ease.Background : GLib.Object
 		if (image != null)
 		{
 			obj.set_string_member(Theme.BACKGROUND_IMAGE, image.filename);
+			obj.set_string_member(Theme.BACKGROUND_IMAGE_FILL,
+			                      image.fill.to_string());
 			obj.set_string_member(Theme.BACKGROUND_IMAGE_SOURCE,
 			                      image.source);
 		}
@@ -150,6 +157,7 @@ public class Ease.Background : GLib.Object
 		if (gradient.start in item) return true;
 		if (gradient.end in item) return true;
 		if (gradient in item) return true;
+		if (image in item) return true;
 		return false;
 	}
 }
diff --git a/ease-core/ease-image.vala b/ease-core/ease-image.vala
index 5ccc0b2..c113793 100644
--- a/ease-core/ease-image.vala
+++ b/ease-core/ease-image.vala
@@ -23,12 +23,17 @@ public class Ease.Image : GLib.Object
 	 * To use this property, { link background_type} must also be set to
 	 * { link BackgroundType.IMAGE}.
 	 */
-	public string filename { get; set; }
+	internal string filename { get; set; }
 	
 	/**
 	 * The original path to the background image. This path is used in the UI.
 	 */
-	public string source { get; set; }
+	internal string source { get; set; }
+	
+	/**
+	 * The fill mode of this image.
+	 */
+	internal ImageFillType fill { get; set; default = ImageFillType.STRETCH; }
 	
 	/**
 	 * Sets up a CairoContext to render this image.
@@ -43,11 +48,53 @@ public class Ease.Image : GLib.Object
 		try
 		{
 			string full = Path.build_filename(path, filename);
-			var pixbuf = new Gdk.Pixbuf.from_file_at_scale(full,
-	    	                                               width,
-	    	                                               height,
-	    	                                               false);
-			Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
+			Gdk.Pixbuf pixbuf;
+			switch (fill)
+			{
+				case ImageFillType.STRETCH:
+					pixbuf = new Gdk.Pixbuf.from_file_at_scale(full,
+					                                           width,
+					                                           height,
+					                                           false);
+					Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
+					break;
+				case ImageFillType.ASPECT:
+					pixbuf = new Gdk.Pixbuf.from_file(full);
+					
+					// get the aspect ratio of both image and drawing area
+					var this_aspect = (float)width / height;
+					
+					// set the pixbuf as source
+					Gdk.Pixbuf out_pixbuf;
+					if (this_aspect > 1) // set the image's height
+					{
+						out_pixbuf = pixbuf.scale_simple(
+							width, (int)(height * this_aspect),
+							Gdk.InterpType.BILINEAR);
+						Gdk.cairo_set_source_pixbuf(
+							cr, out_pixbuf,
+					    	0,
+					    	(height - out_pixbuf.height) / 2);
+					}
+					else // set the image's width
+					{
+						out_pixbuf = pixbuf.scale_simple(
+							(int)(width / this_aspect), height,
+							Gdk.InterpType.BILINEAR);
+						Gdk.cairo_set_source_pixbuf(
+							cr, out_pixbuf,
+					    	(width - out_pixbuf.width) / 2,
+					    	0);
+					}
+					break;
+				case ImageFillType.ORIGINAL:
+					pixbuf = new Gdk.Pixbuf.from_file(full);
+					Gdk.cairo_set_source_pixbuf(cr, pixbuf,
+					                            (width - pixbuf.width) / 2,
+					                            (height - pixbuf.height) / 2);
+					break;
+			}
+			
 		}
 		catch (Error e)
 		{
@@ -55,3 +102,74 @@ public class Ease.Image : GLib.Object
 		}
 	}
 }
+
+internal enum Ease.ImageFillType
+{
+	STRETCH,
+	ASPECT,
+	ORIGINAL;
+	
+	/**
+	 * Returns a string representation of this ImageFillType.
+	 */
+	public string to_string()
+	{
+		switch (this)
+		{
+			case STRETCH: return Theme.IMAGE_STRETCH;
+			case ASPECT: return Theme.IMAGE_ASPECT;
+			case ORIGINAL: return Theme.IMAGE_ORIGINAL;
+		}
+		return "undefined";
+	}
+	
+	/**
+	 * Creates a ImageFillType from a string representation.
+	 */
+	public static ImageFillType from_string(string str)
+	{
+		switch (str)
+		{
+			case Theme.IMAGE_STRETCH: return STRETCH;
+			case Theme.IMAGE_ASPECT: return ASPECT;
+			case Theme.IMAGE_ORIGINAL: return ORIGINAL;
+		}
+		
+		warning("%s is not an image fill type", str);
+		return STRETCH;
+	}
+	
+	/**
+	 * Returns a string description of the ImageFillType
+	 */
+	public string description()
+	{
+		switch (this)
+		{
+			case STRETCH: return _("Stretch");
+			case ASPECT: return _("Maintain Aspect Ratio");
+			case ORIGINAL: return _("Do not Scale");
+		}
+		return "undefined";
+	}
+	
+	/**
+	 * Creates a ListStore with the first column set as the description
+	 * and the second column set as the ImageFillType.
+	 */
+	public static Gtk.ListStore list_store()
+	{
+		var store = new Gtk.ListStore(2, typeof(string), typeof(ImageFillType));
+		Gtk.TreeIter itr;
+		
+		store.append(out itr);
+		store.set(itr, 0, STRETCH.description(), 1, STRETCH);
+		store.append(out itr);
+		store.set(itr, 0, ASPECT.description(), 1, ASPECT);
+		store.append(out itr);
+		store.set(itr, 0, ORIGINAL.description(), 1, ORIGINAL);
+		
+		return store;
+	}
+}
+
diff --git a/ease-core/ease-slide.vala b/ease-core/ease-slide.vala
index 1dc92d7..22dfb13 100644
--- a/ease-core/ease-slide.vala
+++ b/ease-core/ease-slide.vala
@@ -292,7 +292,8 @@ public class Ease.Slide : GLib.Object, UndoSource
 		// write the slide's background properties
 		if (background.image.filename != null)
 		{
-			obj.set_string_member(Theme.BACKGROUND_IMAGE, background.image.filename);
+			obj.set_string_member(Theme.BACKGROUND_IMAGE,
+			                      background.image.filename);
 			obj.set_string_member("background-image-source",
 			                      background.image.source);
 		}
@@ -432,25 +433,12 @@ public class Ease.Slide : GLib.Object, UndoSource
 	public void cairo_render_background(Cairo.Context cr,
 	                                    int w, int h) throws GLib.Error
 	{
-		switch (background.background_type)
-		{
-			case BackgroundType.COLOR:
-				cr.rectangle(0, 0, w, h);
-				background.color.set_cairo(cr);
-				cr.fill();
-				break;
-			case BackgroundType.GRADIENT:
-				background.gradient.cairo_render_rect(cr, w, h);
-				break;
-			case BackgroundType.IMAGE:
-				var pixbuf = new Gdk.Pixbuf.from_file_at_scale(background_abs,
-			                                                   w, h,
-			                                                   false);
-				Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
-				cr.rectangle(0, 0, w, h);
-				cr.fill();
-				break;
-		}
+		cr.save();
+		background.set_cairo(cr, w, h,
+		                     parent == null ? theme.path : parent.path);
+		cr.rectangle(0, 0, w, h);
+		cr.fill();
+		cr.restore();
 	}
 	
 	/**
diff --git a/ease-core/ease-theme.vala b/ease-core/ease-theme.vala
index 634294d..36e4911 100644
--- a/ease-core/ease-theme.vala
+++ b/ease-core/ease-theme.vala
@@ -60,6 +60,7 @@ public class Ease.Theme : GLib.Object
 	public const string BACKGROUND_GRADIENT = "background-gradient";
 	public const string BACKGROUND_IMAGE = "background-image";
 	public const string BACKGROUND_IMAGE_SOURCE = "background-image-source";
+	public const string BACKGROUND_IMAGE_FILL = "background-image-fill";
 	public const string S_IDENTIFIER = "slide-identifier";
 	
 	// background types
@@ -101,6 +102,11 @@ public class Ease.Theme : GLib.Object
 	public const string GRAD_LINEAR_MIRRORED = "linear-mirrored";
 	public const string GRAD_RADIAL = "radial";
 	
+	// image fill types
+	public const string IMAGE_STRETCH = "image-fill-stretch";
+	public const string IMAGE_ASPECT = "image-fill-aspect";
+	public const string IMAGE_ORIGINAL = "image-fill-original";
+	
 	// generic element properties
 	public const string E_IDENTIFIER = "element-identifier";
 	public const string ELEMENT_TYPE = "element-type";



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