HT 撤销重做手册

索引


概述

做一个全功能的拓扑编辑器或3D场景编辑器,撤销和重做功能是不可或缺的,想象一下;用户费劲心思设计了一个图元,然后一不小心按到了delete键,如果不能撤销,用户只能欲哭无泪了。

此插件提供了ht.HistoryManager类,监听记录DataModel中图元的属性变化并提供API接口撤销或重做历史记录。在正式使用API之前,您的页面里需要引入相关的js文件:

<script src="ht.js"></script> <!--先引入ht.js-->
<script src="ht-historymanager.js"></script>

使用方式非常简单,创建一个HistoryManager并绑定DataModel即可:

var historyManager = new ht.HistoryManager(dataModel);

dataModel中所有图元的属性变化都会被historyManager对象记录,当要撤销操作时,调用:

historyManager.undo();

要重做时,调用

historyManager.redo();

用户无法直接操作API,所以通常把上面API绑定到页面的快捷键上:

window.addEventListener('keydown', function(e) {
    if (e.ctrlKey) {
        if (e.keyCode == 90) {//ctrl + z
            historyManager.undo();
        } else if (e.keyCode == 89) {//ctrl + y
            historyManager.redo();
        }
    }
})

ht.HistoryManager提供的API如下:

简单示例

接下来看一个例子:

这个例子里,左上角是一个Palette组件,可以拖动其中的Node到中间的拓扑来创建Node;左下角是一个TreeView组件,可以呈现父子关系; 中间是拓扑组件,可以通过拖拽等方式操作改变图元属性;右上角是一个属性页组件,可以编辑labellabel背景色;右下角是一个ListView,展示HistoryManager中的历史记录,选中不同的记录还可以跳转历史记录。

historyManager.mp(function(e) {//监听historyManager属性变化,把历史记录同步到右下角的ListView中展示
    var property = e.property;
    if (property === 'historyIndex' || property === 'histories') {
        var histories = historyManager.getHistories(),
            historyIndex = historyManager.getHistoryIndex(),
            dataModel = list.dm();
        list._betweenUpdate = 1;
        dataModel.clear();
        var initData = new ht.Data();
        initData.setName('init status');
        dataModel.add(initData);
        histories.forEach(function(history) {
            var actions = [];
            history.forEach(function(action) {
                actions.push(action.kind);
            });
            var actionsStr = actions.join(', ');
            var data = new ht.Data();
            data.setName(actionsStr);
            dataModel.add(data);
        });
        list.sm().ss(dataModel.getDatas().get(historyIndex + 1));
        list._betweenUpdate = 0;
    }
});

list.sm().ms(function(e) {//监听右下角ListView选中状态变化,跳转到相应的历史记录
    if (!list._betweenUpdate) {
        var data = list.sm().ld(),
            index = list.dm().getDatas().indexOf(data);
        historyManager.setHistoryIndex(index - 1);
    }
});

window.addEventListener('keydown', function(e) {//增加快捷键支持
    if (e.ctrlKey) {
        if (e.keyCode == 90) {//ctrl+z 撤销
            historyManager.undo();
        } else if (e.keyCode == 89) {//ctrl+y 重做
            historyManager.redo();
        }
    }
})

欢迎交流 service@hightopo.com