Отменить / Повторить реализацию

62
задан Koekiebox 14 November 2010 в 18:37
поделиться

3 ответа

Я знаю два основных подразделения типов отмены

  • SAVE STATE: Одна из категорий отмены - это когда вы фактически сохраняете состояния истории. В этом случае происходит то, что на каждом этапе вы сохраняете состояние в каком-то месте памяти. Когда вы хотите выполнить отмену, вы просто меняете текущее состояние и меняете состояние, которое уже было в памяти. Вот как это делается, например, с историей в Adobe Photoshop или повторным открытием закрытых вкладок в Google Chrome.

alt text

  • ОБЩЕЕ СОСТОЯНИЕ: Другая категория - это когда вместо сохранения самих состояний вы просто запоминаете, какие были действия. когда вам нужно отменить, вам нужно сделать логическое обратное этому конкретному действию. В качестве простого примера, когда вы выполняете Ctrl + B в текстовом редакторе, который поддерживает отмену, оно запоминается как действие жирным шрифтом . Теперь с каждым действием отображается отображение его логических противоположностей. Итак, когда вы выполняете Ctrl + Z , он просматривает таблицу обратных действий и обнаруживает, что действие отмены - это Ctrl + B снова. Это выполняется, и вы получаете свое предыдущее состояние. Итак, здесь ваше предыдущее состояние не было сохранено в памяти, а сгенерировано, когда вам это нужно.

Для текстовых редакторов создание состояния таким способом не требует слишком больших вычислительных ресурсов, но для таких программ, как Adobe Photoshop, это может быть слишком ресурсоемким или просто невозможным.Например, для действия Blur вы укажете действие de-Blur , но оно никогда не вернет вас в исходное состояние, поскольку данные уже потеряны. Итак, в зависимости от ситуации - возможности логического обратного действия и его осуществимости, вам нужно выбрать между этими двумя широкими категориями, а затем реализовать их так, как вы хотите. Конечно, можно создать гибридную стратегию, которая будет работать на вас.

Кроме того, иногда, как в Gmail, возможна отмена с ограничением по времени, потому что действие (отправка письма) никогда не выполняется. Таким образом, вы здесь не «отменяете», вы просто «не выполняете» само действие.

75
ответ дан 24 November 2019 в 16:20
поделиться

Есть несколько способов сделать это, но вы можете начать смотреть на Командный шаблон . Используйте список команд для перемещения назад (Отменить) или вперед (повторить) по своим действиям. Пример на C # можно найти здесь .

13
ответ дан 24 November 2019 в 16:20
поделиться

Я написал два текстовых редактора с нуля, и оба они используют очень примитивную форму функции отмены / повтора. Под «примитивом» я подразумеваю, что эту функциональность было очень легко реализовать, но это неэкономично для очень больших файлов (скажем, >> 10 МБ). Однако система очень гибкая; например, он поддерживает неограниченное количество уровней отмены.

По сути, я определяю структуру вроде

type
  TUndoDataItem = record
    text: /array of/ string;
    selBegin: integer;
    selEnd: integer;
    scrollPos: TPoint;
  end;

, а затем определяю массив

var
  UndoData: array of TUndoDataItem;

Затем каждый член этого массива определяет сохраненное состояние текста. Теперь, при каждом редактировании текста (клавиша символа вниз, возврат вниз, клавиша удаления вниз, вырезание / вставка, выделение, перемещаемое мышью и т. Д.), Я (повторно) запускаю таймер (скажем) на одну секунду. При запуске таймер сохраняет текущее состояние как новый член массива UndoData .

При отмене (Ctrl + Z) я возвращаю редактор в состояние UndoData [UndoLevel - 1] и уменьшаю UndoLevel на единицу.По умолчанию UndoLevel равен индексу последнего члена массива UndoData . При повторном выполнении (Ctrl + Y или Shift + Ctrl + Z) я восстанавливаю редактор до состояния UndoData [UndoLevel + 1] и увеличиваю UndoLevel на единицу. Конечно, если таймер редактирования срабатывает, когда UndoLevel не равна длине (минус один) массива UndoData , я очищаю все элементы этого массива после UndoLevel , что является обычным для платформы Microsoft Windows (но Emacs лучше, если я правильно помню - недостатком подхода Microsoft Windows является то, что если вы отмените много изменений, а затем случайно отредактируете буфер, предыдущий контент (который был отменен) безвозвратно утерян). Вы можете пропустить это сокращение массива.

В программе другого типа, например, в редакторе изображений, можно применить тот же метод, но, конечно, с совершенно другой структурой UndoDataItem . Более продвинутый подход, который не требует столько памяти, заключается в сохранении только изменений между уровнями отмены (то есть вместо сохранения «alpha \ nbeta \ gamma» и «alpha \ nbeta \ ngamma» \ ndelta ", вы можете сохранить" alpha \ nbeta \ ngamma "и" ADD \ ndelta ", если вы понимаете, что я имею в виду). В очень больших файлах, где каждое изменение мало по сравнению с размером файла, это значительно уменьшит использование памяти данными отмены, но это сложнее реализовать и, возможно, более подвержено ошибкам.

15
ответ дан 24 November 2019 в 16:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: