using Hydro.Inp;
|
using System;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using System.Windows.Forms;
|
|
namespace Hydro.MapView.Common
|
{
|
public class UndoRedoCommand<T>
|
{
|
private readonly Action<T> _undoAction;
|
private readonly Action<T> _redoAction;
|
private readonly T _oldValue;
|
private readonly T _newValue;
|
|
public UndoRedoCommand(T oldValue, T newValue, Action<T> undoAction, Action<T> redoAction)
|
{
|
_oldValue = oldValue;
|
_newValue = newValue;
|
_undoAction = undoAction;
|
_redoAction = redoAction;
|
}
|
|
public void Undo()
|
{
|
_undoAction?.Invoke(_oldValue);
|
}
|
|
public void Redo()
|
{
|
_redoAction?.Invoke(_newValue);
|
}
|
}
|
|
public static class MapObjectExtensions
|
{
|
private static readonly Stack<UndoRedoCommand<object>> _undoStack = new Stack<UndoRedoCommand<object>>();
|
private static readonly Stack<UndoRedoCommand<object>> _redoStack = new Stack<UndoRedoCommand<object>>();
|
|
public static void AddUndoRedoSupport(this List<IBaseViewModel> list, PropertyGrid propertyGrid)
|
{
|
propertyGrid.PropertyValueChanged += (sender, e) =>
|
{
|
if (propertyGrid.SelectedObject is IBaseViewModel obj && obj != null)
|
{
|
var propertyDescriptor = TypeDescriptor.GetProperties(obj)[e.ChangedItem.PropertyDescriptor.Name];
|
var oldValue = e.OldValue;//propertyDescriptor.GetValue(obj);
|
var newValue = e.ChangedItem.Value;
|
|
var undoAction = new Action<object>(v => propertyDescriptor.SetValue(obj, v));
|
var redoAction = new Action<object>(v => propertyDescriptor.SetValue(obj, v));
|
|
|
var command = new UndoRedoCommand<object>(oldValue, newValue, undoAction, redoAction);
|
|
_undoStack.Push(command);
|
_redoStack.Clear();
|
}
|
};
|
}
|
public static void AddCommand(UndoRedoCommand<object> command)
|
{
|
_undoStack.Push(command);
|
_redoStack.Clear();
|
}
|
private static List<IBaseViewModel> getObj(object o)
|
{
|
var list = o as List<IBaseViewModel>;
|
if (list == null)
|
{
|
if (o is List<NodeViewModel> list_nodes) list = new List<IBaseViewModel>(list_nodes);
|
if (o is List<LinkViewModel> list_links) list = new List<IBaseViewModel>(list_links);
|
}
|
return list;
|
}
|
public static void AddCommand(object o, string PropertyDescriptorName, dynamic oldValue, dynamic newValue)
|
{
|
switch (PropertyDescriptorName)
|
{
|
case "Add":
|
{
|
|
var net = o as MapViewNetWork;
|
var undoAction = new Action<object>(v => net.Remove(newValue));
|
var redoAction = new Action<object>(v => net.Add(newValue));
|
//object oldValue=propertyDescriptor.GetValue(obj);
|
var command = new UndoRedoCommand<object>(oldValue, newValue, undoAction, redoAction);
|
AddCommand(command);
|
}
|
return;
|
case "Remove":
|
{
|
var net = o as MapViewNetWork;
|
var undoAction = new Action<object>(v => net.Add(newValue));
|
var redoAction = new Action<object>(v => net.Remove(newValue));
|
//object oldValue=propertyDescriptor.GetValue(obj);
|
var command = new UndoRedoCommand<object>(oldValue, newValue, undoAction, redoAction);
|
AddCommand(command);
|
}
|
return;
|
case "Map":
|
{
|
var mv = o as MapDimensions;
|
var undoAction = new Action<object>(v =>
|
{
|
mv.Center = oldValue.Center;
|
mv.zoom = oldValue.zoom;
|
mv.rotation = oldValue.rotation;
|
mv.rotationF = oldValue.rotationF;
|
|
});
|
var redoAction = new Action<object>(v =>
|
{
|
mv.Center = newValue.Center;
|
mv.zoom = newValue.zoom;
|
mv.rotation = newValue.rotation;
|
mv.rotationF = newValue.rotationF;
|
|
});
|
//object oldValue=propertyDescriptor.GetValue(obj);
|
var command = new UndoRedoCommand<object>(oldValue, newValue, undoAction, redoAction);
|
AddCommand(command);
|
}
|
return;
|
}
|
|
|
if (o is IBaseViewModel obj && obj != null)
|
{
|
var propertyDescriptor = TypeDescriptor.GetProperties(obj)[PropertyDescriptorName];
|
if (propertyDescriptor == null) return;
|
var undoAction = new Action<object>(v => propertyDescriptor.SetValue(obj, v));
|
var redoAction = new Action<object>(v => propertyDescriptor.SetValue(obj, v));
|
var command = new UndoRedoCommand<object>(oldValue, newValue, undoAction, redoAction);
|
AddCommand(command);
|
}
|
else if (o is List<IBaseViewModel> || o is List<NodeViewModel>)
|
{
|
var list = getObj(o);
|
//List<Action<object>> list_undoAction = new List<Action<object>>();
|
//List<Action<object>> list_redoAction = new List<Action<object>>();
|
List<UndoRedoCommand<object>> list_command = new List<UndoRedoCommand<object>>();
|
PropertyDescriptor propertyDescriptor = null;
|
//List<object> oldValues = oldValue as List<object>;
|
//List<object> newValues = newValue as List<object>;
|
for (int i = 0; i < list.Count; i++)
|
{
|
var item = list[i];
|
if (propertyDescriptor == null) propertyDescriptor = TypeDescriptor.GetProperties(item)[PropertyDescriptorName];
|
if (propertyDescriptor == null) continue;
|
IBaseViewModel obj0 = (IBaseViewModel)item;
|
var undoAction0 = new Action<object>(v => propertyDescriptor.SetValue(obj0, v));
|
var redoAction0 = new Action<object>(v => propertyDescriptor.SetValue(obj0, v));
|
//object oldValue = propertyDescriptor.GetValue(obj0);
|
|
var command0 = new UndoRedoCommand<object>(oldValue[i], newValue[i], undoAction0, redoAction0);
|
list_command.Add(command0);
|
//list_undoAction.Add(undoAction0);
|
//list_redoAction.Add(redoAction0);
|
|
|
}
|
|
var undoAction = new Action<object>(v =>
|
{
|
for (int i = 0; i < list_command.Count; i++)
|
{
|
list_command[i].Undo();
|
}
|
});
|
|
var redoAction = new Action<object>(v =>
|
{
|
for (int i = 0; i < list_command.Count; i++)
|
{
|
list_command[i].Redo();
|
}
|
});
|
var command = new UndoRedoCommand<object>(null, null, undoAction, redoAction);
|
AddCommand(command);
|
|
}
|
|
}
|
|
public static void Undo()
|
{
|
if (_undoStack.Count > 0)
|
{
|
var command = _undoStack.Pop();
|
command.Undo();
|
_redoStack.Push(command);
|
}
|
|
}
|
|
public static void Redo()
|
{
|
if (_redoStack.Count > 0)
|
{
|
var command = _redoStack.Pop();
|
command.Redo();
|
_undoStack.Push(command);
|
}
|
|
}
|
}
|
}
|