diff --git a/core/flyout_base.js b/core/flyout_base.js index 6ee69aa30..07f4a9096 100644 --- a/core/flyout_base.js +++ b/core/flyout_base.js @@ -249,29 +249,7 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) { this.targetWorkspace_.getGesture.bind(this.targetWorkspace_); // Get variables from the main workspace rather than the target workspace. - this.workspace_.getVariable = - this.targetWorkspace_.getVariable.bind(this.targetWorkspace_); - - this.workspace_.getVariableById = - this.targetWorkspace_.getVariableById.bind(this.targetWorkspace_); - - this.workspace_.getVariablesOfType = - this.targetWorkspace_.getVariablesOfType.bind(this.targetWorkspace_); - - this.workspace_.deleteVariable = - this.targetWorkspace_.deleteVariable.bind(this.targetWorkspace_); - - this.workspace_.deleteVariableById = - this.targetWorkspace_.deleteVariableById.bind(this.targetWorkspace_); - - this.workspace_.renameVariable = - this.targetWorkspace_.renameVariable.bind(this.targetWorkspace_); - - this.workspace_.renameVariableById = - this.targetWorkspace_.renameVariableById.bind(this.targetWorkspace_); - - this.workspace_.getVariableTypes = - this.targetWorkspace_.getVariableTypes.bind(this.targetWorkspace_); + this.workspace_.variableMap_ = this.targetWorkspace_.getVariableMap(); }; /** diff --git a/core/variable_map.js b/core/variable_map.js index 0995d4fdd..40f150b20 100644 --- a/core/variable_map.js +++ b/core/variable_map.js @@ -58,6 +58,8 @@ Blockly.VariableMap.prototype.clear = function() { this.variableMap_ = new Object(null); }; +/* Begin functions for renaming variables. */ + /** * Rename the given variable by updating its name in the variable map. * @param {!Blockly.VariableModel} variable Variable to rename. @@ -78,6 +80,21 @@ Blockly.VariableMap.prototype.renameVariable = function(variable, newName) { Blockly.Events.setGroup(false); }; +/** + * Rename a variable by updating its name in the variable map. Identify the + * variable to rename with the given ID. + * @param {string} id ID of the variable to rename. + * @param {string} newName New variable name. + */ +Blockly.VariableMap.prototype.renameVariableById = function(id, newName) { + var variable = this.getVariableById(id); + if (!variable) { + throw new Error('Tried to rename a variable that didn\'t exist. ID: ' + id); + } + + this.renameVariable(variable, newName); +}; + /** * Update the name of the given variable and refresh all references to it. * The new name must not conflict with any existing variable names. @@ -134,6 +151,8 @@ Blockly.VariableMap.prototype.renameVariableWithConflict_ = function(variable, }; +/* End functions for renaming variabless. */ + /** * Create a variable with a given name, optional type, and optional ID. * @param {string} name The name of the variable. This must be unique across @@ -174,6 +193,8 @@ Blockly.VariableMap.prototype.createVariable = function(name, return variable; }; +/* Begin functions for variable deletion. */ + /** * Delete a variable. * @param {!Blockly.VariableModel} variable Variable to delete. @@ -189,6 +210,69 @@ Blockly.VariableMap.prototype.deleteVariable = function(variable) { } }; +/** + * Delete a variables by the passed in ID and all of its uses from this + * workspace. May prompt the user for confirmation. + * @param {string} id ID of variable to delete. + */ +Blockly.VariableMap.prototype.deleteVariableById = function(id) { + var variable = this.getVariableById(id); + if (variable) { + // Check whether this variable is a function parameter before deleting. + var variableName = variable.name; + var uses = this.getVariableUsesById(id); + for (var i = 0, block; block = uses[i]; i++) { + if (block.type == 'procedures_defnoreturn' || + block.type == 'procedures_defreturn') { + var procedureName = block.getFieldValue('NAME'); + var deleteText = Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE. + replace('%1', variableName). + replace('%2', procedureName); + Blockly.alert(deleteText); + return; + } + } + + var map = this; + if (uses.length > 1) { + // Confirm before deleting multiple blocks. + var confirmText = Blockly.Msg.DELETE_VARIABLE_CONFIRMATION. + replace('%1', String(uses.length)). + replace('%2', variableName); + Blockly.confirm(confirmText, + function(ok) { + if (ok) { + map.deleteVariableInternal_(variable, uses); + } + }); + } else { + // No confirmation necessary for a single block. + map.deleteVariableInternal_(variable, uses); + } + } else { + console.warn("Can't delete non-existent variable: " + id); + } +}; + +/** + * Deletes a variable and all of its uses from this workspace without asking the + * user for confirmation. + * @param {!Blockly.VariableModel} variable Variable to delete. + * @param {!Array.} uses An array of uses of the variable. + * @private + */ +Blockly.VariableMap.prototype.deleteVariableInternal_ = function(variable, + uses) { + Blockly.Events.setGroup(true); + for (var i = 0; i < uses.length; i++) { + uses[i].dispose(true, false); + } + this.deleteVariable(variable); + Blockly.Events.setGroup(false); +}; + +/* End functions for variable deletion. */ + /** * Find the variable by the given name and type and return it. Return null if * it is not found. @@ -276,3 +360,25 @@ Blockly.VariableMap.prototype.getAllVariables = function() { } return all_variables; }; + +/** + * Find all the uses of a named variable. + * @param {string} id ID of the variable to find. + * @return {!Array.} Array of block usages. + */ +Blockly.VariableMap.prototype.getVariableUsesById = function(id) { + var uses = []; + var blocks = this.workspace.getAllBlocks(); + // Iterate through every block and check the name. + for (var i = 0; i < blocks.length; i++) { + var blockVariables = blocks[i].getVarModels(); + if (blockVariables) { + for (var j = 0; j < blockVariables.length; j++) { + if (blockVariables[j].getId() == id) { + uses.push(blocks[i]); + } + } + } + } + return uses; +}; diff --git a/core/workspace.js b/core/workspace.js index 6505560ce..29dfb860d 100644 --- a/core/workspace.js +++ b/core/workspace.js @@ -212,6 +212,7 @@ Blockly.Workspace.prototype.clear = function() { this.potentialVariableMap_.clear(); }; +/* Begin functions that are just pass-throughs to the variable map. */ /** * Rename a variable by updating its name in the variable map. Identify the * variable to rename with the given ID. @@ -219,12 +220,7 @@ Blockly.Workspace.prototype.clear = function() { * @param {string} newName New variable name. */ Blockly.Workspace.prototype.renameVariableById = function(id, newName) { - var variable = this.getVariableById(id); - if (!variable) { - throw new Error('Tried to rename a variable that didn\'t exist. ID: ' + id); - } - - this.variableMap_.renameVariable(variable, newName); + this.variableMap_.renameVariableById(id, newName); }; /** @@ -248,20 +244,7 @@ Blockly.Workspace.prototype.createVariable = function(name, opt_type, opt_id) { * @return {!Array.} Array of block usages. */ Blockly.Workspace.prototype.getVariableUsesById = function(id) { - var uses = []; - var blocks = this.getAllBlocks(); - // Iterate through every block and check the name. - for (var i = 0; i < blocks.length; i++) { - var blockVariables = blocks[i].getVarModels(); - if (blockVariables) { - for (var j = 0; j < blockVariables.length; j++) { - if (blockVariables[j].getId() == id) { - uses.push(blocks[i]); - } - } - } - } - return uses; + return this.variableMap_.getVariableUsesById(id); }; /** @@ -270,42 +253,7 @@ Blockly.Workspace.prototype.getVariableUsesById = function(id) { * @param {string} id ID of variable to delete. */ Blockly.Workspace.prototype.deleteVariableById = function(id) { - var variable = this.getVariableById(id); - if (variable) { - // Check whether this variable is a function parameter before deleting. - var variableName = variable.name; - var uses = this.getVariableUsesById(id); - for (var i = 0, block; block = uses[i]; i++) { - if (block.type == 'procedures_defnoreturn' || - block.type == 'procedures_defreturn') { - var procedureName = block.getFieldValue('NAME'); - var deleteText = Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE. - replace('%1', variableName). - replace('%2', procedureName); - Blockly.alert(deleteText); - return; - } - } - - var workspace = this; - if (uses.length > 1) { - // Confirm before deleting multiple blocks. - var confirmText = Blockly.Msg.DELETE_VARIABLE_CONFIRMATION. - replace('%1', String(uses.length)). - replace('%2', variableName); - Blockly.confirm(confirmText, - function(ok) { - if (ok) { - workspace.deleteVariableInternal_(variable, uses); - } - }); - } else { - // No confirmation necessary for a single block. - this.deleteVariableInternal_(variable, uses); - } - } else { - console.warn("Can't delete non-existent variable: " + id); - } + this.variableMap_.deleteVariableById(id); }; /** @@ -316,12 +264,7 @@ Blockly.Workspace.prototype.deleteVariableById = function(id) { * @private */ Blockly.Workspace.prototype.deleteVariableInternal_ = function(variable, uses) { - Blockly.Events.setGroup(true); - for (var i = 0; i < uses.length; i++) { - uses[i].dispose(true, false); - } - this.variableMap_.deleteVariable(variable); - Blockly.Events.setGroup(false); + this.variableMap_.deleteVariableInternal_(variable, uses); }; /** @@ -364,6 +307,35 @@ Blockly.Workspace.prototype.getVariableById = function(id) { return this.variableMap_.getVariableById(id); }; +/** + * Find the variable with the specified type. If type is null, return list of + * variables with empty string type. + * @param {?string} type Type of the variables to find. + * @return {Array.} The sought after variables of the + * passed in type. An empty array if none are found. + */ +Blockly.Workspace.prototype.getVariablesOfType = function(type) { + return this.variableMap_.getVariablesOfType(type); +}; + +/** + * Return all variable types. + * @return {!Array.} List of variable types. + */ +Blockly.Workspace.prototype.getVariableTypes = function() { + return this.variableMap_.getVariableTypes(); +}; + +/** + * Return all variables of all types. + * @return {!Array.} List of variable models. + */ +Blockly.Workspace.prototype.getAllVariables = function() { + return this.variableMap_.getAllVariables(); +}; + +/* End functions that are just pass-throughs to the variable map. */ + /** * Returns the horizontal offset of the workspace. * Intended for LTR/RTL compatibility in XML. @@ -502,33 +474,6 @@ Blockly.Workspace.prototype.allInputsFilled = function(opt_shadowBlocksAreFilled return true; }; -/** - * Find the variable with the specified type. If type is null, return list of - * variables with empty string type. - * @param {?string} type Type of the variables to find. - * @return {Array.} The sought after variables of the - * passed in type. An empty array if none are found. - */ -Blockly.Workspace.prototype.getVariablesOfType = function(type) { - return this.variableMap_.getVariablesOfType(type); -}; - -/** - * Return all variable types. - * @return {!Array.} List of variable types. - */ -Blockly.Workspace.prototype.getVariableTypes = function() { - return this.variableMap_.getVariableTypes(); -}; - -/** - * Return all variables of all types. - * @return {!Array.} List of variable models. - */ -Blockly.Workspace.prototype.getAllVariables = function() { - return this.variableMap_.getAllVariables(); -}; - /** * Return the variable map that contains "potential" variables. These exist in * the flyout but not in the workspace.