From 455432250e1d26129023eab5289f1be2f2113c67 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Wed, 22 Feb 2017 17:05:52 -0800 Subject: [PATCH] Use mutator extension for controls_if block --- blocks/logic.js | 18 +++++++++------- core/block.js | 5 +++++ core/extensions.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/blocks/logic.js b/blocks/logic.js index a9d165314..051c46fdf 100644 --- a/blocks/logic.js +++ b/blocks/logic.js @@ -86,7 +86,8 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT "nextStatement": null, "colour": "%{BKY_LOGIC_HUE}", "helpUrl": "%{BKY_CONTROLS_IF_HELPURL}", - "extensions": ["controls_if_mutator"] + "mutator": "controls_if_mutator", + "extensions": ["controls_if_tooltip"] }, // If/else block that does not use a mutator. { @@ -457,15 +458,16 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN = { } }; +Blockly.Extensions.registerMutator('controls_if_mutator', + Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN, + ['controls_if_elseif', 'controls_if_else']); /** * "controls_if" extension function. Adds mutator, shape updating methods, and * dynamic tooltip to "controls_if" blocks. * @this Blockly.Block * @package */ -Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_EXTENSION = function() { - this.setMutator(new Blockly.Mutator(['controls_if_elseif', 'controls_if_else'])); - this.mixin(Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN); +Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION = function() { this.setTooltip(function() { if (!this.elseifCount_ && !this.elseCount_) { @@ -481,11 +483,11 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_EXTENSION = function() { }.bind(this)); }; -Blockly.Extensions.register('controls_if_mutator', - Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_EXTENSION); +Blockly.Extensions.register('controls_if_tooltip', + Blockly.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION); /** - * Corrects the logic_compate dropdown label with respect to language direction. + * Corrects the logic_compare dropdown label with respect to language direction. * @this Blockly.Block * @package */ @@ -513,7 +515,7 @@ Blockly.Constants.Logic.fixLogicCompareRtlOpLabels = }; /** - * Adds dynamic type validation for the left and right sides of a logic_compate block. + * Adds dynamic type validation for the left and right sides of a logic_compare block. * @mixin * @augments Blockly.Block * @package diff --git a/core/block.js b/core/block.js index 4ad3117b0..73abaebf0 100644 --- a/core/block.js +++ b/core/block.js @@ -985,6 +985,11 @@ Blockly.Block.prototype.appendDummyInput = function(opt_name) { * @param {!Object} json Structured data describing the block. */ Blockly.Block.prototype.jsonInit = function(json) { + // Add the mutator to the block + if (json['mutator'] !== undefined) { + Blockly.Extensions.apply(json['mutator'], this); + } + // Validate inputs. goog.asserts.assert(json['output'] == undefined || json['previousStatement'] == undefined, diff --git a/core/extensions.js b/core/extensions.js index ad9db0dc6..b64a8ca21 100644 --- a/core/extensions.js +++ b/core/extensions.js @@ -76,6 +76,60 @@ Blockly.Extensions.registerMixin = function(name, mixinObj) { }); }; +/** + * Registers a new extension function that adds a mutator to the block. + * A mutator must have, at minimum, domToMutation and mutationToDom. When + * mixing it into a block, the wrapper will check that domToMutation and + * mutationToDom are not already defined on that block. + * The wrapper may also add a mutator dialog to the block. + * @param {string} name The name of this mutator extension. + * @param {!Object} mixinObj The values to mix in. + * @param {Array.=} opt_blockList A list of blocks to appear in the flyout + * of the mutator dialog. If a list is passed in, the extension will also + * add a mutator dialog to the block. + * @throws {Error} if the extension name is empty; the extension is already + * registered; or domToMutation and mutationToDom are wrong. + */ +Blockly.Extensions.registerMutator = function(name, mixinObj, opt_blockList) { + Blockly.Extensions.register(name, function() { + // Check that the mixin object makese sense. + if (!mixinObj.hasOwnProperty('domToMutation')) { + throw new Error('Error: mutation name "' + name + '" is missing domToMutation'); + } else if (typeof mixinObj['domToMutation'] !== "function") { + throw new Error('Error: mutation name "' + name + + '" has a domToMutation that is not a function'); + } + + if (!mixinObj.hasOwnProperty('mutationToDom')) { + throw new Error('Error: mutation name "' + name + '" is missing mutationToDom'); + } else if (typeof mixinObj['mutationToDom'] !== "function") { + throw new Error('Error: mutation name "' + name + + '" has a mutationToDom that is not a function'); + } + + // Check that we're not overwriting anything. + if (this.hasOwnProperty('domToMutation')) { + throw new Error('Error: tried to apply mutation "' + name + + '" to a block that already has a domToMutation function. Block id: ' + + this.id); + } + + if (this.hasOwnProperty('mutationToDom')) { + throw new Error('Error: tried to apply mutation "' + name + + '" to a block that already has a domToMutation function. Block id: ' + + this.id); + } + + // Possibly add a mutator dialog. + if (opt_blockList) { + this.setMutator(new Blockly.Mutator(opt_blockList)); + } + + // Finally, mixin the object. + this.mixin(mixinObj); + }); +}; + /** * Applies an extension method to a block. This should only be called during * block construction.