Bloqueios personalizados: parâmetros de bloqueio

Há vários paradigmas para escolher ao projetar um aplicativo que usa o Blockly. Considere essas escolhas com antecedência, porque elas afetam os bloqueios de que o usuário vai precisar.

Configuração

Muitos aplicativos do Blockly são usados para descrever configurações em vez de programas executáveis. Os aplicativos de configuração geralmente começam inicializando um bloco no nível raiz no espaço de trabalho. Um bom exemplo é a guia "Block Factory" das Ferramentas para desenvolvedores do Blockly:

Blockly.Blocks['factory_base'] = {
  init: function() {
    this.setDeletable(false);
    this.setMovable(false);
    this.setEditable(false);
    // etc...
  }
}

Blockly.serialization.blocks.append({'type': 'factory_base'}, workspace);

Isso cria um bloco a que não pode ser movido, que armazena toda a configuração do usuário. O espaço de trabalho pode ser serializado a qualquer momento para determinar a configuração atual.

Esses aplicativos podem querer desativar automaticamente qualquer bloco não conectado ao bloco raiz. Isso pode ser feito com uma linha:

workspace.addChangeListener(Blockly.Events.disableOrphans);

Programa em série

A maioria dos aplicativos Blockly são projetados para criar programas seriais. Os usuários empilham blocos que são executados em ordem.

Todos os blocos (não desativados) no espaço de trabalho farão parte do programa. Se houver várias pilhas de blocos, as mais altas vão ser executadas primeiro. Se duas pilhas tiverem aproximadamente a mesma altura, as pilhas à esquerda (à direita no modo RTL) terão prioridade.

A área de trabalho pode ser exportada para código executável a qualquer momento. Esse código pode ser executado no lado do cliente em JavaScript (usando eval ou JS Interpreter) ou no lado do servidor em qualquer linguagem.

import {javascriptGenerator} from 'blockly/javascript';

var code = javascriptGenerator.workspaceToCode(workspace);

Programa paralelo

Alguns aplicativos do Blockly optam por executar todas as pilhas de blocos em paralelo, em vez de em série. Um exemplo seria um aplicativo de música em que um loop de bateria é executado simultaneamente com uma melodia.

Uma maneira de implementar a execução paralela é gerar o código para cada bloco individualmente:

import {javascriptGenerator} from 'blockly/javascript';

var json = Blockly.serialization.workspaces.save(workspace);

// Store top blocks separately, and remove them from the JSON.
var blocks = json['blocks']['blocks'];
var topBlocks = blocks.slice();  // Create shallow copy.
blocks.length = 0;

// Load each block into the workspace individually and generate code.
var allCode = [];
var headless = new Blockly.Workspace();
for (var i = 0; block < topBlocks.length; i++) {
  var block = topBlocks[i];
  blocks.push(block);
  Blockly.serialization.workspaces.load(json, headless);
  allCode.push(javascriptGenerator.workspaceToCode(headless));
  blocks.length = 0;
}

Se o idioma de destino for JavaScript, a matriz allCode poderá ser usada para criar vários intérpretes de JS para execução simultânea. Se a linguagem de destino for algo como Python, a matriz allCode poderá ser montada em um único programa que usa um módulo de linha de execução.

Como em qualquer programa paralelo, é preciso tomar decisões cuidadosas sobre qualquer recurso compartilhado, como variáveis e funções.

Programa impulsionado por eventos

Os manipuladores de eventos são apenas funções chamadas pelo sistema, e não pelo programa. Esses blocos podem incluir a pilha de blocos a serem executados ou ser cabeçalhos que ficam sobre uma pilha de blocos.

Alguns desenvolvedores gostam de adicionar um "chapéu" à parte de cima dos blocos de evento para que eles pareçam diferentes dos outros. Essa não é a aparência padrão do Blockly, mas ela pode ser adicionada substituindo a constante do renderizador ADD_START_HATS para true (Codelab de renderizadores personalizados: Substituir constantes) ou adicionando um tema e definindo a opção de chapéu no estilo do bloco. Mais informações sobre como definir chapéus em blocos como parte dos temas podem ser encontradas aqui.

Em um modelo orientado a eventos, pode fazer sentido criar um gerenciador para o início do programa. Nesse modelo, qualquer bloco no espaço de trabalho não conectado a um manipulador de eventos é ignorado e não é executado.

Ao projetar um sistema que usa eventos, considere se é possível ou desejável oferecer suporte a várias instâncias do mesmo manipulador de eventos.