====== Undo/Redo机制 ====== XT框架支持无限Undo/Redo的特性。一个命令的完成包含着对数据的一系列处理,包括数据的增加、修改和删除,除此之外还有数据对象关系的修改(如绑定、解除绑定),为了支持Undo/Redo,对于一个文档,XT会打开一个文件用于记录所有数据的操作历史。\\ 从命令在执行之前,会记录当前历史文件的位置。在命令执行期间,数据对象会有以下几种基本操作: * 数据的检出,涉及修改或者删除时需首先从数据管理器中检出,检出的时候数据对象将标记为SET写入当前命令记录文件中;如该数据为新增项ADD,则不用检出; * 数据的增加,数据的特征值(数据ID,数据类型以及管理器ID)将标记为ADD写入到当前命令记录文件中; * 数据的删除,首先检出数据(如为新增项则省略),标记为DEL写入到当前命令记录文件中; * 数据的绑定,数据特征值与绑定对象的特征值标记为ATTACH写入到当前命令记录文件中; * 数据的解绑,数据特征值与绑定对象的特征值标记为DETACH写入到当前命令记录文件中 数据的增加以及删除,只需在对象管理器中为其分配内存并指定ID即可;对于数据的修改,则需要特别小心保持修改前后关联数据的一致性,这些关联数据包括一些临时性的缓存数据(缓存数据是为了提高程序访问速度提前准备好的一些临时数据,依赖于其他数据,其他数据更新之后如果缓存数据没有更新就可能导致程序调用失败),数据管理器提供了updateCache的接口以方便开发者定制其实现。在一次命令操作中,凡是对数据的修改,一般会有两条对应的SET记录存在,一次对应检出,一次对应检入。\\ 在命令执行失败时,数据对象从命令操作记录文件的尾部反向执行直到命令开始的位置为止: * 若记录为ADD,删除数据; * 若记录为SET,从记录中读取数据内容; * 若记录为SET-DEL,添加数据; * 若记录为ATTACH,解除数据的绑定关系; * 若记录为DETACH,绑定数据对象关系; 在命令执行完成时,根据数据已有的状态,数据对象会有以下几种操作以完成数据更改的提交: * 若数据有ADD-DEL标志,不操作; * 若数据有SET-DEL标志,不操作; * 若数据只有ADD标志,将数据的当前内容以SET标记写入到记录文件中; * 若数据只有SET标志,将数据的当前内容以SET标记写入到记录文件中; 最后会得到对于该操作在记录文件的起始位置和结束位置,并作为命令操作的历史记录到另外一个文件cmd.htr中。 特别的,对于单元,它有一个节点的数组,由于每一个节点会维持一份关联单元的指针数组,在修改单元的前后应更新包含节点的单元指针数组。 记录文件中每一个记录单元的格式如下: - int :数据管理器ID - int :操作标志符 - int :数据对象ID - int :数据对象类型 - optional :在SET时表示数据对象的大小,其他情况下无 - optional :在SET时为对象数据的具体内容的二进制表达,其他情况下无 - int : 表示记录的大小(不包含这个数) 在Undo操作时,首先定位到当前操作的记录末端,接着反向执行每一条记录直到当前操作的起始位置为止。 在Redo操作时,首先定位到当前操作的记录起始位置,接着顺序执行每一条记录直到当前操作的结束位置为止。 __如果需要动态增加数据管理器的情况,则需要另外的处理。__ 在XT框架里,可管理(即包含类型定义、可索引、可修改、可删除)的数据对象可以是独立的个体(比如坐标系),也可以与其他对象发生关联(比如拓扑体,它与单元以及拓扑面构成关联关系),为了支持这些特性,数据对象的定义需要满足如下条件: * 数据项须由自[[class::domain::xmanager|XManager]]继承的数据项管理器管理; * 实现serialize序列化接口; * 如果该对象须维护缓存数据,应实现updateCache接口;