Как должен вести себя «Отменить ввод»?

12

Я реализую приложение Java, которое включает в себя стек Undo / Redo. Я заметил, что некоторые приложения (такие как TextEdit в Mac OS X) позволяют вам выбрать «Отменить ввод» в меню «Правка» после ввода текста. Я бы тоже хотел внедрить подобные вещи в свое приложение, но мне очень трудно найти рекомендации по его поведению.

С некоторой пробой и ошибкой я лучше всего расскажу о том, как ведет себя Undo Typing в TextEdit:

  • Когда пользователь вводит новый символ (или вводит ключ удаления), объедините его с предыдущим элементом отмены ввода, если он находится в верхней части стека отмены, если только не произойдет одна из следующих ситуаций
  • Всегда создавайте новый элемент отмены набора текста после того, как пользователь продолжит печатать после не менее 15 секунд бездействия
  • Всегда создавайте новый элемент отмены набора текста после того, как пользователь печатает в течение продолжительного периода времени и когда выполняется какое-то условие (не удалось выяснить, было ли это основано на времени или на основе количества символов).
  • Всегда создавайте новый элемент «Отменить набор текста», когда любой текст выделен, а затем удален или перезаписан (выбор текста, без внесения изменений, затем возврат к исходной точке вставки и продолжение ввода не вызывает этого)

На практике стратегия Apple, кажется, работает (по крайней мере, она работает для меня, когда я печатаю), но, как было отмечено в последнем пункте, я действительно не смог выяснить правила. Кроме того, похоже, что другие программы следуют другим правилам, таким как Microsoft Word. Google не нашел определенного списка правил для какой-либо реализации Undo Typing, и я не сталкивался с рекомендациями относительно того, как он должен себя вести. Так как это должно вести себя? Или дело только в прихотях программиста?

РЕДАКТИРОВАТЬ: Просто чтобы уточнить, я не заинтересован в деталях реализации прямо сейчас. Мне особенно любопытно, существует ли авторитетная ссылка (например, лучшие практики или документ интерфейса пользователя), описывающая это или описание того, как это реализовано в нескольких продуктах.

Thunderforge
источник
Мое предложение: сжать изменения до такой степени, чтобы по-прежнему можно было восстановить точную последовательность нажатых клавиш из информации отмены, и не более. Например, это означает, что если пользователь что-то печатает и сразу использует backspace для его удаления, между ними должна быть точка отмены.
Амброз Бизжак
Возможно, вы также можете добавить новый «Отменить ввод текста» каждый раз, когда пользователь создает новую строку, и, возможно, каждый раз, когда пробел используется сразу после ввода символов. IMO 15 секунд ожидания до того, как новый "Undo Typing item" может быть немного длинным, но это только я. (Я бы пошел около 5 секунд)
user82529
Или, может быть, «точная последовательность нажатых клавиш» должна быть смягчена до «состояния текста после каждой модификации». Идея состоит в том, чтобы предотвратить потерю любого текста из-за сжатия.
Амброз Бизжак
Мне кажется, что TextEdit объединяет пробелы и удаляет их с последним элементом отмены набора текста при условии, что другие условия не выполняются. Итак 124<delete>3, отмена и повторное выполнение этого приводит к 123. Я предполагаю, что преимущество этого в том, что оно приводит к конечному состоянию текста пользователя, что-то вроде вышеупомянутого предложения.
Thunderforge
Вы уже пытались искать патенты? (Правила обычно кодируются на уровне библиотеки, а не подвергаются пользовательскому коду.)
Donal Fellows

Ответы:

5

Если вы ищете авторитетный источник, я думаю, что лучший материал для Mac будет найден в документе Undo Architecture от Apple.

Я не думаю, что вы найдете список правил о том, когда вы должны или не должны объединять события отмены, хотя. То, что кажется правильным для одного приложения, не обязательно будет иметь смысл для другого. Например, объединение нажатий клавиш имеет смысл в текстовом редакторе, потому что пользователь, вероятно, увидит ввод абзаца как одно действие, а не как 539 отдельных действий, а также потому, что вы не хотите, чтобы пользователь отменил 539 раз просто для того, чтобы получить до того момента, когда они набрали этот параграф. Но как быть с операциями перемещения фигуры в программе рисования? Или последовательные корректировки цвета заливки? Вы можете сделать хороший аргумент в пользу их объединения или нет, в зависимости от характера вашей программы.

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

Он основан на автосохранении. К счастью для вас, исходный код TextEdit доступен и хорошо прокомментирован. Я думаю, что если вы посмотрите на это, вы получите лучшее представление о том, что происходит и почему. Например:

- (void)saveToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation completionHandler:(void (^)(NSError *error))handler {
    // Note that we do the breakUndoCoalescing call even during autosave, which 
    // means the user's undo of long typing will take them back to the last spot an 
    // autosave occured. This might seem confusing, and a more elaborate solution may 
    // be possible (cause an autosave without having to breakUndoCoalescing), but since 
    // this change is coming late in Leopard, we decided to go with the lower risk fix.
    [[self windowControllers] makeObjectsPerformSelector:@selector(breakUndoCoalescing)];
 ...

Я знаю, что вы сказали, что вас пока не интересуют подробности реализации, но, глядя на то, как Apple реализовала TextEdit, может сообщать о решениях, которые вы принимаете для своего собственного приложения.

Калеб
источник
1
Я думаю, что я объявлю это лучшим ответом. Я благодарен вам за то, что вы дали ссылку на реализацию Apple, а также немного кода для конкретного примера, который я привел. Я думаю, что вы правы, хотя, как правило, это основано на потребностях приложения, и никто действительно не пытался стандартизировать, что это за потребности и как их удовлетворить.
Thunderforge
1

при нажатой клавише -> таймер, представляющий старты в режиме ожидания

при включении / выключении таймера -> сброс таймера

при нажатии клавиши / без таймера -> перенастроить блоки ячеек, чтобы подготовиться к новому сохраненному состоянию при изменении положения

таймер простоя отключается -> установить новое состояние отмены

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

Эрик Реппен
источник