mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-06-26 20:20:23 -04:00
195 lines
6.3 KiB
JavaScript
195 lines
6.3 KiB
JavaScript
/**
|
|
* @license
|
|
* Visual Blocks Editor
|
|
*
|
|
* Copyright 2012 Google Inc.
|
|
* https://developers.google.com/blockly/
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview Variable input field.
|
|
* @author fraser@google.com (Neil Fraser)
|
|
*/
|
|
'use strict';
|
|
|
|
goog.provide('Blockly.FieldVariable');
|
|
|
|
goog.require('Blockly.FieldDropdown');
|
|
goog.require('Blockly.Msg');
|
|
goog.require('Blockly.Variables');
|
|
goog.require('goog.asserts');
|
|
goog.require('goog.string');
|
|
|
|
|
|
/**
|
|
* Class for a variable's dropdown field.
|
|
* @param {?string} varname The default name for the variable. If null,
|
|
* a unique variable name will be generated.
|
|
* @param {Function=} opt_validator A function that is executed when a new
|
|
* option is selected. Its sole argument is the new option value.
|
|
* @extends {Blockly.FieldDropdown}
|
|
* @constructor
|
|
*/
|
|
Blockly.FieldVariable = function(varname, opt_validator) {
|
|
Blockly.FieldVariable.superClass_.constructor.call(this,
|
|
Blockly.FieldVariable.dropdownCreate, opt_validator);
|
|
this.setValue(varname || '');
|
|
};
|
|
goog.inherits(Blockly.FieldVariable, Blockly.FieldDropdown);
|
|
|
|
/**
|
|
* The menu item index for the rename variable option.
|
|
* @type {number}
|
|
*/
|
|
Blockly.FieldVariable.prototype.renameVarItemIndex_ = -1;
|
|
|
|
/**
|
|
* The menu item index for the delete variable option.
|
|
* @type {number}
|
|
*/
|
|
Blockly.FieldVariable.prototype.deleteVarItemIndex_ = -1;
|
|
|
|
|
|
/**
|
|
* Install this dropdown on a block.
|
|
*/
|
|
Blockly.FieldVariable.prototype.init = function() {
|
|
if (this.fieldGroup_) {
|
|
// Dropdown has already been initialized once.
|
|
return;
|
|
}
|
|
Blockly.FieldVariable.superClass_.init.call(this);
|
|
if (!this.getValue()) {
|
|
// Variables without names get uniquely named for this workspace.
|
|
var workspace =
|
|
this.sourceBlock_.isInFlyout ?
|
|
this.sourceBlock_.workspace.targetWorkspace :
|
|
this.sourceBlock_.workspace;
|
|
this.setValue(Blockly.Variables.generateUniqueName(workspace));
|
|
}
|
|
// If the selected variable doesn't exist yet, create it.
|
|
// For instance, some blocks in the toolbox have variable dropdowns filled
|
|
// in by default.
|
|
if (!this.sourceBlock_.isInFlyout) {
|
|
this.sourceBlock_.workspace.createVariable(this.getValue());
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Attach this field to a block.
|
|
* @param {!Blockly.Block} block The block containing this field.
|
|
*/
|
|
Blockly.FieldVariable.prototype.setSourceBlock = function(block) {
|
|
goog.asserts.assert(!block.isShadow(),
|
|
'Variable fields are not allowed to exist on shadow blocks.');
|
|
Blockly.FieldVariable.superClass_.setSourceBlock.call(this, block);
|
|
};
|
|
|
|
/**
|
|
* Get the variable's name (use a variableDB to convert into a real name).
|
|
* Unline a regular dropdown, variables are literal and have no neutral value.
|
|
* @return {string} Current text.
|
|
*/
|
|
Blockly.FieldVariable.prototype.getValue = function() {
|
|
return this.getText();
|
|
};
|
|
|
|
/**
|
|
* Set the variable name.
|
|
* @param {string} newValue New text.
|
|
*/
|
|
Blockly.FieldVariable.prototype.setValue = function(newValue) {
|
|
if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
|
|
Blockly.Events.fire(new Blockly.Events.Change(
|
|
this.sourceBlock_, 'field', this.name, this.value_, newValue));
|
|
}
|
|
this.value_ = newValue;
|
|
this.setText(newValue);
|
|
};
|
|
|
|
/**
|
|
* Return a sorted list of variable names for variable dropdown menus.
|
|
* Include a special option at the end for creating a new variable name.
|
|
* @return {!Array.<string>} Array of variable names.
|
|
* @this {!Blockly.FieldVariable}
|
|
*/
|
|
Blockly.FieldVariable.dropdownCreate = function() {
|
|
if (this.sourceBlock_ && this.sourceBlock_.workspace) {
|
|
// Get a copy of the list, so that adding rename and new variable options
|
|
// doesn't modify the workspace's list.
|
|
var variableList = this.sourceBlock_.workspace.variableList.slice(0);
|
|
} else {
|
|
var variableList = [];
|
|
}
|
|
// Ensure that the currently selected variable is an option.
|
|
var name = this.getText();
|
|
if (name && variableList.indexOf(name) == -1) {
|
|
variableList.push(name);
|
|
}
|
|
variableList.sort(goog.string.caseInsensitiveCompare);
|
|
|
|
this.renameVarItemIndex_ = variableList.length;
|
|
variableList.push(Blockly.Msg.RENAME_VARIABLE);
|
|
|
|
this.deleteVarItemIndex_ = variableList.length;
|
|
variableList.push(Blockly.Msg.DELETE_VARIABLE.replace('%1', name));
|
|
// Variables are not language-specific, use the name as both the user-facing
|
|
// text and the internal representation.
|
|
var options = [];
|
|
for (var i = 0; i < variableList.length; i++) {
|
|
options[i] = [variableList[i], variableList[i]];
|
|
}
|
|
return options;
|
|
};
|
|
|
|
/**
|
|
* Handle the selection of an item in the variable dropdown menu.
|
|
* Special case the 'Rename variable...' and 'Delete variable...' options.
|
|
* In the rename case, prompt the user for a new name.
|
|
* @param {!goog.ui.Menu} menu The Menu component clicked.
|
|
* @param {!goog.ui.MenuItem} menuItem The MenuItem selected within menu.
|
|
*/
|
|
Blockly.FieldVariable.prototype.onItemSelected = function(menu, menuItem) {
|
|
var menuLength = menu.getChildCount();
|
|
var itemText = menuItem.getValue();
|
|
if (this.sourceBlock_) {
|
|
var workspace = this.sourceBlock_.workspace;
|
|
if (this.renameVarItemIndex_ >= 0 &&
|
|
menu.getChildAt(this.renameVarItemIndex_) === menuItem) {
|
|
// Rename variable.
|
|
var oldName = this.getText();
|
|
Blockly.hideChaff();
|
|
Blockly.Variables.promptName(
|
|
Blockly.Msg.RENAME_VARIABLE_TITLE.replace('%1', oldName), oldName,
|
|
function(newName) {
|
|
if (newName) {
|
|
workspace.renameVariable(oldName, newName);
|
|
}
|
|
});
|
|
return;
|
|
} else if (this.deleteVarItemIndex_ >= 0 &&
|
|
menu.getChildAt(this.deleteVarItemIndex_) === menuItem) {
|
|
// Delete variable.
|
|
workspace.deleteVariable(this.getText());
|
|
return;
|
|
}
|
|
|
|
// Call any validation function, and allow it to override.
|
|
itemText = this.callValidator(itemText);
|
|
}
|
|
if (itemText !== null) {
|
|
this.setValue(itemText);
|
|
}
|
|
};
|