From b68fb77663cc98e536ce90c22494c1b5e1a78ded Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 12 Nov 2020 11:40:38 +0100 Subject: [PATCH] fix logic block --- src/components/Blockly/blocks/logic.js | 295 ++++++++++++++++++++----- 1 file changed, 237 insertions(+), 58 deletions(-) diff --git a/src/components/Blockly/blocks/logic.js b/src/components/Blockly/blocks/logic.js index 75839e6..9ed3a26 100644 --- a/src/components/Blockly/blocks/logic.js +++ b/src/components/Blockly/blocks/logic.js @@ -4,6 +4,239 @@ import * as Types from '../helpers/types'; import { getCompatibleTypes } from '../helpers/types'; + +Blockly.Blocks['controls_if'] = { + /** + * Block for if/elseif/else condition. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL); + this.setColour(getColour().logic); + this.appendValueInput('IF0') + .setCheck(Types.getCompatibleTypes('boolean')) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendStatementInput('DO0') + .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.Mutator(['controls_if_elseif', + 'controls_if_else'])); + // 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) { + this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10) || 0; + this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10) || 0; + this.updateShape_(); + }, + /** + * 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.nextConnection; + 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) { + var clauseBlock = containerBlock.nextConnection.targetBlock(); + // Count number of inputs. + this.elseifCount_ = 0; + this.elseCount_ = 0; + 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 'Unknown block type.'; + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 1; i <= this.elseifCount_; i++) { + Blockly.Mutator.reconnect(valueConnections[i], this, 'IF' + i); + Blockly.Mutator.reconnect(statementConnections[i], this, 'DO' + i); + } + Blockly.Mutator.reconnect(elseStatementConnection, this, 'ELSE'); + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var clauseBlock = containerBlock.nextConnection.targetBlock(); + 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(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + 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(Types.getCompatibleTypes('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); + } + } +}; + +Blockly.Blocks['controls_if_if'] = { + /** + * Mutator block for if container. + * @this Blockly.Block + */ + init: function () { + this.setColour(getColour().logic); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['controls_if_elseif'] = { + /** + * Mutator bolck for else-if condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(getColour().logic); + 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; + } +}; + +Blockly.Blocks['controls_if_else'] = { + /** + * Mutator block for else condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(getColour().logic); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP); + this.contextMenu = false; + } +}; + + Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT // Block for boolean data type: true and false. { @@ -24,32 +257,6 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT "tooltip": "%{BKY_LOGIC_BOOLEAN_TOOLTIP}", "helpUrl": "%{BKY_LOGIC_BOOLEAN_HELPURL}" }, - // Block for if/elseif/else condition. - { - "type": "controls_if", - "message0": "%{BKY_CONTROLS_IF_MSG_IF} %1", - "args0": [ - { - "type": "input_value", - "name": "IF0", - "check": Types.getCompatibleTypes('boolean') - } - ], - "message1": "%{BKY_CONTROLS_IF_MSG_THEN} %1", - "args1": [ - { - "type": "input_statement", - "name": "DO0" - } - ], - "previousStatement": null, - "nextStatement": null, - "style": "logic_blocks", - "helpUrl": "%{BKY_CONTROLS_IF_HELPURL}", - "mutator": "controls_if_mutator", - "extensions": ["controls_if_tooltip"] - }, - // If/else block that does not use a mutator. { "type": "controls_ifelse", "message0": "%{BKY_CONTROLS_IF_MSG_IF} %1", @@ -183,14 +390,16 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT "args1": [ { "type": "input_value", - "name": "THEN" + "name": "THEN", + "check": Types.getCompatibleTypes('boolean'), } ], "message2": "%{BKY_LOGIC_TERNARY_IF_FALSE} %1", "args2": [ { "type": "input_value", - "name": "ELSE" + "name": "ELSE", + "check": Types.getCompatibleTypes('boolean'), } ], "output": null, @@ -201,36 +410,6 @@ Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT } ]); // END JSON EXTRACT (Do not delete this comment.) -Blockly.defineBlocksWithJsonArray([ // Mutator blocks. Do not extract. - // Block representing the if statement in the controls_if mutator. - { - "type": "controls_if_if", - "message0": "%{BKY_CONTROLS_IF_IF_TITLE_IF}", - "nextStatement": null, - "enableContextMenu": false, - "style": "logic_blocks", - "tooltip": "%{BKY_CONTROLS_IF_IF_TOOLTIP}" - }, - // Block representing the else-if statement in the controls_if mutator. - { - "type": "controls_if_elseif", - "message0": "%{BKY_CONTROLS_IF_ELSEIF_TITLE_ELSEIF}", - "previousStatement": null, - "nextStatement": null, - "enableContextMenu": false, - "style": "logic_blocks", - "tooltip": "%{BKY_CONTROLS_IF_ELSEIF_TOOLTIP}" - }, - // Block representing the else statement in the controls_if mutator. - { - "type": "controls_if_else", - "message0": "%{BKY_CONTROLS_IF_ELSE_TITLE_ELSE}", - "previousStatement": null, - "enableContextMenu": false, - "style": "logic_blocks", - "tooltip": "%{BKY_CONTROLS_IF_ELSE_TOOLTIP}" - } -]); Blockly.Blocks['logic_compare'] = { /**