-
Notifications
You must be signed in to change notification settings - Fork 0
/
variables.js
185 lines (177 loc) · 6.43 KB
/
variables.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/**
* Visual Blocks Language
*
* Copyright 2012 Google Inc.
* http://code.google.com/p/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 Utility functions for handling variables and procedure names.
* Note that variables and procedures share the same name space, meaning that
* one can't have a variable and a procedure of the same name.
* @author fraser@google.com (Neil Fraser)
*/
/**
* Class for a database of variables.
* @param {Array.<string>} reservedWords An array of words that are illegal for
* use as variable names in a language (e.g. ['new', 'if', 'this', ...]).
* @constructor
*/
Blockly.Variables = {};
Blockly.Variables.NAME_TYPE = 'variable';
/**
* Find all user-created variables.
* @param {Blockly.Block} opt_block Optional root block.
* @return {!Array.<string>} Array of variable names.
*/
Blockly.Variables.allVariables = function(opt_block) {
var blocks;
if (opt_block) {
blocks = opt_block.getDescendants();
} else {
blocks = Blockly.mainWorkspace.getAllBlocks();
}
var variableHash = {};
// Iterate through every block and add each variable to the hash.
for (var x = 0; x < blocks.length; x++) {
var func = blocks[x].getVars;
if (func) {
var blockVariables = func.call(blocks[x]);
for (var y = 0; y < blockVariables.length; y++) {
var varName = blockVariables[y];
// Variable name may be null if the block is only half-built.
if (varName) {
variableHash[Blockly.Names.PREFIX_ +
varName.toLowerCase()] = varName;
}
}
}
}
// Flatten the hash into a list.
var variableList = [];
for (var name in variableHash) {
variableList.push(variableHash[name]);
}
return variableList;
};
/**
* 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.
*/
Blockly.Variables.dropdownCreate = function() {
var variableList = Blockly.Variables.allVariables();
// Ensure that the currently selected variable is an option.
var name = this.getText();
if (name && variableList.indexOf(name) == -1) {
variableList.push(name);
}
variableList.sort(Blockly.caseInsensitiveComparator);
variableList.push(Blockly.MSG_RENAME_VARIABLE);
variableList.push(Blockly.MSG_NEW_VARIABLE);
// Variables are not language-specific, use the name as both the user-facing
// text and the internal representation.
var options = [];
for (var x = 0; x < variableList.length; x++) {
options[x] = [variableList[x], variableList[x]];
}
return options;
};
/**
* 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.
* @param {string} text The selected dropdown menu option.
*/
Blockly.Variables.dropdownChange = function(text) {
function promptName(promptText, defaultText) {
Blockly.hideChaff();
var newVar = window.prompt(promptText, defaultText);
// Strip leading and trailing whitespace. Beyond this, all names are legal.
return newVar && newVar.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
}
if (text == Blockly.MSG_RENAME_VARIABLE) {
var oldVar = this.getText();
text = promptName(Blockly.MSG_RENAME_VARIABLE_TITLE.replace('%1', oldVar),
oldVar);
if (text) {
Blockly.Variables.renameVariable(oldVar, text);
}
} 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.
Blockly.Variables.renameVariable(text, text);
}
if (text) {
this.setText(text);
}
}
};
/**
* Find all instances of the specified variable and rename them.
* @param {string} oldName Variable to rename.
* @param {string} newName New variable name.
*/
Blockly.Variables.renameVariable = function(oldName, newName) {
var blocks = Blockly.mainWorkspace.getAllBlocks();
// Iterate through every block.
for (var x = 0; x < blocks.length; x++) {
var func = blocks[x].renameVar;
if (func) {
func.call(blocks[x], oldName, newName);
}
}
};
/**
* Construct the blocks required by the flyout for the variable category.
* @param {!Array.<!Blockly.Block>} blocks List of blocks to show.
* @param {!Array.<number>} gaps List of widths between blocks.
* @param {number} margin Standard margin width for calculating gaps.
* @param {!Blockly.Workspace} workspace The flyout's workspace.
*/
Blockly.Variables.flyoutCategory = function(blocks, gaps, margin, workspace) {
var variableList = Blockly.Variables.allVariables();
variableList.sort(Blockly.caseInsensitiveComparator);
// In addition to the user's variables, we also want to display the default
// variable name at the top. We also don't want this duplicated if the
// user has created a variable of the same name.
variableList.unshift(null);
var defaultVariable = undefined;
for (var i = 0; i < variableList.length; i++) {
if (variableList[i] === defaultVariable) {
continue;
}
var getBlock = Blockly.Language.variables_get ?
new Blockly.Block(workspace, 'variables_get') : null;
getBlock && getBlock.initSvg();
var setBlock = Blockly.Language.variables_set ?
new Blockly.Block(workspace, 'variables_set') : null;
setBlock && setBlock.initSvg();
if (variableList[i] === null) {
defaultVariable = (getBlock || setBlock).getVars()[0];
} else {
getBlock && getBlock.setTitleText(variableList[i], 'VAR');
setBlock && setBlock.setTitleText(variableList[i], 'VAR');
}
setBlock && blocks.push(setBlock);
getBlock && blocks.push(getBlock);
if (getBlock && setBlock) {
gaps.push(margin, margin * 3);
} else {
gaps.push(margin * 2);
}
}
};