Blockly.Blocks['controls_if_better'] = { /** * Block for if/elseif/else condition. * @this Blockly.Block */ init: function() { this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL); this.setColour(Blockly.Blocks.logic.HUE); this.appendValueInput('IF0') .setCheck('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.updateShape_(); // 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('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.Python['controls_if_better'] = function(block) { // If/elseif/else condition. var n = 0; var code = '', branchCode, conditionCode; do { conditionCode = Blockly.Python.valueToCode(block, 'IF' + n, Blockly.Python.ORDER_NONE) || '___'; branchCode = Blockly.Python.statementToCode(block, 'DO' + n) || Blockly.Python.PASS; code += (n == 0 ? 'if ' : 'elif ' ) + conditionCode + ':\n' + branchCode; ++n; } while (block.getInput('IF' + n)); if (block.getInput('ELSE')) { branchCode = Blockly.Python.statementToCode(block, 'ELSE') || Blockly.Python.PASS; code += 'else:\n' + branchCode; } return code; };