在一个具体项目中想实现UNDO/REDO的功能, 操作的次数没有限制, 而且数据的类型比较复杂.  如有这方面有经验的高手, 可否谈谈你是如何实现的.

posted on 2005-09-23 08:56 moonriver 阅读(562) 评论(5)  编辑 收藏 引用
评论
  • # re: 有没有在具体项目中作过UNDO/REDO的高手, 给提点建议.
    深圳夜归人
    Posted @ 2005-09-23 10:21
    这是个很好的话题,相信很多人都考虑过,而且想过各种复杂的做法。

    实际上有个最简单的解决办法。有几点要先注意到的:

    1、每个基本操作都是可以分解为添加/删除动作的。
    2、每个UNDO/REDO动作是由一组基本的添加/删除动作组成的,这个基本的动作本身也是一个UNDO/REDO动作。
    3、如果一个基本的UNDO动作做的工作是添加,对应的REDO动作就是删除。
    4、UNDO/REDO动作必须以一个顺序来执行。
    5、当前位置处于UNDO历史中时,一个DO动作要删除当前位置后面的所有UNDO动作。

    比如在文字编辑器中,输入一段话,构成一个“添加字符串”动作。删除一段话,构成一个“删除字符串”动作。它们在动作历史中,只需要保存发生这个动作时的一些基本环境信息。

    另一些复杂的动作,比如选择一段文字,拖到另一个位置,可以分解为一个删除+一个添加动作,并把这2个动作组成一个给用户使用的UNDO/REDO动作。当用户UNDO时,执行后一个添加动作的反动作即删除动作,接着执行前一个删除动作的反动作即添加动作。

    设计UNDO/REDO功能,实际上就是把那些高级功能拆为最基本的添加/删除动作。



    以上是个人看法。可以找一些开源的编辑器程序来看它们的源码,实际上UNDO/REDO功能大部分时候都是用在编辑器中。。。  回复  更多评论   
  • # re: 有没有在具体项目中作过UNDO/REDO的高手, 给提点建议.
    moonriver
    Posted @ 2005-09-23 11:07
    谢谢!

    COMMAND模式似乎也是提供这样的解决方案. 我在以前也考虑过, 但这种方法也是有些不足:

    1. 通常COMMAND模式已经应用到接近APPLICATION/GUI层, 在这个层面的DEVELOPER通常还是稍微差些,要求去理解底层的逻辑通常是不容易的.

    2. 考虑到COMMAND众多, 在COMMAND中实现UNDO/REDO也是很麻烦的事.

    还有一点是, 个人认为UNDO/REDO应该是一种架构层面的问题, 应该从架构角度找到解决问题的方法. 这样一来, 至少在另一个项目中可以复用. 如依赖COMMAND, 没办法做到这一点.  回复  更多评论   
  • # re: 有没有在具体项目中作过UNDO/REDO的高手, 给提点建议.
    深圳夜归人
    Posted @ 2005-09-23 11:40
    那些东西应该全部封装在底层,而且你不该把这么底层的部分暴露给GUI开发人员。

    比如你提供了几个底层的函数:addChar(ch), addString(text), insertString(pos, text),moveCursor(pos)它的实现中都向Undo History中插入Action。

    GUI开发人员可能要定义一个功能functionA,这个功能中要调用这几个函数,并组成一个Undo动作。他们根本不需要知道你底层如何动作的,只需要简单做这个过程:

    document->BeginAction ("插入日期和开发人员名字");
    document->addChar(...);
    docuemnt->insertString(...);
    document->...;
    document->EndAction();
    注意中间有一项失败时,应该调用回滚。

    EndAction()激发一个事件,通知GUI在UNDO列表中加入一项“插入日期和开发人员名字”。

    这不是我的方案,实际上我至少看到过3个编辑器源码这么干,好像成了一个定式了。。。呵呵  回复  更多评论   
  • # re: 有没有在具体项目中作过UNDO/REDO的高手, 给提点建议.
    moonriver
    Posted @ 2005-09-23 12:16
    谢谢, 很清楚! 我考虑试试看!  回复  更多评论   
  • # re: 有没有在具体项目中作过UNDO/REDO的高手, 给提点建议.
    pandaxcl
    Posted @ 2006-04-21 10:54
    我是采用C++实现的,在我得博客里面有比较详细的介绍,可以参考。
    我得博客:http://blog.csdn.net/pandaxcl/  回复  更多评论   

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


统计