Реализация undo/redo с помощью состояния
Начнем с базовой идеи: чтобы создать возможность отмены и повтора действий, нам нужно хранить предыдущие состояния. Когда пользователь выполняет действие, текущее состояние сохраняется. Если нужно отменить действие, мы возвращаемся к предыдущему состоянию. А при повторе — снова продвигаемся вперед, используя более новое сохраненное состояние.
Вариант 1: Хранение состояния в стекеОдин из наиболее простых методов реализации undo/redo — это использование стека. Представьте, что каждое состояние вашего приложения помещается в «стопку», как книги, которые вы кладете друг на друга. Важно сохранять как текущую версию состояния, так и предыдущие версии. При откате или повторе действий нужно только «перекладывать» эти состояния, как вы снимаете или добавляете книгу на вершину стопки.
Как это работает? Допустим, у вас есть два стека: один для undo, а другой для redo. При изменении состояния вы добавляете текущее состояние в стек undo и очищаете стек redo. Когда нужно отменить действие, вы перемещаете текущее состояние в стек redo, а затем берете предыдущее состояние из undo.
Пример: Если у вас есть приложение для рисования, каждый новый штрих или изменение цвета добавляется в стек undo. Когда пользователь нажимает «Отменить», последнее действие извлекается из undo и перемещается в стек redo. Если пользователь хочет повторить действие, вы просто возвращаете его обратно из redo.
Управление состоянием через «историю»
Вариант 2: Промежуточное сохранение состоянийЕсли требуется не просто откатить последнее действие, а позволить пользователю вернуться на любой шаг, вам потребуется хранить историю состояний. Это делается с помощью списка, где каждое состояние — это отдельный «снимок» интерфейса в определенный момент времени. Когда пользователь выполняет действие, текущее состояние добавляется в историю. Undo приводит к «путешествию» назад по истории, а redo — вперед.
Чтобы эффективно управлять историей, важно определиться, какие состояния требуют сохранения. Если каждое действие будет сохранять состояние, история может быстро стать слишком большой. Промежуточное сохранение позволяет хранить состояние не для каждого действия, а для ключевых изменений.
Пример: В текстовом редакторе после каждых 20 изменений можно сохранять состояние. Это позволяет контролировать размер истории, сохраняя лишь важные шаги. Пользователь видит только основные версии документа, которые он может откатить или повторить.
Реализация с использованием переменной состояния
Вариант 3: Структура данных для состоянияКогда мы используем переменную состояния для undo/redo, необходимо выбрать способ хранения состояний. Существует несколько вариантов, и выбор зависит от типа приложения. Одним из подходов является использование «двойного списка» или массива, где текущее состояние располагается в середине, а undo/redo происходят за счет перехода по массиву.
Пример: В приложении для редактирования фотографий каждое новое состояние добавляется в массив. Текущее состояние определяется индексом, и при undo/redo перемещается только индекс.






Комментарии