From 7e221c20deae780a4791dd6da5a70cf9dff76980 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Wed, 23 Feb 2022 22:12:32 +0000 Subject: [PATCH] refactor: convert PathObject to an ES6 class (#5954) * refactor: add super call to geras path_object * refactor: run conversion script * clean: cleanup from conversion script * fix: make debug build happy * clean: add clarifying comment * clean: format --- core/renderers/common/path_object.js | 431 ++++++++++++++------------- core/renderers/geras/path_object.js | 253 ++++++++-------- core/renderers/zelos/path_object.js | 1 - tests/deps.js | 2 +- 4 files changed, 337 insertions(+), 350 deletions(-) diff --git a/core/renderers/common/path_object.js b/core/renderers/common/path_object.js index 7898078c8..712e16bde 100644 --- a/core/renderers/common/path_object.js +++ b/core/renderers/common/path_object.js @@ -33,248 +33,251 @@ const {Theme} = goog.requireType('Blockly.Theme'); /** * An object that handles creating and setting each of the SVG elements * used by the renderer. - * @param {!SVGElement} root The root SVG element. - * @param {!Theme.BlockStyle} style The style object to use for - * colouring. - * @param {!ConstantProvider} constants The renderer's - * constants. - * @constructor * @implements {IPathObject} - * @package - * @alias Blockly.blockRendering.PathObject */ -const PathObject = function(root, style, constants) { +class PathObject { /** - * The renderer's constant provider. - * @type {!ConstantProvider} + * @param {!SVGElement} root The root SVG element. + * @param {!Theme.BlockStyle} style The style object to use for + * colouring. + * @param {!ConstantProvider} constants The renderer's + * constants. * @package + * @alias Blockly.blockRendering.PathObject */ - this.constants = constants; + constructor(root, style, constants) { + /** + * The renderer's constant provider. + * @type {!ConstantProvider} + * @package + */ + this.constants = constants; - this.svgRoot = root; + this.svgRoot = root; - /** - * The primary path of the block. - * @type {!SVGElement} - * @package - */ - this.svgPath = - dom.createSvgElement(Svg.PATH, {'class': 'blocklyPath'}, this.svgRoot); + /** + * The primary path of the block. + * @type {!SVGElement} + * @package + */ + this.svgPath = + dom.createSvgElement(Svg.PATH, {'class': 'blocklyPath'}, this.svgRoot); - /** - * The style object to use when colouring block paths. - * @type {!Theme.BlockStyle} - * @package - */ - this.style = style; + /** + * The style object to use when colouring block paths. + * @type {!Theme.BlockStyle} + * @package + */ + this.style = style; - /** - * Holds the cursors svg element when the cursor is attached to the block. - * This is null if there is no cursor on the block. - * @type {SVGElement} - * @package - */ - this.cursorSvg = null; - - /** - * Holds the markers svg element when the marker is attached to the block. - * This is null if there is no marker on the block. - * @type {SVGElement} - * @package - */ - this.markerSvg = null; -}; - -/** - * Set the path generated by the renderer onto the respective SVG element. - * @param {string} pathString The path. - * @package - */ -PathObject.prototype.setPath = function(pathString) { - this.svgPath.setAttribute('d', pathString); -}; - -/** - * Flip the SVG paths in RTL. - * @package - */ -PathObject.prototype.flipRTL = function() { - // Mirror the block's path. - this.svgPath.setAttribute('transform', 'scale(-1 1)'); -}; - -/** - * Add the cursor SVG to this block's SVG group. - * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the - * block SVG group. - * @package - */ -PathObject.prototype.setCursorSvg = function(cursorSvg) { - if (!cursorSvg) { + /** + * Holds the cursors svg element when the cursor is attached to the block. + * This is null if there is no cursor on the block. + * @type {SVGElement} + * @package + */ this.cursorSvg = null; - return; - } - this.svgRoot.appendChild(cursorSvg); - this.cursorSvg = cursorSvg; -}; - -/** - * Add the marker SVG to this block's SVG group. - * @param {SVGElement} markerSvg The SVG root of the marker to be added to the - * block SVG group. - * @package - */ -PathObject.prototype.setMarkerSvg = function(markerSvg) { - if (!markerSvg) { + /** + * Holds the markers svg element when the marker is attached to the block. + * This is null if there is no marker on the block. + * @type {SVGElement} + * @package + */ this.markerSvg = null; - return; } - if (this.cursorSvg) { - this.svgRoot.insertBefore(markerSvg, this.cursorSvg); - } else { - this.svgRoot.appendChild(markerSvg); + /** + * Set the path generated by the renderer onto the respective SVG element. + * @param {string} pathString The path. + * @package + */ + setPath(pathString) { + this.svgPath.setAttribute('d', pathString); } - this.markerSvg = markerSvg; -}; -/** - * Apply the stored colours to the block's path, taking into account whether - * the paths belong to a shadow block. - * @param {!Block} block The source block. - * @package - */ -PathObject.prototype.applyColour = function(block) { - this.svgPath.setAttribute('stroke', this.style.colourTertiary); - this.svgPath.setAttribute('fill', this.style.colourPrimary); - - this.updateShadow_(block.isShadow()); - this.updateDisabled_(!block.isEnabled() || block.getInheritedDisabled()); -}; - -/** - * Set the style. - * @param {!Theme.BlockStyle} blockStyle The block style to use. - * @package - */ -PathObject.prototype.setStyle = function(blockStyle) { - this.style = blockStyle; -}; - -/** - * Add or remove the given CSS class on the path object's root SVG element. - * @param {string} className The name of the class to add or remove - * @param {boolean} add True if the class should be added. False if it should - * be removed. - * @protected - */ -PathObject.prototype.setClass_ = function(className, add) { - if (add) { - dom.addClass(/** @type {!Element} */ (this.svgRoot), className); - } else { - dom.removeClass(/** @type {!Element} */ (this.svgRoot), className); + /** + * Flip the SVG paths in RTL. + * @package + */ + flipRTL() { + // Mirror the block's path. + this.svgPath.setAttribute('transform', 'scale(-1 1)'); } -}; -/** - * Set whether the block shows a highlight or not. Block highlighting is - * often used to visually mark blocks currently being executed. - * @param {boolean} enable True if highlighted. - * @package - */ -PathObject.prototype.updateHighlighted = function(enable) { - if (enable) { - this.svgPath.setAttribute( - 'filter', 'url(#' + this.constants.embossFilterId + ')'); - } else { - this.svgPath.setAttribute('filter', 'none'); + /** + * Add the cursor SVG to this block's SVG group. + * @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the + * block SVG group. + * @package + */ + setCursorSvg(cursorSvg) { + if (!cursorSvg) { + this.cursorSvg = null; + return; + } + + this.svgRoot.appendChild(cursorSvg); + this.cursorSvg = cursorSvg; } -}; -/** - * Updates the look of the block to reflect a shadow state. - * @param {boolean} shadow True if the block is a shadow block. - * @protected - */ -PathObject.prototype.updateShadow_ = function(shadow) { - if (shadow) { - this.svgPath.setAttribute('stroke', 'none'); - this.svgPath.setAttribute('fill', this.style.colourSecondary); + /** + * Add the marker SVG to this block's SVG group. + * @param {SVGElement} markerSvg The SVG root of the marker to be added to the + * block SVG group. + * @package + */ + setMarkerSvg(markerSvg) { + if (!markerSvg) { + this.markerSvg = null; + return; + } + + if (this.cursorSvg) { + this.svgRoot.insertBefore(markerSvg, this.cursorSvg); + } else { + this.svgRoot.appendChild(markerSvg); + } + this.markerSvg = markerSvg; } -}; -/** - * Updates the look of the block to reflect a disabled state. - * @param {boolean} disabled True if disabled. - * @protected - */ -PathObject.prototype.updateDisabled_ = function(disabled) { - this.setClass_('blocklyDisabled', disabled); - if (disabled) { - this.svgPath.setAttribute( - 'fill', 'url(#' + this.constants.disabledPatternId + ')'); + /** + * Apply the stored colours to the block's path, taking into account whether + * the paths belong to a shadow block. + * @param {!Block} block The source block. + * @package + */ + applyColour(block) { + this.svgPath.setAttribute('stroke', this.style.colourTertiary); + this.svgPath.setAttribute('fill', this.style.colourPrimary); + + this.updateShadow_(block.isShadow()); + this.updateDisabled_(!block.isEnabled() || block.getInheritedDisabled()); } -}; -/** - * Add or remove styling showing that a block is selected. - * @param {boolean} enable True if selection is enabled, false otherwise. - * @package - */ -PathObject.prototype.updateSelected = function(enable) { - this.setClass_('blocklySelected', enable); -}; + /** + * Set the style. + * @param {!Theme.BlockStyle} blockStyle The block style to use. + * @package + */ + setStyle(blockStyle) { + this.style = blockStyle; + } -/** - * Add or remove styling showing that a block is dragged over a delete area. - * @param {boolean} enable True if the block is being dragged over a delete - * area, false otherwise. - * @package - */ -PathObject.prototype.updateDraggingDelete = function(enable) { - this.setClass_('blocklyDraggingDelete', enable); -}; + /** + * Add or remove the given CSS class on the path object's root SVG element. + * @param {string} className The name of the class to add or remove + * @param {boolean} add True if the class should be added. False if it should + * be removed. + * @protected + */ + setClass_(className, add) { + if (add) { + dom.addClass(/** @type {!Element} */ (this.svgRoot), className); + } else { + dom.removeClass(/** @type {!Element} */ (this.svgRoot), className); + } + } -/** - * Add or remove styling showing that a block is an insertion marker. - * @param {boolean} enable True if the block is an insertion marker, false - * otherwise. - * @package - */ -PathObject.prototype.updateInsertionMarker = function(enable) { - this.setClass_('blocklyInsertionMarker', enable); -}; + /** + * Set whether the block shows a highlight or not. Block highlighting is + * often used to visually mark blocks currently being executed. + * @param {boolean} enable True if highlighted. + * @package + */ + updateHighlighted(enable) { + if (enable) { + this.svgPath.setAttribute( + 'filter', 'url(#' + this.constants.embossFilterId + ')'); + } else { + this.svgPath.setAttribute('filter', 'none'); + } + } -/** - * Add or remove styling showing that a block is movable. - * @param {boolean} enable True if the block is movable, false otherwise. - * @package - */ -PathObject.prototype.updateMovable = function(enable) { - this.setClass_('blocklyDraggable', enable); -}; + /** + * Updates the look of the block to reflect a shadow state. + * @param {boolean} shadow True if the block is a shadow block. + * @protected + */ + updateShadow_(shadow) { + if (shadow) { + this.svgPath.setAttribute('stroke', 'none'); + this.svgPath.setAttribute('fill', this.style.colourSecondary); + } + } -/** - * Add or remove styling that shows that if the dragging block is dropped, this - * block will be replaced. If a shadow block, it will disappear. Otherwise it - * will bump. - * @param {boolean} enable True if styling should be added. - * @package - */ -PathObject.prototype.updateReplacementFade = function(enable) { - this.setClass_('blocklyReplaceable', enable); -}; + /** + * Updates the look of the block to reflect a disabled state. + * @param {boolean} disabled True if disabled. + * @protected + */ + updateDisabled_(disabled) { + this.setClass_('blocklyDisabled', disabled); + if (disabled) { + this.svgPath.setAttribute( + 'fill', 'url(#' + this.constants.disabledPatternId + ')'); + } + } -/** - * Add or remove styling that shows that if the dragging block is dropped, this - * block will be connected to the input. - * @param {Connection} _conn The connection on the input to highlight. - * @param {boolean} _enable True if styling should be added. - * @package - */ -PathObject.prototype.updateShapeForInputHighlight = function(_conn, _enable) { - // NOP -}; + /** + * Add or remove styling showing that a block is selected. + * @param {boolean} enable True if selection is enabled, false otherwise. + * @package + */ + updateSelected(enable) { + this.setClass_('blocklySelected', enable); + } + + /** + * Add or remove styling showing that a block is dragged over a delete area. + * @param {boolean} enable True if the block is being dragged over a delete + * area, false otherwise. + * @package + */ + updateDraggingDelete(enable) { + this.setClass_('blocklyDraggingDelete', enable); + } + + /** + * Add or remove styling showing that a block is an insertion marker. + * @param {boolean} enable True if the block is an insertion marker, false + * otherwise. + * @package + */ + updateInsertionMarker(enable) { + this.setClass_('blocklyInsertionMarker', enable); + } + + /** + * Add or remove styling showing that a block is movable. + * @param {boolean} enable True if the block is movable, false otherwise. + * @package + */ + updateMovable(enable) { + this.setClass_('blocklyDraggable', enable); + } + + /** + * Add or remove styling that shows that if the dragging block is dropped, + * this block will be replaced. If a shadow block, it will disappear. + * Otherwise it will bump. + * @param {boolean} enable True if styling should be added. + * @package + */ + updateReplacementFade(enable) { + this.setClass_('blocklyReplaceable', enable); + } + + /** + * Add or remove styling that shows that if the dragging block is dropped, + * this block will be connected to the input. + * @param {Connection} _conn The connection on the input to highlight. + * @param {boolean} _enable True if styling should be added. + * @package + */ + updateShapeForInputHighlight(_conn, _enable) { + // NOP + } +} exports.PathObject = PathObject; diff --git a/core/renderers/geras/path_object.js b/core/renderers/geras/path_object.js index d8497279f..139a27579 100644 --- a/core/renderers/geras/path_object.js +++ b/core/renderers/geras/path_object.js @@ -18,7 +18,6 @@ goog.module('Blockly.geras.PathObject'); const colour = goog.require('Blockly.utils.colour'); const dom = goog.require('Blockly.utils.dom'); -const object = goog.require('Blockly.utils.object'); /* eslint-disable-next-line no-unused-vars */ const {ConstantProvider} = goog.requireType('Blockly.geras.ConstantProvider'); const {PathObject: BasePathObject} = goog.require('Blockly.blockRendering.PathObject'); @@ -30,152 +29,138 @@ const {Theme} = goog.requireType('Blockly.Theme'); /** * An object that handles creating and setting each of the SVG elements * used by the renderer. - * @param {!SVGElement} root The root SVG element. - * @param {!Theme.BlockStyle} style The style object to use for - * colouring. - * @param {!ConstantProvider} constants The renderer's constants. - * @constructor - * @extends {BasePathObject} - * @package - * @alias Blockly.geras.PathObject */ -const PathObject = function(root, style, constants) { +class PathObject extends BasePathObject { /** - * The renderer's constant provider. - * @type {!ConstantProvider} - */ - this.constants = constants; - - this.svgRoot = root; - - // The order of creation for these next three matters, because that - // effectively sets their z-indices. - - /** - * The dark path of the block. - * @type {SVGElement} + * @param {!SVGElement} root The root SVG element. + * @param {!Theme.BlockStyle} style The style object to use for + * colouring. + * @param {!ConstantProvider} constants The renderer's constants. + * @alias Blockly.geras.PathObject * @package */ - this.svgPathDark = dom.createSvgElement( - Svg.PATH, {'class': 'blocklyPathDark', 'transform': 'translate(1,1)'}, - this.svgRoot); + constructor(root, style, constants) { + super(root, style, constants); + /** + * The renderer's constant provider. + * @type {!ConstantProvider} + */ + this.constants = constants; - /** - * The primary path of the block. - * @type {!SVGElement} - * @package - */ - this.svgPath = - dom.createSvgElement(Svg.PATH, {'class': 'blocklyPath'}, this.svgRoot); + /** + * The dark path of the block. + * @type {SVGElement} + * @package + */ + this.svgPathDark = dom.createSvgElement( + Svg.PATH, {'class': 'blocklyPathDark', 'transform': 'translate(1,1)'}); - /** - * The light path of the block. - * @type {SVGElement} - * @package - */ - this.svgPathLight = dom.createSvgElement( - Svg.PATH, {'class': 'blocklyPathLight'}, this.svgRoot); + // SVG draw order is based on the order of elements (top most = back most) + // So we need to insert the dark path before the base path to make sure it + // gets drawn first. + this.svgRoot.insertBefore(this.svgPathDark, this.svgPath); - /** - * The colour of the dark path on the block in '#RRGGBB' format. - * @type {string} - * @package - */ - this.colourDark = '#000000'; + /** + * The light path of the block. + * @type {SVGElement} + * @package + */ + this.svgPathLight = dom.createSvgElement( + Svg.PATH, {'class': 'blocklyPathLight'}, this.svgRoot); - /** - * The style object to use when colouring block paths. - * @type {!Theme.BlockStyle} - * @package - */ - this.style = style; -}; -object.inherits(PathObject, BasePathObject); - -/** - * @override - */ -PathObject.prototype.setPath = function(mainPath) { - this.svgPath.setAttribute('d', mainPath); - this.svgPathDark.setAttribute('d', mainPath); -}; - -/** - * Set the highlight path generated by the renderer onto the SVG element. - * @param {string} highlightPath The highlight path. - * @package - */ -PathObject.prototype.setHighlightPath = function(highlightPath) { - this.svgPathLight.setAttribute('d', highlightPath); -}; - -/** - * @override - */ -PathObject.prototype.flipRTL = function() { - // Mirror the block's path. - this.svgPath.setAttribute('transform', 'scale(-1 1)'); - this.svgPathLight.setAttribute('transform', 'scale(-1 1)'); - this.svgPathDark.setAttribute('transform', 'translate(1,1) scale(-1 1)'); -}; - -/** - * @override - */ -PathObject.prototype.applyColour = function(block) { - this.svgPathLight.style.display = ''; - this.svgPathDark.style.display = ''; - this.svgPathLight.setAttribute('stroke', this.style.colourTertiary); - this.svgPathDark.setAttribute('fill', this.colourDark); - - PathObject.superClass_.applyColour.call(this, block); - - this.svgPath.setAttribute('stroke', 'none'); -}; - -/** - * @override - */ -PathObject.prototype.setStyle = function(blockStyle) { - this.style = blockStyle; - this.colourDark = - colour.blend('#000', this.style.colourPrimary, 0.2) || this.colourDark; -}; - -/** - * @override - */ -PathObject.prototype.updateHighlighted = function(highlighted) { - if (highlighted) { - this.svgPath.setAttribute( - 'filter', 'url(#' + this.constants.embossFilterId + ')'); - this.svgPathLight.style.display = 'none'; - } else { - this.svgPath.setAttribute('filter', 'none'); - this.svgPathLight.style.display = 'inline'; + /** + * The colour of the dark path on the block in '#RRGGBB' format. + * @type {string} + * @package + */ + this.colourDark = '#000000'; } -}; -/** - * @override - */ -PathObject.prototype.updateShadow_ = function(shadow) { - if (shadow) { - this.svgPathLight.style.display = 'none'; - this.svgPathDark.setAttribute('fill', this.style.colourSecondary); - this.svgPath.setAttribute('stroke', 'none'); - this.svgPath.setAttribute('fill', this.style.colourSecondary); + /** + * @override + */ + setPath(mainPath) { + this.svgPath.setAttribute('d', mainPath); + this.svgPathDark.setAttribute('d', mainPath); } -}; -/** - * @override - */ -PathObject.prototype.updateDisabled_ = function(disabled) { - PathObject.superClass_.updateDisabled_.call(this, disabled); - if (disabled) { + /** + * Set the highlight path generated by the renderer onto the SVG element. + * @param {string} highlightPath The highlight path. + * @package + */ + setHighlightPath(highlightPath) { + this.svgPathLight.setAttribute('d', highlightPath); + } + + /** + * @override + */ + flipRTL() { + // Mirror the block's path. + this.svgPath.setAttribute('transform', 'scale(-1 1)'); + this.svgPathLight.setAttribute('transform', 'scale(-1 1)'); + this.svgPathDark.setAttribute('transform', 'translate(1,1) scale(-1 1)'); + } + + /** + * @override + */ + applyColour(block) { + this.svgPathLight.style.display = ''; + this.svgPathDark.style.display = ''; + this.svgPathLight.setAttribute('stroke', this.style.colourTertiary); + this.svgPathDark.setAttribute('fill', this.colourDark); + + super.applyColour(block); + this.svgPath.setAttribute('stroke', 'none'); } -}; + + /** + * @override + */ + setStyle(blockStyle) { + this.style = blockStyle; + this.colourDark = + colour.blend('#000', this.style.colourPrimary, 0.2) || this.colourDark; + } + + /** + * @override + */ + updateHighlighted(highlighted) { + if (highlighted) { + this.svgPath.setAttribute( + 'filter', 'url(#' + this.constants.embossFilterId + ')'); + this.svgPathLight.style.display = 'none'; + } else { + this.svgPath.setAttribute('filter', 'none'); + this.svgPathLight.style.display = 'inline'; + } + } + + /** + * @override + */ + updateShadow_(shadow) { + if (shadow) { + this.svgPathLight.style.display = 'none'; + this.svgPathDark.setAttribute('fill', this.style.colourSecondary); + this.svgPath.setAttribute('stroke', 'none'); + this.svgPath.setAttribute('fill', this.style.colourSecondary); + } + } + + /** + * @override + */ + updateDisabled_(disabled) { + super.updateDisabled_(disabled); + if (disabled) { + this.svgPath.setAttribute('stroke', 'none'); + } + } +} exports.PathObject = PathObject; diff --git a/core/renderers/zelos/path_object.js b/core/renderers/zelos/path_object.js index 84131e166..387770eba 100644 --- a/core/renderers/zelos/path_object.js +++ b/core/renderers/zelos/path_object.js @@ -28,7 +28,6 @@ const {Theme} = goog.requireType('Blockly.Theme'); /** * An object that handles creating and setting each of the SVG elements * used by the renderer. - * @extends {BasePathObject} */ class PathObject extends BasePathObject { /** diff --git a/tests/deps.js b/tests/deps.js index 19b5c7257..f6bb165b6 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -159,7 +159,7 @@ goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras. goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/geras/measurables/inline_input.js', ['Blockly.geras.InlineInput'], ['Blockly.blockRendering.InlineInput'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/geras/measurables/statement_input.js', ['Blockly.geras.StatementInput'], ['Blockly.blockRendering.StatementInput'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/renderers/measurables/bottom_row.js', ['Blockly.blockRendering.BottomRow'], ['Blockly.blockRendering.Row', 'Blockly.blockRendering.Types'], {'lang': 'es6', 'module': 'goog'});