From 17823db4df31c099cf51af50ffd7df8056a34d06 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Tue, 14 Aug 2018 16:29:59 -0700 Subject: [PATCH] Fix problem with connecting a statement into a stack, but not a c-shape block --- core/block_dragger.js | 5 +++ core/connection.js | 69 +++++++++++++++++++++++++++--- core/constants.js | 6 +-- core/insertion_marker_manager.js | 10 +++++ tests/jsunit/connection_db_test.js | 4 +- 5 files changed, 85 insertions(+), 9 deletions(-) diff --git a/core/block_dragger.js b/core/block_dragger.js index 9204e1a00..0fed99b36 100644 --- a/core/block_dragger.js +++ b/core/block_dragger.js @@ -162,6 +162,9 @@ Blockly.BlockDragger.prototype.startBlockDrag = function(currentDragDeltaXY, this.draggingBlock_.bringToFront(); } + // // During a drag there may be a lot of rerenders, but not field changes. + // // Turn the cache on so we don't do spurious remeasures during the drag. + // Blockly.Field.startCache(); this.workspace_.setResizesEnabled(false); Blockly.BlockAnimations.disconnectUiStop(); @@ -222,6 +225,8 @@ Blockly.BlockDragger.prototype.endBlockDrag = function(e, currentDragDeltaXY) { this.dragBlock(e, currentDragDeltaXY); this.dragIconData_ = []; + Blockly.Field.stopCache(); + Blockly.BlockAnimations.disconnectUiStop(); var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); diff --git a/core/connection.js b/core/connection.js index b94d07fec..197b4c468 100644 --- a/core/connection.js +++ b/core/connection.js @@ -245,6 +245,14 @@ Blockly.Connection.prototype.dispose = function() { this.dbOpposite_ = null; }; +/** + * @return {boolean} true if the connection is not connected or is connected to + * an insertion marker, false otherwise. + */ +Blockly.Connection.prototype.isConnectedToNonInsertionMarker = function() { + return this.targetConnection && !this.targetBlock().isInsertionMarker(); +}; + /** * Get the source block for this connection. * @return {Blockly.Block} The source block, or null if there is none. @@ -336,13 +344,16 @@ Blockly.Connection.prototype.checkConnection_ = function(target) { /** * Check if the two connections can be dragged to connect to each other. - * @param {!Blockly.Connection} candidate A nearby connection to check. + * This is used by the connection database when searching for the closest + * connection. + * @param {!Blockly.Connection} candidate A nearby connection to check, which + * must be a previous connection. * @return {boolean} True if the connection is allowed, false otherwise. */ -Blockly.Connection.prototype.isConnectionAllowed = function(candidate) { - // Type checking. - var canConnect = this.canConnectWithReason_(candidate); - if (canConnect != Blockly.Connection.CAN_CONNECT) { +Blockly.Connection.prototype.canConnectToPrevious_ = function(candidate) { + if (this.targetConnection) { + // This connection is already occupied. + // A next connection will never disconnect itself mid-drag. return false; } @@ -387,6 +398,54 @@ Blockly.Connection.prototype.isConnectionAllowed = function(candidate) { throw Error('Unknown connection type in isConnectionAllowed'); } + return true; +}; + +/** + * Check if the two connections can be dragged to connect to each other. + * @param {!Blockly.Connection} candidate A nearby connection to check. + * @return {boolean} True if the connection is allowed, false otherwise. + */ +Blockly.Connection.prototype.isConnectionAllowed = function(candidate) { + // Don't consider insertion markers. + if (candidate.sourceBlock_.isInsertionMarker()) { + return false; + } + // Type checking. + var canConnect = this.canConnectWithReason_(candidate); + if (canConnect != Blockly.Connection.CAN_CONNECT) { + return false; + } + + switch (candidate.type) { + case Blockly.PREVIOUS_STATEMENT: + return this.canConnectToPrevious_(candidate); + case Blockly.OUTPUT_VALUE: { + // Don't offer to connect an already connected left (male) value plug to + // an available right (female) value plug. + if (candidate.isConnected() || this.isConnected()) { + return false; + } + break; + } + case Blockly.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 (candidate.isConnected() && + !candidate.targetBlock().isMovable() && + !candidate.targetBlock().isShadow()) { + return false; + } + break; + } + case Blockly.NEXT_STATEMENT: { + break; + } + default: + throw Error('Unknown connection type in isConnectionAllowed'); + } + // Don't let blocks try to connect to themselves or ones they nest. if (Blockly.draggingConnections_.indexOf(candidate) != -1) { return false; diff --git a/core/constants.js b/core/constants.js index c71e44437..7668989f7 100644 --- a/core/constants.js +++ b/core/constants.js @@ -42,20 +42,20 @@ Blockly.FLYOUT_DRAG_RADIUS = 10; /** * Maximum misalignment between connections for them to snap together. */ -Blockly.SNAP_RADIUS = 48; +Blockly.SNAP_RADIUS = 36; /** * Maximum misalignment between connections for them to snap together, * when a connection is already highlighted. */ -Blockly.CONNECTING_SNAP_RADIUS = 68; +Blockly.CONNECTING_SNAP_RADIUS = 48; /** * How much to prefer staying connected to the current connection over moving to * a new connection. The current previewed connection is considered to be this * much closer to the matching connection on the block than it actually is. */ -Blockly.CURRENT_CONNECTION_PREFERENCE = 20; +Blockly.CURRENT_CONNECTION_PREFERENCE = 0; /** * The main colour of insertion markers, in hex. The block is rendered a diff --git a/core/insertion_marker_manager.js b/core/insertion_marker_manager.js index 0b43f000c..b53f2adf4 100644 --- a/core/insertion_marker_manager.js +++ b/core/insertion_marker_manager.js @@ -240,6 +240,8 @@ Blockly.InsertionMarkerManager.prototype.update = function(dxy, deleteArea) { this.shouldUpdatePreviews_(candidate, dxy); if (shouldUpdate) { + //console.log("updating previews"); + //console.log(candidate); // Don't fire events for insertion marker creation or movement. Blockly.Events.disable(); this.maybeHidePreview_(candidate); @@ -371,6 +373,7 @@ Blockly.InsertionMarkerManager.prototype.shouldUpdatePreviews_ = function( */ Blockly.InsertionMarkerManager.prototype.getCandidate_ = function(dxy) { var radius = this.getStartRadius_(); + //console.log(radius); var candidateClosest = null; var candidateLocal = null; @@ -378,11 +381,15 @@ Blockly.InsertionMarkerManager.prototype.getCandidate_ = function(dxy) { var myConnection = this.availableConnections_[i]; var neighbour = myConnection.closest(radius, dxy); if (neighbour.connection) { + //console.log('neighbour: '); + //console.log(neighbour.connection); + //console.log('Is insertion marker: ' + neighbour.connection.sourceBlock_.isInsertionMarker()); candidateClosest = neighbour.connection; candidateLocal = myConnection; radius = neighbour.radius; } } + //console.log(radius); return { closest: candidateClosest, local: candidateLocal, @@ -500,6 +507,7 @@ Blockly.InsertionMarkerManager.prototype.maybeShowPreview_ = function(candidate) // Something went wrong and we're trying to connect to an invalid connection. if (closest == this.closestConnection_ || closest.sourceBlock_.isInsertionMarker()) { + console.log("trying to connect to an insertion marker"); return; } // Add an insertion marker or replacement marker. @@ -695,7 +703,9 @@ Blockly.InsertionMarkerManager.prototype.connectMarker_ = function() { imBlock.positionNewBlock(imBlock, imConn, closest); // Connect() also renders the insertion marker. + console.log("connecting the insertion marker"); imConn.connect(closest); + console.log("done connecting the insertion marker"); this.markerConnection_ = imConn; }; diff --git a/tests/jsunit/connection_db_test.js b/tests/jsunit/connection_db_test.js index c9eb6add1..1ef07c6b8 100644 --- a/tests/jsunit/connection_db_test.js +++ b/tests/jsunit/connection_db_test.js @@ -289,7 +289,9 @@ function helper_makeSourceBlock(sharedWorkspace) { getParent: function() { return null; }, movable_: true, isMovable: function() { return true; }, - isShadow: function() { return false; } + isShadow: function() { return false; }, + isInsertionMarker: function() { return false; }, + getFirstStatementConnection: function() { return null; } }; }