Отмена операций
Для того чтобы отменить или повторить команду, нужна операция Unexecute
в интерфейсе класса Command. Ее выполнение отменяет все, что было сделано пре-
дыдущей командой Execute. При этом используется информация, сохраненная
операцией Execute. Так, при команде FontCommand операция Execute была
бы должна сохранить координаты участка текста, шрифт которого изменялся,
а равно и первоначальный шрифт (или шрифты). Операция Unexecute класса
FontCommand должна была бы восстановить старый шрифт (или шрифты) для
этого участка текста.
Иногда определять, можно ли осуществить отмену, необходимо во время вы-
полнения. Скажем, запрос на изменение шрифта выделенного участка текста не
производит никаких действий, если текст уже отображен требуемым шрифтом.
Предположим, что пользователь выбрал некий текст и решил изменить его шрифт
на случайно выбранный. Что произойдет в результате последующего запроса на
отмену? Должно ли бессмысленное изменение приводить к столь же бессмыслен-
ной отмене? Наверное, нет. Если пользователь повторит случайное изменение
шрифта несколько раз, то не следует заставлять его выполнять точно такое же
число отмен, чтобы вернуться к последнему осмысленному состоянию. Если сум-
марный эффект выполнения последовательности команд нулевой, то нет необхо-
димости вообще делать что-либо при запросе на отмену.
Для определения того, можно ли отменить действие команды, мы добавим
к интерфейсу класса Command абстрактную операцию Reversible (обратимая),
которая возвращает булево значение. Подклассы могут переопределить эту опе-
рацию и возвращать true или f a l s e в зависимости от критерия, вычисляемого
во время выполнения.
Операции пользователя
История команд
Последний шаг в направлении поддержки отмены и повтора с произвольным
числом уровней - определение
истории команд,
то есть списка ранее выполнен-
ных или отмененных команд. Концептуально история команд выглядит так:
•^ Прошлые команды
Настоящее
Каждый кружок представляет один объект Command. В данном случае пользо-
ватель выполнил четыре команды. Линия с пометкой «настоящее» показывает са-
мую последнюю выполненную (или отмененную) команду.
Для того чтобы отменить последнюю команду, мы просто вызываем операцию
Unexecute для самой последней команды:
Настоящее
После отмены команды сдвигаем линию «настоящее» на одну команду влево.
Если пользователь выполнит еще одну отмену, то произойдет откат на один шаг
(см. рис. ниже).
Настоящее
Видно, что за счет простого повторения процедуры мы получаем произволь-
ное число уровней отмены, ограниченное лишь длиной списка истории команд.
Чтобы повторить только что отмененную команду, произведем обратные дей-
ствия. Команды справа от линии «настоящее» - те, что могут быть повторены
в будущем. Для повтора последней отмененной команды мы вызываем операцию
Execute для последней команды справа от линии «настоящее»:
Execute()
Настоящее
Затем мы сдвигаем линию «настоящее» так, чтобы следующий повтор вызвал
операцию Execute для следующей команды «в области будущего».
Do'stlaringiz bilan baham: |