Formas de conexión

Existen varias formas de personalizar la apariencia de las conexiones, cada una con una dificultad creciente. Todos requieren la creación de un procesador personalizado.

Dimensiones básicas

conexiones con diferentes dimensiones

Para personalizar las conexiones, cambia su ancho o alto y mantén la misma forma básica. Para ello, debes crear un componente de proveedor de constantes personalizado y anular algunas constantes.

Los diferentes procesadores definen y usan diferentes constantes, por lo que debes consultar la documentación de referencia para tu superclase:

En el caso del procesador base, puedes anular NOTCH_WIDTH y NOTCH_HEIGHT para las conexiones siguientes y anteriores, y TAB_WIDTH y TAB_HEIGHT para las conexiones de entrada y salida.

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

Formas básicas

conexiones con diferentes formas

Puedes personalizar las conexiones anulando su forma básica. Las formas básicas tienen una altura, un ancho y dos rutas.

Cada ruta dibuja la misma forma, ¡pero desde extremos opuestos!

un espacio dibujado en ambas direcciones

Esto es necesario porque, a medida que el panel lateral dibuja el contorno del bloque, dibuja cada tipo de conexión en ambas direcciones. Por ejemplo, las conexiones anteriores se dibujan de izquierda a derecha, pero las siguientes, de derecha a izquierda. Por lo tanto, debes proporcionar rutas para ambos casos.

la dirección en la que se dibuja un bloque

Puedes anular el método makeNotch para las conexiones siguientes y anteriores, y el método makePuzzleTab para las conexiones de entrada y salida.

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)]),
    };
  }
}

Consulta la documentación de la ruta de acceso SVG de MN para obtener información sobre cómo definir cadenas de ruta de acceso. El espacio de nombres Blockly.utils.svgPaths se proporciona como un wrapper delgado alrededor de estas strings para hacerlas más legibles.

Formas para las comprobaciones de conexión

diferentes conexiones con diferentes formas

Puedes personalizar las conexiones si cambias la forma según la verificación de conexión de la conexión.

Esto te permite crear diferentes formas para representar distintos tipos de datos. Por ejemplo, las strings podrían representarse con conexiones triangulares, mientras que los booleanos se representan con conexiones redondas.

A fin de proporcionar diferentes formas para diferentes comprobaciones de conexión, debes anular el método shapeFor. Las formas que se muestran se deben inicializar en init.

Consulta Formas básicas para obtener información sobre los tipos de formas compatibles.

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

Puedes personalizar las formas de conexión creando una entrada completamente personalizada. Esto solo se hace si deseas que algunas conexiones se vean diferentes a otras, pero no deseas que se base en la verificación de conexiones.

Por ejemplo, si deseas que algunas entradas de valor tengan sangría como las entradas de instrucción, puedes crear una entrada personalizada para admitir esto.

Cómo crear una clase de entrada personalizada

Sigue los pasos para crear una entrada personalizada.

Crear una herramienta medible

Debes crear un valor medible para representar tu entrada personalizada.

La entrada personalizada medible debe heredar de Blockly.blockRendering.InputConnection. También puede incluir los datos de medición adicionales que necesites para dibujar la forma de la entrada.

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

    // Any extra measurement data...
  }
}

Crea una instancia de tus recursos

La información de renderización debe crear una instancia de la medición personalizada. Para ello, debes anular el 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);
  }
}

Crea una fila de manera opcional

De forma predeterminada, las entradas no crean filas nuevas. Si quieres que tu entrada active el final de una fila, debes anular el método shouldStartNewRow_ de la información de renderización.

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

De manera opcional, crea una forma para la entrada.

Es una buena idea almacenar la forma de tu entrada en una constante, al igual que lo hacemos con las muescas y las pestañas de rompecabezas. Esto mantiene tu código organizado y facilita su modificación más adelante.

Dibuja la entrada

Por último, debes modificar el panel lateral para dibujar la forma.

Las entradas personalizadas pueden tener las siguientes opciones:

  • Afecta el esquema del bloque, como las entradas de sentencias

    imagen de las entradas de Outline

  • O afecta las partes internas del bloque, como entradas de valores intercaladas.

    imagen de las entradas internas

Si la entrada afecta el contorno de tu bloque, anula drawOutline_; de lo contrario, anula 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);
        }
      }
    }
  }
}