mirror of
https://github.com/google/blockly.git
synced 2026-01-09 01:50:11 +01:00
Merge pull request #2767 from moniika/moniika-render-collapsed
Updating logic to handle rendering collapsed blocks.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 = '';
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) +
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user