Add batch command and ensure changes to multiple selected elements are atomic in undo/redo

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@248 eee81c28-f429-11dd-99c0-75d572ba1ddd
This commit is contained in:
Jeff Schiller
2009-07-01 21:28:22 +00:00
parent 45bf0fca08
commit 67bcf98e30

View File

@@ -44,6 +44,8 @@ function ChangeElementCommand(elem, attrs, text) {
}
return true;
};
this.elements = function() { return [this.elem]; }
}
function InsertElementCommand(elem, text) {
@@ -57,6 +59,8 @@ function InsertElementCommand(elem, text) {
this.parent = this.elem.parentNode;
this.elem = this.elem.parentNode.removeChild(this.elem);
};
this.elements = function() { return [this.elem]; };
}
function RemoveElementCommand(elem, parent, text) {
@@ -70,6 +74,8 @@ function RemoveElementCommand(elem, parent, text) {
};
this.unapply = function() { this.elem = this.parent.insertBefore(this.elem, this.elem.nextSibling); };
this.elements = function() { return [this.elem]; };
}
function MoveElementCommand(elem, oldNextSibling, oldParent, text) {
@@ -87,15 +93,38 @@ function MoveElementCommand(elem, oldNextSibling, oldParent, text) {
this.unapply = function() {
this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling);
};
this.elements = function() { return [this.elem]; };
}
// TODO: create a 'typing' command object that tracks changes in text
// if a new Typing command is created and the top command on the stack is also a Typing
// and they both affect the same element, then collapse the two commands into one
// TODO: create a 'batch' command object that you can add an arbitrary number of
// commands to (this will be useful for making changes to many elements in a
// multiselection at one, we don't want to have to undo each element's change)
// this command object acts an arbitrary number of subcommands
function BatchCommand(text) {
this.elems = [];
this.text = text || "Batch Command";
this.stack = [];
this.apply = function() {
for (var i = 0; i < this.stack.length; ++i) {
this.stack[i].apply();
}
};
this.unapply = function() {
for (var i = this.stack.length-1; i >= 0; i--) {
this.stack[i].unapply();
}
};
this.elements = function() { return this.elems; };
this.addSubCommand = function(cmd) { this.stack[this.stack.length] = cmd; };
this.isEmpty = function() { return this.stack.length == 0; };
}
function SvgCanvas(c)
{
@@ -227,7 +256,6 @@ function SvgCanvas(c)
this.reset(elem);
};
// TODO: add accessor methods to determine number of currently selected elements
function SelectorManager() {
// this will hold the <g> element that contains all selector rects/grips
@@ -413,6 +441,7 @@ function SvgCanvas(c)
}
undoStack[undoStack.length] = cmd;
undoStackPointer = undoStack.length;
console.log(undoStack);
};
// private functions
@@ -503,6 +532,8 @@ function SvgCanvas(c)
}; // end svgToString()
var recalculateSelectedDimensions = function() {
var text = (current_resize_mode == "none" ? "position" : "size");
var batchCmd = new BatchCommand(text);
for (var i = 0; i < selectedElements.length; ++i) {
var selected = selectedElements[i];
if (selected == null) break;
@@ -601,14 +632,12 @@ function SvgCanvas(c)
console.log("Unknown shape type: " + selected.tagName);
break;
}
// fire changed event
if (changes) {
var text = (current_resize_mode == "none" ? "position" : "size");
// TODO: store these changes in a batch command
addCommandToHistory(new ChangeElementCommand(selected, changes, text));
batchCmd.addSubCommand(new ChangeElementCommand(selected, changes, text));
}
}
// TODO: add the batch command to history
} // for each selected element
if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd);
call("changed", selectedElements);
};
@@ -626,8 +655,6 @@ function SvgCanvas(c)
// public events
// TODO: grab code here and add to addSelection...
this.clearSelection = function() {
if (selectedElements[0] == null) { return; }
@@ -1323,6 +1350,7 @@ function SvgCanvas(c)
};
this.changeSelectedAttribute = function(attr, val) {
var batchCmd = new BatchCommand("Change " + attr);
for (var i = 0; i < selectedElements.length; ++i) {
var selected = selectedElements[i];
if (selected == null) break;
@@ -1335,11 +1363,10 @@ function SvgCanvas(c)
recalculateSelectedOutline();
var changes = {};
changes[attr] = oldval;
// TODO: create a batch command here
addCommandToHistory(new ChangeElementCommand(selected, changes, attr));
batchCmd.addSubCommand(new ChangeElementCommand(selected, changes, attr));
}
}
// TODO: add batch command to history here
if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd);
call("changed", selectedElements);
};
@@ -1352,6 +1379,7 @@ function SvgCanvas(c)
};
this.deleteSelectedElements = function() {
var batchCmd = new BatchCommand("Delete Elements");
for (var i = 0; i < selectedElements.length; ++i) {
var selected = selectedElements[i];
if (selected == null) break;
@@ -1363,9 +1391,9 @@ function SvgCanvas(c)
var elem = parent.removeChild(t);
selectedElements[i] = null;
// TODO: batch all element deletions up into a batch command
addCommandToHistory(new RemoveElementCommand(elem, parent));
batchCmd.addSubCommand(new RemoveElementCommand(elem, parent));
}
// TODO: add batch command to history
if (!batchCmd.isEmpty()) addCommandToHistory(batchCmd);
call("selected", selectedElements);
};
@@ -1413,7 +1441,7 @@ function SvgCanvas(c)
this.clearSelection();
var cmd = undoStack[--undoStackPointer];
cmd.unapply();
call("changed", [cmd.elem]);
call("changed", cmd.elements());
}
}
this.redo = function() {
@@ -1421,7 +1449,7 @@ function SvgCanvas(c)
this.clearSelection();
var cmd = undoStack[undoStackPointer++];
cmd.apply();
call("changed", [cmd.elem]);
call("changed", cmd.elements());
}
};