|
- #pragma once
-
- #include <cstddef>
- #include <optional>
- #include <utility>
- #include <vector>
-
- /**
- * @brief 保存有限数量的编辑前快照并提供撤销、重做
- *
- * State 由具体编辑服务决定,可以是 HMI 页面集合或控制逻辑集合
- * 历史只存在当前编辑会话内,不写入工程文件
- * 新编辑会清空重做栈,超过容量时丢弃最早记录
- */
- template <typename State>
- class EditorHistory final
- {
- public:
- // 单个编辑服务最多保留 30 条撤销和重做历史
- static constexpr std::size_t kMaximumEntries = 30U;
-
- template <typename Equal>
- /**
- * @brief 记录一次编辑前状态
- * @param before 编辑前状态
- * @param after 编辑完成后的当前状态
- * @param equal 比较前后状态是否相同的可调用对象
- *
- * 状态没有变化时不创建空历史
- * 新编辑成功记录后清空重做栈
- */
- void record(State before, const State &after, Equal equal)
- {
- if (equal(before, after))
- {
- return;
- }
- undo_states_.push_back(std::move(before));
- trim(&undo_states_);
- redo_states_.clear();
- }
-
- /**
- * @brief 撤销最近一次编辑
- * @param current 当前状态
- * @return 撤销后的目标状态;没有可撤销历史时返回空值
- *
- * 当前状态会先进入重做栈,之后取出撤销栈顶的编辑前快照
- */
- std::optional<State> undo(State current)
- {
- if (undo_states_.empty())
- {
- return std::nullopt;
- }
- redo_states_.push_back(std::move(current));
- trim(&redo_states_);
- State target = std::move(undo_states_.back());
- undo_states_.pop_back();
- return target;
- }
-
- /**
- * @brief 重做最近一次被撤销的编辑
- * @param current 当前状态
- * @return 重做后的目标状态;没有可重做历史时返回空值
- *
- * 当前状态会先放回撤销栈,之后取出重做栈顶的目标状态
- */
- std::optional<State> redo(State current)
- {
- if (redo_states_.empty())
- {
- return std::nullopt;
- }
- undo_states_.push_back(std::move(current));
- trim(&undo_states_);
- State target = std::move(redo_states_.back());
- redo_states_.pop_back();
- return target;
- }
-
- /**
- * @brief 清空撤销栈和重做栈
- */
- void clear()
- {
- undo_states_.clear();
- redo_states_.clear();
- }
-
- /**
- * @brief 判断是否存在可撤销历史
- */
- bool canUndo() const
- {
- return !undo_states_.empty();
- }
-
- /**
- * @brief 判断是否存在可重做历史
- */
- bool canRedo() const
- {
- return !redo_states_.empty();
- }
-
- private:
- // 保持历史不超过上限,超出时从最早的记录开始丢弃
- static void trim(std::vector<State> *states)
- {
- while (states->size() > kMaximumEntries)
- {
- states->erase(states->begin());
- }
- }
-
- std::vector<State> undo_states_; // 编辑前快照栈,末尾是下一次撤销要恢复的状态
- std::vector<State> redo_states_; // 撤销后状态栈,末尾是下一次重做要恢复的状态
- };
|