scratch-blocks 2.0.0-spork.2 → 2.0.0-spork.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +0 -12
- package/package.json +4 -4
- package/src/{block_reporting.js → block_reporting.ts} +7 -5
- package/src/blocks/{colour.js → colour.ts} +6 -6
- package/src/blocks/{control.js → control.ts} +21 -54
- package/src/blocks/{data.js → data.ts} +134 -142
- package/src/blocks/{event.js → event.ts} +12 -33
- package/src/blocks/{looks.js → looks.ts} +24 -73
- package/src/blocks/{math.js → math.ts} +6 -11
- package/src/blocks/{matrix.js → matrix.ts} +2 -3
- package/src/blocks/{motion.js → motion.ts} +23 -70
- package/src/blocks/{note.js → note.ts} +2 -3
- package/src/blocks/{operators.js → operators.ts} +18 -55
- package/src/blocks/{procedures.js → procedures.ts} +418 -269
- package/src/blocks/{sensing.js → sensing.ts} +21 -61
- package/src/blocks/{sound.js → sound.ts} +9 -28
- package/src/blocks/{text.js → text.ts} +1 -2
- package/src/blocks/{vertical_extensions.js → vertical_extensions.ts} +63 -100
- package/src/checkable_continuous_flyout.ts +112 -0
- package/src/{checkbox_bubble.js → checkbox_bubble.ts} +40 -58
- package/src/{colours.js → colours.ts} +11 -4
- package/src/{constants.js → constants.ts} +13 -0
- package/src/{context_menu_items.js → context_menu_items.ts} +18 -12
- package/src/{css.js → css.ts} +13 -7
- package/src/{data_category.js → data_category.ts} +216 -150
- package/src/events/{events_block_comment_base.js → events_block_comment_base.ts} +23 -4
- package/src/events/{events_block_comment_change.js → events_block_comment_change.ts} +29 -5
- package/src/events/{events_block_comment_collapse.js → events_block_comment_collapse.ts} +24 -6
- package/src/events/{events_block_comment_create.js → events_block_comment_create.ts} +36 -10
- package/src/events/{events_block_comment_delete.js → events_block_comment_delete.ts} +6 -2
- package/src/events/{events_block_comment_move.js → events_block_comment_move.ts} +36 -6
- package/src/events/events_block_comment_resize.ts +88 -0
- package/src/events/events_block_drag_end.ts +49 -0
- package/src/events/events_block_drag_outside.ts +44 -0
- package/src/events/{events_scratch_variable_create.js → events_scratch_variable_create.ts} +28 -15
- package/src/fields/{field_colour_slider.js → field_colour_slider.ts} +117 -106
- package/src/fields/{field_matrix.js → field_matrix.ts} +189 -215
- package/src/fields/{field_note.js → field_note.ts} +227 -286
- package/src/fields/{field_textinput_removable.js → field_textinput_removable.ts} +17 -20
- package/src/fields/{field_variable_getter.js → field_variable_getter.ts} +28 -17
- package/src/fields/{field_vertical_separator.js → field_vertical_separator.ts} +14 -30
- package/src/fields/{field_angle.js → scratch_field_angle.ts} +124 -80
- package/src/fields/{field_dropdown.js → scratch_field_dropdown.ts} +9 -7
- package/src/fields/{field_number.js → scratch_field_number.ts} +60 -55
- package/src/fields/{field_variable.js → scratch_field_variable.ts} +46 -27
- package/src/{flyout_checkbox_icon.js → flyout_checkbox_icon.ts} +15 -19
- package/src/{glows.js → glows.ts} +29 -18
- package/src/index.ts +62 -63
- package/src/procedures.ts +462 -0
- package/src/recyclable_block_flyout_inflater.ts +51 -0
- package/src/renderer/{bowler_hat.js → bowler_hat.ts} +1 -1
- package/src/renderer/{constants.js → constants.ts} +26 -12
- package/src/renderer/{drawer.js → drawer.ts} +8 -3
- package/src/renderer/{path_object.js → path_object.ts} +2 -2
- package/src/renderer/{render_info.js → render_info.ts} +19 -7
- package/src/renderer/renderer.ts +76 -0
- package/src/{scratch_block_paster.js → scratch_block_paster.ts} +9 -7
- package/src/scratch_blocks_utils.ts +39 -0
- package/src/{scratch_comment_icon.js → scratch_comment_icon.ts} +43 -26
- package/src/scratch_connection_checker.ts +44 -0
- package/src/{scratch_continuous_category.js → scratch_continuous_category.ts} +20 -13
- package/src/scratch_continuous_toolbox.ts +70 -0
- package/src/{scratch_dragger.js → scratch_dragger.ts} +97 -28
- package/src/{scratch_variable_map.js → scratch_variable_map.ts} +4 -1
- package/src/scratch_variable_model.ts +30 -0
- package/src/{shadows.js → shadows.ts} +8 -4
- package/src/{status_indicator_label.js → status_indicator_label.ts} +24 -36
- package/src/{status_indicator_label_flyout_inflater.js → status_indicator_label_flyout_inflater.ts} +13 -9
- package/src/{variables.js → variables.ts} +153 -123
- package/tsconfig.json +5 -0
- package/src/categories.js +0 -15
- package/src/checkable_continuous_flyout.js +0 -138
- package/src/events/events_block_comment_resize.js +0 -52
- package/src/events/events_block_drag_end.js +0 -33
- package/src/events/events_block_drag_outside.js +0 -30
- package/src/procedures.js +0 -425
- package/src/recyclable_block_flyout_inflater.js +0 -194
- package/src/renderer/renderer.js +0 -74
- package/src/scratch_blocks_utils.js +0 -148
- package/src/scratch_connection_checker.js +0 -29
- package/src/scratch_continuous_toolbox.js +0 -78
- package/src/scratch_variable_model.js +0 -24
- /package/{continuous-toolbox.d.ts → types/continuous-toolbox.d.ts} +0 -0
|
@@ -23,38 +23,78 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import * as Blockly from "blockly/core";
|
|
26
|
-
import { FieldTextInputRemovable } from "../fields/field_textinput_removable
|
|
26
|
+
import { FieldTextInputRemovable } from "../fields/field_textinput_removable";
|
|
27
|
+
import type { ScratchDragger } from "../scratch_dragger";
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/**
|
|
30
|
+
* An object mapping argument IDs to blocks and shadow DOMs.
|
|
31
|
+
*/
|
|
32
|
+
type ConnectionMap = {
|
|
33
|
+
[key: string]: {
|
|
34
|
+
shadow: Element;
|
|
35
|
+
block: Blockly.BlockSvg;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Possible types for procedure arguments.
|
|
41
|
+
*/
|
|
42
|
+
enum ArgumentType {
|
|
43
|
+
STRING = "s",
|
|
44
|
+
NUMBER = "n",
|
|
45
|
+
BOOLEAN = "b",
|
|
46
|
+
}
|
|
32
47
|
|
|
33
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Class representing a draggable block that copies itself on drag.
|
|
50
|
+
*/
|
|
51
|
+
class DuplicateOnDragDraggable implements Blockly.IDraggable {
|
|
52
|
+
/**
|
|
53
|
+
* The newly-created duplicate block.
|
|
54
|
+
*/
|
|
55
|
+
private copy?: Blockly.BlockSvg;
|
|
56
|
+
constructor(private block: Blockly.BlockSvg) {}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Returns whether or not this draggable is movable. */
|
|
60
|
+
isMovable(): boolean {
|
|
34
61
|
return true;
|
|
35
62
|
}
|
|
36
63
|
|
|
37
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Handles the start of a drag.
|
|
66
|
+
*
|
|
67
|
+
* @param e The event that triggered the drag.
|
|
68
|
+
*/
|
|
69
|
+
startDrag(e: PointerEvent) {
|
|
38
70
|
const data = this.block.toCopyData();
|
|
39
|
-
this.copy = Blockly.clipboard.paste(
|
|
71
|
+
this.copy = Blockly.clipboard.paste(
|
|
72
|
+
data,
|
|
73
|
+
this.block.workspace
|
|
74
|
+
) as Blockly.BlockSvg;
|
|
40
75
|
this.copy.startDrag(e);
|
|
41
76
|
}
|
|
42
77
|
|
|
43
|
-
drag(e) {
|
|
44
|
-
|
|
45
|
-
.getGesture(e)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.copy.drag(e);
|
|
78
|
+
drag(newLoc: Blockly.utils.Coordinate, e?: PointerEvent) {
|
|
79
|
+
(
|
|
80
|
+
this.block.workspace.getGesture(e).getCurrentDragger() as ScratchDragger
|
|
81
|
+
).setDraggable(this.copy);
|
|
82
|
+
this.copy.drag(newLoc, e);
|
|
49
83
|
}
|
|
50
84
|
|
|
51
|
-
endDrag(e) {
|
|
85
|
+
endDrag(e: PointerEvent) {
|
|
52
86
|
this.copy?.endDrag(e);
|
|
53
87
|
}
|
|
54
88
|
|
|
55
|
-
revertDrag(
|
|
89
|
+
revertDrag() {
|
|
56
90
|
this.copy?.dispose();
|
|
57
91
|
}
|
|
92
|
+
|
|
93
|
+
getRelativeToSurfaceXY() {
|
|
94
|
+
return this.copy
|
|
95
|
+
? this.copy.getRelativeToSurfaceXY()
|
|
96
|
+
: this.block.getRelativeToSurfaceXY();
|
|
97
|
+
}
|
|
58
98
|
}
|
|
59
99
|
|
|
60
100
|
// Serialization and deserialization.
|
|
@@ -62,11 +102,11 @@ class DuplicateOnDragDraggable {
|
|
|
62
102
|
/**
|
|
63
103
|
* Create XML to represent the (non-editable) name and arguments of a procedure
|
|
64
104
|
* call block.
|
|
65
|
-
*
|
|
66
|
-
* @
|
|
105
|
+
*
|
|
106
|
+
* @returns XML storage element.
|
|
67
107
|
*/
|
|
68
|
-
function callerMutationToDom() {
|
|
69
|
-
|
|
108
|
+
function callerMutationToDom(this: ProcedureCallBlock): Element {
|
|
109
|
+
const container = document.createElement("mutation");
|
|
70
110
|
container.setAttribute("proccode", this.procCode_);
|
|
71
111
|
container.setAttribute("argumentids", JSON.stringify(this.argumentIds_));
|
|
72
112
|
container.setAttribute("warp", JSON.stringify(this.warp_));
|
|
@@ -76,10 +116,10 @@ function callerMutationToDom() {
|
|
|
76
116
|
/**
|
|
77
117
|
* Parse XML to restore the (non-editable) name and arguments of a procedure
|
|
78
118
|
* call block.
|
|
79
|
-
*
|
|
80
|
-
* @
|
|
119
|
+
*
|
|
120
|
+
* @param xmlElement XML storage element.
|
|
81
121
|
*/
|
|
82
|
-
function callerDomToMutation(xmlElement) {
|
|
122
|
+
function callerDomToMutation(this: ProcedureCallBlock, xmlElement: Element) {
|
|
83
123
|
this.procCode_ = xmlElement.getAttribute("proccode");
|
|
84
124
|
this.generateShadows_ = JSON.parse(
|
|
85
125
|
xmlElement.getAttribute("generateshadows")
|
|
@@ -92,16 +132,19 @@ function callerDomToMutation(xmlElement) {
|
|
|
92
132
|
/**
|
|
93
133
|
* Create XML to represent the (non-editable) name and arguments of a
|
|
94
134
|
* procedures_prototype block or a procedures_declaration block.
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* @
|
|
135
|
+
*
|
|
136
|
+
* @param opt_generateShadows Whether to include the generateshadows flag in the
|
|
137
|
+
* generated XML. False if not provided.
|
|
138
|
+
* @returns XML storage element.
|
|
99
139
|
*/
|
|
100
|
-
function definitionMutationToDom(
|
|
101
|
-
|
|
140
|
+
function definitionMutationToDom(
|
|
141
|
+
this: ProcedurePrototypeBlock | ProcedureDeclarationBlock,
|
|
142
|
+
opt_generateShadows?: boolean
|
|
143
|
+
): Element {
|
|
144
|
+
const container = document.createElement("mutation");
|
|
102
145
|
|
|
103
146
|
if (opt_generateShadows) {
|
|
104
|
-
container.setAttribute("generateshadows", true);
|
|
147
|
+
container.setAttribute("generateshadows", "true");
|
|
105
148
|
}
|
|
106
149
|
container.setAttribute("proccode", this.procCode_);
|
|
107
150
|
container.setAttribute("argumentids", JSON.stringify(this.argumentIds_));
|
|
@@ -117,15 +160,18 @@ function definitionMutationToDom(opt_generateShadows) {
|
|
|
117
160
|
/**
|
|
118
161
|
* Parse XML to restore the (non-editable) name and arguments of a
|
|
119
162
|
* procedures_prototype block or a procedures_declaration block.
|
|
120
|
-
*
|
|
121
|
-
* @
|
|
163
|
+
*
|
|
164
|
+
* @param xmlElement XML storage element.
|
|
122
165
|
*/
|
|
123
|
-
function definitionDomToMutation(
|
|
166
|
+
function definitionDomToMutation(
|
|
167
|
+
this: ProcedurePrototypeBlock | ProcedureDeclarationBlock,
|
|
168
|
+
xmlElement: Element
|
|
169
|
+
) {
|
|
124
170
|
this.procCode_ = xmlElement.getAttribute("proccode");
|
|
125
171
|
this.warp_ = JSON.parse(xmlElement.getAttribute("warp"));
|
|
126
172
|
|
|
127
|
-
|
|
128
|
-
|
|
173
|
+
const prevArgIds = this.argumentIds_;
|
|
174
|
+
const prevDisplayNames = this.displayNames_;
|
|
129
175
|
|
|
130
176
|
this.argumentIds_ = JSON.parse(xmlElement.getAttribute("argumentids"));
|
|
131
177
|
this.displayNames_ = JSON.parse(xmlElement.getAttribute("argumentnames"));
|
|
@@ -133,7 +179,7 @@ function definitionDomToMutation(xmlElement) {
|
|
|
133
179
|
xmlElement.getAttribute("argumentdefaults")
|
|
134
180
|
);
|
|
135
181
|
this.updateDisplay_();
|
|
136
|
-
if (this
|
|
182
|
+
if ("updateArgumentReporterNames_" in this) {
|
|
137
183
|
this.updateArgumentReporterNames_(prevArgIds, prevDisplayNames);
|
|
138
184
|
}
|
|
139
185
|
}
|
|
@@ -145,21 +191,19 @@ function definitionDomToMutation(xmlElement) {
|
|
|
145
191
|
/**
|
|
146
192
|
* Returns the name of the procedure this block calls, or the empty string if
|
|
147
193
|
* it has not yet been set.
|
|
148
|
-
*
|
|
149
|
-
* @
|
|
194
|
+
*
|
|
195
|
+
* @returns Procedure name.
|
|
150
196
|
*/
|
|
151
|
-
function getProcCode() {
|
|
197
|
+
function getProcCode(this: ProcedureBlock): string {
|
|
152
198
|
return this.procCode_;
|
|
153
199
|
}
|
|
154
200
|
|
|
155
201
|
/**
|
|
156
202
|
* Update the block's structure and appearance to match the internally stored
|
|
157
203
|
* mutation.
|
|
158
|
-
* @private
|
|
159
|
-
* @this Blockly.Block
|
|
160
204
|
*/
|
|
161
|
-
function updateDisplay_() {
|
|
162
|
-
|
|
205
|
+
function updateDisplay_(this: ProcedureBlock) {
|
|
206
|
+
const connectionMap = this.disconnectOldBlocks_();
|
|
163
207
|
this.removeAllInputs_();
|
|
164
208
|
this.createAllInputs_(connectionMap);
|
|
165
209
|
this.deleteShadows_(connectionMap);
|
|
@@ -170,18 +214,16 @@ function updateDisplay_() {
|
|
|
170
214
|
* in case they can be reattached later. Also save the shadow DOM if it exists.
|
|
171
215
|
* The result is a map from argument ID to information that was associated with
|
|
172
216
|
* that argument at the beginning of the mutation.
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* @private
|
|
176
|
-
* @this Blockly.Block
|
|
217
|
+
*
|
|
218
|
+
* @returns An object mapping argument IDs to blocks and shadow DOMs.
|
|
177
219
|
*/
|
|
178
|
-
function disconnectOldBlocks_() {
|
|
220
|
+
function disconnectOldBlocks_(this: ProcedureBlock): ConnectionMap {
|
|
179
221
|
// Remove old stuff
|
|
180
|
-
|
|
181
|
-
for (
|
|
222
|
+
const connectionMap: ConnectionMap = {};
|
|
223
|
+
for (const input of this.inputList) {
|
|
182
224
|
if (input.connection) {
|
|
183
|
-
|
|
184
|
-
|
|
225
|
+
const target = input.connection.targetBlock() as Blockly.BlockSvg;
|
|
226
|
+
const saveInfo = {
|
|
185
227
|
shadow: input.connection.getShadowDom(),
|
|
186
228
|
block: target,
|
|
187
229
|
};
|
|
@@ -198,40 +240,39 @@ function disconnectOldBlocks_() {
|
|
|
198
240
|
/**
|
|
199
241
|
* Remove all inputs on the block, including dummy inputs.
|
|
200
242
|
* Assumes no input has shadow DOM set.
|
|
201
|
-
* @private
|
|
202
|
-
* @this Blockly.Block
|
|
203
243
|
*/
|
|
204
|
-
function removeAllInputs_() {
|
|
244
|
+
function removeAllInputs_(this: ProcedureBlock) {
|
|
205
245
|
// Delete inputs directly instead of with block.removeInput to avoid splicing
|
|
206
246
|
// out of the input list at every index.
|
|
207
|
-
|
|
208
|
-
input.dispose();
|
|
209
|
-
}
|
|
247
|
+
this.inputList.forEach((input: Blockly.Input) => input.dispose());
|
|
210
248
|
this.inputList = [];
|
|
211
249
|
}
|
|
212
250
|
|
|
213
251
|
/**
|
|
214
252
|
* Create all inputs specified by the new procCode, and populate them with
|
|
215
253
|
* shadow blocks or reconnected old blocks as appropriate.
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* @private
|
|
219
|
-
* @this Blockly.Block
|
|
254
|
+
*
|
|
255
|
+
* @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
|
|
220
256
|
*/
|
|
221
|
-
function createAllInputs_(connectionMap) {
|
|
257
|
+
function createAllInputs_(this: ProcedureBlock, connectionMap: ConnectionMap) {
|
|
222
258
|
// Split the proc into components, by %n, %b, and %s (ignoring escaped).
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
259
|
+
const procComponents = this.procCode_
|
|
260
|
+
.split(/(?=[^\\]%[nbs])/)
|
|
261
|
+
.map(function (c: string) {
|
|
262
|
+
return c.trim(); // Strip whitespace.
|
|
263
|
+
});
|
|
227
264
|
// Create arguments and labels as appropriate.
|
|
228
|
-
|
|
229
|
-
for (
|
|
230
|
-
|
|
231
|
-
if (component.substring(0, 1)
|
|
232
|
-
|
|
265
|
+
let argumentCount = 0;
|
|
266
|
+
for (const component of procComponents) {
|
|
267
|
+
let labelText;
|
|
268
|
+
if (component.substring(0, 1) === "%") {
|
|
269
|
+
const argumentType = component.substring(1, 2);
|
|
233
270
|
if (
|
|
234
|
-
!(
|
|
271
|
+
!(
|
|
272
|
+
argumentType === ArgumentType.NUMBER ||
|
|
273
|
+
argumentType === ArgumentType.BOOLEAN ||
|
|
274
|
+
argumentType === ArgumentType.STRING
|
|
275
|
+
)
|
|
235
276
|
) {
|
|
236
277
|
throw new Error(
|
|
237
278
|
"Found an custom procedure with an invalid type: " + argumentType
|
|
@@ -239,10 +280,10 @@ function createAllInputs_(connectionMap) {
|
|
|
239
280
|
}
|
|
240
281
|
labelText = component.substring(2).trim();
|
|
241
282
|
|
|
242
|
-
|
|
283
|
+
const id = this.argumentIds_[argumentCount];
|
|
243
284
|
|
|
244
|
-
|
|
245
|
-
if (argumentType
|
|
285
|
+
const input = this.appendValueInput(id);
|
|
286
|
+
if (argumentType === ArgumentType.BOOLEAN) {
|
|
246
287
|
input.setCheck("Boolean");
|
|
247
288
|
}
|
|
248
289
|
this.populateArgument_(
|
|
@@ -262,19 +303,17 @@ function createAllInputs_(connectionMap) {
|
|
|
262
303
|
|
|
263
304
|
/**
|
|
264
305
|
* Delete all shadow blocks in the given map.
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
* beginning of the mutation.
|
|
268
|
-
* @private
|
|
269
|
-
* @this Blockly.Block
|
|
306
|
+
*
|
|
307
|
+
* @param connectionMap An object mapping argument IDs to the blocks that were
|
|
308
|
+
* connected to those IDs at the beginning of the mutation.
|
|
270
309
|
*/
|
|
271
|
-
function deleteShadows_(connectionMap) {
|
|
310
|
+
function deleteShadows_(this: ProcedureBlock, connectionMap: ConnectionMap) {
|
|
272
311
|
// Get rid of all of the old shadow blocks if they aren't connected.
|
|
273
312
|
if (connectionMap) {
|
|
274
|
-
for (
|
|
275
|
-
|
|
313
|
+
for (const id in connectionMap) {
|
|
314
|
+
const saveInfo = connectionMap[id];
|
|
276
315
|
if (saveInfo) {
|
|
277
|
-
|
|
316
|
+
const block = saveInfo["block"];
|
|
278
317
|
if (block && block.isShadow()) {
|
|
279
318
|
block.dispose();
|
|
280
319
|
connectionMap[id] = null;
|
|
@@ -290,10 +329,13 @@ function deleteShadows_(connectionMap) {
|
|
|
290
329
|
/**
|
|
291
330
|
* Add a label field with the given text to a procedures_call or
|
|
292
331
|
* procedures_prototype block.
|
|
293
|
-
*
|
|
294
|
-
* @
|
|
332
|
+
*
|
|
333
|
+
* @param text The label text.
|
|
295
334
|
*/
|
|
296
|
-
function addLabelField_(
|
|
335
|
+
function addLabelField_(
|
|
336
|
+
this: ProcedureCallBlock | ProcedurePrototypeBlock,
|
|
337
|
+
text: string
|
|
338
|
+
) {
|
|
297
339
|
this.appendDummyInput().appendField(text);
|
|
298
340
|
}
|
|
299
341
|
|
|
@@ -301,10 +343,10 @@ function addLabelField_(text) {
|
|
|
301
343
|
* Add a label editor with the given text to a procedures_declaration
|
|
302
344
|
* block. Editing the text in the label editor updates the text of the
|
|
303
345
|
* corresponding label fields on function calls.
|
|
304
|
-
*
|
|
305
|
-
* @
|
|
346
|
+
*
|
|
347
|
+
* @param text The label text.
|
|
306
348
|
*/
|
|
307
|
-
function addLabelEditor_(text) {
|
|
349
|
+
function addLabelEditor_(this: ProcedureDeclarationBlock, text: string) {
|
|
308
350
|
if (text) {
|
|
309
351
|
this.appendDummyInput(Blockly.utils.idGenerator.genUid()).appendField(
|
|
310
352
|
new FieldTextInputRemovable(text)
|
|
@@ -314,24 +356,25 @@ function addLabelEditor_(text) {
|
|
|
314
356
|
|
|
315
357
|
/**
|
|
316
358
|
* Build a DOM node representing a shadow block of the given type.
|
|
317
|
-
*
|
|
318
|
-
* @
|
|
319
|
-
* @
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
if (type
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
359
|
+
*
|
|
360
|
+
* @param type One of 's' (string) or 'n' (number).
|
|
361
|
+
* @returns The DOM node representing the new shadow block.
|
|
362
|
+
*/
|
|
363
|
+
function buildShadowDom_(type: ArgumentType): Element {
|
|
364
|
+
const shadowDom = document.createElement("shadow");
|
|
365
|
+
let shadowType, fieldName, fieldValue;
|
|
366
|
+
if (type === ArgumentType.NUMBER) {
|
|
367
|
+
shadowType = "math_number";
|
|
368
|
+
fieldName = "NUM";
|
|
369
|
+
fieldValue = "1";
|
|
328
370
|
} else {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
371
|
+
shadowType = "text";
|
|
372
|
+
fieldName = "TEXT";
|
|
373
|
+
fieldValue = "";
|
|
332
374
|
}
|
|
333
375
|
shadowDom.setAttribute("type", shadowType);
|
|
334
|
-
|
|
376
|
+
const fieldDom = document.createElement("field");
|
|
377
|
+
fieldDom.textContent = fieldValue;
|
|
335
378
|
fieldDom.setAttribute("name", fieldName);
|
|
336
379
|
shadowDom.appendChild(fieldDom);
|
|
337
380
|
return shadowDom;
|
|
@@ -339,19 +382,27 @@ function buildShadowDom_(type) {
|
|
|
339
382
|
|
|
340
383
|
/**
|
|
341
384
|
* Create a new shadow block and attach it to the given input.
|
|
342
|
-
*
|
|
343
|
-
* @param
|
|
385
|
+
*
|
|
386
|
+
* @param input The value input to attach a block to.
|
|
387
|
+
* @param argumentType One of 'b' (boolean), 's' (string) or
|
|
344
388
|
* 'n' (number).
|
|
345
|
-
* @private
|
|
346
|
-
* @this Blockly.Block
|
|
347
389
|
*/
|
|
348
|
-
function attachShadow_(
|
|
349
|
-
|
|
350
|
-
|
|
390
|
+
function attachShadow_(
|
|
391
|
+
this: ProcedureCallBlock,
|
|
392
|
+
input: Blockly.Input,
|
|
393
|
+
argumentType: ArgumentType
|
|
394
|
+
) {
|
|
395
|
+
if (
|
|
396
|
+
argumentType === ArgumentType.NUMBER ||
|
|
397
|
+
argumentType === ArgumentType.STRING
|
|
398
|
+
) {
|
|
399
|
+
const blockType =
|
|
400
|
+
argumentType === ArgumentType.NUMBER ? "math_number" : "text";
|
|
351
401
|
Blockly.Events.disable();
|
|
402
|
+
let newBlock;
|
|
352
403
|
try {
|
|
353
|
-
|
|
354
|
-
if (argumentType
|
|
404
|
+
newBlock = this.workspace.newBlock(blockType);
|
|
405
|
+
if (argumentType === ArgumentType.NUMBER) {
|
|
355
406
|
newBlock.setFieldValue("1", "NUM");
|
|
356
407
|
} else {
|
|
357
408
|
newBlock.setFieldValue("", "TEXT");
|
|
@@ -359,7 +410,7 @@ function attachShadow_(input, argumentType) {
|
|
|
359
410
|
newBlock.setShadow(true);
|
|
360
411
|
if (!this.isInsertionMarker()) {
|
|
361
412
|
newBlock.initSvg();
|
|
362
|
-
newBlock.render(
|
|
413
|
+
newBlock.render();
|
|
363
414
|
}
|
|
364
415
|
} finally {
|
|
365
416
|
Blockly.Events.enable();
|
|
@@ -375,28 +426,36 @@ function attachShadow_(input, argumentType) {
|
|
|
375
426
|
|
|
376
427
|
/**
|
|
377
428
|
* Create a new argument reporter block.
|
|
378
|
-
*
|
|
429
|
+
*
|
|
430
|
+
* @param argumentType One of 'b' (boolean), 's' (string) or
|
|
379
431
|
* 'n' (number).
|
|
380
|
-
* @param
|
|
432
|
+
* @param displayName The name of the argument as provided by the
|
|
381
433
|
* user, which becomes the text of the label on the argument reporter block.
|
|
382
|
-
* @
|
|
383
|
-
* @private
|
|
384
|
-
* @this Blockly.Block
|
|
434
|
+
* @returns The newly created argument reporter block.
|
|
385
435
|
*/
|
|
386
|
-
function createArgumentReporter_(
|
|
387
|
-
|
|
388
|
-
|
|
436
|
+
function createArgumentReporter_(
|
|
437
|
+
this: ProcedurePrototypeBlock,
|
|
438
|
+
argumentType: ArgumentType,
|
|
439
|
+
displayName: string
|
|
440
|
+
): Blockly.BlockSvg {
|
|
441
|
+
let blockType;
|
|
442
|
+
if (
|
|
443
|
+
argumentType === ArgumentType.NUMBER ||
|
|
444
|
+
argumentType === ArgumentType.STRING
|
|
445
|
+
) {
|
|
446
|
+
blockType = "argument_reporter_string_number";
|
|
389
447
|
} else {
|
|
390
|
-
|
|
448
|
+
blockType = "argument_reporter_boolean";
|
|
391
449
|
}
|
|
392
450
|
Blockly.Events.disable();
|
|
451
|
+
let newBlock;
|
|
393
452
|
try {
|
|
394
|
-
|
|
453
|
+
newBlock = this.workspace.newBlock(blockType);
|
|
395
454
|
newBlock.setShadow(true);
|
|
396
455
|
newBlock.setFieldValue(displayName, "VALUE");
|
|
397
456
|
if (!this.isInsertionMarker()) {
|
|
398
457
|
newBlock.initSvg();
|
|
399
|
-
newBlock.render(
|
|
458
|
+
newBlock.render();
|
|
400
459
|
}
|
|
401
460
|
} finally {
|
|
402
461
|
Blockly.Events.enable();
|
|
@@ -412,20 +471,25 @@ function createArgumentReporter_(argumentType, displayName) {
|
|
|
412
471
|
/**
|
|
413
472
|
* Populate the argument by attaching the correct child block or shadow to the
|
|
414
473
|
* given input.
|
|
415
|
-
*
|
|
416
|
-
* @param
|
|
417
|
-
* @param
|
|
418
|
-
*
|
|
419
|
-
* @param
|
|
420
|
-
* @param
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
474
|
+
*
|
|
475
|
+
* @param type One of 'b' (boolean), 's' (string) or 'n' (number).
|
|
476
|
+
* @param index The index of this argument into the argument id array.
|
|
477
|
+
* @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
|
|
478
|
+
* @param id The ID of the input to populate.
|
|
479
|
+
* @param input The newly created input to populate.
|
|
480
|
+
*/
|
|
481
|
+
function populateArgumentOnCaller_(
|
|
482
|
+
this: ProcedureCallBlock,
|
|
483
|
+
type: ArgumentType,
|
|
484
|
+
index: number,
|
|
485
|
+
connectionMap: ConnectionMap,
|
|
486
|
+
id: string,
|
|
487
|
+
input: Blockly.Input
|
|
488
|
+
) {
|
|
489
|
+
let oldBlock: Blockly.BlockSvg;
|
|
490
|
+
let oldShadow: Element;
|
|
427
491
|
if (connectionMap && id in connectionMap) {
|
|
428
|
-
|
|
492
|
+
const saveInfo = connectionMap[id];
|
|
429
493
|
oldBlock = saveInfo["block"];
|
|
430
494
|
oldShadow = saveInfo["shadow"];
|
|
431
495
|
}
|
|
@@ -434,9 +498,8 @@ function populateArgumentOnCaller_(type, index, connectionMap, id, input) {
|
|
|
434
498
|
// Reattach the old block and shadow DOM.
|
|
435
499
|
connectionMap[input.name] = null;
|
|
436
500
|
oldBlock.outputConnection.connect(input.connection);
|
|
437
|
-
if (type
|
|
438
|
-
|
|
439
|
-
console.log("setting shadow dom: " + shadowDom);
|
|
501
|
+
if (type !== ArgumentType.BOOLEAN && this.generateShadows_) {
|
|
502
|
+
const shadowDom = oldShadow || this.buildShadowDom_(type);
|
|
440
503
|
input.connection.setShadowDom(shadowDom);
|
|
441
504
|
}
|
|
442
505
|
} else if (this.generateShadows_) {
|
|
@@ -447,35 +510,41 @@ function populateArgumentOnCaller_(type, index, connectionMap, id, input) {
|
|
|
447
510
|
/**
|
|
448
511
|
* Populate the argument by attaching the correct argument reporter to the given
|
|
449
512
|
* input.
|
|
450
|
-
*
|
|
451
|
-
* @param
|
|
513
|
+
*
|
|
514
|
+
* @param type One of 'b' (boolean), 's' (string) or 'n' (number).
|
|
515
|
+
* @param index The index of this argument into the argument ID and
|
|
452
516
|
* argument display name arrays.
|
|
453
|
-
* @param
|
|
454
|
-
*
|
|
455
|
-
* @param
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
517
|
+
* @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
|
|
518
|
+
* @param id The ID of the input to populate.
|
|
519
|
+
* @param input The newly created input to populate.
|
|
520
|
+
*/
|
|
521
|
+
function populateArgumentOnPrototype_(
|
|
522
|
+
this: ProcedurePrototypeBlock,
|
|
523
|
+
type: ArgumentType,
|
|
524
|
+
index: number,
|
|
525
|
+
connectionMap: ConnectionMap,
|
|
526
|
+
id: string,
|
|
527
|
+
input: Blockly.Input
|
|
528
|
+
) {
|
|
529
|
+
let oldBlock = null;
|
|
462
530
|
if (connectionMap && id in connectionMap) {
|
|
463
|
-
|
|
531
|
+
const saveInfo = connectionMap[id];
|
|
464
532
|
oldBlock = saveInfo["block"];
|
|
465
533
|
}
|
|
466
534
|
|
|
467
|
-
|
|
468
|
-
|
|
535
|
+
const oldTypeMatches = checkOldTypeMatches_(oldBlock, type);
|
|
536
|
+
const displayName = this.displayNames_[index];
|
|
469
537
|
|
|
470
538
|
// Decide which block to attach.
|
|
539
|
+
let argumentReporter: Blockly.BlockSvg;
|
|
471
540
|
if (connectionMap && oldBlock && oldTypeMatches) {
|
|
472
541
|
// Update the text if needed. The old argument reporter is the same type,
|
|
473
542
|
// and on the same input, but the argument's display name may have changed.
|
|
474
|
-
|
|
543
|
+
argumentReporter = oldBlock;
|
|
475
544
|
argumentReporter.setFieldValue(displayName, "VALUE");
|
|
476
545
|
connectionMap[input.name] = null;
|
|
477
546
|
} else {
|
|
478
|
-
|
|
547
|
+
argumentReporter = this.createArgumentReporter_(type, displayName);
|
|
479
548
|
}
|
|
480
549
|
|
|
481
550
|
// Attach the block.
|
|
@@ -485,36 +554,42 @@ function populateArgumentOnPrototype_(type, index, connectionMap, id, input) {
|
|
|
485
554
|
/**
|
|
486
555
|
* Populate the argument by attaching the correct argument editor to the given
|
|
487
556
|
* input.
|
|
488
|
-
*
|
|
489
|
-
* @param
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
* @param
|
|
494
|
-
* @param
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
557
|
+
*
|
|
558
|
+
* @param type One of 'b' (boolean), 's' (string) or 'n' (number).
|
|
559
|
+
* @param index The index of this argument into the argument id and argument
|
|
560
|
+
* display name arrays.
|
|
561
|
+
* @param connectionMap An object mapping argument IDs to blocks and shadow DOMs.
|
|
562
|
+
* @param id The ID of the input to populate.
|
|
563
|
+
* @param input The newly created input to populate.
|
|
564
|
+
*/
|
|
565
|
+
function populateArgumentOnDeclaration_(
|
|
566
|
+
this: ProcedureDeclarationBlock,
|
|
567
|
+
type: ArgumentType,
|
|
568
|
+
index: number,
|
|
569
|
+
connectionMap: ConnectionMap,
|
|
570
|
+
id: string,
|
|
571
|
+
input: Blockly.Input
|
|
572
|
+
) {
|
|
573
|
+
let oldBlock = null;
|
|
500
574
|
if (connectionMap && id in connectionMap) {
|
|
501
|
-
|
|
575
|
+
const saveInfo = connectionMap[id];
|
|
502
576
|
oldBlock = saveInfo["block"];
|
|
503
577
|
}
|
|
504
578
|
|
|
505
579
|
// TODO: This always returns false, because it checks for argument reporter
|
|
506
580
|
// blocks instead of argument editor blocks. Create a new version for argument
|
|
507
581
|
// editors.
|
|
508
|
-
|
|
509
|
-
|
|
582
|
+
const oldTypeMatches = checkOldTypeMatches_(oldBlock, type);
|
|
583
|
+
const displayName = this.displayNames_[index];
|
|
510
584
|
|
|
511
585
|
// Decide which block to attach.
|
|
586
|
+
let argumentEditor: Blockly.BlockSvg;
|
|
512
587
|
if (oldBlock && oldTypeMatches) {
|
|
513
|
-
|
|
588
|
+
argumentEditor = oldBlock;
|
|
514
589
|
oldBlock.setFieldValue(displayName, "TEXT");
|
|
515
590
|
connectionMap[input.name] = null;
|
|
516
591
|
} else {
|
|
517
|
-
|
|
592
|
+
argumentEditor = this.createArgumentEditor_(type, displayName);
|
|
518
593
|
}
|
|
519
594
|
|
|
520
595
|
// Attach the block.
|
|
@@ -524,21 +599,28 @@ function populateArgumentOnDeclaration_(type, index, connectionMap, id, input) {
|
|
|
524
599
|
/**
|
|
525
600
|
* Check whether the type of the old block corresponds to the given argument
|
|
526
601
|
* type.
|
|
527
|
-
*
|
|
528
|
-
* @param
|
|
529
|
-
* @
|
|
602
|
+
*
|
|
603
|
+
* @param oldBlock The old block to check.
|
|
604
|
+
* @param type The argument type. One of 'n', 'n', or 's'.
|
|
605
|
+
* @returns True if the type matches, false otherwise.
|
|
530
606
|
*/
|
|
531
|
-
function checkOldTypeMatches_(
|
|
607
|
+
function checkOldTypeMatches_(
|
|
608
|
+
oldBlock: Blockly.BlockSvg | null,
|
|
609
|
+
type: string
|
|
610
|
+
): boolean {
|
|
532
611
|
if (!oldBlock) {
|
|
533
612
|
return false;
|
|
534
613
|
}
|
|
535
614
|
if (
|
|
536
|
-
(type
|
|
537
|
-
oldBlock.type
|
|
615
|
+
(type === ArgumentType.NUMBER || type === ArgumentType.STRING) &&
|
|
616
|
+
oldBlock.type === "argument_reporter_string_number"
|
|
538
617
|
) {
|
|
539
618
|
return true;
|
|
540
619
|
}
|
|
541
|
-
if (
|
|
620
|
+
if (
|
|
621
|
+
type === ArgumentType.BOOLEAN &&
|
|
622
|
+
oldBlock.type === "argument_reporter_boolean"
|
|
623
|
+
) {
|
|
542
624
|
return true;
|
|
543
625
|
}
|
|
544
626
|
return false;
|
|
@@ -548,21 +630,27 @@ function checkOldTypeMatches_(oldBlock, type) {
|
|
|
548
630
|
* Create an argument editor.
|
|
549
631
|
* An argument editor is a shadow block with a single text field, which is used
|
|
550
632
|
* to set the display name of the argument.
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
* @param
|
|
554
|
-
*
|
|
555
|
-
* @
|
|
556
|
-
* @private
|
|
557
|
-
* @this Blockly.Block
|
|
633
|
+
*
|
|
634
|
+
* @param argumentType One of 'b' (boolean), 's' (string) or 'n' (number).
|
|
635
|
+
* @param displayName The display name of this argument, which is the text of
|
|
636
|
+
* the field on the shadow block.
|
|
637
|
+
* @returns The newly created argument editor block.
|
|
558
638
|
*/
|
|
559
|
-
function createArgumentEditor_(
|
|
639
|
+
function createArgumentEditor_(
|
|
640
|
+
this: ProcedureDeclarationBlock,
|
|
641
|
+
argumentType: ArgumentType,
|
|
642
|
+
displayName: string
|
|
643
|
+
): Blockly.BlockSvg {
|
|
560
644
|
Blockly.Events.disable();
|
|
645
|
+
let newBlock;
|
|
561
646
|
try {
|
|
562
|
-
if (
|
|
563
|
-
|
|
647
|
+
if (
|
|
648
|
+
argumentType === ArgumentType.NUMBER ||
|
|
649
|
+
argumentType === ArgumentType.STRING
|
|
650
|
+
) {
|
|
651
|
+
newBlock = this.workspace.newBlock("argument_editor_string_number");
|
|
564
652
|
} else {
|
|
565
|
-
|
|
653
|
+
newBlock = this.workspace.newBlock("argument_editor_boolean");
|
|
566
654
|
}
|
|
567
655
|
newBlock.setFieldValue(displayName, "TEXT");
|
|
568
656
|
newBlock.setShadow(true);
|
|
@@ -585,23 +673,23 @@ function createArgumentEditor_(argumentType, displayName) {
|
|
|
585
673
|
* Update the serializable information on the block based on the existing inputs
|
|
586
674
|
* and their text.
|
|
587
675
|
*/
|
|
588
|
-
function updateDeclarationProcCode_() {
|
|
676
|
+
function updateDeclarationProcCode_(this: ProcedureDeclarationBlock) {
|
|
589
677
|
this.procCode_ = "";
|
|
590
678
|
this.displayNames_ = [];
|
|
591
679
|
this.argumentIds_ = [];
|
|
592
|
-
for (
|
|
593
|
-
if (i
|
|
680
|
+
for (let i = 0; i < this.inputList.length; i++) {
|
|
681
|
+
if (i !== 0) {
|
|
594
682
|
this.procCode_ += " ";
|
|
595
683
|
}
|
|
596
|
-
|
|
597
|
-
if (input.type
|
|
684
|
+
const input = this.inputList[i];
|
|
685
|
+
if (input.type === Blockly.inputs.inputTypes.DUMMY) {
|
|
598
686
|
this.procCode_ += input.fieldRow[0].getValue();
|
|
599
|
-
} else if (input.type
|
|
687
|
+
} else if (input.type === Blockly.inputs.inputTypes.VALUE) {
|
|
600
688
|
// Inspect the argument editor.
|
|
601
|
-
|
|
689
|
+
const target = input.connection.targetBlock();
|
|
602
690
|
this.displayNames_.push(target.getFieldValue("TEXT"));
|
|
603
691
|
this.argumentIds_.push(input.name);
|
|
604
|
-
if (target.type
|
|
692
|
+
if (target.type === "argument_editor_boolean") {
|
|
605
693
|
this.procCode_ += "%b";
|
|
606
694
|
} else {
|
|
607
695
|
this.procCode_ += "%s";
|
|
@@ -616,27 +704,25 @@ function updateDeclarationProcCode_() {
|
|
|
616
704
|
|
|
617
705
|
/**
|
|
618
706
|
* Focus on the last argument editor or label editor on the block.
|
|
619
|
-
* @private
|
|
620
707
|
*/
|
|
621
|
-
function focusLastEditor_() {
|
|
708
|
+
function focusLastEditor_(this: ProcedureDeclarationBlock) {
|
|
622
709
|
if (this.inputList.length > 0) {
|
|
623
|
-
|
|
624
|
-
if (newInput.type
|
|
625
|
-
newInput.fieldRow[0].
|
|
626
|
-
} else if (newInput.type
|
|
710
|
+
const newInput = this.inputList[this.inputList.length - 1];
|
|
711
|
+
if (newInput.type === Blockly.inputs.inputTypes.DUMMY) {
|
|
712
|
+
newInput.fieldRow[0].showEditor();
|
|
713
|
+
} else if (newInput.type === Blockly.inputs.inputTypes.VALUE) {
|
|
627
714
|
// Inspect the argument editor.
|
|
628
|
-
|
|
629
|
-
target.getField("TEXT").
|
|
715
|
+
const target = newInput.connection.targetBlock();
|
|
716
|
+
target.getField("TEXT").showEditor();
|
|
630
717
|
}
|
|
631
718
|
}
|
|
632
719
|
}
|
|
633
720
|
|
|
634
721
|
/**
|
|
635
722
|
* Externally-visible function to add a label to the procedure declaration.
|
|
636
|
-
* @public
|
|
637
723
|
*/
|
|
638
|
-
function addLabelExternal() {
|
|
639
|
-
Blockly.WidgetDiv.hide(
|
|
724
|
+
function addLabelExternal(this: ProcedureDeclarationBlock) {
|
|
725
|
+
Blockly.WidgetDiv.hide();
|
|
640
726
|
this.procCode_ = this.procCode_ + " label text";
|
|
641
727
|
this.updateDisplay_();
|
|
642
728
|
this.focusLastEditor_();
|
|
@@ -645,10 +731,9 @@ function addLabelExternal() {
|
|
|
645
731
|
/**
|
|
646
732
|
* Externally-visible function to add a boolean argument to the procedure
|
|
647
733
|
* declaration.
|
|
648
|
-
* @public
|
|
649
734
|
*/
|
|
650
|
-
function addBooleanExternal() {
|
|
651
|
-
Blockly.WidgetDiv.hide(
|
|
735
|
+
function addBooleanExternal(this: ProcedureDeclarationBlock) {
|
|
736
|
+
Blockly.WidgetDiv.hide();
|
|
652
737
|
this.procCode_ = this.procCode_ + " %b";
|
|
653
738
|
this.displayNames_.push("boolean");
|
|
654
739
|
this.argumentIds_.push(Blockly.utils.idGenerator.genUid());
|
|
@@ -660,10 +745,9 @@ function addBooleanExternal() {
|
|
|
660
745
|
/**
|
|
661
746
|
* Externally-visible function to add a string/number argument to the procedure
|
|
662
747
|
* declaration.
|
|
663
|
-
* @public
|
|
664
748
|
*/
|
|
665
|
-
function addStringNumberExternal() {
|
|
666
|
-
Blockly.WidgetDiv.hide(
|
|
749
|
+
function addStringNumberExternal(this: ProcedureDeclarationBlock) {
|
|
750
|
+
Blockly.WidgetDiv.hide();
|
|
667
751
|
this.procCode_ = this.procCode_ + " %s";
|
|
668
752
|
this.displayNames_.push("number or text");
|
|
669
753
|
this.argumentIds_.push(Blockly.utils.idGenerator.genUid());
|
|
@@ -674,28 +758,31 @@ function addStringNumberExternal() {
|
|
|
674
758
|
|
|
675
759
|
/**
|
|
676
760
|
* Externally-visible function to get the warp on procedure declaration.
|
|
677
|
-
*
|
|
678
|
-
* @
|
|
761
|
+
*
|
|
762
|
+
* @returns The value of the warp_ property.
|
|
679
763
|
*/
|
|
680
|
-
function getWarp() {
|
|
764
|
+
function getWarp(this: ProcedureDeclarationBlock): boolean {
|
|
681
765
|
return this.warp_;
|
|
682
766
|
}
|
|
683
767
|
|
|
684
768
|
/**
|
|
685
769
|
* Externally-visible function to set the warp on procedure declaration.
|
|
686
|
-
*
|
|
687
|
-
* @
|
|
770
|
+
*
|
|
771
|
+
* @param warp The value of the warp_ property.
|
|
688
772
|
*/
|
|
689
|
-
function setWarp(warp) {
|
|
773
|
+
function setWarp(this: ProcedureDeclarationBlock, warp: boolean) {
|
|
690
774
|
this.warp_ = warp;
|
|
691
775
|
}
|
|
692
776
|
|
|
693
777
|
/**
|
|
694
778
|
* Callback to remove a field, only for the declaration block.
|
|
695
|
-
*
|
|
696
|
-
* @
|
|
779
|
+
*
|
|
780
|
+
* @param field The field being removed.
|
|
697
781
|
*/
|
|
698
|
-
function removeFieldCallback(
|
|
782
|
+
function removeFieldCallback(
|
|
783
|
+
this: ProcedureDeclarationBlock,
|
|
784
|
+
field: Blockly.Field
|
|
785
|
+
) {
|
|
699
786
|
// Do not delete if there is only one input
|
|
700
787
|
if (this.inputList.length === 1) {
|
|
701
788
|
return;
|
|
@@ -705,19 +792,19 @@ function removeFieldCallback(field) {
|
|
|
705
792
|
var input = this.inputList[n];
|
|
706
793
|
if (input.connection) {
|
|
707
794
|
var target = input.connection.targetBlock();
|
|
708
|
-
if (field.name && target.getField(field.name)
|
|
795
|
+
if (field.name && target.getField(field.name) === field) {
|
|
709
796
|
inputNameToRemove = input.name;
|
|
710
797
|
}
|
|
711
798
|
} else {
|
|
712
799
|
for (var j = 0; j < input.fieldRow.length; j++) {
|
|
713
|
-
if (input.fieldRow[j]
|
|
800
|
+
if (input.fieldRow[j] === field) {
|
|
714
801
|
inputNameToRemove = input.name;
|
|
715
802
|
}
|
|
716
803
|
}
|
|
717
804
|
}
|
|
718
805
|
}
|
|
719
806
|
if (inputNameToRemove) {
|
|
720
|
-
Blockly.WidgetDiv.hide(
|
|
807
|
+
Blockly.WidgetDiv.hide();
|
|
721
808
|
this.removeInput(inputNameToRemove);
|
|
722
809
|
this.onChangeFn();
|
|
723
810
|
this.updateDisplay_();
|
|
@@ -726,12 +813,16 @@ function removeFieldCallback(field) {
|
|
|
726
813
|
|
|
727
814
|
/**
|
|
728
815
|
* Callback to pass removeField up to the declaration block from arguments.
|
|
729
|
-
*
|
|
730
|
-
* @
|
|
816
|
+
*
|
|
817
|
+
* @param field The field being removed.
|
|
731
818
|
*/
|
|
732
|
-
function removeArgumentCallback_(
|
|
733
|
-
|
|
734
|
-
|
|
819
|
+
function removeArgumentCallback_(
|
|
820
|
+
this: ProcedureDeclarationBlock | ProcedureArgumentEditorBlock,
|
|
821
|
+
field: Blockly.Field
|
|
822
|
+
) {
|
|
823
|
+
const parent = this.getParent();
|
|
824
|
+
if (parent && parent.removeFieldCallback) {
|
|
825
|
+
parent.removeFieldCallback(field);
|
|
735
826
|
}
|
|
736
827
|
}
|
|
737
828
|
|
|
@@ -744,20 +835,22 @@ function removeArgumentCallback_(field) {
|
|
|
744
835
|
* Until there is a more explicit way of identifying argument reporter blocks using ids,
|
|
745
836
|
* be conservative and only update argument reporters that are used in the
|
|
746
837
|
* stack below the prototype, ie the definition.
|
|
747
|
-
*
|
|
748
|
-
* @param
|
|
749
|
-
* @
|
|
750
|
-
*/
|
|
751
|
-
function updateArgumentReporterNames_(
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
838
|
+
*
|
|
839
|
+
* @param prevArgIds The previous ordering of argument ids.
|
|
840
|
+
* @param prevDisplayNames The previous argument names.
|
|
841
|
+
*/
|
|
842
|
+
function updateArgumentReporterNames_(
|
|
843
|
+
this: ProcedurePrototypeBlock,
|
|
844
|
+
prevArgIds: string[],
|
|
845
|
+
prevDisplayNames: string[]
|
|
846
|
+
) {
|
|
847
|
+
const nameChanges: { newName: string; blocks: Blockly.BlockSvg[] }[] = [];
|
|
848
|
+
const argReporters: Blockly.BlockSvg[] = [];
|
|
849
|
+
const definitionBlock = this.getParent();
|
|
755
850
|
if (!definitionBlock) return;
|
|
756
851
|
|
|
757
852
|
// Create a list of argument reporters that are descendants of the definition stack (see above comment)
|
|
758
|
-
|
|
759
|
-
for (var i = 0; i < allBlocks.length; i++) {
|
|
760
|
-
var block = allBlocks[i];
|
|
853
|
+
definitionBlock.getDescendants(false).forEach((block: Blockly.BlockSvg) => {
|
|
761
854
|
if (
|
|
762
855
|
(block.type === "argument_reporter_string_number" ||
|
|
763
856
|
block.type === "argument_reporter_boolean") &&
|
|
@@ -766,20 +859,20 @@ function updateArgumentReporterNames_(prevArgIds, prevDisplayNames) {
|
|
|
766
859
|
// Exclude arg reporters in the prototype block, which are shadows.
|
|
767
860
|
argReporters.push(block);
|
|
768
861
|
}
|
|
769
|
-
}
|
|
862
|
+
});
|
|
770
863
|
|
|
771
864
|
// Create a list of "name changes", including the new name and blocks matching the old name
|
|
772
865
|
// Only search over the current set of argument ids, ignore args that have been removed
|
|
773
|
-
for (
|
|
866
|
+
for (let i = 0, id; (id = this.argumentIds_[i]); i++) {
|
|
774
867
|
// Find the previous index of this argument id. Could be -1 if it is newly added.
|
|
775
|
-
|
|
776
|
-
if (prevIndex
|
|
777
|
-
|
|
778
|
-
if (prevName
|
|
868
|
+
const prevIndex = prevArgIds.indexOf(id);
|
|
869
|
+
if (prevIndex === -1) continue; // Newly added argument, no corresponding previous argument to update.
|
|
870
|
+
const prevName = prevDisplayNames[prevIndex];
|
|
871
|
+
if (prevName !== this.displayNames_[i]) {
|
|
779
872
|
nameChanges.push({
|
|
780
873
|
newName: this.displayNames_[i],
|
|
781
|
-
blocks: argReporters.filter(
|
|
782
|
-
return block.getFieldValue("VALUE")
|
|
874
|
+
blocks: argReporters.filter((block) => {
|
|
875
|
+
return block.getFieldValue("VALUE") === prevName;
|
|
783
876
|
}),
|
|
784
877
|
});
|
|
785
878
|
}
|
|
@@ -787,8 +880,8 @@ function updateArgumentReporterNames_(prevArgIds, prevDisplayNames) {
|
|
|
787
880
|
|
|
788
881
|
// Finally update the blocks for each name change.
|
|
789
882
|
// Do this after creating the lists to avoid cycles of renaming.
|
|
790
|
-
for (
|
|
791
|
-
for (
|
|
883
|
+
for (const nameChange of nameChanges) {
|
|
884
|
+
for (const block of nameChange.blocks) {
|
|
792
885
|
block.setFieldValue(nameChange.newName, "VALUE");
|
|
793
886
|
}
|
|
794
887
|
}
|
|
@@ -797,9 +890,8 @@ function updateArgumentReporterNames_(prevArgIds, prevDisplayNames) {
|
|
|
797
890
|
Blockly.Blocks["procedures_definition"] = {
|
|
798
891
|
/**
|
|
799
892
|
* Block for defining a procedure with no return value.
|
|
800
|
-
* @this Blockly.Block
|
|
801
893
|
*/
|
|
802
|
-
init: function () {
|
|
894
|
+
init: function (this: Blockly.Block) {
|
|
803
895
|
this.jsonInit({
|
|
804
896
|
message0: Blockly.Msg.PROCEDURES_DEFINITION,
|
|
805
897
|
args0: [
|
|
@@ -820,9 +912,8 @@ Blockly.Blocks["procedures_definition"] = {
|
|
|
820
912
|
Blockly.Blocks["procedures_call"] = {
|
|
821
913
|
/**
|
|
822
914
|
* Block for calling a procedure with no return value.
|
|
823
|
-
* @this Blockly.Block
|
|
824
915
|
*/
|
|
825
|
-
init: function () {
|
|
916
|
+
init: function (this: ProcedureCallBlock) {
|
|
826
917
|
this.jsonInit({
|
|
827
918
|
extensions: [
|
|
828
919
|
"colours_more",
|
|
@@ -858,9 +949,8 @@ Blockly.Blocks["procedures_prototype"] = {
|
|
|
858
949
|
/**
|
|
859
950
|
* Block for calling a procedure with no return value, for rendering inside
|
|
860
951
|
* define block.
|
|
861
|
-
* @this Blockly.Block
|
|
862
952
|
*/
|
|
863
|
-
init: function () {
|
|
953
|
+
init: function (this: ProcedurePrototypeBlock) {
|
|
864
954
|
this.jsonInit({
|
|
865
955
|
extensions: ["colours_more", "shape_statement"],
|
|
866
956
|
});
|
|
@@ -894,9 +984,8 @@ Blockly.Blocks["procedures_prototype"] = {
|
|
|
894
984
|
Blockly.Blocks["procedures_declaration"] = {
|
|
895
985
|
/**
|
|
896
986
|
* The root block in the procedure declaration editor.
|
|
897
|
-
* @this Blockly.Block
|
|
898
987
|
*/
|
|
899
|
-
init: function () {
|
|
988
|
+
init: function (this: ProcedureDeclarationBlock) {
|
|
900
989
|
this.jsonInit({
|
|
901
990
|
extensions: ["colours_more", "shape_statement"],
|
|
902
991
|
});
|
|
@@ -937,7 +1026,7 @@ Blockly.Blocks["procedures_declaration"] = {
|
|
|
937
1026
|
};
|
|
938
1027
|
|
|
939
1028
|
Blockly.Blocks["argument_reporter_boolean"] = {
|
|
940
|
-
init: function () {
|
|
1029
|
+
init: function (this: Blockly.BlockSvg) {
|
|
941
1030
|
this.jsonInit({
|
|
942
1031
|
message0: " %1",
|
|
943
1032
|
args0: [
|
|
@@ -954,7 +1043,7 @@ Blockly.Blocks["argument_reporter_boolean"] = {
|
|
|
954
1043
|
};
|
|
955
1044
|
|
|
956
1045
|
Blockly.Blocks["argument_reporter_string_number"] = {
|
|
957
|
-
init: function () {
|
|
1046
|
+
init: function (this: Blockly.BlockSvg) {
|
|
958
1047
|
this.jsonInit({
|
|
959
1048
|
message0: " %1",
|
|
960
1049
|
args0: [
|
|
@@ -971,7 +1060,7 @@ Blockly.Blocks["argument_reporter_string_number"] = {
|
|
|
971
1060
|
};
|
|
972
1061
|
|
|
973
1062
|
Blockly.Blocks["argument_editor_boolean"] = {
|
|
974
|
-
init: function () {
|
|
1063
|
+
init: function (this: ProcedureArgumentEditorBlock) {
|
|
975
1064
|
this.jsonInit({
|
|
976
1065
|
message0: " %1",
|
|
977
1066
|
args0: [
|
|
@@ -990,7 +1079,7 @@ Blockly.Blocks["argument_editor_boolean"] = {
|
|
|
990
1079
|
};
|
|
991
1080
|
|
|
992
1081
|
Blockly.Blocks["argument_editor_string_number"] = {
|
|
993
|
-
init: function () {
|
|
1082
|
+
init: function (this: ProcedureArgumentEditorBlock) {
|
|
994
1083
|
this.jsonInit({
|
|
995
1084
|
message0: " %1",
|
|
996
1085
|
args0: [
|
|
@@ -1007,3 +1096,63 @@ Blockly.Blocks["argument_editor_string_number"] = {
|
|
|
1007
1096
|
this.removeFieldCallback = removeArgumentCallback_.bind(this);
|
|
1008
1097
|
},
|
|
1009
1098
|
};
|
|
1099
|
+
|
|
1100
|
+
interface ProcedureBlock extends Blockly.BlockSvg {
|
|
1101
|
+
procCode_: string;
|
|
1102
|
+
argumentIds_: string[];
|
|
1103
|
+
warp_: boolean;
|
|
1104
|
+
getProcCode: () => string;
|
|
1105
|
+
removeAllInputs_: () => void;
|
|
1106
|
+
disconnectOldBlocks_: () => ConnectionMap;
|
|
1107
|
+
deleteShadows_: (connectionMap: ConnectionMap) => void;
|
|
1108
|
+
createAllInputs_: (connectionMap: ConnectionMap) => void;
|
|
1109
|
+
updateDisplay_: () => void;
|
|
1110
|
+
populateArgument_: (
|
|
1111
|
+
type: ArgumentType,
|
|
1112
|
+
index: number,
|
|
1113
|
+
connectionMap: ConnectionMap,
|
|
1114
|
+
id: string,
|
|
1115
|
+
input: Blockly.Input
|
|
1116
|
+
) => void;
|
|
1117
|
+
addProcedureLabel_: (text: string) => void;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
export interface ProcedureDeclarationBlock extends ProcedureBlock {
|
|
1121
|
+
displayNames_: string[];
|
|
1122
|
+
argumentDefaults_: string[];
|
|
1123
|
+
removeFieldCallback: (field: Blockly.Field) => void;
|
|
1124
|
+
createArgumentEditor_: (
|
|
1125
|
+
argumentType: ArgumentType,
|
|
1126
|
+
displayName: string
|
|
1127
|
+
) => Blockly.BlockSvg;
|
|
1128
|
+
focusLastEditor_: () => void;
|
|
1129
|
+
getWarp: () => boolean;
|
|
1130
|
+
setWarp: (warp: boolean) => void;
|
|
1131
|
+
addLabelExternal: () => void;
|
|
1132
|
+
addBooleanExternal: () => void;
|
|
1133
|
+
addStringNumberExternal: () => void;
|
|
1134
|
+
onChangeFn: () => void;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
interface ProcedureCallBlock extends ProcedureBlock {
|
|
1138
|
+
generateShadows_: boolean;
|
|
1139
|
+
attachShadow_: (input: Blockly.Input, argumentType: ArgumentType) => void;
|
|
1140
|
+
buildShadowDom_: (type: ArgumentType) => Element;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
interface ProcedurePrototypeBlock extends ProcedureBlock {
|
|
1144
|
+
displayNames_: string[];
|
|
1145
|
+
argumentDefaults_: string[];
|
|
1146
|
+
createArgumentReporter_: (
|
|
1147
|
+
argumentType: ArgumentType,
|
|
1148
|
+
displayName: string
|
|
1149
|
+
) => Blockly.BlockSvg;
|
|
1150
|
+
updateArgumentReporterNames_: (
|
|
1151
|
+
prevArgIds: string[],
|
|
1152
|
+
prevDisplayNames: string[]
|
|
1153
|
+
) => void;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
interface ProcedureArgumentEditorBlock extends Blockly.BlockSvg {
|
|
1157
|
+
removeFieldCallback: (field: Blockly.Field) => void;
|
|
1158
|
+
}
|