Problem with defining a block for switch statements

1,216 views
Skip to first unread message

florian....@itizzimo.com

unread,
Oct 7, 2014, 8:54:47 AM10/7/14
to blo...@googlegroups.com
Hi,

I add some blocks to Blockly's code app like a console.log() block. I am now trying to add block for switch statements like here descriped.
I think my problem is that I don't really understand the mutators.I tried to understand it through reading other definitions of blocks with mutators.
I'm not sure if I am on the rigth way and it would be nice if you can say me what I did wrong.

Here is the code of the block definition so far:
Blockly.Blocks['switch_case'] = {
  init
: function() {
   
this.setColour(180);
   
this.setPreviousStatement(true);
   
this.setNextStatement(true);
   
this.appendValueInput('CONDITION')
       
.appendField('The case is');
   
this.appendValueInput('CASECONDITION0')
       
.appendField('In case of');
   
this.appendStatementInput('CASE0')
       
.appendField('do');
   
this.setMutator(new Blockly.Mutator(['control_case']));
   
this.appendStatementInput('ONDEFAULT')
       
.appendField('default:');
   
this.setTooltip('Does something if the condition is true. If there isn\'t a matching case the default function will be executed.');
   
this.caseCount_ = 0;
 
},

  mutationToDom
: function() {
   
var container = document.createElement('mutation');
    container
.setAttribute('case', this.caseCount_);
   
return container;
 
},

  domToMutation
: function(xmlElement) {
   
this.caseCount_ = parseInt(xmlElement.getAttribute('case'), 10);
   
for (var x = 1; x <= this.caseCount_; x++) {
       
this.appendValueInput('CASECONDITION' + x)
           
.appendField('In case of');
       
this.appendStatementInput('CASE' + x)
           
.appendField('do');
   
}
 
},

  decompose
: function(workspace) {
   
var containerBlock = Blockly.Block.obtain(workspace, 'control_case');
    containerBlock
.initSvg();
   
var connection = containerBlock.getInput('STACK').connection;
   
for (var x = 1; x <= this.caseCount_; x++) {
     
var caseBlock = Blockly.Block.obtain(workspace, 'control_case');
      caseCount
.initSvg();
      connection
.connect(caseBlock.previousConnection);
      connection
= caseBlock.nextConnection;
   
}
   
return containerBlock;
 
},

  compose
: function(containerBlock) {
   
for (var x = this.caseCount_ - 1; x >= 0; x--) {
       
this.removeInput('CASECONDITION' + x);
       
this.removeInput('CASE' + x);
   
}
   
   
this.caseCount_ = 0;
   
var caseBlock = containerBlock.getInputTargetBlock('STACK');
   
while (caseBlock) {
     
var caseconditionInput = this.appendValueInput('CASECONDITION' + x)
                                   
.appendField('In case of');  
     
var caseInput = this.appendStatementInput('CASE' + x)
                         
.appendField('do');
     
if (caseCount.valueConnection_) {
        caseconditionInput
.connection.connect(caseCount.valueConnection_);
     
}
     
if (caseCount.statementConnection_) {
        caseInput
.connection.connect(caseCount.statementConnection_);
     
}
     
this.caseCount_++;
      caseCount
= caseCount.nextConnection &&
          caseCount
.nextConnection.targetBlock();
   
}
 
},
  saveConnections
: function(containerBlock) {
   
var caseBlock = containerBlock.getInputTargetBlock('STACK');
   
var x = 0;
   
while (caseCount) {
     
var caseconditionInput = this.appendValueInput('CASECONDITION' + x)
                                   
.appendField('In case of');  
     
var caseInput = this.appendStatementInput('CASE' + x)
                         
.appendField('do');
      caseBlock
.valueConnection_ = caseconditionInput && caseconditionInput.connection.targetConnection;
      caseBlock
.statementConnection_ = caseInput && caseInput.connecttion.targetConnection;
      x
++;
      caseBlock
= caseBlock.nextConnection &&
          caseBlock
.nextConnection.targetBlock();
   
}
 
}
};

Feel free to ask questions if you don't understand what's my problem :)

Neil Fraser

unread,
Oct 7, 2014, 4:27:01 PM10/7/14
to blo...@googlegroups.com

Can you also provide the code for 'control_case' and any other blocks in the mutator?  Thanks.

Interesting... decompose() creates a 'control_case' as the top-level mutator container, but then attempts to populate the container with more 'control_case' containers?  This might not be what you want, though I can't say for sure until I see what 'control_case' is.

By contrast, the 'controls_if' block (it should have been named 'logic_if', but we had a category reorg and could not rename the block) has three mutator blocks:* 'controls_if_if': The mutator container (a singleton).

* 'controls_if_if': The mutator container (a singleton).
* 'controls_if_elseif': A block for an elseif.
* 'controls_if_else': A block for the else.

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Florian Pechwitz

unread,
Oct 8, 2014, 4:06:28 AM10/8/14
to blo...@googlegroups.com, ro...@neil.fraser.name
Thank you very much! You helped me with you question about the control_case block. It wasn't implemented yet. I will work on it now and will post the result as soon as it's ready.

My main problem is that I tried to copy other blocks without knowledge of what it really does.

Florian Pechwitz

unread,
Oct 8, 2014, 10:30:58 AM10/8/14
to blo...@googlegroups.com, ro...@neil.fraser.name
My block works! It took some work and the code of the controls_if block helped well. Here is the promised definition of the block.
Blockly.Blocks['switch_case'] = {
  init: function() {
    this.setColour(180);
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.appendValueInput('CONDITION')
        .appendField('the case is');
    this.appendValueInput('CASECONDITION0')
        .appendField('in case of');
    this.appendStatementInput('CASE0')
        .appendField('do');
    this.setMutator(new Blockly.Mutator(['case_incaseof','case_default']));
    this.setTooltip('Does something if the condition is true. If there isn\'t a matching case the default function will be executed.');
    this.caseCount_ = 0;
    this.defaultCount_ = 0;
  },

  mutationToDom: function() {
    if(!this.caseCount_ && !this.defaultCount_) {
        return null;
    }
    var container = document.createElement('mutation');
    if (this.caseCount_) {
        container.setAttribute('case', this.caseCount_);
    }
    if (this.defaultCount_) {
        container.setAttribute('default', 1);
    }
    return container;
  },

  domToMutation: function(xmlElement) {
    this.caseCount_ = parseInt(xmlElement.getAttribute('case'), 10);
    this.defaultCount_ = parseInt(xmlElement.getAttribute('default'), 10);
    for (var x = 1; x <= this.caseCount_; x++) {
        this.appendValueInput('CASECONDITION' + x)
            .appendField('in case of');
        this.appendStatementInput('CASE' + x)
            .appendField('do');
    }
    if (this.defaultCount_) {
        this.appendStatementInput('ONDEFAULT')
            .appendField('default');
    }
  },

  decompose: function(workspace) {
    var containerBlock = Blockly.Block.obtain(workspace, 'control_case');
    containerBlock.initSvg();
    var connection = containerBlock.getInput('STACK').connection;
    for (var x = 1; x <= this.caseCount_; x++) {
        var caseBlock = Blockly.Block.obtain(workspace, 'case_incaseof');
        caseBlock.initSvg();
        connection.connect(caseBlock.previousConnection);
        connection = caseBlock.nextConnection;
    }
    if(this.defaultCount_) {
        var defaultBlock = Blockly.Block.obtain(workspace, 'case_default');
        defaultBlock.initSvg();
        connection.connect(defaultBlock.previousConnection);
    }
    return containerBlock;
  },

  compose: function(containerBlock) {
    //Disconnect all input blocks and remove all inputs.
    if (this.defaultCount_) {
        this.removeInput('ONDEFAULT');
    }
    this.defaultCount_ = 0;
    for (var x = this.caseCount_; x > 0; x--) {
        this.removeInput('CASECONDITION' + x);
        this.removeInput('CASE' + x);
    }
    this.caseCount_ = 0;
    var caseBlock = containerBlock.getInputTargetBlock('STACK');
    while (caseBlock) {
        switch(caseBlock.type) {
            case 'case_incaseof':
                this.caseCount_++;
                var caseconditionInput = this.appendValueInput('CASECONDITION' + this.caseCount_)
                                             .appendField('in case of');   
                var caseInput = this.appendStatementInput('CASE' + this.caseCount_)
                                    .appendField('do');
                if (caseBlock.valueConnection_) {
                    caseconditionInput.connection.connect(caseBlock.valueConnection_);
                }
                if (caseBlock.statementConnection_) {
                    caseInput.connection.connect(caseBlock.statementConnection_);
                }
                break;
            case 'case_default':
                this.defaultCount_++;
                var defaultInput = this.appendStatementInput('ONDEFAULT')
                                       .appendField('default');
                if(caseBlock.statementConnection_) {
                    defaultInput.connection.connect(caseBlock.statementConnection_);
                }
                break;
            default:
                throw 'Unknown block type.';
        }
        caseBlock = caseBlock.nextConnection &&
                  caseBlock.nextConnection.targetBlock();
    }
  },

  saveConnections: function(containerBlock) {
    var caseBlock = containerBlock.getInputTargetBlock('STACK');
    var x = 1;
    while (caseBlock) {
        switch (caseBlock.type) {
            case'case_incaseof':
                var caseconditionInput = this.getInput('CASECONDITION' + x);  
                var caseInput = this.getInput('CASE' + x);
                caseBlock.valueConnection_ = caseconditionInput && caseconditionInput.connection.targetConnection;
                caseBlock.statementConnection_ = caseInput && caseInput.connection.targetConnection;
                x++;
                break;
            case'case_default':
                var defaultInput = this.getInput('ONDEFAULT');
                caseBlock.satementConnection_ = defaultInput && defaultInput.connection.targetConnection;
                break;
            default:
                throw 'Unknown block type';
        }
        caseBlock = caseBlock.nextConnection &&
                    caseBlock.nextConnection.targetBlock();
    }
  }
};

Blockly.Blocks['control_case'] = {
  init: function() {
    this.setColour(180);
    this.appendDummyInput()
        .appendField('the case is');
    this.appendStatementInput('STACK');
    this.setTooltip('--Placeholder--');
    this.contextMenu = false;
  }
};

Blockly.Blocks['case_incaseof'] = {
  init: function() {
    this.setColour(180);
    this.appendDummyInput()
        .appendField('in case of');
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.setTooltip('--Placeholder--');
    this.contextMenu = false;
  }
};

Blockly.Blocks['case_default'] = {
  init: function() {
      this.setColour(180);
      this.appendDummyInput()
          .appendField('default');
      this.setPreviousStatement(true);
      this.setNextStatement(false);
      this.setTooltip('This function will run if there aren\'t any matching cases.');
      this.contextMenu = false;
  }
};

jungwon rhyu

unread,
May 17, 2015, 8:16:55 PM5/17/15
to blo...@googlegroups.com, ro...@neil.fraser.name
If you still want the code, here is the code for switch)case

Blockly.JavaScript['switch_case'] = function(block) {
var code = '';
var do_n;
var case_n;
var switchVariable = Blockly.JavaScript.valueToCode(block, 'CONDITION',
Blockly.JavaScript.ORDER_NONE) || null;
if (switchVariable){
var pattern = /^([a-zA-Z_]+(\d|[a-zA-Z_])*)$/g;
if (pattern.test(switchVariable)){ // Check to see if the switch is a kind of variable type
code = '\nswitch (' + switchVariable + '){\n';
var case_0 = Blockly.JavaScript.valueToCode(block, 'CASECONDITION0',
Blockly.JavaScript.ORDER_NONE) || null;
var do_0 = Blockly.JavaScript.statementToCode(block, 'CASE0');
code += '\tcase ' + case_0 + ':\n' + do_0 + '\n\t\tbreak;\n';
for (var n = 1; n <= block.caseCount_; n++) {
case_n = Blockly.JavaScript.valueToCode(block, 'CASECONDITION' + n,
Blockly.JavaScript.ORDER_NONE) || null;
if (case_n){
do_n = Blockly.JavaScript.statementToCode(block, 'CASE' + n);
code += '\tcase ' + case_n + ':\n' + do_n + '\n\t\tbreak;\n';
}
}
if (block.defaultCount_) {
do_n = Blockly.JavaScript.statementToCode(block, 'ONDEFAULT');
code += '\tdefault:\n' + do_n + '\n\t\tbreak;\n';
}
code += '}\n';
 }
 else
 alert('switch_case: ' + switchVariable + ' is not a variable name');
}
return code;
};

Jonathan Malessa

unread,
Sep 18, 2018, 7:28:37 AM9/18/18
to Blockly
Hello,

I would like to use your blockly switch/case block for the project "ioBroker". Would you mind specifiing a license under which you publish this or better yet posting it to github with a license? If you don't want any restrictions on your code I would suggest the MIT license.

This is the MIT license content:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


 Thank you for your help,
Jonathan

Smart Home - ioBroker

unread,
Feb 26, 2019, 4:37:18 PM2/26/19
to Blockly
I would like to use it too. But license is a problem. 
Can you confirm that MIT License is OK for your code?

вторник, 7 октября 2014 г., 14:54:47 UTC+2 пользователь florian....@itizzimo.com написал:
Message has been deleted
Message has been deleted
Message has been deleted

Livio Cicala

unread,
Oct 20, 2022, 7:01:46 AM10/20/22
to Blockly
Hi to all,
I tried the switch_case block and it works but I can't add any other case and not even the case-else
Has anyone tried and succeeds?
Am I doing something wrong?

fu6...@gmail.com

unread,
Oct 21, 2022, 7:32:34 PM10/21/22
to Blockly
Hi, li...

I have the sample code. Hope this helps.

switch.png

Besh wishes.
fu6...

li...@freetw.net 在 2022年10月20日 星期四晚上7:01:46 [UTC+8] 的信中寫道:

Livio Cicala

unread,
Oct 22, 2022, 3:15:20 AM10/22/22
to Blockly
Thanks,
i use the same code nut when trying to add cases they are greyed and I can not connect them

Livio Cicala

unread,
Oct 22, 2022, 3:18:48 AM10/22/22
to Blockly
Today I will compare accurately with my Blockly code to see the differences.
My application is a little different because it must work on a local computer. 
Reply all
Reply to author
Forward
0 new messages