From f623004b3a675d6eb7afd67610ef74117f71a283 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Wed, 16 May 2018 12:52:12 -0700 Subject: [PATCH 1/3] Small changes --- core/block.js | 7 +++++-- core/block_svg.js | 14 ++++++++++---- core/dragged_connection_manager.js | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/core/block.js b/core/block.js index 5386b4372..3c9988c7c 100644 --- a/core/block.js +++ b/core/block.js @@ -259,6 +259,10 @@ Blockly.Block.prototype.dispose = function(healStack) { // well as corruption of the connection database. Therefore we must // methodically step through the blocks and carefully disassemble them. + if (Blockly.selected == this) { + Blockly.selected = null; + } + // First, dispose of all my children. for (var i = this.childBlocks_.length - 1; i >= 0; i--) { this.childBlocks_[i].dispose(false); @@ -365,7 +369,7 @@ Blockly.Block.prototype.getConnections_ = function(_all) { * @return {Blockly.Connection} The last next connection on the stack, or null. * @package */ -Blockly.Block.prototype.lastConnectionInStack_ = function() { +Blockly.Block.prototype.lastConnectionInStack = function() { var nextConnection = this.nextConnection; while (nextConnection) { var nextBlock = nextConnection.targetBlock(); @@ -1282,7 +1286,6 @@ Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) { case 'input_dummy': input = this.appendDummyInput(element['name']); break; - default: field = Blockly.Field.fromJson(element); diff --git a/core/block_svg.js b/core/block_svg.js index e1fda02f6..313103794 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -36,6 +36,7 @@ goog.require('Blockly.RenderedConnection'); goog.require('Blockly.Tooltip'); goog.require('Blockly.Touch'); goog.require('Blockly.utils'); + goog.require('goog.Timer'); goog.require('goog.asserts'); goog.require('goog.dom'); @@ -320,13 +321,18 @@ Blockly.BlockSvg.prototype.getRelativeToSurfaceXY = function() { */ Blockly.BlockSvg.prototype.moveBy = function(dx, dy) { goog.asserts.assert(!this.parentBlock_, 'Block has parent.'); - var event = new Blockly.Events.BlockMove(this); + var eventsEnabled = Blockly.Events.isEnabled(); + if (eventsEnabled) { + var event = new Blockly.Events.BlockMove(this); + } var xy = this.getRelativeToSurfaceXY(); this.translate(xy.x + dx, xy.y + dy); this.moveConnections_(dx, dy); - event.recordNew(); + if (eventsEnabled) { + event.recordNew(); + Blockly.Events.fire(event); + } this.workspace.resizeContents(); - Blockly.Events.fire(event); }; /** @@ -570,7 +576,7 @@ Blockly.BlockSvg.prototype.createTabList_ = function() { * @private */ Blockly.BlockSvg.prototype.onMouseDown_ = function(e) { - var gesture = this.workspace.getGesture(e); + var gesture = this.workspace && this.workspace.getGesture(e); if (gesture) { gesture.handleBlockStart(e, this); } diff --git a/core/dragged_connection_manager.js b/core/dragged_connection_manager.js index 5763a9a9d..fc5525fd5 100644 --- a/core/dragged_connection_manager.js +++ b/core/dragged_connection_manager.js @@ -215,7 +215,7 @@ Blockly.DraggedConnectionManager.prototype.addHighlighting_ = function() { Blockly.DraggedConnectionManager.prototype.initAvailableConnections_ = function() { var available = this.topBlock_.getConnections_(false); // Also check the last connection on this stack - var lastOnStack = this.topBlock_.lastConnectionInStack_(); + var lastOnStack = this.topBlock_.lastConnectionInStack(); if (lastOnStack && lastOnStack != this.topBlock_.nextConnection) { available.push(lastOnStack); } From 8ead7dabd8b2ff1354a39f8490bcbb80e952d9ca Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Wed, 16 May 2018 14:48:41 -0700 Subject: [PATCH 2/3] Use .textContent setter for field text --- core/field.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/field.js b/core/field.js index e90c2f1bb..ce4ba1919 100644 --- a/core/field.js +++ b/core/field.js @@ -360,10 +360,7 @@ Blockly.Field.prototype.render_ = function() { } // Replace the text. - goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_)); - var textNode = document.createTextNode(this.getDisplayText_()); - this.textElement_.appendChild(textNode); - + this.textElement_.textContent = this.getDisplayText_(); this.updateWidth(); }; From df7f534ad6ed287ecc8d13c4e159138b71ed1e88 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Thu, 17 May 2018 11:05:18 -0700 Subject: [PATCH 3/3] Performance improvements for workspace clear and load --- core/block_svg.js | 30 +++++++++++++++++++++--------- core/workspace.js | 44 ++++++++++++++++++++++++++++---------------- core/xml.js | 15 +++++++++++++++ 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/core/block_svg.js b/core/block_svg.js index 313103794..a073aacf0 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -252,28 +252,40 @@ Blockly.BlockSvg.prototype.getIcons = function() { * @param {Blockly.BlockSvg} newParent New parent block. */ Blockly.BlockSvg.prototype.setParent = function(newParent) { - if (newParent == this.parentBlock_) { + var oldParent = this.parentBlock_; + if (newParent == oldParent) { return; } - var svgRoot = this.getSvgRoot(); - if (this.parentBlock_ && svgRoot) { - // Move this block up the DOM. Keep track of x/y translations. - var xy = this.getRelativeToSurfaceXY(); - this.workspace.getCanvas().appendChild(svgRoot); - svgRoot.setAttribute('transform', 'translate(' + xy.x + ',' + xy.y + ')'); - } Blockly.Field.startCache(); Blockly.BlockSvg.superClass_.setParent.call(this, newParent); Blockly.Field.stopCache(); + var svgRoot = this.getSvgRoot(); + + // Bail early if workspace is clearing, or we aren't rendered. + // We won't need to reattach ourselves anywhere. + if (this.workspace.isClearing || !svgRoot) { + return; + } + + var oldXY = this.getRelativeToSurfaceXY(); if (newParent) { - var oldXY = this.getRelativeToSurfaceXY(); newParent.getSvgRoot().appendChild(svgRoot); var newXY = this.getRelativeToSurfaceXY(); // Move the connections to match the child's new position. this.moveConnections_(newXY.x - oldXY.x, newXY.y - oldXY.y); } + // If we are losing a parent, we want to move our DOM element to the + // root of the workspace. + else if (oldParent) { + // Avoid moving a block up the DOM if it's currently selected/dragging, + // so as to avoid taking things off the drag surface. + if (Blockly.selected != this) { + this.workspace.getCanvas().appendChild(svgRoot); + this.translate(oldXY.x, oldXY.y); + } + } }; /** diff --git a/core/workspace.js b/core/workspace.js index 13815f7d2..2bb088c52 100644 --- a/core/workspace.js +++ b/core/workspace.js @@ -115,6 +115,13 @@ Blockly.Workspace = function(opt_options) { */ Blockly.Workspace.prototype.rendered = false; +/** + * Returns `true` if the workspace is currently in the process of a bulk clear. + * @type {boolean} + * @package + */ +Blockly.Workspace.prototype.isClearing = false; + /** * Maximum number of undo events in stack. `0` turns off undo, `Infinity` sets it to unlimited. * @type {number} @@ -264,22 +271,27 @@ Blockly.Workspace.prototype.getAllBlocks = function(ordered) { * Dispose of all blocks and comments in workspace. */ Blockly.Workspace.prototype.clear = function() { - var existingGroup = Blockly.Events.getGroup(); - if (!existingGroup) { - Blockly.Events.setGroup(true); - } - while (this.topBlocks_.length) { - this.topBlocks_[0].dispose(); - } - while (this.topComments_.length) { - this.topComments_[this.topComments_.length - 1].dispose(); - } - if (!existingGroup) { - Blockly.Events.setGroup(false); - } - this.variableMap_.clear(); - if (this.potentialVariableMap_) { - this.potentialVariableMap_.clear(); + this.isClearing = true; + try { + var existingGroup = Blockly.Events.getGroup(); + if (!existingGroup) { + Blockly.Events.setGroup(true); + } + while (this.topBlocks_.length) { + this.topBlocks_[0].dispose(); + } + while (this.topComments_.length) { + this.topComments_[this.topComments_.length - 1].dispose(); + } + if (!existingGroup) { + Blockly.Events.setGroup(false); + } + this.variableMap_.clear(); + if (this.potentialVariableMap_) { + this.potentialVariableMap_.clear(); + } + } finally { + this.isClearing = false; } }; diff --git a/core/xml.js b/core/xml.js index 15199c1ac..744274629 100644 --- a/core/xml.js +++ b/core/xml.js @@ -364,6 +364,21 @@ Blockly.Xml.textToDom = function(text) { return dom.firstChild; }; +/** + * Clear the given workspace then decode an XML DOM and + * create blocks on the workspace. + * @param {!Element} xml XML DOM. + * @param {!Blockly.Workspace} workspace The workspace. + * @return {Array.} An array containing new block ids. + */ +Blockly.Xml.clearWorkspaceAndLoadFromXml = function(xml, workspace) { + workspace.setResizesEnabled(false); + workspace.clear(); + var blockIds = Blockly.Xml.domToWorkspace(xml, workspace); + workspace.setResizesEnabled(true); + return blockIds; +}; + /** * Decode an XML DOM and create blocks on the workspace. * @param {!Element} xml XML DOM.