[ease] Element resizing via Handles mostly functional*.



commit 215aa1f25a4b941b8a78d79ada51027309eb300b
Author: Nate Stedman <natesm gmail com>
Date:   Wed May 19 02:38:07 2010 -0400

    Element resizing via Handles mostly functional*.
    
    *There are a few issues:
    
    - Top left handle is broken with shift held down.
    - Handles only work where they do not overlap their Actor (hence the size)
    - "Collapsing" an actor to the right or the bottom causes it to begin moving with the mouse.

 src/libease/Actor.vala       |   38 ++++++++++++++
 src/libease/EditorEmbed.vala |  111 ++++++++++++++++++++++++++++++++++++++++--
 src/libease/Handle.vala      |   79 +++++++++++++++++++++---------
 3 files changed, 200 insertions(+), 28 deletions(-)
---
diff --git a/src/libease/Actor.vala b/src/libease/Actor.vala
index 59ed449..769a9f3 100644
--- a/src/libease/Actor.vala
+++ b/src/libease/Actor.vala
@@ -69,5 +69,43 @@ public class Ease.Actor : Clutter.Group
 		element.x = x;
 		element.y = y;
 	}
+	
+	/**
+	 * Resize this Actor and update its { link Element}
+	 * 
+	 * Used in the editor and tied to Clutter MotionEvents on handles.
+	 *
+	 * @param w_change The amount of width change.
+	 * @param h_change The amount of height change.
+	 * @param proportional If the resize should be proportional only
+	 */
+	public void resize(float w_change, float h_change, bool proportional)
+	{
+		if (proportional)
+		{
+			if (w_change / h_change > width / height)
+			{
+				w_change = h_change * (width / height);
+			}
+			else if (w_change / h_change < width / height)
+			{
+				h_change = w_change * (height / width);
+			}
+		}
+	
+		if (width + w_change > 1)
+		{
+			width += w_change;
+			contents.width += w_change;
+		}
+		if (height + h_change > 1)
+		{
+			height += h_change;
+			contents.height += h_change;
+		}
+		
+		element.width = width;
+		element.height = height;	
+	}
 }
 
diff --git a/src/libease/EditorEmbed.vala b/src/libease/EditorEmbed.vala
index 977397b..406d5b5 100644
--- a/src/libease/EditorEmbed.vala
+++ b/src/libease/EditorEmbed.vala
@@ -157,10 +157,18 @@ public class Ease.EditorEmbed : ScrollableEmbed
 		// remove the selection rectangle
 		if (selection_rectangle != null)
 		{
-			contents.remove_actor(selection_rectangle);
+			if (selection_rectangle.get_parent() == contents)
+			{
+				contents.remove_actor(selection_rectangle);
+			}
 			foreach (var h in handles)
 			{
-				contents.remove_actor(h);
+				if (h.get_parent() == contents)
+				{
+					contents.remove_actor(h);
+				}
+				h.button_press_event.disconnect(handle_clicked);
+				h.button_release_event.disconnect(handle_released);
 			}
 		}
 		
@@ -255,14 +263,23 @@ public class Ease.EditorEmbed : ScrollableEmbed
 			return true;
 		}
 		
-		// remove the selection rectangle
+		// remove the selection rectangle and handles
 		if (selection_rectangle != null)
 		{
 			foreach (var h in handles)
 			{
-				contents.remove_actor(h);
+				h.button_press_event.disconnect(handle_clicked);
+				h.button_release_event.disconnect(handle_released);
+				
+				if (h.get_parent() == contents)
+				{	
+					contents.remove_actor(h);
+				}
+			}
+			if (selection_rectangle.get_parent() == contents)
+			{
+				contents.remove_actor(selection_rectangle);
 			}
-			contents.remove_actor(selection_rectangle);
 		}
 		
 		selected = (Actor)sender;
@@ -281,6 +298,9 @@ public class Ease.EditorEmbed : ScrollableEmbed
 			handles[i] = new Handle((HandlePosition)i);
 			handles[i].reposition(selection_rectangle);
 			contents.add_actor(handles[i]);
+			
+			handles[i].button_press_event.connect(handle_clicked);
+			handles[i].button_release_event.connect(handle_released);
 		}
 		
 		return true;
@@ -343,5 +363,86 @@ public class Ease.EditorEmbed : ScrollableEmbed
 		}
 		return true;
 	}
+	
+	/**
+	 * Signal handler for clicking on a { link Handle}.
+	 * 
+	 * This handler is attached to the button_press_event of all
+	 * { link Handle}s.
+	 *
+	 * @param sender The { link Handle} that was clicked
+	 * @param event The corresponding Clutter.Event
+	 */
+	public bool handle_clicked(Clutter.Actor sender, Clutter.Event event)
+	{
+		is_dragging = true;
+		is_drag_ready = false;
+		sender.motion_event.connect(handle_motion);
+		Clutter.grab_pointer(sender);
+		return true;
+	}
+	
+	/**
+	 * Signal handler for releasing an { link Handle}.
+	 * 
+	 * This handler is attached to the button_release_event of all
+	 * { link Handle}s.
+	 *
+	 * When the { link Handle} is being dragged, this ends the drag action.
+	 *
+	 * @param sender The { link Handle} that was released
+	 * @param event The corresponding Clutter.Event
+	 */
+	public bool handle_released(Clutter.Actor sender, Clutter.Event event)
+	{
+		if (is_dragging)
+		{
+			is_dragging = false;
+			sender.motion_event.disconnect(handle_motion);
+		}
+		
+		Clutter.ungrab_pointer();
+		return true;
+	}
+	
+	/**
+	 * Signal handler for dragging an { link Handle}.
+	 * 
+	 * This handler is attached to the motion_event of all
+	 * { link Handle}s.
+	 *
+	 * It will only have an effect if a drag is active.
+	 *
+	 * @param sender The { link Handle} that was dragged
+	 * @param event The corresponding Clutter.Event
+	 */
+	public bool handle_motion(Clutter.Actor sender, Clutter.Event event)
+	{
+		Handle handle = (Handle)sender;
+		
+		if (!is_drag_ready)
+		{
+			is_drag_ready = true;
+			mouse_x = event.motion.x;
+			mouse_y = event.motion.y;
+			return true;
+		}
+		
+		float factor = 1 / zoom;
+		var motion = event.motion;
+		var p = (motion.modifier_state & Clutter.ModifierType.SHIFT_MASK) != 0;
+		
+		handle.drag(factor * (motion.x - mouse_x),
+		            factor * (motion.y - mouse_y),
+		            selected,
+		            p);
+		
+		mouse_x = motion.x;
+		mouse_y = motion.y;
+		
+		position_selection();
+		
+		return true;
+	}
 }
 
diff --git a/src/libease/Handle.vala b/src/libease/Handle.vala
index daa3314..cbd21cf 100644
--- a/src/libease/Handle.vala
+++ b/src/libease/Handle.vala
@@ -15,45 +15,78 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-public class Ease.Handle : Clutter.Group
-{
-	// the graphical element of the rectangle
-	private Clutter.Rectangle rectangle;
-	
-	// the position of this rectangle
+/**
+ * Interface element for manipulating the size of { link Actor}s.
+ */
+public class Ease.Handle : Clutter.Rectangle
+{	
+	// the position of this handle
 	private HandlePosition position;
-
-	// the offset of the pointer, so things don't jump
-	private int pointer_offset_x;
-	private int pointer_offset_y;
 	
 	// constants
-	public static const float SIZE = 10;
+	public const float SIZE = 50;
 	
 	public Handle(HandlePosition pos)
 	{
 		// set the rectangle's position
 		position = pos;
 
-		// make the actual rectangle
-		rectangle = new Clutter.Rectangle();
-
 		// set the rectangle's color
-		rectangle.color = {0, 0, 0, 255};
+		color = {0, 0, 0, 255};
 
 		// set the rectangle's border
-		rectangle.border_width = 2;
-		rectangle.border_color = {255, 255, 255, 255};
+		border_width = 2;
+		border_color = {255, 255, 255, 255};
 
 		// set the rectangle's size
-		rectangle.width = SIZE;
-		rectangle.height = SIZE;
+		width = SIZE;
+		height = SIZE;
 		set_anchor_point(SIZE / 2, SIZE / 2);
-
-		// add the rectangle
-		add_actor(rectangle);
 		
-		reactive = true;
+		set_reactive(true);
+	}
+	
+	public void drag(float change_x, float change_y, Actor target, bool prop)
+	{
+		switch (position)
+		{
+			case HandlePosition.TOP_LEFT:
+				target.translate(change_x, change_y);
+				target.resize(-change_x, -change_y, prop);
+				break;
+				
+			case HandlePosition.TOP_RIGHT:
+				target.translate(0, change_y);
+				target.resize(change_x, -change_y, prop);
+				break;
+				
+			case HandlePosition.TOP:
+				target.translate(0, change_y);
+				target.resize(0, -change_y, false);
+				break;
+				
+			case HandlePosition.BOTTOM:
+				target.resize(0, change_y, false);
+				break;
+				
+			case HandlePosition.LEFT:
+				target.translate(change_x, 0);
+				target.resize(-change_x, 0, false);
+				break;
+				
+			case HandlePosition.RIGHT:
+				target.resize(change_x, 0, false);
+				break;
+				
+			case HandlePosition.BOTTOM_LEFT:
+				target.translate(change_x, 0);
+				target.resize(-change_x, change_y, prop);
+				break;
+				
+			case HandlePosition.BOTTOM_RIGHT:
+				target.resize(change_x, change_y, prop);
+				break;
+		}
 	}
 	
 	public void reposition(Clutter.Actor selection)



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