diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 66cc9b953..42b42685c 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -371,8 +371,13 @@ class Blocks { if (e.isLocal && editingTarget && !editingTarget.isStage && !e.isCloud) { if (!editingTarget.lookupVariableById(e.varId)) { editingTarget.createVariable(e.varId, e.varName, e.varType); + this.emitProjectChanged(); } } else { + if (stage.lookupVariableById(e.varId)) { + // Do not re-create a variable if it already exists + return; + } // Check for name conflicts in all of the targets const allTargets = this.runtime.targets.filter(t => t.isOriginal); for (const target of allTargets) { @@ -381,6 +386,7 @@ class Blocks { } } stage.createVariable(e.varId, e.varName, e.varType, e.isCloud); + this.emitProjectChanged(); } break; case 'var_rename': @@ -400,11 +406,13 @@ class Blocks { currTarget.blocks.updateBlocksAfterVarRename(e.varId, e.newName); } } + this.emitProjectChanged(); break; case 'var_delete': { const target = (editingTarget && editingTarget.variables.hasOwnProperty(e.varId)) ? editingTarget : stage; target.deleteVariable(e.varId); + this.emitProjectChanged(); break; } case 'comment_create': @@ -425,6 +433,7 @@ class Blocks { currTarget.comments[e.commentId].y = e.xy.y; } } + this.emitProjectChanged(); break; case 'comment_change': if (this.runtime.getEditingTarget()) { @@ -445,6 +454,7 @@ class Blocks { if (change.hasOwnProperty('text')) { comment.text = change.text; } + this.emitProjectChanged(); } break; case 'comment_move': @@ -458,6 +468,8 @@ class Blocks { const newCoord = e.newCoordinate_; comment.x = newCoord.x; comment.y = newCoord.y; + + this.emitProjectChanged(); } break; case 'comment_delete': @@ -479,13 +491,11 @@ class Blocks { } delete block.comment; } + + this.emitProjectChanged(); } break; } - - // forceNoGlow is set to true on containers that don't affect the project serialization, - // e.g., the toolbox or monitor containers. - if (!this.forceNoGlow) this.runtime.emitProjectChanged(); } // --------------------------------------------------------------------- @@ -501,6 +511,16 @@ class Blocks { this._cache._monitored = null; } + /** + * Emit a project changed event if this is a block container + * that can affect the project state. + */ + emitProjectChanged () { + if (!this.forceNoGlow) { + this.runtime.emitProjectChanged(); + } + } + /** * Block management: create blocks and scripts from a `create` event * @param {!object} block Blockly create event to be processed @@ -521,6 +541,10 @@ class Blocks { } this.resetCache(); + + // A new block was actually added to the block container, + // emit a project changed event + this.emitProjectChanged(); } /** @@ -659,6 +683,10 @@ class Blocks { } } + // TODO maybe track actual changes, + // but for now, emit a project change always + this.emitProjectChanged(); + this.resetCache(); } @@ -671,10 +699,19 @@ class Blocks { return; } + const block = this._blocks[e.id]; + // Track whether a change actually occurred + // ignoring changes like routine re-positioning + // of a block when loading a workspace + let didChange = false; + // Move coordinate changes. if (e.newCoordinate) { - this._blocks[e.id].x = e.newCoordinate.x; - this._blocks[e.id].y = e.newCoordinate.y; + + didChange = (block.x !== e.newCoordinate.x) || (block.y !== e.newCoordinate.y); + + block.x = e.newCoordinate.x; + block.y = e.newCoordinate.y; } // Remove from any old parent. @@ -689,9 +726,10 @@ class Blocks { oldParent.next = null; } this._blocks[e.id].parent = null; + didChange = true; } - // Has the block become a top-level block? + // Is this block a top-level block? if (typeof e.newParent === 'undefined') { this._addScript(e.id); } else { @@ -715,8 +753,11 @@ class Blocks { }; } this._blocks[e.id].parent = e.newParent; + didChange = true; } this.resetCache(); + + if (didChange) this.emitProjectChanged(); } @@ -784,6 +825,7 @@ class Blocks { delete this._blocks[blockId]; this.resetCache(); + this.emitProjectChanged(); } /**