From 7b1fdcb7c6ac0ea00925bb34432b517c75c863e2 Mon Sep 17 00:00:00 2001 From: rachel-fenichel Date: Fri, 1 Apr 2016 16:59:28 -0700 Subject: [PATCH] make tests work; make connext_ a member function. --- core/block.js | 30 +++-- core/block_svg.js | 4 + core/connection.js | 179 +++++++++++++---------------- core/rendered_connection.js | 47 +++++++- tests/jsunit/connection_db_test.js | 55 +++++---- tests/jsunit/connection_test.js | 34 +++--- 6 files changed, 203 insertions(+), 146 deletions(-) diff --git a/core/block.js b/core/block.js index b33fe7bb4..6fc29b49d 100644 --- a/core/block.js +++ b/core/block.js @@ -746,8 +746,7 @@ Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) { if (!this.previousConnection) { goog.asserts.assert(!this.outputConnection, 'Remove output connection prior to adding previous connection.'); - this.previousConnection = - new Blockly.Connection(this, Blockly.PREVIOUS_STATEMENT); + this.previousConnection = this.makeConnection(Blockly.PREVIOUS_STATEMENT); } this.previousConnection.setCheck(opt_check); } else { @@ -772,8 +771,7 @@ Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) { opt_check = null; } if (!this.nextConnection) { - this.nextConnection = - new Blockly.Connection(this, Blockly.NEXT_STATEMENT); + this.nextConnection = this.makeConnection(Blockly.NEXT_STATEMENT); } this.nextConnection.setCheck(opt_check); } else { @@ -801,8 +799,7 @@ Blockly.Block.prototype.setOutput = function(newBoolean, opt_check) { if (!this.outputConnection) { goog.asserts.assert(!this.previousConnection, 'Remove previous connection prior to adding output connection.'); - this.outputConnection = - new Blockly.Connection(this, Blockly.OUTPUT_VALUE); + this.outputConnection = this.makeConnection(Blockly.OUTPUT_VALUE); } this.outputConnection.setCheck(opt_check); } else { @@ -1159,7 +1156,7 @@ Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) { Blockly.Block.prototype.appendInput_ = function(type, name) { var connection = null; if (type == Blockly.INPUT_VALUE || type == Blockly.NEXT_STATEMENT) { - connection = new Blockly.Connection(this, type); + connection = this.makeConnection(type); } var input = new Blockly.Input(type, name, this, connection); // Append input to list. @@ -1336,3 +1333,22 @@ Blockly.Block.prototype.moveBy = function(dx, dy) { event.recordNew(); Blockly.Events.fire(event); }; + +/** + * Database of all blocks. + * @private + */ +Blockly.Block.BlockDB_ = Object.create(null); + +/** + * Find the block with the specified ID. + * @param {string} id ID of block to find. + * @return {Blockly.Block} The sought after block or null if not found. + */ +Blockly.Block.getById = function(id) { + return Blockly.Block.BlockDB_[id] || null; +}; + +Blockly.Block.prototype.makeConnection = function(type) { + return new Blockly.Connection(this, type); +}; diff --git a/core/block_svg.js b/core/block_svg.js index d376a9272..3cd9a4c52 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -1589,3 +1589,7 @@ Blockly.BlockSvg.prototype.getConnections_ = function(all) { } return myConnections; }; + +Blockly.BlockSvg.prototype.makeConnection = function(type) { + return new Blockly.RenderedConnection(this, type); +}; diff --git a/core/connection.js b/core/connection.js index 9dc7be3a2..0d5772eb6 100644 --- a/core/connection.js +++ b/core/connection.js @@ -64,12 +64,76 @@ Blockly.Connection.REASON_CHECKS_FAILED = 4; Blockly.Connection.REASON_DIFFERENT_WORKSPACES = 5; /** - * Connect two connections together. - * @param {!Blockly.Connection} parentConnection Connection on superior block. + * Connection this connection connects to. Null if not connected. + * @type {Blockly.Connection} + */ +Blockly.Connection.prototype.targetConnection = null; + +/** + * List of compatible value types. Null if all types are compatible. + * @type {Array} + * @private + */ +Blockly.Connection.prototype.check_ = null; + +/** + * DOM representation of a shadow block, or null if none. + * @type {Element} + * @private + */ +Blockly.Connection.prototype.shadowDom_ = null; + +/** + * Horizontal location of this connection. + * @type {number} + * @private + */ +Blockly.Connection.prototype.x_ = 0; + +/** + * Vertical location of this connection. + * @type {number} + * @private + */ +Blockly.Connection.prototype.y_ = 0; + +/** + * Has this connection been added to the connection database? + * @type {boolean} + * @private + */ +Blockly.Connection.prototype.inDB_ = false; + +/** + * Connection database for connections of this type on the current workspace. + * @type {Blockly.ConnectionDB} + * @private + */ +Blockly.Connection.prototype.db_ = null; + +/** + * Connection database for connections compatible with this type on the + * current workspace. + * @type {Blockly.ConnectionDB} + * @private + */ +Blockly.Connection.prototype.dbOpposite_ = null; + +/** + * Whether this connections is hidden (not tracked in a database) or not. + * @type {boolean} + * @private + */ +Blockly.Connection.prototype.hidden_ = null; + +/** + * Connect two connections together. This is the connection on the superior + * block. * @param {!Blockly.Connection} childConnection Connection on inferior block. * @private */ -Blockly.Connection.connect_ = function(parentConnection, childConnection) { +Blockly.Connection.prototype.connect_ = function(childConnection) { + var parentConnection = this; var parentBlock = parentConnection.getSourceBlock(); var childBlock = childConnection.getSourceBlock(); // Disconnect any existing parent on the child connection. @@ -163,90 +227,8 @@ Blockly.Connection.connect_ = function(parentConnection, childConnection) { event.recordNew(); Blockly.Events.fire(event); } - - if (parentBlock.rendered) { - parentBlock.updateDisabled(); - } - if (childBlock.rendered) { - childBlock.updateDisabled(); - } - if (parentBlock.rendered && childBlock.rendered) { - if (parentConnection.type == Blockly.NEXT_STATEMENT || - parentConnection.type == Blockly.PREVIOUS_STATEMENT) { - // Child block may need to square off its corners if it is in a stack. - // Rendering a child will render its parent. - childBlock.render(); - } else { - // Child block does not change shape. Rendering the parent node will - // move its connected children into position. - parentBlock.render(); - } - } }; -/** - * Connection this connection connects to. Null if not connected. - * @type {Blockly.Connection} - */ -Blockly.Connection.prototype.targetConnection = null; - -/** - * List of compatible value types. Null if all types are compatible. - * @type {Array} - * @private - */ -Blockly.Connection.prototype.check_ = null; - -/** - * DOM representation of a shadow block, or null if none. - * @type {Element} - * @private - */ -Blockly.Connection.prototype.shadowDom_ = null; - -/** - * Horizontal location of this connection. - * @type {number} - * @private - */ -Blockly.Connection.prototype.x_ = 0; - -/** - * Vertical location of this connection. - * @type {number} - * @private - */ -Blockly.Connection.prototype.y_ = 0; - -/** - * Has this connection been added to the connection database? - * @type {boolean} - * @private - */ -Blockly.Connection.prototype.inDB_ = false; - -/** - * Connection database for connections of this type on the current workspace. - * @type {Blockly.ConnectionDB} - * @private - */ -Blockly.Connection.prototype.db_ = null; - -/** - * Connection database for connections compatible with this type on the - * current workspace. - * @type {Blockly.ConnectionDB} - * @private - */ -Blockly.Connection.prototype.dbOpposite_ = null; - -/** - * Whether this connections is hidden (not tracked in a database) or not. - * @type {boolean} - * @private - */ -Blockly.Connection.prototype.hidden_ = null; - /** * Sever all links to this connection (not including from the source object). */ @@ -284,6 +266,14 @@ Blockly.Connection.prototype.isSuperior = function() { this.type == Blockly.NEXT_STATEMENT; }; +/** + * Is the connection connected? + * @return {boolean} True if connection is connected to another connection. + */ +Blockly.Connection.prototype.isConnected = function() { + return !!this.targetConnection; +}; + /** * Checks whether the current connection can connect with the target * connection. @@ -404,10 +394,10 @@ Blockly.Connection.prototype.connect = function(otherConnection) { // Determine which block is superior (higher in the source stack). if (this.isSuperior()) { // Superior block. - Blockly.Connection.connect_(this, otherConnection); + this.connect_(otherConnection); } else { // Inferior block. - Blockly.Connection.connect_(otherConnection, this); + otherConnection.connect_(this); } }; @@ -494,12 +484,12 @@ Blockly.Connection.prototype.disconnect = function() { childBlock = this.sourceBlock_; parentConnection = otherConnection; } - this.disconnectInternal(parentBlock, childBlock, parentConnection); + this.disconnectInternal(parentBlock, childBlock, otherConnection); this.respawnShadow(parentConnection, parentBlock); }; Blockly.Connection.prototype.disconnectInternal = function(parentBlock, - childBlock, parentConnection) { + childBlock, otherConnection) { var event; if (Blockly.Events.isEnabled()) { event = new Blockly.Events.Move(childBlock); @@ -605,14 +595,3 @@ Blockly.Connection.prototype.setShadowDom = function(shadow) { Blockly.Connection.prototype.getShadowDom = function() { return this.shadowDom_; }; - -/** - * Find all nearby compatible connections to this connection. - * Type checking does not apply, since this function is used for bumping. - * @param {number} maxLimit The maximum radius to another connection. - * @return {!Array.} List of connections. - * @private - */ -Blockly.Connection.prototype.neighbours_ = function(maxLimit) { - return this.dbOpposite_.getNeighbours(this, maxLimit); -}; diff --git a/core/rendered_connection.js b/core/rendered_connection.js index 8dc9dd196..2df1dc88a 100644 --- a/core/rendered_connection.js +++ b/core/rendered_connection.js @@ -24,11 +24,11 @@ */ 'use strict'; + goog.provide('Blockly.RenderedConnection'); goog.require('Blockly.Connection'); - /** * Class for a connection between blocks that may be rendered on screen. * @param {!Blockly.Block} source The block establishing this connection. @@ -223,7 +223,6 @@ Blockly.RenderedConnection.prototype.unhideAll = function() { return renderList; }; - /** * Remove the highlighting around this connection. */ @@ -287,9 +286,9 @@ Blockly.RenderedConnection.prototype.isConnectionAllowed = function(candidate, }; Blockly.RenderedConnection.prototype.disconnectInternal = function(parentBlock, - childBlock, parentConnection) { + childBlock, otherConnection) { Blockly.RenderedConnection.superClass_.disconnectInternal.call(this, - parentBlock, childBlock, parentConnection); + parentBlock, childBlock, otherConnection); // Rerender the parent so that it may reflow. if (parentBlock.rendered) { parentBlock.render(); @@ -317,4 +316,42 @@ Blockly.RenderedConnection.prototype.respawnShadow = function(parentConnection, blockShadow.initSvg(); blockShadow.render(false); } -}; \ No newline at end of file +}; + +/** + * Find all nearby compatible connections to this connection. + * Type checking does not apply, since this function is used for bumping. + * @param {number} maxLimit The maximum radius to another connection. + * @return {!Array.} List of connections. + * @private + */ +Blockly.RenderedConnection.prototype.neighbours_ = function(maxLimit) { + return this.dbOpposite_.getNeighbours(this, maxLimit); +}; + +Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { + Blockly.RenderedConnection.superClass_.connect_.call(this, childConnection); + + var parentConnection = this; + var parentBlock = parentConnection.getSourceBlock(); + var childBlock = childConnection.getSourceBlock(); + + if (parentBlock.rendered) { + parentBlock.updateDisabled(); + } + if (childBlock.rendered) { + childBlock.updateDisabled(); + } + if (parentBlock.rendered && childBlock.rendered) { + if (parentConnection.type == Blockly.NEXT_STATEMENT || + parentConnection.type == Blockly.PREVIOUS_STATEMENT) { + // Child block may need to square off its corners if it is in a stack. + // Rendering a child will render its parent. + childBlock.render(); + } else { + // Child block does not change shape. Rendering the parent node will + // move its connected children into position. + parentBlock.render(); + } + } +}; diff --git a/tests/jsunit/connection_db_test.js b/tests/jsunit/connection_db_test.js index 1f1bb2882..269d2d123 100644 --- a/tests/jsunit/connection_db_test.js +++ b/tests/jsunit/connection_db_test.js @@ -115,7 +115,7 @@ function test_DB_getNeighbours() { // Set up some connections. for (var i = 0; i < 10; i++) { db.addConnection(helper_createConnection(0, i, - Blockly.PREVIOUS_STATEMENT)); + Blockly.PREVIOUS_STATEMENT, null, true)); } // Test block belongs at beginning. @@ -154,14 +154,20 @@ function test_DB_getNeighbours() { function test_DB_findPositionForConnection() { var db = new Blockly.ConnectionDB(); - db.addConnection(helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT)); - db.addConnection(helper_createConnection(0, 1, Blockly.PREVIOUS_STATEMENT)); - db.addConnection(helper_createConnection(0, 2, Blockly.PREVIOUS_STATEMENT)); - db.addConnection(helper_createConnection(0, 4, Blockly.PREVIOUS_STATEMENT)); - db.addConnection(helper_createConnection(0, 5, Blockly.PREVIOUS_STATEMENT)); + db.addConnection(helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT, + null, true)); + db.addConnection(helper_createConnection(0, 1, Blockly.PREVIOUS_STATEMENT, + null, true)); + db.addConnection(helper_createConnection(0, 2, Blockly.PREVIOUS_STATEMENT, + null, true)); + db.addConnection(helper_createConnection(0, 4, Blockly.PREVIOUS_STATEMENT, + null, true)); + db.addConnection(helper_createConnection(0, 5, Blockly.PREVIOUS_STATEMENT, + null, true)); assertEquals(5, db.length); - var conn = helper_createConnection(0, 3, Blockly.PREVIOUS_STATEMENT); + var conn = helper_createConnection(0, 3, Blockly.PREVIOUS_STATEMENT, null, + true); assertEquals(3, db.findPositionForConnection_(conn)); } @@ -169,16 +175,17 @@ function test_DB_findConnection() { var db = new Blockly.ConnectionDB(); for (var i = 0; i < 10; i++) { db.addConnection(helper_createConnection(i, 0, - Blockly.PREVIOUS_STATEMENT)); + Blockly.PREVIOUS_STATEMENT, null, true)); db.addConnection(helper_createConnection(0, i, - Blockly.PREVIOUS_STATEMENT)); + Blockly.PREVIOUS_STATEMENT, null, true)); } - var conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT); + var conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null, + true); db.addConnection(conn); assertEquals(conn, db[db.findConnection(conn)]); - conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT); + conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null, true); assertEquals(-1, db.findConnection(conn)); } @@ -186,7 +193,7 @@ function test_DB_ordering() { var db = new Blockly.ConnectionDB(); for (var i = 0; i < 10; i++) { db.addConnection(helper_createConnection(0, 9 - i, - Blockly.PREVIOUS_STATEMENT)); + Blockly.PREVIOUS_STATEMENT), null, true); } for (i = 0; i < 10; i++) { @@ -210,7 +217,7 @@ function test_DB_ordering() { -19, -20, -95]; for (i = 0; i < xCoords.length; i++) { db.addConnection(helper_createConnection(xCoords[i], yCoords[i], - Blockly.PREVIOUS_STATEMENT)); + Blockly.PREVIOUS_STATEMENT), null, true); } for (i = 1; i < xCoords.length; i++) { @@ -227,13 +234,13 @@ function test_SearchForClosest() { 100 /* radius */)); db.addConnection(helper_createConnection(100, 0, Blockly.PREVIOUS_STATEMENT, - sharedWorkspace)); + sharedWorkspace, true)); assertEquals(null, helper_searchDB(db, 0, 0, 5, sharedWorkspace)); db = new Blockly.ConnectionDB(); for (var i = 0; i < 10; i++) { var tempConn = helper_createConnection(0, i, Blockly.PREVIOUS_STATEMENT, - sharedWorkspace); + sharedWorkspace, true); tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); db.addConnection(tempConn); } @@ -248,11 +255,11 @@ function test_SearchForClosest() { assertEquals(db[0], helper_searchDB(db, 0, 0, 0, sharedWorkspace)); tempConn = helper_createConnection(6, 6, Blockly.PREVIOUS_STATEMENT, - sharedWorkspace); + sharedWorkspace, true); tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); db.addConnection(tempConn); tempConn = helper_createConnection(5, 5, Blockly.PREVIOUS_STATEMENT, - sharedWorkspace); + sharedWorkspace, true); tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); db.addConnection(tempConn); @@ -263,13 +270,14 @@ function test_SearchForClosest() { function helper_getNeighbours(db, x, y, radius) { - return db.getNeighbours(helper_createConnection(x, y, Blockly.NEXT_STATEMENT), + return db.getNeighbours(helper_createConnection(x, y, Blockly.NEXT_STATEMENT, + null, true), radius); } function helper_searchDB(db, x, y, radius, shared_workspace) { var tempConn = helper_createConnection(x, y, - Blockly.NEXT_STATEMENT, shared_workspace); + Blockly.NEXT_STATEMENT, shared_workspace, true); tempConn.sourceBlock_ = helper_makeSourceBlock(shared_workspace); var closest = db.searchForClosest(tempConn, radius, {x: 0, y: 0}); return closest.connection; @@ -285,9 +293,14 @@ function helper_makeSourceBlock(sharedWorkspace) { }; } -function helper_createConnection(x, y, type, opt_shared_workspace) { +function helper_createConnection(x, y, type, opt_shared_workspace, + opt_rendered) { var workspace = opt_shared_workspace ? opt_shared_workspace : {}; - var conn = new Blockly.Connection({workspace: workspace}, type); + if (opt_rendered) { + var conn = new Blockly.RenderedConnection({workspace: workspace}, type); + } else { + var conn = new Blockly.Connection({workspace: workspace}, type); + } conn.x_ = x; conn.y_ = y; return conn; diff --git a/tests/jsunit/connection_test.js b/tests/jsunit/connection_test.js index c9ad00dae..d0a11662a 100644 --- a/tests/jsunit/connection_test.js +++ b/tests/jsunit/connection_test.js @@ -245,15 +245,15 @@ function testCheckConnection_TypeNextOutput() { connectionTest_tearDown(); } -function test_isConnectionAllowed() { +function test_isConnectionAllowed_Distance() { var sharedWorkspace = {}; // Two connections of opposite types near each other. var one = helper_createConnection(5 /* x */, 10 /* y */, - Blockly.INPUT_VALUE); + Blockly.INPUT_VALUE, null, true); one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); var two = helper_createConnection(10 /* x */, 15 /* y */, - Blockly.OUTPUT_VALUE); + Blockly.OUTPUT_VALUE, null, true); two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); assertTrue(one.isConnectionAllowed(two, 20.0)); @@ -261,22 +261,30 @@ function test_isConnectionAllowed() { two.x_ = 100; two.y_ = 100; assertFalse(one.isConnectionAllowed(two, 20.0)); +} + +function test_isConnectionAllowed_Unrendered() { + var sharedWorkspace = {}; + + var one = helper_createConnection(5 /* x */, 10 /* y */, + Blockly.INPUT_VALUE); + one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); // Don't offer to connect an already connected left (male) value plug to // an available right (female) value plug. - var three = helper_createConnection(0, 0, Blockly.OUTPUT_VALUE); + var two = helper_createConnection(0, 0, Blockly.OUTPUT_VALUE); + two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); + + assertTrue(one.isConnectionAllowed(two)); + var three = helper_createConnection(0, 0, Blockly.INPUT_VALUE); three.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); - assertTrue(one.isConnectionAllowed(three, 20.0)); - var four = helper_createConnection(0, 0, Blockly.INPUT_VALUE); - four.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); - - Blockly.Connection.connectReciprocally_(three, four); - assertFalse(one.isConnectionAllowed(three, 20.0)); + Blockly.Connection.connectReciprocally_(two, three); + assertFalse(one.isConnectionAllowed(two)); // Don't connect two connections on the same block. two.sourceBlock_ = one.sourceBlock_; - assertFalse(one.isConnectionAllowed(two, 1000.0)); + assertFalse(one.isConnectionAllowed(two)); } function test_isConnectionAllowed_NoNext() { @@ -288,14 +296,14 @@ function test_isConnectionAllowed_NoNext() { var two = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT); two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); - assertTrue(two.isConnectionAllowed(one, 1000.0)); + assertTrue(two.isConnectionAllowed(one)); var three = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT); three.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); three.sourceBlock_.previousConnection = three; Blockly.Connection.connectReciprocally_(one, three); - assertFalse(two.isConnectionAllowed(one, 1000.0)); + assertFalse(two.isConnectionAllowed(one)); } function testCheckConnection_Okay() {