综合平台编程器项目的远程存储
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

121 líneas
3.2 KiB

  1. #pragma once
  2. #include <cstddef>
  3. #include <optional>
  4. #include <utility>
  5. #include <vector>
  6. /**
  7. * @brief 保存有限数量的编辑前快照并提供撤销、重做
  8. *
  9. * State 由具体编辑服务决定,可以是 HMI 页面集合或控制逻辑集合
  10. * 历史只存在当前编辑会话内,不写入工程文件
  11. * 新编辑会清空重做栈,超过容量时丢弃最早记录
  12. */
  13. template <typename State>
  14. class EditorHistory final
  15. {
  16. public:
  17. // 单个编辑服务最多保留 30 条撤销和重做历史
  18. static constexpr std::size_t kMaximumEntries = 30U;
  19. template <typename Equal>
  20. /**
  21. * @brief 记录一次编辑前状态
  22. * @param before 编辑前状态
  23. * @param after 编辑完成后的当前状态
  24. * @param equal 比较前后状态是否相同的可调用对象
  25. *
  26. * 状态没有变化时不创建空历史
  27. * 新编辑成功记录后清空重做栈
  28. */
  29. void record(State before, const State &after, Equal equal)
  30. {
  31. if (equal(before, after))
  32. {
  33. return;
  34. }
  35. undo_states_.push_back(std::move(before));
  36. trim(&undo_states_);
  37. redo_states_.clear();
  38. }
  39. /**
  40. * @brief 撤销最近一次编辑
  41. * @param current 当前状态
  42. * @return 撤销后的目标状态;没有可撤销历史时返回空值
  43. *
  44. * 当前状态会先进入重做栈,之后取出撤销栈顶的编辑前快照
  45. */
  46. std::optional<State> undo(State current)
  47. {
  48. if (undo_states_.empty())
  49. {
  50. return std::nullopt;
  51. }
  52. redo_states_.push_back(std::move(current));
  53. trim(&redo_states_);
  54. State target = std::move(undo_states_.back());
  55. undo_states_.pop_back();
  56. return target;
  57. }
  58. /**
  59. * @brief 重做最近一次被撤销的编辑
  60. * @param current 当前状态
  61. * @return 重做后的目标状态;没有可重做历史时返回空值
  62. *
  63. * 当前状态会先放回撤销栈,之后取出重做栈顶的目标状态
  64. */
  65. std::optional<State> redo(State current)
  66. {
  67. if (redo_states_.empty())
  68. {
  69. return std::nullopt;
  70. }
  71. undo_states_.push_back(std::move(current));
  72. trim(&undo_states_);
  73. State target = std::move(redo_states_.back());
  74. redo_states_.pop_back();
  75. return target;
  76. }
  77. /**
  78. * @brief 清空撤销栈和重做栈
  79. */
  80. void clear()
  81. {
  82. undo_states_.clear();
  83. redo_states_.clear();
  84. }
  85. /**
  86. * @brief 判断是否存在可撤销历史
  87. */
  88. bool canUndo() const
  89. {
  90. return !undo_states_.empty();
  91. }
  92. /**
  93. * @brief 判断是否存在可重做历史
  94. */
  95. bool canRedo() const
  96. {
  97. return !redo_states_.empty();
  98. }
  99. private:
  100. // 保持历史不超过上限,超出时从最早的记录开始丢弃
  101. static void trim(std::vector<State> *states)
  102. {
  103. while (states->size() > kMaximumEntries)
  104. {
  105. states->erase(states->begin());
  106. }
  107. }
  108. std::vector<State> undo_states_; // 编辑前快照栈,末尾是下一次撤销要恢复的状态
  109. std::vector<State> redo_states_; // 撤销后状态栈,末尾是下一次重做要恢复的状态
  110. };