Merge pull request #2767 from moniika/moniika-render-collapsed

Updating logic to handle rendering collapsed blocks.
This commit is contained in:
Monica Kozbial
2019-08-02 17:41:38 -07:00
committed by GitHub
6 changed files with 159 additions and 13 deletions

View File

@@ -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.hasJaggedEdge) {
this.drawJaggedEdge_(row);
} else if (row.hasStatement) {
this.drawStatementInput_(row);
} else if (row.hasExternalInput) {
this.drawValueInput_(row);
@@ -136,6 +150,20 @@ 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) {
if (this.highlighter_) {
this.highlighter_.drawJaggedEdge_(row);
}
this.steps_.push(Blockly.blockRendering.constants.JAGGED_TEETH.path);
var remainder =
row.height - Blockly.blockRendering.constants.JAGGED_TEETH.height;
this.steps_.push('v', remainder);
};
/**
* Add steps for an external value input, rendered as a notch in the side

View File

@@ -67,6 +67,8 @@ Blockly.blockRendering.Highlighter = function(info, pathObject) {
this.puzzleTabPaths_ = Blockly.blockRendering.highlightConstants.PUZZLE_TAB;
this.notchPaths_ = Blockly.blockRendering.highlightConstants.NOTCH;
this.startPaths_ = Blockly.blockRendering.highlightConstants.START_HAT;
this.jaggedTeethPaths_ =
Blockly.blockRendering.highlightConstants.JAGGED_TEETH;
};
Blockly.blockRendering.Highlighter.prototype.drawTopCorner = function(row) {
@@ -91,6 +93,16 @@ 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) {
this.steps_.push('H', row.width - this.highlightOffset_);
this.steps_.push(this.jaggedTeethPaths_.pathLeft);
var remainder =
row.height - this.jaggedTeethPaths_.height - this.highlightOffset_;
this.steps_.push(Blockly.utils.svgPaths.lineOnAxis('v', remainder));
}
};
Blockly.blockRendering.Highlighter.prototype.drawValueInput = function(row) {
var input = row.getLastInput();
var steps = '';

View File

@@ -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.<!Blockly.blockRendering.Icon>}
*/
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,12 @@ 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.hasJaggedEdge = true;
activeRow.elements.push(new Blockly.blockRendering.JaggedEdge());
}
if (activeRow.elements.length) {
@@ -285,7 +312,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 +347,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 +368,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 +387,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 +441,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 +459,11 @@ Blockly.blockRendering.RenderInfo.prototype.getInRowSpacing_ = function(prev, ne
return Blockly.blockRendering.constants.LARGE_PADDING;
}
// Spacing between anything and a jagged edge.
if (next.isJaggedEdge()) {
return Blockly.blockRendering.constants.LARGE_PADDING;
}
return Blockly.blockRendering.constants.MEDIUM_PADDING;
};

View File

@@ -141,6 +141,39 @@ Blockly.blockRendering.constants.START_POINT = Blockly.utils.svgPaths.moveBy(0,
Blockly.blockRendering.constants.TOP_LEFT_CORNER_START =
'm 0,' + Blockly.blockRendering.constants.CORNER_RADIUS;
/**
* 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;
/**
* SVG path for drawing jagged teeth at the end of collapsed blocks.
* @const
*/
Blockly.blockRendering.constants.JAGGED_TEETH = (function() {
var height = Blockly.blockRendering.constants.JAGGED_TEETH_HEIGHT;
var width = Blockly.blockRendering.constants.JAGGED_TEETH_WIDTH;
var mainPath =
Blockly.utils.svgPaths.line(
[
Blockly.utils.svgPaths.point(6, 3),
Blockly.utils.svgPaths.point(-12, 6),
Blockly.utils.svgPaths.point(6, 3)
]);
return {
height: height,
width: width,
path: mainPath
};
})();
/**
* Information about the hat on a start block.
*/
@@ -180,7 +213,7 @@ Blockly.blockRendering.constants.PUZZLE_TAB = (function() {
var halfHeight = height / 2;
var control1Y = halfHeight + overlap;
var control2Y = halfHeight + 0.5;
var control3Y = overlap; //2.5
var control3Y = overlap; // 2.5
var endPoint1 = Blockly.utils.svgPaths.point(-width, forward * halfHeight);
var endPoint2 = Blockly.utils.svgPaths.point(width, forward * halfHeight);

View File

@@ -205,6 +205,16 @@ Blockly.blockRendering.highlightConstants.NOTCH = (function() {
};
})();
Blockly.blockRendering.highlightConstants.JAGGED_TEETH = (function() {
var pathLeft =
Blockly.utils.svgPaths.lineTo(5.1, 2.6) +
Blockly.utils.svgPaths.moveBy(-10.2, 6.8) +
Blockly.utils.svgPaths.lineTo(5.1, 2.6);
return {
pathLeft: pathLeft
};
})();
Blockly.blockRendering.highlightConstants.START_HAT = (function() {
var pathRtl =
Blockly.utils.svgPaths.moveBy(25, -8.7) +

View File

@@ -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
@@ -386,6 +411,7 @@ Blockly.blockRendering.Row = function() {
this.hasStatement = false;
this.hasInlineInput = false;
this.hasDummyInput = false;
this.hasJaggedEdge = false;
};
Blockly.blockRendering.Row.prototype.isSpacer = function() {
@@ -409,9 +435,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 +496,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;