Undo/Redo机制

XT框架支持无限Undo/Redo的特性。一个命令的完成包含着对数据的一系列处理,包括数据的增加、修改和删除,除此之外还有数据对象关系的修改(如绑定、解除绑定),为了支持Undo/Redo,对于一个文档,XT会打开一个文件用于记录所有数据的操作历史。
从命令在执行之前,会记录当前历史文件的位置。在命令执行期间,数据对象会有以下几种基本操作:

数据的增加以及删除,只需在对象管理器中为其分配内存并指定ID即可;对于数据的修改,则需要特别小心保持修改前后关联数据的一致性,这些关联数据包括一些临时性的缓存数据(缓存数据是为了提高程序访问速度提前准备好的一些临时数据,依赖于其他数据,其他数据更新之后如果缓存数据没有更新就可能导致程序调用失败),数据管理器提供了updateCache的接口以方便开发者定制其实现。在一次命令操作中,凡是对数据的修改,一般会有两条对应的SET记录存在,一次对应检出,一次对应检入。
在命令执行失败时,数据对象从命令操作记录文件的尾部反向执行直到命令开始的位置为止:

在命令执行完成时,根据数据已有的状态,数据对象会有以下几种操作以完成数据更改的提交:

最后会得到对于该操作在记录文件的起始位置和结束位置,并作为命令操作的历史记录到另外一个文件cmd.htr中。

特别的,对于单元,它有一个节点的数组,由于每一个节点会维持一份关联单元的指针数组,在修改单元的前后应更新包含节点的单元指针数组。 记录文件中每一个记录单元的格式如下:

  1. int :数据管理器ID
  2. int :操作标志符
  3. int :数据对象ID
  4. int :数据对象类型
  5. optional :在SET时表示数据对象的大小,其他情况下无
  6. optional :在SET时为对象数据的具体内容的二进制表达,其他情况下无
  7. int : 表示记录的大小(不包含这个数)

在Undo操作时,首先定位到当前操作的记录末端,接着反向执行每一条记录直到当前操作的起始位置为止。 在Redo操作时,首先定位到当前操作的记录起始位置,接着顺序执行每一条记录直到当前操作的结束位置为止。

如果需要动态增加数据管理器的情况,则需要另外的处理。

在XT框架里,可管理(即包含类型定义、可索引、可修改、可删除)的数据对象可以是独立的个体(比如坐标系),也可以与其他对象发生关联(比如拓扑体,它与单元以及拓扑面构成关联关系),为了支持这些特性,数据对象的定义需要满足如下条件: