Verificações de conexão

As verificações de conexão restringem quais conexões (e, portanto, blocos) podem se conectar uma à outra.

As verificações de conexão são úteis para modelar tipos. Por exemplo, os três blocos a seguir não têm negócios conectados, porque representam código que retorna tipos diferentes:

Um bloco de lista vazio, conectado a um bloco de raiz quadrada, conectado a um
bloco de letras maiúsculas

As verificações de conexão podem ser usadas para impedir a conexão desses blocos. Isso dá aos usuários um feedback instantâneo e evita muitos erros simples.

Como funcionam

Cada conexão pode ser associada a uma "verificação de conexão", que é uma matriz de strings nulas.

Duas conexões podem se conectar se:

  1. Eles são tipos compatíveis (por exemplo, uma saída que se conecta a uma entrada).
  2. Elas têm pelo menos uma string em comum na verificação de conexão.

Por exemplo, as conexões com as duas verificações a seguir podem se conectar, porque elas compartilham a string 'apple':

['apple', 'ball', 'cat']
['apple', 'bear', 'caterpillar']

No entanto, as conexões com essas duas verificações não foram possíveis, porque elas não compartilham strings:

['apple', 'ball', 'cat']
['ape', 'bear', 'caterpillar']

Há outro caso especial. Se uma das matrizes for null, as duas conexões também poderão se conectar. Isso permite que você defina conexões que podem se conectar a qualquer coisa.

null
['ape', 'bear', 'caterpillar]

Exemplos

Para conferir uma lista de exemplos de como usar as verificações de conexão, consulte o manual de verificação de conexão.

Configurar verificações

Por padrão, todas as conexões têm uma verificação de conexão null, o que significa que elas podem se conectar a qualquer coisa. As verificações de conexão precisam ser atribuídas manualmente.

A forma de atribuir verificações de conexão a conexões é diferente se você estiver usando definições de bloco JSON ou definições de bloco JavaScript.

JSON

Para conexões de nível superior, atribua a verificação diretamente à propriedade que define a conexão. O valor atribuído pode ser null, uma string (que se torna a única entrada na verificação de conexão) ou uma matriz de strings.

{
  'type': 'custom_value_block',

  'output': 'a connection check entry',
},
{
  'type': 'custom_statement_block',

  'nextStatement': null, // null check
  'previousStatement': ['four', 'connection', 'check', 'entries']
}

Para entradas, é possível atribuir a verificação a uma propriedade check da definição de entrada. Se a propriedade check não existir, a verificação será considerada null. O valor atribuído pode ser uma string ou uma matriz de strings.

{
  'type': 'custom_block',
  'message0': '%1 %2',

  'args0': [
    {
      'type': 'input_value',
      'check': 'a connection check entry' // Accepts custom_value_block
    },
    {
      'type': 'input_statement',
      'check': ['two', 'entries'] // Accepts custom_statement_block
    }
  ]
}

JavaScript

Para conexões de nível superior, é possível transmitir a verificação diretamente ao método que define a conexão. Se você não transmitir um valor, a verificação será considerada null. O valor transmitido pode ser uma string (que se torna a única entrada na verificação de conexão) ou uma matriz de strings.

Blockly.Blocks['custom_value_block'] = {
  init: function() {
    this.setOutput(true, 'a connection check entry');
  }
};
Blockly.Blocks['custom_statement_block'] = {
  init: function() {
    this.setNextStatement(true); // null check
    this.setPreviousStatement(true, ['four', 'connection', 'check', 'entries']);
  }
};

Para entradas, você pode transmitir a verificação para o método setCheck depois de definir a entrada. Se o método setCheck não for chamado, a verificação será considerada null. O valor transmitido pode ser uma string ou uma matriz de strings.

Blockly.Blocks['custom_block'] = {
  init: function() {
    this.appendValueInput('NAME')
        .setCheck('a connection check entry'); // Accepts custom_value_block
    this.appendStatementInput('NAME')
        .setCheck(['two', 'entries']); // Accepts custom_statement_block
  }
};

Strings de verificação integradas

Os blocos integrados têm verificações de conexão com os valores 'Array', 'Boolean', 'Colour', 'Number' e 'String'. Se você quiser que seus blocos interajam com os blocos integrados, use esses valores para torná-los compatíveis.

Limitações

Esse sistema é bastante robusto e pode resolver muitos casos de uso, mas tem algumas limitações.

Restringir o contexto maior

Esse sistema não oferece suporte por si só para restringir o "contexto maior" em que uma conexão pode ser feita. Por exemplo, não é possível dizer que um bloco break só pode existir dentro de um bloco loop. O sistema de verificação de conexão considera apenas as duas conexões imediatas que estão conectadas.

É possível oferecer suporte a isso usando o sistema de eventos para detectar eventos de movimentação de bloco e verificar se o bloco está posicionado incorretamente.

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (this.workspace.isDragging()) return;
    if (e.type !== Blockly.Events.BlockMove) return;
    if (!this.getSurroundLoop()) this.outputConnection.disconnect();
  }

  loopTypes: new Set(); // Your valid *block types* (not connection checks).

  getSurroundLoop: function () {
    let block = this.getSurroundParent();
    do {
      if (loopTypes.has(block.type)) return block;
      block = block.getSurroundParent();
    } while (block);
    return null;
  },
}

Tipos genéricos

Esse sistema não oferece suporte à definição de tipos genéricos. Por exemplo, não é possível criar um bloco "Identidade" que "retorne" qualquer entrada.

É possível de certa forma oferecer suporte a isso mudando ativamente a verificação de conexão na saída do bloco para corresponder à entrada. O que pode ser feito usando o sistema de eventos para detectar eventos de bloqueio de movimento.

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (e.type !== Blockly.Events.BlockMove) return;
    this.setOutput(
        true, this.getInputTargetBlock()?.outputConnection.getCheck());
  }
}

No entanto, se o bloco conectado também for genérico, isso não vai funcionar corretamente. Não há uma boa solução alternativa para esse caso.

Verificadores de conexão

Se esse sistema não funcionar para seu caso de uso, você também pode mudar a forma como as verificações de conexão são comparadas criando um verificador de conexão personalizado.

Por exemplo, se você quiser criar um sistema mais avançado que processe algumas das limitações dele, crie um verificador de conexão personalizado.