Formas de conexão

Há várias maneiras de personalizar a aparência das conexões, cada uma com cada vez mais dificuldade. Todos eles exigem a criação de um renderizador personalizado.

Dimensões básicas

conexões com diferentes dimensões

Você pode personalizar as conexões mudando a largura ou altura delas, mantendo a mesma forma básica. Para isso, você precisa criar um componente personalizado de provedor de constante e substituir algumas constantes.

Diferentes renderizadores definem e usam constantes diferentes. Portanto, confira a documentação de referência da sua superclasse:

Para o renderizador base, você pode substituir NOTCH_WIDTH e NOTCH_HEIGHT para conexões seguintes e anteriores, e TAB_WIDTH e TAB_HEIGHT para conexões de entrada e saída.

class CustomConstantProvider extends Blockly.blockRendering.ConstantProvider {
  constructor() {
    super();
    this.NOTCH_WIDTH = 20;
    this.NOTCH_HEIGHT = 10;
    this.TAB_HEIGHT = 8;
  }
}

Formas básicas

conexões com diferentes formas

Você pode personalizar as conexões substituindo o formato básico delas. As formas básicas têm altura, largura e dois caminhos.

Cada caminho desenha a mesma forma, mas de extremidades opostas!

um entalhe desenhado em ambas as direções

Isso é necessário porque, como a gaveta desenha o contorno do bloco, ela desenha cada tipo de conexão nas duas direções. Por exemplo, as conexões anteriores são desenhadas da esquerda para a direita, enquanto as próximas são desenhadas da direita para a esquerda. Portanto, é preciso fornecer caminhos para esses dois casos.

a direção em que um bloco está sendo desenhado

Você pode substituir o método makeNotch para as conexões seguintes e anteriores, e o método makePuzzleTab para conexões de entrada e saída.

class CustomConstantProvider extends Blockly.blockRendering.ConstantProvider {
  makePuzzleTab() {
    const width = this.TAB_WIDTH;
    const height = this.TAB_HEIGHT;
    return {
      type: this.SHAPES.PUZZLE,
      width,
      height,
      pathUp: Blockly.utils.svgPaths.line([
          Blockly.utils.svgPaths.point(-width, -height / 2),
          Blockly.utils.svgPaths.point(width, -height / 2)]),
      pathDown: Blockly.utils.svgPaths.line([
          Blockly.utils.svgPaths.point(-width, height / 2),
          Blockly.utils.svgPaths.point(width, height / 2)]),
    };
  }
}

Confira a documentação de caminho do MDN SVG para informações sobre como definir strings de caminho. O namespace Blockly.utils.svgPaths é fornecido como um wrapper fino em torno dessas strings para torná-las mais legíveis.

Formas para verificações de conexão

conexões diferentes com formas diferentes

Você pode personalizar as conexões alterando a forma com base na verificação de conexão da conexão.

Isso permite criar formas diferentes para representar tipos de dados distintos. Por exemplo, strings podem ser representadas por conexões triangulares, enquanto booleanos são representados por conexões redondas.

Para fornecer formas diferentes em diversas verificações de conexão, é necessário modificar o método shapeFor. As formas retornadas precisam ser inicializadas em init.

Consulte formas básicas para ver informações sobre os tipos compatíveis.

export class ConstantProvider extends Blockly.blockRendering.BaseConstantProvider {
  shapeFor(connection) {
    let check = connection.getCheck();
    // For connections with no check, match any child block.
    if (!check && connection.targetConnection) {
      check = connection.targetConnection.getCheck();
    }

    if (check && check.includes('String')) return this.TRIANGULAR_TAB;
    if (check && check.includes('Boolean')) return this.ROUND_TAB;

    return super.shapeFor(connection);
  }
}

Entradas personalizadas

Você pode criar uma entrada totalmente personalizada para personalizar os formatos de conexão. Isso só será feito se você quiser que algumas conexões pareçam diferentes de outras, mas não quiser que isso seja baseado na verificação de conexão.

Por exemplo, se você quiser que algumas entradas de valor sejam recuadas como entradas de instrução, crie uma entrada personalizada para ser compatível com isso.

Criar uma classe de entrada personalizada

Siga as etapas para criar uma entrada personalizada.

Crie um design

Você precisa criar uma entrada mensurável para representar sua entrada personalizada.

A entrada mensurável personalizada precisa herdar de Blockly.blockRendering.InputConnection. Ela também pode incluir quaisquer dados de medição extras necessários para desenhar a forma da entrada.

export class CustomInputMeasurable extends Blockly.blockRendering.InputConnection {
  constructor(constants, input) {
    super(constants, input);

    // Any extra measurement data...
  }
}

Instancie suas campanhas mensuráveis

As informações de renderização precisam instanciar a medição personalizada. Para fazer isso, substitua o método addInput_.

export class RenderInfo extends Blockly.blockRendering.RenderInfo {
  addInput_(input, activeRow) {
    if (input instanceof CustomInput) {
      activeRow.elements.push(new CustomInputMeasurable(this.constants_, input));
    }
    super.addInput_(input, activeRow);
  }
}

Como opção, crie uma linha

Por padrão, as entradas não criam novas linhas. Se você quiser que a entrada acione o fim de uma linha, modifique o método shouldStartNewRow_ das informações de renderização.

export class RenderInfo extends Blockly.blockRendering.RenderInfo {
  shouldStartNewRow_(currInput, prevInput) {
    if (prevInput instanceof CustomInput) return true;
    return super.shouldStartNewRow_(currInput, prevInput);
  }
}

Como opção, crie uma forma para a entrada

É uma boa ideia armazenar a forma da entrada de forma constante, como fazemos para entalhes e guias de quebra-cabeças. Isso mantém seu código organizado e facilita modificações posteriores.

Desenhar a entrada

Por fim, é necessário modificar sua gaveta para desenhar a forma.

As entradas personalizadas podem:

  • afetar o contorno do seu bloco, como entradas de instrução

    imagem de entradas de contorno

  • Ou afetar os componentes internos do bloco, como entradas de valores inline

    imagem de entradas internas

Se a entrada afetar o contorno do bloco, substitua drawOutline_. Caso contrário, substitua drawInternals_.

export class Drawer extends Blockly.blockRendering.Drawer {
  drawOutline_() {
    this.drawTop_();
    for (let r = 1; r < this.info_.rows.length - 1; r++) {
      const row = this.info_.rows[r];

      // Insert checks for your input here!
      if (row.getLastInput() instanceof CustomInputMeasurable) {
        this.drawCustomInput(row);
      } else if (row.hasJaggedEdge) {
        this.drawJaggedEdge_(row);
      } else if (row.hasStatement) {
        this.drawStatementInput_(row);
      } else if (row.hasExternalInput) {
        this.drawValueInput_(row);
      } else {
        this.drawRightSideRow_(row);
      }
    }
    this.drawBottom_();
    this.drawLeft_();
  }

  protected drawInternals_() {
    for (const row of rows) {
      for (const elem of row) {

        // Insert checks for your input here!
        if (elem instanceof CustomInputMeasurable) {
          this.drawCustomInput(elem);
        }

        if (Types.isInlineInput(elem)) {
          this.drawInlineInput_(elem as InlineInput);
        } else if (Types.isIcon(elem) || Types.isField(elem)) {
          this.layoutField_(elem as Field | Icon);
        }
      }
    }
  }
}