/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Model/Editing/UndoStack.cs
106 строк
3 KB
docNemo
Фундамент продукта: параметрическое построение выкроек, печать, установщик
08 авг 2026, 22:17
08 авг 2026, 22:17
cd47cce
Код
Авторство
О чём код?
using System; using System.Collections.Generic; namespace ClothesGraph.Model.Editing; /// <summary> /// Обратимое действие над моделью. /// </summary> public interface IUndoableAction { /// <summary>Название для показа в меню отмены.</summary> string Name { get; } void Apply(); void Revert(); } /// <summary> /// Журнал отмены и повтора. /// </summary> /// <remarks> /// Хранятся действия, а не снимки всего документа: чертёж со всеми /// построениями и деталями слишком велик, чтобы копировать его на каждую /// правку, а правки почти всегда затрагивают одно построение. /// </remarks> public sealed class UndoStack { private readonly Stack<IUndoableAction> _undo = new(); private readonly Stack<IUndoableAction> _redo = new(); private bool _suspended; public bool CanUndo => _undo.Count > 0; public bool CanRedo => _redo.Count > 0; public string? NextUndoName => CanUndo ? _undo.Peek().Name : null; public string? NextRedoName => CanRedo ? _redo.Peek().Name : null; public event EventHandler? Changed; /// <summary>Выполняет действие и помещает его в журнал.</summary> public void Do(IUndoableAction action) { action.Apply(); if (_suspended) return; _undo.Push(action); // Новое действие обрывает ветку повтора: вернуться к отменённому // состоянию после иной правки уже нельзя. _redo.Clear(); Changed?.Invoke(this, EventArgs.Empty); } public void Undo() { if (!CanUndo) return; var action = _undo.Pop(); _suspended = true; try { action.Revert(); } finally { _suspended = false; } _redo.Push(action); Changed?.Invoke(this, EventArgs.Empty); } public void Redo() { if (!CanRedo) return; var action = _redo.Pop(); _suspended = true; try { action.Apply(); } finally { _suspended = false; } _undo.Push(action); Changed?.Invoke(this, EventArgs.Empty); } public void Clear() { _undo.Clear(); _redo.Clear(); Changed?.Invoke(this, EventArgs.Empty); } }