mirror of
https://github.com/google/blockly.git
synced 2025-12-16 06:10:12 +01:00
Refactor connect logic (#4880)
* Refactor connect logic. * Fixup from rebase * Fix build * PR Comments
This commit is contained in:
@@ -575,20 +575,21 @@ Blockly.Block.prototype.getConnections_ = function(_all) {
|
||||
|
||||
/**
|
||||
* Walks down a stack of blocks and finds the last next connection on the stack.
|
||||
* @param {boolean} ignoreShadows If true,the last connection on a non-shadow
|
||||
* block will be returned. If false, this will follow shadows to find the
|
||||
* last connection.
|
||||
* @return {?Blockly.Connection} The last next connection on the stack, or null.
|
||||
* @package
|
||||
*/
|
||||
Blockly.Block.prototype.lastConnectionInStack = function() {
|
||||
Blockly.Block.prototype.lastConnectionInStack = function(ignoreShadows) {
|
||||
var nextConnection = this.nextConnection;
|
||||
while (nextConnection) {
|
||||
var nextBlock = nextConnection.targetBlock();
|
||||
if (!nextBlock) {
|
||||
// Found a next connection with nothing on the other side.
|
||||
if (!nextBlock || (ignoreShadows && nextBlock.isShadow())) {
|
||||
return nextConnection;
|
||||
}
|
||||
nextConnection = nextBlock.nextConnection;
|
||||
}
|
||||
// Ran out of next connections.
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -607,7 +608,6 @@ Blockly.Block.prototype.bumpNeighbours = function() {
|
||||
* @return {?Blockly.Block} The block (if any) that holds the current block.
|
||||
*/
|
||||
Blockly.Block.prototype.getParent = function() {
|
||||
// Look at the DOM to see if we are nested in another block.
|
||||
return this.parentBlock_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1475,14 +1475,18 @@ Blockly.BlockSvg.prototype.getConnections_ = function(all) {
|
||||
|
||||
/**
|
||||
* Walks down a stack of blocks and finds the last next connection on the stack.
|
||||
* @param {boolean} ignoreShadows If true,the last connection on a non-shadow
|
||||
* block will be returned. If false, this will follow shadows to find the
|
||||
* last connection.
|
||||
* @return {?Blockly.RenderedConnection} The last next connection on the stack,
|
||||
* or null.
|
||||
* @package
|
||||
* @override
|
||||
*/
|
||||
Blockly.BlockSvg.prototype.lastConnectionInStack = function() {
|
||||
Blockly.BlockSvg.prototype.lastConnectionInStack = function(ignoreShadows) {
|
||||
return /** @type {Blockly.RenderedConnection} */ (
|
||||
Blockly.BlockSvg.superClass_.lastConnectionInStack.call(this));
|
||||
Blockly.BlockSvg.superClass_
|
||||
.lastConnectionInStack.call(this, ignoreShadows));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -104,106 +104,58 @@ Blockly.Connection.prototype.y = 0;
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Connection.prototype.connect_ = function(childConnection) {
|
||||
var INPUT = Blockly.connectionTypes.INPUT_VALUE;
|
||||
var parentConnection = this;
|
||||
var parentBlock = parentConnection.getSourceBlock();
|
||||
var childBlock = childConnection.getSourceBlock();
|
||||
// Disconnect any existing parent on the child connection.
|
||||
|
||||
// Make sure the childConnection is available.
|
||||
if (childConnection.isConnected()) {
|
||||
childConnection.disconnect();
|
||||
}
|
||||
|
||||
// Make sure the parentConnection is available.
|
||||
var orphan;
|
||||
if (parentConnection.isConnected()) {
|
||||
// Other connection is already connected to something.
|
||||
// Disconnect it and reattach it or bump it as needed.
|
||||
var orphanBlock = parentConnection.targetBlock();
|
||||
var shadowDom = parentConnection.getShadowDom();
|
||||
// Temporarily set the shadow DOM to null so it does not respawn.
|
||||
parentConnection.shadowDom_ = null;
|
||||
// Displaced shadow blocks dissolve rather than reattaching or bumping.
|
||||
if (orphanBlock.isShadow()) {
|
||||
// Save the shadow block so that field values are preserved.
|
||||
// This cast assumes that a block can not be both a shadow block and an insertion marker.
|
||||
shadowDom = /** @type {!Element} */ (Blockly.Xml.blockToDom(orphanBlock));
|
||||
orphanBlock.dispose(false);
|
||||
orphanBlock = null;
|
||||
} else if (parentConnection.type == Blockly.connectionTypes.INPUT_VALUE) {
|
||||
// Value connections.
|
||||
// If female block is already connected, disconnect and bump the male.
|
||||
if (!orphanBlock.outputConnection) {
|
||||
throw Error('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
|
||||
// or to the first (and only) shadow block.
|
||||
var connection = Blockly.Connection.getConnectionForOrphanedOutput(
|
||||
childBlock, orphanBlock);
|
||||
if (connection) {
|
||||
orphanBlock.outputConnection.connect(connection);
|
||||
orphanBlock = null;
|
||||
}
|
||||
} else if (
|
||||
parentConnection.type == Blockly.connectionTypes.NEXT_STATEMENT) {
|
||||
// Statement connections.
|
||||
// Statement blocks may be inserted into the middle of a stack.
|
||||
// Split the stack.
|
||||
if (!orphanBlock.previousConnection) {
|
||||
throw Error('Orphan block does not have a previous connection.');
|
||||
}
|
||||
// Attempt to reattach the orphan at the bottom of the newly inserted
|
||||
// block. Since this block may be a stack, walk down to the end.
|
||||
var newBlock = childBlock;
|
||||
while (newBlock.nextConnection) {
|
||||
var nextBlock = newBlock.getNextBlock();
|
||||
if (nextBlock && !nextBlock.isShadow()) {
|
||||
newBlock = nextBlock;
|
||||
} else {
|
||||
var checker = orphanBlock.workspace.connectionChecker;
|
||||
if (checker.canConnect(
|
||||
orphanBlock.previousConnection, newBlock.nextConnection, false)) {
|
||||
newBlock.nextConnection.connect(orphanBlock.previousConnection);
|
||||
orphanBlock = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (orphanBlock) {
|
||||
// Unable to reattach orphan.
|
||||
var shadowDom = parentConnection.getShadowDom(true);
|
||||
parentConnection.shadowDom_ = null; // Set to null so it doesn't respawn.
|
||||
var target = parentConnection.targetBlock();
|
||||
if (target.isShadow()) {
|
||||
target.dispose(false);
|
||||
} else {
|
||||
parentConnection.disconnect();
|
||||
if (Blockly.Events.recordUndo) {
|
||||
// Bump it off to the side after a moment.
|
||||
var group = Blockly.Events.getGroup();
|
||||
setTimeout(function() {
|
||||
// Verify orphan hasn't been deleted or reconnected.
|
||||
if (orphanBlock.workspace && !orphanBlock.getParent()) {
|
||||
Blockly.Events.setGroup(group);
|
||||
if (orphanBlock.outputConnection) {
|
||||
orphanBlock.outputConnection.onFailedConnect(parentConnection);
|
||||
} else if (orphanBlock.previousConnection) {
|
||||
orphanBlock.previousConnection.onFailedConnect(parentConnection);
|
||||
}
|
||||
Blockly.Events.setGroup(false);
|
||||
}
|
||||
}, Blockly.BUMP_DELAY);
|
||||
}
|
||||
orphan = target;
|
||||
}
|
||||
// Restore the shadow DOM.
|
||||
parentConnection.shadowDom_ = shadowDom;
|
||||
}
|
||||
|
||||
// Connect the new connection to the parent.
|
||||
var event;
|
||||
if (Blockly.Events.isEnabled()) {
|
||||
event = new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(childBlock);
|
||||
}
|
||||
// Establish the connections.
|
||||
Blockly.Connection.connectReciprocally_(parentConnection, childConnection);
|
||||
// Demote the inferior block so that one is a child of the superior one.
|
||||
childBlock.setParent(parentBlock);
|
||||
if (event) {
|
||||
event.recordNew();
|
||||
Blockly.Events.fire(event);
|
||||
}
|
||||
|
||||
// Deal with the orphan if it exists.
|
||||
if (orphan) {
|
||||
var orphanConnection = parentConnection.type === INPUT ?
|
||||
orphan.outputConnection : orphan.previousConnection;
|
||||
var connection = Blockly.Connection.getConnectionForOrphanedConnection(
|
||||
childBlock, /** @type {!Blockly.Connection} */ (orphanConnection));
|
||||
if (connection) {
|
||||
orphanConnection.connect(connection);
|
||||
} else {
|
||||
orphanConnection.onFailedConnect(parentConnection);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dispose of this connection and deal with connected blocks.
|
||||
* @package
|
||||
@@ -318,7 +270,8 @@ Blockly.Connection.prototype.isConnectionAllowed = function(candidate) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Behavior after a connection attempt fails.
|
||||
* Called when an attempted connection fails. NOP by default (i.e. for headless
|
||||
* workspaces).
|
||||
* @param {!Blockly.Connection} _otherConnection Connection that this connection
|
||||
* failed to connect to.
|
||||
* @package
|
||||
@@ -409,9 +362,9 @@ Blockly.Connection.getSingleConnection_ = function(block, orphanBlock) {
|
||||
* @param {!Blockly.Block} orphanBlock The block that is looking for a home.
|
||||
* @return {?Blockly.Connection} The suitable connection point on the chain
|
||||
* of blocks, or null.
|
||||
* @package
|
||||
* @private
|
||||
*/
|
||||
Blockly.Connection.getConnectionForOrphanedOutput =
|
||||
Blockly.Connection.getConnectionForOrphanedOutput_ =
|
||||
function(startBlock, orphanBlock) {
|
||||
var newBlock = startBlock;
|
||||
var connection;
|
||||
@@ -425,6 +378,32 @@ Blockly.Connection.getConnectionForOrphanedOutput =
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the connection (starting at the startBlock) which will accept
|
||||
* the given connection. This includes compatible connection types and
|
||||
* connection checks.
|
||||
* @param {!Blockly.Block} startBlock The block on which to start the search.
|
||||
* @param {!Blockly.Connection} orphanConnection The connection that is looking
|
||||
* for a home.
|
||||
* @return {?Blockly.Connection} The suitable connection point on the chain of
|
||||
* blocks, or null.
|
||||
*/
|
||||
Blockly.Connection.getConnectionForOrphanedConnection =
|
||||
function(startBlock, orphanConnection) {
|
||||
if (orphanConnection.type === Blockly.connectionTypes.OUTPUT_VALUE) {
|
||||
return Blockly.Connection.getConnectionForOrphanedOutput_(
|
||||
startBlock, orphanConnection.getSourceBlock());
|
||||
}
|
||||
// Otherwise we're dealing with a stack.
|
||||
var connection = startBlock.lastConnectionInStack(true);
|
||||
var checker = orphanConnection.getConnectionChecker();
|
||||
if (connection &&
|
||||
checker.canConnect(orphanConnection, connection, false)) {
|
||||
return connection;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Disconnect this connection.
|
||||
*/
|
||||
@@ -614,11 +593,18 @@ Blockly.Connection.prototype.setShadowDom = function(shadow) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the XML representation of the connection's shadow block.
|
||||
* Returns the xml representation of the connection's shadow block.
|
||||
* @param {boolean=} returnCurrent If true, and the shadow block is currently
|
||||
* attached to this connection, this serializes the state of that block
|
||||
* and returns it (so that field values are correct). Otherwise the saved
|
||||
* shadowDom is just returned.
|
||||
* @return {?Element} Shadow DOM representation of a block or null.
|
||||
*/
|
||||
Blockly.Connection.prototype.getShadowDom = function() {
|
||||
return this.shadowDom_;
|
||||
Blockly.Connection.prototype.getShadowDom = function(returnCurrent) {
|
||||
return (returnCurrent && this.targetBlock().isShadow()) ?
|
||||
/** @type {!Element} */ (Blockly.Xml.blockToDom(
|
||||
/** @type {!Blockly.Block} */ (this.targetBlock()))) :
|
||||
this.shadowDom_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -331,7 +331,7 @@ Blockly.InsertionMarkerManager.prototype.createMarkerBlock_ = function(sourceBlo
|
||||
Blockly.InsertionMarkerManager.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(true);
|
||||
if (lastOnStack && lastOnStack != this.topBlock_.nextConnection) {
|
||||
available.push(lastOnStack);
|
||||
this.lastOnStack_ = lastOnStack;
|
||||
|
||||
@@ -449,14 +449,26 @@ Blockly.RenderedConnection.prototype.isConnectionAllowed = function(candidate,
|
||||
|
||||
/**
|
||||
* Behavior after a connection attempt fails.
|
||||
* Bumps this connection away from the other connection. Called when an
|
||||
* attempted connection fails.
|
||||
* @param {!Blockly.Connection} otherConnection Connection that this connection
|
||||
* failed to connect to.
|
||||
* @package
|
||||
*/
|
||||
Blockly.RenderedConnection.prototype.onFailedConnect = function(
|
||||
otherConnection) {
|
||||
this.bumpAwayFrom(otherConnection);
|
||||
};
|
||||
Blockly.RenderedConnection.prototype.onFailedConnect =
|
||||
function(otherConnection) {
|
||||
var block = this.getSourceBlock();
|
||||
if (Blockly.Events.recordUndo) {
|
||||
var group = Blockly.Events.getGroup();
|
||||
setTimeout(function() {
|
||||
if (!block.isDisposed() && !block.getParent()) {
|
||||
Blockly.Events.setGroup(group);
|
||||
this.bumpAwayFrom(otherConnection);
|
||||
Blockly.Events.setGroup(false);
|
||||
}
|
||||
}.bind(this), Blockly.BUMP_DELAY);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -246,23 +246,11 @@ Blockly.blockRendering.Renderer.prototype.shouldHighlightConnection =
|
||||
*/
|
||||
Blockly.blockRendering.Renderer.prototype.orphanCanConnectAtEnd =
|
||||
function(topBlock, orphanBlock, localType) {
|
||||
var orphanConnection = null;
|
||||
var lastConnection = null;
|
||||
if (localType == Blockly.connectionTypes.OUTPUT_VALUE) {
|
||||
orphanConnection = orphanBlock.outputConnection;
|
||||
lastConnection =
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(
|
||||
/** @type {!Blockly.Block} **/ (topBlock), orphanBlock);
|
||||
} else {
|
||||
orphanConnection = orphanBlock.previousConnection;
|
||||
lastConnection = topBlock.lastConnectionInStack();
|
||||
}
|
||||
|
||||
if (!lastConnection) {
|
||||
return false;
|
||||
}
|
||||
return orphanConnection.getConnectionChecker().canConnect(
|
||||
lastConnection, orphanConnection, false);
|
||||
var orphanConnection = localType === Blockly.connectionTypes.OUTPUT_VALUE ?
|
||||
orphanBlock.outputConnection : orphanBlock.previousConnection;
|
||||
return !!Blockly.Connection.getConnectionForOrphanedConnection(
|
||||
/** @type {!Blockly.Block} **/ (topBlock),
|
||||
/** @type {!Blockly.Connection} **/ (orphanConnection));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
64
package-lock.json
generated
64
package-lock.json
generated
@@ -248,15 +248,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz",
|
||||
"integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==",
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz",
|
||||
"integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.1.1",
|
||||
"espree": "^7.3.0",
|
||||
"globals": "^12.1.0",
|
||||
"globals": "^13.9.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.2.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
@@ -265,12 +265,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"globals": {
|
||||
"version": "12.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
|
||||
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
|
||||
"version": "13.9.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz",
|
||||
"integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-fest": "^0.8.1"
|
||||
"type-fest": "^0.20.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2650,13 +2650,13 @@
|
||||
}
|
||||
},
|
||||
"eslint": {
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.27.0.tgz",
|
||||
"integrity": "sha512-JZuR6La2ZF0UD384lcbnd0Cgg6QJjiCwhMD6eU4h/VGPcVGwawNNzKU41tgokGXnfjOOyI6QIffthhJTPzzuRA==",
|
||||
"version": "7.28.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz",
|
||||
"integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "7.12.11",
|
||||
"@eslint/eslintrc": "^0.4.1",
|
||||
"@eslint/eslintrc": "^0.4.2",
|
||||
"ajv": "^6.10.0",
|
||||
"chalk": "^4.0.0",
|
||||
"cross-spawn": "^7.0.2",
|
||||
@@ -2673,7 +2673,7 @@
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"file-entry-cache": "^6.0.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^5.0.0",
|
||||
"glob-parent": "^5.1.2",
|
||||
"globals": "^13.6.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.0.0",
|
||||
@@ -2706,18 +2706,18 @@
|
||||
}
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
|
||||
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
|
||||
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
|
||||
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
|
||||
"version": "7.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz",
|
||||
"integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-validator-identifier": "^7.14.0",
|
||||
"@babel/helper-validator-identifier": "^7.14.5",
|
||||
"chalk": "^2.0.0",
|
||||
"js-tokens": "^4.0.0"
|
||||
},
|
||||
@@ -2899,12 +2899,6 @@
|
||||
"requires": {
|
||||
"prelude-ls": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -7219,9 +7213,9 @@
|
||||
}
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
|
||||
"integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
|
||||
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
|
||||
"dev": true
|
||||
},
|
||||
"registry-auth-token": {
|
||||
@@ -8327,9 +8321,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "8.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.5.0.tgz",
|
||||
"integrity": "sha512-Y2l399Tt1AguU3BPRP9Fn4eN+Or+StUGWCUpbnFyXSo8NZ9S4uj+AG2pjs5apK+ZMOwYOz1+a+VKvKH7CudXgQ==",
|
||||
"version": "8.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz",
|
||||
"integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
@@ -8661,9 +8655,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
|
||||
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
|
||||
"dev": true
|
||||
},
|
||||
"typedarray": {
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"chai": "^4.2.0",
|
||||
"clang-format": "^1.5.0",
|
||||
"concurrently": "^6.0.0",
|
||||
"eslint": "^7.6.0",
|
||||
"eslint": "^7.28.0",
|
||||
"google-closure-compiler": "^20210505.0.0",
|
||||
"google-closure-deps": "^20210406.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
|
||||
@@ -782,329 +782,6 @@ suite('Connection', function() {
|
||||
});
|
||||
});
|
||||
|
||||
suite('getConnectionForOrphanedOutput', function() {
|
||||
setup(function() {
|
||||
this.workspace = new Blockly.Workspace();
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([
|
||||
{
|
||||
'type': 'input',
|
||||
'message0': '%1',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT',
|
||||
'check': 'check'
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
'type': 'output',
|
||||
'message0': '',
|
||||
'output': 'check',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
workspaceTeardown.call(this, this.workspace);
|
||||
});
|
||||
|
||||
suite('No available spots', function() {
|
||||
setup(function() {
|
||||
Blockly.defineBlocksWithJsonArray([
|
||||
{
|
||||
'type': 'output_and_statements',
|
||||
'message0': '%1 %2',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_statement',
|
||||
'name': 'INPUT',
|
||||
'check': 'check'
|
||||
},
|
||||
{
|
||||
'type': 'input_statement',
|
||||
'name': 'INPUT2',
|
||||
'check': 'check'
|
||||
}
|
||||
],
|
||||
'output': 'check',
|
||||
},
|
||||
{
|
||||
'type': 'output_and_inputs',
|
||||
'message0': '%1 %2',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT',
|
||||
'check': 'check2'
|
||||
},
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT2',
|
||||
'check': 'check2'
|
||||
}
|
||||
],
|
||||
'output': 'check',
|
||||
},
|
||||
{
|
||||
'type': 'check_to_check2',
|
||||
'message0': '%1',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT',
|
||||
'check': 'check2'
|
||||
},
|
||||
],
|
||||
'output': 'check',
|
||||
},
|
||||
{
|
||||
'type': 'check2_to_check',
|
||||
'message0': '%1',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'CHECK2TOCHECKINPUT',
|
||||
'check': 'check'
|
||||
},
|
||||
],
|
||||
'output': 'check2',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('No connection', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('output');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
|
||||
test('All statements', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('output_and_statements');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
|
||||
test('Bad checks', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('output_and_inputs');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
|
||||
test('Through different types', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('check_to_check2');
|
||||
const otherChild = this.workspace.newBlock('check2_to_check');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
oldChild.getInput('INPUT').connection
|
||||
.connect(otherChild.outputConnection);
|
||||
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Multiple available spots', function() {
|
||||
setup(function() {
|
||||
Blockly.defineBlocksWithJsonArray([
|
||||
{
|
||||
'type': 'multiple_inputs',
|
||||
'message0': '%1 %2',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT',
|
||||
'check': 'check'
|
||||
},
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT2',
|
||||
'check': 'check'
|
||||
},
|
||||
],
|
||||
'output': 'check',
|
||||
},
|
||||
{
|
||||
'type': 'single_input',
|
||||
'message0': '%1',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT',
|
||||
'check': 'check'
|
||||
},
|
||||
],
|
||||
'output': 'check',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
suite('No shadows', function() {
|
||||
test('Top block', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('multiple_inputs');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
|
||||
test('Child blocks', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('multiple_inputs');
|
||||
const childX = this.workspace.newBlock('single_input');
|
||||
const childY = this.workspace.newBlock('single_input');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
oldChild.getInput('INPUT').connection.connect(childX.outputConnection);
|
||||
oldChild.getInput('INPUT2').connection.connect(childY.outputConnection);
|
||||
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
|
||||
test('Spots filled', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('multiple_inputs');
|
||||
const otherChild = this.workspace.newBlock('output');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
oldChild.getInput('INPUT').connection
|
||||
.connect(otherChild.outputConnection);
|
||||
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Shadows', function() {
|
||||
test('Top block', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('multiple_inputs');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
oldChild.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="output"/></xml>')
|
||||
.firstChild);
|
||||
oldChild.getInput('INPUT2').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="output"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
|
||||
test('Child blocks', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('multiple_inputs');
|
||||
const childX = this.workspace.newBlock('single_input');
|
||||
const childY = this.workspace.newBlock('single_input');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
oldChild.getInput('INPUT').connection.connect(childX.outputConnection);
|
||||
oldChild.getInput('INPUT2').connection.connect(childY.outputConnection);
|
||||
childX.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="output"/></xml>')
|
||||
.firstChild);
|
||||
childY.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="output"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
|
||||
test('Spots filled', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('multiple_inputs');
|
||||
const otherChild = this.workspace.newBlock('output');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
oldChild.getInput('INPUT').connection
|
||||
.connect(otherChild.outputConnection);
|
||||
oldChild.getInput('INPUT2').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="output"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
chai.assert.notExists(
|
||||
Blockly.Connection.getConnectionForOrphanedOutput(oldChild, newChild));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Single available spot', function() {
|
||||
setup(function() {
|
||||
Blockly.defineBlocksWithJsonArray([
|
||||
{
|
||||
'type': 'single_input',
|
||||
'message0': '%1',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_value',
|
||||
'name': 'INPUT',
|
||||
'check': 'check'
|
||||
},
|
||||
],
|
||||
'output': 'check',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('No shadows', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('single_input');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
|
||||
const result = Blockly.Connection
|
||||
.getConnectionForOrphanedOutput(oldChild, newChild);
|
||||
chai.assert.exists(result);
|
||||
chai.assert.equal(result.getParentInput().name, 'INPUT');
|
||||
});
|
||||
|
||||
test('Shadows', function() {
|
||||
const parent = this.workspace.newBlock('input');
|
||||
const oldChild = this.workspace.newBlock('single_input');
|
||||
const newChild = this.workspace.newBlock('output');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
oldChild.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="output"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
const result = Blockly.Connection
|
||||
.getConnectionForOrphanedOutput(oldChild, newChild);
|
||||
chai.assert.exists(result);
|
||||
chai.assert.equal(result.getParentInput().name, 'INPUT');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Connect', function() {
|
||||
setup(function() {
|
||||
this.workspace = new Blockly.Workspace();
|
||||
@@ -1185,6 +862,40 @@ suite('Connection', function() {
|
||||
"message0": "",
|
||||
"output": 'check1'
|
||||
},
|
||||
{
|
||||
"type": "row_block_multiple_inputs",
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "INPUT",
|
||||
"check": 'check1'
|
||||
},
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "INPUT2",
|
||||
"check": 'check1'
|
||||
}
|
||||
],
|
||||
"output": 'check1'
|
||||
},
|
||||
{
|
||||
'type': 'output_to_statements',
|
||||
'message0': '%1 %2',
|
||||
'args0': [
|
||||
{
|
||||
'type': 'input_statement',
|
||||
'name': 'INPUT',
|
||||
'check': 'check1'
|
||||
},
|
||||
{
|
||||
'type': 'input_statement',
|
||||
'name': 'INPUT2',
|
||||
'check': 'check1'
|
||||
}
|
||||
],
|
||||
'output': 'check1',
|
||||
},
|
||||
{
|
||||
"type": "statement_block",
|
||||
"message0": "%1 %2",
|
||||
@@ -1401,42 +1112,288 @@ suite('Connection', function() {
|
||||
|
||||
suite('Reattach or bump orphan', function() {
|
||||
suite('Value', function() {
|
||||
// Only one test for this b/c tested by getConnectionForOrphanedOutput.
|
||||
test('Simple', function() {
|
||||
var parent = this.workspace.newBlock('row_block');
|
||||
var oldChild = this.workspace.newBlock('row_block');
|
||||
var newChild = this.workspace.newBlock('row_block');
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
var spy = sinon.spy(
|
||||
Blockly.Connection, 'getConnectionForOrphanedOutput');
|
||||
suite('No available spots', function() {
|
||||
test('No connection', function() {
|
||||
var parent = this.workspace.newBlock('row_block');
|
||||
var oldChild = this.workspace.newBlock('row_block');
|
||||
var newChild = this.workspace.newBlock('row_block_noend');
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
|
||||
parent.getInput('INPUT').connection.connect(newChild.outputConnection);
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isTrue(newChild.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(newChild.getInputTargetBlock('INPUT'), oldChild);
|
||||
// Make sure it is actually getting called, so all functionality has
|
||||
// been tested.
|
||||
// Future people: if you ever stop calling this function you need to
|
||||
// add more tests for reattaching orphans.
|
||||
chai.assert.isTrue(spy.calledOnce);
|
||||
this.assertBlockCount(3);
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
|
||||
test('All statements', function() {
|
||||
var parent = this.workspace.newBlock('row_block');
|
||||
var oldChild = this.workspace.newBlock('row_block');
|
||||
var newChild = this.workspace.newBlock('output_to_statements');
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Bad checks', function() {
|
||||
var parent = this.workspace.newBlock('row_block');
|
||||
var oldChild = this.workspace.newBlock('row_block');
|
||||
var newChild = this.workspace.newBlock('row_block_2to1');
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Through different types', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock('row_block_2to1');
|
||||
const otherChild = this.workspace.newBlock('row_block_1to2');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
newChild.getInput('INPUT').connection
|
||||
.connect(otherChild.outputConnection);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
});
|
||||
|
||||
test('Bump', function() {
|
||||
var parent = this.workspace.newBlock('row_block');
|
||||
var oldChild = this.workspace.newBlock('row_block');
|
||||
var newChild = this.workspace.newBlock('row_block_noend');
|
||||
parent.getInput('INPUT').connection.connect(oldChild.outputConnection);
|
||||
var spy = sinon.spy(oldChild.outputConnection, 'onFailedConnect');
|
||||
suite('Multiple available spots', function() {
|
||||
suite('No shadows', function() {
|
||||
test('Top block', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock(
|
||||
'row_block_multiple_inputs');
|
||||
|
||||
parent.getInput('INPUT').connection.connect(newChild.outputConnection);
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isTrue(spy.calledOnce);
|
||||
this.assertBlockCount(3);
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Child blocks', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock(
|
||||
'row_block_multiple_inputs');
|
||||
const childX = this.workspace.newBlock('row_block');
|
||||
const childY = this.workspace.newBlock('row_block');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
newChild.getInput('INPUT').connection
|
||||
.connect(childX.outputConnection);
|
||||
newChild.getInput('INPUT2').connection
|
||||
.connect(childY.outputConnection);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Spots filled', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock(
|
||||
'row_block_multiple_inputs');
|
||||
const otherChild = this.workspace.newBlock('row_block_noend');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
newChild.getInput('INPUT').connection
|
||||
.connect(otherChild.outputConnection);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
});
|
||||
|
||||
suite('Shadows', function() {
|
||||
test('Top block', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock(
|
||||
'row_block_multiple_inputs');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
newChild.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
||||
.firstChild);
|
||||
newChild.getInput('INPUT2').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Child blocks', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock(
|
||||
'row_block_multiple_inputs');
|
||||
const childX = this.workspace.newBlock('row_block');
|
||||
const childY = this.workspace.newBlock('row_block');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
newChild.getInput('INPUT').connection
|
||||
.connect(childX.outputConnection);
|
||||
newChild.getInput('INPUT2').connection
|
||||
.connect(childY.outputConnection);
|
||||
childX.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
||||
.firstChild);
|
||||
childY.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Spots filled', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock(
|
||||
'row_block_multiple_inputs');
|
||||
const otherChild = this.workspace.newBlock('row_block_noend');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
newChild.getInput('INPUT').connection
|
||||
.connect(otherChild.outputConnection);
|
||||
newChild.getInput('INPUT2').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isFalse(
|
||||
oldChild.outputConnection.isConnected());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Single available spot', function() {
|
||||
test('No shadows', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock('row_block');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isTrue(
|
||||
newChild.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
newChild.getInputTargetBlock('INPUT'), oldChild);
|
||||
});
|
||||
|
||||
test('Shadows', function() {
|
||||
const parent = this.workspace.newBlock('row_block');
|
||||
const oldChild = this.workspace.newBlock('row_block');
|
||||
const newChild = this.workspace.newBlock('row_block');
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(oldChild.outputConnection);
|
||||
newChild.getInput('INPUT').connection.setShadowDom(
|
||||
Blockly.Xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
||||
.firstChild);
|
||||
|
||||
parent.getInput('INPUT').connection
|
||||
.connect(newChild.outputConnection);
|
||||
|
||||
chai.assert.isTrue(
|
||||
parent.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
parent.getInputTargetBlock('INPUT'), newChild);
|
||||
chai.assert.isTrue(
|
||||
newChild.getInput('INPUT').connection.isConnected());
|
||||
chai.assert.equal(
|
||||
newChild.getInputTargetBlock('INPUT'), oldChild);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user