[ease/themes] [editor] New undo system.



commit cb1a4b2f774cda2dccf8abaf645cda720673e9a9
Author: Nate Stedman <natesm gmail com>
Date:   Thu Jul 22 02:28:12 2010 -0400

    [editor] New undo system.
    
    - Undo system now uses object/property pairs
      instead of subclasses for each undo type.
    - Prevents Ease from needing around 3000 or
      so subclasses of UndoAction
    - Allows undo functionality to be easily
      added to anything in Ease.

 src/ease-editor-embed.vala |   28 +++++++++----
 src/ease-undo-actions.vala |   99 ++++++++++++++++++++++++++-----------------
 2 files changed, 80 insertions(+), 47 deletions(-)
---
diff --git a/src/ease-editor-embed.vala b/src/ease-editor-embed.vala
index 528e6bb..30ac67f 100644
--- a/src/ease-editor-embed.vala
+++ b/src/ease-editor-embed.vala
@@ -70,6 +70,11 @@ public class Ease.EditorEmbed : ScrollableEmbed
 	private bool is_drag_initialized;
 	
 	/**
+	 * An UndoAction to be added on drag/resize completion.
+	 */
+	private UndoAction move_undo;
+	
+	/**
 	 * The X position of the mouse in the prior drag event.
 	 */
 	private float mouse_x;
@@ -396,6 +401,11 @@ public class Ease.EditorEmbed : ScrollableEmbed
 			is_drag_initialized = false;
 			Clutter.grab_pointer(sender);
 			sender.motion_event.connect(actor_motion);
+			
+			// create an UndoAction for this drag
+			move_undo = new UndoAction(selected.element, "x");
+			move_undo.add(selected.element, "y");
+			
 			return true;
 		}
 		
@@ -465,9 +475,7 @@ public class Ease.EditorEmbed : ScrollableEmbed
 			is_dragging = false;
 			Clutter.ungrab_pointer();
 			sender.motion_event.disconnect(actor_motion);
-			win.add_undo_action(new MoveUndoAction(selected.element,
-			                                       orig_x, orig_y,
-			                                       orig_w, orig_h));
+			win.add_undo_action(move_undo);
 		}
 		return true;
 	}
@@ -525,12 +533,19 @@ public class Ease.EditorEmbed : ScrollableEmbed
 	 * @param event The corresponding Clutter.Event
 	 */
 	private bool handle_clicked(Clutter.Actor sender, Clutter.ButtonEvent event)
-	{	
+	{
 		(sender as Handle).flip(true);
 		is_dragging = true;
 		is_drag_initialized = false;
 		sender.motion_event.connect(handle_motion);
 		Clutter.grab_pointer(sender);
+		
+		// create an UndoAction for this resize
+		move_undo = new UndoAction(selected.element, "x");
+		move_undo.add(selected.element, "y");
+		move_undo.add(selected.element, "width");
+		move_undo.add(selected.element, "height");
+		
 		return true;
 	}
 	
@@ -552,10 +567,7 @@ public class Ease.EditorEmbed : ScrollableEmbed
 			(sender as Handle).flip(false);
 			is_dragging = false;
 			sender.motion_event.disconnect(handle_motion);
-			
-			win.add_undo_action(new MoveUndoAction(selected.element,
-			                                       orig_x, orig_y,
-			                                       orig_w, orig_h));
+			win.add_undo_action(move_undo);
 		}
 		
 		Clutter.ungrab_pointer();
diff --git a/src/ease-undo-actions.vala b/src/ease-undo-actions.vala
index 5dadfcd..d91b098 100644
--- a/src/ease-undo-actions.vala
+++ b/src/ease-undo-actions.vala
@@ -21,62 +21,83 @@
  * Subclasses should override apply() and add a constructor, as well as any
  * needed data fields.
  */
-public abstract class Ease.UndoAction : Object
+public class Ease.UndoAction : Object
 {
+	private Gee.LinkedList<UndoPair> pairs = new Gee.LinkedList<UndoPair>();
+	
 	/**
-	 * Applies the { link UndoAction}.
+	 * Creates an UndoAction.
+	 *
+	 * This should be followed up with calls to add() if the action has
+	 * multiple properties (or someone could figure out varargs in Vala).
 	 *
-	 * This method should be overriden by subclasses to undo the appropriate
-	 * action. It should return an UndoAction that will redo the UndoAction.
+	 * @param obj The first object.
+	 * @param val The first property.
 	 */
-	public abstract UndoAction apply();
-}
-
-/**
- * { link UndoAction} for moving or resizing an { link Actor}.
- */
-public class Ease.MoveUndoAction : UndoAction
-{
-	private Element element;
-	private float x_pos;
-	private float y_pos;
-	private float width;
-	private float height;
+	public UndoAction(GLib.Object obj, string prop)
+	{
+		pairs.add(new UndoPair(obj, prop));
+	}
 	
 	/**
-	 * Creates a new MoveUndoAction.
+	 * Adds an additional object/property pair.
 	 *
-	 * @param element The { link Element} this applies to.
-	 * @param x The original X position of the { link Element}.
-	 * @param y The original Y position of the { link Element}.
-	 * @param w The original width of the { link Element}
-	 * @param h The original height position of the { link Element}
+	 * @param obj The first object.
+	 * @param val The first property.
 	 */
-	public MoveUndoAction(Element e, float x, float y, float w, float h)
+	public void add(GLib.Object obj, string prop)
 	{
-		element = e;
-		x_pos = x;
-		y_pos = y;
-		width = w;
-		height = h;
+		pairs.add(new UndoPair(obj, prop));
 	}
 	
 	/**
-	 * Moves the { link Element} back to its original position.
+	 * Applies the { link UndoAction}, restoring previous settings.
 	 *
-	 * { inheritDoc}
+	 * Returns an UndoAction that will redo the undo action.
+	 */
+	public UndoAction apply()
+	{
+		foreach (var pair in pairs) pair.apply();
+		return this;
+	}
+	
+	/**
+	 * Embedded class for storing object/property pairs in undo actions.
 	 */
-	public override UndoAction apply()
+	private class UndoPair
 	{
-		var ret = new MoveUndoAction(element, element.x, element.y,
-		                             element.width, element.height);
+		private string property;
+		private GLib.Object object;
+		private GLib.Value val;
+		private GLib.Type type;
 		
-		element.x = x_pos;
-		element.y = y_pos;
-		element.width = width;
-		element.height = height;
+		public UndoPair(GLib.Object obj, string prop)
+		{
+			object = obj;
+			property = prop;
+			type = obj.get_class().find_property(prop).value_type;
+			val = GLib.Value(type);
+			obj.get_property(prop, ref val);
+		}
 		
-		return ret;
+		/**
+		 * Applies this UndoPair, restoring the property to its original value.
+		 *
+		 * The current (before restoration) value is then placed into this
+		 * UndoPair, converting it into a "RedoPair" of sorts.
+		 */
+		public void apply()
+		{
+			// remember the current value so that it can be restored (redo)
+			GLib.Value temp = GLib.Value(type);
+			object.get_property(property, ref temp);
+			
+			// restore the old value
+			object.set_property(property, val);
+			
+			// give the pair the old value so it can be used to revert
+			val = temp;
+		}
 	}
 }
 



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