diff --git a/core/renderers/common/constants.js b/core/renderers/common/constants.js index 1ec8c8fdc..bfc753f09 100644 --- a/core/renderers/common/constants.js +++ b/core/renderers/common/constants.js @@ -60,6 +60,12 @@ Blockly.blockRendering.ConstantProvider = function() { this.EMPTY_BLOCK_SPACER_HEIGHT = 16; + /** + * The minimum height of a dummy input row. + * @type {number} + */ + this.DUMMY_INPUT_MIN_HEIGHT = this.TAB_HEIGHT; + /** * Rounded corner radius. * @type {number} diff --git a/core/renderers/common/info.js b/core/renderers/common/info.js index f47b8c136..eed3591f1 100644 --- a/core/renderers/common/info.js +++ b/core/renderers/common/info.js @@ -376,8 +376,11 @@ Blockly.blockRendering.RenderInfo.prototype.addInput_ = function(input, activeRo } else if (input.type == Blockly.DUMMY_INPUT) { // Dummy inputs have no visual representation, but the information is still // important. + activeRow.minHeight = Math.max(activeRow.minHeight, + this.constants_.DUMMY_INPUT_MIN_HEIGHT); activeRow.hasDummyInput = true; } + activeRow.align = input.align; }; /** diff --git a/core/renderers/geras/info.js b/core/renderers/geras/info.js index 31b99e6b7..3df571bf2 100644 --- a/core/renderers/geras/info.js +++ b/core/renderers/geras/info.js @@ -115,8 +115,49 @@ Blockly.geras.RenderInfo.prototype.addInput_ = function(input, activeRow) { } else if (input.type == Blockly.DUMMY_INPUT) { // Dummy inputs have no visual representation, but the information is still // important. + activeRow.minHeight = Math.max(activeRow.minHeight, + this.constants_.DUMMY_INPUT_MIN_HEIGHT); activeRow.hasDummyInput = true; } + activeRow.align = input.align; +}; + +/** + * @override + */ +Blockly.geras.RenderInfo.prototype.addElemSpacing_ = function() { + var hasExternalInputs = false; + for (var i = 0, row; (row = this.rows[i]); i++) { + if (row.hasExternalInput) { + hasExternalInputs = true; + } + } + for (var i = 0, row; (row = this.rows[i]); i++) { + var oldElems = row.elements; + row.elements = []; + // No spacing needed before the corner on the top row or the bottom row. + if (row.startsWithElemSpacer()) { + // There's a spacer before the first element in the row. + row.elements.push(new Blockly.blockRendering.InRowSpacer( + this.constants_, this.getInRowSpacing_(null, oldElems[0]))); + } + for (var e = 0; e < oldElems.length - 1; e++) { + row.elements.push(oldElems[e]); + var spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]); + row.elements.push( + new Blockly.blockRendering.InRowSpacer(this.constants_, spacing)); + } + row.elements.push(oldElems[oldElems.length - 1]); + if (row.endsWithElemSpacer()) { + var spacing = this.getInRowSpacing_(oldElems[oldElems.length - 1], null); + if (hasExternalInputs && row.hasDummyInput) { + spacing += this.constants_.TAB_WIDTH; + } + // There's a spacer after the last element in the row. + row.elements.push(new Blockly.blockRendering.InRowSpacer( + this.constants_, spacing)); + } + } }; /** @@ -274,22 +315,19 @@ Blockly.geras.RenderInfo.prototype.addAlignmentPadding_ = function(row, missingS row.widthWithConnectedBlocks += missingSpace; } - var input = row.getLastInput(); - if (input) { - // Decide where the extra padding goes. - if (input.align == Blockly.ALIGN_LEFT) { - // Add padding to the end of the row. - lastSpacer.width += missingSpace; - } else if (input.align == Blockly.ALIGN_CENTRE) { - // Split the padding between the beginning and end of the row. - firstSpacer.width += missingSpace / 2; - lastSpacer.width += missingSpace / 2; - } else if (input.align == Blockly.ALIGN_RIGHT) { - // Add padding at the beginning of the row. - firstSpacer.width += missingSpace; - } + // Decide where the extra padding goes. + if (row.align == Blockly.ALIGN_LEFT) { + // Add padding to the end of the row. + lastSpacer.width += missingSpace; + } else if (row.align == Blockly.ALIGN_CENTRE) { + // Split the padding between the beginning and end of the row. + firstSpacer.width += missingSpace / 2; + lastSpacer.width += missingSpace / 2; + } else if (row.align == Blockly.ALIGN_RIGHT) { + // Add padding at the beginning of the row. + firstSpacer.width += missingSpace; } else { - // Default to left-aligning if there's no input to say where to align. + // Default to left-aligning. lastSpacer.width += missingSpace; } row.width += missingSpace; @@ -321,6 +359,9 @@ Blockly.geras.RenderInfo.prototype.getSpacerRowHeight_ = function(prev, next) { if (!prev.hasStatement && next.hasDummyInput) { return this.constants_.LARGE_PADDING; } + if (prev.hasDummyInput) { + return this.constants_.LARGE_PADDING; + } return this.constants_.MEDIUM_PADDING; }; diff --git a/core/renderers/thrasos/info.js b/core/renderers/thrasos/info.js index 48ed1f9ed..b8772cbb9 100644 --- a/core/renderers/thrasos/info.js +++ b/core/renderers/thrasos/info.js @@ -70,6 +70,44 @@ Blockly.thrasos.RenderInfo.prototype.getRenderer = function() { return /** @type {!Blockly.thrasos.Renderer} */ (this.renderer_); }; +/** + * @override + */ +Blockly.thrasos.RenderInfo.prototype.addElemSpacing_ = function() { + var hasExternalInputs = false; + for (var i = 0, row; (row = this.rows[i]); i++) { + if (row.hasExternalInput) { + hasExternalInputs = true; + } + } + for (var i = 0, row; (row = this.rows[i]); i++) { + var oldElems = row.elements; + row.elements = []; + // No spacing needed before the corner on the top row or the bottom row. + if (row.startsWithElemSpacer()) { + // There's a spacer before the first element in the row. + row.elements.push(new Blockly.blockRendering.InRowSpacer( + this.constants_, this.getInRowSpacing_(null, oldElems[0]))); + } + for (var e = 0; e < oldElems.length - 1; e++) { + row.elements.push(oldElems[e]); + var spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]); + row.elements.push( + new Blockly.blockRendering.InRowSpacer(this.constants_, spacing)); + } + row.elements.push(oldElems[oldElems.length - 1]); + if (row.endsWithElemSpacer()) { + var spacing = this.getInRowSpacing_(oldElems[oldElems.length - 1], null); + if (hasExternalInputs && row.hasDummyInput) { + spacing += this.constants_.TAB_WIDTH; + } + // There's a spacer after the last element in the row. + row.elements.push(new Blockly.blockRendering.InRowSpacer( + this.constants_, spacing)); + } + } +}; + /** * @override */ @@ -211,23 +249,20 @@ Blockly.thrasos.RenderInfo.prototype.addAlignmentPadding_ = function(row, missin if (row.hasExternalInput || row.hasStatement) { row.widthWithConnectedBlocks += missingSpace; } - - var input = row.getLastInput(); - if (input) { - // Decide where the extra padding goes. - if (input.align == Blockly.ALIGN_LEFT) { - // Add padding to the end of the row. - lastSpacer.width += missingSpace; - } else if (input.align == Blockly.ALIGN_CENTRE) { - // Split the padding between the beginning and end of the row. - firstSpacer.width += missingSpace / 2; - lastSpacer.width += missingSpace / 2; - } else if (input.align == Blockly.ALIGN_RIGHT) { - // Add padding at the beginning of the row. - firstSpacer.width += missingSpace; - } + + // Decide where the extra padding goes. + if (row.align == Blockly.ALIGN_LEFT) { + // Add padding to the end of the row. + lastSpacer.width += missingSpace; + } else if (row.align == Blockly.ALIGN_CENTRE) { + // Split the padding between the beginning and end of the row. + firstSpacer.width += missingSpace / 2; + lastSpacer.width += missingSpace / 2; + } else if (row.align == Blockly.ALIGN_RIGHT) { + // Add padding at the beginning of the row. + firstSpacer.width += missingSpace; } else { - // Default to left-aligning if there's no input to say where to align. + // Default to left-aligning. lastSpacer.width += missingSpace; } row.width += missingSpace; @@ -257,7 +292,7 @@ Blockly.thrasos.RenderInfo.prototype.getSpacerRowHeight_ = function( if (prev.hasStatement && next.hasStatement) { return this.constants_.LARGE_PADDING; } - if (next.hasDummyInput) { + if (prev.hasDummyInput || next.hasDummyInput) { return this.constants_.LARGE_PADDING; } return this.constants_.MEDIUM_PADDING; diff --git a/tests/blocks/test_blocks.js b/tests/blocks/test_blocks.js index 537adb0f5..6f9e0af33 100644 --- a/tests/blocks/test_blocks.js +++ b/tests/blocks/test_blocks.js @@ -31,6 +31,29 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT "nextStatement": null, "style": "math_blocks" }, + { + "type": "test_basic_dummy", + "message0": "dummy input %1", + "args0": [ + { + "type": "input_dummy" + } + ], + "style": "math_blocks" + }, + { + "type": "test_basic_multiple_dummy", + "message0": "first dummy %1 second dummy %2", + "args0": [ + { + "type": "input_dummy" + }, + { + "type": "input_dummy" + } + ], + "style": "math_blocks" + }, { "type": "test_basic_row", "message0": "row block %1", @@ -124,6 +147,64 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT "colour": 200, "tooltip": "Hello world." }, + { + "type": "test_align_dummy_right", + "message0": "text %1 long text %2", + "args0": [ + { + "type": "input_dummy", + "align": "RIGHT", + }, + { + "type": "input_dummy", + "align": "RIGHT", + }, + ], + "style": "math_blocks" + }, + { + "type": "test_align_all", + "message0": "text %1 long text %2 text %3 much longer text", + "args0": [ + { + "type": "input_dummy", + "align": "LEFT", + }, + { + "type": "input_dummy", + "align": "CENTRE", + }, + { + "type": "input_dummy", + "align": "RIGHT", + }, + ], + "style": "math_blocks" + }, + { + "type": "test_align_with_external_input", + "message0": "text %1 long text %2 text %3 much longer text %4", + "args0": [ + { + "type": "input_dummy", + "align": "RIGHT", + }, + { + "type": "input_dummy", + "align": "CENTRE", + }, + { + "type": "input_dummy", + "align": "LEFT", + }, + { + "type": "input_value", + "name": "VALUE" + }, + ], + "inputsInline": false, + "style": "math_blocks" + }, { "type": "test_dropdowns_long", "message0": "long: %1", diff --git a/tests/playground.html b/tests/playground.html index d9969cc1b..742b5858f 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -1359,6 +1359,8 @@ var spaghettiXml = [ + + @@ -1367,6 +1369,11 @@ var spaghettiXml = [ + + + + +