Глава 18 · История и документ
Повтор действий (Redo)
Redo — второй стек рядом с Undo. Новое действие после отмены должно его опустошить.
Redo — второй стек, а не «отмена отмены»
Раздел 18.24 отменяет действие, снимая его с undo_stack. Чтобы
вернуть его назад, само действие нужно куда-то временно положить — во второй стек,
redo_stack:
redo.py
def redo(self):
if not self.redo_stack:
return
shapes = self.redo_stack.pop()
self.document.extend(shapes)
self.undo_stack.append(shapes)
self.render_document()
Новое действие обязано опустошить redo_stack
Если после Undo пользователь рисует что-то НОВОЕ, старая ветка «которую можно было бы
повторить» перестаёт иметь смысл — вернуть её означало бы применить действие к документу,
который уже стал другим. Поэтому _commit_action() (раздел 18.24)
всегда очищает redo_stack:
commit_ochischaet_redo.py
def _commit_action(self, shapes):
self.document.extend(shapes)
self.undo_stack.append(shapes)
self.redo_stack.clear() # новое действие делает старую ветку redo недействительной
self.render_document()
Забытый redo_stack.clear() — незаметная, но реальная ошибка
Без этой строки Redo мог бы «воскресить» фигуру, которая никак не связана с текущим состоянием документа — потому что после Undo пользователь успел нарисовать что-то ещё, а старое отменённое действие всё ещё лежит в очереди «повторить». Раздел 18.31 разбирает этот случай как отдельный Debug Lab.
Практика: стек повтора и его очистка новым действием
Автоматическая проверка — redo восстанавливает действие, новое действие обнуляет redo