[zelos] Set a maximum width for dynamic connection shapes. (#3685)

* Set a maximum width for dynamic connection shapes.

* Only render the left side connection if a block has a statement input
This commit is contained in:
Sam El-Husseini
2020-02-07 15:13:51 -08:00
committed by GitHub
parent e1bb1d667e
commit 95aadbffb1
5 changed files with 76 additions and 29 deletions

View File

@@ -139,11 +139,10 @@ Blockly.blockRendering.RenderInfo = function(renderer, block) {
this.rows = [];
/**
* The total number of input rows added onto the block.
* @type {number}
* @protected
* An array of input rows on the block.
* @type {!Array.<!Blockly.blockRendering.InputRow>}
*/
this.inputRowNum_ = 1;
this.inputRows = [];
/**
* An array of measurable objects containing hidden icons.
@@ -206,6 +205,7 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() {
this.populateTopRow_();
this.rows.push(this.topRow);
var activeRow = new Blockly.blockRendering.InputRow(this.constants_);
this.inputRows.push(activeRow);
// Icons always go on the first row, before anything else.
var icons = this.block_.getIcons();
@@ -231,7 +231,7 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() {
// Finish this row and create a new one.
this.rows.push(activeRow);
activeRow = new Blockly.blockRendering.InputRow(this.constants_);
this.inputRowNum_ ++;
this.inputRows.push(activeRow);
}
// All of the fields in an input go on the same row.

View File

@@ -358,6 +358,13 @@ Blockly.zelos.ConstantProvider = function() {
*/
this.FIELD_CHECKBOX_DEFAULT_WIDTH = 6 * this.GRID_UNIT;
/**
* The maximum width of a dynamic connection shape.
* @type {number}
*/
this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH = 12 * this.GRID_UNIT;
/**
* The ID of the selected glow filter, or the empty string if no filter is
* set.
@@ -441,13 +448,16 @@ Blockly.zelos.ConstantProvider.prototype.makeStartHat = function() {
* @package
*/
Blockly.zelos.ConstantProvider.prototype.makeHexagonal = function() {
var maxWidth = this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;
// The main path for the hexagonal connection shape is made out of two lines.
// The lines are defined with relative positons and require the block height.
// The 'up' and 'down' versions of the paths are the same, but the Y sign
// flips. The 'left' and 'right' versions of the path are also the same, but
// the X sign flips.
function makeMainPath(height, up, right) {
var width = height / 2;
var halfHeight = height / 2;
var width = halfHeight > maxWidth ? maxWidth : halfHeight;
var forward = up ? -1 : 1;
var direction = right ? -1 : 1;
var dy = forward * height / 2;
@@ -459,7 +469,8 @@ Blockly.zelos.ConstantProvider.prototype.makeHexagonal = function() {
type: this.SHAPES.HEXAGONAL,
isDynamic: true,
width: function(height) {
return height / 2;
var halfHeight = height / 2;
return halfHeight > maxWidth ? maxWidth : halfHeight;
},
height: function(height) {
return height;
@@ -492,22 +503,34 @@ Blockly.zelos.ConstantProvider.prototype.makeHexagonal = function() {
* @package
*/
Blockly.zelos.ConstantProvider.prototype.makeRounded = function() {
// The main path for the rounded connection shape is made out of a single arc.
// The arc is defined with relative positions and requires the block height.
var maxWidth = this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;
var maxHeight = maxWidth * 2;
// The main path for the rounded connection shape is made out of two arcs and
// a line that joins them. The arcs are defined with relative positions.
// Usually, the height of the block is split between the two arcs. In the case
// where the height of the block exceeds the maximum height, a line is drawn
// in between the two arcs.
// The 'up' and 'down' versions of the paths are the same, but the Y sign
// flips. The 'up' and 'right' versions of the path flip the sweep-flag
// which moves the arc at negative angles.
function makeMainPath(height, up, right) {
var edgeWidth = height / 2;
return Blockly.utils.svgPaths.arc('a', '0 0 ' + (up || right ? 1 : 0), edgeWidth,
Blockly.utils.svgPaths.point(0, (up ? -1 : 1) * edgeWidth * 2));
function makeMainPath(blockHeight, up, right) {
var remainingHeight = blockHeight > maxHeight ? blockHeight - maxHeight : 0;
var height = blockHeight > maxHeight ? maxHeight : blockHeight;
var radius = height / 2;
return Blockly.utils.svgPaths.arc('a', '0 0,1', radius,
Blockly.utils.svgPaths.point((up ? -1 : 1) * radius, (up ? -1 : 1) * radius)) +
Blockly.utils.svgPaths.lineOnAxis('v', (right ? 1 : -1) * remainingHeight) +
Blockly.utils.svgPaths.arc('a', '0 0,1', radius,
Blockly.utils.svgPaths.point((up ? 1 : -1) * radius, (up ? -1 : 1) * radius));
}
return {
type: this.SHAPES.ROUND,
isDynamic: true,
width: function(height) {
return height / 2;
var halfHeight = height / 2;
return halfHeight > maxWidth ? maxWidth : halfHeight;
},
height: function(height) {
return height;

View File

@@ -80,7 +80,8 @@ Blockly.zelos.Drawer.prototype.draw = function() {
*/
Blockly.zelos.Drawer.prototype.drawOutline_ = function() {
if (this.info_.outputConnection &&
this.info_.outputConnection.isDynamicShape) {
this.info_.outputConnection.isDynamicShape &&
!this.info_.hasStatementInput) {
this.drawFlatTop_();
this.drawRightDynamicConnection_();
this.drawFlatBottom_();
@@ -90,6 +91,18 @@ Blockly.zelos.Drawer.prototype.drawOutline_ = function() {
}
};
/**
* @override
*/
Blockly.zelos.Drawer.prototype.drawLeft_ = function() {
if (this.info_.outputConnection &&
this.info_.outputConnection.isDynamicShape) {
this.drawLeftDynamicConnection_();
} else {
Blockly.zelos.Drawer.superClass_.drawLeft_.call(this);
}
};
/**
* Add steps for the right side of a row that does not have value or
* statement input connections.

View File

@@ -89,6 +89,12 @@ Blockly.zelos.RenderInfo = function(renderer, block) {
*/
this.isMultiRow = !block.getInputsInline() || block.isCollapsed();
/**
* Whether or not the block has a statement input in one of its rows.
* @type {boolean}
*/
this.hasStatementInput = false;
/**
* An object with rendering information about the right connection shape.
* @type {Blockly.zelos.RightConnectionShape}
@@ -164,7 +170,8 @@ Blockly.zelos.RenderInfo.prototype.getInRowSpacing_ = function(prev, next) {
if (!prev || !next) {
// No need for padding at the beginning or end of the row if the
// output shape is dynamic.
if (this.outputConnection && this.outputConnection.isDynamicShape) {
if (this.outputConnection && this.outputConnection.isDynamicShape &&
!this.hasStatementInput) {
return this.constants_.NO_PADDING;
}
}
@@ -270,6 +277,7 @@ Blockly.zelos.RenderInfo.prototype.addInput_ = function(input, activeRow) {
activeRow.elements.push(
new Blockly.zelos.StatementInput(this.constants_, input));
activeRow.hasStatement = true;
this.hasStatementInput = true;
} else if (input.type == Blockly.INPUT_VALUE) {
activeRow.elements.push(
new Blockly.blockRendering.ExternalValueInput(this.constants_, input));
@@ -397,10 +405,12 @@ Blockly.zelos.RenderInfo.prototype.finalizeOutputConnection_ = function() {
this.outputConnection.shape.connectionOffsetX(connectionWidth);
// Adjust right side measurable.
this.rightSide.height = connectionHeight;
this.rightSide.width = connectionWidth;
this.rightSide.centerline = connectionHeight / 2;
this.rightSide.xPos = this.width + connectionWidth;
if (!this.hasStatementInput) {
this.rightSide.height = connectionHeight;
this.rightSide.width = connectionWidth;
this.rightSide.centerline = connectionHeight / 2;
this.rightSide.xPos = this.width + connectionWidth;
}
this.startX = connectionWidth;
this.width += connectionWidth * 2;
@@ -415,7 +425,7 @@ Blockly.zelos.RenderInfo.prototype.finalizeOutputConnection_ = function() {
* @protected
*/
Blockly.zelos.RenderInfo.prototype.finalizeHorizontalAlignment_ = function() {
if (!this.outputConnection) {
if (!this.outputConnection || this.hasStatementInput) {
return;
}
var totalNegativeSpacing = 0;
@@ -474,14 +484,15 @@ Blockly.zelos.RenderInfo.prototype.getNegativeSpacing_ = function(elem) {
var outerShape = this.outputConnection.shape.type;
var constants =
/** @type {!Blockly.zelos.ConstantProvider} */ (this.constants_);
if (this.isMultiRow && this.inputRowNum_ > 1) {
if (this.isMultiRow && this.inputRows.length > 1) {
switch (outerShape) {
case constants.SHAPES.ROUND:
// Special case for multi-row round reporter blocks.
var radius = this.height / 2;
var maxWidth = this.constants_.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;
var width = this.height / 2 > maxWidth ? maxWidth : this.height / 2;
var topPadding = this.constants_.SMALL_PADDING;
var roundPadding = radius *
(1 - Math.sin(Math.acos((radius - topPadding) / radius)));
var roundPadding = width *
(1 - Math.sin(Math.acos((width - topPadding) / width)));
return connectionWidth - roundPadding;
default:
return 0;

View File

@@ -72,8 +72,8 @@ Blockly.zelos.TopRow.prototype.hasLeftSquareCorner = function(block) {
* Render a round corner unless the block has an output connection.
* @override
*/
Blockly.zelos.TopRow.prototype.hasRightSquareCorner = function(block) {
return !!block.outputConnection;
Blockly.zelos.TopRow.prototype.hasRightSquareCorner = function(_block) {
return false;
};
/**
@@ -112,6 +112,6 @@ Blockly.zelos.BottomRow.prototype.hasLeftSquareCorner = function(block) {
* Render a round corner unless the block has an output connection.
* @override
*/
Blockly.zelos.BottomRow.prototype.hasRightSquareCorner = function(block) {
return !!block.outputConnection;
Blockly.zelos.BottomRow.prototype.hasRightSquareCorner = function(_block) {
return false;
};