I'd highly recommend you look into the Command Pattern:
Essentially, this involves creating "Command" subclasses for each type of action the user can perform - and pushing them unto a stack once the command has been executed.
Each command knows how to "do" itself, and also "undo" itself.
Thus, undo is a relatively straight forward process of popping commands off the stack, and calling the undo method on them.
Because each instance of a Command can contain it's own state ("options"), you can create exactly the commands you want to use ahead of time, and "batch" them to get the result you are looking for.
pseudo-code:
public class ImageEditor { public Stack<Command> undoList = new Stack<Command>(); public void executeCommand(Command command) { command.performAction(this); undoList.push(command); } public void undo() { undoList.peek().undoAction(this); undoList.pop(); } } public interface ICommand { void performAction(ImageEditor editor); void undoAction(ImageEditor editor); } public class CreateBorderCommand : ICommand { public int BorderWidth { get; set; } private Border MyBorderBox { get; set; } public void performAction(ImageEditor editor) { MyBorderBox = new Border(BorderWidth, editor.frame); editor.addElement(MyBorderBox); } public void undoAction(ImageEditor editor) { editor.removeElement(MyBorderBox); } }
Later on:
ImageEditor editor = new ImageEditor(); editor.executeCommand(new CreateBorderCommand() { BorderWidth = 10 }); ...
If you really want, you could make it a little more involved, and make all of the command definitions serializable - allowing you to create a list of them and read in the list and execute them later.