From 002e470ccd72d2e3f602cc904466726d61e172a2 Mon Sep 17 00:00:00 2001 From: rachel-fenichel Date: Wed, 6 Apr 2016 14:42:12 -0700 Subject: [PATCH 1/2] ghost -> insertion marker --- core/block.js | 30 ++++---- core/block_render_svg_horizontal.js | 2 +- core/block_svg.js | 107 ++++++++++++++-------------- core/blockly.js | 10 +-- core/connection.js | 23 +++--- javascript_compressed.js | 44 ++++++------ tests/jsunit/connection_db_test.js | 2 +- tests/jsunit/connection_test.js | 6 +- 8 files changed, 113 insertions(+), 111 deletions(-) diff --git a/core/block.js b/core/block.js index 73f37538a4..08ba5bae39 100644 --- a/core/block.js +++ b/core/block.js @@ -101,9 +101,9 @@ Blockly.Block = function(workspace, prototypeName, opt_id) { this.RTL = workspace.RTL; /** @type {Blockly.Block} */ - this.ghostBlock_ = null; + this.insertionMarker_ = null; /** @type {boolean} */ - this.isGhost_ = false; + this.isInsertionMarker_ = false; // Copy the type-specific functions and data from the prototype. if (prototypeName) { @@ -208,8 +208,8 @@ Blockly.Block.prototype.dispose = function(healStack) { Blockly.selected = null; } - if (this.ghostBlock_) { - this.ghostBlock_.dispose(); + if (this.insertionMarker_) { + this.insertionMarker_.dispose(); } // First, dispose of all my children. @@ -553,23 +553,23 @@ Blockly.Block.prototype.setShadow = function(shadow) { }; /** - * Get whether this block is a ghost block or not. - * @return {boolean} True if a ghost. + * Get whether this block is an insertion marker block or not. + * @return {boolean} True if an insertion marker. */ -Blockly.Block.prototype.isGhost = function() { - return this.isGhost_; +Blockly.Block.prototype.isInsertionMarker = function() { + return this.isInsertionMarker_; }; /** - * Set whether this block is a ghost block or not. - * @param {boolean} ghost True if a ghost. + * Set whether this block is an insertion marker block or not. + * @param {boolean} insertionMarker True if an insertion marker. */ -Blockly.Block.prototype.setGhost = function(ghost) { - if (this.isGhost_ == ghost) { +Blockly.Block.prototype.setInsertionMarker = function(insertionMarker) { + if (this.isInsertionMarker_ == insertionMarker) { return; // No change. } - this.isGhost_ = ghost; - if (this.isGhost_) { + this.isInsertionMarker_ = insertionMarker; + if (this.isInsertionMarker_) { this.setColour("#949494"); } }; @@ -632,7 +632,7 @@ Blockly.Block.prototype.setConnectionsHidden = function(hidden) { /** * Find the connection on this block that corresponds to the given connection * on the other block. - * Used to match connections between a block and its ghost. + * Used to match connections between a block and its insertion marker. * @param {!Blockly.Block} otherBlock The other block to match against. * @param {!Blockly.Connection} conn The other connection to match. * @return {Blockly.Connection} the matching connection on this block, or null. diff --git a/core/block_render_svg_horizontal.js b/core/block_render_svg_horizontal.js index a56762ce81..df788d39e6 100644 --- a/core/block_render_svg_horizontal.js +++ b/core/block_render_svg_horizontal.js @@ -396,7 +396,7 @@ Blockly.BlockSvg.prototype.renderDraw_ = function(metrics) { iconX = -metrics.width + Blockly.BlockSvg.SEP_SPACE_X / 1.5; } } - if (this.isGhost()) { + if (this.isInsertionMarker()) { icon.setAttribute('display', 'none'); } icon.setAttribute('transform', diff --git a/core/block_svg.js b/core/block_svg.js index f4c9cf0956..e9d8ad5c31 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -237,13 +237,13 @@ Blockly.BlockSvg.terminateDrag_ = function() { if (Blockly.dragMode_ == Blockly.DRAG_FREE) { // Terminate a drag operation. if (selected) { - if (selected.ghostBlock_) { + if (selected.insertionMarker_) { Blockly.Events.disable(); - if (Blockly.localGhostConnection_) { - selected.disconnectGhost(); + if (Blockly.insertionMarkerConnection_) { + selected.disconnectInsertionMarker(); } - selected.ghostBlock_.dispose(); - selected.ghostBlock_ = null; + selected.insertionMarker_.dispose(); + selected.insertionMarker_ = null; Blockly.Events.enable(); } // Update the connection locations. @@ -876,66 +876,67 @@ Blockly.BlockSvg.prototype.onMouseMove_ = function(e) { */ Blockly.BlockSvg.prototype.updatePreviews = function(closestConnection, localConnection, radiusConnection, e, dx, dy) { - // Don't fire events for ghost block creation or movement. + // Don't fire events for insertion marker creation or movement. Blockly.Events.disable(); - // Remove a ghost if needed. For Scratch-Blockly we are using ghosts instead - // of highlighting the connection; for compatibility with Web Blockly the - // name "highlightedConnection" will still be used. + // Remove an insertion marker if needed. For Scratch-Blockly we are using + // grayed-out blocks instead of highlighting the connection; for compatibility + // with Web Blockly the name "highlightedConnection" will still be used. if (Blockly.highlightedConnection_ && Blockly.highlightedConnection_ != closestConnection) { - if (this.ghostBlock_ && Blockly.localGhostConnection_) { - this.disconnectGhost(); + if (this.insertionMarker_ && Blockly.insertionMarkerConnection_) { + this.disconnectInsertionMarker(); } Blockly.highlightedConnection_ = null; Blockly.localConnection_ = null; } - // Add a ghost if needed. + // Add an insertion marker if needed. if (closestConnection && closestConnection != Blockly.highlightedConnection_ && - !closestConnection.sourceBlock_.isGhost()) { + !closestConnection.sourceBlock_.isInsertionMarker()) { Blockly.highlightedConnection_ = closestConnection; Blockly.localConnection_ = localConnection; - if (!this.ghostBlock_){ - this.ghostBlock_ = this.workspace.newBlock(this.type); - this.ghostBlock_.setGhost(true); - this.ghostBlock_.initSvg(); + if (!this.insertionMarker_){ + this.insertionMarker_ = this.workspace.newBlock(this.type); + this.insertionMarker_.setInsertionMarker(true); + this.insertionMarker_.initSvg(); } - var ghostBlock = this.ghostBlock_; - var localGhostConnection = ghostBlock.getMatchingConnection(this, + var insertionMarker = this.insertionMarker_; + var insertionMarkerConnection = insertionMarker.getMatchingConnection(this, localConnection); - if (localGhostConnection != Blockly.localGhostConnection_) { - ghostBlock.getSvgRoot().setAttribute('visibility', 'visible'); - ghostBlock.rendered = true; + if (insertionMarkerConnection != Blockly.insertionMarkerConnection_) { + insertionMarker.getSvgRoot().setAttribute('visibility', 'visible'); + insertionMarker.rendered = true; // Move the preview to the correct location before the existing block. - if (localGhostConnection.type == Blockly.NEXT_STATEMENT) { + if (insertionMarkerConnection.type == Blockly.NEXT_STATEMENT) { var relativeXy = this.getRelativeToSurfaceXY(); var connectionOffsetX = (localConnection.x_ - (relativeXy.x - dx)); var connectionOffsetY = (localConnection.y_ - (relativeXy.y - dy)); var newX = closestConnection.x_ - connectionOffsetX; var newY = closestConnection.y_ - connectionOffsetY; - var ghostPosition = ghostBlock.getRelativeToSurfaceXY(); + var insertionPosition = insertionMarker.getRelativeToSurfaceXY(); // If it's the first statement connection of a c-block, this block is // going to get taller as soon as render() is called below. - if (localGhostConnection != ghostBlock.nextConnection) { + if (insertionMarkerConnection != insertionMarker.nextConnection) { newY -= closestConnection.sourceBlock_.getHeightWidth().height - Blockly.BlockSvg.MIN_BLOCK_Y; } - ghostBlock.moveBy(newX - ghostPosition.x, newY - ghostPosition.y); + insertionMarker.moveBy(newX - insertionPosition.x, + newY - insertionPosition.y); } - if (localGhostConnection.type == Blockly.PREVIOUS_STATEMENT && - !ghostBlock.nextConnection) { + if (insertionMarkerConnection.type == Blockly.PREVIOUS_STATEMENT && + !insertionMarker.nextConnection) { Blockly.bumpedConnection_ = closestConnection.targetConnection; } - // Renders ghost. - localGhostConnection.connect(closestConnection); + // Renders insertin marker. + insertionMarkerConnection.connect(closestConnection); // Render dragging block so it appears on top. this.workspace.getCanvas().appendChild(this.getSvgRoot()); - Blockly.localGhostConnection_ = localGhostConnection; + Blockly.insertionMarkerConnection_ = insertionMarkerConnection; } } // Reenable events. @@ -949,40 +950,40 @@ Blockly.BlockSvg.prototype.updatePreviews = function(closestConnection, }; /** - * Disconnect the current ghost block from the stack, and heal the stack to its - * previous state. + * Disconnect the current insertion marker from the stack, and heal the stack to + * its previous state. */ -Blockly.BlockSvg.prototype.disconnectGhost = function() { - // The ghost block is the first block in a stack, either because it doesn't +Blockly.BlockSvg.prototype.disconnectInsertionMarker = function() { + // The insertion marker is the first block in a stack, either because it doesn't // have a previous connection or because the previous connection is not // connection. Unplug won't do anything in that case. Instead, unplug the // following block. - if (Blockly.localGhostConnection_ == this.ghostBlock_.nextConnection && - (!this.ghostBlock_.previousConnection || - !this.ghostBlock_.previousConnection.targetConnection)) { - Blockly.localGhostConnection_.targetBlock().unplug(false); + if (Blockly.insertionMarkerConnection_ == this.insertionMarker_.nextConnection && + (!this.insertionMarker_.previousConnection || + !this.insertionMarker_.previousConnection.targetConnection)) { + Blockly.insertionMarkerConnection_.targetBlock().unplug(false); } // Inside of a C-block, first statement connection. - else if (Blockly.localGhostConnection_.type == Blockly.NEXT_STATEMENT && - Blockly.localGhostConnection_ != this.ghostBlock_.nextConnection) { - var innerConnection = Blockly.localGhostConnection_.targetConnection; + else if (Blockly.insertionMarkerConnection_.type == Blockly.NEXT_STATEMENT && + Blockly.insertionMarkerConnection_ != this.insertionMarker_.nextConnection) { + var innerConnection = Blockly.insertionMarkerConnection_.targetConnection; innerConnection.sourceBlock_.unplug(false); var previousBlockNextConnection = - this.ghostBlock_.previousConnection.targetConnection; - this.ghostBlock_.unplug(true); + this.insertionMarker_.previousConnection.targetConnection; + this.insertionMarker_.unplug(true); if (previousBlockNextConnection) { previousBlockNextConnection.connect(innerConnection); } } else { - this.ghostBlock_.unplug(true /* healStack */); + this.insertionMarker_.unplug(true /* healStack */); } - if (Blockly.localGhostConnection_.targetConnection) { - throw 'LocalGhostConnection still connected at the end of disconnectGhost'; + if (Blockly.insertionMarkerConnection_.targetConnection) { + throw 'insertionMarkerConnection still connected at the end of disconnectInsertionMarker'; } - Blockly.localGhostConnection_ = null; - this.ghostBlock_.getSvgRoot().setAttribute('visibility', 'hidden'); + Blockly.insertionMarkerConnection_ = null; + this.insertionMarker_.getSvgRoot().setAttribute('visibility', 'hidden'); }; /** @@ -1030,11 +1031,11 @@ Blockly.BlockSvg.prototype.setShadow = function(shadow) { }; /** - * Set whether this block is a ghost block or not. - * @param {boolean} ghost True if a ghost. + * Set whether this block is an insertion marker block or not. + * @param {boolean} insertionMarker True if an insertion marker. */ -Blockly.BlockSvg.prototype.setGhost = function(ghost) { - Blockly.BlockSvg.superClass_.setGhost.call(this, ghost); +Blockly.BlockSvg.prototype.setInsertionMarker = function(insertionMarker) { + Blockly.BlockSvg.superClass_.setInsertionMarker.call(this, insertionMarker); this.updateColour(); }; diff --git a/core/blockly.js b/core/blockly.js index 7a7f51df89..680c3cdbb3 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -83,16 +83,16 @@ Blockly.highlightedConnection_ = null; Blockly.localConnection_ = null; /** - * Connection on ghost block that matches Blockly.localConnecxtion_ on the - * dragged block. + * Connection on the insertion marker block that matches + * Blockly.localConnecxtion_ on the dragged block. * @type {Blockly.Connection} * @private */ -Blockly.localGhostConnection_ = null; +Blockly.insertionMarkerConnection_ = null; /** - * Connection that was bumped out of the way by a ghost block, and may need - * to be put back as the drag continues. + * Connection that was bumped out of the way by an insertion marker, and may + * need to be put back as the drag continues. * @type {Blockly.Connection} * @private */ diff --git a/core/connection.js b/core/connection.js index 67a7db2761..40a011cb09 100644 --- a/core/connection.js +++ b/core/connection.js @@ -296,11 +296,11 @@ Blockly.Connection.prototype.dispose = function() { }; /** - * @return true if the connection is not connected or is connected to a ghost - * block, false otherwise. + * @return {boolean} true if the connection is not connected or is connected to + * an insertion marker, false otherwise. */ -Blockly.Connection.prototype.isConnectedToNonGhost = function() { - return this.targetConnection && !this.targetBlock().isGhost(); +Blockly.Connection.prototype.isConnectedToNonInsertionMarker = function() { + return this.targetConnection && !this.targetBlock().isInsertionMarker(); }; /** @@ -416,10 +416,11 @@ Blockly.Connection.prototype.isConnectionAllowed = function(candidate, return false; } if (candidate.targetConnection) { - // If the other side of this connection is the active ghost + // If the other side of this connection is the active insertion marker // connection, we've obviously already decided that this is a good // connection. - if (candidate.targetConnection == Blockly.localGhostConnection_) { + if (candidate.targetConnection == + Blockly.insertionMarkerConnection_) { return true; } else { return false; @@ -441,7 +442,7 @@ Blockly.Connection.prototype.isConnectionAllowed = function(candidate, // Can't connect this block's next connection unless we're connecting // in front of the first block on a stack. else if (this == this.sourceBlock_.nextConnection && - candidate.isConnectedToNonGhost()) { + candidate.isConnectedToNonInsertionMarker()) { return false; } } @@ -473,13 +474,13 @@ Blockly.Connection.prototype.isConnectionAllowed = function(candidate, // block on a stack or there's already a block connected inside the c. if (firstStatementConnection && this == this.sourceBlock_.previousConnection && - candidate.isConnectedToNonGhost() && + candidate.isConnectedToNonInsertionMarker() && !firstStatementConnection.targetConnection) { return false; } // Don't let a block with no next connection bump other blocks out of the // stack. - if (candidate.isConnectedToNonGhost() && + if (candidate.isConnectedToNonInsertionMarker() && !this.sourceBlock_.nextConnection) { return false; } @@ -505,8 +506,8 @@ Blockly.Connection.prototype.checkBasicCompatibility_ = function(candidate, return false; } - // Don't consider ghost blocks. - if (candidate.sourceBlock_.isGhost()) { + // Don't consider insertion markers. + if (candidate.sourceBlock_.isInsertionMarker()) { return false; } diff --git a/javascript_compressed.js b/javascript_compressed.js index fe1941a466..524af6f847 100644 --- a/javascript_compressed.js +++ b/javascript_compressed.js @@ -10,12 +10,7 @@ Blockly.JavaScript.ORDER_LOGICAL_AND=13;Blockly.JavaScript.ORDER_LOGICAL_OR=14;B Blockly.JavaScript.init=function(a){Blockly.JavaScript.definitions_=Object.create(null);Blockly.JavaScript.functionNames_=Object.create(null);Blockly.JavaScript.variableDB_?Blockly.JavaScript.variableDB_.reset():Blockly.JavaScript.variableDB_=new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_);var b=[];a=Blockly.Variables.allVariables(a);for(var c=0;c",GTE:">="}[a.getFieldValue("OP")],c="=="==b||"!="==b?Blockly.JavaScript.ORDER_EQUALITY:Blockly.JavaScript.ORDER_RELATIONAL,d=Blockly.JavaScript.valueToCode(a,"A",c)||"0";a=Blockly.JavaScript.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; -Blockly.JavaScript.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"&&":"||",c="&&"==b?Blockly.JavaScript.ORDER_LOGICAL_AND:Blockly.JavaScript.ORDER_LOGICAL_OR,d=Blockly.JavaScript.valueToCode(a,"A",c);a=Blockly.JavaScript.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]}; -Blockly.JavaScript.logic_negate=function(a){var b=Blockly.JavaScript.ORDER_LOGICAL_NOT;return["!"+(Blockly.JavaScript.valueToCode(a,"BOOL",b)||"true"),b]};Blockly.JavaScript.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.logic_null=function(a){return["null",Blockly.JavaScript.ORDER_ATOMIC]}; -Blockly.JavaScript.logic_ternary=function(a){var b=Blockly.JavaScript.valueToCode(a,"IF",Blockly.JavaScript.ORDER_CONDITIONAL)||"false",c=Blockly.JavaScript.valueToCode(a,"THEN",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";a=Blockly.JavaScript.valueToCode(a,"ELSE",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.JavaScript.ORDER_CONDITIONAL]};Blockly.JavaScript.looks={};Blockly.JavaScript.looks_say=function(a){a=Blockly.JavaScript.valueToCode(a,"MESSAGE",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0";var b="";Blockly.JavaScript.variableDB_.getDistinctName("message",Blockly.Variables.NAME_TYPE);return b+("console.log("+a+");\n")};Blockly.JavaScript.loops={}; -Blockly.JavaScript.controls_repeat_ext=function(a){var b=a.getField("TIMES")?String(Number(a.getFieldValue("TIMES"))):Blockly.JavaScript.valueToCode(a,"TIMES",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0",c=Blockly.JavaScript.statementToCode(a,"DO"),c=Blockly.JavaScript.addLoopTrap(c,a.id);a="";var d=Blockly.JavaScript.variableDB_.getDistinctName("count",Blockly.Variables.NAME_TYPE),e=b;b.match(/^\w+$/)||Blockly.isNumber(b)||(e=Blockly.JavaScript.variableDB_.getDistinctName("repeat_end",Blockly.Variables.NAME_TYPE), -a+="var "+e+" = "+b+";\n");return a+("for (var "+d+" = 0; "+d+" < "+e+"; "+d+"++) {\n"+c+"}\n")};Blockly.JavaScript.controls_repeat=Blockly.JavaScript.controls_repeat_ext; -Blockly.JavaScript.controls_whileUntil=function(a){var b="UNTIL"==a.getFieldValue("MODE"),c=Blockly.JavaScript.valueToCode(a,"BOOL",b?Blockly.JavaScript.ORDER_LOGICAL_NOT:Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO"),d=Blockly.JavaScript.addLoopTrap(d,a.id);b&&(c="!"+c);return"while ("+c+") {\n"+d+"}\n"}; -Blockly.JavaScript.controls_for=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0",d=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0",e=Blockly.JavaScript.valueToCode(a,"BY",Blockly.JavaScript.ORDER_ASSIGNMENT)||"1",f=Blockly.JavaScript.statementToCode(a,"DO"),f=Blockly.JavaScript.addLoopTrap(f,a.id);if(Blockly.isNumber(c)&&Blockly.isNumber(d)&& -Blockly.isNumber(e)){var g=parseFloat(c)<=parseFloat(d);a="for ("+b+" = "+c+"; "+b+(g?" <= ":" >= ")+d+"; "+b;b=Math.abs(parseFloat(e));a=(1==b?a+(g?"++":"--"):a+((g?" += ":" -= ")+b))+(") {\n"+f+"}\n")}else a="",g=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(g=Blockly.JavaScript.variableDB_.getDistinctName(b+"_start",Blockly.Variables.NAME_TYPE),a+="var "+g+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.JavaScript.variableDB_.getDistinctName(b+"_end",Blockly.Variables.NAME_TYPE), -a+="var "+c+" = "+d+";\n"),d=Blockly.JavaScript.variableDB_.getDistinctName(b+"_inc",Blockly.Variables.NAME_TYPE),a+="var "+d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("Math.abs("+e+");\n"),a+="if ("+g+" > "+c+") {\n",a+=Blockly.JavaScript.INDENT+d+" = -"+d+";\n",a+="}\n",a+="for ("+b+" = "+g+";\n "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+";\n "+b+" += "+d+") {\n"+f+"}\n";return a}; -Blockly.JavaScript.controls_forEach=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_ASSIGNMENT)||"[]",d=Blockly.JavaScript.statementToCode(a,"DO"),d=Blockly.JavaScript.addLoopTrap(d,a.id);a="";var e=c;c.match(/^\w+$/)||(e=Blockly.JavaScript.variableDB_.getDistinctName(b+"_list",Blockly.Variables.NAME_TYPE),a+="var "+e+" = "+c+";\n");c=Blockly.JavaScript.variableDB_.getDistinctName(b+ -"_index",Blockly.Variables.NAME_TYPE);d=Blockly.JavaScript.INDENT+b+" = "+e+"["+c+"];\n"+d;return a+("for (var "+c+" in "+e+") {\n"+d+"}\n")};Blockly.JavaScript.controls_flow_statements=function(a){switch(a.getFieldValue("FLOW")){case "BREAK":return"break;\n";case "CONTINUE":return"continue;\n"}throw"Unknown flow statement.";};Blockly.JavaScript.math={};Blockly.JavaScript.math_number=function(a){return[parseFloat(a.getFieldValue("NUM")),Blockly.JavaScript.ORDER_ATOMIC]}; +"}"])+"("+b+", '"+c+"', "+e+", '"+d+"', "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.lists_split=function(a){var b=Blockly.JavaScript.valueToCode(a,"INPUT",Blockly.JavaScript.ORDER_MEMBER),c=Blockly.JavaScript.valueToCode(a,"DELIM",Blockly.JavaScript.ORDER_NONE)||"''";a=a.getFieldValue("MODE");if("SPLIT"==a)b||(b="''"),a="split";else if("JOIN"==a)b||(b="[]"),a="join";else throw"Unknown mode: "+a;return[b+"."+a+"("+c+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.looks={};Blockly.JavaScript.looks_say=function(a){a=Blockly.JavaScript.valueToCode(a,"MESSAGE",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0";var b="";Blockly.JavaScript.variableDB_.getDistinctName("message",Blockly.Variables.NAME_TYPE);return b+("console.log("+a+");\n")};Blockly.JavaScript.motion={};Blockly.JavaScript.motion_moveright=function(a){return"moveRight();\n"};Blockly.JavaScript.math={};Blockly.JavaScript.math_number=function(a){return[parseFloat(a.getFieldValue("NUM")),Blockly.JavaScript.ORDER_ATOMIC]}; Blockly.JavaScript.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.JavaScript.ORDER_ADDITION],MINUS:[" - ",Blockly.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[" * ",Blockly.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[" / ",Blockly.JavaScript.ORDER_DIVISION],POWER:[null,Blockly.JavaScript.ORDER_COMMA]}[a.getFieldValue("OP")],c=b[0],b=b[1],d=Blockly.JavaScript.valueToCode(a,"A",b)||"0";a=Blockly.JavaScript.valueToCode(a,"B",b)||"0";return c?[d+c+a,b]:["Math.pow("+d+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; Blockly.JavaScript.math_single=function(a){var b=a.getFieldValue("OP"),c;if("NEG"==b)return a=Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_UNARY_NEGATION)||"0","-"==a[0]&&(a=" "+a),["-"+a,Blockly.JavaScript.ORDER_UNARY_NEGATION];a="SIN"==b||"COS"==b||"TAN"==b?Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_DIVISION)||"0":Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_NONE)||"0";switch(b){case "ABS":c="Math.abs("+a+")";break;case "ROOT":c="Math.sqrt("+ a+")";break;case "LN":c="Math.log("+a+")";break;case "EXP":c="Math.exp("+a+")";break;case "POW10":c="Math.pow(10,"+a+")";break;case "ROUND":c="Math.round("+a+")";break;case "ROUNDUP":c="Math.ceil("+a+")";break;case "ROUNDDOWN":c="Math.floor("+a+")";break;case "SIN":c="Math.sin("+a+" / 180 * Math.PI)";break;case "COS":c="Math.cos("+a+" / 180 * Math.PI)";break;case "TAN":c="Math.tan("+a+" / 180 * Math.PI)"}if(c)return[c,Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(b){case "LOG10":c="Math.log("+a+ @@ -62,7 +44,12 @@ Blockly.JavaScript.math_on_list=function(a){var b=a.getFieldValue("OP");switch(b "LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;default:throw"Unknown operator: "+b;}return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_modulo=function(a){var b=Blockly.JavaScript.valueToCode(a,"DIVIDEND",Blockly.JavaScript.ORDER_MODULUS)||"0";a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0";return[b+" % "+a,Blockly.JavaScript.ORDER_MODULUS]}; Blockly.JavaScript.math_constrain=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_COMMA)||"0",c=Blockly.JavaScript.valueToCode(a,"LOW",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"HIGH",Blockly.JavaScript.ORDER_COMMA)||"Infinity";return["Math.min(Math.max("+b+", "+c+"), "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; Blockly.JavaScript.math_random_int=function(a){var b=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_COMMA)||"0";return[Blockly.JavaScript.provideFunction_("math_random_int",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(a, b) {"," if (a > b) {"," // Swap a and b to ensure a is smaller."," var c = a;"," a = b;"," b = c;"," }"," return Math.floor(Math.random() * (b - a + 1) + a);", -"}"])+"("+b+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_random_float=function(a){return["Math.random()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.motion={};Blockly.JavaScript.motion_moveright=function(a){return"moveRight();\n"};Blockly.JavaScript.procedures={}; +"}"])+"("+b+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_random_float=function(a){return["Math.random()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.variables={};Blockly.JavaScript.variables_get=function(a){return[Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.variables_set=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0";return Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" = "+b+";\n"};Blockly.JavaScript.colour={};Blockly.JavaScript.colour_picker=function(a){return["'"+a.getFieldValue("COLOUR")+"'",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.colour_random=function(a){return[Blockly.JavaScript.provideFunction_("colour_random",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"() {"," var num = Math.floor(Math.random() * Math.pow(2, 24));"," return '#' + ('00000' + num.toString(16)).substr(-6);","}"])+"()",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.colour_rgb=function(a){var b=Blockly.JavaScript.valueToCode(a,"RED",Blockly.JavaScript.ORDER_COMMA)||0,c=Blockly.JavaScript.valueToCode(a,"GREEN",Blockly.JavaScript.ORDER_COMMA)||0;a=Blockly.JavaScript.valueToCode(a,"BLUE",Blockly.JavaScript.ORDER_COMMA)||0;return[Blockly.JavaScript.provideFunction_("colour_rgb",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b) {"," r = Math.max(Math.min(Number(r), 100), 0) * 2.55;"," g = Math.max(Math.min(Number(g), 100), 0) * 2.55;", +" b = Math.max(Math.min(Number(b), 100), 0) * 2.55;"," r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);"," g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);"," b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.colour_blend=function(a){var b=Blockly.JavaScript.valueToCode(a,"COLOUR1",Blockly.JavaScript.ORDER_COMMA)||"'#000000'",c=Blockly.JavaScript.valueToCode(a,"COLOUR2",Blockly.JavaScript.ORDER_COMMA)||"'#000000'";a=Blockly.JavaScript.valueToCode(a,"RATIO",Blockly.JavaScript.ORDER_COMMA)||.5;return[Blockly.JavaScript.provideFunction_("colour_blend",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(c1, c2, ratio) {"," ratio = Math.max(Math.min(Number(ratio), 1), 0);"," var r1 = parseInt(c1.substring(1, 3), 16);", +" var g1 = parseInt(c1.substring(3, 5), 16);"," var b1 = parseInt(c1.substring(5, 7), 16);"," var r2 = parseInt(c2.substring(1, 3), 16);"," var g2 = parseInt(c2.substring(3, 5), 16);"," var b2 = parseInt(c2.substring(5, 7), 16);"," var r = Math.round(r1 * (1 - ratio) + r2 * ratio);"," var g = Math.round(g1 * (1 - ratio) + g2 * ratio);"," var b = Math.round(b1 * (1 - ratio) + b2 * ratio);"," r = ('0' + (r || 0).toString(16)).slice(-2);"," g = ('0' + (g || 0).toString(16)).slice(-2);"," b = ('0' + (b || 0).toString(16)).slice(-2);", +" return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.procedures={}; Blockly.JavaScript.procedures_defreturn=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("NAME"),Blockly.Procedures.NAME_TYPE),c=Blockly.JavaScript.statementToCode(a,"STACK");Blockly.JavaScript.STATEMENT_PREFIX&&(c=Blockly.JavaScript.prefixLines(Blockly.JavaScript.STATEMENT_PREFIX.replace(/%1/g,"'"+a.id+"'"),Blockly.JavaScript.INDENT)+c);Blockly.JavaScript.INFINITE_LOOP_TRAP&&(c=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+c);var d=Blockly.JavaScript.valueToCode(a, "RETURN",Blockly.JavaScript.ORDER_NONE)||"";d&&(d=" return "+d+";\n");for(var e=[],f=0;f= ")+d+"; "+b;b=Math.abs(parseFloat(e));a=(1==b?a+(g?"++":"--"):a+((g?" += ":" -= ")+b))+(") {\n"+f+"}\n")}else a="",g=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(g=Blockly.JavaScript.variableDB_.getDistinctName(b+"_start",Blockly.Variables.NAME_TYPE),a+="var "+g+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.JavaScript.variableDB_.getDistinctName(b+"_end",Blockly.Variables.NAME_TYPE), +a+="var "+c+" = "+d+";\n"),d=Blockly.JavaScript.variableDB_.getDistinctName(b+"_inc",Blockly.Variables.NAME_TYPE),a+="var "+d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("Math.abs("+e+");\n"),a+="if ("+g+" > "+c+") {\n",a+=Blockly.JavaScript.INDENT+d+" = -"+d+";\n",a+="}\n",a+="for ("+b+" = "+g+";\n "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+";\n "+b+" += "+d+") {\n"+f+"}\n";return a}; +Blockly.JavaScript.controls_forEach=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_ASSIGNMENT)||"[]",d=Blockly.JavaScript.statementToCode(a,"DO"),d=Blockly.JavaScript.addLoopTrap(d,a.id);a="";var e=c;c.match(/^\w+$/)||(e=Blockly.JavaScript.variableDB_.getDistinctName(b+"_list",Blockly.Variables.NAME_TYPE),a+="var "+e+" = "+c+";\n");c=Blockly.JavaScript.variableDB_.getDistinctName(b+ +"_index",Blockly.Variables.NAME_TYPE);d=Blockly.JavaScript.INDENT+b+" = "+e+"["+c+"];\n"+d;return a+("for (var "+c+" in "+e+") {\n"+d+"}\n")};Blockly.JavaScript.controls_flow_statements=function(a){switch(a.getFieldValue("FLOW")){case "BREAK":return"break;\n";case "CONTINUE":return"continue;\n"}throw"Unknown flow statement.";};Blockly.JavaScript.logic={}; +Blockly.JavaScript.controls_if=function(a){for(var b=0,c=Blockly.JavaScript.valueToCode(a,"IF"+b,Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO"+b),e="if ("+c+") {\n"+d+"}",b=1;b<=a.elseifCount_;b++)c=Blockly.JavaScript.valueToCode(a,"IF"+b,Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO"+b),e+=" else if ("+c+") {\n"+d+"}";a.elseCount_&&(d=Blockly.JavaScript.statementToCode(a,"ELSE"),e+=" else {\n"+d+"}");return e+"\n"}; +Blockly.JavaScript.logic_compare=function(a){var b={EQ:"==",NEQ:"!=",LT:"<",LTE:"<=",GT:">",GTE:">="}[a.getFieldValue("OP")],c="=="==b||"!="==b?Blockly.JavaScript.ORDER_EQUALITY:Blockly.JavaScript.ORDER_RELATIONAL,d=Blockly.JavaScript.valueToCode(a,"A",c)||"0";a=Blockly.JavaScript.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; +Blockly.JavaScript.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"&&":"||",c="&&"==b?Blockly.JavaScript.ORDER_LOGICAL_AND:Blockly.JavaScript.ORDER_LOGICAL_OR,d=Blockly.JavaScript.valueToCode(a,"A",c);a=Blockly.JavaScript.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]}; +Blockly.JavaScript.logic_negate=function(a){var b=Blockly.JavaScript.ORDER_LOGICAL_NOT;return["!"+(Blockly.JavaScript.valueToCode(a,"BOOL",b)||"true"),b]};Blockly.JavaScript.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.logic_null=function(a){return["null",Blockly.JavaScript.ORDER_ATOMIC]}; +Blockly.JavaScript.logic_ternary=function(a){var b=Blockly.JavaScript.valueToCode(a,"IF",Blockly.JavaScript.ORDER_CONDITIONAL)||"false",c=Blockly.JavaScript.valueToCode(a,"THEN",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";a=Blockly.JavaScript.valueToCode(a,"ELSE",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.JavaScript.ORDER_CONDITIONAL]}; \ No newline at end of file diff --git a/tests/jsunit/connection_db_test.js b/tests/jsunit/connection_db_test.js index ca680addf6..24b16de52a 100644 --- a/tests/jsunit/connection_db_test.js +++ b/tests/jsunit/connection_db_test.js @@ -282,7 +282,7 @@ function helper_makeSourceBlock(sharedWorkspace) { movable_: true, isMovable: function() { return true; }, isShadow: function() { return false; }, - isGhost: function() { return false; }, + isInsertionMarker: function() { return false; }, getFirstStatementConnection: function() { return null; } }; } diff --git a/tests/jsunit/connection_test.js b/tests/jsunit/connection_test.js index c09c155fd7..5b66b52e22 100644 --- a/tests/jsunit/connection_test.js +++ b/tests/jsunit/connection_test.js @@ -298,18 +298,18 @@ function test_isConnectionAllowed_NoNext() { assertFalse(two.isConnectionAllowed(one, 1000.0)); } -function test_isConnectionAllowed_Ghost() { +function test_isConnectionAllowed_InsertionMarker() { var sharedWorkspace = {}; // Two connections of opposite types near each other. var one = helper_createConnection(5 /* x */, 10 /* y */, Blockly.INPUT_VALUE); one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); - // The second one is a ghost. + // The second one is an insertion marker. var two = helper_createConnection(10 /* x */, 15 /* y */, Blockly.OUTPUT_VALUE); two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace); - two.sourceBlock_.isGhost = function() { + two.sourceBlock_.isInsertionMarker = function() { return true; }; From 3a07be9b5c2ee57119f8a93ee95378ff3b2c667c Mon Sep 17 00:00:00 2001 From: rachel-fenichel Date: Wed, 6 Apr 2016 14:57:16 -0700 Subject: [PATCH 2/2] Store a single global insertion marker instead on one per block --- core/block.js | 6 ------ core/block_svg.js | 48 ++++++++++++++++++++++++----------------------- core/blockly.js | 10 +++++++++- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/core/block.js b/core/block.js index 08ba5bae39..6cfa2a2972 100644 --- a/core/block.js +++ b/core/block.js @@ -100,8 +100,6 @@ Blockly.Block = function(workspace, prototypeName, opt_id) { /** @type {boolean} */ this.RTL = workspace.RTL; - /** @type {Blockly.Block} */ - this.insertionMarker_ = null; /** @type {boolean} */ this.isInsertionMarker_ = false; @@ -208,10 +206,6 @@ Blockly.Block.prototype.dispose = function(healStack) { Blockly.selected = null; } - if (this.insertionMarker_) { - this.insertionMarker_.dispose(); - } - // First, dispose of all my children. for (var i = this.childBlocks_.length - 1; i >= 0; i--) { this.childBlocks_[i].dispose(false); diff --git a/core/block_svg.js b/core/block_svg.js index e9d8ad5c31..5a62247b43 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -237,13 +237,13 @@ Blockly.BlockSvg.terminateDrag_ = function() { if (Blockly.dragMode_ == Blockly.DRAG_FREE) { // Terminate a drag operation. if (selected) { - if (selected.insertionMarker_) { + if (Blockly.insertionMarker_) { Blockly.Events.disable(); if (Blockly.insertionMarkerConnection_) { - selected.disconnectInsertionMarker(); + Blockly.BlockSvg.disconnectInsertionMarker(); } - selected.insertionMarker_.dispose(); - selected.insertionMarker_ = null; + Blockly.insertionMarker_.dispose(); + Blockly.insertionMarker_ = null; Blockly.Events.enable(); } // Update the connection locations. @@ -883,8 +883,8 @@ Blockly.BlockSvg.prototype.updatePreviews = function(closestConnection, // with Web Blockly the name "highlightedConnection" will still be used. if (Blockly.highlightedConnection_ && Blockly.highlightedConnection_ != closestConnection) { - if (this.insertionMarker_ && Blockly.insertionMarkerConnection_) { - this.disconnectInsertionMarker(); + if (Blockly.insertionMarker_ && Blockly.insertionMarkerConnection_) { + Blockly.BlockSvg.disconnectInsertionMarker(); } Blockly.highlightedConnection_ = null; Blockly.localConnection_ = null; @@ -896,13 +896,13 @@ Blockly.BlockSvg.prototype.updatePreviews = function(closestConnection, !closestConnection.sourceBlock_.isInsertionMarker()) { Blockly.highlightedConnection_ = closestConnection; Blockly.localConnection_ = localConnection; - if (!this.insertionMarker_){ - this.insertionMarker_ = this.workspace.newBlock(this.type); - this.insertionMarker_.setInsertionMarker(true); - this.insertionMarker_.initSvg(); + if (!Blockly.insertionMarker_){ + Blockly.insertionMarker_ = this.workspace.newBlock(this.type); + Blockly.insertionMarker_.setInsertionMarker(true); + Blockly.insertionMarker_.initSvg(); } - var insertionMarker = this.insertionMarker_; + var insertionMarker = Blockly.insertionMarker_; var insertionMarkerConnection = insertionMarker.getMatchingConnection(this, localConnection); if (insertionMarkerConnection != Blockly.insertionMarkerConnection_) { @@ -953,37 +953,39 @@ Blockly.BlockSvg.prototype.updatePreviews = function(closestConnection, * Disconnect the current insertion marker from the stack, and heal the stack to * its previous state. */ -Blockly.BlockSvg.prototype.disconnectInsertionMarker = function() { - // The insertion marker is the first block in a stack, either because it doesn't - // have a previous connection or because the previous connection is not - // connection. Unplug won't do anything in that case. Instead, unplug the +Blockly.BlockSvg.disconnectInsertionMarker = function() { + // The insertion marker is the first block in a stack, either because it + // doesn't have a previous connection or because the previous connection is + // not connected. Unplug won't do anything in that case. Instead, unplug the // following block. - if (Blockly.insertionMarkerConnection_ == this.insertionMarker_.nextConnection && - (!this.insertionMarker_.previousConnection || - !this.insertionMarker_.previousConnection.targetConnection)) { + if (Blockly.insertionMarkerConnection_ == + Blockly.insertionMarker_.nextConnection && + (!Blockly.insertionMarker_.previousConnection || + !Blockly.insertionMarker_.previousConnection.targetConnection)) { Blockly.insertionMarkerConnection_.targetBlock().unplug(false); } // Inside of a C-block, first statement connection. else if (Blockly.insertionMarkerConnection_.type == Blockly.NEXT_STATEMENT && - Blockly.insertionMarkerConnection_ != this.insertionMarker_.nextConnection) { + Blockly.insertionMarkerConnection_ != + Blockly.insertionMarker_.nextConnection) { var innerConnection = Blockly.insertionMarkerConnection_.targetConnection; innerConnection.sourceBlock_.unplug(false); var previousBlockNextConnection = - this.insertionMarker_.previousConnection.targetConnection; - this.insertionMarker_.unplug(true); + Blockly.insertionMarker_.previousConnection.targetConnection; + Blockly.insertionMarker_.unplug(true); if (previousBlockNextConnection) { previousBlockNextConnection.connect(innerConnection); } } else { - this.insertionMarker_.unplug(true /* healStack */); + Blockly.insertionMarker_.unplug(true /* healStack */); } if (Blockly.insertionMarkerConnection_.targetConnection) { throw 'insertionMarkerConnection still connected at the end of disconnectInsertionMarker'; } Blockly.insertionMarkerConnection_ = null; - this.insertionMarker_.getSvgRoot().setAttribute('visibility', 'hidden'); + Blockly.insertionMarker_.getSvgRoot().setAttribute('visibility', 'hidden'); }; /** diff --git a/core/blockly.js b/core/blockly.js index 680c3cdbb3..b04f7f32e3 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -84,12 +84,20 @@ Blockly.localConnection_ = null; /** * Connection on the insertion marker block that matches - * Blockly.localConnecxtion_ on the dragged block. + * Blockly.localConnection_ on the dragged block. * @type {Blockly.Connection} * @private */ Blockly.insertionMarkerConnection_ = null; +/** + * Grayed-out block that indicates to the user what will happen if they release + * a drag immediately. + * @type {Blockly.Block} + * @private + */ +Blockly.insertionMarker_ = null; + /** * Connection that was bumped out of the way by an insertion marker, and may * need to be put back as the drag continues.