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
|
@@ -26,24 +26,22 @@
|
|
|
26
26
|
* @author fenichel@google.com (Rachel Fenichel)
|
|
27
27
|
*/
|
|
28
28
|
import * as Blockly from "blockly/core";
|
|
29
|
-
import { ScratchProcedures } from "../procedures
|
|
30
|
-
import * as Constants from "../constants
|
|
31
|
-
import { FlyoutCheckboxIcon } from "../flyout_checkbox_icon
|
|
29
|
+
import { ScratchProcedures } from "../procedures";
|
|
30
|
+
import * as Constants from "../constants";
|
|
31
|
+
import { FlyoutCheckboxIcon } from "../flyout_checkbox_icon";
|
|
32
32
|
|
|
33
|
-
const VerticalExtensions = {};
|
|
34
33
|
/**
|
|
35
34
|
* Helper function that generates an extension based on a category name.
|
|
36
35
|
* The generated function will set the block's style based on the category name.
|
|
37
|
-
*
|
|
38
|
-
* @
|
|
39
|
-
*
|
|
36
|
+
*
|
|
37
|
+
* @param category The name of the category to set colours for.
|
|
38
|
+
* @return An extension function that sets colours based on the given category.
|
|
40
39
|
*/
|
|
41
|
-
|
|
40
|
+
const colourHelper = function (category: string): () => void {
|
|
42
41
|
/**
|
|
43
42
|
* Set the block style on this block for the given category.
|
|
44
|
-
* @this {Blockly.Block}
|
|
45
43
|
*/
|
|
46
|
-
return function () {
|
|
44
|
+
return function (this: Blockly.Block) {
|
|
47
45
|
this.setStyle(category);
|
|
48
46
|
};
|
|
49
47
|
};
|
|
@@ -51,18 +49,16 @@ VerticalExtensions.colourHelper = function (category) {
|
|
|
51
49
|
/**
|
|
52
50
|
* Extension to set the colours of a text field, which are all the same.
|
|
53
51
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const COLOUR_TEXTFIELD = function (this: Blockly.Block) {
|
|
53
|
+
colourHelper("textField").apply(this);
|
|
56
54
|
};
|
|
57
55
|
|
|
58
56
|
/**
|
|
59
57
|
* Extension to make a block fit into a stack of statements, regardless of its
|
|
60
58
|
* inputs. That means the block should have a previous connection and a next
|
|
61
59
|
* connection and have inline inputs.
|
|
62
|
-
* @this {Blockly.Block}
|
|
63
|
-
* @readonly
|
|
64
60
|
*/
|
|
65
|
-
|
|
61
|
+
const SHAPE_STATEMENT = function (this: Blockly.Block) {
|
|
66
62
|
this.setInputsInline(true);
|
|
67
63
|
this.setPreviousStatement(true, null);
|
|
68
64
|
this.setNextStatement(true, null);
|
|
@@ -72,10 +68,8 @@ VerticalExtensions.SHAPE_STATEMENT = function () {
|
|
|
72
68
|
* Extension to make a block be shaped as a hat block, regardless of its
|
|
73
69
|
* inputs. That means the block should have a next connection and have inline
|
|
74
70
|
* inputs, but have no previous connection.
|
|
75
|
-
* @this {Blockly.Block}
|
|
76
|
-
* @readonly
|
|
77
71
|
*/
|
|
78
|
-
|
|
72
|
+
const SHAPE_HAT = function (this: Blockly.Block) {
|
|
79
73
|
this.setInputsInline(true);
|
|
80
74
|
this.setNextStatement(true, null);
|
|
81
75
|
this.hat = "cap";
|
|
@@ -84,10 +78,8 @@ VerticalExtensions.SHAPE_HAT = function () {
|
|
|
84
78
|
/**
|
|
85
79
|
* Extension to make a block be shaped as a bowler hat block, with rounded
|
|
86
80
|
* corners on both sides and no indentation for statement blocks.
|
|
87
|
-
* @this {Blockly.Block}
|
|
88
|
-
* @readonly
|
|
89
81
|
*/
|
|
90
|
-
|
|
82
|
+
const SHAPE_BOWLER_HAT = function (this: Blockly.Block) {
|
|
91
83
|
this.setInputsInline(true);
|
|
92
84
|
this.setNextStatement(true, null);
|
|
93
85
|
this.hat = "bowler";
|
|
@@ -97,10 +89,8 @@ VerticalExtensions.SHAPE_BOWLER_HAT = function () {
|
|
|
97
89
|
* Extension to make a block be shaped as an end block, regardless of its
|
|
98
90
|
* inputs. That means the block should have a previous connection and have
|
|
99
91
|
* inline inputs, but have no next connection.
|
|
100
|
-
* @this {Blockly.Block}
|
|
101
|
-
* @readonly
|
|
102
92
|
*/
|
|
103
|
-
|
|
93
|
+
const SHAPE_END = function (this: Blockly.Block) {
|
|
104
94
|
this.setInputsInline(true);
|
|
105
95
|
this.setPreviousStatement(true, null);
|
|
106
96
|
};
|
|
@@ -109,10 +99,8 @@ VerticalExtensions.SHAPE_END = function () {
|
|
|
109
99
|
* Extension to make represent a number reporter in Scratch-Blocks.
|
|
110
100
|
* That means the block has inline inputs, a round output shape, and a 'Number'
|
|
111
101
|
* output type.
|
|
112
|
-
* @this {Blockly.Block}
|
|
113
|
-
* @readonly
|
|
114
102
|
*/
|
|
115
|
-
|
|
103
|
+
const OUTPUT_NUMBER = function (this: Blockly.Block) {
|
|
116
104
|
this.setInputsInline(true);
|
|
117
105
|
this.setOutputShape(Constants.OUTPUT_SHAPE_ROUND);
|
|
118
106
|
this.setOutput(true, "Number");
|
|
@@ -122,10 +110,8 @@ VerticalExtensions.OUTPUT_NUMBER = function () {
|
|
|
122
110
|
* Extension to make represent a string reporter in Scratch-Blocks.
|
|
123
111
|
* That means the block has inline inputs, a round output shape, and a 'String'
|
|
124
112
|
* output type.
|
|
125
|
-
* @this {Blockly.Block}
|
|
126
|
-
* @readonly
|
|
127
113
|
*/
|
|
128
|
-
|
|
114
|
+
const OUTPUT_STRING = function (this: Blockly.Block) {
|
|
129
115
|
this.setInputsInline(true);
|
|
130
116
|
this.setOutputShape(Constants.OUTPUT_SHAPE_ROUND);
|
|
131
117
|
this.setOutput(true, "String");
|
|
@@ -135,10 +121,8 @@ VerticalExtensions.OUTPUT_STRING = function () {
|
|
|
135
121
|
* Extension to make represent a boolean reporter in Scratch-Blocks.
|
|
136
122
|
* That means the block has inline inputs, a round output shape, and a 'Boolean'
|
|
137
123
|
* output type.
|
|
138
|
-
* @this {Blockly.Block}
|
|
139
|
-
* @readonly
|
|
140
124
|
*/
|
|
141
|
-
|
|
125
|
+
const OUTPUT_BOOLEAN = function (this: Blockly.Block) {
|
|
142
126
|
this.setInputsInline(true);
|
|
143
127
|
this.setOutputShape(Constants.OUTPUT_SHAPE_HEXAGONAL);
|
|
144
128
|
this.setOutput(true, "Boolean");
|
|
@@ -149,34 +133,35 @@ VerticalExtensions.OUTPUT_BOOLEAN = function () {
|
|
|
149
133
|
* value in a dropdown. These blocks also have an accompanying checkbox in the
|
|
150
134
|
* flyout to toggle display of their current value in a chip on the stage.
|
|
151
135
|
*/
|
|
152
|
-
|
|
136
|
+
const MONITOR_BLOCK = function (this: Blockly.BlockSvg) {
|
|
153
137
|
this.addIcon(new FlyoutCheckboxIcon(this));
|
|
154
|
-
this.checkboxInFlyout = true;
|
|
138
|
+
(this as any).checkboxInFlyout = true;
|
|
155
139
|
};
|
|
156
140
|
|
|
157
141
|
/**
|
|
158
142
|
* Mixin to add a context menu for a procedure definition block.
|
|
159
143
|
* It adds the "edit" option and removes the "duplicate" option.
|
|
160
|
-
* @mixin
|
|
161
|
-
* @augments Blockly.Block
|
|
162
|
-
* @package
|
|
163
|
-
* @readonly
|
|
164
144
|
*/
|
|
165
|
-
|
|
145
|
+
const PROCEDURE_DEF_CONTEXTMENU = function (this: Blockly.Block) {
|
|
166
146
|
/**
|
|
167
147
|
* Add the "edit" option and removes the "duplicate" option from the context
|
|
168
148
|
* menu.
|
|
169
|
-
*
|
|
170
|
-
* @
|
|
149
|
+
*
|
|
150
|
+
* @param menuOptions List of menu options to edit.
|
|
171
151
|
*/
|
|
172
152
|
this.mixin(
|
|
173
153
|
{
|
|
174
|
-
customContextMenu: function (
|
|
154
|
+
customContextMenu: function (
|
|
155
|
+
menuOptions: Array<
|
|
156
|
+
| Blockly.ContextMenuRegistry.ContextMenuOption
|
|
157
|
+
| Blockly.ContextMenuRegistry.LegacyContextMenuOption
|
|
158
|
+
>
|
|
159
|
+
) {
|
|
175
160
|
// Add the edit option at the end.
|
|
176
161
|
menuOptions.push(ScratchProcedures.makeEditOption(this));
|
|
177
162
|
|
|
178
163
|
// Find and remove the duplicate option
|
|
179
|
-
for (
|
|
164
|
+
for (let i = 0, option; (option = menuOptions[i]); i++) {
|
|
180
165
|
if (option.text == Blockly.Msg.DUPLICATE) {
|
|
181
166
|
menuOptions.splice(i, 1);
|
|
182
167
|
break;
|
|
@@ -184,11 +169,11 @@ VerticalExtensions.PROCEDURE_DEF_CONTEXTMENU = function () {
|
|
|
184
169
|
}
|
|
185
170
|
},
|
|
186
171
|
checkAndDelete: function () {
|
|
187
|
-
|
|
172
|
+
const input = this.getInput("custom_block");
|
|
188
173
|
// this is the root block, not the shadow block.
|
|
189
174
|
if (input && input.connection && input.connection.targetBlock()) {
|
|
190
|
-
|
|
191
|
-
|
|
175
|
+
const procCode = input.connection.targetBlock().getProcCode();
|
|
176
|
+
const didDelete = ScratchProcedures.deleteProcedureDefCallback(
|
|
192
177
|
procCode,
|
|
193
178
|
this
|
|
194
179
|
);
|
|
@@ -208,29 +193,35 @@ VerticalExtensions.PROCEDURE_DEF_CONTEXTMENU = function () {
|
|
|
208
193
|
* @mixin
|
|
209
194
|
* @augments Blockly.Block
|
|
210
195
|
* @package
|
|
211
|
-
* @readonly
|
|
212
196
|
*/
|
|
213
|
-
|
|
197
|
+
const PROCEDURE_CALL_CONTEXTMENU = {
|
|
214
198
|
/**
|
|
215
199
|
* Add the "edit" option to the context menu.
|
|
200
|
+
*
|
|
216
201
|
* @todo Add "go to definition" option once implemented.
|
|
217
|
-
* @param
|
|
218
|
-
* @this Blockly.Block
|
|
202
|
+
* @param menuOptions List of menu options to edit.
|
|
219
203
|
*/
|
|
220
|
-
customContextMenu: function (
|
|
204
|
+
customContextMenu: function (
|
|
205
|
+
this: Blockly.BlockSvg,
|
|
206
|
+
menuOptions: Array<
|
|
207
|
+
| Blockly.ContextMenuRegistry.ContextMenuOption
|
|
208
|
+
| Blockly.ContextMenuRegistry.LegacyContextMenuOption
|
|
209
|
+
>
|
|
210
|
+
) {
|
|
221
211
|
menuOptions.push(ScratchProcedures.makeEditOption(this));
|
|
222
212
|
},
|
|
223
213
|
};
|
|
224
214
|
|
|
225
|
-
|
|
226
|
-
this.isScratchExtension = true;
|
|
215
|
+
const SCRATCH_EXTENSION = function (this: Blockly.Block) {
|
|
216
|
+
(this as any).isScratchExtension = true;
|
|
227
217
|
};
|
|
218
|
+
|
|
228
219
|
/**
|
|
229
220
|
* Register all extensions for scratch-blocks.
|
|
230
221
|
* @package
|
|
231
222
|
*/
|
|
232
|
-
|
|
233
|
-
|
|
223
|
+
function registerAll() {
|
|
224
|
+
const categoryNames = [
|
|
234
225
|
"control",
|
|
235
226
|
"data",
|
|
236
227
|
"data_lists",
|
|
@@ -244,66 +235,38 @@ VerticalExtensions.registerAll = function () {
|
|
|
244
235
|
"more",
|
|
245
236
|
];
|
|
246
237
|
// Register functions for all category colours.
|
|
247
|
-
for (
|
|
248
|
-
|
|
249
|
-
Blockly.Extensions.register(
|
|
250
|
-
"colours_" + name,
|
|
251
|
-
VerticalExtensions.colourHelper(name)
|
|
252
|
-
);
|
|
238
|
+
for (const name of categoryNames) {
|
|
239
|
+
Blockly.Extensions.register("colours_" + name, colourHelper(name));
|
|
253
240
|
}
|
|
254
241
|
|
|
255
242
|
// Text fields transcend categories.
|
|
256
|
-
Blockly.Extensions.register(
|
|
257
|
-
"colours_textfield",
|
|
258
|
-
VerticalExtensions.COLOUR_TEXTFIELD
|
|
259
|
-
);
|
|
243
|
+
Blockly.Extensions.register("colours_textfield", COLOUR_TEXTFIELD);
|
|
260
244
|
|
|
261
245
|
// Register extensions for common block shapes.
|
|
262
|
-
Blockly.Extensions.register(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
);
|
|
266
|
-
Blockly.Extensions.register("shape_hat", VerticalExtensions.SHAPE_HAT);
|
|
267
|
-
Blockly.Extensions.register(
|
|
268
|
-
"shape_bowler_hat",
|
|
269
|
-
VerticalExtensions.SHAPE_BOWLER_HAT
|
|
270
|
-
);
|
|
271
|
-
Blockly.Extensions.register("shape_end", VerticalExtensions.SHAPE_END);
|
|
246
|
+
Blockly.Extensions.register("shape_statement", SHAPE_STATEMENT);
|
|
247
|
+
Blockly.Extensions.register("shape_hat", SHAPE_HAT);
|
|
248
|
+
Blockly.Extensions.register("shape_bowler_hat", SHAPE_BOWLER_HAT);
|
|
249
|
+
Blockly.Extensions.register("shape_end", SHAPE_END);
|
|
272
250
|
|
|
273
251
|
// Output shapes and types are related.
|
|
274
|
-
Blockly.Extensions.register(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
);
|
|
278
|
-
Blockly.Extensions.register(
|
|
279
|
-
"output_string",
|
|
280
|
-
VerticalExtensions.OUTPUT_STRING
|
|
281
|
-
);
|
|
282
|
-
Blockly.Extensions.register(
|
|
283
|
-
"output_boolean",
|
|
284
|
-
VerticalExtensions.OUTPUT_BOOLEAN
|
|
285
|
-
);
|
|
252
|
+
Blockly.Extensions.register("output_number", OUTPUT_NUMBER);
|
|
253
|
+
Blockly.Extensions.register("output_string", OUTPUT_STRING);
|
|
254
|
+
Blockly.Extensions.register("output_boolean", OUTPUT_BOOLEAN);
|
|
286
255
|
|
|
287
256
|
// Custom procedures have interesting context menus.
|
|
288
257
|
Blockly.Extensions.register(
|
|
289
258
|
"procedure_def_contextmenu",
|
|
290
|
-
|
|
259
|
+
PROCEDURE_DEF_CONTEXTMENU
|
|
291
260
|
);
|
|
292
261
|
Blockly.Extensions.registerMixin(
|
|
293
262
|
"procedure_call_contextmenu",
|
|
294
|
-
|
|
263
|
+
PROCEDURE_CALL_CONTEXTMENU
|
|
295
264
|
);
|
|
296
265
|
|
|
297
266
|
// Extension blocks have slightly different block rendering.
|
|
298
|
-
Blockly.Extensions.register(
|
|
299
|
-
"scratch_extension",
|
|
300
|
-
VerticalExtensions.SCRATCH_EXTENSION
|
|
301
|
-
);
|
|
267
|
+
Blockly.Extensions.register("scratch_extension", SCRATCH_EXTENSION);
|
|
302
268
|
|
|
303
|
-
Blockly.Extensions.register(
|
|
304
|
-
|
|
305
|
-
VerticalExtensions.MONITOR_BLOCK
|
|
306
|
-
);
|
|
307
|
-
};
|
|
269
|
+
Blockly.Extensions.register("monitor_block", MONITOR_BLOCK);
|
|
270
|
+
}
|
|
308
271
|
|
|
309
|
-
|
|
272
|
+
registerAll();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2024 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as Blockly from "blockly/core";
|
|
8
|
+
import { ContinuousFlyout } from "@blockly/continuous-toolbox";
|
|
9
|
+
import { CheckboxBubble } from "./checkbox_bubble";
|
|
10
|
+
import { StatusIndicatorLabel } from "./status_indicator_label";
|
|
11
|
+
import { STATUS_INDICATOR_LABEL_TYPE } from "./status_indicator_label_flyout_inflater";
|
|
12
|
+
|
|
13
|
+
export class CheckableContinuousFlyout extends ContinuousFlyout {
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new CheckableContinuousFlyout.
|
|
16
|
+
*
|
|
17
|
+
* @param workspaceOptions Configuration options for the flyout workspace.
|
|
18
|
+
*/
|
|
19
|
+
constructor(workspaceOptions: Blockly.Options) {
|
|
20
|
+
workspaceOptions.modalInputs = false;
|
|
21
|
+
super(workspaceOptions);
|
|
22
|
+
this.tabWidth_ = 0;
|
|
23
|
+
this.MARGIN = 12;
|
|
24
|
+
this.GAP_Y = 12;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Serializes a block to JSON in order to copy it to the main workspace.
|
|
29
|
+
*
|
|
30
|
+
* @param block The block to serialize.
|
|
31
|
+
* @returns A JSON representation of the block.
|
|
32
|
+
*/
|
|
33
|
+
protected serializeBlock(block: Blockly.BlockSvg) {
|
|
34
|
+
const json = super.serializeBlock(block);
|
|
35
|
+
// Delete the serialized block's ID so that a new one is generated when it is
|
|
36
|
+
// placed on the workspace. Otherwise, the block on the workspace may be
|
|
37
|
+
// indistinguishable from the one in the flyout, which can cause reporter blocks
|
|
38
|
+
// to have their value dropdown shown in the wrong place.
|
|
39
|
+
delete json.id;
|
|
40
|
+
return json;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Set the state of a checkbox by block ID.
|
|
45
|
+
*
|
|
46
|
+
* @param blockId ID of the block whose checkbox should be set
|
|
47
|
+
* @param value Value to set the checkbox to.
|
|
48
|
+
*/
|
|
49
|
+
setCheckboxState(blockId: string, value: boolean) {
|
|
50
|
+
this.getWorkspace()
|
|
51
|
+
.getBlockById(blockId)
|
|
52
|
+
?.getIcon("checkbox")
|
|
53
|
+
?.setChecked(value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getFlyoutScale() {
|
|
57
|
+
return 0.675;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getWidth() {
|
|
61
|
+
return 250;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected reflowInternal_() {
|
|
65
|
+
super.reflowInternal_();
|
|
66
|
+
|
|
67
|
+
if (this.RTL) {
|
|
68
|
+
// The parent implementation assumes that the flyout grows to fit its
|
|
69
|
+
// contents, and adjusts blocks in RTL mode accordingly. In Scratch, the
|
|
70
|
+
// flyout width is fixed (and blocks may exceed it), so re-adjust blocks
|
|
71
|
+
// accordingly based on the actual fixed width.
|
|
72
|
+
for (const item of this.getContents()) {
|
|
73
|
+
const oldX = item.getElement().getBoundingRectangle().left;
|
|
74
|
+
let newX =
|
|
75
|
+
this.getWidth() / this.workspace_.scale -
|
|
76
|
+
item.getElement().getBoundingRectangle().getWidth() -
|
|
77
|
+
this.MARGIN;
|
|
78
|
+
if (
|
|
79
|
+
"checkboxInFlyout" in item.getElement() &&
|
|
80
|
+
item.getElement().checkboxInFlyout
|
|
81
|
+
) {
|
|
82
|
+
newX -= CheckboxBubble.CHECKBOX_SIZE + CheckboxBubble.CHECKBOX_MARGIN;
|
|
83
|
+
}
|
|
84
|
+
item.getElement().moveBy(newX - oldX, 0);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Validates that the given toolbox item represents a label.
|
|
91
|
+
*
|
|
92
|
+
* @param item The toolbox item to check.
|
|
93
|
+
* @returns True if the item represents a label in the flyout.
|
|
94
|
+
*/
|
|
95
|
+
protected toolboxItemIsLabel(item: Blockly.FlyoutItem) {
|
|
96
|
+
return (
|
|
97
|
+
item.getType() === STATUS_INDICATOR_LABEL_TYPE ||
|
|
98
|
+
super.toolboxItemIsLabel(item)
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Updates the state of status indicators for hardware-based extensions.
|
|
104
|
+
*/
|
|
105
|
+
refreshStatusButtons() {
|
|
106
|
+
for (const item of this.contents) {
|
|
107
|
+
if (item.element instanceof StatusIndicatorLabel) {
|
|
108
|
+
item.element.refreshStatus();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -8,30 +8,24 @@ import * as Blockly from "blockly/core";
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* A checkbox shown next to reporter blocks in the flyout.
|
|
11
|
-
* @implements {Blockly.IBubble}
|
|
12
|
-
* @implements {Blockly.IRenderedElement}
|
|
13
11
|
*/
|
|
14
|
-
export class CheckboxBubble
|
|
12
|
+
export class CheckboxBubble
|
|
13
|
+
implements Blockly.IBubble, Blockly.IRenderedElement
|
|
14
|
+
{
|
|
15
15
|
/**
|
|
16
16
|
* Size of a checkbox next to a variable reporter.
|
|
17
|
-
* @type {number}
|
|
18
|
-
* @const
|
|
19
17
|
*/
|
|
20
|
-
static CHECKBOX_SIZE = 25;
|
|
18
|
+
static readonly CHECKBOX_SIZE = 25;
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
21
|
* Amount of touchable padding around reporter checkboxes.
|
|
24
|
-
* @type {number}
|
|
25
|
-
* @const
|
|
26
22
|
*/
|
|
27
|
-
static CHECKBOX_TOUCH_PADDING = 12;
|
|
23
|
+
static readonly CHECKBOX_TOUCH_PADDING = 12;
|
|
28
24
|
|
|
29
25
|
/**
|
|
30
26
|
* SVG path data for checkmark in checkbox.
|
|
31
|
-
* @type {string}
|
|
32
|
-
* @const
|
|
33
27
|
*/
|
|
34
|
-
static CHECKMARK_PATH =
|
|
28
|
+
static readonly CHECKMARK_PATH =
|
|
35
29
|
"M" +
|
|
36
30
|
CheckboxBubble.CHECKBOX_SIZE / 4 +
|
|
37
31
|
" " +
|
|
@@ -46,59 +40,48 @@ export class CheckboxBubble {
|
|
|
46
40
|
CheckboxBubble.CHECKBOX_SIZE / 3;
|
|
47
41
|
|
|
48
42
|
/**
|
|
49
|
-
* Size of the checkbox corner radius
|
|
50
|
-
* @type {number}
|
|
51
|
-
* @const
|
|
43
|
+
* Size of the checkbox corner radius.
|
|
52
44
|
*/
|
|
53
|
-
static CHECKBOX_CORNER_RADIUS = 5;
|
|
45
|
+
static readonly CHECKBOX_CORNER_RADIUS = 5;
|
|
54
46
|
|
|
55
47
|
/**
|
|
56
|
-
*
|
|
57
|
-
* @const
|
|
48
|
+
* The margin around a checkbox.
|
|
58
49
|
*/
|
|
59
|
-
static CHECKBOX_MARGIN = 12;
|
|
50
|
+
static readonly CHECKBOX_MARGIN = 12;
|
|
60
51
|
|
|
61
52
|
/**
|
|
62
53
|
* Total additional width of a row that contains a checkbox.
|
|
63
|
-
* @type {number}
|
|
64
|
-
* @const
|
|
65
54
|
*/
|
|
66
|
-
static CHECKBOX_SPACE_X =
|
|
55
|
+
static readonly CHECKBOX_SPACE_X =
|
|
67
56
|
CheckboxBubble.CHECKBOX_SIZE + 2 * CheckboxBubble.CHECKBOX_MARGIN;
|
|
68
57
|
|
|
69
58
|
/**
|
|
70
59
|
* Root SVG element for this bubble.
|
|
71
|
-
* @type {!SVGGElement}
|
|
72
60
|
*/
|
|
73
|
-
svgRoot;
|
|
61
|
+
svgRoot: SVGGElement;
|
|
74
62
|
|
|
75
63
|
/**
|
|
76
64
|
* Identifier for click handler, to allow unregistering during disposal.
|
|
77
|
-
* @type {!Blockly.browserEvents.Data}
|
|
78
65
|
*/
|
|
79
|
-
clickListener;
|
|
66
|
+
clickListener: Blockly.browserEvents.Data;
|
|
80
67
|
|
|
81
68
|
/**
|
|
82
69
|
* Whether or not this bubble is displayed as checked. Note that the source of
|
|
83
70
|
* truth is the Scratch VM.
|
|
84
|
-
* @type {boolean}
|
|
85
71
|
*/
|
|
86
72
|
checked = false;
|
|
87
73
|
|
|
88
74
|
/**
|
|
89
75
|
* The location of this bubble in workspace coordinates.
|
|
90
|
-
* @type {!Blockly.utils.Coordinate}
|
|
91
76
|
*/
|
|
92
77
|
location = new Blockly.utils.Coordinate(0, 0);
|
|
93
78
|
|
|
94
79
|
/**
|
|
95
80
|
* Creates a new flyout checkbox bubble.
|
|
96
81
|
*
|
|
97
|
-
* @param
|
|
98
|
-
* associated with.
|
|
82
|
+
* @param sourceBlock The block this bubble should be associated with.
|
|
99
83
|
*/
|
|
100
|
-
constructor(sourceBlock) {
|
|
101
|
-
this.sourceBlock = sourceBlock;
|
|
84
|
+
constructor(private sourceBlock: Blockly.BlockSvg) {
|
|
102
85
|
this.svgRoot = Blockly.utils.dom.createSvgElement(
|
|
103
86
|
Blockly.utils.Svg.G,
|
|
104
87
|
{},
|
|
@@ -149,9 +132,9 @@ export class CheckboxBubble {
|
|
|
149
132
|
|
|
150
133
|
this.clickListener = Blockly.browserEvents.bind(
|
|
151
134
|
this.svgRoot,
|
|
152
|
-
"
|
|
135
|
+
"pointerdown",
|
|
153
136
|
null,
|
|
154
|
-
(event) => {
|
|
137
|
+
(event: PointerEvent) => {
|
|
155
138
|
this.setChecked(!this.checked);
|
|
156
139
|
event.stopPropagation();
|
|
157
140
|
event.preventDefault();
|
|
@@ -163,9 +146,9 @@ export class CheckboxBubble {
|
|
|
163
146
|
/**
|
|
164
147
|
* Sets whether or not this bubble should be displayed in the checked state.
|
|
165
148
|
*
|
|
166
|
-
* @param
|
|
149
|
+
* @param checked True if this bubble should be checked.
|
|
167
150
|
*/
|
|
168
|
-
setChecked(checked) {
|
|
151
|
+
setChecked(checked: boolean) {
|
|
169
152
|
if (checked === this.checked) return;
|
|
170
153
|
|
|
171
154
|
this.checked = checked;
|
|
@@ -191,28 +174,28 @@ export class CheckboxBubble {
|
|
|
191
174
|
*
|
|
192
175
|
* This method is patched by scratch-gui to query the VM state.
|
|
193
176
|
*
|
|
194
|
-
* @param
|
|
195
|
-
* @returns
|
|
177
|
+
* @param blockId The ID of the block in question.
|
|
178
|
+
* @returns True if the block's checkbox should be checked.
|
|
196
179
|
*/
|
|
197
|
-
isChecked(blockId) {
|
|
180
|
+
isChecked(blockId: string): boolean {
|
|
198
181
|
return false;
|
|
199
182
|
}
|
|
200
183
|
|
|
201
184
|
/**
|
|
202
185
|
* Returns whether this bubble is movable by the user.
|
|
203
186
|
*
|
|
204
|
-
* @returns
|
|
187
|
+
* @returns Always returns false.
|
|
205
188
|
*/
|
|
206
|
-
isMovable() {
|
|
189
|
+
isMovable(): boolean {
|
|
207
190
|
return false;
|
|
208
191
|
}
|
|
209
192
|
|
|
210
193
|
/**
|
|
211
194
|
* Returns the root SVG element for this bubble.
|
|
212
195
|
*
|
|
213
|
-
* @returns
|
|
196
|
+
* @returns The root SVG element.
|
|
214
197
|
*/
|
|
215
|
-
getSvgRoot() {
|
|
198
|
+
getSvgRoot(): SVGGElement {
|
|
216
199
|
return this.svgRoot;
|
|
217
200
|
}
|
|
218
201
|
|
|
@@ -220,25 +203,24 @@ export class CheckboxBubble {
|
|
|
220
203
|
* Recalculates this bubble's location, keeping it adjacent to its block.
|
|
221
204
|
*/
|
|
222
205
|
updateLocation() {
|
|
223
|
-
const
|
|
224
|
-
const blockBounds = this.sourceBlock.getHeightWidth();
|
|
206
|
+
const bounds = this.sourceBlock.getBoundingRectangle();
|
|
225
207
|
const x = this.sourceBlock.workspace.RTL
|
|
226
|
-
?
|
|
227
|
-
:
|
|
208
|
+
? bounds.right + CheckboxBubble.CHECKBOX_MARGIN
|
|
209
|
+
: bounds.left -
|
|
228
210
|
CheckboxBubble.CHECKBOX_MARGIN -
|
|
229
211
|
CheckboxBubble.CHECKBOX_SIZE;
|
|
230
212
|
const y =
|
|
231
|
-
|
|
213
|
+
bounds.top + (bounds.getHeight() - CheckboxBubble.CHECKBOX_SIZE) / 2;
|
|
232
214
|
this.moveTo(x, y);
|
|
233
215
|
}
|
|
234
216
|
|
|
235
217
|
/**
|
|
236
218
|
* Moves this bubble to the specified location.
|
|
237
219
|
*
|
|
238
|
-
* @param
|
|
239
|
-
* @param
|
|
220
|
+
* @param x The location on the X axis to move to.
|
|
221
|
+
* @param y The location on the Y axis to move to.
|
|
240
222
|
*/
|
|
241
|
-
moveTo(x, y) {
|
|
223
|
+
moveTo(x: number, y: number) {
|
|
242
224
|
this.location.x = x;
|
|
243
225
|
this.location.y = y;
|
|
244
226
|
this.svgRoot.setAttribute("transform", `translate(${x}, ${y})`);
|
|
@@ -247,9 +229,9 @@ export class CheckboxBubble {
|
|
|
247
229
|
/**
|
|
248
230
|
* Returns this bubble's location in workspace coordinates.
|
|
249
231
|
*
|
|
250
|
-
* @returns
|
|
232
|
+
* @returns The bubble's location.
|
|
251
233
|
*/
|
|
252
|
-
getRelativeToSurfaceXY() {
|
|
234
|
+
getRelativeToSurfaceXY(): Blockly.utils.Coordinate {
|
|
253
235
|
return this.location;
|
|
254
236
|
}
|
|
255
237
|
|
|
@@ -266,17 +248,17 @@ export class CheckboxBubble {
|
|
|
266
248
|
// to its block and is not draggable by the user.
|
|
267
249
|
showContextMenu() {}
|
|
268
250
|
|
|
269
|
-
setDragging(dragging) {}
|
|
251
|
+
setDragging(dragging: boolean) {}
|
|
270
252
|
|
|
271
|
-
startDrag(event) {}
|
|
253
|
+
startDrag(event: PointerEvent) {}
|
|
272
254
|
|
|
273
|
-
drag(newLocation, event) {}
|
|
255
|
+
drag(newLocation: Blockly.utils.Coordinate, event: PointerEvent) {}
|
|
274
256
|
|
|
275
|
-
moveDuringDrag(newLocation) {}
|
|
257
|
+
moveDuringDrag(newLocation: Blockly.utils.Coordinate) {}
|
|
276
258
|
|
|
277
259
|
endDrag() {}
|
|
278
260
|
|
|
279
261
|
revertDrag() {}
|
|
280
262
|
|
|
281
|
-
setDeleteStyle(enable) {}
|
|
263
|
+
setDeleteStyle(enable: boolean) {}
|
|
282
264
|
}
|
|
@@ -55,10 +55,17 @@ const Colours = {
|
|
|
55
55
|
contextualMenuHover: "rgba(77, 151, 255, .25)",
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Converts the given colours to CSS variables.
|
|
60
|
+
*
|
|
61
|
+
* @param coloursObj A (potentially nested) object whose keys are colour names
|
|
62
|
+
* and values are CSS colours.
|
|
63
|
+
* @param prefix A prefix to prepend to the CSS variables.
|
|
64
|
+
* @returns A string containing CSS variable definitions for the colours.
|
|
65
|
+
*/
|
|
66
|
+
function varify(coloursObj: Object, prefix = "--colour"): string {
|
|
67
|
+
return Object.entries(coloursObj)
|
|
68
|
+
.map(([key, colour]) => {
|
|
62
69
|
if (typeof colour === "string") {
|
|
63
70
|
return `${prefix}-${key}: ${colour};`;
|
|
64
71
|
} else {
|