Criar um novo tipo de ícone

Para criar um ícone personalizado, você precisa implementar a interface IIcon. Isso informa ao Blockly como você quer que seu ícone seja renderizado, o que você quer que ele faça se for clicado etc.

Recomendamos subclassificar a classe abstrata Icon, porque ela já fornece implementações padrão de muitos métodos na interface IIcon.

class MyIcon extends Blockly.icons.Icon {
  // The constructor should always take in the source block so that svg elements
  // can be properly created.
  constructor(sourceBlock) {
    super(sourceBlock);
  }
}

Especificar o tipo de ícone

O método getType retorna um valor que representa o tipo do ícone. Ele é usado para registrar o ícone para serialização e recuperar o ícone de getIcon.

JavaScript

  getType() {
    return new Blockly.icons.IconType('my_icon');
  }

TypeScript

  getType(): Blockly.icons.IconType<MyIcon> {
    return new Blockly.icons.IconType<MyIcon>('my_icon');
  }

Criar a visualização do ícone

A visualização do ícone se refere aos elementos SVG que residem no bloco.

Inicializar a visualização

O método initView é onde você cria os elementos SVG do ícone que ficam no bloco. Os novos elementos precisam ser filhos do elemento this.svgRoot para que sejam limpos automaticamente quando o ícone for destruído.

O módulo Blockly.utils.dom fornece uma interface limpa para instanciar SVGs.

initView(pointerdownListener) {
  if (this.svgRoot) return;  // Already initialized.

  // This adds the pointerdownListener to the svgRoot element.
  // If you do not call `super` you must do this yourself.
  super.initView(pointerdownListener);

  Blockly.utils.dom.createSvgElement(
    Blockly.utils.Svg.CIRCLE,
    {
      'class': 'my-css-class',
      'r': '8',
      'cx': '8',
      'cy': '8',
    },
    this.svgRoot  // Append to the svgRoot.
  );
}

Retornar o tamanho

O método getSize retorna o tamanho do ícone para que o renderizador possa aumentar a largura do bloco o suficiente.

O tamanho está em "unidades de espaço de trabalho" arbitrárias (que não mudam à medida que o espaço de trabalho muda de escala).

getSize() {
  return new Blockly.utils.Size(16, 16);
}

Definir a ordem

Os ícones têm uma ordem estática no bloco. Por exemplo, os ícones de mutador integrados são sempre mostrados na frente dos ícones de comentário, que aparecem na frente dos ícones de aviso.

A ordem é controlada pelo valor retornado pelo método getWeight. Ícones com pesos mais positivos são renderizados depois dos ícones com pesos menos positivos.

getWeight() {
  return 10;
}

Implementar o comportamento do clique

Muitos ícones são interativos e fazem algo quando são clicados. Por exemplo, todos os ícones integrados mostram um balão quando são clicados. Use o método onClick para implementar isso.

onClick() {
  // Do something when clicked.
}

Responder a alterações em blocos

Alguns ícones também precisam responder a mudanças no bloco, especialmente alterações de edição e fechamento.

Capacidade de edição

Se o ícone tiver um comportamento diferente dependendo se o bloco é editável ou não (por exemplo, não ser clicável quando o bloco não é editável), implemente o método updateEditable. Esse método é chamado automaticamente quando o status editável do bloco muda.

updateEditable() {
  if (this.sourceBlock.isEditable()) {
    // Do editable things.
  } else {
    // Do non-editable things.
  }
}

Recolhido

Alguns ícones são mostrados quando o bloco é recolhido, mas eles não são mostrados por padrão. Se você quiser que o ícone seja mostrado, substitua o método isShownWhenCollapsed para retornar true.

isShownWhenCollapsed() {
  return true;
}

Em seguida, substitua o método updateCollapsed.

updateCollapsed() {
  // By default icons are hidden when the block is collapsed. We want it to
  // be shown, so do nothing.
}

Descartar o ícone

Os ícones precisam limpar todos os elementos de DOM ou referências externas quando dispostos. Por padrão, tudo o que é anexado a this.svgRoot é destruído, mas outras referências precisam ser limpas manualmente. Isso precisa ser feito no método dispose.

dispose() {
  // Always call super!
  super.dispose();

  this.myBubble?.dispose();
  this.myOtherReference?.dispose();
}