From 46f323971a8000c4fa9a5f0186c6d22ae387a51e Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 1 Nov 2019 13:32:17 -0700 Subject: [PATCH 1/2] Move filter and pattern creation from inject into constants. --- core/block_svg.js | 6 ++- core/inject.js | 67 ----------------------- core/renderers/common/constants.js | 86 ++++++++++++++++++++++++++++++ core/workspace_svg.js | 1 + 4 files changed, 91 insertions(+), 69 deletions(-) diff --git a/core/block_svg.js b/core/block_svg.js index d568207fd..4c5902ed5 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -1061,7 +1061,8 @@ Blockly.BlockSvg.prototype.updateDisabled = function() { /** @type {!Element} */ (this.svgGroup_), 'blocklyDisabled'); if (added) { this.svgPath_.setAttribute('fill', - 'url(#' + this.workspace.options.disabledPatternId + ')'); + 'url(#' + + this.workspace.getRenderer().getConstants().disabledPatternId + ')'); } } else { var removed = Blockly.utils.dom.removeClass( @@ -1253,7 +1254,8 @@ Blockly.BlockSvg.prototype.setHighlighted = function(highlighted) { } if (highlighted) { this.svgPath_.setAttribute('filter', - 'url(#' + this.workspace.options.embossFilterId + ')'); + 'url(#' + + this.workspace.getRenderer().getConstants().embossFilterId + ')'); this.svgPathLight_.style.display = 'none'; } else { this.svgPath_.setAttribute('filter', 'none'); diff --git a/core/inject.js b/core/inject.js index 805200e75..be46c684c 100644 --- a/core/inject.js +++ b/core/inject.js @@ -139,73 +139,6 @@ Blockly.createDom_ = function(container, options) { // instances on a page. Browser behaviour becomes undefined otherwise. // https://neil.fraser.name/news/2015/11/01/ var rnd = String(Math.random()).substring(2); - /* - - - - - - - - - */ - var embossFilter = Blockly.utils.dom.createSvgElement('filter', - {'id': 'blocklyEmbossFilter' + rnd}, defs); - Blockly.utils.dom.createSvgElement('feGaussianBlur', - {'in': 'SourceAlpha', 'stdDeviation': 1, 'result': 'blur'}, embossFilter); - var feSpecularLighting = Blockly.utils.dom.createSvgElement('feSpecularLighting', - { - 'in': 'blur', - 'surfaceScale': 1, - 'specularConstant': 0.5, - 'specularExponent': 10, - 'lighting-color': 'white', - 'result': 'specOut' - }, - embossFilter); - Blockly.utils.dom.createSvgElement('fePointLight', - {'x': -5000, 'y': -10000, 'z': 20000}, feSpecularLighting); - Blockly.utils.dom.createSvgElement('feComposite', - { - 'in': 'specOut', - 'in2': 'SourceAlpha', - 'operator': 'in', - 'result': 'specOut' - }, embossFilter); - Blockly.utils.dom.createSvgElement('feComposite', - { - 'in': 'SourceGraphic', - 'in2': 'specOut', - 'operator': 'arithmetic', - 'k1': 0, - 'k2': 1, - 'k3': 1, - 'k4': 0 - }, embossFilter); - options.embossFilterId = embossFilter.id; - /* - - - - - */ - var disabledPattern = Blockly.utils.dom.createSvgElement('pattern', - { - 'id': 'blocklyDisabledPattern' + rnd, - 'patternUnits': 'userSpaceOnUse', - 'width': 10, - 'height': 10 - }, defs); - Blockly.utils.dom.createSvgElement('rect', - {'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern); - Blockly.utils.dom.createSvgElement('path', - {'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, disabledPattern); - options.disabledPatternId = disabledPattern.id; options.gridPattern = Blockly.Grid.createDom(rnd, options.gridOptions, defs); return svg; diff --git a/core/renderers/common/constants.js b/core/renderers/common/constants.js index bfc753f09..fedfd85a7 100644 --- a/core/renderers/common/constants.js +++ b/core/renderers/common/constants.js @@ -398,3 +398,89 @@ Blockly.blockRendering.ConstantProvider.prototype.shapeFor = function( throw Error('Unknown connection type'); } }; + +/** + * Create any DOM elements that this renderer needs (filters, patterns, etc). + * @param {!SVGElement} svg The root of the workspace's SVG. + * @package + */ +Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg) { + /* + + ... filters go here ... + + */ + var defs = Blockly.utils.dom.createSvgElement('defs', {}, svg); + // Each filter/pattern needs a unique ID for the case of multiple Blockly + // instances on a page. Browser behaviour becomes undefined otherwise. + // https://neil.fraser.name/news/2015/11/01/ + var rnd = String(Math.random()).substring(2); + /* + + + + + + + + + */ + var embossFilter = Blockly.utils.dom.createSvgElement('filter', + {'id': 'blocklyEmbossFilter' + rnd}, defs); + Blockly.utils.dom.createSvgElement('feGaussianBlur', + {'in': 'SourceAlpha', 'stdDeviation': 1, 'result': 'blur'}, embossFilter); + var feSpecularLighting = Blockly.utils.dom.createSvgElement('feSpecularLighting', + { + 'in': 'blur', + 'surfaceScale': 1, + 'specularConstant': 0.5, + 'specularExponent': 10, + 'lighting-color': 'white', + 'result': 'specOut' + }, + embossFilter); + Blockly.utils.dom.createSvgElement('fePointLight', + {'x': -5000, 'y': -10000, 'z': 20000}, feSpecularLighting); + Blockly.utils.dom.createSvgElement('feComposite', + { + 'in': 'specOut', + 'in2': 'SourceAlpha', + 'operator': 'in', + 'result': 'specOut' + }, embossFilter); + Blockly.utils.dom.createSvgElement('feComposite', + { + 'in': 'SourceGraphic', + 'in2': 'specOut', + 'operator': 'arithmetic', + 'k1': 0, + 'k2': 1, + 'k3': 1, + 'k4': 0 + }, embossFilter); + this.embossFilterId = embossFilter.id; + + /* + + + + + */ + var disabledPattern = Blockly.utils.dom.createSvgElement('pattern', + { + 'id': 'blocklyDisabledPattern' + rnd, + 'patternUnits': 'userSpaceOnUse', + 'width': 10, + 'height': 10 + }, defs); + Blockly.utils.dom.createSvgElement('rect', + {'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern); + Blockly.utils.dom.createSvgElement('path', + {'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, disabledPattern); + this.disabledPatternId = disabledPattern.id; +}; diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 4876dd0e0..9e961d8df 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -676,6 +676,7 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) { var svgMarker = this.marker_.getDrawer().createDom(); this.svgGroup_.appendChild(svgMarker); + this.getRenderer().getConstants().createDom(this.svgGroup_); return this.svgGroup_; }; From 13e4d671c3d42230d397e0b4656d3e02923383d1 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Fri, 1 Nov 2019 14:28:51 -0700 Subject: [PATCH 2/2] Moved setHighlighted and setDisabled into the path object. --- core/block_svg.js | 39 ++++------------------ core/bubble.js | 6 ++-- core/mutator.js | 1 - core/renderers/common/constants.js | 45 ++++++++++++++++++++++++++ core/renderers/common/i_path_object.js | 19 ++++++++++- core/renderers/common/path_object.js | 40 ++++++++++++++++++++++- core/renderers/common/renderer.js | 4 ++- core/renderers/geras/path_object.js | 42 +++++++++++++++++++++++- core/renderers/geras/renderer.js | 3 +- core/toolbox.js | 1 - core/trashcan.js | 1 - core/workspace_svg.js | 3 +- 12 files changed, 160 insertions(+), 44 deletions(-) diff --git a/core/block_svg.js b/core/block_svg.js index 4c5902ed5..2527d6756 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -76,23 +76,6 @@ Blockly.BlockSvg = function(workspace, prototypeName, opt_id) { */ this.pathObject = workspace.getRenderer().makePathObject(this.svgGroup_); - // The next two paths are set only for backwards compatibility reasons. - /** - * The primary path of the block. - * @type {SVGElement} - * @private - */ - this.svgPath_ = this.pathObject.svgPath || null; - - /** - * The light path of the block. - * @type {SVGElement} - * @private - */ - this.svgPathLight_ = this.pathObject.svgPathLight || null; - - this.svgPath_.tooltip = this; - /** @type {boolean} */ this.rendered = false; @@ -115,7 +98,9 @@ Blockly.BlockSvg = function(workspace, prototypeName, opt_id) { this.useDragSurface_ = Blockly.utils.is3dSupported() && !!workspace.getBlockDragSurface(); - Blockly.Tooltip.bindMouseEvents(this.svgPath_); + var svgPath = this.pathObject.svgPath; + svgPath.tooltip = this; + Blockly.Tooltip.bindMouseEvents(svgPath); Blockly.BlockSvg.superClass_.constructor.call(this, workspace, prototypeName, opt_id); @@ -1023,8 +1008,6 @@ Blockly.BlockSvg.prototype.dispose = function(healStack, animate) { blockWorkspace.resizeContents(); // Sever JavaScript to DOM connections. this.svgGroup_ = null; - this.svgPath_ = null; - this.svgPathLight_ = null; Blockly.utils.dom.stopTextWidthCache(); }; @@ -1060,15 +1043,13 @@ Blockly.BlockSvg.prototype.updateDisabled = function() { var added = Blockly.utils.dom.addClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDisabled'); if (added) { - this.svgPath_.setAttribute('fill', - 'url(#' + - this.workspace.getRenderer().getConstants().disabledPatternId + ')'); + this.pathObject.setDisabled(true, this.isShadow()); } } else { var removed = Blockly.utils.dom.removeClass( /** @type {!Element} */ (this.svgGroup_), 'blocklyDisabled'); if (removed) { - this.applyColour(); + this.pathObject.setDisabled(false, this.isShadow()); } } var children = this.getChildren(false); @@ -1252,15 +1233,7 @@ Blockly.BlockSvg.prototype.setHighlighted = function(highlighted) { if (!this.rendered) { return; } - if (highlighted) { - this.svgPath_.setAttribute('filter', - 'url(#' + - this.workspace.getRenderer().getConstants().embossFilterId + ')'); - this.svgPathLight_.style.display = 'none'; - } else { - this.svgPath_.setAttribute('filter', 'none'); - this.svgPathLight_.style.display = 'inline'; - } + this.pathObject.setHighlighted(highlighted); }; /** diff --git a/core/bubble.js b/core/bubble.js index c3713d4f8..4e139bdc3 100644 --- a/core/bubble.js +++ b/core/bubble.js @@ -232,7 +232,8 @@ Blockly.Bubble.prototype.createDom_ = function(content, hasResize) { */ this.bubbleGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); var filter = - {'filter': 'url(#' + this.workspace_.options.embossFilterId + ')'}; + {'filter': 'url(#' + + this.workspace_.getRenderer().getConstants().embossFilterId + ')'}; if (Blockly.utils.userAgent.JAVA_FX) { // Multiple reports that JavaFX can't handle filters. // https://github.com/google/blockly/issues/99 @@ -240,7 +241,8 @@ Blockly.Bubble.prototype.createDom_ = function(content, hasResize) { } var bubbleEmboss = Blockly.utils.dom.createSvgElement('g', filter, this.bubbleGroup_); - this.bubbleArrow_ = Blockly.utils.dom.createSvgElement('path', {}, bubbleEmboss); + this.bubbleArrow_ = Blockly.utils.dom.createSvgElement('path', {}, + bubbleEmboss); this.bubbleBack_ = Blockly.utils.dom.createSvgElement('rect', { 'class': 'blocklyDraggable', diff --git a/core/mutator.js b/core/mutator.js index 3b1a1ff4b..006aea0b8 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -154,7 +154,6 @@ Blockly.Mutator.prototype.createEditor_ = function() { // If you want to enable disabling, also remove the // event filter from workspaceChanged_ . disable: false, - disabledPatternId: this.block_.workspace.options.disabledPatternId, languageTree: quarkXml, parentWorkspace: this.block_.workspace, pathToMedia: this.block_.workspace.options.pathToMedia, diff --git a/core/renderers/common/constants.js b/core/renderers/common/constants.js index fedfd85a7..6aa0863f6 100644 --- a/core/renderers/common/constants.js +++ b/core/renderers/common/constants.js @@ -23,6 +23,7 @@ goog.provide('Blockly.blockRendering.ConstantProvider'); +goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.svgPaths'); @@ -134,6 +135,34 @@ Blockly.blockRendering.ConstantProvider = function() { * @const */ this.JAGGED_TEETH_WIDTH = 6; + + /** + * The ID of the emboss filter, or the empty string if no filter is set. + * @type {string} + * @package + */ + this.embossFilterId = ''; + + /** + * The element to use for highlighting, or null if not set. + * @type {SVGElement} + * @private + */ + this.embossFilter_ = null; + + /** + * The ID of the disabled pattern, or the empty string if no pattern is set. + * @type {string} + * @package + */ + this.disabledPatternId = ''; + + /** + * The element to use for disabled blocks, or null if not set. + * @type {SVGElement} + * @private + */ + this.disabledPattern_ = null; }; /** @@ -180,6 +209,20 @@ Blockly.blockRendering.ConstantProvider.prototype.init = function() { this.OUTSIDE_CORNERS = this.makeOutsideCorners(); }; +/** + * Dispose of this constants provider. + * Delete all DOM elements that this provider created. + * @package + */ +Blockly.blockRendering.ConstantProvider.prototype.dispose = function() { + if (this.embossFilter_) { + Blockly.utils.dom.removeNode(this.embossFilter_); + } + if (this.disabledPattern_) { + Blockly.utils.dom.removeNode(this.disabledPattern_); + } +}; + /** * @return {!Object} An object containing sizing and path information about * collapsed block indicators. @@ -463,6 +506,7 @@ Blockly.blockRendering.ConstantProvider.prototype.createDom = function(svg) { 'k4': 0 }, embossFilter); this.embossFilterId = embossFilter.id; + this.embossFilter_ = embossFilter; /*