唯杰地图 logo唯杰地图
VJMAP
EN

撤销/重做系统

vjcad/references/autodraw/undo-patterns.md 3.7 KB143 行
原文

撤销标记、撤销组、嵌套撤销、各类操作的撤销模式。


核心规则

start_undoMark() / end_undoMark() 只负责把多条撤销记录合并为一步;未包裹时每条记录单独成一步,仍可撤销。

Engine.addEntities() / Engine.eraseEntities() 已自带撤销记录,切勿再手动 added_undoMark / erased_undoMark(撤销实现为从块末尾 pop,重复记录会多删一个原有实体)。只有用 Engine.pcanvas.addEntity / currentSpace.erase 等底层 API 才手动补记。不需要撤销时传 { recordUndo: false }:Engine.addEntities(ents, { recordUndo: false })、Engine.eraseEntities(ents, { recordUndo: false })。


基本用法

const { Engine } = vjcad;
const undoMgr = Engine.undoManager;

// 字符串简写(最常用)
undoMgr.start_undoMark('绘制图形');
try {
    // ... 创建/修改/删除实体 ...
    Engine.addEntities(entity);   // 自带撤销记录,无需再 added_undoMark
} finally {
    undoMgr.end_undoMark();
}

嵌套撤销(推荐在命令中使用)

const { Engine } = vjcad;

Engine.startUndoRecord('我的操作');   // 支持嵌套,只有最外层生效
// ... 操作 ...
Engine.endUndoRecord();

新增实体的撤销

undoMgr.start_undoMark('添加实体');
try {
    const line = new LineEnt([0, 0], [100, 0]);
    line.setDefaults();
    Engine.addEntities(line);   // 已自动记录撤销
} finally {
    undoMgr.end_undoMark();
}

注意:Engine.addEntities() 会自动记录撤销,不要再手动调用 added_undoMark(双重记录会让 Ctrl+Z 多删一个原有实体、重做时新实体被压入两次)。只有用 Engine.pcanvas.addEntity(ent) 底层入库时才需要手动补记:

Engine.pcanvas.addEntity(line);          // 底层 API,不记撤销
undoMgr.added_undoMark([line]);          // 手动补记

修改已有实体的撤销

undoMgr.start_undoMark('修改颜色');
try {
    Engine.markModified(entity);    // 先标记(记录修改前状态)
    entity.color = 1;               // 再修改属性
    entity.layer = "新图层";
    entity.setModified();           // 通知修改完成
} finally {
    undoMgr.end_undoMark();
}

删除实体的撤销

undoMgr.start_undoMark('删除实体');
try {
    Engine.eraseEntities(entities);      // 自带 erased_undoMark,勿重复记录
} finally {
    undoMgr.end_undoMark();
}

变换操作的撤销

const { Point2D } = vjcad;

undoMgr.start_undoMark('移动');
try {
    const from = new Point2D(0, 0);
    const to = new Point2D(50, 0);
    entities.forEach(ent => ent.move(from, to));
    undoMgr.moved_undoMark(entities, from, to);
    Engine.regen();
} finally {
    undoMgr.end_undoMark();
}

其他变换撤销标记:

undoMgr.rotate_undoMark(entities, basePoint, angle);
undoMgr.scaled_undoMark(entities, basePoint, scale);
undoMgr.mirrored_undoMark(entities, p1, p2);

撤销/重做操作

undoMgr.undo();                             // 撤销一步
undoMgr.redo();                             // 重做一步
undoMgr.undoSteps(3);                       // 撤销 3 步
undoMgr.undoSteps('绘制图形');              // 按名称撤销到最近匹配项
undoMgr.redoSteps('绘制图形');              // 按名称重做
undoMgr.undoSteps(3, { silent: true });     // 静默撤销(不触发消息)

检查状态

if (undoMgr.canUndo()) { undoMgr.undo(); }
if (undoMgr.canRedo()) { undoMgr.redo(); }
Engine.isInUndoRecord();   // 是否在撤销记录中