在GIS地图数据编辑中,撤销和恢复功能也算是基本功能了,那么如何设计一个简单高效的编辑撤销和恢复模块也显得比较重要,这里本人也是用C#写了一个简单的撤销和恢复功能供大家参考,有更好的方法请不吝指教。
设计接口:IDoable,凡是需要具有撤销和恢复功能的类都必须要实现此接口,代码如下:
public interface IDoable
{
bool CanUndo();
bool CanRedo();
void Undo();
void Redo();
}
设计泛型接口:IDoManager<T>,这个类作为需要有撤销和恢复功能的类的一个成员变量,主要用来辅助管理撤销和恢复的一些数据存储和读取,代码如下:
interface IDoManager<T>
{
void PushData(T data);
T PopData();
void ClearDatas();
void SetUndoLen(int len);
bool CanUndo();
bool CanRedo();
}
IDoManager<T>接口的实现类DoManager<T>:
public class DoManager<T> : IDoManager<T>
{
private Queue<T> _datas;
private int _len = 8;
private int _cur = -1;
public DoManager()
{
_datas = new Queue<T>(_len);
}
#region IDoManager<T> 成员
public void PushData(T data)
{
if (_cur < _len)
{
_cur++;
_datas.Enqueue(data);
}
else
{
_datas.Dequeue();
_datas.Enqueue(data);
}
}
public void ClearDatas()
{
_datas.Clear();
_cur = -1;
}
public void SetUndoLen(int len)
{
_datas.Clear();
_len = len;
}
public T PopData()
{
return _datas.ToArray()[_cur--];
}
public bool CanUndo()
{
if (_cur < _len)
return true;
return false;
}
public bool CanRedo()
{
if (_cur > -1)
return true;
else return false;
}
#endregion
}
如上几行简单的代码就实现了一个具有撤销和恢复功能的基本接口和基础类的实现。
这里写一个简单的小例子来作为测试,如地图中,我们需要编辑数据,假如是采集面数据,采集面的时候可以支持撤销和恢复,废话不多说,具体见代码:
public class Polygon:IDoable
{
private List<Point> _points = new List<Point>();
private DoManager<Point> _doManager = new DoManager<Point>();
public List<Point> Points
{
get { return _points; }
set { _points = value; }
}
public Polygon()
{
_doManager.SetUndoLen(100);
}
public void AddPoint(Point pt)
{
_points.Add(pt);
}
#region IDoable 成员
public bool CanUndo()
{
if (_doManager.CanUndo() && _points.Count > 1)
return true;
return false;
}
public bool CanRedo()
{
if (_doManager.CanRedo())
return true;
return false;
}
public void Undo()
{
if (CanUndo())
{
_doManager.PushData(_points[_points.Count - 1]);
_points.RemoveAt(_points.Count - 1);
}
}
public void Redo()
{
if (CanRedo())
{
_points.Add(_doManager.PopData());
}
}
#endregion
}
测试方法:运行工程中demo,如下图所示,点击界面白颜色部分采集点,点击上方的撤销按钮撤销,点击上方的恢复按钮恢复撤销。
效果如下: