diff --git a/blockly_uncompressed.js b/blockly_uncompressed.js index dc06f2b86..f0a828915 100644 --- a/blockly_uncompressed.js +++ b/blockly_uncompressed.js @@ -116,11 +116,11 @@ goog.addDependency("../../core/renderers/minimalist/info.js", ['Blockly.minimali goog.addDependency("../../core/renderers/minimalist/renderer.js", ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.utils.object', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo']); goog.addDependency("../../core/renderers/thrasos/info.js", ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.utils.object']); goog.addDependency("../../core/renderers/thrasos/renderer.js", ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object']); -goog.addDependency("../../core/renderers/zelos/constants.js", ['Blockly.zelos.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object', 'Blockly.utils.svgPaths']); +goog.addDependency("../../core/renderers/zelos/constants.js", ['Blockly.zelos.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths']); goog.addDependency("../../core/renderers/zelos/drawer.js", ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.Types', 'Blockly.utils.object', 'Blockly.zelos.RenderInfo']); goog.addDependency("../../core/renderers/zelos/info.js", ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.utils.object', 'Blockly.zelos.AfterStatementSpacerRow', 'Blockly.zelos.BeforeStatementSpacerRow', 'Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow']); goog.addDependency("../../core/renderers/zelos/measurables/rows.js", ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow', 'Blockly.zelos.AfterStatementSpacerRow', 'Blockly.zelos.BeforeStatementSpacerRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.SpacerRow', 'Blockly.utils.object']); -goog.addDependency("../../core/renderers/zelos/path_object.js", ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.zelos.ConstantProvider', 'Blockly.utils.object']); +goog.addDependency("../../core/renderers/zelos/path_object.js", ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.zelos.ConstantProvider', 'Blockly.utils.dom', 'Blockly.utils.object']); goog.addDependency("../../core/renderers/zelos/renderer.js", ['Blockly.zelos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo']); goog.addDependency("../../core/requires.js", ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.HorizontalFlyout', 'Blockly.VerticalFlyout', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.ZoomControls', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldLabelSerializable', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldVariable', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer', 'Blockly.Themes.Classic', 'Blockly.Themes.Dark', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia']); goog.addDependency("../../core/scrollbar.js", ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Touch', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']); diff --git a/core/css.js b/core/css.js index a59640bae..761ac9e39 100644 --- a/core/css.js +++ b/core/css.js @@ -254,11 +254,6 @@ Blockly.Css.CONTENT = [ 'stroke-width: 1;', '}', - '.blocklySelected>.blocklyPath {', - 'stroke: #fc3;', - 'stroke-width: 3px;', - '}', - '.blocklySelected>.blocklyPathLight {', 'display: none;', '}', diff --git a/core/renderers/common/path_object.js b/core/renderers/common/path_object.js index 8e82b2be2..1671f3777 100644 --- a/core/renderers/common/path_object.js +++ b/core/renderers/common/path_object.js @@ -181,6 +181,13 @@ Blockly.blockRendering.PathObject.prototype.updateDisabled = function(disabled, */ Blockly.blockRendering.PathObject.prototype.updateSelected = function(enable) { this.setClass_('blocklySelected', enable); + if (enable) { + this.svgPath.setAttribute('stroke', '#fc3'); + this.svgPath.setAttribute('stroke-width', '3px'); + } else { + this.svgPath.setAttribute('stroke', ''); + this.svgPath.setAttribute('stroke-width', ''); + } }; /** diff --git a/core/renderers/zelos/constants.js b/core/renderers/zelos/constants.js index 8e17d9d69..f12ea22f2 100644 --- a/core/renderers/zelos/constants.js +++ b/core/renderers/zelos/constants.js @@ -25,6 +25,7 @@ goog.provide('Blockly.zelos.ConstantProvider'); goog.require('Blockly.blockRendering.ConstantProvider'); +goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.object'); goog.require('Blockly.utils.svgPaths'); @@ -79,6 +80,21 @@ Blockly.zelos.ConstantProvider = function() { * @override */ this.AFTER_STATEMENT_BOTTOM_ROW_MIN_HEIGHT = this.LARGE_PADDING * 2; + + /** + * The ID of the highlight glow filter, or the empty string if no filter is + * set. + * @type {string} + * @package + */ + this.highlightGlowFilterId = ''; + + /** + * The element to use for a higlight glow, or null if not set. + * @type {SVGElement} + * @private + */ + this.highlightGlowFilter_ = null; }; Blockly.utils.object.inherits(Blockly.zelos.ConstantProvider, Blockly.blockRendering.ConstantProvider); @@ -92,6 +108,16 @@ Blockly.zelos.ConstantProvider.prototype.init = function() { this.ROUNDED = this.makeRounded(); }; +/** + * @override + */ +Blockly.zelos.ConstantProvider.prototype.dispose = function() { + Blockly.zelos.ConstantProvider.superClass_.dispose.call(this); + if (this.highlightGlowFilter_) { + Blockly.utils.dom.removeNode(this.highlightGlowFilter_); + } +}; + /** * @return {!Object} An object containing sizing and path information about * a hexagonal shape for connections. @@ -298,3 +324,61 @@ Blockly.zelos.ConstantProvider.prototype.makeInsideCorners = function() { pathBottomRight: innerBottomRightCorner }; }; + +/** + * @override + */ +Blockly.zelos.ConstantProvider.prototype.createDom = function(svg) { + Blockly.zelos.ConstantProvider.superClass_.createDom.call(this, 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); + // Using a dilate distorts the block shape. + // Instead use a gaussian blur, and then set all alpha to 1 with a transfer. + var highlightGlowFilter = Blockly.utils.dom.createSvgElement('filter', + { + 'id': 'blocklyHighlightGlowFilter' + rnd, + 'height': '160%', + 'width': '180%', + y: '-30%', + x: '-40%' + }, + defs); + Blockly.utils.dom.createSvgElement('feGaussianBlur', + { + 'in': 'SourceGraphic', + 'stdDeviation': 0.5 // TODO: configure size in theme. + }, + highlightGlowFilter); + // Set all gaussian blur pixels to 1 opacity before applying flood + var componentTransfer = Blockly.utils.dom.createSvgElement( + 'feComponentTransfer', {'result': 'outBlur'}, highlightGlowFilter); + Blockly.utils.dom.createSvgElement('feFuncA', + { + 'type': 'table', 'tableValues': '0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1' + }, + componentTransfer); + // Color the highlight + Blockly.utils.dom.createSvgElement('feFlood', + { + 'flood-color': '#FFF200', // TODO: configure colour in theme. + 'flood-opacity': 1, + 'result': 'outColor' + }, + highlightGlowFilter); + Blockly.utils.dom.createSvgElement('feComposite', + { + 'in': 'outColor', 'in2': 'outBlur', + 'operator': 'in', 'result': 'outGlow' + }, + highlightGlowFilter); + this.highlightGlowFilterId = highlightGlowFilter.id; + this.highlightGlowFilter_ = highlightGlowFilter; +}; diff --git a/core/renderers/zelos/path_object.js b/core/renderers/zelos/path_object.js index 8a1383ac6..b0b3b2629 100644 --- a/core/renderers/zelos/path_object.js +++ b/core/renderers/zelos/path_object.js @@ -26,6 +26,7 @@ goog.provide('Blockly.zelos.PathObject'); goog.require('Blockly.blockRendering.PathObject'); goog.require('Blockly.zelos.ConstantProvider'); +goog.require('Blockly.utils.dom'); goog.require('Blockly.utils.object'); @@ -46,6 +47,43 @@ Blockly.zelos.PathObject = function(root, constants) { * @type {!Blockly.zelos.ConstantProvider} */ this.constants_ = constants; + + /** + * The selected path of the block. + * @type {SVGElement} + * @private + */ + this.svgPathSelected_ = null; }; Blockly.utils.object.inherits(Blockly.zelos.PathObject, Blockly.blockRendering.PathObject); + +/** + * @override + */ +Blockly.zelos.PathObject.prototype.setPath = function(pathString) { + Blockly.zelos.PathObject.superClass_.setPath.call(this, pathString); + if (this.svgPathSelected_) { + this.svgPathSelected_.setAttribute('d', pathString); + } +}; + +/** + * @override + */ +Blockly.zelos.PathObject.prototype.updateSelected = function(enable) { + this.setClass_('blocklySelected', enable); + if (enable) { + this.svgPathSelected_ = + /** @type {!SVGElement} */ (this.svgPath.cloneNode(true)); + this.svgPathSelected_.setAttribute('fill', 'none'); + this.svgPathSelected_.setAttribute('filter', + 'url(#' + this.constants_.highlightGlowFilterId + ')'); + this.svgRoot.appendChild(this.svgPathSelected_); + } else { + if (this.svgPathSelected_) { + this.svgRoot.removeChild(this.svgPathSelected_); + this.svgPathSelected_ = null; + } + } +};