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 { private readonly Action _undoAction; private readonly Action _redoAction; private readonly T _oldValue; private readonly T _newValue; public UndoRedoCommand(T oldValue, T newValue, Action undoAction, Action 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> _undoStack = new Stack>(); private static readonly Stack> _redoStack = new Stack>(); public static void AddUndoRedoSupport(this List 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(v => propertyDescriptor.SetValue(obj, v)); var redoAction = new Action(v => propertyDescriptor.SetValue(obj, v)); var command = new UndoRedoCommand(oldValue, newValue, undoAction, redoAction); _undoStack.Push(command); _redoStack.Clear(); } }; } public static void AddCommand(UndoRedoCommand command) { _undoStack.Push(command); _redoStack.Clear(); } private static List getObj(object o) { var list = o as List; if (list == null) { if (o is List list_nodes) list = new List(list_nodes); if (o is List list_links) list = new List(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(v => net.Remove(newValue)); var redoAction = new Action(v => net.Add(newValue)); //object oldValue=propertyDescriptor.GetValue(obj); var command = new UndoRedoCommand(oldValue, newValue, undoAction, redoAction); AddCommand(command); } return; case "Remove": { var net = o as MapViewNetWork; var undoAction = new Action(v => net.Add(newValue)); var redoAction = new Action(v => net.Remove(newValue)); //object oldValue=propertyDescriptor.GetValue(obj); var command = new UndoRedoCommand(oldValue, newValue, undoAction, redoAction); AddCommand(command); } return; case "Map": { var mv = o as MapDimensions; var undoAction = new Action(v => { mv.Center = oldValue.Center; mv.zoom = oldValue.zoom; mv.rotation = oldValue.rotation; mv.rotationF = oldValue.rotationF; }); var redoAction = new Action(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(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(v => propertyDescriptor.SetValue(obj, v)); var redoAction = new Action(v => propertyDescriptor.SetValue(obj, v)); var command = new UndoRedoCommand(oldValue, newValue, undoAction, redoAction); AddCommand(command); } else if (o is List || o is List) { var list = getObj(o); //List> list_undoAction = new List>(); //List> list_redoAction = new List>(); List> list_command = new List>(); PropertyDescriptor propertyDescriptor = null; //List oldValues = oldValue as List; //List newValues = newValue as List; 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(v => propertyDescriptor.SetValue(obj0, v)); var redoAction0 = new Action(v => propertyDescriptor.SetValue(obj0, v)); //object oldValue = propertyDescriptor.GetValue(obj0); var command0 = new UndoRedoCommand(oldValue[i], newValue[i], undoAction0, redoAction0); list_command.Add(command0); //list_undoAction.Add(undoAction0); //list_redoAction.Add(redoAction0); } var undoAction = new Action(v => { for (int i = 0; i < list_command.Count; i++) { list_command[i].Undo(); } }); var redoAction = new Action(v => { for (int i = 0; i < list_command.Count; i++) { list_command[i].Redo(); } }); var command = new UndoRedoCommand(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); } } } }