UNPKG

@mixly/micropython

Version:
623 lines (598 loc) 24.4 kB
import * as Blockly from 'blockly/core'; const LOOPS_HUE = 120//'#EB8045'; export const base_setup = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.MIXLY_SETUP); this.appendStatementInput('DO') .appendField(''); this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_SETUP); } }; export const controls_delay = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.MIXLY_DELAY) this.appendDummyInput("") .appendField(new Blockly.FieldDropdown([ [Blockly.Msg.MIXLY_SECOND, "s"], [Blockly.Msg.MIXLY_mSecond, "ms"], [Blockly.Msg.MIXLY_uSecond, "us"] ]), 'Time'); this.appendValueInput("DELAY_TIME", Number) .setCheck(Number); this.setFieldValue('ms', 'Time') this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setInputsInline(true); this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_DELAY); } }; export const Panic_with_status_code = { init: function () { this.setColour(LOOPS_HUE); this.appendValueInput("STATUS_CODE", Number) .appendField(Blockly.Msg.MIXLY_MICROBIT_Panic_with_status_code) .setCheck(Number); this.setPreviousStatement(true, null); // this.setNextStatement(true, null); this.setInputsInline(true); this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Panic_with_status_code); } }; export const reset = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_micro); this.setPreviousStatement(true); // this.setNextStatement(true); this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Reset_micro); } }; export const controls_for = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_WITH) .appendField(new Blockly.FieldTextInput('i'), 'VAR'); this.appendValueInput('FROM') .setCheck(Number) .setAlign(Blockly.inputs.Align.RIGHT) .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_FROM); this.appendValueInput('TO') .setCheck(Number) .setAlign(Blockly.inputs.Align.RIGHT) .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_TO); this.appendValueInput('STEP') .setCheck(Number) .setAlign(Blockly.inputs.Align.RIGHT) .appendField(Blockly.Msg.MIXLY_STEP); this.appendStatementInput('DO') .appendField(Blockly.Msg.MIXLY_DO); this.setPreviousStatement(true); this.setNextStatement(true); this.setInputsInline(true); var thisBlock = this; this.setTooltip(function () { return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1', thisBlock.getFieldValue('VAR')); }); }, getVars: function () { return [this.getFieldValue('VAR')]; }, renameVar: function (oldName, newName) { if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { this.setTitleValue(newName, 'VAR'); } } }; export const controls_whileUntil = { init: function () { this.setColour(LOOPS_HUE); this.appendValueInput('BOOL') .setCheck([Boolean, Number]) .appendField(Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_TITLE_REPEAT) .appendField(new Blockly.FieldDropdown(controls_whileUntil.OPERATORS), 'MODE'); this.appendStatementInput('DO') .appendField(Blockly.Msg.MIXLY_DO); this.setPreviousStatement(true); this.setNextStatement(true); var thisBlock = this; this.setTooltip(function () { var op = thisBlock.getFieldValue('MODE'); var TOOLTIPS = { 'WHILE': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE, 'UNTIL': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL }; return TOOLTIPS[op]; }); }, OPERATORS: [ [Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'], [Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, 'UNTIL'] ] }; export const controls_flow_statements = { init: function () { this.setColour(LOOPS_HUE); var dropdown = new Blockly.FieldDropdown(controls_flow_statements.OPERATORS); this.appendDummyInput() .appendField(dropdown, 'FLOW') .appendField(Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_INPUT_OFLOOP); this.setPreviousStatement(true); var thisBlock = this; this.setTooltip(function () { var op = thisBlock.getFieldValue('FLOW'); var TOOLTIPS = { 'BREAK': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK, 'CONTINUE': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE }; return TOOLTIPS[op]; }); }, onchange: function () { if (!this.workspace) { // Block has been deleted. return; } var legal = false; // Is the block nested in a control statement? var block = this; do { if (block.type == 'controls_repeat' || block.type == 'controls_for' || block.type == 'controls_forEach' || block.type == 'controls_repeat_ext' || block.type == 'controls_whileUntil') { legal = true; break; } block = block.getSurroundParent(); } while (block); if (legal) { this.setWarningText(null); } else { this.setWarningText(Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_WARNING); } }, OPERATORS: [ [Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'], [Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE, 'CONTINUE'] ] }; export const controls_millis = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.MIXLY_RUNTIME); this.appendDummyInput("") .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_mSecond, "ms"], [Blockly.Msg.MIXLY_uSecond, "us"]]), 'Time'); this.setOutput(true, Number); this.setInputsInline(true); this.setTooltip(Blockly.Msg.MIXLY_RUNTIME); } }; export const controls_if = { /** * Block for if/elseif/else condition. * @this Blockly.Block */ init: function () { //this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL); this.setColour(LOOPS_HUE); this.appendValueInput('IF0') .setCheck([Boolean, Number]) .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF); this.appendStatementInput('DO0') .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN); this.setPreviousStatement(true); this.setNextStatement(true); this.setHelpUrl("https://mixly.readthedocs.io/zh_CN/latest/arduino/03.Control.html#if"); this.setMutator(new Blockly.icons.MutatorIcon(['controls_if_elseif', 'controls_if_else'], this)); // Assign 'this' to a variable for use in the tooltip closure below. var thisBlock = this; this.setTooltip(function () { if (!thisBlock.elseifCount_ && !thisBlock.elseCount_) { return Blockly.Msg.CONTROLS_IF_TOOLTIP_1; } else if (!thisBlock.elseifCount_ && thisBlock.elseCount_) { return Blockly.Msg.CONTROLS_IF_TOOLTIP_2; } else if (thisBlock.elseifCount_ && !thisBlock.elseCount_) { return Blockly.Msg.CONTROLS_IF_TOOLTIP_3; } else if (thisBlock.elseifCount_ && thisBlock.elseCount_) { return Blockly.Msg.CONTROLS_IF_TOOLTIP_4; } return ''; }); this.elseifCount_ = 0; this.elseCount_ = 0; }, /** * Create XML to represent the number of else-if and else inputs. * @return {Element} XML storage element. * @this Blockly.Block */ mutationToDom: function () { if (!this.elseifCount_ && !this.elseCount_) { return null; } var container = document.createElement('mutation'); if (this.elseifCount_) { container.setAttribute('elseif', this.elseifCount_); } if (this.elseCount_) { container.setAttribute('else', 1); } return container; }, /** * Parse XML to restore the else-if and else inputs. * @param {!Element} xmlElement XML storage element. * @this Blockly.Block */ domToMutation: function (xmlElement) { var containerBlock = this; var valueConnections = []; var statementConnections = []; // var elseStatementConnection = null; if (this.elseCount_) { // if (containerBlock.getInputTargetBlock('ELSE') && containerBlock.getInputTargetBlock('ELSE').previousConnection) // elseStatementConnection = containerBlock.getInputTargetBlock('ELSE').previousConnection; this.removeInput('ELSE'); } for (var i = this.elseifCount_; i > 0; i--) { if (containerBlock.getInputTargetBlock('IF' + i) && containerBlock.getInputTargetBlock('IF' + i).previousConnection) valueConnections[i] = (containerBlock.getInputTargetBlock('IF' + i).previousConnection); else valueConnections[i] = null; this.removeInput('IF' + i); if (containerBlock.getInputTargetBlock('DO' + i) && containerBlock.getInputTargetBlock('DO' + i).previousConnection) statementConnections[i] = (containerBlock.getInputTargetBlock('DO' + i).previousConnection); else statementConnections[i] = null; this.removeInput('DO' + i); } this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10); this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10); //this.compose(containerBlock); for (var i = 1; i <= this.elseifCount_; i++) { this.appendValueInput('IF' + i) .setCheck([Boolean, Number]) .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF); this.appendStatementInput('DO' + i) .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN); } if (this.elseCount_) { this.appendStatementInput('ELSE') .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE); } for (var i = valueConnections.length - 2; i > 0; i--) { if (valueConnections[i]) valueConnections[i].reconnect(this, 'IF' + i); } for (var i = statementConnections.length - 2; i > 0; i--) { if (statementConnections[i]) statementConnections[i].reconnect(this, 'DO' + i); } }, /** * Populate the mutator's dialog with this block's components. * @param {!Blockly.Workspace} workspace Mutator's workspace. * @return {!Blockly.Block} Root block in mutator. * @this Blockly.Block */ decompose: function (workspace) { var containerBlock = workspace.newBlock('controls_if_if'); containerBlock.initSvg(); var connection = containerBlock.getInput('STACK').connection; for (var i = 1; i <= this.elseifCount_; i++) { var elseifBlock = workspace.newBlock('controls_if_elseif'); elseifBlock.initSvg(); connection.connect(elseifBlock.previousConnection); connection = elseifBlock.nextConnection; } if (this.elseCount_) { var elseBlock = workspace.newBlock('controls_if_else'); elseBlock.initSvg(); connection.connect(elseBlock.previousConnection); } return containerBlock; }, /** * Reconfigure this block based on the mutator dialog's components. * @param {!Blockly.Block} containerBlock Root block in mutator. * @this Blockly.Block */ compose: function (containerBlock) { // Disconnect the else input blocks and remove the inputs. if (this.elseCount_) { this.removeInput('ELSE'); } this.elseCount_ = 0; // Disconnect all the elseif input blocks and remove the inputs. for (var i = this.elseifCount_; i > 0; i--) { this.removeInput('IF' + i); this.removeInput('DO' + i); } this.elseifCount_ = 0; // Rebuild the block's optional inputs. var clauseBlock = containerBlock.getInputTargetBlock('STACK'); var valueConnections = [null]; var statementConnections = [null]; var elseStatementConnection = null; while (clauseBlock) { switch (clauseBlock.type) { case 'controls_if_elseif': this.elseifCount_++; valueConnections.push(clauseBlock.valueConnection_); statementConnections.push(clauseBlock.statementConnection_); break; case 'controls_if_else': this.elseCount_++; elseStatementConnection = clauseBlock.statementConnection_; break; default: throw Error('Unknown block type: ' + clauseBlock.type); } clauseBlock = clauseBlock.nextConnection && clauseBlock.nextConnection.targetBlock(); } this.updateShape_(); // Reconnect any child blocks. this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); }, /** * Store pointers to any connected child blocks. * @param {!Blockly.Block} containerBlock Root block in mutator. * @this Blockly.Block */ saveConnections: function (containerBlock) { var clauseBlock = containerBlock.getInputTargetBlock('STACK'); var i = 1; while (clauseBlock) { switch (clauseBlock.type) { case 'controls_if_elseif': var inputIf = this.getInput('IF' + i); var inputDo = this.getInput('DO' + i); clauseBlock.valueConnection_ = inputIf && inputIf.connection.targetConnection; clauseBlock.statementConnection_ = inputDo && inputDo.connection.targetConnection; i++; break; case 'controls_if_else': var inputDo = this.getInput('ELSE'); clauseBlock.statementConnection_ = inputDo && inputDo.connection.targetConnection; break; default: throw 'Unknown block type.'; } clauseBlock = clauseBlock.nextConnection && clauseBlock.nextConnection.targetBlock(); } }, /** * Reconstructs the block with all child blocks attached. */ rebuildShape_: function () { var valueConnections = [null]; var statementConnections = [null]; var elseStatementConnection = null; if (this.getInput('ELSE')) { elseStatementConnection = this.getInput('ELSE').connection.targetConnection; } var i = 1; while (this.getInput('IF' + i)) { var inputIf = this.getInput('IF' + i); var inputDo = this.getInput('DO' + i); console.log(inputIf.connection.targetConnection); valueConnections.push(inputIf.connection.targetConnection); statementConnections.push(inputDo.connection.targetConnection); i++; } this.updateShape_(); this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); }, /** * Modify this block to have the correct number of inputs. * @this Blockly.Block * @private */ updateShape_: function () { // Delete everything. if (this.getInput('ELSE')) { this.removeInput('ELSE'); } var i = 1; while (this.getInput('IF' + i)) { this.removeInput('IF' + i); this.removeInput('DO' + i); i++; } // Rebuild block. for (var i = 1; i <= this.elseifCount_; i++) { this.appendValueInput('IF' + i) .setCheck([Number, Boolean]) .appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSEIF']); this.appendStatementInput('DO' + i) .appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']); } if (this.elseCount_) { this.appendStatementInput('ELSE') .appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSE']); } }, /** * Reconnects child blocks. * @param {!Array<?Blockly.RenderedConnection>} valueConnections List of value * connectsions for if input. * @param {!Array<?Blockly.RenderedConnection>} statementConnections List of * statement connections for do input. * @param {?Blockly.RenderedConnection} elseStatementConnection Statement * connection for else input. */ reconnectChildBlocks_: function (valueConnections, statementConnections, elseStatementConnection) { for (var i = 1; i <= this.elseifCount_; i++) { valueConnections[i] && Blockly.Mutator.reconnect(this, 'IF' + i); statementConnections[i] && statementConnections[i].reconnect(this, 'DO' + i); } elseStatementConnection && elseStatementConnection.reconnect(this, 'ELSE'); } }; export const controls_if_if = { /** * Mutator block for if container. * @this Blockly.Block */ init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF); this.appendStatementInput('STACK'); this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP); this.contextMenu = false; } }; export const controls_if_elseif = { /** * Mutator bolck for else-if condition. * @this Blockly.Block */ init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF); this.setPreviousStatement(true); this.setNextStatement(true); this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP); this.contextMenu = false; } }; export const controls_if_else = { /** * Mutator block for else condition. * @this Blockly.Block */ init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE); this.setPreviousStatement(true); this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP); this.contextMenu = false; } }; export const controls_end_program = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.MIXLY_CONTROL_END_PROGRAM); this.setPreviousStatement(true); this.setTooltip(Blockly.Msg.MIXLY_CONTROL_END_PROGRAM); } }; export const controls_forEach = { init: function () { this.setColour(LOOPS_HUE); this.appendValueInput('LIST') .setCheck(['List', String]) .setAlign(Blockly.inputs.Align.RIGHT) .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT); this.appendDummyInput() .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM) .appendField(new Blockly.FieldTextInput('i'), 'VAR'); this.appendStatementInput('DO') .appendField(Blockly.Msg.MIXLY_DO); this.setPreviousStatement(true); this.setNextStatement(true); this.setInputsInline(true); var thisBlock = this; this.setTooltip(function () { return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1', thisBlock.getFieldValue('VAR')); }); }, getVars: function () { return [this.getFieldValue('VAR')]; }, renameVar: function (oldName, newName) { if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { this.setTitleValue(newName, 'VAR'); } } }; export const raw_block = { // Container. init: function () { this.setColour(LOOPS_HUE); this.setPreviousStatement(true); this.setNextStatement(true); this.appendDummyInput() .appendField('Code Block:'); this.appendDummyInput() .appendField(new Blockly.FieldMultilineInput('12345'), 'TEXT'); } }; export const base_type = { init: function () { this.setColour(LOOPS_HUE); this.appendValueInput("DATA") .appendField(Blockly.Msg.MICROBIT_PYTHON_TYPE); this.setInputsInline(true); this.setOutput(true); this.setTooltip(Blockly.Msg.MICROBIT_PYTHON_TYPE); } }; export const controls_TypeLists = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_GET_TYPE) .appendField(new Blockly.FieldDropdown([ [Blockly.Msg.LANG_MATH_INT, "int"], [Blockly.Msg.MIXLY_MICROBIT_TYPE_FLOAT, "float"], [Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING, "str"], [Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, "list"], [Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, "tuple"], [Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, "dict"], [Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, "set"], // [Blockly.Msg.MIXLY_MICROBIT_IMAGE,"image"], [Blockly.Msg.LOGIC_NULL, "NoneType"]]), "type"); //整数、浮点数、字符串、列表、元组、字典、集合、图像不太对, unfinished this.setInputsInline(true); this.setOutput(true); var thisBlock = this; this.setTooltip(function () { var mode = thisBlock.getFieldValue('type'); var mode0 = Blockly.Msg.MICROBIT_controls_TypeLists; var TOOLTIPS = { 'int': Blockly.Msg.LANG_MATH_INT, 'float': Blockly.Msg.MIXLY_MICROBIT_TYPE_FLOAT, 'str': Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING, 'list': Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, 'tuple': Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, 'dict': Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, 'set': Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, 'image': Blockly.Msg.MIXLY_MICROBIT_IMAGE, 'NoneType': Blockly.Msg.LOGIC_NULL }; return mode0 + TOOLTIPS[mode]; }); } }; export const controls_uname = { init: function () { this.setColour(LOOPS_HUE); this.appendDummyInput() .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_UNAME); this.setInputsInline(true); this.setOutput(true); this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_UNAME); } };