Variáveis

As variáveis são um conceito importante de programação. O Blockly oferece suporte a linguagens digitadas dinamicamente, como Python e JavaScript, e, com um pouco mais de trabalho, é possível adicionar informações para oferecer suporte a linguagens fortemente tipadas (ou linguagens de tipo estática), como Java ou C.

Confira mais informações sobre linguagens dinâmicas em comparação a linguagens tipadas estáticas.

O Blockly fornece campos variáveis, que são caixas suspensas dinâmicas que mostram os nomes das variáveis fornecidas pelo usuário. Veja abaixo um exemplo.

Por padrão, o Blockly permite que qualquer tipo seja atribuído a uma variável, e todos os geradores fornecidos pelo Blockly são para linguagens com digitação dinâmica. Se você estiver usando uma linguagem digitada, poderá configurar o Blockly para oferecer suporte a ela fazendo o seguinte:

Blocos de variáveis sem tipo

Os blocos mais básicos para acessar e manipular uma variável são os blocos getter e setter. Vamos analisar os blocos getter e setter fornecidos pelo Blockly.

JSON

// Block for variable getter.
{
  "type": "variables_get",
  "message0": "%1",
  "args0": [
    {    // Beginning of the field variable dropdown
      "type": "field_variable",
      "name": "VAR",    // Static name of the field
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}"    // Given at runtime
    }    // End of the field variable dropdown
  ],
  "output": null,    // Null means the return value can be of any type
  ...
},

// Block for variable setter.
{
  "type": "variables_set",
  "message0": "%{BKY_VARIABLES_SET}",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}"
    },
    {
      "type": "input_value",    // This expects an input of any type
      "name": "VALUE"
    }
  ],
  ...
}

JavaScript

// Block for variable getter.
Blockly.Blocks['variables_get'] = {
  init: function() {
    this.appendDummyInput()
      .appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME");
    this.setOutput(true, null);
    ...
  }
};

// Block for variable setter.
Blockly.Blocks['variables_set'] = {
  init: function() {
    this.appendValueInput("NAME")
        .setCheck(null)
        .appendField("set")
        .appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME")
        .appendField("to");
    this.setOutput(true, null);
    ...
  }
};

Isso cria os dois blocos a seguir:

Um detalhe importante a ser observado é que, ao definir a "output" do getter da variável como nula, o valor de retorno pode ser de qualquer tipo. Além disso, a entrada do setter da variável não especifica nenhuma verificação. Como resultado, a variável pode ser definida como qualquer tipo de valor.

Blocos variáveis com tipo

É possível adicionar getters e setters que aplicam a verificação de tipo. Por exemplo, se você criou uma variável do tipo "Panda", as definições a seguir vão criar um getter e um setter com os tipos apropriados.

JSON

 // Block for Panda variable getter.
 {
  "type": "variables_get_panda",
  "message0": "%1",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
      "variableTypes": ["Panda"],    // Specifies what types to put in the dropdown
      "defaultType": "Panda"
    }
  ],
  "output": "Panda",    // Returns a value of "Panda"
  ...
},

 // Block for Panda variable setter.
{
  "type": "variables_set_panda",
  "message0": "%{BKY_VARIABLES_SET}",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
      "variableTypes": ["Panda"],
      "defaultType": "Panda"
    },
    {
      "type": "input_value",
      "name": "VALUE",
      "check": "Panda"    // Checks that the input value is of type "Panda"
    }
  ],
  "previousStatement": null,
  "nextStatement": null,
  ...
}

JavaScript

// Block for variable getter.
Blockly.Blocks['variables_get_panda'] = {
  init: function() {
    this.appendDummyInput()
      .appendField(new Blockly.FieldVariable(
          "VAR_NAME", ['Panda'], 'Panda'), "FIELD_NAME");
    this.setOutput(true, 'Panda');
    ...
  }
};

// Block for variable setter.
Blockly.Blocks['variables_set_panda'] = {
  init: function() {
    this.appendValueInput("NAME")
        .setCheck('Panda')
        .appendField("set")
        .appendField(new Blockly.FieldVariable(
            "VAR_NAME", null, ['Panda'], 'Panda'), "FIELD_NAME")
        .appendField("to");
        this.setPreviousStatement(true, null);
        this.setNextStatement(true, null);
    ...
  }
};

Isso cria dois tipos de blocos: um getter e um setter. Os menus suspensos exibem apenas variáveis do tipo Panda. As entradas e saídas só aceitam conexões com o tipo Panda. O defaultType do campo precisa ser definido como um dos valores na matriz variableTypes. Se você não definir o defaultType ao fornecer uma matriz variableTypes, um erro será gerado.

Por padrão, não há um indicador visual para informar ao usuário qual tipo está sendo usado. Uma maneira fácil de diferenciar os tipos de variáveis é por cor.

Adicionar variáveis à caixa de ferramentas

Para tornar esse novo tipo de variável útil para seus usuários, você precisa adicionar uma maneira de criar e usar as novas variáveis.

Crie uma nova categoria dinâmica para as variáveis, se você ainda não tiver uma.

Adicione os novos getters e setters à categoria.

Botão "Criar variável"

Em seguida, seu usuário precisa de uma maneira de criar variáveis. A maneira mais simples é com um botão "Criar variável".

Ao criar o botão, faça a chamada de callback

Blockly.Variables.createVariableButtonHandler(button.getTargetWorkspace(), null, 'panda');

e uma variável do tipo Panda será criada!

A maneira mais fácil de permitir que os usuários criem variáveis de vários tipos é ter um botão "Criar" por tipo (por exemplo, Criar variável de string, Criar variável de número, Criar variável panda).

Se você tiver mais de dois ou três tipos de variáveis, poderá acabar rapidamente com muitos botões. Nesse caso, use @blockly/plugin-typed-variable-modal para exibir um pop-up em que os usuários podem selecionar o tipo de variável que quiserem.

Definir geradores

Por fim, você vai precisar definir geradores de código de bloco para os novos blocos de variáveis. Também é possível acessar a lista de variáveis diretamente com Blockly.Workspace.getAllVariables() para conferir todas as variáveis de todos os tipos ou Blockly.Workspace.getVariablesOfType() para todas as variáveis de um tipo específico.