From b1d86a57aa636dd000de445118d3ccb2b7863cce Mon Sep 17 00:00:00 2001 From: kozbial Date: Wed, 31 Jul 2019 13:55:19 -0700 Subject: [PATCH] Updating logic to handle rendering collapsed blocks. --- .../block_render_draw.js | 28 ++++++++++- .../block_render_draw_highlight.js | 14 ++++++ .../block_render_info.js | 47 ++++++++++++++++--- .../block_rendering_constants.js | 22 +++++++++ .../highlight_constants.js | 1 - .../block_rendering_rewrite/measurables.js | 35 ++++++++++++-- 6 files changed, 134 insertions(+), 13 deletions(-) diff --git a/core/renderers/block_rendering_rewrite/block_render_draw.js b/core/renderers/block_rendering_rewrite/block_render_draw.js index c7a423b0d..f678e496d 100644 --- a/core/renderers/block_rendering_rewrite/block_render_draw.js +++ b/core/renderers/block_rendering_rewrite/block_render_draw.js @@ -60,6 +60,7 @@ Blockly.blockRendering.Drawer = function(block, info) { * @private */ Blockly.blockRendering.Drawer.prototype.draw_ = function() { + this.hideHiddenIcons_(); this.drawOutline_(); this.drawInternals_(); this.block_.setPaths_(this.pathObject_); @@ -83,6 +84,17 @@ Blockly.blockRendering.Drawer.prototype.recordSizeOnBlock_ = function() { this.block_.startHat_ = this.info_.topRow.startHat; }; +/** + * Hide icons that were marked as hidden. + * @private + */ +Blockly.blockRendering.Drawer.prototype.hideHiddenIcons_ = function() { + for (var i = 0; i < this.info_.hiddenIcons.length; i++) { + var iconInfo = this.info_.hiddenIcons[i]; + iconInfo.icon.iconGroup_.setAttribute('display', 'none'); + } +}; + /** * Create the outline of the block. This is a single continuous path. * @private @@ -91,7 +103,9 @@ Blockly.blockRendering.Drawer.prototype.drawOutline_ = function() { this.drawTop_(); for (var r = 1; r < this.info_.rows.length - 1; r++) { var row = this.info_.rows[r]; - if (row.hasStatement) { + if (!row.isSpacer() && this.info_.isCollapsed) { + this.drawJaggedEdge_(row) + } else if (row.hasStatement) { this.drawStatementInput_(row); } else if (row.hasExternalInput) { this.drawValueInput_(row); @@ -136,6 +150,18 @@ Blockly.blockRendering.Drawer.prototype.drawTop_ = function() { this.steps_.push('v', topRow.height); }; +/** + * Add steps for the jagged edge of a row on a collapsed block. + * @param {!Blockly.blockRendering.Row} row The row to draw the side of. + * @private + */ +Blockly.blockRendering.Drawer.prototype.drawJaggedEdge_ = function(row) { + this.highlighter_.drawJaggedEdge_(row); + this.steps_.push(Blockly.blockRendering.constants.JAGGED_TEETH); + var remainder = row.height - Blockly.blockRendering.constants.JAGGED_TEETH_HEIGHT; + this.steps_.push('v', remainder); + console.log('remainder: ' + remainder); +}; /** * Add steps for an external value input, rendered as a notch in the side diff --git a/core/renderers/block_rendering_rewrite/block_render_draw_highlight.js b/core/renderers/block_rendering_rewrite/block_render_draw_highlight.js index 323e13b83..6438058ee 100644 --- a/core/renderers/block_rendering_rewrite/block_render_draw_highlight.js +++ b/core/renderers/block_rendering_rewrite/block_render_draw_highlight.js @@ -91,6 +91,20 @@ Blockly.blockRendering.Highlighter.prototype.drawTopCorner = function(row) { this.steps_.push('H', row.width - this.highlightOffset_); }; +Blockly.blockRendering.Highlighter.prototype.drawJaggedEdge_ = function(row) { + if (this.info_.RTL) { + var remainder = + row.height - Blockly.blockRendering.constants.JAGGED_TEETH_HEIGHT - this.highlightOffset_; + this.steps_.push('H', row.width - this.highlightOffset_); + var steps = + Blockly.utils.svgPaths.lineTo(5.1, 2.6) + + Blockly.utils.svgPaths.moveBy(-10.2, 6.8) + + Blockly.utils.svgPaths.lineTo(5.1, 2.6) + + Blockly.utils.svgPaths.lineOnAxis('v', remainder); + this.steps_.push(steps); + } +}; + Blockly.blockRendering.Highlighter.prototype.drawValueInput = function(row) { var input = row.getLastInput(); var steps = ''; diff --git a/core/renderers/block_rendering_rewrite/block_render_info.js b/core/renderers/block_rendering_rewrite/block_render_info.js index b9de72069..69c70af81 100644 --- a/core/renderers/block_rendering_rewrite/block_render_info.js +++ b/core/renderers/block_rendering_rewrite/block_render_info.js @@ -59,6 +59,12 @@ Blockly.blockRendering.RenderInfo = function(block) { */ this.isInline = block.getInputsInline() && !block.isCollapsed(); + /** + * Whether the block is collapsed. + * @type {boolean} + */ + this.isCollapsed = block.isCollapsed(); + /** * Whether the block is an insertion marker. Insertion markers are the same * shape as normal blocks, but don't show fields. @@ -103,6 +109,12 @@ Blockly.blockRendering.RenderInfo = function(block) { */ this.rows = []; + /** + * An array of measureable objects containing hidden icons. + * @type {Array} + */ + this.hiddenIcons = []; + this.topRow = null; this.bottomRow = null; @@ -145,16 +157,25 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { var icons = this.block_.getIcons(); if (icons.length) { for (var i = 0; i < icons.length; i++) { - activeRow.elements.push( - new Blockly.blockRendering.Icon(icons[i])); + var icon = icons[i]; + var iconInfo = new Blockly.blockRendering.Icon(icon); + if (this.isCollapsed && icon.collapseHidden) { + this.hiddenIcons.push(iconInfo); + } else { + activeRow.elements.push(iconInfo); + } } } + var lastInput = undefined; // Loop across all of the inputs on the block, creating objects for anything // that needs to be rendered and breaking the block up into visual rows. for (var i = 0; i < this.block_.inputList.length; i++) { var input = this.block_.inputList[i]; - if (this.shouldStartNewRow_(input, this.block_.inputList[i - 1])) { + if (!input.isVisible()) { + continue; + } + if (this.shouldStartNewRow_(input, lastInput)) { // Finish this row and create a new one. this.rows.push(activeRow); activeRow = new Blockly.blockRendering.Row(); @@ -166,6 +187,11 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() { activeRow.elements.push(new Blockly.blockRendering.Field(field, input)); } this.addInput_(input, activeRow); + lastInput = input; + } + + if (this.isCollapsed) { + activeRow.elements.push(new Blockly.blockRendering.JaggedEdge()); } if (activeRow.elements.length) { @@ -285,7 +311,6 @@ Blockly.blockRendering.RenderInfo.prototype.addElemSpacing_ = function() { row.elements.push(new Blockly.blockRendering.InRowSpacer( this.getInRowSpacing_(null, oldElems[0]))); } - for (var e = 0; e < oldElems.length; e++) { row.elements.push(oldElems[e]); var spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]); @@ -321,7 +346,7 @@ Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, ne return Blockly.blockRendering.constants.LARGE_PADDING; } - // Spacing between a field or icon and the end of the row. + // Spacing between a non-input and the end of the row. if (!prev.isInput && !next) { // Between an editable field and the end of the row. if (prev.isField() && prev.isEditable) { @@ -342,6 +367,10 @@ Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, ne if (prev.isRoundedCorner()) { return Blockly.blockRendering.constants.MIN_BLOCK_WIDTH; } + // Between a jagged edge and the end of the row. + if (prev.isJaggedEdge()) { + return Blockly.blockRendering.constants.NO_PADDING; + } // Between noneditable fields and icons and the end of the row. return Blockly.blockRendering.constants.LARGE_PADDING; } @@ -357,7 +386,7 @@ Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, ne } } - // Spacing between a field or icon and an input. + // Spacing between a non-input and an input. if (!prev.isInput && next.isInput) { // Between an editable field and an input. if (prev.isEditable) { @@ -411,7 +440,7 @@ Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, ne } } - // Spacing between a rounded corner and a previous or next connection + // Spacing between a rounded corner and a previous or next connection. if (prev.isRoundedCorner()){ if (next.isPreviousConnection()) { return Blockly.blockRendering.constants.NOTCH_OFFSET_ROUNDED_CORNER_PREV; @@ -429,6 +458,10 @@ Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, ne return Blockly.blockRendering.constants.LARGE_PADDING; } + if (next.isJaggedEdge()) { + return Blockly.blockRendering.constants.LARGE_PADDING; + } + return Blockly.blockRendering.constants.MEDIUM_PADDING; }; diff --git a/core/renderers/block_rendering_rewrite/block_rendering_constants.js b/core/renderers/block_rendering_rewrite/block_rendering_constants.js index 1439d3fbf..9809c49e8 100644 --- a/core/renderers/block_rendering_rewrite/block_rendering_constants.js +++ b/core/renderers/block_rendering_rewrite/block_rendering_constants.js @@ -141,6 +141,28 @@ Blockly.blockRendering.constants.START_POINT = Blockly.utils.svgPaths.moveBy(0, Blockly.blockRendering.constants.TOP_LEFT_CORNER_START = 'm 0,' + Blockly.blockRendering.constants.CORNER_RADIUS; +/** + * SVG path for drawing jagged teeth at the end of collapsed blocks. + * @const + */ +Blockly.blockRendering.constants.JAGGED_TEETH = Blockly.utils.svgPaths.line( + [ + Blockly.utils.svgPaths.point(6, 3), + Blockly.utils.svgPaths.point(-12, 6), + Blockly.utils.svgPaths.point(6, 3) + ]); + +/** + * Height of SVG path for jagged teeth at the end of collapsed blocks. + * @const + */ +Blockly.blockRendering.constants.JAGGED_TEETH_HEIGHT = 12; +/** + * Width of SVG path for jagged teeth at the end of collapsed blocks. + * @const + */ +Blockly.blockRendering.constants.JAGGED_TEETH_WIDTH = 6; + /** * Information about the hat on a start block. */ diff --git a/core/renderers/block_rendering_rewrite/highlight_constants.js b/core/renderers/block_rendering_rewrite/highlight_constants.js index 340aadc2d..77692a93c 100644 --- a/core/renderers/block_rendering_rewrite/highlight_constants.js +++ b/core/renderers/block_rendering_rewrite/highlight_constants.js @@ -140,7 +140,6 @@ Blockly.blockRendering.highlightConstants.OUTSIDE_CORNER = (function() { }; })(); - Blockly.blockRendering.highlightConstants.PUZZLE_TAB = (function() { var width = Blockly.blockRendering.constants.TAB_WIDTH; var height = Blockly.blockRendering.constants.TAB_HEIGHT; diff --git a/core/renderers/block_rendering_rewrite/measurables.js b/core/renderers/block_rendering_rewrite/measurables.js index be247d114..0be8a3058 100644 --- a/core/renderers/block_rendering_rewrite/measurables.js +++ b/core/renderers/block_rendering_rewrite/measurables.js @@ -127,6 +127,16 @@ Blockly.blockRendering.Measurable.prototype.isRoundedCorner = function() { Blockly.blockRendering.Measurable.prototype.isSquareCorner = function() { return this.type == 'square corner'; }; + +/** + * Whether this stores information about a jagged edge. + * @return {boolean} True if this object stores information about a jagged edge. + * @package + */ +Blockly.blockRendering.Measurable.prototype.isJaggedEdge = function() { + return this.type == 'jagged edge'; +}; + /** * The base class to represent an input that takes up space on a block * during rendering @@ -178,6 +188,21 @@ Blockly.blockRendering.Icon = function(icon) { }; goog.inherits(Blockly.blockRendering.Icon, Blockly.blockRendering.Measurable); +/** + * An object containing information about the jagged edge of a collapsed block + * takes up during rendering + * @package + * @constructor + */ +Blockly.blockRendering.JaggedEdge = function() { + Blockly.blockRendering.JaggedEdge.superClass_.constructor.call(this); + this.type = 'jagged edge'; + this.height = Blockly.blockRendering.constants.JAGGED_TEETH_HEIGHT; + this.width = Blockly.blockRendering.constants.JAGGED_TEETH_WIDTH; +}; +goog.inherits(Blockly.blockRendering.JaggedEdge, Blockly.blockRendering.Measurable); + + /** * An object containing information about the space a field takes up during * rendering @@ -409,9 +434,11 @@ Blockly.blockRendering.Row.prototype.measure = function() { }; Blockly.blockRendering.Row.prototype.getLastInput = function() { - // There's always a spacer after the last input, unless there are no inputs. - if (this.elements.length > 1) { - var elem = this.elements[this.elements.length - 2]; + for (var i = this.elements.length - 1; i >= 0; i--) { + var elem = this.elements[i]; + if (elem.isSpacer()) { + continue; + } if (elem.isInput) { return elem; } else if (elem.isField()) { @@ -468,7 +495,7 @@ Blockly.blockRendering.TopRow = function(block) { // This is the minimum height for the row. If one of its elements has a greater // height it will be overwritten in the compute pass. - if (precedesStatement) { + if (precedesStatement && !block.isCollapsed()) { this.height = Blockly.blockRendering.constants.LARGE_PADDING; } else { this.height = Blockly.blockRendering.constants.MEDIUM_PADDING;