Tạo khối quy trình tuỳ chỉnh

Việc tạo các khối quy trình tuỳ chỉnh yêu cầu bạn phải:

  1. Cài đặt @blockly/block-shareable-procedures trình bổ trợ, như được mô tả trong quy trình sử dụng .
  2. Sử dụng hệ thống chuyển đổi tuần tự JSON, như đã giải thích trên trang tổng quan .

Thêm mô hình dữ liệu vào không gian làm việc

Cả định nghĩa quy trình và khối phương thức gọi quy trình đều tham chiếu dữ liệu sao lưu mô hình xác định chữ ký của quy trình (tên, thông số và trả lại hàng). Điều này giúp bạn linh hoạt hơn trong việc thiết kế ứng dụng (ví dụ: bạn có thể cho phép xác định các quy trình trong một không gian làm việc và được tham chiếu trong khác).

Điều này có nghĩa là bạn sẽ cần thêm các mô hình dữ liệu quy trình vào không gian làm việc để các khối của bạn hoạt động. Có nhiều cách để bạn làm việc này (ví dụ: tuỳ chỉnh giao diện người dùng).

@blockly/block-shareable-procedures thực hiện việc này bằng cách có các khối định nghĩa quy trình tự động tạo mô hình dữ liệu sao lưu khi chúng được tạo thực thể vào không gian làm việc. Để tự triển khai, bạn tạo mô hình trong init rồi xoá mô hình đó trong destroy.

import {ObservableProcedureModel} from '@blockly/block-shareable-procedures';

Blockly.Blocks['my_procedure_def'] = {
  init: function() {
    this.model = new ObservableProcedureModel('default name');
    this.workspace.getProcedureMap().add(model);
    // etc...
  }

  destroy: function() {
    // (Optionally) Destroy the model when the definition block is deleted.

    // Insertion markers reference the model of the original block.
    if (this.isInsertionMarker()) return;
    this.workpace.getProcedureMap().delete(model.getId());
  }
}

Trả về thông tin về các khối

Định nghĩa quy trình và các khối lệnh gọi quy trình cần triển khai Phương thức getProcedureModel, isProcedureDefgetVarModels. Đây là những hooks Mã Blockly dùng để lấy thông tin về các khối quy trình của bạn.

Blockly.Blocks['my_procedure_def'] = {
  getProcedureModel() {
    return this.model;
  },

  isProcedureDef() {
    return true;
  },

  getVarModels() {
    // If your procedure references variables
    // then you should return those models here.
    return [];
  },
};

Blockly.Blocks['my_procedure_call'] = {
  getProcedureModel() {
    return this.model;
  },

  isProcedureDef() {
    return false;
  },

  getVarModels() {
    // If your procedure references variables
    // then you should return those models here.
    return [];
  },
};

Kích hoạt hiển thị lại khi cập nhật

Định nghĩa quy trình và các khối lệnh gọi quy trình cần triển khai doProcedureUpdate. Đây là nội dung hấp dẫn của lệnh gọi mô hình dữ liệu để cho bạn biết các khối quy trình để kết xuất lại chính nó.

Blockly.Blocks['my_procedure_def'] = {
  doProcedureUpdate() {
    this.setFieldValue('NAME', this.model.getName());
    this.setFieldValue(
        'PARAMS',
        this.model.getParameters()
            .map((p) => p.getName())
            .join(','));
    this.setFieldValue(
        'RETURN', this.model.getReturnTypes().join(',');
  }
};

Blockly.Blocks['my_procedure_call'] = {
  doProcedureUpdate() {
    // Similar to the def block above...
  }
};

Thêm chuyển đổi tuần tự tuỳ chỉnh

Quá trình chuyển đổi tuần tự cho các khối quy trình phải thực hiện hai việc riêng biệt.

  1. Khi tải từ JSON, các khối của bạn sẽ cần lấy thông tin tham chiếu đến mô hình dữ liệu sao lưu vì các khối và mô hình được chuyển đổi tuần tự riêng biệt.
  2. Khi sao chép và dán một khối quy trình, khối này sẽ cần chuyển đổi tuần tự toàn bộ trạng thái của mô hình quy trình để có thể được sao chép.

Cả hai tác vụ này đều được xử lý thông qua saveExtraStateloadExtraState. Xin lưu ý rằng các khối quy trình tuỳ chỉnh chỉ được hỗ trợ khi sử dụng tệp JSON hệ thống chuyển đổi tuần tự, nên chúng ta chỉ cần xác định móc chuyển đổi tuần tự JSON.

import {
    ObservableProcedureModel,
    ObservableParameterModel,
    isProcedureBlock
} from '@blockly/block-shareable-procedures';

Blockly.Blocks['my_procedure_def'] = {
  // When doFullSerialization is true, we should serialize the full state of
  // the model.
  saveExtraState(doFullSerialization) {
    const state = Object.create(null);
    state['procedureId']: this.model.getId();

    if (doFullSerialization) {
      state['name'] = this.model.getName();
      state['parameters'] = this.model.getParameters().map((p) => {
        return {name: p.getName(), p.getId()};
      });
      state['returnTypes'] = this.model.getReturnTypes();

      // Flag for deserialization.
      state['createNewModel'] = true;
    }

    return state;
  },

  loadExtraState(state) {
    const id = state['procedureId']
    const map = this.workspace.getProcedureMap();

    if (map.has(id) && !state['createNewModel']) {
      // Delete the existing model (created in init).
      map.delete(this.model.getId());
      // Grab a reference to the model we're supposed to reference.
      this.model = map.get(id);
      this.doProcedureUpdate();
      return;
    }

    // There is no existing procedure model (we are likely pasting), so
    // generate it from JSON.
    this.model
        .setName(state['name'])
        .setReturnTypes(state['returnTypes']);
    for (const [i, param] of state['parameters'].entries()) {
      this.model.insertParameter(
          i,
          new ObservableParameterModel(
              this.workspace, param['name'], param['id']));
    }
    this.doProcedureUpdate();
  },
};

Blockly.Blocks['my_procedure_call'] = {
  saveExtraState() {
    return {
      'procedureId': this.model.getId(),
    };
  },

  loadExtraState(state) {
    // Delete our existing model (created in init).
    this.workspace.getProcedureMap().delete(model.getId());
    // Grab a reference to the new model.
    this.model = this.workspace.getProcedureMap()
        .get(state['procedureId']);
    if (this.model) this.doProcedureUpdate();
  },

  // Handle pasting after the procedure definition has been deleted.
  onchange(event) {
    if (event.type === Blockly.Events.BLOCK_CREATE &&
        event.blockId === this.id) {
      if(!this.model) { // Our procedure definition doesn't exist =(
        this.dispose();
      }
    }
  }
};

Sửa đổi mô hình quy trình (không bắt buộc)

Bạn cũng có thể thêm khả năng cho phép người dùng sửa đổi mô hình quy trình. Gọi điện insertParameter, deleteParameter hoặc setReturnTypes phương thức sẽ tự động kích hoạt các khối của bạn để kết xuất lại (thông qua doProcedureUpdate).

Các tuỳ chọn để tạo giao diện người dùng để sửa đổi mô hình quy trình bao gồm việc sử dụng người đột biến quy trình tích hợp sẵn chặn sử dụng), các trường hình ảnh với trình xử lý lượt nhấp, một cái gì đó hoàn toàn bên ngoài Blockly, v.v.

Thêm khối vào hộp công cụ

Danh mục quy trình động tích hợp sẵn của Blockly dành riêng cho quy trình tích hợp sẵn của Blockly các khối quy trình. Vì vậy, để có thể truy cập các khối, bạn cần xác định quảng cáo động tùy chỉnh của riêng bạn danh mụcthêm danh mục đó vào bộ công cụ của mình.

const proceduresFlyoutCallback = function(workspace) {
  const blockList = [];
  blockList.push({
    'kind': 'block',
    'type': 'my_procedure_def',
  });
  for (const model of
        workspace.getProcedureMap().getProcedures()) {
    blockList.push({
      'kind': 'block',
      'type': 'my_procedure_call',
      'extraState': {
        'procedureId': model.getId(),
      },
    });
  }
  return blockList;
};

myWorkspace.registerToolboxCategoryCallback(
    'MY_PROCEDURES', proceduresFlyoutCallback);