Variáveis

As variáveis são um conceito importante de programação. O Blockly é compatível com linguagens de tipagem dinâmica, como Python e JavaScript. Com um pouco mais de trabalho, é possível adicionar informações para oferecer suporte a linguagens de tipagem forte (ou estática), como Java ou C.

Para mais informações sobre linguagens dinâmicas e estáticas, consulte Introdução aos tipos de dados: estáticos, dinâmicos, fortes e fracos.

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

Um campo de variável com um menu suspenso para escolher uma variável, mudar o nome da variável atual ou excluir a variável atual.

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 tipagem dinâmica. Se você estiver usando uma linguagem digitada, configure 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:

Blocos getter e setter para a variável
`foo`.

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

Blocos de variáveis tipadas

É 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 criam 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 Panda 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 Panda 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 mostram apenas variáveis do tipo "Panda". As entradas e saídas deles só aceitam conexões do tipo "Panda". O defaultType do campo precisa ser definido como um dos valores na matriz variableTypes. Não definir o defaultType ao fornecer uma matriz variableTypes vai gerar um erro.

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 que esse novo tipo de variável seja útil para seus usuários, adicione uma maneira de criar e usar as novas variáveis.

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

Uma categoria aberta chamada "Variáveis" com um botão "Criar variável".

Adicione os novos getters e setters à categoria.

A mesma categoria depois que as variáveis "foo" e "bar" foram criadas. Ele
contém um botão "Criar variável", blocos "definir variável como" e "mudar variável por"
e blocos de getter.

Botão "Criar variável"

Em seguida, o 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 tipada "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 numérica", "Criar variável Panda").

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

Definir geradores

Por fim, você precisará definir geradores de código de bloco para os novos blocos de variáveis. Você também pode acessar a lista de variáveis diretamente com Workspace.getVariableMap().getAllVariables() para receber todas as variáveis de todos os tipos ou Workspace.getVariableMap().getVariablesOfType() para receber todas as variáveis de um tipo específico.