Mercurial > repos > IBBoard
diff Commands/CommandStack.cs @ 0:961030992bd2
Initial commit of IBBoard libraries
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Fri, 19 Dec 2008 11:13:48 +0000 |
parents | |
children | 0352fa33ee8f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Commands/CommandStack.cs Fri Dec 19 11:13:48 2008 +0000 @@ -0,0 +1,176 @@ +using System; +using System.Collections; + +namespace IBBoard.Commands +{ + /// <summary> + /// Summary description for CommandStack. + /// </summary> + public class CommandStack + { + private ArrayList commandStack; + private int listPos = -1; + private int listMax = -1; + private int cleanPos; + + public event MethodInvoker CommandStackUpdated; + + public CommandStack() + { + commandStack = new ArrayList(10); + cleanPos = -1; + } + + public bool IsDirty() + { + return listPos!=cleanPos; + } + + public void setCleanMark() + { + cleanPos = listPos; + } + + public bool IsEmpty() + { + return listMax == -1; + } + + public bool CanUndo() + { + return listPos > -1; + } + + public int UndoLength + { + get { return listPos + 1; } + } + + public int RedoLength + { + get { return listMax - listPos; } + } + + public bool CanRedo() + { + return listPos < listMax; + } + + public void Reset() + { + commandStack.Clear(); + listMax = -1; + listPos = -1; + DoCommandStackUpdated(); + } + + public void Undo() + { + if (CanUndo()) + { + ((Command)commandStack[listPos]).Undo(); + listPos--; + DoCommandStackUpdated(); + } + else + { + throw new InvalidOperationException("Cannot undo action on empty command stack"); + } + } + + public void Redo() + { + if (CanRedo()) + { + ((Command)commandStack[listPos+1]).Redo(); + listPos++; + DoCommandStackUpdated(); + } + else + { + throw new InvalidOperationException("No actions to redo"); + } + } + + public bool Execute(Command cmd) + { + if (cmd.CanExecute()) + { + if (cmd.Execute()) + { + //if we can't redo, i.e. there's no commands beyond our current point, add to the end else insert + if (!CanRedo()) + { + commandStack.Add(cmd); + listPos++; + } + else + { + if (cleanPos>listPos) + { + cleanPos = -2; + } + + //else overwrite at our current position, setting the listMax value will ignore any commands we could have redone beyond here + commandStack[++listPos] = cmd; + } + + listMax = listPos; + DoCommandStackUpdated(); + return true; + } + else + { + throw new InvalidOperationException("Executable command failed to execute"); + } + } + else + { + return false; + } + } + + protected void DoCommandStackUpdated() + { + if (CommandStackUpdated!=null) + { + CommandStackUpdated(); + } + } + + public Command PeekUndoCommand() + { + return PeekUndoCommand(1); + } + + public Command PeekUndoCommand(int backCount) + { + backCount = backCount - 1; + if (backCount > -1 && backCount <= listPos) + { + return (Command)commandStack[listPos-backCount]; + } + else + { + return null; + } + } + + public Command PeekRedoCommand() + { + return PeekRedoCommand(1); + } + + public Command PeekRedoCommand(int forwardCount) + { + if (forwardCount > 0 && listPos+forwardCount <= listMax) + { + return (Command)commandStack[listPos+forwardCount]; + } + else + { + return null; + } + } + } +}