scratch-blocks 2.0.0-spork.4 → 2.0.0-spork.6
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/.nvmrc +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +6 -0
- package/msg/js/en.js +1 -0
- package/msg/json/en.json +2 -1
- package/msg/messages.js +1 -0
- package/msg/scratch_msgs.js +117 -37
- package/package.json +10 -10
- package/src/blocks/procedures.ts +1 -1
- package/src/blocks/sensing.ts +12 -0
- package/src/checkable_continuous_flyout.ts +4 -0
- package/src/checkbox_bubble.ts +21 -0
- package/src/colours.ts +1 -0
- package/src/context_menu_items.ts +24 -0
- package/src/css.ts +17 -14
- package/src/fields/field_matrix.ts +38 -27
- package/src/fields/field_note.ts +1 -1
- package/src/fields/scratch_field_angle.ts +9 -1
- package/src/fields/scratch_field_variable.ts +9 -8
- package/src/flyout_checkbox_icon.ts +15 -21
- package/src/index.ts +3 -0
- package/src/scratch_block_paster.ts +10 -0
- package/src/{scratch_comment_bubble.js → scratch_comment_bubble.ts} +52 -19
- package/src/scratch_comment_icon.ts +20 -5
- package/src/scratch_continuous_toolbox.ts +16 -0
- package/src/scratch_insertion_marker_previewer.ts +45 -0
- package/src/status_indicator_label_flyout_inflater.ts +4 -4
- package/src/xml.ts +57 -0
- package/CHANGELOG.md +0 -1140
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scratch-blocks",
|
|
3
|
-
"version": "2.0.0-spork.
|
|
3
|
+
"version": "2.0.0-spork.6",
|
|
4
4
|
"description": "Scratch Blocks is a library for building creative computing interfaces.",
|
|
5
5
|
"author": "Massachusetts Institute of Technology",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -17,12 +17,17 @@
|
|
|
17
17
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
18
18
|
"test:lint": "eslint ."
|
|
19
19
|
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@blockly/continuous-toolbox": "^7.0.1",
|
|
22
|
+
"@blockly/field-colour": "^6.0.3",
|
|
23
|
+
"blockly": "^12.3.0-beta.0"
|
|
24
|
+
},
|
|
20
25
|
"devDependencies": {
|
|
21
|
-
"@commitlint/cli": "
|
|
22
|
-
"@commitlint/config-conventional": "
|
|
23
|
-
"eslint": "
|
|
26
|
+
"@commitlint/cli": "17.8.1",
|
|
27
|
+
"@commitlint/config-conventional": "17.8.1",
|
|
28
|
+
"eslint": "4.19.1",
|
|
24
29
|
"husky": "9.1.6",
|
|
25
|
-
"scratch-semantic-release-config": "
|
|
30
|
+
"scratch-semantic-release-config": "4.0.0",
|
|
26
31
|
"semantic-release": "22.0.12",
|
|
27
32
|
"source-map-loader": "^4.0.1",
|
|
28
33
|
"ts-loader": "^9.5.1",
|
|
@@ -31,11 +36,6 @@
|
|
|
31
36
|
"webpack-cli": "^4.10.0",
|
|
32
37
|
"webpack-dev-server": "^4.11.1"
|
|
33
38
|
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@blockly/continuous-toolbox": "^7.0.0-beta.1",
|
|
36
|
-
"@blockly/field-colour": "^4.0.2",
|
|
37
|
-
"blockly": "^12.0.0-beta.1"
|
|
38
|
-
},
|
|
39
39
|
"config": {
|
|
40
40
|
"commitizen": {
|
|
41
41
|
"path": "cz-conventional-changelog"
|
package/src/blocks/procedures.ts
CHANGED
|
@@ -224,7 +224,7 @@ function disconnectOldBlocks_(this: ProcedureBlock): ConnectionMap {
|
|
|
224
224
|
if (input.connection) {
|
|
225
225
|
const target = input.connection.targetBlock() as Blockly.BlockSvg;
|
|
226
226
|
const saveInfo = {
|
|
227
|
-
shadow: input.connection.getShadowDom(),
|
|
227
|
+
shadow: input.connection.getShadowDom(true),
|
|
228
228
|
block: target,
|
|
229
229
|
};
|
|
230
230
|
connectionMap[input.name] = saveInfo;
|
package/src/blocks/sensing.ts
CHANGED
|
@@ -374,6 +374,18 @@ Blockly.Blocks["sensing_dayssince2000"] = {
|
|
|
374
374
|
},
|
|
375
375
|
};
|
|
376
376
|
|
|
377
|
+
Blockly.Blocks["sensing_online"] = {
|
|
378
|
+
/**
|
|
379
|
+
* Block to report whether or not the system is online
|
|
380
|
+
*/
|
|
381
|
+
init: function(this: Blockly.Block) {
|
|
382
|
+
this.jsonInit({
|
|
383
|
+
message0: Blockly.Msg.SENSING_ONLINE,
|
|
384
|
+
extensions: ["colours_sensing", "output_boolean", "monitor_block"],
|
|
385
|
+
});
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
|
|
377
389
|
Blockly.Blocks["sensing_username"] = {
|
|
378
390
|
/**
|
|
379
391
|
* Block to report user's username
|
package/src/checkbox_bubble.ts
CHANGED
|
@@ -243,6 +243,27 @@ export class CheckboxBubble
|
|
|
243
243
|
Blockly.browserEvents.unbind(this.clickListener);
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
+
/** See IFocusableNode.getFocusableElement. */
|
|
247
|
+
getFocusableElement(): HTMLElement | SVGElement {
|
|
248
|
+
return this.svgRoot;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** See IFocusableNode.getFocusableTree. */
|
|
252
|
+
getFocusableTree(): Blockly.IFocusableTree {
|
|
253
|
+
return this.sourceBlock.workspace;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** See IFocusableNode.onNodeFocus. */
|
|
257
|
+
onNodeFocus(): void {}
|
|
258
|
+
|
|
259
|
+
/** See IFocusableNode.onNodeBlur. */
|
|
260
|
+
onNodeBlur(): void {}
|
|
261
|
+
|
|
262
|
+
/** See IFocusableNode.canBeFocused. */
|
|
263
|
+
canBeFocused(): boolean {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
|
|
246
267
|
// These methods are required by the interfaces, but intentionally have no
|
|
247
268
|
// implementation, largely because this bubble's location is fixed relative
|
|
248
269
|
// to its block and is not draggable by the user.
|
package/src/colours.ts
CHANGED
|
@@ -154,3 +154,27 @@ function deleteNext(deleteList: Blockly.BlockSvg[], eventGroup?: string) {
|
|
|
154
154
|
}
|
|
155
155
|
Blockly.Events.setGroup(false);
|
|
156
156
|
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Registers a block duplicate option that duplicates the selected block and
|
|
160
|
+
* all subsequent blocks in the stack.
|
|
161
|
+
*/
|
|
162
|
+
export function registerDuplicateBlock() {
|
|
163
|
+
const original =
|
|
164
|
+
Blockly.ContextMenuRegistry.registry.getItem("blockDuplicate");
|
|
165
|
+
const duplicateOption = {
|
|
166
|
+
displayText: original.displayText,
|
|
167
|
+
preconditionFn: original.preconditionFn,
|
|
168
|
+
callback(scope: Blockly.ContextMenuRegistry.Scope) {
|
|
169
|
+
if (!scope.block) return;
|
|
170
|
+
const data = scope.block.toCopyData(true);
|
|
171
|
+
if (!data) return;
|
|
172
|
+
Blockly.clipboard.paste(data, scope.block.workspace);
|
|
173
|
+
},
|
|
174
|
+
scopeType: original.scopeType,
|
|
175
|
+
id: original.id,
|
|
176
|
+
weight: original.weight,
|
|
177
|
+
};
|
|
178
|
+
Blockly.ContextMenuRegistry.registry.unregister(duplicateOption.id);
|
|
179
|
+
Blockly.ContextMenuRegistry.registry.register(duplicateOption);
|
|
180
|
+
}
|
package/src/css.ts
CHANGED
|
@@ -702,16 +702,16 @@ const styles = `
|
|
|
702
702
|
}
|
|
703
703
|
|
|
704
704
|
.blocklyAngleCenterPoint {
|
|
705
|
-
stroke:
|
|
705
|
+
stroke: var(--colour-text);
|
|
706
706
|
stroke-width: 1;
|
|
707
|
-
fill:
|
|
707
|
+
fill: var(--colour-text);
|
|
708
708
|
}
|
|
709
709
|
|
|
710
710
|
.blocklyAngleDragHandle {
|
|
711
|
-
stroke:
|
|
711
|
+
stroke: var(--colour-text);
|
|
712
712
|
stroke-width: 5;
|
|
713
713
|
stroke-opacity: 0.25;
|
|
714
|
-
fill:
|
|
714
|
+
fill: var(--colour-text);
|
|
715
715
|
cursor: pointer;
|
|
716
716
|
}
|
|
717
717
|
|
|
@@ -720,18 +720,18 @@ const styles = `
|
|
|
720
720
|
}
|
|
721
721
|
|
|
722
722
|
.blocklyAngleMarks {
|
|
723
|
-
stroke:
|
|
723
|
+
stroke: var(--colour-text);
|
|
724
724
|
stroke-width: 1;
|
|
725
725
|
stroke-opacity: 0.5;
|
|
726
726
|
}
|
|
727
727
|
|
|
728
728
|
.blocklyAngleGauge {
|
|
729
|
-
fill:
|
|
729
|
+
fill: var(--colour-text);
|
|
730
730
|
fill-opacity: 0.20;
|
|
731
731
|
}
|
|
732
732
|
|
|
733
733
|
.blocklyAngleLine {
|
|
734
|
-
stroke:
|
|
734
|
+
stroke: var(--colour-text);
|
|
735
735
|
stroke-width: 1;
|
|
736
736
|
stroke-linecap: round;
|
|
737
737
|
pointer-events: none;
|
|
@@ -1011,12 +1011,12 @@ const styles = `
|
|
|
1011
1011
|
z-index: 20000; /* Arbitrary, but some apps depend on it... */
|
|
1012
1012
|
}
|
|
1013
1013
|
|
|
1014
|
-
.blocklyDropDownDiv .blocklyMenu .blocklyMenuItem
|
|
1015
|
-
background: var(--colour-menuHover);
|
|
1014
|
+
.blocklyDropDownDiv .blocklyMenu .blocklyMenuItem.blocklyMenuItemHighlight {
|
|
1015
|
+
background-color: var(--colour-menuHover);
|
|
1016
1016
|
}
|
|
1017
1017
|
|
|
1018
|
-
.blocklyWidgetDiv .blocklyMenu .blocklyMenuItem
|
|
1019
|
-
background: var(--colour-contextualMenuHover);
|
|
1018
|
+
.blocklyWidgetDiv .blocklyMenu .blocklyMenuItem.blocklyMenuItemHighlight {
|
|
1019
|
+
background-color: var(--colour-contextualMenuHover);
|
|
1020
1020
|
}
|
|
1021
1021
|
|
|
1022
1022
|
.blocklyWidgetDiv .blocklyMenu .blocklyMenuItemDisabled.blocklyMenuItem:hover {
|
|
@@ -1168,13 +1168,12 @@ const styles = `
|
|
|
1168
1168
|
color: #4c97ff;
|
|
1169
1169
|
}
|
|
1170
1170
|
.blocklyDropDownDiv .blocklyMenuItem {
|
|
1171
|
-
color: #fff;
|
|
1172
1171
|
font-weight: bold;
|
|
1173
1172
|
min-height: 32px;
|
|
1174
1173
|
padding: 4px 7em 4px 28px;
|
|
1175
1174
|
}
|
|
1176
|
-
.
|
|
1177
|
-
color:
|
|
1175
|
+
.scratch-renderer.blocklyDropDownDiv .blocklyMenuItem .blocklyMenuItemContent {
|
|
1176
|
+
color: var(--colour-text);
|
|
1178
1177
|
}
|
|
1179
1178
|
.blocklyToolboxSelected .blocklyTreeLabel {
|
|
1180
1179
|
color: var(--colour-toolboxText);
|
|
@@ -1198,6 +1197,10 @@ const styles = `
|
|
|
1198
1197
|
stroke: revert-layer;
|
|
1199
1198
|
stroke-width: 1;
|
|
1200
1199
|
}
|
|
1200
|
+
|
|
1201
|
+
.blocklyInsertionMarker > g:not(:last-child) {
|
|
1202
|
+
visibility: hidden;
|
|
1203
|
+
}
|
|
1201
1204
|
`;
|
|
1202
1205
|
|
|
1203
1206
|
Blockly.Css.register(styles);
|
|
@@ -215,7 +215,7 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
215
215
|
this.arrow_.setAttributeNS(
|
|
216
216
|
"http://www.w3.org/1999/xlink",
|
|
217
217
|
"xlink:href",
|
|
218
|
-
|
|
218
|
+
this.getConstants().FIELD_DROPDOWN_SVG_ARROW_DATAURI
|
|
219
219
|
);
|
|
220
220
|
this.arrow_.style.cursor = "default";
|
|
221
221
|
}
|
|
@@ -238,6 +238,25 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
238
238
|
* Show the drop-down menu for editing this field.
|
|
239
239
|
*/
|
|
240
240
|
showEditor_() {
|
|
241
|
+
const sourceBlock = this.getSourceBlock() as Blockly.BlockSvg;
|
|
242
|
+
Blockly.DropDownDiv.setColour(
|
|
243
|
+
sourceBlock.getColour(),
|
|
244
|
+
sourceBlock.getColourTertiary()
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const style = sourceBlock.style;
|
|
248
|
+
if (sourceBlock.isShadow()) {
|
|
249
|
+
this.originalStyle = sourceBlock.getStyleName();
|
|
250
|
+
sourceBlock.setStyle(`${this.originalStyle}_selected`);
|
|
251
|
+
} else if (this.borderRect_) {
|
|
252
|
+
this.borderRect_.setAttribute(
|
|
253
|
+
"fill",
|
|
254
|
+
"colourQuaternary" in style
|
|
255
|
+
? `${style.colourQuaternary}`
|
|
256
|
+
: style.colourTertiary
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
241
260
|
const div = Blockly.DropDownDiv.getContentDiv();
|
|
242
261
|
// Build the SVG DOM.
|
|
243
262
|
const matrixSize =
|
|
@@ -286,23 +305,19 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
286
305
|
// Button to clear matrix
|
|
287
306
|
const clearButtonDiv = document.createElement("div");
|
|
288
307
|
clearButtonDiv.className = "scratchMatrixButtonDiv";
|
|
289
|
-
|
|
308
|
+
|
|
290
309
|
const clearButton = this.createButton_(sourceBlock.getColourSecondary());
|
|
291
310
|
clearButtonDiv.appendChild(clearButton);
|
|
292
311
|
// Button to fill matrix
|
|
293
312
|
const fillButtonDiv = document.createElement("div");
|
|
294
313
|
fillButtonDiv.className = "scratchMatrixButtonDiv";
|
|
295
|
-
const fillButton = this.createButton_("
|
|
314
|
+
const fillButton = this.createButton_("var(--colour-text)");
|
|
296
315
|
fillButtonDiv.appendChild(fillButton);
|
|
297
316
|
|
|
298
317
|
buttonDiv.appendChild(clearButtonDiv);
|
|
299
318
|
buttonDiv.appendChild(fillButtonDiv);
|
|
300
319
|
div.appendChild(buttonDiv);
|
|
301
320
|
|
|
302
|
-
Blockly.DropDownDiv.setColour(
|
|
303
|
-
sourceBlock.getColour(),
|
|
304
|
-
sourceBlock.getColourTertiary()
|
|
305
|
-
);
|
|
306
321
|
Blockly.DropDownDiv.showPositionedByBlock(
|
|
307
322
|
this,
|
|
308
323
|
sourceBlock,
|
|
@@ -328,19 +343,6 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
328
343
|
this.fillMatrix_
|
|
329
344
|
);
|
|
330
345
|
|
|
331
|
-
const style = sourceBlock.style;
|
|
332
|
-
if (sourceBlock.isShadow()) {
|
|
333
|
-
this.originalStyle = sourceBlock.getStyleName();
|
|
334
|
-
sourceBlock.setStyle(`${this.originalStyle}_selected`);
|
|
335
|
-
} else if (this.borderRect_) {
|
|
336
|
-
this.borderRect_.setAttribute(
|
|
337
|
-
"fill",
|
|
338
|
-
"colourQuaternary" in style
|
|
339
|
-
? `${style.colourQuaternary}`
|
|
340
|
-
: style.colourTertiary
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
346
|
// Update the matrix for the current value
|
|
345
347
|
this.updateMatrix_();
|
|
346
348
|
}
|
|
@@ -350,6 +352,7 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
350
352
|
if (sourceBlock.isShadow()) {
|
|
351
353
|
sourceBlock.setStyle(this.originalStyle);
|
|
352
354
|
}
|
|
355
|
+
this.updateMatrix_();
|
|
353
356
|
}
|
|
354
357
|
|
|
355
358
|
/**
|
|
@@ -400,12 +403,16 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
400
403
|
this.fillMatrixNode_(
|
|
401
404
|
this.ledButtons_,
|
|
402
405
|
i,
|
|
406
|
+
sourceBlock.getColourTertiary()
|
|
407
|
+
);
|
|
408
|
+
this.fillMatrixNode_(
|
|
409
|
+
this.ledThumbNodes_,
|
|
410
|
+
i,
|
|
403
411
|
sourceBlock.getColourSecondary()
|
|
404
412
|
);
|
|
405
|
-
this.fillMatrixNode_(this.ledThumbNodes_, i, sourceBlock.getColour());
|
|
406
413
|
} else {
|
|
407
|
-
this.fillMatrixNode_(this.ledButtons_, i, "
|
|
408
|
-
this.fillMatrixNode_(this.ledThumbNodes_, i, "
|
|
414
|
+
this.fillMatrixNode_(this.ledButtons_, i, "var(--colour-text)");
|
|
415
|
+
this.fillMatrixNode_(this.ledThumbNodes_, i, "var(--colour-text)");
|
|
409
416
|
}
|
|
410
417
|
}
|
|
411
418
|
}
|
|
@@ -505,10 +512,14 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
505
512
|
* Unbind mouse move event and clear the paint style.
|
|
506
513
|
*/
|
|
507
514
|
onMouseUp() {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
515
|
+
if (this.matrixMoveWrapper_) {
|
|
516
|
+
Blockly.browserEvents.unbind(this.matrixMoveWrapper_);
|
|
517
|
+
this.matrixMoveWrapper_ = null;
|
|
518
|
+
}
|
|
519
|
+
if (this.matrixReleaseWrapper_) {
|
|
520
|
+
Blockly.browserEvents.unbind(this.matrixReleaseWrapper_);
|
|
521
|
+
this.matrixReleaseWrapper_ = null;
|
|
522
|
+
}
|
|
512
523
|
this.paintStyle_ = null;
|
|
513
524
|
}
|
|
514
525
|
|
package/src/fields/field_note.ts
CHANGED
|
@@ -286,7 +286,7 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
286
286
|
* Show a field with piano keys.
|
|
287
287
|
*/
|
|
288
288
|
showEditor_(event: PointerEvent, quietInput = false) {
|
|
289
|
-
super.showEditor_(event, quietInput);
|
|
289
|
+
super.showEditor_(event, quietInput, false);
|
|
290
290
|
|
|
291
291
|
// Build the SVG DOM.
|
|
292
292
|
const div = Blockly.DropDownDiv.getContentDiv();
|
|
@@ -157,7 +157,15 @@ class ScratchFieldAngle extends Blockly.FieldNumber {
|
|
|
157
157
|
* Show the inline free-text editor on top of the text.
|
|
158
158
|
*/
|
|
159
159
|
showEditor_(event: PointerEvent) {
|
|
160
|
-
|
|
160
|
+
// Mobile browsers have issues with in-line textareas (focus & keyboards).
|
|
161
|
+
// Also, don't let the parent take ephemeral focus since the drop-down div
|
|
162
|
+
// below will handle it, instead.
|
|
163
|
+
const noFocus =
|
|
164
|
+
Blockly.utils.userAgent.MOBILE ||
|
|
165
|
+
Blockly.utils.userAgent.ANDROID ||
|
|
166
|
+
Blockly.utils.userAgent.IPAD;
|
|
167
|
+
super.showEditor_(event, noFocus, false);
|
|
168
|
+
|
|
161
169
|
// If there is an existing drop-down someone else owns, hide it immediately and clear it.
|
|
162
170
|
Blockly.DropDownDiv.hideWithoutAnimation();
|
|
163
171
|
Blockly.DropDownDiv.clearContent();
|
|
@@ -94,7 +94,7 @@ export class ScratchFieldVariable extends Blockly.FieldVariable {
|
|
|
94
94
|
* @returns Array of variable names.
|
|
95
95
|
*/
|
|
96
96
|
static dropdownCreate(this: ScratchFieldVariable): Blockly.MenuOption[] {
|
|
97
|
-
|
|
97
|
+
let options = super.dropdownCreate();
|
|
98
98
|
const type = this.getDefaultType();
|
|
99
99
|
if (type === Constants.BROADCAST_MESSAGE_VARIABLE_TYPE) {
|
|
100
100
|
options.splice(-2, 2, [
|
|
@@ -102,16 +102,17 @@ export class ScratchFieldVariable extends Blockly.FieldVariable {
|
|
|
102
102
|
Constants.NEW_BROADCAST_MESSAGE_ID,
|
|
103
103
|
]);
|
|
104
104
|
} else if (type === Constants.LIST_VARIABLE_TYPE) {
|
|
105
|
-
|
|
105
|
+
options = options.map((option) => {
|
|
106
106
|
if (option[1] === Blockly.RENAME_VARIABLE_ID) {
|
|
107
|
-
|
|
107
|
+
return [ScratchMsgs.translate("RENAME_LIST"), option[1]];
|
|
108
108
|
} else if (option[1] === Blockly.DELETE_VARIABLE_ID) {
|
|
109
|
-
|
|
110
|
-
"%1",
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
return [
|
|
110
|
+
ScratchMsgs.translate("DELETE_LIST").replace("%1", this.getText()),
|
|
111
|
+
option[1],
|
|
112
|
+
];
|
|
113
113
|
}
|
|
114
|
-
|
|
114
|
+
return option;
|
|
115
|
+
});
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
return options;
|
|
@@ -10,11 +10,15 @@ import { CheckboxBubble } from "./checkbox_bubble";
|
|
|
10
10
|
/**
|
|
11
11
|
* Invisible icon that exists solely to host the corresponding checkbox bubble.
|
|
12
12
|
*/
|
|
13
|
-
export class FlyoutCheckboxIcon
|
|
13
|
+
export class FlyoutCheckboxIcon
|
|
14
|
+
extends Blockly.icons.Icon
|
|
15
|
+
implements Blockly.IHasBubble
|
|
16
|
+
{
|
|
14
17
|
private checkboxBubble: CheckboxBubble;
|
|
15
18
|
private type = new Blockly.icons.IconType("checkbox");
|
|
16
19
|
|
|
17
|
-
constructor(
|
|
20
|
+
constructor(protected override sourceBlock: Blockly.BlockSvg) {
|
|
21
|
+
super(sourceBlock);
|
|
18
22
|
if (this.sourceBlock.workspace.isFlyout) {
|
|
19
23
|
this.checkboxBubble = new CheckboxBubble(this.sourceBlock);
|
|
20
24
|
}
|
|
@@ -24,19 +28,11 @@ export class FlyoutCheckboxIcon implements Blockly.IIcon, Blockly.IHasBubble {
|
|
|
24
28
|
return this.type;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
getWeight(): number {
|
|
28
|
-
return -1;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
31
|
getSize(): Blockly.utils.Size {
|
|
32
32
|
// Awful hack to cancel out the default padding added to icons.
|
|
33
33
|
return new Blockly.utils.Size(-8, 0);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
isShownWhenCollapsed(): boolean {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
36
|
isClickableInFlyout(): boolean {
|
|
41
37
|
return false;
|
|
42
38
|
}
|
|
@@ -55,25 +51,23 @@ export class FlyoutCheckboxIcon implements Blockly.IIcon, Blockly.IHasBubble {
|
|
|
55
51
|
|
|
56
52
|
dispose() {
|
|
57
53
|
this.checkboxBubble?.dispose();
|
|
54
|
+
super.dispose();
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
// These methods are required by the interfaces, but intentionally have no
|
|
61
58
|
// implementation, largely because this icon has no visual representation.
|
|
62
|
-
applyColour() {}
|
|
63
|
-
|
|
64
|
-
hideForInsertionMarker() {}
|
|
65
|
-
|
|
66
|
-
updateEditable() {}
|
|
67
|
-
|
|
68
|
-
updateCollapsed() {}
|
|
69
|
-
|
|
70
|
-
setOffsetInBlock() {}
|
|
71
|
-
|
|
72
|
-
onClick() {}
|
|
73
59
|
|
|
74
60
|
async setBubbleVisible(visible: boolean) {}
|
|
75
61
|
|
|
76
62
|
initView(pointerDownListener: (e: PointerEvent) => void) {}
|
|
63
|
+
|
|
64
|
+
canBeFocused() {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getBubble() {
|
|
69
|
+
return this.checkboxBubble;
|
|
70
|
+
}
|
|
77
71
|
}
|
|
78
72
|
|
|
79
73
|
Blockly.registry.register(
|
package/src/index.ts
CHANGED
|
@@ -37,6 +37,7 @@ import "./scratch_dragger";
|
|
|
37
37
|
import "./scratch_variable_map";
|
|
38
38
|
import "./scratch_variable_model";
|
|
39
39
|
import "./scratch_connection_checker";
|
|
40
|
+
import "./scratch_insertion_marker_previewer";
|
|
40
41
|
import "./flyout_checkbox_icon";
|
|
41
42
|
import "./events/events_block_comment_change";
|
|
42
43
|
import "./events/events_block_comment_collapse";
|
|
@@ -80,6 +81,7 @@ export {
|
|
|
80
81
|
StatusIndicatorLabel,
|
|
81
82
|
StatusButtonState,
|
|
82
83
|
} from "./status_indicator_label";
|
|
84
|
+
export * from "./xml";
|
|
83
85
|
|
|
84
86
|
export function inject(container: Element, options: Blockly.BlocklyOptions) {
|
|
85
87
|
registerScratchFieldAngle();
|
|
@@ -128,6 +130,7 @@ Blockly.ContextMenuRegistry.registry.unregister("blockInline");
|
|
|
128
130
|
Blockly.ContextMenuItems.registerCommentOptions();
|
|
129
131
|
Blockly.ContextMenuRegistry.registry.unregister("blockDelete");
|
|
130
132
|
contextMenuItems.registerDeleteBlock();
|
|
133
|
+
contextMenuItems.registerDuplicateBlock();
|
|
131
134
|
Blockly.ContextMenuRegistry.registry.unregister("workspaceDelete");
|
|
132
135
|
contextMenuItems.registerDeleteAll();
|
|
133
136
|
Blockly.comments.CommentView.defaultCommentSize = new Blockly.utils.Size(
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as Blockly from "blockly/core";
|
|
8
|
+
import type { ScratchCommentIcon } from "./scratch_comment_icon";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Class responsible for handling the pasting of copied blocks.
|
|
@@ -31,6 +32,15 @@ class ScratchBlockPaster extends Blockly.clipboard.BlockPaster {
|
|
|
31
32
|
block.setDragStrategy(new Blockly.dragging.BlockDragStrategy(block));
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
// Deserialization of blocks suppresses events, so even though this gets
|
|
36
|
+
// fired for blocks with comments, the VM will never receive it, causing its
|
|
37
|
+
// state to get out of sync. Manually fire it here (after suppression has
|
|
38
|
+
// been turned off) if needed.
|
|
39
|
+
const commentIcon = block.getIcon(Blockly.icons.IconType.COMMENT);
|
|
40
|
+
if (commentIcon) {
|
|
41
|
+
(commentIcon as ScratchCommentIcon).fireCreateEvent();
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
return block;
|
|
35
45
|
}
|
|
36
46
|
}
|