diff --git a/core/block_render_svg_horizontal.js b/core/block_render_svg_horizontal.js index 4c91f7c112..99fd12dfd9 100644 --- a/core/block_render_svg_horizontal.js +++ b/core/block_render_svg_horizontal.js @@ -201,7 +201,8 @@ Blockly.BlockSvg.prototype.updateColour = function() { this.svgPath_.setAttribute('stroke', strokeColour); // Render block fill - this.svgPath_.setAttribute('fill', this.getColour()); + var fillColour = (this.isGlowing_) ? this.getColourSecondary() : this.getColour(); + this.svgPath_.setAttribute('fill', fillColour); // Bump every dropdown to change its colour. for (var x = 0, input; input = this.inputList[x]; x++) { diff --git a/core/block_svg.js b/core/block_svg.js index ce19f26e86..6694aba840 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -76,6 +76,13 @@ Blockly.BlockSvg.prototype.width = 0; */ Blockly.BlockSvg.prototype.dragStartXY_ = null; +/** + * Whether the block glows as if running. + * @type {boolean} + * @private + */ +Blockly.BlockSvg.prototype.isGlowing_ = false; + /** * Constant for identifying rows that are to be rendered inline. * Don't collide with Blockly.INPUT_VALUE and friends. @@ -134,6 +141,15 @@ Blockly.BlockSvg.prototype.unselect = function() { Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange'); }; +/** + * Glow this block. Highlight it visually as if it's running. + * @param {boolean} isGlowing Whether the block should glow. + */ +Blockly.BlockSvg.prototype.setGlow = function(isGlowing) { + this.isGlowing_ = isGlowing; + this.updateColour(); +}; + /** * Block's mutator icon (if any). * @type {Blockly.Mutator} diff --git a/core/inject.js b/core/inject.js index 13d3a04d77..29c936f0a0 100644 --- a/core/inject.js +++ b/core/inject.js @@ -279,6 +279,19 @@ Blockly.createDom_ = function(container, options) { 'k1': 0, 'k2': 1, 'k3': 1, 'k4': 0}, embossFilter); options.embossFilterId = embossFilter.id; + var stackGlowFilter = Blockly.createSvgElement('filter', + {'id': 'blocklyStackGlowFilter' + rnd}, defs); + Blockly.createSvgElement('feMorphology', + {'in': 'SourceAlpha', 'operator': 'dilate', 'radius': 4, 'result': 'outBlur'}, stackGlowFilter); + Blockly.createSvgElement('feFlood', + {'flood-color': '#05f', 'flood-opacity': '0.9', 'result': 'outColor'}, stackGlowFilter); + Blockly.createSvgElement('feComposite', + {'in': 'outColor', 'in2': 'outBlur', + 'operator': 'in', 'result': 'outGlow'}, stackGlowFilter); + Blockly.createSvgElement('feComposite', + {'in': 'SourceGraphic', 'in2': 'outGlow', 'operator': 'over'}, stackGlowFilter); + options.stackGlowFilterId = stackGlowFilter.id; + var disabledPattern = Blockly.createSvgElement('pattern', {'id': 'blocklyDisabledPattern' + rnd, 'patternUnits': 'userSpaceOnUse', diff --git a/core/workspace_svg.js b/core/workspace_svg.js index e258a6e15c..c9ff7a4639 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -454,6 +454,22 @@ Blockly.WorkspaceSvg.prototype.highlightBlock = function(id) { setTimeout(function() {thisWorkspace.traceOn(true);}, 1); }; +/** + * Glow/unglow a block in the workspace. + * @param {?string} id ID of block to find. + * @param {boolean} isGlowing Whether to glow the block. + */ +Blockly.WorkspaceSvg.prototype.glowBlock = function(id, isGlowing) { + var block = null; + if (id) { + block = Blockly.Block.getById(id); + if (!block) { + throw 'Tried to glow block that does not exist.'; + } + } + block.setGlow(isGlowing); +}; + /** * Paste the provided block onto the workspace. * @param {!Element} xmlBlock XML block element.