Cómo crear un nuevo tipo de ícono

Para crear un ícono personalizado, debes implementar la interfaz IIcon. Esto le indica a Blockly cómo quieres que se renderice tu ícono, qué quieres que haga si alguien hace clic en él, etcétera.

Recomendamos crear subclases de la clase abstracta Icon, dado que ya proporciona implementaciones predeterminadas de muchos métodos en la interfaz 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);
  }
}

Cómo especificar el tipo de ícono

El método getType muestra un valor que representa el tipo del ícono. Se usa a fin de registrar el ícono para la serialización y recuperar el ícono 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');
  }

Cómo crear la vista del ícono

La vista del ícono hace referencia a los elementos SVG que residen en el bloque.

Cómo inicializar la vista

El método initView es donde creas los elementos SVG de tu ícono que se encuentran en el bloque. Los elementos nuevos deben ser secundarios del elemento this.svgRoot para que se limpien automáticamente cuando se destruya el ícono.

El módulo Blockly.utils.dom proporciona una interfaz limpia para crear instancias de SVG.

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.
  );
}

Muestra el tamaño

El método getSize muestra el tamaño del ícono, de modo que el procesador pueda hacer que el bloque sea lo suficientemente ancho para él.

El tamaño está en “unidades de lugar de trabajo” arbitrarias (que no cambian a medida que el lugar de trabajo cambia de escala).

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

Establece el orden

Los íconos tienen un orden estático dentro del bloque. Por ejemplo, los íconos de mutador integrados siempre se muestran frente a los íconos de comentarios, que se muestran frente a los íconos de advertencia.

El valor que muestra el método getWeight controla el orden. Los íconos con pesos más positivos se renderizan después de los íconos con pesos menos positivos.

getWeight() {
  return 10;
}

Implementa el comportamiento de clic

Muchos iconos son interactivos y hacen algo cuando se hace clic en ellos. Por ejemplo, todos los íconos integrados muestran una burbuja cuando se hace clic en ellos. Puedes usar el método onClick para implementarlo.

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

Cómo responder a cambios de bloqueo

Algunos íconos también quieren responder a los cambios en el bloque, en particular, a los cambios en la edición y la capacidad contraída.

Edición

Si tu ícono debe comportarse de manera diferente dependiendo de si el bloque se puede editar o no (por ejemplo, no se puede hacer clic en el bloque cuando no se puede editar el bloque), implementa el método updateEditable. Se llama a este método automáticamente cuando cambia el estado editable del bloque.

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

Contraída

Algunos íconos se muestran cuando se contrae el bloque, pero no lo hacen de forma predeterminada. Si quieres que se muestre tu ícono, anula el método isShownWhenCollapsed para mostrar true.

isShownWhenCollapsed() {
  return true;
}

Luego, anula el método updateCollapsed.

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

Eliminar el ícono

Los íconos deben limpiar todos los elementos del dominio o las referencias externas cuando se desechan. De forma predeterminada, se destruye todo lo que se agrega a this.svgRoot, pero otras referencias deben limpiarse de forma manual. Esto se debe hacer dentro del método dispose.

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

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