diff --git a/core/block.js b/core/block.js index 8b0ed2b1f9..2286e78cad 100644 --- a/core/block.js +++ b/core/block.js @@ -66,8 +66,6 @@ Blockly.Block = function(workspace, prototypeName, opt_id) { /** @type {boolean|undefined} */ this.inputsInline = undefined; /** @type {boolean} */ - this.rendered = false; - /** @type {boolean} */ this.disabled = false; /** @type {string|!Function} */ this.tooltip = ''; @@ -246,29 +244,23 @@ Blockly.Block.prototype.unplug = function(opt_healStack) { /** * Returns all connections originating from this block. - * @param {boolean} all If true, return all connections even hidden ones. - * Otherwise return those that are visible. * @return {!Array.} Array of connections. * @private */ -Blockly.Block.prototype.getConnections_ = function(all) { +Blockly.Block.prototype.getConnections_ = function() { var myConnections = []; - if (all || this.rendered) { - if (this.outputConnection) { - myConnections.push(this.outputConnection); - } - if (this.previousConnection) { - myConnections.push(this.previousConnection); - } - if (this.nextConnection) { - myConnections.push(this.nextConnection); - } - if (all || !this.collapsed_) { - for (var i = 0, input; input = this.inputList[i]; i++) { - if (input.connection) { - myConnections.push(input.connection); - } - } + if (this.outputConnection) { + myConnections.push(this.outputConnection); + } + if (this.previousConnection) { + myConnections.push(this.previousConnection); + } + if (this.nextConnection) { + myConnections.push(this.nextConnection); + } + for (var i = 0, input; input = this.inputList[i]; i++) { + if (input.connection) { + myConnections.push(input.connection); } } return myConnections; @@ -613,9 +605,6 @@ Blockly.Block.prototype.setColour = function(colour) { } else { throw 'Invalid colour: ' + colour; } - if (this.rendered) { - this.updateColour(); - } }; /** @@ -736,10 +725,6 @@ Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) { new Blockly.Connection(this, Blockly.PREVIOUS_STATEMENT); this.previousConnection.setCheck(opt_check); } - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } }; /** @@ -763,10 +748,6 @@ Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) { new Blockly.Connection(this, Blockly.NEXT_STATEMENT); this.nextConnection.setCheck(opt_check); } - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } }; /** @@ -793,10 +774,6 @@ Blockly.Block.prototype.setOutput = function(newBoolean, opt_check) { new Blockly.Connection(this, Blockly.OUTPUT_VALUE); this.outputConnection.setCheck(opt_check); } - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } }; /** @@ -808,10 +785,6 @@ Blockly.Block.prototype.setInputsInline = function(newBoolean) { Blockly.Events.fire(new Blockly.Events.Change( this, 'inline', null, this.inputsInline, newBoolean)); this.inputsInline = newBoolean; - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } } }; @@ -1149,11 +1122,6 @@ Blockly.Block.prototype.appendInput_ = function(type, name) { var input = new Blockly.Input(type, name, this, connection); // Append input to list. this.inputList.push(input); - if (this.rendered) { - this.render(); - // Adding an input will cause the block to change shape. - this.bumpNeighbours_(); - } return input; }; @@ -1210,11 +1178,6 @@ Blockly.Block.prototype.moveNumberedInputBefore = function( } // Reinsert input. this.inputList.splice(refIndex, 0, input); - if (this.rendered) { - this.render(); - // Moving an input will cause the block to change shape. - this.bumpNeighbours_(); - } }; /** @@ -1240,11 +1203,6 @@ Blockly.Block.prototype.removeInput = function(name, opt_quiet) { } input.dispose(); this.inputList.splice(i, 1); - if (this.rendered) { - this.render(); - // Removing an input will cause the block to change shape. - this.bumpNeighbours_(); - } return; } } diff --git a/core/block_svg.js b/core/block_svg.js index f31bbf035f..9069ba2adf 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -61,6 +61,10 @@ Blockly.BlockSvg = function(workspace, prototypeName, opt_id) { this.svgPathLight_ = Blockly.createSvgElement('path', {'class': 'blocklyPathLight'}, this.svgGroup_); this.svgPath_.tooltip = this; + + /** @type {boolean} */ + this.rendered = false; + Blockly.Tooltip.bindMouseEvents(this.svgPath_); Blockly.BlockSvg.superClass_.constructor.call(this, workspace, prototypeName, opt_id); @@ -1402,3 +1406,165 @@ Blockly.BlockSvg.prototype.removeDragging = function() { Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), 'blocklyDragging'); }; + +// Overrides of functions on Blockly.Block that take into account whether the +// block has been rendered. + +/** + * Change the colour of a block. + * @param {number|string} colour HSV hue value, or #RRGGBB string. + */ +Blockly.BlockSvg.prototype.setColour = function(colour) { + Blockly.BlockSvg.superClass_.setColour.call(this, colour); + + if (this.rendered) { + this.updateColour(); + } +}; + +/** + * Set whether this block can chain onto the bottom of another block. + * @param {boolean} newBoolean True if there can be a previous statement. + * @param {string|Array.|null|undefined} opt_check Statement type or + * list of statement types. Null/undefined if any type could be connected. + */ +Blockly.BlockSvg.prototype.setPreviousStatement = + function(newBoolean, opt_check) { + Blockly.BlockSvg.superClass_.setPreviousStatement.call(this, newBoolean, + opt_check); + + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + } +}; + +/** + * Set whether another block can chain onto the bottom of this block. + * @param {boolean} newBoolean True if there can be a next statement. + * @param {string|Array.|null|undefined} opt_check Statement type or + * list of statement types. Null/undefined if any type could be connected. + */ +Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) { + Blockly.BlockSvg.superClass_.setNextStatement.call(this, newBoolean, + opt_check); + + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + } +}; + +/** + * Set whether this block returns a value. + * @param {boolean} newBoolean True if there is an output. + * @param {string|Array.|null|undefined} opt_check Returned type or list + * of returned types. Null or undefined if any type could be returned + * (e.g. variable get). + */ +Blockly.BlockSvg.prototype.setOutput = function(newBoolean, opt_check) { + Blockly.BlockSvg.superClass_.setOutput.call(this, newBoolean, opt_check); + + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + } +}; + +/** + * Set whether value inputs are arranged horizontally or vertically. + * @param {boolean} newBoolean True if inputs are horizontal. + */ +Blockly.BlockSvg.prototype.setInputsInline = function(newBoolean) { + Blockly.BlockSvg.superClass_.setInputsInline.call(this, newBoolean); + + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + } +}; + +/** + * Remove an input from this block. + * @param {string} name The name of the input. + * @param {boolean=} opt_quiet True to prevent error if input is not present. + * @throws {goog.asserts.AssertionError} if the input is not present and + * opt_quiet is not true. + */ +Blockly.BlockSvg.prototype.removeInput = function(name, opt_quiet) { + Blockly.BlockSvg.superClass_.removeInput.call(this, name, opt_quiet); + + if (this.rendered) { + this.render(); + // Removing an input will cause the block to change shape. + this.bumpNeighbours_(); + } +}; + +/** + * Move a numbered input to a different location on this block. + * @param {number} inputIndex Index of the input to move. + * @param {number} refIndex Index of input that should be after the moved input. + */ +Blockly.BlockSvg.prototype.moveNumberedInputBefore = function( + inputIndex, refIndex) { + Blockly.BlockSvg.superClass_.moveNumberedInputBefore.call(this, inputIndex, + refIndex); + + if (this.rendered) { + this.render(); + // Moving an input will cause the block to change shape. + this.bumpNeighbours_(); + } +}; + +/** + * Add a value input, statement input or local variable to this block. + * @param {number} type Either Blockly.INPUT_VALUE or Blockly.NEXT_STATEMENT or + * Blockly.DUMMY_INPUT. + * @param {string} name Language-neutral identifier which may used to find this + * input again. Should be unique to this block. + * @return {!Blockly.Input} The input object created. + * @private + */ +Blockly.BlockSvg.prototype.appendInput_ = function(type, name) { + var input = Blockly.BlockSvg.superClass_.appendInput_.call(this, type, name); + + if (this.rendered) { + this.render(); + // Adding an input will cause the block to change shape. + this.bumpNeighbours_(); + } + return input; +}; + +/** + * Returns connections originating from this block. + * @param {boolean} all If true, return all connections even hidden ones. + * Otherwise, for a non-rendered block return an empty list, and for a + * collapsed block don't return inputs connections. + * @return {!Array.} Array of connections. + * @private + */ +Blockly.BlockSvg.prototype.getConnections_ = function(all) { + var myConnections = []; + if (all || this.rendered) { + if (this.outputConnection) { + myConnections.push(this.outputConnection); + } + if (this.previousConnection) { + myConnections.push(this.previousConnection); + } + if (this.nextConnection) { + myConnections.push(this.nextConnection); + } + if (all || !this.collapsed_) { + for (var i = 0, input; input = this.inputList[i]; i++) { + if (input.connection) { + myConnections.push(input.connection); + } + } + } + } + return myConnections; +};