Merge pull request #5106 from gonfunko/connection_checker

Migrate core/connection_checker.js to goog.module
This commit is contained in:
Aaron Dodson
2021-07-19 08:19:08 -07:00
committed by GitHub
2 changed files with 85 additions and 87 deletions

View File

@@ -5,37 +5,36 @@
*/
/**
* @fileoverview An object that encapsulates logic for checking whether a potential
* connection is safe and valid.
* @fileoverview An object that encapsulates logic for checking whether a
* potential connection is safe and valid.
* @author fenichel@google.com (Rachel Fenichel)
*/
'use strict';
goog.provide('Blockly.ConnectionChecker');
goog.module('Blockly.ConnectionChecker');
goog.module.declareLegacyNamespace();
goog.require('Blockly.Connection');
goog.require('Blockly.connectionTypes');
const Connection = goog.require('Blockly.Connection');
const IConnectionChecker = goog.require('Blockly.IConnectionChecker');
const RenderedConnection = goog.requireType('Blockly.RenderedConnection');
const connectionTypes = goog.require('Blockly.connectionTypes');
const registry = goog.require('Blockly.registry');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.IConnectionChecker');
goog.require('Blockly.registry');
goog.requireType('Blockly.RenderedConnection');
/**
* Class for connection type checking logic.
* @implements {Blockly.IConnectionChecker}
* @implements {IConnectionChecker}
* @constructor
*/
Blockly.ConnectionChecker = function() {
};
const ConnectionChecker = function() {};
/**
* Check whether the current connection can connect with the target
* connection.
* @param {Blockly.Connection} a Connection to check compatibility with.
* @param {Blockly.Connection} b Connection to check compatibility with.
* @param {Connection} a Connection to check compatibility with.
* @param {Connection} b Connection to check compatibility with.
* @param {boolean} isDragging True if the connection is being made by dragging
* a block.
* @param {number=} opt_distance The max allowable distance between the
@@ -43,80 +42,80 @@ Blockly.ConnectionChecker = function() {
* @return {boolean} Whether the connection is legal.
* @public
*/
Blockly.ConnectionChecker.prototype.canConnect = function(a, b,
isDragging, opt_distance) {
ConnectionChecker.prototype.canConnect = function(
a, b, isDragging, opt_distance) {
return this.canConnectWithReason(a, b, isDragging, opt_distance) ==
Blockly.Connection.CAN_CONNECT;
Connection.CAN_CONNECT;
};
/**
* Checks whether the current connection can connect with the target
* connection, and return an error code if there are problems.
* @param {Blockly.Connection} a Connection to check compatibility with.
* @param {Blockly.Connection} b Connection to check compatibility with.
* @param {Connection} a Connection to check compatibility with.
* @param {Connection} b Connection to check compatibility with.
* @param {boolean} isDragging True if the connection is being made by dragging
* a block.
* @param {number=} opt_distance The max allowable distance between the
* connections for drag checks.
* @return {number} Blockly.Connection.CAN_CONNECT if the connection is legal,
* @return {number} Connection.CAN_CONNECT if the connection is legal,
* an error code otherwise.
* @public
*/
Blockly.ConnectionChecker.prototype.canConnectWithReason = function(
ConnectionChecker.prototype.canConnectWithReason = function(
a, b, isDragging, opt_distance) {
var safety = this.doSafetyChecks(a, b);
if (safety != Blockly.Connection.CAN_CONNECT) {
const safety = this.doSafetyChecks(a, b);
if (safety != Connection.CAN_CONNECT) {
return safety;
}
// If the safety checks passed, both connections are non-null.
var connOne = /** @type {!Blockly.Connection} **/ (a);
var connTwo = /** @type {!Blockly.Connection} **/ (b);
const connOne = /** @type {!Connection} **/ (a);
const connTwo = /** @type {!Connection} **/ (b);
if (!this.doTypeChecks(connOne, connTwo)) {
return Blockly.Connection.REASON_CHECKS_FAILED;
return Connection.REASON_CHECKS_FAILED;
}
if (isDragging &&
!this.doDragChecks(
/** @type {!Blockly.RenderedConnection} **/ (a),
/** @type {!Blockly.RenderedConnection} **/ (b),
opt_distance || 0)) {
return Blockly.Connection.REASON_DRAG_CHECKS_FAILED;
/** @type {!RenderedConnection} **/ (a),
/** @type {!RenderedConnection} **/ (b), opt_distance || 0)) {
return Connection.REASON_DRAG_CHECKS_FAILED;
}
return Blockly.Connection.CAN_CONNECT;
return Connection.CAN_CONNECT;
};
/**
* Helper method that translates a connection error code into a string.
* @param {number} errorCode The error code.
* @param {Blockly.Connection} a One of the two connections being checked.
* @param {Blockly.Connection} b The second of the two connections being
* @param {Connection} a One of the two connections being checked.
* @param {Connection} b The second of the two connections being
* checked.
* @return {string} A developer-readable error string.
* @public
*/
Blockly.ConnectionChecker.prototype.getErrorMessage = function(errorCode,
a, b) {
ConnectionChecker.prototype.getErrorMessage = function(errorCode, a, b) {
switch (errorCode) {
case Blockly.Connection.REASON_SELF_CONNECTION:
case Connection.REASON_SELF_CONNECTION:
return 'Attempted to connect a block to itself.';
case Blockly.Connection.REASON_DIFFERENT_WORKSPACES:
case Connection.REASON_DIFFERENT_WORKSPACES:
// Usually this means one block has been deleted.
return 'Blocks not on same workspace.';
case Blockly.Connection.REASON_WRONG_TYPE:
case Connection.REASON_WRONG_TYPE:
return 'Attempt to connect incompatible types.';
case Blockly.Connection.REASON_TARGET_NULL:
case Connection.REASON_TARGET_NULL:
return 'Target connection is null.';
case Blockly.Connection.REASON_CHECKS_FAILED:
var connOne = /** @type {!Blockly.Connection} **/ (a);
var connTwo = /** @type {!Blockly.Connection} **/ (b);
var msg = 'Connection checks failed. ';
msg += connOne + ' expected ' + connOne.getCheck() + ', found ' + connTwo.getCheck();
case Connection.REASON_CHECKS_FAILED: {
const connOne = /** @type {!Connection} **/ (a);
const connTwo = /** @type {!Connection} **/ (b);
let msg = 'Connection checks failed. ';
msg += connOne + ' expected ' + connOne.getCheck() + ', found ' +
connTwo.getCheck();
return msg;
case Blockly.Connection.REASON_SHADOW_PARENT:
}
case Connection.REASON_SHADOW_PARENT:
return 'Connecting non-shadow to shadow block.';
case Blockly.Connection.REASON_DRAG_CHECKS_FAILED:
case Connection.REASON_DRAG_CHECKS_FAILED:
return 'Drag checks failed.';
default:
return 'Unknown connection failure: this should never happen!';
@@ -126,53 +125,54 @@ Blockly.ConnectionChecker.prototype.getErrorMessage = function(errorCode,
/**
* Check that connecting the given connections is safe, meaning that it would
* not break any of Blockly's basic assumptions (e.g. no self connections).
* @param {Blockly.Connection} a The first of the connections to check.
* @param {Blockly.Connection} b The second of the connections to check.
* @param {Connection} a The first of the connections to check.
* @param {Connection} b The second of the connections to check.
* @return {number} An enum with the reason this connection is safe or unsafe.
* @public
*/
Blockly.ConnectionChecker.prototype.doSafetyChecks = function(a, b) {
ConnectionChecker.prototype.doSafetyChecks = function(a, b) {
if (!a || !b) {
return Blockly.Connection.REASON_TARGET_NULL;
return Connection.REASON_TARGET_NULL;
}
let blockA, blockB;
if (a.isSuperior()) {
var blockA = a.getSourceBlock();
var blockB = b.getSourceBlock();
blockA = a.getSourceBlock();
blockB = b.getSourceBlock();
} else {
var blockB = a.getSourceBlock();
var blockA = b.getSourceBlock();
blockB = a.getSourceBlock();
blockA = b.getSourceBlock();
}
if (blockA == blockB) {
return Blockly.Connection.REASON_SELF_CONNECTION;
return Connection.REASON_SELF_CONNECTION;
} else if (b.type != Blockly.OPPOSITE_TYPE[a.type]) {
return Blockly.Connection.REASON_WRONG_TYPE;
return Connection.REASON_WRONG_TYPE;
} else if (blockA.workspace !== blockB.workspace) {
return Blockly.Connection.REASON_DIFFERENT_WORKSPACES;
return Connection.REASON_DIFFERENT_WORKSPACES;
} else if (blockA.isShadow() && !blockB.isShadow()) {
return Blockly.Connection.REASON_SHADOW_PARENT;
return Connection.REASON_SHADOW_PARENT;
}
return Blockly.Connection.CAN_CONNECT;
return Connection.CAN_CONNECT;
};
/**
* Check whether this connection is compatible with another connection with
* respect to the value type system. E.g. square_root("Hello") is not
* compatible.
* @param {!Blockly.Connection} a Connection to compare.
* @param {!Blockly.Connection} b Connection to compare against.
* @param {!Connection} a Connection to compare.
* @param {!Connection} b Connection to compare against.
* @return {boolean} True if the connections share a type.
* @public
*/
Blockly.ConnectionChecker.prototype.doTypeChecks = function(a, b) {
var checkArrayOne = a.getCheck();
var checkArrayTwo = b.getCheck();
ConnectionChecker.prototype.doTypeChecks = function(a, b) {
const checkArrayOne = a.getCheck();
const checkArrayTwo = b.getCheck();
if (!checkArrayOne || !checkArrayTwo) {
// One or both sides are promiscuous enough that anything will fit.
return true;
}
// Find any intersection in the check lists.
for (var i = 0; i < checkArrayOne.length; i++) {
for (let i = 0; i < checkArrayOne.length; i++) {
if (checkArrayTwo.indexOf(checkArrayOne[i]) != -1) {
return true;
}
@@ -183,13 +183,13 @@ Blockly.ConnectionChecker.prototype.doTypeChecks = function(a, b) {
/**
* Check whether this connection can be made by dragging.
* @param {!Blockly.RenderedConnection} a Connection to compare.
* @param {!Blockly.RenderedConnection} b Connection to compare against.
* @param {!RenderedConnection} a Connection to compare.
* @param {!RenderedConnection} b Connection to compare against.
* @param {number} distance The maximum allowable distance between connections.
* @return {boolean} True if the connection is allowed during a drag.
* @public
*/
Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
if (a.distanceFrom(b) > distance) {
return false;
}
@@ -200,38 +200,34 @@ Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
}
switch (b.type) {
case Blockly.connectionTypes.PREVIOUS_STATEMENT:
case connectionTypes.PREVIOUS_STATEMENT:
return this.canConnectToPrevious_(a, b);
case Blockly.connectionTypes.OUTPUT_VALUE: {
case connectionTypes.OUTPUT_VALUE: {
// Don't offer to connect an already connected left (male) value plug to
// an available right (female) value plug.
if ((b.isConnected() &&
!b.targetBlock().isInsertionMarker()) ||
if ((b.isConnected() && !b.targetBlock().isInsertionMarker()) ||
a.isConnected()) {
return false;
}
break;
}
case Blockly.connectionTypes.INPUT_VALUE: {
case connectionTypes.INPUT_VALUE: {
// Offering to connect the left (male) of a value block to an already
// connected value pair is ok, we'll splice it in.
// However, don't offer to splice into an immovable block.
if (b.isConnected() &&
!b.targetBlock().isMovable() &&
if (b.isConnected() && !b.targetBlock().isMovable() &&
!b.targetBlock().isShadow()) {
return false;
}
break;
}
case Blockly.connectionTypes.NEXT_STATEMENT: {
case connectionTypes.NEXT_STATEMENT: {
// Don't let a block with no next connection bump other blocks out of the
// stack. But covering up a shadow block or stack of shadow blocks is
// fine. Similarly, replacing a terminal statement with another terminal
// statement is allowed.
if (b.isConnected() &&
!a.getSourceBlock().nextConnection &&
!b.targetBlock().isShadow() &&
b.targetBlock().nextConnection) {
if (b.isConnected() && !a.getSourceBlock().nextConnection &&
!b.targetBlock().isShadow() && b.targetBlock().nextConnection) {
return false;
}
break;
@@ -251,14 +247,14 @@ Blockly.ConnectionChecker.prototype.doDragChecks = function(a, b, distance) {
/**
* Helper function for drag checking.
* @param {!Blockly.Connection} a The connection to check, which must be a
* @param {!Connection} a The connection to check, which must be a
* statement input or next connection.
* @param {!Blockly.Connection} b A nearby connection to check, which
* @param {!Connection} b A nearby connection to check, which
* must be a previous connection.
* @return {boolean} True if the connection is allowed, false otherwise.
* @protected
*/
Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
if (a.targetConnection) {
// This connection is already occupied.
// A next connection will never disconnect itself mid-drag.
@@ -274,7 +270,7 @@ Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
return true;
}
var targetBlock = b.targetBlock();
const targetBlock = b.targetBlock();
// If it is connected to a real block, game over.
if (!targetBlock.isInsertionMarker()) {
return false;
@@ -285,5 +281,7 @@ Blockly.ConnectionChecker.prototype.canConnectToPrevious_ = function(a, b) {
return !targetBlock.getPreviousBlock();
};
Blockly.registry.register(Blockly.registry.Type.CONNECTION_CHECKER,
Blockly.registry.DEFAULT, Blockly.ConnectionChecker);
registry.register(
registry.Type.CONNECTION_CHECKER, registry.DEFAULT, ConnectionChecker);
exports = ConnectionChecker;

View File

@@ -20,7 +20,7 @@ goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['
goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], [], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation']);
goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry']);
goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry'], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants']);
goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], [], {'lang': 'es6', 'module': 'goog'});
goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes']);