Initial Commit
This commit is contained in:
154
Common/UndoSystem/UndoProvider.cs
Normal file
154
Common/UndoSystem/UndoProvider.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Common.UndoSystem
|
||||
{
|
||||
public class UndoProvider : INotifyPropertyChanged
|
||||
{
|
||||
private readonly ActionStack undoStack = new ActionStack();
|
||||
private readonly ActionStack redoStack = new ActionStack();
|
||||
|
||||
public UndoProvider()
|
||||
{
|
||||
undoStack.IsEmptyChanged += OnUndoStackIsEmptyChanged;
|
||||
redoStack.IsEmptyChanged += OnRedoStackIsEmptyChanged;
|
||||
}
|
||||
|
||||
private bool isEnabled = true;
|
||||
public bool IsEnabled
|
||||
{
|
||||
get { return isEnabled; }
|
||||
set { isEnabled = value; }
|
||||
}
|
||||
|
||||
private void OnUndoStackIsEmptyChanged(object sender, EventArgs e)
|
||||
{
|
||||
PropertyChanged.Raise(this, "CanUndo");
|
||||
}
|
||||
|
||||
private void OnRedoStackIsEmptyChanged(object sender, EventArgs e)
|
||||
{
|
||||
PropertyChanged.Raise(this, "CanRedo");
|
||||
}
|
||||
|
||||
public void AddAction(UndoAction action)
|
||||
{
|
||||
if (!isEnabled)
|
||||
return;
|
||||
|
||||
if (state != UndoState.None)
|
||||
return;
|
||||
|
||||
undoStack.Push(action);
|
||||
redoStack.Clear();
|
||||
}
|
||||
|
||||
public void Undo()
|
||||
{
|
||||
var action = undoStack.Pop();
|
||||
redoStack.Push(action);
|
||||
|
||||
state = UndoState.Undoing;
|
||||
try
|
||||
{
|
||||
action.Undo();
|
||||
}
|
||||
finally
|
||||
{
|
||||
state = UndoState.None;
|
||||
}
|
||||
}
|
||||
|
||||
public void Redo()
|
||||
{
|
||||
var action = redoStack.Pop();
|
||||
undoStack.Push(action);
|
||||
|
||||
state = UndoState.Redoing;
|
||||
try
|
||||
{
|
||||
action.Do();
|
||||
}
|
||||
finally
|
||||
{
|
||||
state = UndoState.None;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanUndo
|
||||
{
|
||||
get { return !undoStack.IsEmpty; }
|
||||
}
|
||||
|
||||
public bool CanRedo
|
||||
{
|
||||
get { return !redoStack.IsEmpty; }
|
||||
}
|
||||
|
||||
private UndoState state = UndoState.None;
|
||||
public UndoState State
|
||||
{
|
||||
get { return state; }
|
||||
}
|
||||
|
||||
#region INotifyPropertyChanged Members
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly Dictionary<CaptureKeyHolder, object> captureHolders = new Dictionary<CaptureKeyHolder, object>();
|
||||
public void CaptureOldValue(DependencyObject target, DependencyProperty property, object oldValue)
|
||||
{
|
||||
captureHolders[new CaptureKeyHolder { Target = target, Property = property }] = oldValue;
|
||||
}
|
||||
|
||||
public void CaptureNewValue(DependencyObject target, DependencyProperty property, object newValue)
|
||||
{
|
||||
var holder = new CaptureKeyHolder { Target = target, Property = property };
|
||||
if (captureHolders.ContainsKey(holder))
|
||||
{
|
||||
object oldValue = captureHolders[holder];
|
||||
captureHolders.Remove(holder);
|
||||
|
||||
if (!Object.Equals(oldValue, newValue))
|
||||
{
|
||||
var action = new DependencyPropertyChangedUndoAction(target, property, oldValue, newValue);
|
||||
AddAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class CaptureKeyHolder
|
||||
{
|
||||
public DependencyObject Target { get; set; }
|
||||
public DependencyProperty Property { get; set; }
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Target.GetHashCode() ^ Property.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null) return false;
|
||||
|
||||
CaptureKeyHolder other = obj as CaptureKeyHolder;
|
||||
if (other == null) return false;
|
||||
|
||||
return Target == other.Target && Property == other.Property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum UndoState
|
||||
{
|
||||
None,
|
||||
Undoing,
|
||||
Redoing
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user