mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-28 22:10:31 -04:00
Allow for local variables by passing in extra scope information (provided by the gui). This information is included in the varCreate event. Pass in a list of additional var names to check against when creating a variable (e.g. local var names from all sprites when checking for name conflicts to create a global var.
This commit is contained in:
parent
0d7ca1823f
commit
c23fe53344
6 changed files with 40 additions and 17 deletions
|
@ -88,6 +88,7 @@ Blockly.Events.VarCreate = function(variable) {
|
|||
Blockly.Events.VarCreate.superClass_.constructor.call(this, variable);
|
||||
this.varType = variable.type;
|
||||
this.varName = variable.name;
|
||||
this.isLocal = variable.isLocal;
|
||||
};
|
||||
goog.inherits(Blockly.Events.VarCreate, Blockly.Events.VarBase);
|
||||
|
||||
|
@ -105,6 +106,7 @@ Blockly.Events.VarCreate.prototype.toJson = function() {
|
|||
var json = Blockly.Events.VarCreate.superClass_.toJson.call(this);
|
||||
json['varType'] = this.varType;
|
||||
json['varName'] = this.varName;
|
||||
json['isLocal'] = this.isLocal;
|
||||
return json;
|
||||
};
|
||||
|
||||
|
@ -116,6 +118,7 @@ Blockly.Events.VarCreate.prototype.fromJson = function(json) {
|
|||
Blockly.Events.VarCreate.superClass_.fromJson.call(this, json);
|
||||
this.varType = json['varType'];
|
||||
this.varName = json['varName'];
|
||||
this.isLocal = json['isLocal'];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -125,7 +128,7 @@ Blockly.Events.VarCreate.prototype.fromJson = function(json) {
|
|||
Blockly.Events.VarCreate.prototype.run = function(forward) {
|
||||
var workspace = this.getEventWorkspace_();
|
||||
if (forward) {
|
||||
workspace.createVariable(this.varName, this.varType, this.varId);
|
||||
workspace.createVariable(this.varName, this.varType, this.varId, this.isLocal);
|
||||
} else {
|
||||
workspace.deleteVariableById(this.varId);
|
||||
}
|
||||
|
@ -145,6 +148,7 @@ Blockly.Events.VarDelete = function(variable) {
|
|||
Blockly.Events.VarDelete.superClass_.constructor.call(this, variable);
|
||||
this.varType = variable.type;
|
||||
this.varName = variable.name;
|
||||
this.isLocal = variable.isLocal;
|
||||
};
|
||||
goog.inherits(Blockly.Events.VarDelete, Blockly.Events.VarBase);
|
||||
|
||||
|
@ -162,6 +166,7 @@ Blockly.Events.VarDelete.prototype.toJson = function() {
|
|||
var json = Blockly.Events.VarDelete.superClass_.toJson.call(this);
|
||||
json['varType'] = this.varType;
|
||||
json['varName'] = this.varName;
|
||||
json['isLocal'] = this.isLocal;
|
||||
return json;
|
||||
};
|
||||
|
||||
|
@ -173,6 +178,7 @@ Blockly.Events.VarDelete.prototype.fromJson = function(json) {
|
|||
Blockly.Events.VarDelete.superClass_.fromJson.call(this, json);
|
||||
this.varType = json['varType'];
|
||||
this.varName = json['varName'];
|
||||
this.isLocal = json['isLocal'];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -184,7 +190,7 @@ Blockly.Events.VarDelete.prototype.run = function(forward) {
|
|||
if (forward) {
|
||||
workspace.deleteVariableById(this.varId);
|
||||
} else {
|
||||
workspace.createVariable(this.varName, this.varType, this.varId);
|
||||
workspace.createVariable(this.varName, this.varType, this.varId, this.isLocal);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -174,10 +174,11 @@ Blockly.VariableMap.prototype.renameVariableWithConflict_ = function(variable,
|
|||
* their type. This will default to '' which is a specific type.
|
||||
* @param {string=} opt_id The unique ID of the variable. This will default to
|
||||
* a UUID.
|
||||
* @param {boolean=} opt_isLocal Whether the variable is locally scoped.
|
||||
* @return {?Blockly.VariableModel} The newly created variable.
|
||||
*/
|
||||
Blockly.VariableMap.prototype.createVariable = function(name,
|
||||
opt_type, opt_id) {
|
||||
opt_type, opt_id, opt_isLocal) {
|
||||
var variable = this.getVariable(name, opt_type);
|
||||
if (variable) {
|
||||
if (opt_id && variable.getId() != opt_id) {
|
||||
|
@ -194,7 +195,8 @@ Blockly.VariableMap.prototype.createVariable = function(name,
|
|||
opt_id = opt_id || Blockly.utils.genUid();
|
||||
opt_type = opt_type || '';
|
||||
|
||||
variable = new Blockly.VariableModel(this.workspace, name, opt_type, opt_id);
|
||||
variable = new Blockly.VariableModel(this.workspace, name, opt_type, opt_id,
|
||||
opt_isLocal);
|
||||
// If opt_type is not a key, create a new list.
|
||||
if (!this.variableMap_[opt_type]) {
|
||||
this.variableMap_[opt_type] = [variable];
|
||||
|
|
|
@ -42,10 +42,11 @@ goog.require('goog.string');
|
|||
* their type. This will default to '' which is a specific type.
|
||||
* @param {string=} opt_id The unique ID of the variable. This will default to
|
||||
* a UUID.
|
||||
* @param {boolean=} opt_isLocal Whether the variable is locally scoped.
|
||||
* @see {Blockly.FieldVariable}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.VariableModel = function(workspace, name, opt_type, opt_id) {
|
||||
Blockly.VariableModel = function(workspace, name, opt_type, opt_id, opt_isLocal) {
|
||||
/**
|
||||
* The workspace the variable is in.
|
||||
* @type {!Blockly.Workspace}
|
||||
|
@ -78,6 +79,12 @@ Blockly.VariableModel = function(workspace, name, opt_type, opt_id) {
|
|||
*/
|
||||
this.id_ = opt_id || Blockly.utils.genUid();
|
||||
|
||||
/**
|
||||
* Whether this variable is locally scoped.
|
||||
* @package
|
||||
*/
|
||||
this.isLocal = opt_isLocal || false;
|
||||
|
||||
Blockly.Events.fire(new Blockly.Events.VarCreate(this));
|
||||
};
|
||||
|
||||
|
|
|
@ -289,8 +289,9 @@ Blockly.Variables.createVariable = function(workspace, opt_callback, opt_type) {
|
|||
|
||||
// Prompt the user to enter a name for the variable
|
||||
Blockly.prompt(newMsg, '',
|
||||
function(text) {
|
||||
var validatedText = validate(text, workspace, opt_callback);
|
||||
function(text, scope, additionalVars) {
|
||||
var isLocal = (scope === 'local') || false;
|
||||
var validatedText = validate(text, workspace, additionalVars, opt_callback);
|
||||
if (validatedText) {
|
||||
// The name is valid according to the type, create the variable
|
||||
var potentialVarMap = workspace.getPotentialVariableMap();
|
||||
|
@ -305,7 +306,7 @@ Blockly.Variables.createVariable = function(workspace, opt_callback, opt_type) {
|
|||
opt_type, workspace, false);
|
||||
}
|
||||
if (!variable) {
|
||||
variable = workspace.createVariable(validatedText, opt_type);
|
||||
variable = workspace.createVariable(validatedText, opt_type, null, isLocal);
|
||||
}
|
||||
|
||||
var flyout = workspace.isFlyout ? workspace : workspace.getFlyout();
|
||||
|
@ -338,6 +339,8 @@ Blockly.Variables.createVariable = function(workspace, opt_callback, opt_type) {
|
|||
* @param {!Blockly.Workspace} workspace The workspace on which to validate the
|
||||
* variable name. This is the workspace used to check whether the variable
|
||||
* already exists.
|
||||
* @param {Array<string>} additionalVars A list of additional var names to check
|
||||
* for conflicts against.
|
||||
* @param {function(?string=)=} opt_callback An optional function to be called on
|
||||
* a pre-existing variable of the user-provided name. This function is currently
|
||||
* only used for broadcast messages.
|
||||
|
@ -347,7 +350,7 @@ Blockly.Variables.createVariable = function(workspace, opt_callback, opt_type) {
|
|||
* proceed with creating or renaming the variable.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Variables.nameValidator_ = function(type, text, workspace, opt_callback) {
|
||||
Blockly.Variables.nameValidator_ = function(type, text, workspace, additionalVars, opt_callback) {
|
||||
// The validators for the different variable types require slightly different arguments.
|
||||
// For broadcast messages, if a broadcast message of the provided name already exists,
|
||||
// the validator needs to call a function that updates the selected
|
||||
|
@ -359,10 +362,10 @@ Blockly.Variables.nameValidator_ = function(type, text, workspace, opt_callback)
|
|||
if (type == Blockly.BROADCAST_MESSAGE_VARIABLE_TYPE) {
|
||||
return Blockly.Variables.validateBroadcastMessageName_(text, workspace, opt_callback);
|
||||
} else if (type == Blockly.LIST_VARIABLE_TYPE) {
|
||||
return Blockly.Variables.validateScalarVarOrListName_(text, workspace, type,
|
||||
return Blockly.Variables.validateScalarVarOrListName_(text, workspace, additionalVars, type,
|
||||
Blockly.Msg.LIST_ALREADY_EXISTS);
|
||||
} else {
|
||||
return Blockly.Variables.validateScalarVarOrListName_(text, workspace, type,
|
||||
return Blockly.Variables.validateScalarVarOrListName_(text, workspace, additionalVars, type,
|
||||
Blockly.Msg.VARIABLE_ALREADY_EXISTS);
|
||||
}
|
||||
};
|
||||
|
@ -407,6 +410,8 @@ Blockly.Variables.validateBroadcastMessageName_ = function(name, workspace, opt_
|
|||
* @param {string} name The name to validate
|
||||
* @param {!Blockly.Workspace} workspace The workspace the name should be validated
|
||||
* against.
|
||||
* @param {Array<string>} additionalVars A list of additional variable names to check
|
||||
* for conflicts against.
|
||||
* @param {string} type The type to validate the variable as. This should be one of
|
||||
* Blockly.SCALAR_VARIABLE_TYPE or Blockly.LIST_VARIABLE_TYPE.
|
||||
* @param {string} errorMsg The type-specific error message the user should see
|
||||
|
@ -414,14 +419,14 @@ Blockly.Variables.validateBroadcastMessageName_ = function(name, workspace, opt_
|
|||
* @return {string} The validated name, or null if invalid.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Variables.validateScalarVarOrListName_ = function(name, workspace,
|
||||
Blockly.Variables.validateScalarVarOrListName_ = function(name, workspace, additionalVars,
|
||||
type, errorMsg) {
|
||||
// For scalar variables, we don't want leading or trailing white space
|
||||
name = Blockly.Variables.trimName_(name);
|
||||
if (!name) {
|
||||
return null;
|
||||
}
|
||||
if (workspace.getVariable(name, type)) {
|
||||
if (workspace.getVariable(name, type) || additionalVars.indexOf(name) >= 0) {
|
||||
// error
|
||||
Blockly.alert(errorMsg.replace('%1', name));
|
||||
return null;
|
||||
|
|
|
@ -340,10 +340,11 @@ Blockly.Workspace.prototype.renameVariableById = function(id, newName) {
|
|||
* their type. This will default to '' which is a specific type.
|
||||
* @param {string=} opt_id The unique ID of the variable. This will default to
|
||||
* a UUID.
|
||||
* @param {boolean=} opt_isLocal Whether the variable to create is locally scoped.
|
||||
* @return {?Blockly.VariableModel} The newly created variable.
|
||||
*/
|
||||
Blockly.Workspace.prototype.createVariable = function(name, opt_type, opt_id) {
|
||||
return this.variableMap_.createVariable(name, opt_type, opt_id);
|
||||
Blockly.Workspace.prototype.createVariable = function(name, opt_type, opt_id, opt_isLocal) {
|
||||
return this.variableMap_.createVariable(name, opt_type, opt_id, opt_isLocal);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1142,13 +1142,15 @@ Blockly.WorkspaceSvg.prototype.deleteVariableById = function(id) {
|
|||
* their type. This will default to '' which is a specific type.
|
||||
* @param {string=} opt_id The unique ID of the variable. This will default to
|
||||
* a UUID.
|
||||
* @param {boolean=} opt_isLocal Whether the variable is locally scoped.
|
||||
* @return {?Blockly.VariableModel} The newly created variable.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.createVariable = function(name, opt_type, opt_id) {
|
||||
Blockly.WorkspaceSvg.prototype.createVariable = function(name, opt_type, opt_id,
|
||||
opt_isLocal) {
|
||||
var variableInMap = (this.getVariable(name, opt_type) != null);
|
||||
var newVar = Blockly.WorkspaceSvg.superClass_.createVariable.call(
|
||||
this, name, opt_type, opt_id);
|
||||
this, name, opt_type, opt_id, opt_isLocal);
|
||||
// For performance reasons, only refresh the the toolbox for new variables.
|
||||
// Variables that already exist should already be there.
|
||||
if (!variableInMap && (opt_type != Blockly.BROADCAST_MESSAGE_VARIABLE_TYPE)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue