scratch-blocks 2.1.4 → 2.1.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/AGENTS.md +76 -24
- package/README.md +40 -0
- package/dist/main.mjs +1 -1
- package/dist/types/src/block_reporting.d.ts.map +1 -1
- package/dist/types/src/blocks/procedures.d.ts +2 -2
- package/dist/types/src/blocks/procedures.d.ts.map +1 -1
- package/dist/types/src/checkable_continuous_flyout.d.ts +6 -3
- package/dist/types/src/checkable_continuous_flyout.d.ts.map +1 -1
- package/dist/types/src/checkbox_bubble.d.ts +7 -7
- package/dist/types/src/checkbox_bubble.d.ts.map +1 -1
- package/dist/types/src/colours.d.ts.map +1 -1
- package/dist/types/src/context_menu_items.d.ts.map +1 -1
- package/dist/types/src/events/events_block_comment_base.d.ts +1 -1
- package/dist/types/src/events/events_block_comment_base.d.ts.map +1 -1
- package/dist/types/src/events/events_block_drag_end.d.ts +1 -1
- package/dist/types/src/events/events_block_drag_end.d.ts.map +1 -1
- package/dist/types/src/events/events_block_drag_outside.d.ts +1 -1
- package/dist/types/src/events/events_block_drag_outside.d.ts.map +1 -1
- package/dist/types/src/fields/field_colour_slider.d.ts.map +1 -1
- package/dist/types/src/fields/field_matrix.d.ts.map +1 -1
- package/dist/types/src/fields/field_note.d.ts +6 -4
- package/dist/types/src/fields/field_note.d.ts.map +1 -1
- package/dist/types/src/fields/field_textinput_removable.d.ts.map +1 -1
- package/dist/types/src/fields/field_variable_getter.d.ts.map +1 -1
- package/dist/types/src/fields/field_vertical_separator.d.ts.map +1 -1
- package/dist/types/src/fields/scratch_field_angle.d.ts.map +1 -1
- package/dist/types/src/fields/scratch_field_dropdown.d.ts.map +1 -1
- package/dist/types/src/fields/scratch_field_number.d.ts.map +1 -1
- package/dist/types/src/fields/scratch_field_variable.d.ts +1 -0
- package/dist/types/src/fields/scratch_field_variable.d.ts.map +1 -1
- package/dist/types/src/flyout_checkbox_icon.d.ts +5 -5
- package/dist/types/src/flyout_checkbox_icon.d.ts.map +1 -1
- package/dist/types/src/glows.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/procedures.d.ts +4 -4
- package/dist/types/src/procedures.d.ts.map +1 -1
- package/dist/types/src/recyclable_block_flyout_inflater.d.ts +2 -2
- package/dist/types/src/recyclable_block_flyout_inflater.d.ts.map +1 -1
- package/dist/types/src/renderer/cat/cat_face.d.ts +1 -1
- package/dist/types/src/renderer/cat/cat_face.d.ts.map +1 -1
- package/dist/types/src/renderer/cat/drawer.d.ts.map +1 -1
- package/dist/types/src/renderer/constants.d.ts.map +1 -1
- package/dist/types/src/renderer/drawer.d.ts.map +1 -1
- package/dist/types/src/renderer/render_info.d.ts.map +1 -1
- package/dist/types/src/scratch_blocks_utils.d.ts +22 -0
- package/dist/types/src/scratch_blocks_utils.d.ts.map +1 -1
- package/dist/types/src/scratch_c_block_wrap.d.ts +2 -0
- package/dist/types/src/scratch_c_block_wrap.d.ts.map +1 -0
- package/dist/types/src/scratch_comment_bubble.d.ts +4 -4
- package/dist/types/src/scratch_comment_bubble.d.ts.map +1 -1
- package/dist/types/src/scratch_comment_icon.d.ts +1 -1
- package/dist/types/src/scratch_comment_icon.d.ts.map +1 -1
- package/dist/types/src/scratch_continuous_category.d.ts +3 -1
- package/dist/types/src/scratch_continuous_category.d.ts.map +1 -1
- package/dist/types/src/scratch_continuous_toolbox.d.ts +2 -1
- package/dist/types/src/scratch_continuous_toolbox.d.ts.map +1 -1
- package/dist/types/src/status_indicator_label.d.ts +3 -3
- package/dist/types/src/status_indicator_label.d.ts.map +1 -1
- package/dist/types/src/status_indicator_label_flyout_inflater.d.ts.map +1 -1
- package/dist/types/src/variables.d.ts +1 -1
- package/dist/types/src/variables.d.ts.map +1 -1
- package/dist/types/src/workspace_block_lookup.d.ts +4 -0
- package/dist/types/src/workspace_block_lookup.d.ts.map +1 -0
- package/eslint.config.mjs +23 -26
- package/package.json +10 -3
- package/src/block_reporting.ts +5 -5
- package/src/blocks/control.ts +5 -5
- package/src/blocks/event.ts +1 -1
- package/src/blocks/motion.ts +2 -2
- package/src/blocks/procedures.ts +162 -69
- package/src/blocks/sensing.ts +0 -1
- package/src/blocks/vertical_extensions.ts +11 -8
- package/src/checkable_continuous_flyout.ts +45 -12
- package/src/checkbox_bubble.ts +7 -7
- package/src/colours.ts +4 -2
- package/src/context_menu_items.ts +41 -16
- package/src/data_category.ts +11 -3
- package/src/events/events_block_comment_base.ts +5 -1
- package/src/events/events_block_comment_change.ts +5 -1
- package/src/events/events_block_comment_collapse.ts +6 -2
- package/src/events/events_block_comment_create.ts +5 -1
- package/src/events/events_block_comment_move.ts +6 -2
- package/src/events/events_block_comment_resize.ts +6 -2
- package/src/events/events_block_drag_end.ts +5 -1
- package/src/events/events_block_drag_outside.ts +5 -1
- package/src/events/events_scratch_variable_create.ts +5 -1
- package/src/fields/field_colour_slider.ts +3 -5
- package/src/fields/field_matrix.ts +33 -17
- package/src/fields/field_note.ts +56 -20
- package/src/fields/field_textinput_removable.ts +13 -4
- package/src/fields/field_variable_getter.ts +20 -6
- package/src/fields/field_vertical_separator.ts +5 -1
- package/src/fields/scratch_field_angle.ts +32 -21
- package/src/fields/scratch_field_dropdown.ts +6 -2
- package/src/fields/scratch_field_number.ts +22 -13
- package/src/fields/scratch_field_variable.ts +26 -12
- package/src/flyout_checkbox_icon.ts +9 -5
- package/src/glows.ts +5 -5
- package/src/index.ts +21 -11
- package/src/procedures.ts +92 -42
- package/src/recyclable_block_flyout_inflater.ts +5 -4
- package/src/renderer/cat/cat_face.ts +1 -1
- package/src/renderer/cat/drawer.ts +4 -1
- package/src/renderer/constants.ts +19 -14
- package/src/renderer/drawer.ts +2 -1
- package/src/renderer/render_info.ts +12 -9
- package/src/renderer/renderer.ts +1 -1
- package/src/scratch_blocks_utils.ts +0 -2
- package/src/scratch_c_block_wrap.ts +108 -0
- package/src/scratch_comment_bubble.ts +30 -19
- package/src/scratch_comment_icon.ts +9 -12
- package/src/scratch_connection_checker.ts +1 -2
- package/src/scratch_continuous_category.ts +20 -11
- package/src/scratch_continuous_toolbox.ts +12 -3
- package/src/scratch_dragger.ts +2 -2
- package/src/scratch_variable_map.ts +1 -1
- package/src/status_indicator_label.ts +13 -9
- package/src/status_indicator_label_flyout_inflater.ts +2 -1
- package/src/variables.ts +21 -14
- package/src/workspace_block_lookup.ts +14 -0
- package/src/xml.ts +1 -1
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +35 -0
- package/dist/types/tests/blocks/logic_ternary_test.d.ts +0 -13
- package/dist/types/tests/blocks/logic_ternary_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/block_test.d.ts +0 -4
- package/dist/types/tests/jsunit/block_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/connection_db_test.d.ts +0 -25
- package/dist/types/tests/jsunit/connection_db_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/connection_test.d.ts +0 -39
- package/dist/types/tests/jsunit/connection_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/db_test.d.ts +0 -7
- package/dist/types/tests/jsunit/db_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/event_test.d.ts +0 -76
- package/dist/types/tests/jsunit/event_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/extensions_test.d.ts +0 -18
- package/dist/types/tests/jsunit/extensions_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/field_angle_test.d.ts +0 -3
- package/dist/types/tests/jsunit/field_angle_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/field_number_test.d.ts +0 -3
- package/dist/types/tests/jsunit/field_number_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/field_test.d.ts +0 -8
- package/dist/types/tests/jsunit/field_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/field_variable_getter_test.d.ts +0 -5
- package/dist/types/tests/jsunit/field_variable_getter_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/field_variable_test.d.ts +0 -19
- package/dist/types/tests/jsunit/field_variable_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/generator_test.d.ts +0 -2
- package/dist/types/tests/jsunit/generator_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/gesture_test.d.ts +0 -10
- package/dist/types/tests/jsunit/gesture_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/input_test.d.ts +0 -9
- package/dist/types/tests/jsunit/input_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/json_test.d.ts +0 -11
- package/dist/types/tests/jsunit/json_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/names_test.d.ts +0 -5
- package/dist/types/tests/jsunit/names_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/procedure_test.d.ts +0 -15
- package/dist/types/tests/jsunit/procedure_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/scratch_block_comment_test.d.ts +0 -14
- package/dist/types/tests/jsunit/scratch_block_comment_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/svg_test.d.ts +0 -14
- package/dist/types/tests/jsunit/svg_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/test_runner.d.ts +0 -2
- package/dist/types/tests/jsunit/test_runner.d.ts.map +0 -1
- package/dist/types/tests/jsunit/test_utilities.d.ts +0 -50
- package/dist/types/tests/jsunit/test_utilities.d.ts.map +0 -1
- package/dist/types/tests/jsunit/utils_test.d.ts +0 -10
- package/dist/types/tests/jsunit/utils_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/variable_map_test.d.ts +0 -28
- package/dist/types/tests/jsunit/variable_map_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/variable_model_test.d.ts +0 -14
- package/dist/types/tests/jsunit/variable_model_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/widget_div_test.d.ts +0 -37
- package/dist/types/tests/jsunit/widget_div_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/workspace_comment_test.d.ts +0 -13
- package/dist/types/tests/jsunit/workspace_comment_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/workspace_test.d.ts +0 -22
- package/dist/types/tests/jsunit/workspace_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/workspace_undo_redo_test.d.ts +0 -33
- package/dist/types/tests/jsunit/workspace_undo_redo_test.d.ts.map +0 -1
- package/dist/types/tests/jsunit/xml_test.d.ts +0 -55
- package/dist/types/tests/jsunit/xml_test.d.ts.map +0 -1
- package/dist/types/tests/workspace_svg/workspace_svg_test.d.ts +0 -12
- package/dist/types/tests/workspace_svg/workspace_svg_test.d.ts.map +0 -1
- package/types/continuous-toolbox.d.ts +0 -1
|
@@ -4,26 +4,38 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as Blockly from 'blockly/core'
|
|
6
6
|
|
|
7
|
+
type ActionRegistryItem = Extract<Blockly.ContextMenuRegistry.RegistryItem, { callback: unknown }>
|
|
8
|
+
|
|
9
|
+
function isActionRegistryItem(item: Blockly.ContextMenuRegistry.RegistryItem): item is ActionRegistryItem {
|
|
10
|
+
return 'callback' in item && 'displayText' in item && 'preconditionFn' in item
|
|
11
|
+
}
|
|
12
|
+
|
|
7
13
|
/**
|
|
8
14
|
* Registers a block delete option that ignores shadows in the block count.
|
|
9
15
|
*/
|
|
10
16
|
export function registerDeleteBlock() {
|
|
11
17
|
const deleteOption = {
|
|
12
18
|
displayText(scope: Blockly.ContextMenuRegistry.Scope) {
|
|
13
|
-
|
|
19
|
+
if (!scope.block) {
|
|
20
|
+
return Blockly.Msg.DELETE_BLOCK
|
|
21
|
+
}
|
|
22
|
+
const descendantCount = getDeletableBlocksInStack(scope.block).length
|
|
14
23
|
return descendantCount === 1
|
|
15
24
|
? Blockly.Msg.DELETE_BLOCK
|
|
16
25
|
: Blockly.Msg.DELETE_X_BLOCKS.replace('%1', `${descendantCount}`)
|
|
17
26
|
},
|
|
18
27
|
preconditionFn(scope: Blockly.ContextMenuRegistry.Scope) {
|
|
19
|
-
if (!scope.block
|
|
28
|
+
if (scope.block && !scope.block.isInFlyout && scope.block.isDeletable()) {
|
|
20
29
|
return 'enabled'
|
|
21
30
|
}
|
|
22
31
|
return 'hidden'
|
|
23
32
|
},
|
|
24
33
|
callback(scope: Blockly.ContextMenuRegistry.Scope) {
|
|
34
|
+
if (!scope.block) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
25
37
|
Blockly.Events.setGroup(true)
|
|
26
|
-
scope.block
|
|
38
|
+
scope.block.dispose(true, true)
|
|
27
39
|
Blockly.Events.setGroup(false)
|
|
28
40
|
},
|
|
29
41
|
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
|
|
@@ -33,17 +45,18 @@ export function registerDeleteBlock() {
|
|
|
33
45
|
Blockly.ContextMenuRegistry.registry.register(deleteOption)
|
|
34
46
|
}
|
|
35
47
|
|
|
36
|
-
function getDeletableBlocksInStack(block: Blockly.
|
|
48
|
+
function getDeletableBlocksInStack(block: Blockly.Block): Blockly.Block[] {
|
|
37
49
|
let descendants = block.getDescendants(false).filter(isDeletable)
|
|
38
|
-
|
|
50
|
+
const nextBlock = block.getNextBlock()
|
|
51
|
+
if (nextBlock) {
|
|
39
52
|
// Next blocks are not deleted.
|
|
40
|
-
const nextDescendants =
|
|
53
|
+
const nextDescendants = nextBlock.getDescendants(false).filter(isDeletable)
|
|
41
54
|
descendants = descendants.filter((b) => !nextDescendants.includes(b))
|
|
42
55
|
}
|
|
43
56
|
return descendants
|
|
44
57
|
}
|
|
45
58
|
|
|
46
|
-
function isDeletable(block: Blockly.
|
|
59
|
+
function isDeletable(block: Blockly.Block): boolean {
|
|
47
60
|
return block.isDeletable() && !block.isShadow()
|
|
48
61
|
}
|
|
49
62
|
|
|
@@ -101,8 +114,8 @@ export function registerDeleteAll() {
|
|
|
101
114
|
* @param workspace to delete all blocks from.
|
|
102
115
|
* @returns list of blocks to delete.
|
|
103
116
|
*/
|
|
104
|
-
function getDeletableBlocksInWorkspace(workspace: Blockly.
|
|
105
|
-
return workspace.getTopBlocks(true).flatMap((b
|
|
117
|
+
function getDeletableBlocksInWorkspace(workspace: Blockly.Workspace): Blockly.Block[] {
|
|
118
|
+
return workspace.getTopBlocks(true).flatMap((b) => b.getDescendants(false).filter(isDeletable))
|
|
106
119
|
}
|
|
107
120
|
|
|
108
121
|
/**
|
|
@@ -111,7 +124,7 @@ function getDeletableBlocksInWorkspace(workspace: Blockly.WorkspaceSvg): Blockly
|
|
|
111
124
|
* @param eventGroup Event group ID with which all delete events should be
|
|
112
125
|
* associated. If not specified, create a new group.
|
|
113
126
|
*/
|
|
114
|
-
function deleteNext(deleteList: Blockly.
|
|
127
|
+
function deleteNext(deleteList: Blockly.Block[], eventGroup?: string) {
|
|
115
128
|
const DELAY = 10
|
|
116
129
|
if (eventGroup) {
|
|
117
130
|
Blockly.Events.setGroup(eventGroup)
|
|
@@ -122,8 +135,12 @@ function deleteNext(deleteList: Blockly.BlockSvg[], eventGroup?: string) {
|
|
|
122
135
|
const block = deleteList.shift()
|
|
123
136
|
if (block) {
|
|
124
137
|
if (!block.isDeadOrDying()) {
|
|
125
|
-
block.
|
|
126
|
-
|
|
138
|
+
if (block instanceof Blockly.BlockSvg) {
|
|
139
|
+
block.dispose(false, true)
|
|
140
|
+
} else {
|
|
141
|
+
block.dispose(false)
|
|
142
|
+
}
|
|
143
|
+
setTimeout(() => deleteNext(deleteList, eventGroup), DELAY)
|
|
127
144
|
} else {
|
|
128
145
|
deleteNext(deleteList, eventGroup)
|
|
129
146
|
}
|
|
@@ -136,10 +153,18 @@ function deleteNext(deleteList: Blockly.BlockSvg[], eventGroup?: string) {
|
|
|
136
153
|
* all subsequent blocks in the stack.
|
|
137
154
|
*/
|
|
138
155
|
export function registerDuplicateBlock() {
|
|
139
|
-
const original = Blockly.ContextMenuRegistry.registry.getItem('blockDuplicate')
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
const original = Blockly.ContextMenuRegistry.registry.getItem('blockDuplicate')
|
|
157
|
+
if (!original) {
|
|
158
|
+
console.error('[context_menu_items] Missing required blockDuplicate menu item')
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
if (!isActionRegistryItem(original)) {
|
|
162
|
+
console.error('[context_menu_items] Expected blockDuplicate to be an action item')
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
const duplicateOption: ActionRegistryItem = {
|
|
166
|
+
displayText: original.displayText,
|
|
167
|
+
preconditionFn: original.preconditionFn,
|
|
143
168
|
callback(scope: Blockly.ContextMenuRegistry.Scope) {
|
|
144
169
|
if (!scope.block) return
|
|
145
170
|
const data = scope.block.toCopyData(true)
|
package/src/data_category.ts
CHANGED
|
@@ -440,7 +440,11 @@ function addBlock(
|
|
|
440
440
|
${secondValueField}
|
|
441
441
|
</block>
|
|
442
442
|
</xml>`
|
|
443
|
-
const block = Blockly.utils.xml.textToDom(blockText).firstElementChild
|
|
443
|
+
const block = Blockly.utils.xml.textToDom(blockText).firstElementChild
|
|
444
|
+
if (!block) {
|
|
445
|
+
console.error(`[data_category/addBlock] Failed to create block XML for type ${blockType}`)
|
|
446
|
+
return
|
|
447
|
+
}
|
|
444
448
|
xmlList.push(block)
|
|
445
449
|
}
|
|
446
450
|
}
|
|
@@ -456,7 +460,7 @@ function generateVariableFieldXml(
|
|
|
456
460
|
opt_name?: string,
|
|
457
461
|
): string {
|
|
458
462
|
const field = document.createElement('field')
|
|
459
|
-
field.setAttribute('name', opt_name
|
|
463
|
+
field.setAttribute('name', opt_name ?? 'VARIABLE')
|
|
460
464
|
field.setAttribute('id', variableModel.getId())
|
|
461
465
|
field.setAttribute('variabletype', variableModel.getType())
|
|
462
466
|
field.textContent = variableModel.getName()
|
|
@@ -503,6 +507,10 @@ function createValue(valueName: string, type: string, value: string): string {
|
|
|
503
507
|
*/
|
|
504
508
|
function addSep(xmlList: Element[]) {
|
|
505
509
|
const sepText = `<xml><sep gap="36"/></xml>`
|
|
506
|
-
const sep = Blockly.utils.xml.textToDom(sepText).firstElementChild
|
|
510
|
+
const sep = Blockly.utils.xml.textToDom(sepText).firstElementChild
|
|
511
|
+
if (!sep) {
|
|
512
|
+
console.error('[data_category/addSep] Failed to create separator XML')
|
|
513
|
+
return
|
|
514
|
+
}
|
|
507
515
|
xmlList.push(sep)
|
|
508
516
|
}
|
|
@@ -33,7 +33,11 @@ export class BlockCommentBase extends Blockly.Events.Abstract {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
static fromJson(
|
|
36
|
+
static fromJson(
|
|
37
|
+
json: BlockCommentBaseJson,
|
|
38
|
+
workspace: Blockly.Workspace,
|
|
39
|
+
event?: Blockly.Events.Abstract,
|
|
40
|
+
): BlockCommentBase {
|
|
37
41
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockCommentBase()) as BlockCommentBase
|
|
38
42
|
newEvent.commentId = json.commentId
|
|
39
43
|
newEvent.blockId = json.blockId
|
|
@@ -29,7 +29,11 @@ class BlockCommentChange extends BlockCommentBase {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
static fromJson(
|
|
32
|
+
static fromJson(
|
|
33
|
+
json: BlockCommentChangeJson,
|
|
34
|
+
workspace: Blockly.Workspace,
|
|
35
|
+
event?: Blockly.Events.Abstract,
|
|
36
|
+
): BlockCommentChange {
|
|
33
37
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockCommentChange()) as BlockCommentChange
|
|
34
38
|
newEvent.newContents_ = json.newContents
|
|
35
39
|
newEvent.oldContents_ = json.oldContents
|
|
@@ -22,7 +22,11 @@ class BlockCommentCollapse extends BlockCommentBase {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
static fromJson(
|
|
25
|
+
static fromJson(
|
|
26
|
+
json: BlockCommentCollapseJson,
|
|
27
|
+
workspace: Blockly.Workspace,
|
|
28
|
+
event?: Blockly.Events.Abstract,
|
|
29
|
+
): BlockCommentCollapse {
|
|
26
30
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockCommentCollapse()) as BlockCommentCollapse
|
|
27
31
|
newEvent.newCollapsed = json.collapsed
|
|
28
32
|
|
|
@@ -41,7 +45,7 @@ class BlockCommentCollapse extends BlockCommentBase {
|
|
|
41
45
|
console.warn('BlockCommentCollapse.run: comment icon not found', block.id)
|
|
42
46
|
return
|
|
43
47
|
}
|
|
44
|
-
comment.setBubbleVisible(forward ? !this.newCollapsed : this.newCollapsed)
|
|
48
|
+
void comment.setBubbleVisible(forward ? !this.newCollapsed : this.newCollapsed)
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
|
|
@@ -41,7 +41,11 @@ class BlockCommentCreate extends BlockCommentBase {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
static fromJson(
|
|
44
|
+
static fromJson(
|
|
45
|
+
json: BlockCommentCreateJson,
|
|
46
|
+
workspace: Blockly.Workspace,
|
|
47
|
+
event?: Blockly.Events.Abstract,
|
|
48
|
+
): BlockCommentCreate {
|
|
45
49
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockCommentCreate()) as BlockCommentCreate
|
|
46
50
|
newEvent.json = {
|
|
47
51
|
x: json.x,
|
|
@@ -29,7 +29,11 @@ class BlockCommentMove extends BlockCommentBase {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
static fromJson(
|
|
32
|
+
static fromJson(
|
|
33
|
+
json: BlockCommentMoveJson,
|
|
34
|
+
workspace: Blockly.Workspace,
|
|
35
|
+
event?: Blockly.Events.Abstract,
|
|
36
|
+
): BlockCommentMove {
|
|
33
37
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockCommentMove()) as BlockCommentMove
|
|
34
38
|
newEvent.newCoordinate_ = new Blockly.utils.Coordinate(json.newCoordinate.x, json.newCoordinate.y)
|
|
35
39
|
newEvent.oldCoordinate_ = new Blockly.utils.Coordinate(json.oldCoordinate.x, json.oldCoordinate.y)
|
|
@@ -39,7 +43,7 @@ class BlockCommentMove extends BlockCommentBase {
|
|
|
39
43
|
|
|
40
44
|
run(forward: boolean) {
|
|
41
45
|
const workspace = this.getEventWorkspace_()
|
|
42
|
-
const block = workspace
|
|
46
|
+
const block = workspace.getBlockById(this.blockId)
|
|
43
47
|
const comment = block?.getIcon(Blockly.icons.IconType.COMMENT)
|
|
44
48
|
comment?.setBubbleLocation(forward ? this.newCoordinate_ : this.oldCoordinate_)
|
|
45
49
|
}
|
|
@@ -31,7 +31,11 @@ class BlockCommentResize extends BlockCommentBase {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
static fromJson(
|
|
34
|
+
static fromJson(
|
|
35
|
+
json: BlockCommentResizeJson,
|
|
36
|
+
workspace: Blockly.Workspace,
|
|
37
|
+
event?: Blockly.Events.Abstract,
|
|
38
|
+
): BlockCommentResize {
|
|
35
39
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockCommentResize()) as BlockCommentResize
|
|
36
40
|
newEvent.newSize = new Blockly.utils.Size(json.newSize.width, json.newSize.height)
|
|
37
41
|
newEvent.oldSize = new Blockly.utils.Size(json.oldSize.width, json.oldSize.height)
|
|
@@ -41,7 +45,7 @@ class BlockCommentResize extends BlockCommentBase {
|
|
|
41
45
|
|
|
42
46
|
run(forward: boolean) {
|
|
43
47
|
const workspace = this.getEventWorkspace_()
|
|
44
|
-
const block = workspace
|
|
48
|
+
const block = workspace.getBlockById(this.blockId)
|
|
45
49
|
const comment = block?.getIcon(Blockly.icons.IconType.COMMENT)
|
|
46
50
|
comment?.setBubbleSize(forward ? this.newSize : this.oldSize)
|
|
47
51
|
}
|
|
@@ -24,7 +24,11 @@ export class BlockDragEnd extends Blockly.Events.BlockBase {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
static fromJson(
|
|
27
|
+
static fromJson(
|
|
28
|
+
json: BlockDragEndJson,
|
|
29
|
+
workspace: Blockly.Workspace,
|
|
30
|
+
event?: Blockly.Events.Abstract,
|
|
31
|
+
): BlockDragEnd {
|
|
28
32
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockDragEnd()) as BlockDragEnd
|
|
29
33
|
newEvent.isOutside = json.isOutside
|
|
30
34
|
newEvent.xml = Blockly.utils.xml.textToDom(json.xml)
|
|
@@ -21,7 +21,11 @@ export class BlockDragOutside extends Blockly.Events.BlockBase {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
static fromJson(
|
|
24
|
+
static fromJson(
|
|
25
|
+
json: BlockDragOutsideJson,
|
|
26
|
+
workspace: Blockly.Workspace,
|
|
27
|
+
event?: Blockly.Events.Abstract,
|
|
28
|
+
): BlockDragOutside {
|
|
25
29
|
const newEvent = super.fromJson(json, workspace, event ?? new BlockDragOutside()) as BlockDragOutside
|
|
26
30
|
newEvent.isOutside = json.isOutside
|
|
27
31
|
|
|
@@ -25,7 +25,11 @@ class ScratchVariableCreate extends Blockly.Events.VarCreate {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
static fromJson(
|
|
28
|
+
static fromJson(
|
|
29
|
+
json: ScratchVariableCreateJson,
|
|
30
|
+
workspace: Blockly.Workspace,
|
|
31
|
+
event?: Blockly.Events.Abstract,
|
|
32
|
+
): ScratchVariableCreate {
|
|
29
33
|
const newEvent = super.fromJson(json, workspace, event ?? new ScratchVariableCreate()) as ScratchVariableCreate
|
|
30
34
|
newEvent.isLocal = json.isLocal
|
|
31
35
|
newEvent.isCloud = json.isCloud
|
|
@@ -96,7 +96,7 @@ export class FieldColourSlider extends FieldColour {
|
|
|
96
96
|
stops.push(Blockly.utils.colour.hsvToHex(this.hue_, this.saturation_, (255 * n) / 360))
|
|
97
97
|
break
|
|
98
98
|
default:
|
|
99
|
-
throw new Error(
|
|
99
|
+
throw new Error(`Unknown channel for colour sliders: ${String(channel)}`)
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
return stops
|
|
@@ -198,9 +198,7 @@ export class FieldColourSlider extends FieldColour {
|
|
|
198
198
|
break
|
|
199
199
|
}
|
|
200
200
|
const colour = Blockly.utils.colour.hsvToHex(this.hue_, this.saturation_, this.brightness_)
|
|
201
|
-
|
|
202
|
-
this.setValue(colour, true)
|
|
203
|
-
}
|
|
201
|
+
this.setValue(colour, true)
|
|
204
202
|
}
|
|
205
203
|
}
|
|
206
204
|
|
|
@@ -279,7 +277,7 @@ export class FieldColourSlider extends FieldColour {
|
|
|
279
277
|
button,
|
|
280
278
|
'click',
|
|
281
279
|
this,
|
|
282
|
-
this.activateEyedropperInternal_,
|
|
280
|
+
this.activateEyedropperInternal_.bind(this),
|
|
283
281
|
)
|
|
284
282
|
}
|
|
285
283
|
|
|
@@ -210,7 +210,7 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
210
210
|
this.arrow_.setAttributeNS(
|
|
211
211
|
'http://www.w3.org/1999/xlink',
|
|
212
212
|
'xlink:href',
|
|
213
|
-
this.getConstants()
|
|
213
|
+
this.getConstants()?.FIELD_DROPDOWN_SVG_ARROW_DATAURI ?? '',
|
|
214
214
|
)
|
|
215
215
|
this.arrow_.style.cursor = 'default'
|
|
216
216
|
}
|
|
@@ -241,7 +241,7 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
241
241
|
} else if (this.borderRect_) {
|
|
242
242
|
this.borderRect_.setAttribute(
|
|
243
243
|
'fill',
|
|
244
|
-
'colourQuaternary' in style ?
|
|
244
|
+
'colourQuaternary' in style ? String(style.colourQuaternary) : style.colourTertiary,
|
|
245
245
|
)
|
|
246
246
|
}
|
|
247
247
|
|
|
@@ -299,17 +299,22 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
299
299
|
|
|
300
300
|
Blockly.DropDownDiv.showPositionedByBlock(this, sourceBlock, this.dropdownDispose_.bind(this))
|
|
301
301
|
|
|
302
|
-
this.matrixTouchWrapper_ = Blockly.browserEvents.bind(
|
|
303
|
-
|
|
304
|
-
|
|
302
|
+
this.matrixTouchWrapper_ = Blockly.browserEvents.bind(
|
|
303
|
+
this.matrixStage_,
|
|
304
|
+
'mousedown',
|
|
305
|
+
this,
|
|
306
|
+
this.onMouseDown.bind(this),
|
|
307
|
+
)
|
|
308
|
+
this.clearButtonWrapper_ = Blockly.browserEvents.bind(clearButton, 'click', this, this.clearMatrix_.bind(this))
|
|
309
|
+
this.fillButtonWrapper_ = Blockly.browserEvents.bind(fillButton, 'click', this, this.fillMatrix_.bind(this))
|
|
305
310
|
|
|
306
311
|
// Update the matrix for the current value
|
|
307
312
|
this.updateMatrix_()
|
|
308
313
|
}
|
|
309
314
|
|
|
310
315
|
dropdownDispose_() {
|
|
311
|
-
const sourceBlock = this.getSourceBlock()
|
|
312
|
-
if (sourceBlock
|
|
316
|
+
const sourceBlock = this.getSourceBlock()
|
|
317
|
+
if (sourceBlock?.isShadow()) {
|
|
313
318
|
sourceBlock.setStyle(this.originalStyle)
|
|
314
319
|
}
|
|
315
320
|
this.updateMatrix_()
|
|
@@ -355,10 +360,12 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
355
360
|
* Redraw the matrix with the current value.
|
|
356
361
|
*/
|
|
357
362
|
private updateMatrix_() {
|
|
358
|
-
const matrix = this.getValue()
|
|
359
|
-
|
|
363
|
+
const matrix = this.getValue()
|
|
364
|
+
if (!matrix) return
|
|
365
|
+
const sourceBlock = this.getSourceBlock() as Blockly.BlockSvg | null
|
|
366
|
+
if (!sourceBlock) return
|
|
360
367
|
for (let i = 0; i < matrix.length; i++) {
|
|
361
|
-
if (matrix[i] === LEDState.OFF) {
|
|
368
|
+
if ((matrix[i] as LEDState) === LEDState.OFF) {
|
|
362
369
|
this.fillMatrixNode_(this.ledButtons_, i, sourceBlock.getColourTertiary())
|
|
363
370
|
this.fillMatrixNode_(this.ledThumbNodes_, i, sourceBlock.getColourSecondary())
|
|
364
371
|
} else {
|
|
@@ -393,13 +400,14 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
393
400
|
* @param fill The fill colour in '#rrggbb' format.
|
|
394
401
|
*/
|
|
395
402
|
fillMatrixNode_(node: SVGElement[], index: number, fill: string) {
|
|
396
|
-
if (!node
|
|
403
|
+
if (!node[index] || !fill) return
|
|
397
404
|
node[index].setAttribute('fill', fill)
|
|
398
405
|
}
|
|
399
406
|
|
|
400
407
|
setLEDNode_(led: number, state: LEDState) {
|
|
401
408
|
if (led < 0 || led > 24) return
|
|
402
|
-
const oldMatrix = this.getValue()
|
|
409
|
+
const oldMatrix = this.getValue()
|
|
410
|
+
if (!oldMatrix) return
|
|
403
411
|
const newMatrix = oldMatrix.substr(0, led) + state + oldMatrix.substr(led + 1)
|
|
404
412
|
this.setValue(newMatrix)
|
|
405
413
|
}
|
|
@@ -416,7 +424,9 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
416
424
|
|
|
417
425
|
toggleLEDNode_(led: number) {
|
|
418
426
|
if (led < 0 || led > 24) return
|
|
419
|
-
|
|
427
|
+
const value = this.getValue()
|
|
428
|
+
if (!value) return
|
|
429
|
+
if ((value.charAt(led) as LEDState) === LEDState.OFF) {
|
|
420
430
|
this.setLEDNode_(led, LEDState.ON)
|
|
421
431
|
} else {
|
|
422
432
|
this.setLEDNode_(led, LEDState.OFF)
|
|
@@ -428,11 +438,17 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
428
438
|
* @param e Mouse event.
|
|
429
439
|
*/
|
|
430
440
|
onMouseDown(e: PointerEvent) {
|
|
431
|
-
this.matrixMoveWrapper_ = Blockly.browserEvents.bind(
|
|
432
|
-
|
|
441
|
+
this.matrixMoveWrapper_ = Blockly.browserEvents.bind(
|
|
442
|
+
document.body,
|
|
443
|
+
'mousemove',
|
|
444
|
+
this,
|
|
445
|
+
this.onMouseMove.bind(this),
|
|
446
|
+
)
|
|
447
|
+
this.matrixReleaseWrapper_ = Blockly.browserEvents.bind(document.body, 'mouseup', this, this.onMouseUp.bind(this))
|
|
433
448
|
const ledHit = this.checkForLED_(e)
|
|
434
449
|
if (ledHit > -1) {
|
|
435
|
-
|
|
450
|
+
const value = this.getValue()
|
|
451
|
+
if (value && (value.charAt(ledHit) as LEDState) === LEDState.OFF) {
|
|
436
452
|
this.paintStyle_ = PaintStyle.FILL
|
|
437
453
|
} else {
|
|
438
454
|
this.paintStyle_ = PaintStyle.CLEAR
|
|
@@ -470,7 +486,7 @@ class FieldMatrix extends Blockly.Field<string> {
|
|
|
470
486
|
if (led < 0) return
|
|
471
487
|
if (this.paintStyle_ === PaintStyle.CLEAR) {
|
|
472
488
|
this.clearLEDNode_(led)
|
|
473
|
-
} else
|
|
489
|
+
} else {
|
|
474
490
|
this.fillLEDNode_(led)
|
|
475
491
|
}
|
|
476
492
|
}
|
package/src/fields/field_note.ts
CHANGED
|
@@ -284,6 +284,12 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
284
284
|
*/
|
|
285
285
|
showEditor_(event: PointerEvent, quietInput = false) {
|
|
286
286
|
super.showEditor_(event, quietInput, false)
|
|
287
|
+
const parentBlock = this.getSourceBlock()?.getParent() as Blockly.BlockSvg | undefined
|
|
288
|
+
if (!parentBlock) {
|
|
289
|
+
throw new Error('[field_note] Missing parent block for note field editor')
|
|
290
|
+
}
|
|
291
|
+
const parentColour = parentBlock.getColour()
|
|
292
|
+
const parentTertiary = parentBlock.getColourTertiary()
|
|
287
293
|
|
|
288
294
|
// Build the SVG DOM.
|
|
289
295
|
const div = Blockly.DropDownDiv.getContentDiv()
|
|
@@ -314,9 +320,21 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
314
320
|
// Add three piano octaves, so we can animate moving up or down an octave.
|
|
315
321
|
// Only the middle octave gets bound to events.
|
|
316
322
|
this.keySVGs_ = []
|
|
317
|
-
this.addPianoOctave_(
|
|
318
|
-
|
|
319
|
-
|
|
323
|
+
this.addPianoOctave_(
|
|
324
|
+
-this.fieldEditorWidth_ + FieldNote.EDGE_PADDING,
|
|
325
|
+
whiteKeyGroup,
|
|
326
|
+
blackKeyGroup,
|
|
327
|
+
null,
|
|
328
|
+
parentBlock,
|
|
329
|
+
)
|
|
330
|
+
this.addPianoOctave_(0, whiteKeyGroup, blackKeyGroup, this.keySVGs_, parentBlock)
|
|
331
|
+
this.addPianoOctave_(
|
|
332
|
+
this.fieldEditorWidth_ - FieldNote.EDGE_PADDING,
|
|
333
|
+
whiteKeyGroup,
|
|
334
|
+
blackKeyGroup,
|
|
335
|
+
null,
|
|
336
|
+
parentBlock,
|
|
337
|
+
)
|
|
320
338
|
|
|
321
339
|
// Note name indicator at the top of the field
|
|
322
340
|
this.noteNameText_ = Blockly.utils.dom.createSvgElement(
|
|
@@ -341,7 +359,7 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
341
359
|
Blockly.utils.dom.createSvgElement(
|
|
342
360
|
'line',
|
|
343
361
|
{
|
|
344
|
-
stroke:
|
|
362
|
+
stroke: parentTertiary,
|
|
345
363
|
x1: 0,
|
|
346
364
|
y1: FieldNote.TOP_MENU_HEIGHT,
|
|
347
365
|
x2: this.fieldEditorWidth_,
|
|
@@ -365,11 +383,12 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
365
383
|
)
|
|
366
384
|
|
|
367
385
|
// Octave buttons
|
|
368
|
-
const octaveDownButton = this.addOctaveButton_(0, true, svg)
|
|
386
|
+
const octaveDownButton = this.addOctaveButton_(0, true, svg, parentBlock)
|
|
369
387
|
const octaveUpButton = this.addOctaveButton_(
|
|
370
388
|
this.fieldEditorWidth_ + FieldNote.INSET * 2 - FieldNote.OCTAVE_BUTTON_SIZE,
|
|
371
389
|
false,
|
|
372
390
|
svg,
|
|
391
|
+
parentBlock,
|
|
373
392
|
)
|
|
374
393
|
|
|
375
394
|
this.octaveDownMouseDownWrapper_ = Blockly.browserEvents.bind(octaveDownButton, 'mousedown', this, () => {
|
|
@@ -379,8 +398,9 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
379
398
|
this.changeOctaveBy_(1)
|
|
380
399
|
})
|
|
381
400
|
const sourceBlock = this.getSourceBlock() as Blockly.BlockSvg
|
|
382
|
-
Blockly.
|
|
383
|
-
Blockly.DropDownDiv.
|
|
401
|
+
const dropdownAnchor = this as unknown as Blockly.Field<string | null>
|
|
402
|
+
Blockly.DropDownDiv.setColour(parentColour, parentTertiary)
|
|
403
|
+
Blockly.DropDownDiv.showPositionedByBlock(dropdownAnchor, sourceBlock)
|
|
384
404
|
|
|
385
405
|
this.updateSelection_()
|
|
386
406
|
}
|
|
@@ -391,14 +411,17 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
391
411
|
* @param whiteKeyGroup The group for all white piano keys.
|
|
392
412
|
* @param blackKeyGroup The group for all black piano keys.
|
|
393
413
|
* @param keySVGarray An array containing all the key SVGs.
|
|
414
|
+
* @param parentBlock The validated parent block providing styling.
|
|
394
415
|
*/
|
|
395
416
|
private addPianoOctave_(
|
|
396
417
|
x: number,
|
|
397
418
|
whiteKeyGroup: SVGElement,
|
|
398
419
|
blackKeyGroup: SVGElement,
|
|
399
420
|
keySVGarray: SVGElement[] | null,
|
|
421
|
+
parentBlock: Blockly.BlockSvg,
|
|
400
422
|
) {
|
|
401
423
|
let xIncrement, width, height, fill, stroke, group
|
|
424
|
+
const parentTertiary = parentBlock.getColourTertiary()
|
|
402
425
|
x += FieldNote.EDGE_PADDING / 2
|
|
403
426
|
const y = FieldNote.TOP_MENU_HEIGHT
|
|
404
427
|
for (let i = 0; i < FieldNote.KEY_INFO.length; i++) {
|
|
@@ -417,7 +440,7 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
417
440
|
width = FieldNote.WHITE_KEY_WIDTH
|
|
418
441
|
height = FieldNote.WHITE_KEY_HEIGHT
|
|
419
442
|
fill = FieldNote.WHITE_KEY_COLOR
|
|
420
|
-
stroke =
|
|
443
|
+
stroke = parentTertiary
|
|
421
444
|
group = whiteKeyGroup
|
|
422
445
|
}
|
|
423
446
|
const attr = {
|
|
@@ -435,8 +458,18 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
435
458
|
keySVG.setAttribute('data-name', `${FieldNote.KEY_INFO[i].name}`)
|
|
436
459
|
keySVG.setAttribute('data-isBlack', `${FieldNote.KEY_INFO[i].isBlack}`)
|
|
437
460
|
|
|
438
|
-
this.mouseDownWrappers_[i] = Blockly.browserEvents.bind(
|
|
439
|
-
|
|
461
|
+
this.mouseDownWrappers_[i] = Blockly.browserEvents.bind(
|
|
462
|
+
keySVG,
|
|
463
|
+
'mousedown',
|
|
464
|
+
this,
|
|
465
|
+
this.onMouseDownOnKey_.bind(this),
|
|
466
|
+
)
|
|
467
|
+
this.mouseEnterWrappers_[i] = Blockly.browserEvents.bind(
|
|
468
|
+
keySVG,
|
|
469
|
+
'mouseenter',
|
|
470
|
+
this,
|
|
471
|
+
this.onMouseEnter_.bind(this),
|
|
472
|
+
)
|
|
440
473
|
}
|
|
441
474
|
}
|
|
442
475
|
}
|
|
@@ -502,10 +535,12 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
502
535
|
* @param x The x position of the button.
|
|
503
536
|
* @param flipped If true, the icon should be flipped.
|
|
504
537
|
* @param svg The svg element to add the buttons to.
|
|
538
|
+
* @param parentBlock The validated parent block providing styling.
|
|
505
539
|
* @returns A group containing the button SVG elements.
|
|
506
540
|
*/
|
|
507
|
-
private addOctaveButton_(x: number, flipped: boolean, svg: SVGElement): SVGElement {
|
|
541
|
+
private addOctaveButton_(x: number, flipped: boolean, svg: SVGElement, parentBlock: Blockly.BlockSvg): SVGElement {
|
|
508
542
|
const group = Blockly.utils.dom.createSvgElement('g', {}, svg)
|
|
543
|
+
const parentTertiary = parentBlock.getColourTertiary()
|
|
509
544
|
const imageSize = FieldNote.OCTAVE_BUTTON_SIZE
|
|
510
545
|
const arrow = Blockly.utils.dom.createSvgElement(
|
|
511
546
|
'image',
|
|
@@ -525,7 +560,7 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
525
560
|
Blockly.utils.dom.createSvgElement(
|
|
526
561
|
'line',
|
|
527
562
|
{
|
|
528
|
-
stroke:
|
|
563
|
+
stroke: parentTertiary,
|
|
529
564
|
x1: x - FieldNote.INSET,
|
|
530
565
|
y1: 0,
|
|
531
566
|
x2: x - FieldNote.INSET,
|
|
@@ -588,7 +623,7 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
588
623
|
*/
|
|
589
624
|
private onMouseDownOnKey_(e: PointerEvent) {
|
|
590
625
|
this.mouseIsDown_ = true
|
|
591
|
-
this.mouseUpWrapper_ = Blockly.browserEvents.bind(document.body, 'mouseup', this, this.onMouseUp_)
|
|
626
|
+
this.mouseUpWrapper_ = Blockly.browserEvents.bind(document.body, 'mouseup', this, this.onMouseUp_.bind(this))
|
|
592
627
|
this.selectNoteWithMouseEvent_(e)
|
|
593
628
|
}
|
|
594
629
|
|
|
@@ -628,18 +663,19 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
628
663
|
* Play a note, by calling the externally overriden play note function.
|
|
629
664
|
*/
|
|
630
665
|
private playNoteInternal_() {
|
|
631
|
-
|
|
632
|
-
|
|
666
|
+
const noteNum = this.getValue()
|
|
667
|
+
if (FieldNote.playNote_ && noteNum !== null) {
|
|
668
|
+
FieldNote.playNote_(Number(noteNum), 'Music')
|
|
633
669
|
}
|
|
634
670
|
}
|
|
635
671
|
|
|
636
672
|
/**
|
|
637
673
|
* Function to play a musical note corresponding to the key selected.
|
|
638
674
|
* Overridden externally.
|
|
639
|
-
* @param
|
|
640
|
-
* @param
|
|
675
|
+
* @param _noteNum the MIDI note number to play.
|
|
676
|
+
* @param _id An id to select a scratch extension to play the note.
|
|
641
677
|
*/
|
|
642
|
-
static playNote_ = function (
|
|
678
|
+
static playNote_: ((noteNum: number, id: string) => void) | null = function (_noteNum: number, _id: string) {
|
|
643
679
|
return
|
|
644
680
|
}
|
|
645
681
|
|
|
@@ -739,7 +775,7 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
739
775
|
this.noteNameText_.textContent = noteName + ' (' + Math.floor(noteNum) + ')'
|
|
740
776
|
}
|
|
741
777
|
// Update the low and high C note names
|
|
742
|
-
const lowCNum =
|
|
778
|
+
const lowCNum = this.displayedOctave_ * 12
|
|
743
779
|
if (this.lowCText_) this.lowCText_.textContent = 'C(' + lowCNum + ')'
|
|
744
780
|
if (this.highCText_) this.highCText_.textContent = 'C(' + (lowCNum + 12) + ')'
|
|
745
781
|
}
|
|
@@ -750,7 +786,7 @@ export class FieldNote extends Blockly.FieldTextInput {
|
|
|
750
786
|
* @param text The user's text.
|
|
751
787
|
* @returns A string representing a valid note number, or null if invalid.
|
|
752
788
|
*/
|
|
753
|
-
doClassValidation_(text: string): string | null {
|
|
789
|
+
doClassValidation_(text: string | null): string | null {
|
|
754
790
|
if (text === null) {
|
|
755
791
|
return null
|
|
756
792
|
}
|