scratch-blocks 2.0.0-spork.3 → 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 +7 -0
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +0 -12
- package/package.json +4 -4
- package/src/checkable_continuous_flyout.ts +112 -0
- package/src/checkbox_bubble.ts +4 -5
- package/src/css.ts +13 -7
- package/src/index.ts +3 -3
- package/src/recyclable_block_flyout_inflater.ts +8 -151
- package/src/scratch_continuous_toolbox.ts +20 -30
- package/src/status_indicator_label_flyout_inflater.ts +5 -3
- package/src/variables.ts +1 -1
- package/src/checkable_continuous_flyout.js +0 -138
package/dist/main.js.LICENSE.txt
CHANGED
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.4",
|
|
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",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"webpack-dev-server": "^4.11.1"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@blockly/continuous-toolbox": "^
|
|
36
|
-
"@blockly/field-colour": "^
|
|
37
|
-
"blockly": "^12.0.0-beta.
|
|
35
|
+
"@blockly/continuous-toolbox": "^7.0.0-beta.1",
|
|
36
|
+
"@blockly/field-colour": "^4.0.2",
|
|
37
|
+
"blockly": "^12.0.0-beta.1"
|
|
38
38
|
},
|
|
39
39
|
"config": {
|
|
40
40
|
"commitizen": {
|
|
@@ -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
|
+
}
|
package/src/checkbox_bubble.ts
CHANGED
|
@@ -203,15 +203,14 @@ export class CheckboxBubble
|
|
|
203
203
|
* Recalculates this bubble's location, keeping it adjacent to its block.
|
|
204
204
|
*/
|
|
205
205
|
updateLocation() {
|
|
206
|
-
const
|
|
207
|
-
const blockBounds = this.sourceBlock.getHeightWidth();
|
|
206
|
+
const bounds = this.sourceBlock.getBoundingRectangle();
|
|
208
207
|
const x = this.sourceBlock.workspace.RTL
|
|
209
|
-
?
|
|
210
|
-
:
|
|
208
|
+
? bounds.right + CheckboxBubble.CHECKBOX_MARGIN
|
|
209
|
+
: bounds.left -
|
|
211
210
|
CheckboxBubble.CHECKBOX_MARGIN -
|
|
212
211
|
CheckboxBubble.CHECKBOX_SIZE;
|
|
213
212
|
const y =
|
|
214
|
-
|
|
213
|
+
bounds.top + (bounds.getHeight() - CheckboxBubble.CHECKBOX_SIZE) / 2;
|
|
215
214
|
this.moveTo(x, y);
|
|
216
215
|
}
|
|
217
216
|
|
package/src/css.ts
CHANGED
|
@@ -751,8 +751,9 @@ const styles = `
|
|
|
751
751
|
}
|
|
752
752
|
|
|
753
753
|
/* Category tree in Toolbox. */
|
|
754
|
-
.
|
|
754
|
+
.blocklyToolbox {
|
|
755
755
|
background-color: var(--colour-toolbox);
|
|
756
|
+
border-right: 1px solid #ddd;
|
|
756
757
|
color: var(--colour-toolboxText);
|
|
757
758
|
overflow-x: visible;
|
|
758
759
|
overflow-y: auto;
|
|
@@ -763,6 +764,11 @@ const styles = `
|
|
|
763
764
|
padding: 0;
|
|
764
765
|
}
|
|
765
766
|
|
|
767
|
+
.blocklyToolbox[dir="RTL"] {
|
|
768
|
+
border-right: none;
|
|
769
|
+
border-left: 1px solid #ddd;
|
|
770
|
+
}
|
|
771
|
+
|
|
766
772
|
.blocklyTreeRoot {
|
|
767
773
|
padding: 4px 0;
|
|
768
774
|
}
|
|
@@ -771,7 +777,7 @@ const styles = `
|
|
|
771
777
|
outline: none;
|
|
772
778
|
}
|
|
773
779
|
|
|
774
|
-
.
|
|
780
|
+
.blocklyToolbox .blocklyToolboxCategory {
|
|
775
781
|
line-height: 22px;
|
|
776
782
|
margin: 0;
|
|
777
783
|
padding: 0.375rem 0px;
|
|
@@ -789,11 +795,11 @@ const styles = `
|
|
|
789
795
|
margin: 1px 0 8px 5px;
|
|
790
796
|
}
|
|
791
797
|
|
|
792
|
-
.
|
|
793
|
-
margin-left:
|
|
798
|
+
.blocklyToolbox[dir="RTL"] .blocklyToolboxCategory {
|
|
799
|
+
margin-left: 0px;
|
|
794
800
|
}
|
|
795
801
|
|
|
796
|
-
.
|
|
802
|
+
.blocklyToolboxCategory:hover {
|
|
797
803
|
color: var(--colour-toolboxHover);
|
|
798
804
|
}
|
|
799
805
|
|
|
@@ -844,7 +850,7 @@ const styles = `
|
|
|
844
850
|
background-position: -48px -1px;
|
|
845
851
|
}
|
|
846
852
|
|
|
847
|
-
.
|
|
853
|
+
.blocklyToolboxCategoryLabel {
|
|
848
854
|
cursor: default;
|
|
849
855
|
font-family: "Helvetica Neue", Helvetica, sans-serif;
|
|
850
856
|
font-size: .65rem;
|
|
@@ -855,7 +861,7 @@ const styles = `
|
|
|
855
861
|
text-wrap: wrap;
|
|
856
862
|
}
|
|
857
863
|
|
|
858
|
-
.
|
|
864
|
+
.blocklyToolboxSelected .blocklyToolboxCategoryLabel {
|
|
859
865
|
color: inherit;
|
|
860
866
|
}
|
|
861
867
|
|
package/src/index.ts
CHANGED
|
@@ -26,11 +26,10 @@ import "./css";
|
|
|
26
26
|
import "./renderer/renderer";
|
|
27
27
|
import * as contextMenuItems from "./context_menu_items";
|
|
28
28
|
import {
|
|
29
|
-
|
|
30
|
-
ContinuousFlyout,
|
|
29
|
+
registerContinuousToolbox,
|
|
31
30
|
ContinuousMetrics,
|
|
32
31
|
} from "@blockly/continuous-toolbox";
|
|
33
|
-
import { CheckableContinuousFlyout } from "./checkable_continuous_flyout
|
|
32
|
+
import { CheckableContinuousFlyout } from "./checkable_continuous_flyout";
|
|
34
33
|
import { buildGlowFilter, glowStack } from "./glows";
|
|
35
34
|
import { ScratchContinuousToolbox } from "./scratch_continuous_toolbox";
|
|
36
35
|
import "./scratch_comment_icon";
|
|
@@ -120,6 +119,7 @@ export function inject(container: Element, options: Blockly.BlocklyOptions) {
|
|
|
120
119
|
return workspace;
|
|
121
120
|
}
|
|
122
121
|
|
|
122
|
+
registerContinuousToolbox();
|
|
123
123
|
Blockly.Scrollbar.scrollbarThickness = Blockly.Touch.TOUCH_ENABLED ? 14 : 11;
|
|
124
124
|
Blockly.FlyoutButton.TEXT_MARGIN_X = 40;
|
|
125
125
|
Blockly.FlyoutButton.TEXT_MARGIN_Y = 10;
|
|
@@ -6,21 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
import * as Blockly from "blockly/core";
|
|
8
8
|
import { CheckboxBubble } from "./checkbox_bubble";
|
|
9
|
+
import { RecyclableBlockFlyoutInflater as BlocklyRecyclableBlockFlyoutInflater } from "@blockly/continuous-toolbox";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* A block inflater that caches and reuses blocks to improve performance.
|
|
12
13
|
*/
|
|
13
|
-
export class RecyclableBlockFlyoutInflater extends
|
|
14
|
-
/**
|
|
15
|
-
* Whether or not block recycling is enabled.
|
|
16
|
-
*/
|
|
17
|
-
recyclingEnabled = true;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Map from block type to block instance.
|
|
21
|
-
*/
|
|
22
|
-
recycledBlocks = new Map<string, Blockly.BlockSvg>();
|
|
23
|
-
|
|
14
|
+
export class RecyclableBlockFlyoutInflater extends BlocklyRecyclableBlockFlyoutInflater {
|
|
24
15
|
/**
|
|
25
16
|
* Creates a block on the flyout workspace from the given block definition.
|
|
26
17
|
*
|
|
@@ -31,152 +22,18 @@ export class RecyclableBlockFlyoutInflater extends Blockly.BlockFlyoutInflater {
|
|
|
31
22
|
load(
|
|
32
23
|
state: Blockly.utils.toolbox.BlockInfo,
|
|
33
24
|
flyoutWorkspace: Blockly.WorkspaceSvg
|
|
34
|
-
): Blockly.
|
|
35
|
-
const
|
|
25
|
+
): Blockly.FlyoutItem {
|
|
26
|
+
const flyoutItem = super.load(state, flyoutWorkspace);
|
|
27
|
+
const block = flyoutItem.getElement();
|
|
36
28
|
if ("checkboxInFlyout" in block && block.checkboxInFlyout) {
|
|
37
29
|
block.moveBy(
|
|
38
|
-
|
|
30
|
+
(flyoutWorkspace.RTL ? -1 : 1) *
|
|
31
|
+
(CheckboxBubble.CHECKBOX_SIZE + CheckboxBubble.CHECKBOX_MARGIN),
|
|
39
32
|
0
|
|
40
33
|
);
|
|
41
34
|
}
|
|
42
35
|
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Toggles whether or not recycling is enabled.
|
|
48
|
-
*
|
|
49
|
-
* @param enabled True if recycling should be enabled.
|
|
50
|
-
*/
|
|
51
|
-
setRecyclingEnabled(enabled: boolean) {
|
|
52
|
-
this.recyclingEnabled = enabled;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Creates a new block from the given block definition.
|
|
57
|
-
*
|
|
58
|
-
* @param blockDefinition The definition to create a block from.
|
|
59
|
-
* @returns The newly created block.
|
|
60
|
-
*/
|
|
61
|
-
createBlock(
|
|
62
|
-
blockDefinition: Blockly.utils.toolbox.BlockInfo
|
|
63
|
-
): Blockly.BlockSvg {
|
|
64
|
-
const blockType = this.getTypeFromDefinition(blockDefinition);
|
|
65
|
-
return (
|
|
66
|
-
this.getRecycledBlock(blockType) ??
|
|
67
|
-
super.createBlock(blockDefinition, this.flyoutWorkspace)
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Returns the type of a block from an XML or JSON block definition.
|
|
73
|
-
*
|
|
74
|
-
* @param blockDefinition The block definition to parse.
|
|
75
|
-
* @returns The block type.
|
|
76
|
-
*/
|
|
77
|
-
getTypeFromDefinition(
|
|
78
|
-
blockDefinition: Blockly.utils.toolbox.BlockInfo
|
|
79
|
-
): string {
|
|
80
|
-
if (blockDefinition["blockxml"]) {
|
|
81
|
-
const xml =
|
|
82
|
-
typeof blockDefinition["blockxml"] === "string"
|
|
83
|
-
? Blockly.utils.xml.textToDom(blockDefinition["blockxml"])
|
|
84
|
-
: (blockDefinition["blockxml"] as Element);
|
|
85
|
-
return xml.getAttribute("type");
|
|
86
|
-
} else {
|
|
87
|
-
return blockDefinition["type"];
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Puts a previously created block into the recycle bin and moves it to the
|
|
93
|
-
* top of the workspace. Used during large workspace swaps to limit the number
|
|
94
|
-
* of new DOM elements we need to create.
|
|
95
|
-
*
|
|
96
|
-
* @param block The block to recycle.
|
|
97
|
-
*/
|
|
98
|
-
recycleBlock(block: Blockly.BlockSvg) {
|
|
99
|
-
const xy = block.getRelativeToSurfaceXY();
|
|
100
|
-
block.moveBy(-xy.x, -xy.y);
|
|
101
|
-
this.recycledBlocks.set(block.type, block);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Returns a block from the cache of recycled blocks with the given type, or
|
|
106
|
-
* undefined if one cannot be found.
|
|
107
|
-
*
|
|
108
|
-
* @param blockType The type of the block to try to recycle.
|
|
109
|
-
* @returns The recycled block, or undefined if one could not be recycled.
|
|
110
|
-
*/
|
|
111
|
-
getRecycledBlock(blockType: string): Blockly.BlockSvg | undefined {
|
|
112
|
-
const block = this.recycledBlocks.get(blockType);
|
|
113
|
-
this.recycledBlocks.delete(blockType);
|
|
114
|
-
return block;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Returns whether the given block can be recycled or not.
|
|
119
|
-
*
|
|
120
|
-
* @param block The block to check for recyclability.
|
|
121
|
-
* @returns True if the block can be recycled. False otherwise.
|
|
122
|
-
*/
|
|
123
|
-
blockIsRecyclable(block: Blockly.Block): boolean {
|
|
124
|
-
if (!this.recyclingEnabled) {
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// If the block needs to parse mutations, never recycle.
|
|
129
|
-
if (block.mutationToDom && block.domToMutation) {
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (!block.isEnabled()) {
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
for (const input of block.inputList) {
|
|
138
|
-
for (const field of input.fieldRow) {
|
|
139
|
-
// No variables.
|
|
140
|
-
if (field.referencesVariables()) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
if (field instanceof Blockly.FieldDropdown) {
|
|
144
|
-
if (field.isOptionListDynamic()) {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
// Check children.
|
|
150
|
-
if (input.connection) {
|
|
151
|
-
const targetBlock = input.connection.targetBlock();
|
|
152
|
-
if (targetBlock && !this.blockIsRecyclable(targetBlock)) {
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Disposes of the provided block.
|
|
162
|
-
*
|
|
163
|
-
* @param element The block to dispose of.
|
|
164
|
-
*/
|
|
165
|
-
disposeElement(element: Blockly.BlockSvg) {
|
|
166
|
-
if (this.blockIsRecyclable(element)) {
|
|
167
|
-
this.removeListeners(element.id);
|
|
168
|
-
this.recycleBlock(element);
|
|
169
|
-
} else {
|
|
170
|
-
super.disposeElement(element);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Clears the cache of recycled blocks.
|
|
176
|
-
*/
|
|
177
|
-
emptyRecycledBlocks() {
|
|
178
|
-
this.recycledBlocks.forEach((block) => block.dispose(false, false));
|
|
179
|
-
this.recycledBlocks.clear();
|
|
36
|
+
return flyoutItem;
|
|
180
37
|
}
|
|
181
38
|
}
|
|
182
39
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import * as Blockly from "blockly/core";
|
|
8
8
|
import { ContinuousToolbox } from "@blockly/continuous-toolbox";
|
|
9
9
|
import { ScratchContinuousCategory } from "./scratch_continuous_category";
|
|
10
|
+
import { STATUS_INDICATOR_LABEL_TYPE } from "./status_indicator_label_flyout_inflater";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* A toolbox that displays items from all categories in one scrolling list.
|
|
@@ -23,36 +24,25 @@ export class ScratchContinuousToolbox extends ContinuousToolbox {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
+
* Converts the given toolbox item to a corresponding array of items that
|
|
28
|
+
* should appear in the flyout.
|
|
27
29
|
*
|
|
28
|
-
* @
|
|
30
|
+
* @param toolboxItem The toolbox item to convert.
|
|
31
|
+
* @returns An array of flyout item definitions.
|
|
29
32
|
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
contents.push({ kind: "LABEL", text: toolboxItem.getName() });
|
|
44
|
-
}
|
|
45
|
-
let itemContents = toolboxItem.getContents();
|
|
46
|
-
|
|
47
|
-
// Handle custom categories (e.g. variables and functions)
|
|
48
|
-
if (typeof itemContents === "string") {
|
|
49
|
-
itemContents = {
|
|
50
|
-
custom: itemContents,
|
|
51
|
-
kind: "CATEGORY",
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
contents = contents.concat(itemContents);
|
|
55
|
-
}
|
|
33
|
+
protected convertToolboxItemToFlyoutItems(
|
|
34
|
+
toolboxItem: Blockly.IToolboxItem
|
|
35
|
+
): Blockly.utils.toolbox.FlyoutItemInfoArray {
|
|
36
|
+
const contents = super.convertToolboxItemToFlyoutItems(toolboxItem);
|
|
37
|
+
if (
|
|
38
|
+
toolboxItem instanceof ScratchContinuousCategory &&
|
|
39
|
+
toolboxItem.shouldShowStatusButton()
|
|
40
|
+
) {
|
|
41
|
+
contents.splice(0, 1, {
|
|
42
|
+
kind: STATUS_INDICATOR_LABEL_TYPE,
|
|
43
|
+
id: toolboxItem.getId(),
|
|
44
|
+
text: toolboxItem.getName(),
|
|
45
|
+
});
|
|
56
46
|
}
|
|
57
47
|
return contents;
|
|
58
48
|
}
|
|
@@ -62,12 +52,12 @@ export class ScratchContinuousToolbox extends ContinuousToolbox {
|
|
|
62
52
|
*/
|
|
63
53
|
forceRerender() {
|
|
64
54
|
const selectedCategoryName = this.selectedItem_?.getName();
|
|
65
|
-
|
|
55
|
+
this.getFlyout().show(this.getInitialFlyoutContents());
|
|
56
|
+
this.selectCategoryByName(selectedCategoryName);
|
|
66
57
|
let callback;
|
|
67
58
|
while ((callback = this.postRenderCallbacks.shift())) {
|
|
68
59
|
callback();
|
|
69
60
|
}
|
|
70
|
-
this.selectCategoryByName(selectedCategoryName);
|
|
71
61
|
}
|
|
72
62
|
|
|
73
63
|
/**
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import * as Blockly from "blockly/core";
|
|
8
8
|
import { StatusIndicatorLabel } from "./status_indicator_label";
|
|
9
9
|
|
|
10
|
+
export const STATUS_INDICATOR_LABEL_TYPE = "status_indicator_label";
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* Flyout inflater responsible for creating status indicator labels.
|
|
12
14
|
*/
|
|
@@ -21,14 +23,14 @@ class StatusIndicatorLabelFlyoutInflater extends Blockly.LabelFlyoutInflater {
|
|
|
21
23
|
load(
|
|
22
24
|
state: Blockly.utils.toolbox.LabelInfo,
|
|
23
25
|
flyoutWorkspace: Blockly.WorkspaceSvg
|
|
24
|
-
):
|
|
26
|
+
): Blockly.FlyoutItem {
|
|
25
27
|
const label = new StatusIndicatorLabel(
|
|
26
28
|
flyoutWorkspace,
|
|
27
29
|
flyoutWorkspace.targetWorkspace,
|
|
28
30
|
state
|
|
29
31
|
);
|
|
30
32
|
label.show();
|
|
31
|
-
return label;
|
|
33
|
+
return new Blockly.FlyoutItem(label, STATUS_INDICATOR_LABEL_TYPE, true);
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -38,7 +40,7 @@ class StatusIndicatorLabelFlyoutInflater extends Blockly.LabelFlyoutInflater {
|
|
|
38
40
|
export function registerStatusIndicatorLabelFlyoutInflater() {
|
|
39
41
|
Blockly.registry.register(
|
|
40
42
|
Blockly.registry.Type.FLYOUT_INFLATER,
|
|
41
|
-
|
|
43
|
+
STATUS_INDICATOR_LABEL_TYPE,
|
|
42
44
|
StatusIndicatorLabelFlyoutInflater
|
|
43
45
|
);
|
|
44
46
|
}
|
package/src/variables.ts
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
} from "./constants";
|
|
30
30
|
import { ScratchVariableModel } from "./scratch_variable_model";
|
|
31
31
|
import { ScratchContinuousToolbox } from "./scratch_continuous_toolbox";
|
|
32
|
-
import { CheckableContinuousFlyout } from "./checkable_continuous_flyout
|
|
32
|
+
import { CheckableContinuousFlyout } from "./checkable_continuous_flyout";
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Constant prefix to differentiate cloud variable names from other types of
|