-
Notifications
You must be signed in to change notification settings - Fork 638
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
684 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* @license | ||
* Copyright 2024 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import { | ||
JsonDefinitionGenerator, | ||
Order, | ||
jsonDefinitionGenerator, | ||
} from './json_definition_generator'; | ||
import * as Blockly from 'blockly/core'; | ||
|
||
/** | ||
* JSON definition for the "input" block. | ||
* | ||
* @param block | ||
* @param generator | ||
* @returns The stringified JSON representing the stack of input blocks. | ||
* The entire stack will be returned due to the `scrub_` function. | ||
* The JSON returned here should be part of the `args0` of the JSON | ||
* in the final block definition. | ||
*/ | ||
jsonDefinitionGenerator.forBlock['colour_hue'] = function ( | ||
block: Blockly.Block, | ||
generator: JsonDefinitionGenerator, | ||
): [string, number] { | ||
return [this.getFieldValue('HUE').toString(), Order.ATOMIC]; | ||
}; |
81 changes: 81 additions & 0 deletions
81
examples/developer-tools/src/output-generators/connection_check.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/** | ||
* @license | ||
* Copyright 2024 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import * as Blockly from 'blockly/core'; | ||
import { | ||
JsonDefinitionGenerator, | ||
Order, | ||
jsonDefinitionGenerator, | ||
} from './json_definition_generator'; | ||
|
||
/** | ||
* JSON definition for a single "connection_check" block. | ||
* | ||
* @param block | ||
* @param generator | ||
* @returns A connection check string corresponding to the option chosen. | ||
* If custom option is chosen and not specified, returns null. | ||
*/ | ||
jsonDefinitionGenerator.forBlock['connection_check'] = function ( | ||
block: Blockly.Block, | ||
generator: JsonDefinitionGenerator, | ||
): [string, number] { | ||
const selected = block.getFieldValue('CHECKDROPDOWN'); | ||
let output = ''; | ||
switch (selected) { | ||
case 'null': { | ||
output = null; | ||
break; | ||
} | ||
case 'CUSTOM': { | ||
output = block.getFieldValue('CUSTOMCHECK') || null; | ||
break; | ||
} | ||
default: { | ||
output = selected; | ||
} | ||
} | ||
|
||
return [JSON.stringify(output), Order.ATOMIC]; | ||
}; | ||
|
||
/** | ||
* JSON Definition for the "any of" check block. | ||
* | ||
* @param block | ||
* @param generator | ||
* @returns stringified version of: | ||
* - null if the list is empty or contains the "any" check | ||
* - a single check string if that is the only check present in the list | ||
* - an array of all checks in the list, deduplicated | ||
*/ | ||
jsonDefinitionGenerator.forBlock['connection_check_group'] = function ( | ||
block: Blockly.Block, | ||
generator: JsonDefinitionGenerator, | ||
): [string, number] { | ||
const checks = new Set<string>(); | ||
for (const input of block.inputList) { | ||
const value = generator.valueToCode(block, input.name, Order.ATOMIC); | ||
if (!value) continue; // No block connected to this input | ||
const check = JSON.parse(value) || ''; | ||
if (check === null) { | ||
// If the list contains 'any' then the check is simplified to 'any' | ||
return [JSON.stringify(null), Order.ATOMIC]; | ||
} | ||
if (check) checks.add(check); | ||
} | ||
|
||
if (checks.size === 0) { | ||
// No checks were connected to the block. | ||
return [JSON.stringify(null), Order.ATOMIC]; | ||
} | ||
if (checks.size === 1) { | ||
// If there's only one check, we return it directly instead of | ||
// returning an array with one member. | ||
return [JSON.stringify(Array.from(checks)[0]), Order.ATOMIC]; | ||
} | ||
return [JSON.stringify(Array.from(checks)), Order.ATOMIC]; | ||
}; |
125 changes: 125 additions & 0 deletions
125
examples/developer-tools/src/output-generators/factory_base.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/** | ||
* @license | ||
* Copyright 2024 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import * as Blockly from 'blockly/core'; | ||
import {javascriptGenerator} from 'blockly/javascript'; | ||
import { | ||
JsonDefinitionGenerator, | ||
jsonDefinitionGenerator, | ||
Order, | ||
} from './json_definition_generator'; | ||
|
||
/** | ||
* Builds the 'message0' part of the JSON block definition. | ||
* The message should have label fields' text inlined into the message. | ||
* Doing so makes the message more translatable as fields can be moved around. | ||
* | ||
* @param argsList The list of fields and inputs generated from the input stack. | ||
* @returns An object containing: | ||
* - a message string with one placeholder '%i` | ||
* for each field and input in the block | ||
* - the new args list, with label fields removed | ||
*/ | ||
const buildMessageString = function (argsList: Array<Record<string, unknown>>) { | ||
let i = 0; | ||
let messageString = ''; | ||
const newArgs = []; | ||
for (const arg of argsList) { | ||
if (arg.type === 'field_label') { | ||
// Label fields get added directly to the message string. | ||
// They are removed from the arg list so they don't appear twice. | ||
messageString += `${arg.text} `; | ||
} else { | ||
i++; | ||
messageString += `%${i} `; | ||
newArgs.push(arg); | ||
} | ||
} | ||
|
||
return { | ||
message: messageString.trim(), | ||
args: newArgs, | ||
}; | ||
}; | ||
|
||
jsonDefinitionGenerator.forBlock['factory_base'] = function ( | ||
block: Blockly.Block, | ||
generator: JsonDefinitionGenerator, | ||
): string { | ||
// TODO: Get a JSON-legal name for the block | ||
const blockName = block.getFieldValue('NAME'); | ||
// Tooltip and Helpurl string blocks can't be removed, so we don't care what happens if the block doesn't exist | ||
const tooltip = JSON.parse( | ||
generator.valueToCode(block, 'TOOLTIP', Order.ATOMIC), | ||
); | ||
const helpUrl = JSON.parse( | ||
generator.valueToCode(block, 'HELPURL', Order.ATOMIC), | ||
); | ||
|
||
const code: {[key: string]: unknown} = { | ||
type: blockName, | ||
tooltip: tooltip, | ||
helpUrl: helpUrl, | ||
}; | ||
|
||
const inputsStack = generator.statementToCode(block, 'INPUTS'); | ||
if (inputsStack) { | ||
// If there is a stack, they come back as the inner pieces of an array | ||
// Can possibly fix this in scrub? | ||
const args0 = JSON.parse(`[${inputsStack}]`); | ||
const {args, message} = buildMessageString(args0); | ||
code.message0 = message; | ||
code.args0 = args; | ||
} else { | ||
code.message0 = ''; | ||
} | ||
|
||
/** | ||
* Sets the connection check for the given input, if present. If the input exists | ||
* but doesn't have a block attached or a value, the connection property is | ||
* still added to the output with a check of 'null'. If the input doesn't | ||
* exist, that means the block should not have that type of connection, and no | ||
* property is added to the output. | ||
* | ||
* @param inputName The name of the input that would contain the type check. | ||
* @param connectionName The name of the connection in the definition output. | ||
*/ | ||
const setConnectionChecks = (inputName: string, connectionName: string) => { | ||
if (this.getInput(inputName)) { | ||
// If there is no set type, we still need to add 'null` to the check | ||
const output = generator.valueToCode(block, inputName, Order.ATOMIC); | ||
code[connectionName] = output ? JSON.parse(output) : null; | ||
} | ||
}; | ||
|
||
setConnectionChecks('OUTPUTCHECK', 'output'); | ||
setConnectionChecks('TOPCHECK', 'previousStatement'); | ||
setConnectionChecks('BOTTOMCHECK', 'nextStatement'); | ||
|
||
const colour = generator.valueToCode(block, 'COLOUR', Order.ATOMIC); | ||
if (colour !== '') { | ||
code.colour = JSON.parse(colour); | ||
} | ||
|
||
const inputsAlign = block.getFieldValue('INLINE'); | ||
switch (inputsAlign) { | ||
case 'EXT': { | ||
code.inputsInline = false; | ||
break; | ||
} | ||
case 'INT': { | ||
code.inputsInline = true; | ||
break; | ||
} | ||
default: { | ||
// Don't add anything for "auto". | ||
} | ||
} | ||
|
||
return JSON.stringify(code, undefined, 2); | ||
}; | ||
|
||
jsonDefinitionGenerator.forBlock['text'] = javascriptGenerator.forBlock['text']; |
23 changes: 23 additions & 0 deletions
23
examples/developer-tools/src/output-generators/fields/checkbox.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* @license | ||
* Copyright 2024 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import * as Blockly from 'blockly/core'; | ||
import { | ||
JsonDefinitionGenerator, | ||
jsonDefinitionGenerator, | ||
} from '../json_definition_generator'; | ||
|
||
jsonDefinitionGenerator.forBlock['field_checkbox'] = function ( | ||
block: Blockly.Block, | ||
generator: JsonDefinitionGenerator, | ||
): string { | ||
const code = { | ||
type: 'field_checkbox', | ||
name: block.getFieldValue('FIELDNAME'), | ||
checked: block.getFieldValue('CHECKED'), | ||
}; | ||
return JSON.stringify(code); | ||
}; |
34 changes: 34 additions & 0 deletions
34
examples/developer-tools/src/output-generators/fields/dropdown.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/** | ||
* @license | ||
* Copyright 2024 Google LLC | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import { | ||
JsonDefinitionGenerator, | ||
jsonDefinitionGenerator, | ||
} from '../json_definition_generator'; | ||
import {DropdownOptionData, FieldDropdownBlock} from '../../blocks/fields'; | ||
|
||
jsonDefinitionGenerator.forBlock['field_dropdown'] = function ( | ||
block: FieldDropdownBlock, | ||
generator: JsonDefinitionGenerator, | ||
): string { | ||
const code: Record<string, string | Array<[DropdownOptionData, string]>> = { | ||
type: 'field_dropdown', | ||
name: block.getFieldValue('FIELDNAME'), | ||
}; | ||
const options: Array<[DropdownOptionData, string]> = []; | ||
for (let i = 0; i < block.optionList.length; i++) { | ||
options.push([block.getUserData(i), block.getFieldValue('CPU' + i)]); | ||
} | ||
|
||
if (options.length === 0) { | ||
// If there are no options in the dropdown, the field isn't valid. | ||
// Remove it from the list of fields by returning an empty string. | ||
return ''; | ||
} | ||
|
||
code.options = options; | ||
return JSON.stringify(code); | ||
}; |
Oops, something went wrong.