diff --git a/core/field_variable.js b/core/field_variable.js
index 2f48e627d..0221f2937 100644
--- a/core/field_variable.js
+++ b/core/field_variable.js
@@ -110,7 +110,6 @@ Blockly.FieldVariable.dropdownCreate = function() {
}
variableList.sort(goog.string.caseInsensitiveCompare);
variableList.push(Blockly.Msg.RENAME_VARIABLE);
- variableList.push(Blockly.Msg.NEW_VARIABLE);
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.
@@ -123,8 +122,8 @@ Blockly.FieldVariable.dropdownCreate = function() {
/**
* Event handler for a change in variable name.
- * Special case the 'New variable...' and 'Rename variable...' options.
- * In both of these special cases, prompt the user for a new name.
+ * Special case the 'Rename variable...' and 'Delete variable...' options.
+ * In the rename case, prompt the user for a new name.
* @param {string} text The selected dropdown menu option.
* @return {null|undefined|string} An acceptable new variable name, or null if
* change is to be either aborted (cancel button) or has been already
@@ -132,40 +131,17 @@ Blockly.FieldVariable.dropdownCreate = function() {
* @this {!Blockly.FieldVariable}
*/
Blockly.FieldVariable.classValidator = function(text) {
- function promptName(promptText, defaultText) {
- Blockly.hideChaff();
- var newVar = window.prompt(promptText, defaultText);
- // Merge runs of whitespace. Strip leading and trailing whitespace.
- // Beyond this, all names are legal.
- if (newVar) {
- newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
- if (newVar == Blockly.Msg.RENAME_VARIABLE ||
- newVar == Blockly.Msg.NEW_VARIABLE) {
- // Ok, not ALL names are legal...
- newVar = null;
- }
- }
- return newVar;
- }
var workspace = this.sourceBlock_.workspace;
if (text == Blockly.Msg.RENAME_VARIABLE) {
var oldVar = this.getText();
- text = promptName(Blockly.Msg.RENAME_VARIABLE_TITLE.replace('%1', oldVar),
- oldVar);
+ Blockly.hideChaff();
+ text = Blockly.Variables.promptName(
+ Blockly.Msg.RENAME_VARIABLE_TITLE.replace('%1', oldVar), oldVar);
if (text) {
Blockly.Variables.renameVariable(oldVar, text, workspace);
}
return null;
- } else if (text == Blockly.Msg.NEW_VARIABLE) {
- text = promptName(Blockly.Msg.NEW_VARIABLE_TITLE, '');
- // Since variables are case-insensitive, ensure that if the new variable
- // matches with an existing variable, the new case prevails throughout.
- if (text) {
- Blockly.Variables.renameVariable(text, text, workspace);
- return text;
- }
- return null;
- } else if (text == Blockly.Msg.DELETE_VARIABLE.replace('%1', this.getText())) {
+ }else if (text == Blockly.Msg.DELETE_VARIABLE.replace('%1', this.getText())) {
Blockly.Variables.delete(this.getText(), this.sourceBlock_.workspace);
return null;
}
diff --git a/core/flyout.js b/core/flyout.js
index e13bc48de..942b0be38 100644
--- a/core/flyout.js
+++ b/core/flyout.js
@@ -608,7 +608,8 @@ Blockly.Flyout.prototype.show = function(xmlList) {
}
else if (tagName == 'BUTTON') {
var label = xml.getAttribute('text');
- var curButton = new Blockly.FlyoutButton(this.workspace_, label);
+ var curButton = new Blockly.FlyoutButton(this.workspace_,
+ this.targetWorkspace_, label);
contents.push({type: 'button', button: curButton});
gaps.push(this.MARGIN);
}
diff --git a/core/flyout_button.js b/core/flyout_button.js
index 77d18f426..cd251897e 100644
--- a/core/flyout_button.js
+++ b/core/flyout_button.js
@@ -34,16 +34,23 @@ goog.require('goog.math.Coordinate');
* Class for a button in the flyout.
* @param {!Blockly.Workspace} workspace The workspace in which to place this
* button.
+ * @param {!Blockly.Workspace} targetWorkspace The flyout's target workspace.
* @param {string} text The text to display on the button.
* @constructor
*/
-Blockly.FlyoutButton = function(workspace, text) {
+Blockly.FlyoutButton = function(workspace, targetWorkspace, text) {
/**
* @type {!Blockly.Workspace}
* @private
*/
this.workspace_ = workspace;
+ /**
+ * @type {!Blockly.Workspace}
+ * @private
+ */
+ this.targetWorkspace_ = targetWorkspace;
+
/**
* @type {string}
* @private
@@ -150,9 +157,10 @@ Blockly.FlyoutButton.prototype.dispose = function() {
* @param {!Event} e Mouse up event.
*/
Blockly.FlyoutButton.prototype.onMouseUp = function(e) {
- console.log("Button was clicked");
// Don't scroll the page.
e.preventDefault();
// Don't propagate mousewheel event (zooming).
e.stopPropagation();
+
+ Blockly.Variables.createVariable(this.targetWorkspace_);
};
diff --git a/core/toolbox.js b/core/toolbox.js
index b5b27f869..3f715ed3a 100644
--- a/core/toolbox.js
+++ b/core/toolbox.js
@@ -420,6 +420,18 @@ Blockly.Toolbox.prototype.getClientRect = function() {
}
};
+/**
+ * Update the flyout's contents without closing it. Should be used in response
+ * to a change in one of the dynamic categories, such as variables or
+ * procedures.
+ */
+Blockly.Toolbox.prototype.refreshSelection = function() {
+ var selectedItem = this.tree_.getSelectedItem();
+ if (selectedItem && selectedItem.blocks) {
+ this.flyout_.show(selectedItem.blocks);
+ }
+};
+
// Extending Closure's Tree UI.
/**
diff --git a/core/variables.js b/core/variables.js
index 37a881791..3bc77f0e3 100644
--- a/core/variables.js
+++ b/core/variables.js
@@ -110,29 +110,31 @@ Blockly.Variables.flyoutCategory = function(workspace) {
var button = goog.dom.createDom('button');
button.setAttribute('text', 'Create variable');
xmlList.push(button);
- for (var i = 0; i < variableList.length; i++) {
- if (Blockly.Blocks['variables_set']) {
- //
- // item
- //
- var block = goog.dom.createDom('block');
- block.setAttribute('type', 'variables_set');
- if (Blockly.Blocks['variables_get']) {
- block.setAttribute('gap', 8);
- }
- var field = goog.dom.createDom('field', null, variableList[i]);
- field.setAttribute('name', 'VAR');
- block.appendChild(field);
- xmlList.push(block);
- }
+
+ if (Blockly.Blocks['variables_set']) {
+ //
+ // item
+ //
+ var block = goog.dom.createDom('block');
+ block.setAttribute('type', 'variables_set');
if (Blockly.Blocks['variables_get']) {
- //
+ block.setAttribute('gap', 20);
+ }
+ var field = goog.dom.createDom('field', null, variableList[0]);
+ field.setAttribute('name', 'VAR');
+ block.appendChild(field);
+ xmlList.push(block);
+ }
+
+ for (var i = 0; i < variableList.length; i++) {
+ if (Blockly.Blocks['variables_get']) {
+ //
// item
//
var block = goog.dom.createDom('block');
block.setAttribute('type', 'variables_get');
if (Blockly.Blocks['variables_set']) {
- block.setAttribute('gap', 24);
+ block.setAttribute('gap', 8);
}
var field = goog.dom.createDom('field', null, variableList[i]);
field.setAttribute('name', 'VAR');
@@ -244,3 +246,44 @@ Blockly.Variables.delete = function(name, workspace) {
Blockly.Variables.disposeUses(name, workspace);
};
+
+/**
+ * Create a new variable on the given workspace.
+ * @param {!Blockly.Workspace} workspace The workspace on which to create the
+ * variable.
+ * @return {null|undefined|string} An acceptable new variable name, or null if
+ * change is to be aborted (cancel button), or undefined if an existing
+ * variable was chosen.
+ */
+Blockly.Variables.createVariable = function(workspace) {
+ var text = Blockly.Variables.promptName(Blockly.Msg.NEW_VARIABLE_TITLE, '');
+ // Since variables are case-insensitive, ensure that if the new variable
+ // matches with an existing variable, the new case prevails throughout.
+ if (text) {
+ workspace.createVariable(text);
+ return text;
+ }
+ return null;
+};
+
+/**
+ * Prompt the user for a new variable name.
+ * @param {string} promptText The string of the prompt.
+ * @param {string} defaultText The default value to show in the prompt's field.
+ * @return {string|null} The new variable name, or null if the user picked
+ * something illegal.
+ */
+Blockly.Variables.promptName = function(promptText, defaultText) {
+ var newVar = window.prompt(promptText, defaultText);
+ // Merge runs of whitespace. Strip leading and trailing whitespace.
+ // Beyond this, all names are legal.
+ if (newVar) {
+ newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
+ if (newVar == Blockly.Msg.RENAME_VARIABLE ||
+ newVar == Blockly.Msg.NEW_VARIABLE) {
+ // Ok, not ALL names are legal...
+ newVar = null;
+ }
+ }
+ return newVar;
+};
diff --git a/core/workspace.js b/core/workspace.js
index 4d4d635d2..6e044fcb4 100644
--- a/core/workspace.js
+++ b/core/workspace.js
@@ -217,20 +217,33 @@ Blockly.Workspace.prototype.updateVariableList = function() {
/**
* Rename a variable by updating its name in the variable list.
+ * TODO: #468
* @param {string} oldName Variable to rename.
* @param {string} newName New variable name.
*/
Blockly.Workspace.prototype.renameVariable = function(oldName, newName) {
// Find the old name in the list and replace it.
var variableIndex = this.variableList.indexOf(oldName);
- if (variableIndex != -1) {
+ var newVariableIndex = this.variableList.indexOf(newName);
+ if (variableIndex != -1 && newVariableIndex == -1) {
this.variableList[variableIndex] = newName;
+ } else if (variableIndex != -1 && newVariableIndex != -1) {
+ this.variableList.splice(variableIndex, 1);
} else {
this.variableList.push(newName);
console.log('Tried to rename an non-existent variable.');
}
};
+/**
+ * Create a variables with the given name.
+ * TODO: #468
+ * @param {string} name The new variable's name.
+ */
+Blockly.Workspace.prototype.createVariable = function(name) {
+ this.variableList.push(name);
+};
+
/**
* Returns the horizontal offset of the workspace.
* Intended for LTR/RTL compatibility in XML.
diff --git a/core/workspace_svg.js b/core/workspace_svg.js
index 6f9be212d..d02243551 100644
--- a/core/workspace_svg.js
+++ b/core/workspace_svg.js
@@ -589,6 +589,19 @@ Blockly.WorkspaceSvg.prototype.paste = function(xmlBlock) {
block.select();
};
+/**
+ * Create a new variable with the given name. Update the flyout to show the new
+ * variable immediately.
+ * TODO: #468
+ * @param {string} name The new variable's name.
+ */
+Blockly.WorkspaceSvg.prototype.createVariable = function(name) {
+ Blockly.WorkspaceSvg.superClass_.createVariable.call(this, name);
+ if (this.toolbox_ && this.toolbox_.flyout_) {
+ this.toolbox_.refreshSelection();
+ }
+};
+
/**
* Make a list of all the delete areas for this workspace.
*/