From bbfd88362948fe5d52798353888c26cc0883dc20 Mon Sep 17 00:00:00 2001 From: Neil Fraser Date: Sat, 30 Jan 2016 13:08:47 -0500 Subject: [PATCH] Reduce duplication in Connection.connect. Support shadow statement blocks. Fix race condition. --- core/connection.js | 89 +++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/core/connection.js b/core/connection.js index 71e9d6e0e..67b477ced 100644 --- a/core/connection.js +++ b/core/connection.js @@ -156,54 +156,41 @@ Blockly.Connection.prototype.connect = function(otherConnection) { if (Blockly.OPPOSITE_TYPE[this.type] != otherConnection.type) { throw 'Attempt to connect incompatible types.'; } - if (this.type == Blockly.INPUT_VALUE || this.type == Blockly.OUTPUT_VALUE) { - // Value connections. - if (this.targetConnection) { - // Can't make a value connection if male block is already connected. - throw 'Source connection already connected (value).'; - } else if (otherConnection.targetConnection) { + if (this.targetConnection) { + throw 'Source connection already connected.'; + } + if (otherConnection.targetConnection) { + // Other connection is already connected to something. + var orphanBlock = otherConnection.targetBlock(); + if (orphanBlock.isShadow()) { + orphanBlock.dispose(); + orphanBlock = null; + } else if (this.type == Blockly.INPUT_VALUE || + this.type == Blockly.OUTPUT_VALUE) { + // Value connections. // If female block is already connected, disconnect and bump the male. - var orphanBlock = otherConnection.targetBlock(); orphanBlock.setParent(null); - if (orphanBlock.isShadow()) { - orphanBlock.dispose(); - } else { - if (!orphanBlock.outputConnection) { - throw 'Orphan block does not have an output connection.'; - } - // Attempt to reattach the orphan at the end of the newly inserted - // block. Since this block may be a row, walk down to the end. - var newBlock = this.sourceBlock_; - var connection; - while (connection = Blockly.Connection.singleConnection_( - /** @type {!Blockly.Block} */ (newBlock), orphanBlock)) { - // '=' is intentional in line above. - newBlock = connection.targetBlock(); - if (!newBlock || newBlock.isShadow()) { - orphanBlock.outputConnection.connect(connection); - orphanBlock = null; - break; - } - } - if (orphanBlock) { - // Unable to reattach orphan. Bump it off to the side. - setTimeout(function() { - orphanBlock.outputConnection.bumpAwayFrom_(otherConnection); - }, Blockly.BUMP_DELAY); + if (!orphanBlock.outputConnection) { + throw 'Orphan block does not have an output connection.'; + } + // Attempt to reattach the orphan at the end of the newly inserted + // block. Since this block may be a row, walk down to the end. + var newBlock = this.sourceBlock_; + var connection; + while (connection = Blockly.Connection.singleConnection_( + /** @type {!Blockly.Block} */ (newBlock), orphanBlock)) { + // '=' is intentional in line above. + newBlock = connection.targetBlock(); + if (!newBlock || newBlock.isShadow()) { + orphanBlock.outputConnection.connect(connection); + orphanBlock = null; + break; } } - } - } else { - // Statement connections. - if (this.targetConnection) { - throw 'Source connection already connected (block).'; - } else if (otherConnection.targetConnection) { + } else if (this.type == Blockly.PREVIOUS_STATEMENT) { + // Statement connections. // Statement blocks may be inserted into the middle of a stack. - if (this.type != Blockly.PREVIOUS_STATEMENT) { - throw 'Can only do a mid-stack connection with the top of a block.'; - } // Split the stack. - var orphanBlock = otherConnection.targetBlock(); orphanBlock.setParent(null); if (!orphanBlock.previousConnection) { throw 'Orphan block does not have a previous connection.'; @@ -223,12 +210,18 @@ Blockly.Connection.prototype.connect = function(otherConnection) { break; } } - if (orphanBlock) { - // Unable to reattach orphan. Bump it off to the side. - setTimeout(function() { - orphanBlock.previousConnection.bumpAwayFrom_(otherConnection); - }, Blockly.BUMP_DELAY); - } + } else { + // Type is Blockly.NEXT_STATEMENT. + throw 'Can only do a mid-stack connection with the top of a block.'; + } + if (orphanBlock) { + // Unable to reattach orphan. Bump it off to the side after a moment. + setTimeout(function() { + // Verify orphan hasn't been deleted or reconnected (user on meth). + if (orphanBlock.workspace && !orphanBlock.getParent()) { + orphanBlock.outputConnection.bumpAwayFrom_(otherConnection); + } + }, Blockly.BUMP_DELAY); } }