Group mutations into same event.

This commit is contained in:
Neil Fraser 2016-03-06 18:32:20 -08:00
parent 02d60a2dbe
commit 55784580e9
4 changed files with 52 additions and 24 deletions

View file

@ -227,12 +227,12 @@ Blockly.BlockSvg.terminateDrag_ = function() {
Blockly.Events.setGroup(group);
selected.snapToGrid();
Blockly.Events.setGroup(false);
}, Blockly.BUMP_DELAY / 2)
}, Blockly.BUMP_DELAY / 2);
setTimeout(function() {
Blockly.Events.setGroup(group);
selected.bumpNeighbours_();
Blockly.Events.setGroup(false);
}, Blockly.BUMP_DELAY)
}, Blockly.BUMP_DELAY);
// Fire an event to allow scrollbars to resize.
Blockly.fireUiEvent(window, 'resize');
}

View file

@ -97,7 +97,7 @@ Blockly.Events.fire = function(event) {
* @private
*/
Blockly.Events.fireNow_ = function() {
var queue = Blockly.Events.filter_(Blockly.Events.FIRE_QUEUE_);
var queue = Blockly.Events.filter(Blockly.Events.FIRE_QUEUE_);
Blockly.Events.FIRE_QUEUE_.length = 0;
for (var i = 0, event; event = queue[i]; i++) {
var workspace = Blockly.Workspace.getById(event.workspaceId);
@ -111,9 +111,8 @@ Blockly.Events.fireNow_ = function() {
* Filter the queued events and merge duplicates.
* @param {!Array.<!Blockly.Events.Abstract>} queueIn Array of events.
* @return {!Array.<!Blockly.Events.Abstract>} Array of filtered events.
* @private
*/
Blockly.Events.filter_ = function(queueIn) {
Blockly.Events.filter = function(queueIn) {
var queue = goog.array.clone(queueIn);
// Merge duplicates. O(n^2), but n should be very small.
for (var i = 0, event1; event1 = queue[i]; i++) {
@ -145,6 +144,14 @@ Blockly.Events.filter_ = function(queueIn) {
queue.splice(i, 1);
}
}
// Move mutation events to the top of the queue.
// Intentionally skip first event.
for (var i = 1, event; event = queue[i]; i++) {
if (event.type == Blockly.Events.CHANGE &&
event.element == 'mutation') {
queue.unshift(queue.splice(i, 1)[0]);
}
}
return queue;
};
@ -335,6 +342,8 @@ Blockly.Events.Change.prototype.run = function(forward) {
var field = block.getField(this.name);
if (field) {
field.setValue(value);
} else {
console.warn("Can't set non-existant field: " + this.name);
}
break;
case 'comment':
@ -354,10 +363,17 @@ Blockly.Events.Change.prototype.run = function(forward) {
// Close the mutator (if open) since we don't want to update it.
block.mutator.setVisible(false);
}
var oldMutation = '';
if (block.mutationToDom) {
var oldMutationDom = block.mutationToDom();
oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom);
}
if (block.domToMutation) {
var dom = Blockly.Xml.textToDom('<xml>' + value + '</xml>');
block.domToMutation(dom.firstChild);
}
Blockly.Events.fire(new Blockly.Events.Change(
block, 'mutation', null, oldMutation, value));
break;
}
};
@ -457,6 +473,8 @@ Blockly.Events.Move.prototype.run = function(forward) {
var input = parentBlock.getInput(inputName);
if (input) {
parentConnection = input.connection;
} else {
console.warn("Can't connect to non-existant input: " + inputName);
}
} else if (blockConnection.type == Blockly.PREVIOUS_STATEMENT) {
parentConnection = parentBlock.nextConnection;
@ -466,4 +484,3 @@ Blockly.Events.Move.prototype.run = function(forward) {
}
}
};

View file

@ -280,29 +280,36 @@ Blockly.Mutator.prototype.workspaceChanged_ = function() {
// When the mutator's workspace changes, update the source block.
if (this.rootBlock_.workspace == this.workspace_) {
var oldMutationDom = this.block_.mutationToDom();
Blockly.Events.setGroup(true);
var block = this.block_;
var oldMutationDom = block.mutationToDom();
var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom);
// Switch off rendering while the source block is rebuilt.
var savedRendered = this.block_.rendered;
this.block_.rendered = false;
var savedRendered = block.rendered;
block.rendered = false;
// Allow the source block to rebuild itself.
this.block_.compose(this.rootBlock_);
block.compose(this.rootBlock_);
// Restore rendering and show the changes.
this.block_.rendered = savedRendered;
block.rendered = savedRendered;
// Mutation may have added some elements that need initalizing.
this.block_.initSvg();
var newMutationDom = this.block_.mutationToDom();
block.initSvg();
var newMutationDom = block.mutationToDom();
var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom);
if (oldMutation != newMutation) {
Blockly.Events.fire(new Blockly.Events.Change(
this.block_, 'mutation', null, oldMutation, newMutation));
goog.Timer.callOnce(
this.block_.bumpNeighbours_, Blockly.BUMP_DELAY, this.block_);
block, 'mutation', null, oldMutation, newMutation));
// Ensure that any bump is part of this mutation's event group.
var group = Blockly.Events.getGroup();
setTimeout(function() {
Blockly.Events.setGroup(group);
block.bumpNeighbours_();
}, Blockly.BUMP_DELAY);
}
if (this.block_.rendered) {
this.block_.render();
if (block.rendered) {
block.render();
}
this.resizeBubble_();
Blockly.Events.setGroup(false);
}
};

View file

@ -214,15 +214,19 @@ Blockly.Workspace.prototype.undo = function(redo) {
if (!event) {
return;
}
Blockly.Events.recordUndo = false;
event.run(redo);
Blockly.Events.recordUndo = true;
(redo ? this.undoStack_ : this.redoStack_).push(event);
var events = [event];
// Do another undo/redo if the next one is of the same group.
if (sourceStack.length && event.group &&
while (sourceStack.length && event.group &&
event.group == sourceStack[sourceStack.length - 1].group) {
this.undo(redo);
events.push(sourceStack.pop());
}
events = Blockly.Events.filter(events);
Blockly.Events.recordUndo = false;
for (var i = 0, event; event = events[i]; i++) {
event.run(redo);
(redo ? this.undoStack_ : this.redoStack_).push(event);
}
Blockly.Events.recordUndo = true;
};
/**