第一个文件:LC_UndoableRelZero.h (头文件)
文件说明
这是 LibreCAD 中实现可撤销相对零点操作的类声明头文件,用于管理图形视口中相对零点的移动操作。
代码结构分析
1. 类定义
#ifndefLC_UNDOABLERELZERO_H#defineLC_UNDOABLERELZERO_H- 标准的头文件保护宏,防止重复包含
2. 类声明
classLC_UndoableRelZero:publicRS_Undoable- 继承自
RS_Undoable基类,表明这是一个可撤销操作 - 用于封装相对零点的移动操作
3. 成员变量
private:LC_GraphicViewport*viewport=nullptr;RS_Vector m_From=RS_Vector(0,0,0);// 移动前的坐标RS_Vector m_To=RS_Vector(0,0,0);// 移动后的坐标viewport: 指向图形视口的指针m_From: 记录相对零点移动前的三维坐标 (x,y,z)m_To: 记录相对零点移动后的三维坐标
4. 关键方法
voidundoStateChanged(boolundone)override;- 重写基类的虚函数
- 当撤销/重做状态改变时被调用
undone参数表示操作是否被撤销
第二个文件:LC_UndoSection.cpp (源文件)
文件说明
这是 LibreCAD 中撤销操作区域管理类的实现文件,用于批量管理一组撤销操作。
代码结构分析
1. 构造函数
LC_UndoSection::LC_UndoSection(RS_Document*doc,LC_GraphicViewport*view,constboolhandleUndo/*= true*/):document(doc),viewport(view),valid(handleUndo&&nullptr!=doc&&nullptr!=view){if(valid){document->startUndoCycle();}}功能:
- 初始化撤销操作区域
- 参数说明:
doc: 文档指针view: 图形视口指针handleUndo: 是否处理撤销操作(默认为 true)
- 验证条件:文档和视口都不为空且
handleUndo为 true - 如果有效,开始一个撤销周期
2. 析构函数
LC_UndoSection::~LC_UndoSection(){try{if(valid&&viewport!=nullptr){RS_Undoable*relativeZeroUndoable=viewport->getRelativeZeroUndoable();if(relativeZeroUndoable!=nullptr){document->addUndoable(relativeZeroUndoable);}document->endUndoCycle();}}catch(...){}}功能:
- 对象销毁时自动调用
- 关键操作流程:
- 检查区域是否有效且视口存在
- 获取视口中的相对零点可撤销操作
- 如果有相关操作,添加到文档的撤销列表中
- 结束撤销周期
- 使用 try-catch 捕获所有异常,确保资源清理
3. 添加撤销操作的方法
voidLC_UndoSection::addUndoable(RS_Undoable*undoable){if(valid){document->addUndoable(undoable);}}功能:
- 向当前撤销区域添加可撤销操作
- 仅当区域有效时才执行添加
- 参数
undoable可以是任何继承自RS_Undoable的对象
两个类的关系和工作流程
协同工作模式
用户操作相对零点 ↓ LC_UndoableRelZero 记录移动信息 ↓ LC_UndoSection 开始撤销周期 ↓ 执行其他相关操作 ↓ LC_UndoSection 析构时: 1. 获取相对零点操作 2. 添加到文档撤销列表 3. 结束撤销周期关键设计特点
RAII 模式(资源获取即初始化)
LC_UndoSection在构造时开始撤销周期- 在析构时自动结束周期并清理资源
- 异常安全设计
职责分离
LC_UndoableRelZero: 封装具体的操作数据LC_UndoSection: 管理撤销操作的执行流程
灵活扩展
- 通过
addUndoable()可以添加各种类型的撤销操作 - 基类设计支持多态
- 通过
使用场景示例
当用户在 LibreCAD 中执行一个包含多个步骤的复杂操作时:
// 开始一个撤销区域LC_UndoSectionundoSection(document,viewport);// 执行操作1performOperation1();undoSection.addUndoable(operation1Undoable);// 执行操作2(包括相对零点移动)moveRelativeZero(from,to);// LC_UndoableRelZero 会自动记录// 执行操作3performOperation3();undoSection.addUndoable(operation3Undoable);// undoSection 析构时,所有操作被作为一个整体添加到撤销列表这样设计的好处是,用户可以一次性撤销整个操作序列,而不是逐个撤销每个小步骤。