本贴转自http://www.drgraph.com/viewthread.php?tid=109&extra=page%3D1
2.4 创建导线类型
经过创建类型的处理,可以看出,针对某一类型的操作,仅需考虑Undo/Redo该操作时都需要些什么样的信息。
对于创建导线而言,若希望撤销该操作,就是删除该导线;而若要重做时,还有一些额外事宜要做,如:
1. 创建导线时,会设置该导线的连接元件,这是最简单的情况
2. 创建导线时,如果起止点在已有导线上,则会与已有导线合并,这其实应该算是两个子操作,即:创建新导线,合并两条导线
因此,创建导线时,还需要一些额外信息,这些信息应包括:
1. 所连接的元件
2. 所连接的母线
3. 相关的导线
每次创建导线时,最多可首尾连接一个元件,因此可添加成员FBeginUnit, FEndUnit表示起始元件
而母线,只能在结束时连接,可添加成员FConnectedBus表示
对导线而言,可添加成员FWireInfoList以记录相关的导线。
为编程方便,置
下标为0的导线为创建导线的起始导线
下标为1的导线为创建导线的结束导线
下标为2的导线为结果导线,即有0+1=2
为便于阅读,可定义以下三个常量
当然,以上添加了如此之多的成员,对于维护工作有一定的要求,因此,可将连接关系信息全部加入到导线信息中,以省去连接对象数据成员。
有了数据成员后,再来处理需求
创建导线操作,可从元件管脚开始,也可从已有导线的拐点处开始,但开始后,均会创建出一个临时的两线类TTwoWireLine,设置其起始点后,可开始记录导线操作
下来就该考虑结束的事了。结束的逻辑代码如下:
这些代码仅处理了在母线上结束创建导线的逻辑,即设置相连母线、结束导线为空,而目标导线为原导线。而其它情况在CanConnect中处理
上面代码较长,但逻辑很简单,即首先判断连接控点所连导线情况,若有且与当前导线不同,则分别设置;若相同,则可设结束导线为空,而目标导线为结束导线;若无导线,则直接加入控点,并设结束导线为空,而目标导线为当前导线。当然,若无控点,则查找目标导线,找到后再处理。
模型对象构造完毕后,下一件事情就是持久化,即输出为文本。
突然发现,无需进行输出了,因为所谓的输出也就是转化为XmlNode对象,但现在已经是文本列表对象,完全能满足Undo/Redo的需要。
最后的事情就是Redo/Undo了。
对于Undo逻辑,需取出目标导线,将之删除,然后再恢复起始与结束导线。
而Redo呢,反之,需取出起始与结束导线,将之删除,然后再恢复目标导线。
从上述逻辑中可以提取出两个函数:CreateWireByInfo与DeleteWireByInfo
最终发现,创建导线操作的撤销/重做代码是如此的简单:
Undo代码:
Redo代码:
最后的事情就是测试(A + B表示从A开始画导线,到B结束,NULL表示强制结束):
序号 | 测试内容 | Undo | Redo |
1. | 元件 + NULL | OK | OK |
2. | 元件 + NULL,多次 | OK | OK |
3. | 元件 + 元件 | OK | OK |
4. | 元件 + 元件,多次 | OK | OK |
5. | 元件 + 导线 | OK | OK |
6. | 元件 + 导线,多次 | OK | OK |
7. | 元件 + 母线 | OK | OK |
8. | 元件 + 母线,多次 | OK | OK |
9. | 导线 + NULL | OK | OK |
10. | 导线 + NULL,多次 | OK | OK |
11. | 导线 + 元件 | OK | OK |
12. | 导线 + 元件,多次 | OK | OK |
13. | 导线 + 母线 | OK | OK |
14. | 导线 + 母线,多次 | OK | OK |
一次性全部成功, OK 。