Undo

1.  redo和undo的实现
  知道执行了什么命令,影响了那些数据
  终止条件和状态

2.  这里我犯了个错误,其实我根本不需要知道是执行的什么命令,对于绘图系统,我只需知道对数据产生了那些影响。撤销和重做其实都是针对数据(几何对象)来说的。

所有这里只需要在操作(添加几何对象、删除几何对象、修改几何对象、增加节点、删除节点、移动节点等)时另外引一条线,就是UndoRedoBuffer对象,他是一个List,其实如果是栈则更好,用它记录操作影响的数据。注意是操作影响的数据,和上面所说的操作是两个概念。

抽象了一个操作影响数据的EditCommandBase类,具体子类有:添加影响数据类,删除影响数据类、移动影响数据类。

在每一次修改Canvas对象的几何对象集合时都要引出一条线,记录这个操作影响数据信息,即加入UndoRedoBuffer。

Undo就是UndoRedoBuffer顶部的影响数据修改几何对象集合,实现回退。

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Canvas
{
    class EditCommandBase
    {
        public virtual bool DoUndo(IModel data)
        {
            return false;
        }
        public virtual bool DoRedo(IModel data)
        {
            return false;
        }
    }
    class EditCommandAdd : EditCommandBase
    {
        List<IDrawObject> m_objects = null;
        IDrawObject m_object;
        ICanvasLayer m_layer;
        public EditCommandAdd(ICanvasLayer layer, IDrawObject obj)
        {
            m_object = obj;
            m_layer = layer;
        }
        public EditCommandAdd(ICanvasLayer layer, List<IDrawObject> objects)
        {
            m_objects = new List<IDrawObject>(objects);
            m_layer = layer;
        }
        public override bool DoUndo(IModel data)
        {
            if (m_object != null)
                data.DeleteObjects(new IDrawObject[] { m_object });
            if (m_objects != null)
                data.DeleteObjects(m_objects);
            return true;
        }
        public override bool DoRedo(IModel data)
        {
            if (m_object != null)
                data.AddObject(m_layer, m_object);
            if (m_objects != null)
            {
                foreach (IDrawObject obj in m_objects)
                    data.AddObject(m_layer, obj);
            }
            return true;
        }
    }
    class EditCommandRemove : EditCommandBase
    {
        Dictionary<ICanvasLayer, List<IDrawObject>> m_objects = new Dictionary<ICanvasLayer, List<IDrawObject>>();
        public EditCommandRemove()
        {
        }
        public void AddLayerObjects(ICanvasLayer layer, List<IDrawObject> objects)
        {
            m_objects.Add(layer, objects);
        }
        public override bool DoUndo(IModel data)
        {
            foreach (ICanvasLayer layer in m_objects.Keys)
            {
                foreach (IDrawObject obj in m_objects[layer])
                    data.AddObject(layer, obj);
            }
            return true;
        }
        public override bool DoRedo(IModel data)
        {
            foreach (ICanvasLayer layer in m_objects.Keys)
                data.DeleteObjects(m_objects[layer]);
            return true;
        }
    }
    class EditCommandMove : EditCommandBase
    {
        List<IDrawObject> m_objects = new List<IDrawObject>();
        UnitPoint m_offset;
        public EditCommandMove(UnitPoint offset, IEnumerable<IDrawObject> objects)
        {
            m_objects = new List<IDrawObject>(objects);
            m_offset = offset;
        }
        public override bool DoUndo(IModel data)
        {
            foreach (IDrawObject obj in m_objects)
            {
                UnitPoint offset = new UnitPoint(-m_offset.X, -m_offset.Y);
                obj.Move(offset);
            }
            return true;
        }
        public override bool DoRedo(IModel data)
        {
            foreach (IDrawObject obj in m_objects)
                obj.Move(m_offset);
            return true;
        }
    }
    class EditCommandNodeMove : EditCommandBase
    {
        List<INodePoint> m_objects = new List<INodePoint>();
        public EditCommandNodeMove(IEnumerable<INodePoint> objects)
        {
            m_objects = new List<INodePoint>(objects);
        }
        public override bool DoUndo(IModel data)
        {
            foreach (INodePoint obj in m_objects)
                obj.Undo();
            return true;
        }
        public override bool DoRedo(IModel data)
        {
            foreach (INodePoint obj in m_objects)
                obj.Redo();
            return true;
        }
    }
    class EditCommandEditTool : EditCommandBase
    {
        IEditTool m_tool;
        public EditCommandEditTool(IEditTool tool)
        {
            m_tool = tool;
        }
        public override bool DoUndo(IModel data)
        {
            m_tool.Undo();
            return true;
        }
        public override bool DoRedo(IModel data)
        {
            m_tool.Redo();
            return true;
        }
    }
    class UndoRedoBuffer
    {
        List<EditCommandBase> m_undoBuffer = new List<EditCommandBase>();
        List<EditCommandBase> m_redoBuffer = new List<EditCommandBase>();
        bool m_canCapture = true;
        bool m_dirty = false;
        public UndoRedoBuffer()
        {
        }
        public void Clear()
        {
            m_undoBuffer.Clear();
            m_redoBuffer.Clear();
        }
        public bool Dirty
        {
            get { return m_dirty; }
            set { m_dirty = value;}
        }
        public bool CanCapture
        {
            get { return m_canCapture; }
        }
        public bool CanUndo
        {
            get { return m_undoBuffer.Count > 0; }
        }
        public bool CanRedo
        {
            get { return m_redoBuffer.Count > 0; }
        }
        public void AddCommand(EditCommandBase command)
        {
            if (m_canCapture && command != null)
            {
                m_undoBuffer.Add(command);
                m_redoBuffer.Clear();
                Dirty = true;
            }
        }
        public bool DoUndo(IModel data)
        {
            if (m_undoBuffer.Count == 0)
                return false;
            m_canCapture = false;
            EditCommandBase command = m_undoBuffer[m_undoBuffer.Count - 1];
            bool result = command.DoUndo(data);
            m_undoBuffer.RemoveAt(m_undoBuffer.Count - 1);
            m_redoBuffer.Add(command);
            m_canCapture = true;
            Dirty = true;
            return result;
        }
        public bool DoRedo(IModel data)
        {
            if (m_redoBuffer.Count == 0)
                return false;
            m_canCapture = false;
            EditCommandBase command = m_redoBuffer[m_redoBuffer.Count - 1];
            bool result = command.DoRedo(data);
            m_redoBuffer.RemoveAt(m_redoBuffer.Count - 1);
            m_undoBuffer.Add(command);
            m_canCapture = true;
            Dirty = true;
            return result;
        }
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Oracle中,"undo"是指用于回滚事务的数据。在Oracle数据库中,有两种方式来管理undo数据:使用回滚段或使用重做表空间。根据引用,如果将"undo_management"参数设置为"AUTO",系统将使用重做表空间来管理undo数据。而如果将它设置为"MANUAL",则需要手动创建回滚段。根据引用,如果在创建数据库时未指定undotablespace的名称,系统会自动创建一个名为"sys_undotbs"的默认回滚表空间,初始大小为10M,并且可以自动扩展。不过,Oracle建议最好还是使用一个指定大小的回滚表空间。 在进行一些特殊操作时,可能需要重命名或迁移undo数据文件。例如,根据引用,可以使用ALTER TABLESPACE语句来重命名undo数据文件。通过指定旧的文件路径和新的文件路径,可以将数据文件重命名为新的名称。 综上所述,Oracle中的undo是用于回滚事务的数据。可以通过设置"undo_management"参数来选择使用回滚段或重做表空间来管理undo数据。如果未指定undotablespace的名称,系统会创建一个默认的回滚表空间。在某些情况下,可以使用ALTER TABLESPACE语句来重命名或迁移undo数据文件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [oracle中undo相关知识](https://blog.csdn.net/huangliang0703/article/details/16407015)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值