diff --git a/core/gesture.js b/core/gesture.js index 3de14fc38..e7f99102f 100644 --- a/core/gesture.js +++ b/core/gesture.js @@ -489,7 +489,7 @@ Blockly.Gesture.prototype.doStart = function(e) { e.shiftKey && this.targetBlock_.workspace.keyboardAccessibilityMode) { this.creatorWorkspace_.getCursor().setCurNode( - Blockly.navigation.getTopNode(this.targetBlock_)); + Blockly.ASTNode.createTopNode(this.targetBlock_)); } else { this.targetBlock_.select(); } diff --git a/core/keyboard_nav/ast_node.js b/core/keyboard_nav/ast_node.js index 4f111b84c..cd9c94c67 100644 --- a/core/keyboard_nav/ast_node.js +++ b/core/keyboard_nav/ast_node.js @@ -199,6 +199,24 @@ Blockly.ASTNode.createWorkspaceNode = function(workspace, wsCoordinate) { Blockly.ASTNode.types.WORKSPACE, workspace, params); }; +/** + * Creates an AST node for the top position on a block. + * This is either an output connection, previous connection, or block. + * @param {!Blockly.Block} block The block to find the top most AST node on. + * @return {Blockly.ASTNode} The AST node holding the top most position on the + * block. + */ +Blockly.ASTNode.createTopNode = function(block) { + var astNode; + var topConnection = block.previousConnection || block.outputConnection; + if (topConnection) { + astNode = Blockly.ASTNode.createConnectionNode(topConnection); + } else { + astNode = Blockly.ASTNode.createBlockNode(block); + } + return astNode; +}; + /** * Parse the optional parameters. * @param {Object} params The user specified parameters. diff --git a/core/keyboard_nav/navigation.js b/core/keyboard_nav/navigation.js index 385ef676a..d37fe9973 100644 --- a/core/keyboard_nav/navigation.js +++ b/core/keyboard_nav/navigation.js @@ -167,7 +167,7 @@ Blockly.navigation.focusWorkspace_ = function() { Blockly.navigation.resetFlyout_(reset); Blockly.navigation.currentState_ = Blockly.navigation.STATE_WS; if (topBlocks.length > 0) { - cursor.setCurNode(Blockly.navigation.getTopNode(topBlocks[0])); + cursor.setCurNode(Blockly.ASTNode.createTopNode(topBlocks[0])); } else { // TODO: Find the center of the visible workspace. var wsCoord = new Blockly.utils.Coordinate(100, 100); @@ -230,7 +230,7 @@ Blockly.navigation.insertFromFlyout = function() { } Blockly.navigation.focusWorkspace_(); - workspace.getCursor().setCurNode(Blockly.navigation.getTopNode(newBlock)); + workspace.getCursor().setCurNode(Blockly.ASTNode.createTopNode(newBlock)); Blockly.navigation.removeMark_(); }; @@ -606,25 +606,6 @@ Blockly.navigation.setState = function(newState) { Blockly.navigation.currentState_ = newState; }; -/** - * Gets the top node on a block. - * This is either the previous connection, output connection or the block. - * @param {!Blockly.Block} block The block to find the top most AST node on. - * @return {Blockly.ASTNode} The AST node holding the top most node on the - * block. - * @package - */ -Blockly.navigation.getTopNode = function(block) { - var astNode; - var topConnection = block.previousConnection || block.outputConnection; - if (topConnection) { - astNode = Blockly.ASTNode.createConnectionNode(topConnection); - } else { - astNode = Blockly.ASTNode.createBlockNode(block); - } - return astNode; -}; - /** * Before a block is deleted move the cursor to the appropriate position. * @param {!Blockly.Block} deletedBlock The block that is being deleted. diff --git a/core/renderers/common/marker_svg.js b/core/renderers/common/marker_svg.js index a9b005b88..ce3225890 100644 --- a/core/renderers/common/marker_svg.js +++ b/core/renderers/common/marker_svg.js @@ -85,8 +85,7 @@ Blockly.blockRendering.MarkerSvg.MARKER_CLASS = 'blocklyMarker'; /** * What we multiply the height by to get the height of the marker. * Only used for the block and block connections. - * @type {number} - * @const + * @const {number} */ Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER = 3 / 4; @@ -98,6 +97,14 @@ Blockly.blockRendering.MarkerSvg.prototype.getSvgRoot = function() { return this.svgGroup_; }; +/** + * Get the marker. + * @return {!Blockly.Marker} The marker to draw for. + */ +Blockly.blockRendering.MarkerSvg.prototype.getMarker = function() { + return this.marker_; +}; + /** * True if the marker should be drawn as a cursor, false otherwise. * A cursor is drawn as a flashing line. A marker is drawn as a solid line. @@ -123,7 +130,6 @@ Blockly.blockRendering.MarkerSvg.prototype.createDom = function() { }, null); this.createDomInternal_(); - this.applyColour_(); return this.svgGroup_; }; @@ -149,6 +155,61 @@ Blockly.blockRendering.MarkerSvg.prototype.setParent_ = function(newParent) { this.parent_ = newParent; }; +/** + * Update the marker. + * @param {Blockly.ASTNode} oldNode The previous node the marker was on or null. + * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. + */ +Blockly.blockRendering.MarkerSvg.prototype.draw = function(oldNode, curNode) { + if (!curNode) { + this.hide(); + return; + } + + this.constants_ = this.workspace_.getRenderer().getConstants(); + + var defaultColour = this.isCursor() ? this.constants_.CURSOR_COLOUR : + this.constants_.MARKER_COLOUR; + this.colour_ = this.marker_.colour || defaultColour; + this.applyColour_(curNode); + + this.showAtLocation_(curNode); + + this.fireMarkerEvent_(oldNode, curNode); + + // Ensures the marker will be visible immediately after the move. + var animate = this.currentMarkerSvg.childNodes[0]; + if (animate !== undefined) { + animate.beginElement && animate.beginElement(); + } +}; + + +/** + * Update the marker's visible state based on the type of curNode.. + * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) { + if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { + this.showWithBlock_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) { + this.showWithOutput_(curNode); + } else if (curNode.getLocation().type == Blockly.INPUT_VALUE) { + this.showWithInput_(curNode); + } else if (curNode.getLocation().type == Blockly.NEXT_STATEMENT) { + this.showWithNext_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS) { + this.showWithPrevious_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.FIELD) { + this.showWithField_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.WORKSPACE) { + this.showWithCoordinates_(curNode); + } else if (curNode.getType() == Blockly.ASTNode.types.STACK) { + this.showWithStack_(curNode); + } +}; + /************************** * Display **************************/ @@ -156,13 +217,12 @@ Blockly.blockRendering.MarkerSvg.prototype.setParent_ = function(newParent) { /** * Show the marker as a combination of the previous connection and block, * the output connection and block, or just the block. - * @param {Blockly.BlockSvg} block The block the marker is currently on. - * @protected + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @private */ -Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function(block) { - if (!block) { - return; - } +Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function( + curNode) { + var block = /** @type {!Blockly.BlockSvg} */ (curNode.getSourceBlock()); var width = block.width; var height = block.height; var markerHeight = height * Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER; @@ -177,18 +237,46 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function(b } else { this.positionBlock_(width, markerOffset, markerHeight); } - this.setParent_(block); this.showCurrent_(); }; /** - * Show the visual representation of a workspace coordinate. - * This is a horizontal line. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * Position and display the marker for a block. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showWithBlock_ = function(curNode) { + this.showWithBlockPrevOutput_(curNode); +}; + +/** + * Position and display the marker for a previous connection. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showWithPrevious_ = function( + curNode) { + this.showWithBlockPrevOutput_(curNode); +}; + +/** + * Position and display the marker for an output connection. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showWithOutput_ = function(curNode) { + this.showWithBlockPrevOutput_(curNode); +}; + +/** + * Position and display the marker for a workspace coordinate. + * This is a horizontal line. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @protected + */ +Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function( + curNode) { var wsCoordinate = curNode.getWsCoordinate(); var x = wsCoordinate.x; var y = wsCoordinate.y; @@ -203,9 +291,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function(curNo }; /** - * Show the visual representation of a field. + * Position and display the marker for a field. * This is a box around the field. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithField_ = function(curNode) { @@ -219,9 +307,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithField_ = function(curNode) { }; /** - * Show the visual representation of an input. + * Position and display the marker for an input. * This is a puzzle piece. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithInput_ = function(curNode) { @@ -236,9 +324,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithInput_ = function(curNode) { /** - * Show the visual representation of a next connection. + * Position and display the marker for a next connection. * This is a horizontal line. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithNext_ = function(curNode) { @@ -256,9 +344,9 @@ Blockly.blockRendering.MarkerSvg.prototype.showWithNext_ = function(curNode) { }; /** - * Show the visual representation of a stack. + * Position and display the marker for a stack. * This is a box with extra padding around the entire stack of blocks. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. * @protected */ Blockly.blockRendering.MarkerSvg.prototype.showWithStack_ = function(curNode) { @@ -305,7 +393,7 @@ Blockly.blockRendering.MarkerSvg.prototype.showCurrent_ = function() { * @param {number} width The width of the block. * @param {number} markerOffset The extra padding for around the block. * @param {number} markerHeight The height of the marker. - * @private + * @protected */ Blockly.blockRendering.MarkerSvg.prototype.positionBlock_ = function( width, markerOffset, markerHeight) { @@ -323,10 +411,12 @@ Blockly.blockRendering.MarkerSvg.prototype.positionBlock_ = function( /** * Position the marker for an input connection. * Displays a filled in puzzle piece. - * @param {!Blockly.RenderedConnection} connection The connection to position marker around. - * @private + * @param {!Blockly.RenderedConnection} connection The connection to position + * marker around. + * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(connection) { +Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function( + connection) { var x = connection.getOffsetInBlock().x; var y = connection.getOffsetInBlock().y; @@ -335,7 +425,8 @@ Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(connection) this.markerInput_.setAttribute('d', path); this.markerInput_.setAttribute('transform', - 'translate(' + x + ',' + y + ')' + (this.workspace_.RTL ? ' scale(-1 1)' : '')); + 'translate(' + x + ',' + y + ')' + + (this.workspace_.RTL ? ' scale(-1 1)' : '')); this.currentMarkerSvg = this.markerInput_; }; @@ -347,7 +438,8 @@ Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(connection) * @param {number} width The new width, in workspace units. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function(x, y, width) { +Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function( + x, y, width) { this.markerSvgLine_.setAttribute('x', x); this.markerSvgLine_.setAttribute('y', y); this.markerSvgLine_.setAttribute('width', width); @@ -360,7 +452,7 @@ Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function(x, y, width) * @param {number} width The width of the block. * @param {number} height The height of the block. * @param {!Object} connectionShape The shape object for the connection. - * @private + * @protected */ Blockly.blockRendering.MarkerSvg.prototype.positionOutput_ = function( width, height, connectionShape) { @@ -387,7 +479,7 @@ Blockly.blockRendering.MarkerSvg.prototype.positionOutput_ = function( * @param {number} markerOffset The offset of the marker from around the block. * @param {number} markerHeight The height of the marker. * @param {!Object} connectionShape The shape object for the connection. - * @private + * @protected */ Blockly.blockRendering.MarkerSvg.prototype.positionPrevious_ = function( width, markerOffset, markerHeight, connectionShape) { @@ -415,7 +507,8 @@ Blockly.blockRendering.MarkerSvg.prototype.positionPrevious_ = function( * @param {number} height The new height, in workspace units. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.positionRect_ = function(x, y, width, height) { +Blockly.blockRendering.MarkerSvg.prototype.positionRect_ = function( + x, y, width, height) { this.markerSvgRect_.setAttribute('x', x); this.markerSvgRect_.setAttribute('y', y); this.markerSvgRect_.setAttribute('width', width); @@ -434,7 +527,6 @@ Blockly.blockRendering.MarkerSvg.prototype.flipRtl_ = function(markerSvg) { /** * Hide the marker. - * @package */ Blockly.blockRendering.MarkerSvg.prototype.hide = function() { this.markerSvgLine_.style.display = 'none'; @@ -443,64 +535,6 @@ Blockly.blockRendering.MarkerSvg.prototype.hide = function() { this.markerBlock_.style.display = 'none'; }; -/** - * Update the marker. - * @param {Blockly.ASTNode} oldNode The previous node the marker was on or null. - * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. - * @package - */ -Blockly.blockRendering.MarkerSvg.prototype.draw = function(oldNode, curNode) { - if (!curNode) { - this.hide(); - return; - } - - this.constants_ = this.workspace_.getRenderer().getConstants(); - - var defaultColour = this.isCursor() ? this.constants_.CURSOR_COLOUR : - this.constants_.MARKER_COLOUR; - this.colour_ = this.marker_.colour || defaultColour; - this.applyColour_(); - - this.showAtLocation_(curNode); - - this.firemarkerEvent_(oldNode, curNode); - - // Ensures the marker will be visible immediately after the move. - var animate = this.currentMarkerSvg.childNodes[0]; - if (animate !== undefined) { - animate.beginElement && animate.beginElement(); - } -}; - - -/** - * Update the marker's visible state based on the type of curNode.. - * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. - * @protected - */ -Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) { - if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { - var block = /** @type {Blockly.BlockSvg} */ (curNode.getLocation()); - this.showWithBlockPrevOutput_(block); - } else if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) { - var outputBlock = /** @type {Blockly.BlockSvg} */ (curNode.getLocation().getSourceBlock()); - this.showWithBlockPrevOutput_(outputBlock); - } else if (curNode.getLocation().type == Blockly.INPUT_VALUE) { - this.showWithInput_(curNode); - } else if (curNode.getLocation().type == Blockly.NEXT_STATEMENT) { - this.showWithNext_(curNode); - } else if (curNode.getType() == Blockly.ASTNode.types.PREVIOUS) { - var previousBlock = /** @type {Blockly.BlockSvg} */ (curNode.getLocation().getSourceBlock()); - this.showWithBlockPrevOutput_(previousBlock); - } else if (curNode.getType() == Blockly.ASTNode.types.FIELD) { - this.showWithField_(curNode); - } else if (curNode.getType() == Blockly.ASTNode.types.WORKSPACE) { - this.showWithCoordinates_(curNode); - } else if (curNode.getType() == Blockly.ASTNode.types.STACK) { - this.showWithStack_(curNode); - } -}; /** * Fire event for the marker or marker. @@ -508,7 +542,8 @@ Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) { * @param {!Blockly.ASTNode} curNode The new node the marker is currently on. * @private */ -Blockly.blockRendering.MarkerSvg.prototype.firemarkerEvent_ = function(oldNode, curNode) { +Blockly.blockRendering.MarkerSvg.prototype.fireMarkerEvent_ = function( + oldNode, curNode) { var curBlock = curNode.getSourceBlock(); var eventType = this.isCursor() ? 'cursorMove' : 'markerMove'; var event = new Blockly.Events.Ui(curBlock, eventType, oldNode, curNode); @@ -555,7 +590,8 @@ Blockly.blockRendering.MarkerSvg.prototype.createDomInternal_ = function() { 'height': this.constants_.WS_CURSOR_HEIGHT }, this.svgGroup_); - // A horizontal line used to represent a workspace coordinate or next connection. + // A horizontal line used to represent a workspace coordinate or next + // connection. this.markerSvgLine_ = Blockly.utils.dom.createSvgElement('rect', { 'width': this.constants_.CURSOR_WS_WIDTH, @@ -609,9 +645,11 @@ Blockly.blockRendering.MarkerSvg.prototype.createDomInternal_ = function() { /** * Apply the marker's colour. + * @param {!Blockly.ASTNode} _curNode The node that we want to draw the marker + * for. * @protected */ -Blockly.blockRendering.MarkerSvg.prototype.applyColour_ = function() { +Blockly.blockRendering.MarkerSvg.prototype.applyColour_ = function(_curNode) { this.markerSvgLine_.setAttribute('fill', this.colour_); this.markerSvgRect_.setAttribute('stroke', this.colour_); this.markerInput_.setAttribute('fill', this.colour_); @@ -627,7 +665,6 @@ Blockly.blockRendering.MarkerSvg.prototype.applyColour_ = function() { /** * Dispose of this marker. - * @package */ Blockly.blockRendering.MarkerSvg.prototype.dispose = function() { if (this.svgGroup_) { diff --git a/core/renderers/zelos/marker_svg.js b/core/renderers/zelos/marker_svg.js index 7c9bdd120..a118f76c4 100644 --- a/core/renderers/zelos/marker_svg.js +++ b/core/renderers/zelos/marker_svg.js @@ -32,9 +32,11 @@ Blockly.utils.object.inherits(Blockly.zelos.MarkerSvg, Blockly.blockRendering.MarkerSvg); /** - * @override + * Position and display the marker for an input or an output connection. + * @param {!Blockly.ASTNode} curNode The node to draw the marker for. + * @private */ -Blockly.zelos.MarkerSvg.prototype.showWithInput_ = function(curNode) { +Blockly.zelos.MarkerSvg.prototype.showWithInputOutput_ = function(curNode) { var block = /** @type {!Blockly.BlockSvg} */ (curNode.getSourceBlock()); var connection = curNode.getLocation(); var offsetInBlock = connection.getOffsetInBlock(); @@ -44,6 +46,20 @@ Blockly.zelos.MarkerSvg.prototype.showWithInput_ = function(curNode) { this.showCurrent_(); }; +/** + * @override + */ +Blockly.zelos.MarkerSvg.prototype.showWithOutput_ = function(curNode) { + this.showWithInputOutput_(curNode); +}; + +/** + * @override + */ +Blockly.zelos.MarkerSvg.prototype.showWithInput_ = function(curNode) { + this.showWithInputOutput_(curNode); +}; + /** * Draw a rectangle around the block. * @param {!Blockly.ASTNode} curNode The current node of the marker. @@ -72,25 +88,6 @@ Blockly.zelos.MarkerSvg.prototype.positionCircle_ = function(x, y) { this.currentMarkerSvg = this.markerCircle_; }; -/** - * @override - */ -Blockly.zelos.MarkerSvg.prototype.showAtLocation_ = function(curNode) { - var handled = false; - if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) { - // Inputs and outputs are drawn the same. - this.showWithInput_(curNode); - handled = true; - } else if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { - this.showWithBlock_(curNode); - handled = true; - } - - if (!handled) { - Blockly.zelos.MarkerSvg.superClass_.showAtLocation_.call(this, curNode); - } -}; - /** * @override */ @@ -134,8 +131,8 @@ Blockly.zelos.MarkerSvg.prototype.createDomInternal_ = function() { /** * @override */ -Blockly.zelos.MarkerSvg.prototype.applyColour_ = function() { - Blockly.zelos.MarkerSvg.superClass_.applyColour_.call(this); +Blockly.zelos.MarkerSvg.prototype.applyColour_ = function(curNode) { + Blockly.zelos.MarkerSvg.superClass_.applyColour_.call(this, curNode); this.markerCircle_.setAttribute('fill', this.colour_); this.markerCircle_.setAttribute('stroke', this.colour_); diff --git a/tests/mocha/astnode_test.js b/tests/mocha/astnode_test.js index 2d0b111a7..1e9a69c71 100644 --- a/tests/mocha/astnode_test.js +++ b/tests/mocha/astnode_test.js @@ -169,112 +169,176 @@ suite('ASTNode', function() { }); suite('NavigationFunctions', function() { + setup(function() { + Blockly.defineBlocksWithJsonArray([{ + "type": "top_connection", + "message0": "", + "previousStatement": null, + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "start_block", + "message0": "", + "nextStatement": null, + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "fields_and_input", + "message0": "%1 hi %2 %3 %4", + "args0": [ + { + "type": "field_input", + "name": "NAME", + "text": "default" + }, + { + "type": "input_dummy" + }, + { + "type": "field_input", + "name": "NAME", + "text": "default" + }, + { + "type": "input_value", + "name": "NAME" + } + ], + "previousStatement": null, + "nextStatement": null, + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "two_fields", + "message0": "%1 hi", + "args0": [ + { + "type": "field_input", + "name": "NAME", + "text": "default" + } + ], + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "fields_and_input2", + "message0": "%1 %2 %3 hi %4 bye", + "args0": [ + { + "type": "input_value", + "name": "NAME" + }, + { + "type": "field_input", + "name": "NAME", + "text": "default" + }, + { + "type": "input_value", + "name": "NAME" + }, + { + "type": "input_statement", + "name": "NAME" + } + ], + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "dummy_input", + "message0": "Hello", + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "dummy_inputValue", + "message0": "Hello %1 %2", + "args0": [ + { + "type": "input_dummy" + }, + { + "type": "input_value", + "name": "NAME" + } + ], + "colour": 230, + "tooltip": "", + "helpUrl": "" + }, + { + "type": "output_next", + "message0": "", + "output": null, + "colour": 230, + "tooltip": "", + "helpUrl": "", + "nextStatement": null + }]); + + var noNextConnection = this.workspace.newBlock('top_connection'); + var fieldAndInputs = this.workspace.newBlock('fields_and_input'); + var twoFields = this.workspace.newBlock('two_fields'); + var fieldAndInputs2 = this.workspace.newBlock('fields_and_input2'); + var noPrevConnection = this.workspace.newBlock('start_block'); + this.blocks.noNextConnection = noNextConnection; + this.blocks.fieldAndInputs = fieldAndInputs; + this.blocks.twoFields = twoFields; + this.blocks.fieldAndInputs2 = fieldAndInputs2; + this.blocks.noPrevConnection = noPrevConnection; + + var dummyInput = this.workspace.newBlock('dummy_input'); + var dummyInputValue = this.workspace.newBlock('dummy_inputValue'); + var fieldWithOutput2 = this.workspace.newBlock('field_input'); + this.blocks.dummyInput = dummyInput; + this.blocks.dummyInputValue = dummyInputValue; + this.blocks.fieldWithOutput2 = fieldWithOutput2; + + var secondBlock = this.workspace.newBlock('input_statement'); + var outputNextBlock = this.workspace.newBlock('output_next'); + this.blocks.secondBlock = secondBlock; + this.blocks.outputNextBlock = outputNextBlock; + + + }); + teardown(function() { + delete this.blocks.noNextConnection; + delete this.blocks.fieldAndInputs; + delete this.blocks.twoFields; + delete this.blocks.fieldAndInputs2; + delete this.blocks.noPrevConnection; + delete this.blocks.dummyInput; + delete this.blocks.dummyInputValue; + delete this.blocks.fieldWithOutput2; + + + delete Blockly.Blocks['fields_and_input2']; + delete Blockly.Blocks['two_fields']; + delete Blockly.Blocks['fields_and_input']; + delete Blockly.Blocks['top_connection']; + delete Blockly.Blocks['start_block']; + delete Blockly.Blocks['dummy_input']; + delete Blockly.Blocks['dummy_inputValue']; + }); suite('Next', function() { setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "top_connection", - "message0": "", - "previousStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input", - "message0": "%1 hi %2 %3 %4", - "args0": [ - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_dummy" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - } - ], - "previousStatement": null, - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "two_fields", - "message0": "%1 hi", - "args0": [ - { - "type": "field_input", - "name": "NAME", - "text": "default" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input2", - "message0": "%1 %2 %3 hi %4 bye", - "args0": [ - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "input_statement", - "name": "NAME" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }]); - this.singleBlockWorkspace = new Blockly.Workspace(); - - var noNextConnection = this.workspace.newBlock('top_connection'); - var fieldAndInputs = this.workspace.newBlock('fields_and_input'); - var twoFields = this.workspace.newBlock('two_fields'); - var fieldAndInputs2 = this.workspace.newBlock('fields_and_input2'); var singleBlock = this.singleBlockWorkspace.newBlock('two_fields'); - - this.blocks.noNextConnection = noNextConnection; - this.blocks.fieldAndInputs = fieldAndInputs; - this.blocks.twoFields = twoFields; - this.blocks.fieldAndInputs2 = fieldAndInputs2; this.blocks.singleBlock = singleBlock; - - }); teardown(function() { - delete this.blocks.noNextConnection; - delete this.blocks.fieldAndInputs; - delete this.blocks.twoFields; - delete this.blocks.fieldAndInputs2; delete this.blocks.singleBlock; - - delete Blockly.Blocks['fields_and_input2']; - delete Blockly.Blocks['two_fields']; - delete Blockly.Blocks['fields_and_input']; - delete Blockly.Blocks['top_connection']; }); test('fromPreviousToBlock', function() { @@ -374,88 +438,6 @@ suite('ASTNode', function() { }); suite('Previous', function() { - setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "start_block", - "message0": "", - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input", - "message0": "%1 hi %2 %3 %4", - "args0": [ - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_dummy" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - } - ], - "previousStatement": null, - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "fields_and_input2", - "message0": "%1 %2 %3 hi %4 bye", - "args0": [ - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "field_input", - "name": "NAME", - "text": "default" - }, - { - "type": "input_value", - "name": "NAME" - }, - { - "type": "input_statement", - "name": "NAME" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }]); - - var noPrevConnection = this.workspace.newBlock('start_block'); - var fieldsAndInputs = this.workspace.newBlock('fields_and_input'); - var fieldsAndInputs2 = this.workspace.newBlock('fields_and_input2'); - - this.blocks.noPrevConnection = noPrevConnection; - this.blocks.fieldsAndInputs = fieldsAndInputs; - this.blocks.fieldsAndInputs2 = fieldsAndInputs2; - }); - teardown(function() { - delete this.blocks.noPrevConnection; - delete this.blocks.fieldAndInputs; - delete this.blocks.fieldsAndInputs2; - - delete Blockly.Blocks['fields_and_input2']; - delete Blockly.Blocks['start_block']; - delete Blockly.Blocks['fields_and_input']; - }); - test('fromPreviousToNull', function() { var prevConnection = this.blocks.statementInput1.previousConnection; var node = Blockly.ASTNode.createConnectionNode(prevConnection); @@ -505,14 +487,14 @@ suite('ASTNode', function() { assertEquals(prevNode.getLocation(), input.fieldRow[1]); }); test('fromInputToNull', function() { - var input = this.blocks.fieldsAndInputs2.inputList[0]; + var input = this.blocks.fieldAndInputs2.inputList[0]; var node = Blockly.ASTNode.createInputNode(input); var prevNode = node.prev(); assertEquals(prevNode, null); }); test('fromInputToInput', function() { - var input = this.blocks.fieldsAndInputs2.inputList[2]; - var inputConnection = this.blocks.fieldsAndInputs2.inputList[1].connection; + var input = this.blocks.fieldAndInputs2.inputList[2]; + var inputConnection = this.blocks.fieldAndInputs2.inputList[1].connection; var node = Blockly.ASTNode.createInputNode(input); var prevNode = node.prev(); assertEquals(prevNode.getLocation(), inputConnection); @@ -530,15 +512,15 @@ suite('ASTNode', function() { assertEquals(prevNode, null); }); test('fromFieldToInput', function() { - var field = this.blocks.fieldsAndInputs2.inputList[1].fieldRow[0]; - var inputConnection = this.blocks.fieldsAndInputs2.inputList[0].connection; + var field = this.blocks.fieldAndInputs2.inputList[1].fieldRow[0]; + var inputConnection = this.blocks.fieldAndInputs2.inputList[0].connection; var node = Blockly.ASTNode.createFieldNode(field); var prevNode = node.prev(); assertEquals(prevNode.getLocation(), inputConnection); }); test('fromFieldToField', function() { - var field = this.blocks.fieldsAndInputs.inputList[1].fieldRow[0]; - var field2 = this.blocks.fieldsAndInputs.inputList[0].fieldRow[0]; + var field = this.blocks.fieldAndInputs.inputList[1].fieldRow[0]; + var field2 = this.blocks.fieldAndInputs.inputList[0].fieldRow[0]; var node = Blockly.ASTNode.createFieldNode(field); var prevNode = node.prev(); assertEquals(prevNode.getLocation(), field2); @@ -553,46 +535,10 @@ suite('ASTNode', function() { suite('In', function() { setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "dummy_input", - "message0": "Hello", - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "dummy_inputValue", - "message0": "Hello %1 %2", - "args0": [ - { - "type": "input_dummy" - }, - { - "type": "input_value", - "name": "NAME" - } - ], - "colour": 230, - "tooltip": "", - "helpUrl": "" - }]); - var dummyInput = this.workspace.newBlock('dummy_input'); - var dummyInputValue = this.workspace.newBlock('dummy_inputValue'); - var fieldWithOutput2 = this.workspace.newBlock('field_input'); - - this.blocks.dummyInput = dummyInput; - this.blocks.dummyInputValue = dummyInputValue; - this.blocks.fieldWithOutput2 = fieldWithOutput2; this.emptyWorkspace = new Blockly.Workspace(); }); teardown(function() { - delete this.blocks.dummyInput; - delete this.blocks.dummyInputValue; - delete this.blocks.fieldWithOutput2; delete this.emptyWorkspace; - - delete Blockly.Blocks['dummy_input']; - delete Blockly.Blocks['dummy_inputValue']; }); test('fromInputToOutput', function() { @@ -695,44 +641,11 @@ suite('ASTNode', function() { suite('Out', function() { setup(function() { - Blockly.defineBlocksWithJsonArray([{ - "type": "start_block", - "message0": "", - "nextStatement": null, - "colour": 230, - "tooltip": "", - "helpUrl": "" - }, - { - "type": "output_next", - "message0": "", - "output": null, - "colour": 230, - "tooltip": "", - "helpUrl": "", - "nextStatement": null - }]); - var noPrevConnection = this.workspace.newBlock('start_block'); - var secondBlock = this.workspace.newBlock('input_statement'); - var outputNextBlock = this.workspace.newBlock('output_next'); - var fieldWithOutput2 = this.workspace.newBlock('field_input'); - - noPrevConnection.nextConnection.connect(secondBlock.previousConnection); + var secondBlock = this.blocks.secondBlock; + var outputNextBlock = this.blocks.outputNextBlock; + this.blocks.noPrevConnection.nextConnection.connect(secondBlock.previousConnection); secondBlock.inputList[0].connection .connect(outputNextBlock.outputConnection); - this.blocks.noPrevConnection = noPrevConnection; - this.blocks.secondBlock = secondBlock; - this.blocks.outputNextBlock = outputNextBlock; - this.blocks.fieldWithOutput2 = fieldWithOutput2; - }); - teardown(function() { - delete this.blocks.noPrevConnection; - delete this.blocks.secondBlock; - delete this.blocks.outputNextBlock; - delete this.blocks.fieldWithOutput2; - - delete Blockly.Blocks['start_block']; - delete Blockly.Blocks['output_next']; }); test('fromInputToBlock', function() { @@ -896,6 +809,21 @@ suite('ASTNode', function() { assertEquals(node.getType(), Blockly.ASTNode.types.INPUT); assertTrue(node.isConnection()); }); + test('createTopNode-previous', function() { + var block = this.blocks.statementInput1; + var topNode = Blockly.ASTNode.createTopNode(block); + assertEquals(topNode.getLocation(), block.previousConnection); + }); + test('createTopNode-block', function() { + var block = this.blocks.noPrevConnection; + var topNode = Blockly.ASTNode.createTopNode(block); + assertEquals(topNode.getLocation(), block); + }); + test('createTopNode-output', function() { + var block = this.blocks.outputNextBlock; + var topNode = Blockly.ASTNode.createTopNode(block); + assertEquals(topNode.getLocation(), block.outputConnection); + }); }); }); });