首页/文章/ 详情

FreeCAD源码分析:Undo/Redo实现原理

2年前浏览2151

Undo/RedoCAx软件中常见的操作功能,其实现方法也相对比较成熟,本文对FreeCAD Transaction机制进行深入分析,一方面是为了深化对FreeCAD代码的理解,学习其设计思路,领略其设计模式的使用范式;另一方面则考虑到Undo/Redo功能的普遍性,旨在阐述Undo/Redo的实现原理,希望对从事国产CAx软件开发的朋友有所帮助。

注1:限于笔者研究水平,难免有理解不当,欢迎批评指正。

注2:文章内容会不定期更新,欢迎交流讨论。

一、预修知识

1.1 设计模式

Undo/Redo经典实现是采用Command、Memento等设计模式。GoF、Alexander Shvets等已经就Command、Memento等相关设计模式进行了经典阐述,这里不再赘述,仅简要罗列其技术要点。

Command模式将请求封装成了对象,提供了命令响应的统一接口。

image.png

Memento模式在不违反封装的前提下,提供了对象状态记录与恢复的功能。

image.png

1.2 FreeCAD属性系统

image.png


FreeCAD基于Observer模式,实现了App::Property类。按照GoF's Observer模式,Property作为Subject,而App::PropertyContainer则是Observer。

二、代码分析

2.1 App::TransactionalObject

FreeCAD中,整套代码最为基础的类其实只有两个,一个是App::DocumentObject,另一个则是Gui::ViewProvider,而这两个类均派生于App::TransactionalObject。

App::TransactionalObject类比较简单,主要功能是采用Memento模式实现了对象属性快照的功能。

image.png

每当修改属性数据时,便会自动调用onBeforeChangeProperty()函数,而该函数的主要作用就是存储对象相关属性,以便后续执行Undo时,可以完成对象状态的恢复。

image.png

(完整代码见原文)

2.2 App::TransactionObject

由于一个Transaction通常由多个子操作构成,对应于子操作,App::TransactionObject则是用于记录对象创建、对象删除、属性修改等操作历史。

image.png

(完整代码见原文)

需要指出的是,App::TransactionObject通过枚举值New、Del来标记对象创建、对象删除,并记录对象名称;而将属性存储在App::TransactionObject::_PropChangeMap中。

2.3 App::Transaction

App::Transaction正是用于记录一次Transaction中对同一文档的修改,其中可能设计对多个对象的修改。

image.png

(完整代码见原文)

实际使用中,每个Document中都分别定义了自己的App::Transaction对象,因此记录的也就是对本文档对象的修改。

image.png

(完整代码见原文)

2.4 App::Document

按照GoF Memento模式,App::Document实际上扮演的是Caretaker的角色,App::Document提供了Undo/Redo堆栈,

image.png

2.5 Gui::Command

Gui::Command对应的就是GoF Command模式中的Command,提供了命令响应的接口,同时提供了Transaction创建的调用接口。

image.png

参考资料

Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides. Design Patterns:elements of reusable object-oriented software. Addison Wesley, 1994.

Alexander Shvets. Dive into Design Patterns.

理论科普其他软件
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2022-05-27
最近编辑:2年前
YouQuan Soft
硕士 济南友泉软件有限公司
获赞 30粉丝 7文章 12课程 0
点赞
收藏
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习 福利任务 兑换礼品
下载APP
联系我们
帮助与反馈