This seemed like a fun exercise. The following tracks start and end coordinates of display objects, supports undo/redo and destroys redo actions when a new movement is made. It's probably a bit simple and restrictive for your needs, but could be easily extended by adding to the VO.
HistoryVO:
package {
import flash.display.DisplayObject;
public class HistoryVO {
public var mc:DisplayObject;
public var oldX:Number;
public var oldY:Number;
public var newX:Number;
public var newY:Number;
public function HistoryVO($mc:DisplayObject,$oldX:Number,$oldY:Number)
{
mc = $mc;
oldX = $oldX;
oldY = $oldY;
}
}
}
HistoryManager:
package {
import flash.display.DisplayObject;
public class HistoryManager {
private var historyList:Vector.<HistoryVO>;
private var tempVO:HistoryVO;
private var index:int;
public function HistoryManager()
{
//initialize the list
historyList = new Vector.<HistoryVO>();
index = -1;
}
public function createEntry($mc:DisplayObject,$oldX:Number,$oldY:Number):void
{
//create a tempory VO to store the old position and the object
tempVO = new HistoryVO($mc,$oldX,$oldY);
}
public function finishEntry($mc:DisplayObject,$newX:Number,$newY:Number):void
{
//make sure this is the same object
if($mc == tempVO.mc) {
tempVO.newX = $newX;
tempVO.newY = $newY;
if(historyList.length > index+1) {
//delete any future history
historyList = historyList.splice(0,index+1);
}
historyList.push(tempVO);
index++;
} else {
throw new Error("Target DisplayObject does not match the stored value");
}
}
//redo
public function nextStep():void
{
if(historyList.length > index+1) {
var step:HistoryVO = historyList[++index];
step.mc.x = step.newX;
step.mc.y = step.newY;
}
}
//undo
public function previousStep():void
{
if(index > -1) {
var step:HistoryVO = historyList[index--];
step.mc.x = step.oldX;
step.mc.y = step.oldY;
}
}
}
}
Example document class:
package {
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.display.MovieClip;
public class Main extends MovieClip {
private var history:HistoryManager;
private var movies:Vector.<Sprite>;
private var backBut:Sprite;
private var nextBut:Sprite;
public function Main()
{
history = new HistoryManager();
movies = new Vector.<Sprite>();
(stage) ? init() : addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(evt:Event = null):void
{
//create some sprites to play with
for(var i:int = 0; i < 5; i++) {
movies[i] = addChild(new Sprite()) as Sprite;
movies[i].x = Math.round(Math.random() * 500);
movies[i].y = Math.round(Math.random() * 350);
movies[i].graphics.beginFill(Math.round(Math.random()*0xFFFFFF));
movies[i].graphics.drawRect(0,0,50,50);
movies[i].graphics.endFill();
movies[i].addEventListener(MouseEvent.MOUSE_DOWN,onDown);
movies[i].addEventListener(MouseEvent.MOUSE_UP,onUp);
}
//create the buttons
backBut = addChild(new Sprite()) as Sprite;
backBut.graphics.beginFill(0x000000);
backBut.graphics.drawRect(0,0,100,30);
backBut.addEventListener(MouseEvent.CLICK,previousStep);
nextBut = addChild(new Sprite()) as Sprite;
nextBut.x = 110;
nextBut.graphics.beginFill(0x000000);
nextBut.graphics.drawRect(0,0,100,30);
nextBut.addEventListener(MouseEvent.CLICK,nextStep);
}
private function onDown(evt:MouseEvent):void
{
history.createEntry(Sprite(evt.target),evt.target.x,evt.target.y);
evt.target.startDrag();
}
private function onUp(evt:MouseEvent):void
{
evt.target.stopDrag();
history.finishEntry(Sprite(evt.target),evt.target.x,evt.target.y);
}
private function previousStep(evt:MouseEvent):void
{
history.previousStep();
}
private function nextStep(evt:MouseEvent):void
{
history.nextStep();
}
}
}