File "rows.js"
Full path: /usr/home/mndrn/domains/mndrn.ru/public_html/block-hill/blockly/core/renderers/measurables/rows.js
File size: 14.67 KiB (15017 bytes)
MIME-type: text/plain
Charset: utf-8
/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Objects representing a single row on a rendered block and all
* of its subcomponents.
* @author [email protected] (Rachel Fenichel)
*/
goog.provide('Blockly.blockRendering.BottomRow');
goog.provide('Blockly.blockRendering.InputRow');
goog.provide('Blockly.blockRendering.Row');
goog.provide('Blockly.blockRendering.SpacerRow');
goog.provide('Blockly.blockRendering.TopRow');
goog.require('Blockly.blockRendering.InputConnection');
goog.require('Blockly.blockRendering.InRowSpacer');
goog.require('Blockly.blockRendering.Measurable');
goog.require('Blockly.blockRendering.NextConnection');
goog.require('Blockly.blockRendering.PreviousConnection');
goog.require('Blockly.blockRendering.Types');
goog.require('Blockly.utils.object');
/**
* An object representing a single row on a rendered block and all of its
* subcomponents.
* @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
* constants provider.
* @package
* @constructor
*/
Blockly.blockRendering.Row = function(constants) {
/**
* The type of this rendering object.
* @package
* @type {number}
*/
this.type = Blockly.blockRendering.Types.ROW;
/**
* An array of elements contained in this row.
* @package
* @type {!Array.<!Blockly.blockRendering.Measurable>}
*/
this.elements = [];
/**
* The height of the row.
* @package
* @type {number}
*/
this.height = 0;
/**
* The width of the row, from the left edge of the block to the right.
* Does not include child blocks unless they are inline.
* @package
* @type {number}
*/
this.width = 0;
/**
* The minimum height of the row.
* @package
* @type {number}
*/
this.minHeight = 0;
/**
* The minimum width of the row, from the left edge of the block to the right.
* Does not include child blocks unless they are inline.
* @package
* @type {number}
*/
this.minWidth = 0;
/**
* The width of the row, from the left edge of the block to the edge of the
* block or any connected child blocks.
* @package
* @type {number}
*/
this.widthWithConnectedBlocks = 0;
/**
* The Y position of the row relative to the origin of the block's svg group.
* @package
* @type {number}
*/
this.yPos = 0;
/**
* The X position of the row relative to the origin of the block's svg group.
* @package
* @type {number}
*/
this.xPos = 0;
/**
* Whether the row has any external inputs.
* @package
* @type {boolean}
*/
this.hasExternalInput = false;
/**
* Whether the row has any statement inputs.
* @package
* @type {boolean}
*/
this.hasStatement = false;
/**
* Whether the row has any inline inputs.
* @package
* @type {boolean}
*/
this.hasInlineInput = false;
/**
* Whether the row has any dummy inputs.
* @package
* @type {boolean}
*/
this.hasDummyInput = false;
/**
* Whether the row has a jagged edge.
* @package
* @type {boolean}
*/
this.hasJaggedEdge = false;
/**
* The renderer's constant provider.
* @type {!Blockly.blockRendering.ConstantProvider}
* @protected
*/
this.constants_ = constants;
this.notchOffset = this.constants_.NOTCH_OFFSET_LEFT;
/**
* Alignment of the row.
* @package
* @type {?number}
*/
this.align = null;
};
/**
* Inspect all subcomponents and populate all size properties on the row.
* @package
*/
Blockly.blockRendering.Row.prototype.measure = function() {
throw Error('Unexpected attempt to measure a base Row.');
};
/**
* Get the last input on this row, if it has one.
* @return {Blockly.blockRendering.InputConnection} The last input on the row,
* or null.
* @package
*/
// TODO: Consider moving this to InputRow, if possible.
Blockly.blockRendering.Row.prototype.getLastInput = function() {
for (var i = this.elements.length - 1, elem; (elem = this.elements[i]); i--) {
if (Blockly.blockRendering.Types.isInput(elem)) {
return /** @type {Blockly.blockRendering.InputConnection} */ (elem);
}
}
return null;
};
/**
* Determines whether this row should start with an element spacer.
* @return {boolean} Whether the row should start with a spacer.
* @package
*/
Blockly.blockRendering.Row.prototype.startsWithElemSpacer = function() {
return true;
};
/**
* Determines whether this row should end with an element spacer.
* @return {boolean} Whether the row should end with a spacer.
* @package
*/
Blockly.blockRendering.Row.prototype.endsWithElemSpacer = function() {
return true;
};
/**
* Convenience method to get the first spacer element on this row.
* @return {Blockly.blockRendering.InRowSpacer} The first spacer element on
* this row.
* @package
*/
Blockly.blockRendering.Row.prototype.getFirstSpacer = function() {
for (var i = 0, elem; (elem = this.elements[i]); i++) {
if (Blockly.blockRendering.Types.isSpacer(elem)) {
return /** @type {Blockly.blockRendering.InRowSpacer} */ (elem);
}
}
return null;
};
/**
* Convenience method to get the last spacer element on this row.
* @return {Blockly.blockRendering.InRowSpacer} The last spacer element on
* this row.
* @package
*/
Blockly.blockRendering.Row.prototype.getLastSpacer = function() {
for (var i = this.elements.length - 1, elem; (elem = this.elements[i]); i--) {
if (Blockly.blockRendering.Types.isSpacer(elem)) {
return /** @type {Blockly.blockRendering.InRowSpacer} */ (elem);
}
}
return null;
};
/**
* An object containing information about what elements are in the top row of a
* block as well as sizing information for the top row.
* Elements in a top row can consist of corners, hats, spacers, and previous
* connections.
* After this constructor is called, the row will contain all non-spacer
* elements it needs.
* @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
* constants provider.
* @package
* @constructor
* @extends {Blockly.blockRendering.Row}
*/
Blockly.blockRendering.TopRow = function(constants) {
Blockly.blockRendering.TopRow.superClass_.constructor.call(this, constants);
this.type |= Blockly.blockRendering.Types.TOP_ROW;
/**
* The starting point for drawing the row, in the y direction.
* This allows us to draw hats and similar shapes that don't start at the
* origin. Must be non-negative (see #2820).
* @package
* @type {number}
*/
this.capline = 0;
/**
* How much the row extends up above its capline.
* @type {number}
*/
this.ascenderHeight = 0;
/**
* Whether the block has a previous connection.
* @package
* @type {boolean}
*/
this.hasPreviousConnection = false;
/**
* The previous connection on the block, if any.
* @type {Blockly.blockRendering.PreviousConnection}
*/
this.connection = null;
};
Blockly.utils.object.inherits(Blockly.blockRendering.TopRow,
Blockly.blockRendering.Row);
/**
* Returns whether or not the top row has a left square corner.
* @param {!Blockly.BlockSvg} block The block whose top row this represents.
* @return {boolean} Whether or not the top row has a left square corner.
*/
Blockly.blockRendering.TopRow.prototype.hasLeftSquareCorner = function(block) {
var hasHat = (block.hat ?
block.hat === 'cap' : this.constants_.ADD_START_HATS) &&
!block.outputConnection && !block.previousConnection;
var prevBlock = block.getPreviousBlock();
return !!block.outputConnection ||
hasHat || (prevBlock ? prevBlock.getNextBlock() == block : false);
};
/**
* Returns whether or not the top row has a right square corner.
* @param {!Blockly.BlockSvg} _block The block whose top row this represents.
* @return {boolean} Whether or not the top row has a right square corner.
*/
Blockly.blockRendering.TopRow.prototype.hasRightSquareCorner = function(
_block) {
return true;
};
/**
* @override
*/
Blockly.blockRendering.TopRow.prototype.measure = function() {
var height = 0;
var width = 0;
var ascenderHeight = 0;
for (var e = 0, elem; (elem = this.elements[e]); e++) {
width += elem.width;
if (!(Blockly.blockRendering.Types.isSpacer(elem))) {
if (Blockly.blockRendering.Types.isHat(elem)) {
ascenderHeight = Math.max(ascenderHeight, elem.ascenderHeight);
} else {
height = Math.max(height, elem.height);
}
}
}
this.width = Math.max(this.minWidth, width);
this.height = Math.max(this.minHeight, height) + ascenderHeight;
this.ascenderHeight = ascenderHeight;
this.capline = this.ascenderHeight;
this.widthWithConnectedBlocks = this.width;
};
/**
* @override
*/
Blockly.blockRendering.TopRow.prototype.startsWithElemSpacer = function() {
return false;
};
/**
* @override
*/
Blockly.blockRendering.TopRow.prototype.endsWithElemSpacer = function() {
return false;
};
/**
* An object containing information about what elements are in the bottom row of
* a block as well as spacing information for the top row.
* Elements in a bottom row can consist of corners, spacers and next
* connections.
* @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
* constants provider.
* @package
* @constructor
* @extends {Blockly.blockRendering.Row}
*/
Blockly.blockRendering.BottomRow = function(constants) {
Blockly.blockRendering.BottomRow.superClass_.constructor.call(this,
constants);
this.type |= Blockly.blockRendering.Types.BOTTOM_ROW;
/**
* Whether this row has a next connection.
* @package
* @type {boolean}
*/
this.hasNextConnection = false;
/**
* The next connection on the row, if any.
* @package
* @type {Blockly.blockRendering.NextConnection}
*/
this.connection = null;
/**
* The amount that the bottom of the block extends below the horizontal edge,
* e.g. because of a next connection. Must be non-negative (see #2820).
* @package
* @type {number}
*/
this.descenderHeight = 0;
/**
* The Y position of the bottom edge of the block, relative to the origin
* of the block rendering.
* @type {number}
*/
this.baseline = 0;
};
Blockly.utils.object.inherits(Blockly.blockRendering.BottomRow,
Blockly.blockRendering.Row);
/**
* Returns whether or not the bottom row has a left square corner.
* @param {!Blockly.BlockSvg} block The block whose bottom row this represents.
* @return {boolean} Whether or not the bottom row has a left square corner.
*/
Blockly.blockRendering.BottomRow.prototype.hasLeftSquareCorner = function(
block) {
return !!block.outputConnection || !!block.getNextBlock();
};
/**
* Returns whether or not the bottom row has a right square corner.
* @param {!Blockly.BlockSvg} _block The block whose bottom row this represents.
* @return {boolean} Whether or not the bottom row has a right square corner.
*/
Blockly.blockRendering.BottomRow.prototype.hasRightSquareCorner = function(
_block) {
return true;
};
/**
* @override
*/
Blockly.blockRendering.BottomRow.prototype.measure = function() {
var height = 0;
var width = 0;
var descenderHeight = 0;
for (var e = 0, elem; (elem = this.elements[e]); e++) {
width += elem.width;
if (!(Blockly.blockRendering.Types.isSpacer(elem))) {
// Note: this assumes that next connections have *only* descenderHeight,
// with no height above the baseline.
if (Blockly.blockRendering.Types.isNextConnection(elem)) {
descenderHeight = Math.max(descenderHeight, elem.height);
} else {
height = Math.max(height, elem.height);
}
}
}
this.width = Math.max(this.minWidth, width);
this.height = Math.max(this.minHeight, height) + descenderHeight;
this.descenderHeight = descenderHeight;
this.widthWithConnectedBlocks = this.width;
};
/**
* @override
*/
Blockly.blockRendering.BottomRow.prototype.startsWithElemSpacer = function() {
return false;
};
/**
* @override
*/
Blockly.blockRendering.BottomRow.prototype.endsWithElemSpacer = function() {
return false;
};
/**
* An object containing information about a spacer between two rows.
* @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
* constants provider.
* @param {number} height The height of the spacer.
* @param {number} width The width of the spacer.
* @package
* @constructor
* @extends {Blockly.blockRendering.Row}
*/
Blockly.blockRendering.SpacerRow = function(constants, height, width) {
Blockly.blockRendering.SpacerRow.superClass_.constructor.call(this,
constants);
this.type |= Blockly.blockRendering.Types.SPACER |
Blockly.blockRendering.Types.BETWEEN_ROW_SPACER;
this.width = width;
this.height = height;
this.followsStatement = false;
this.widthWithConnectedBlocks = 0;
this.elements = [
new Blockly.blockRendering.InRowSpacer(this.constants_, width)];
};
Blockly.utils.object.inherits(Blockly.blockRendering.SpacerRow,
Blockly.blockRendering.Row);
/**
* @override
*/
Blockly.blockRendering.SpacerRow.prototype.measure = function() {
// NOP. Width and height were set at creation.
};
/**
* An object containing information about a row that holds one or more inputs.
* @param {!Blockly.blockRendering.ConstantProvider} constants The rendering
* constants provider.
* @package
* @constructor
* @extends {Blockly.blockRendering.Row}
*/
Blockly.blockRendering.InputRow = function(constants) {
Blockly.blockRendering.InputRow.superClass_.constructor.call(this, constants);
this.type |= Blockly.blockRendering.Types.INPUT_ROW;
/**
* The total width of all blocks connected to this row.
* @type {number}
* @package
*/
this.connectedBlockWidths = 0;
};
Blockly.utils.object.inherits(Blockly.blockRendering.InputRow,
Blockly.blockRendering.Row);
/**
* Inspect all subcomponents and populate all size properties on the row.
* @package
*/
Blockly.blockRendering.InputRow.prototype.measure = function() {
this.width = this.minWidth;
this.height = this.minHeight;
var connectedBlockWidths = 0;
for (var e = 0, elem; (elem = this.elements[e]); e++) {
this.width += elem.width;
if (Blockly.blockRendering.Types.isInput(elem)) {
if (Blockly.blockRendering.Types.isStatementInput(elem)) {
connectedBlockWidths += elem.connectedBlockWidth;
} else if (Blockly.blockRendering.Types.isExternalInput(elem) &&
elem.connectedBlockWidth != 0) {
connectedBlockWidths += (elem.connectedBlockWidth -
elem.connectionWidth);
}
}
if (!(Blockly.blockRendering.Types.isSpacer(elem))) {
this.height = Math.max(this.height, elem.height);
}
}
this.connectedBlockWidths = connectedBlockWidths;
this.widthWithConnectedBlocks = this.width + connectedBlockWidths;
};
/**
* @override
*/
Blockly.blockRendering.InputRow.prototype.endsWithElemSpacer = function() {
return !this.hasExternalInput && !this.hasStatement;
};