撤消粘贴操作时,撤消管理器堆栈似乎已损坏
Undo Manager stack seems to get corrupted when undoing a paste operation
我正在使用 undomanager 并尝试在双向链表上实现 cut/copy/paste 功能。首先,这是我的代码。
业力测试脚本:
it('should cut and paste a node with working undo/redo', function () {
var list = listFactory.createList();
var node1 = list.appendNode(
nodeFactory.createNode({
//nodeinfo
})
);
var node2 = list.appendNode(
nodeFactory.createNode({
//nodeinfo
})
);
// here we cut the node2 out of the profile
list.cutNode(node2.id);
expect(list.clipboard.id).toBe(node2.id);
expect(list.getLength()).toBe(2);
// undoing the cut should clear the clipboard and return the node2 to where it was.
list.undo();
expect(list.clipboard).toBe(null);
expect(list.getLength()).toBe(2);
// redoing the cut should remove node2
list.redo();
expect(list.clipboard.id).toBe(node2.id);
expect(list.getLength()).toBe(1);
// pasting node2 in front of node1
list.pasteNode(indexSeg.id);
expect(list.getLength()).toBe(2);
// the first undo should remove node2 from the front
list.undo();
expect(list.getLength()).toBe(1);
// this should reset the list back to its original state
list.undo(); // THIS COMMAND FAILS
});
列出具有函数的对象
var List = function () {
this.clipboard = null;
this.head = null;
this.tail = null;
this.head.next = tail;
this.tail.prev = head;
// blahblah typical linked list stuff
};
// Inserts a node in front of the node with nodeId
List.prototype.insertNode = function(node, nodeId) {
this.insertAt(node, nodeId);
var list = this;
this.undoManager.add({
undo: function() {
list.deleteNode(newNode.id);
},
redo: function() {
list.insertNode(node, nodeId);
}
});
return node;
};
// put node at tail
List.prototype.appendNode = function(node) {
this.insertAt(node, null);
var list = this;
this.undoManager.add({
undo: function() {
list.deleteNode(node.id);
},
redo: function() {
list.appendNode(node);
}
});
return node;
};
// delete node with nodeId
List.prototype.deleteNode = function(nodeId) {
var nextId = this.getNextNodeId(nodeId); // returns null if nodeId is at tail
var deletedNode = this.deleteById(nodeId);
var list = this;
this.undoManager.add({
undo: function() {
//special case for handling last node
if(!nextId)
list.appendNode(deletedNode);
else
list.insertNode(deletedNode, nextId);
},
redo: function() {
list.deleteNode(nodeId);
}
});
return deletedNode;
};
// Removes the node with nodeId from list and stores it in clipboard
List.prototype.cutNode = function (nodeId) {
var nextNodeId = this.getNextNodeId(nodeId); // returns null if nodeId is tail
var cuttNode = this.deletedNode(nodeId);
var oldClipboard = this.clipboard;
this.clipboard = cuttNode;
var list = this;
this.undoManager.add({
undo: function() {
if (!nextNodeId) {
list.appendNode(cuttNode);
} else {
list.insertNode(cuttNode, nextNodeId);
}
list.clipboard = oldClipboard;
},
redo: function() {
list.cutNode(nodeId);
}
});
};
// duplicate node with nodeId and store in clipboard
List.prototype.copyNode = function (nodeId) {
var node = this.
var oldClipboard = this.clipboard;
// duplicate() copies the node data to a new node object which generats a new/unique node id
this.clipboard = node.duplicate();
var list = this;
this.undoManager.add({
undo: function() {
list.clipboard = oldClipboard;
},
redo: function() {
list.clipboard = node;
}
});
};
// pastes clipboard node to list before nodeId
List.prototype.pasteNode = function (nodeId) {
if (this.clipboard !== null) {
var pastedNode = this.insertNode(this.clipboard, nodeId);
// just in case we want to paste again, we need a unique node
this.clipboard = pastedNode.duplicate();
var list = this;
this.undoManager.add({
undo: function() {
list.clipboard = list.deleteNode(pastedNode.id);
},
redo: function() {
list.pasteNode(nodeId);
}
});
}
};
karma 测试中的最后一个撤消命令失败并出现以下错误:
Error: Unable to delete node with id 14914926779057942
此节点 ID 属于粘贴操作中的重复节点:this.clipboard = pastedNode.duplicate()
撤消管理器从复制节点的 id 上的 pasteNode 撤消函数调用 deleteNode,而不是 pastedNode。由于复制的节点只存在于剪贴板中,不存在于链表中,因此出错。
我是不是没有正确理解 undo/redo 堆栈? cut/copy/paste的正确写法是什么?
这里的问题是当粘贴函数调用 insertNode
时,撤消管理器的撤消和重做堆栈被双层堆叠。
例如,调用 cutNode 将调用 deleteNode,这将在撤消和重做堆栈上抛出一个命令。然后 cutNode 会在 deleteNode 返回后在两个堆栈上添加另一个层。
我通过在剪切、复制和粘贴调用之间使用 UndoManager 的 getIndex()
函数发现了双堆栈。
我正在使用 undomanager 并尝试在双向链表上实现 cut/copy/paste 功能。首先,这是我的代码。
业力测试脚本:
it('should cut and paste a node with working undo/redo', function () {
var list = listFactory.createList();
var node1 = list.appendNode(
nodeFactory.createNode({
//nodeinfo
})
);
var node2 = list.appendNode(
nodeFactory.createNode({
//nodeinfo
})
);
// here we cut the node2 out of the profile
list.cutNode(node2.id);
expect(list.clipboard.id).toBe(node2.id);
expect(list.getLength()).toBe(2);
// undoing the cut should clear the clipboard and return the node2 to where it was.
list.undo();
expect(list.clipboard).toBe(null);
expect(list.getLength()).toBe(2);
// redoing the cut should remove node2
list.redo();
expect(list.clipboard.id).toBe(node2.id);
expect(list.getLength()).toBe(1);
// pasting node2 in front of node1
list.pasteNode(indexSeg.id);
expect(list.getLength()).toBe(2);
// the first undo should remove node2 from the front
list.undo();
expect(list.getLength()).toBe(1);
// this should reset the list back to its original state
list.undo(); // THIS COMMAND FAILS
});
列出具有函数的对象
var List = function () {
this.clipboard = null;
this.head = null;
this.tail = null;
this.head.next = tail;
this.tail.prev = head;
// blahblah typical linked list stuff
};
// Inserts a node in front of the node with nodeId
List.prototype.insertNode = function(node, nodeId) {
this.insertAt(node, nodeId);
var list = this;
this.undoManager.add({
undo: function() {
list.deleteNode(newNode.id);
},
redo: function() {
list.insertNode(node, nodeId);
}
});
return node;
};
// put node at tail
List.prototype.appendNode = function(node) {
this.insertAt(node, null);
var list = this;
this.undoManager.add({
undo: function() {
list.deleteNode(node.id);
},
redo: function() {
list.appendNode(node);
}
});
return node;
};
// delete node with nodeId
List.prototype.deleteNode = function(nodeId) {
var nextId = this.getNextNodeId(nodeId); // returns null if nodeId is at tail
var deletedNode = this.deleteById(nodeId);
var list = this;
this.undoManager.add({
undo: function() {
//special case for handling last node
if(!nextId)
list.appendNode(deletedNode);
else
list.insertNode(deletedNode, nextId);
},
redo: function() {
list.deleteNode(nodeId);
}
});
return deletedNode;
};
// Removes the node with nodeId from list and stores it in clipboard
List.prototype.cutNode = function (nodeId) {
var nextNodeId = this.getNextNodeId(nodeId); // returns null if nodeId is tail
var cuttNode = this.deletedNode(nodeId);
var oldClipboard = this.clipboard;
this.clipboard = cuttNode;
var list = this;
this.undoManager.add({
undo: function() {
if (!nextNodeId) {
list.appendNode(cuttNode);
} else {
list.insertNode(cuttNode, nextNodeId);
}
list.clipboard = oldClipboard;
},
redo: function() {
list.cutNode(nodeId);
}
});
};
// duplicate node with nodeId and store in clipboard
List.prototype.copyNode = function (nodeId) {
var node = this.
var oldClipboard = this.clipboard;
// duplicate() copies the node data to a new node object which generats a new/unique node id
this.clipboard = node.duplicate();
var list = this;
this.undoManager.add({
undo: function() {
list.clipboard = oldClipboard;
},
redo: function() {
list.clipboard = node;
}
});
};
// pastes clipboard node to list before nodeId
List.prototype.pasteNode = function (nodeId) {
if (this.clipboard !== null) {
var pastedNode = this.insertNode(this.clipboard, nodeId);
// just in case we want to paste again, we need a unique node
this.clipboard = pastedNode.duplicate();
var list = this;
this.undoManager.add({
undo: function() {
list.clipboard = list.deleteNode(pastedNode.id);
},
redo: function() {
list.pasteNode(nodeId);
}
});
}
};
karma 测试中的最后一个撤消命令失败并出现以下错误:
Error: Unable to delete node with id 14914926779057942
此节点 ID 属于粘贴操作中的重复节点:this.clipboard = pastedNode.duplicate()
撤消管理器从复制节点的 id 上的 pasteNode 撤消函数调用 deleteNode,而不是 pastedNode。由于复制的节点只存在于剪贴板中,不存在于链表中,因此出错。
我是不是没有正确理解 undo/redo 堆栈? cut/copy/paste的正确写法是什么?
这里的问题是当粘贴函数调用 insertNode
时,撤消管理器的撤消和重做堆栈被双层堆叠。
例如,调用 cutNode 将调用 deleteNode,这将在撤消和重做堆栈上抛出一个命令。然后 cutNode 会在 deleteNode 返回后在两个堆栈上添加另一个层。
我通过在剪切、复制和粘贴调用之间使用 UndoManager 的 getIndex()
函数发现了双堆栈。