using System.Collections.Generic; namespace Unity.PlasticSCM.Editor.UI.UndoRedo { internal class UndoRedoHelper { internal interface IUndoRedoHost { UndoRedoState UndoRedoState { get; set; } } internal bool CanUndo { get { return mCurrentNode != null && mCurrentNode.Previous != null; } } internal bool CanRedo { get { return mCurrentNode != null && mCurrentNode.Next != null; } } internal UndoRedoHelper(IUndoRedoHost host) { mHost = host; } internal bool TryGetLastState(out UndoRedoState state) { state = null; if (!IsInLastState) return false; state = mCurrentNode.Value; return true; } internal void UpdateLastState() { UpdateLastState(mHost.UndoRedoState); } internal void Undo() { if (mCurrentNode != null && mCurrentNode.Previous != null) { mCurrentNode = mCurrentNode.Previous; mHost.UndoRedoState = mCurrentNode.Value; } } internal void Redo() { if (mCurrentNode != null && mCurrentNode.Next != null) { mCurrentNode = mCurrentNode.Next; mHost.UndoRedoState = mCurrentNode.Value; } } internal void Snapshot() { UndoRedoState current = mHost.UndoRedoState; if (mCurrentNode == null || !mCurrentNode.Value.Equals(current)) { if (mCurrentNode != null && mCurrentNode.Next != null) DiscardRedo(); mStates.AddLast(current); mCurrentNode = mStates.Last; if (mStates.Count > UNDO_LIMIT) mStates.RemoveFirst(); } } bool IsInLastState { get { return mCurrentNode != null && mCurrentNode.Next == null; } } void UpdateLastState(UndoRedoState state) { if (mStates.Last != null) mStates.Last.Value = state; } void DiscardRedo() { while (mCurrentNode != null && mCurrentNode.Next != null) mStates.Remove(mCurrentNode.Next); } LinkedListNode mCurrentNode; readonly IUndoRedoHost mHost; readonly LinkedList mStates = new LinkedList(); const int UNDO_LIMIT = 250; } }