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;
+			}
+		}
+	}
+}