Подтвердить что ты не робот

Как разработать отмену и повтор в текстовом редакторе?

Часть моего проекта - это текстовый редактор, который используется для типа некоторого правила, и мое приложение компилируется и запускает его. Написание компилятора было завершение и выпуск бета-версии. В финальной версии мы должны добавить отмену и повтор в текстовом редакторе. Я использую файл и периодически его сохраняю для текстового редактора. Как отменить и повторить мой текстовый редактор? Что такое изменение структуры стойкого файла?

4b9b3361

Ответ 1

Вы можете моделировать свои действия как команды, которые вы держите в двух стеках. Один для отмены, другой для повтора. Вы можете составить ваши команды для создания более высокоуровневых команд, например, когда вы хотите отменить действия макроса, например; или если вы хотите группировать отдельные нажатия одного слова или фразы в одном действии.

Каждое действие в вашем редакторе (или повторное действие) генерирует новую команду отмены, которая входит в стек отмены (а также удаляет стек повтора). Каждое действие отмены отменяет соответствующую команду повтора, которая переходит в стек повтора.

Вы также можете, как упоминалось в комментариях derekerdmann, объединить команды отмены и повтора в один тип команды, который знает, как отменить и повторить его действия.

Ответ 2

В принципе есть два хороших способа:

  • шаблон дизайна "Команда"

  • используя только OO над неизменяемыми объектами, где все просто неизменные объекты, сделанные из неизменяемых объектов, сделанные из неизменяемых объектов (это менее распространено, но удивительно элегантно, когда все сделано правильно).

Преимущество использования OO над неизменяемыми объектами над наивной командой или наивным отменой/повторением заключается в том, что вам не нужно много об этом думать: не нужно "отменять" действие и не нужно "повторить" все команды. Все, что вам нужно, это указатель на огромный список неизменяемых объектов.

Поскольку объекты неизменяемы, все "состояния" могут быть невероятно легкими, потому что вы можете кэшировать/повторно использовать большинство объектов в любом состоянии.

"OO над неизменными объектами" - это чистый драгоценный камень. Вероятно, он не станет мейнстримом еще до 10 лет. )

P.S: выполнение OO над неизменяемыми объектами также удивительно упрощает параллельное программирование.

Ответ 3

Если вы не хотите ничего фантастического, вы можете просто добавить UndoManager. Ваш Document будет запускать UndoableEdit при каждом добавлении или удалении текста. Чтобы отменить и повторить каждое изменение, просто вызовите эти методы в UndoManager.

Недостатком этого является UndoManager, который добавляет новое редактирование каждый раз, когда пользователь вводит что-то, поэтому набрав "яблоко" , вы оставите 5 изменений, отмененных по одному. Для моего текстового редактора я написал оболочку для исправлений, в которой хранится время, которое было сделано в дополнение к изменению и смещению текста, а также UndoableEditListener, который объединяет новые изменения предыдущих, если есть только короткий промежуток времени между они (0,5 секунды хорошо работают для меня).

Это хорошо работает для общего редактирования, но вызывает проблемы при выполнении массивной замены. Если у вас был документ с 5000 экземплярами "яблока", и вы хотели заменить его "оранжевым", вы в конечном итоге получили бы 5000 исправлений, сохраняя "яблоко" , "оранжевое" и смещение. Чтобы уменьшить объем используемой памяти, я рассматривал это как отдельный случай для обычных изменений и вместо этого хранили "яблоко" , "оранжевый" и массив из 5000 смещений. Я еще не успел применить это, но я знаю, что это вызовет некоторые головные боли, когда несколько строк соответствуют условию поиска (например, регистр без учета регистра, поиск по регулярному выражению).

Ответ 4

Ничего себе, какая коничность - я буквально за последний час внедрил undo/redo в текстовом редакторе WYSIWYG:

Основная идея состоит в том, чтобы либо сохранить все содержимое текстового редактора в массиве, либо разницу между последним редактированием.

Обновите этот массив в значительных точках, т.е. каждый несколько символов (проверьте длину содержимого каждого нажатия клавиши, если его более 20 символов отличаются, а затем создайте точку сохранения). Также при изменении стиля (если используется расширенный текст), добавление изображений (если это разрешено), вставка текста и т.д. Вам также нужен указатель (просто переменная int), чтобы указать, какой элемент в массиве является текущим состоянием редактор)

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

Когда пользователь нажимает кнопку отмены, проверьте, совпадают ли текущие содержимое редактора с последним сохранением (если это не так, тогда пользователь внес изменения с момента последнего сохранения, поэтому сохраните текущий содержимое редактора (поэтому его можно переделать), сделать редактор равным последней точке сохранения и сделать указатель переменной = 1 (2-й элемент в массиве). Если они одинаковы, то никаких изменений не было сделано начиная с последней точки сохранения, поэтому вам нужно отменить до этой точки. Чтобы сделать это, увеличьте значение указателя + 1 и сделайте содержимое редактора = значение указателя.

Для повторного просто уменьшите значение указателя на 1 и загрузите содержимое массива (убедитесь, что вы достигли конца массива).

Если пользователь вносит изменения после отмены, то перемещайте ячейку массива с указанным значением до ячейки 0 и перемещайте оставшуюся часть на ту же сумму (вы не хотите переделывать другие вещи, когда они делали разные изменения).

Еще одна важная точка catch - убедитесь, что вы добавили только точку сохранения, если содержимое текстового редактора фактически изменилось (в противном случае вы получите дубликаты точек сохранения, и это будет похоже на отмену, что ничего не делает для пользователя.

Я не могу помочь вам с спецификой java, но я рад ответить на любые другие ваши вопросы,

Нико

Ответ 5

Вы можете сделать это двумя способами:

  • сохранить список состояний редактора и указатель в списке; undo перемещает указатель назад и восстанавливает состояние там, повтор движется вперед вместо этого, делая что-то, отбрасывает все, кроме указателя, и вставляет состояние в качестве нового верхнего элемента;
  • не сохранять состояния, а действия, которые требуют, чтобы для каждого действия у вас было противодействие, чтобы отменить действие этого действия.

В моем (диаграммном) редакторе есть четыре уровня изменений состояния:

  • фрагменты действия: они являются частью более крупного действия, а не раздельно отменяются или изменяются (например, перемещение мыши).
  • действия: один или несколько фрагментов действия, которые образуют значимые изменения, которые можно отменить или переделать, но которые не отражаются в отредактированном документе, измененном на диске (например, выбор элементов).
  • изменения документа: одно или несколько действий, которые изменяют отредактированный документ, поскольку он будет сохранен на диск (например, изменение, добавление или удаление элементов).
  • сохраняется: текущее состояние документа явно сохраняется на диске - в этот момент мой редактор отбрасывает историю отмены, поэтому вы не можете отменить сохранение

Ответ 8

Вот фрагмент, который показывает, как SWT поддерживает операции Undo/Redo. Возьмите его как практический пример (или используйте его напрямую, если ваш редактор основан на SWT):

SWT Undo Redo