커스텀 프러시저 블록 만들기

커스텀 프러시저 블록을 만들려면 다음 작업이 필요합니다.

  1. @blockly/block-shareable-procedures 설치 플러그인(사용 절차 설명 참조) 페이지를 참고하세요.
  2. 개요에 설명된 대로 JSON 직렬화 시스템 사용 페이지를 참조하세요.
를 통해 개인정보처리방침을 정의할 수 있습니다.

작업공간에 데이터 모델 추가

프러시저 정의와 프러시저 호출자 블록은 모두 지원 데이터를 참조함 프로시저의 서명 (이름, 매개변수 및 시퀀스)을 정의하는 반환합니다. 이를 통해 애플리케이션을 더 유연하게 설계할 수 있습니다 (예: 하나의 작업공간에서 절차를 정의하고 합니다.

즉, 프러시저 데이터 모델을 작업공간에 추가해야 합니다. 차단 기능을 사용할 수 있습니다. 이 작업을 수행하는 방법에는 여러 가지가 있습니다 (예: UI).

@blockly/block-shareable-procedures는 다음을 수행합니다. 프러시저 정의 블록이 지원 데이터 모델을 동적으로 생성하도록 함 작업공간에 인스턴스화될 때 생성됩니다. 이를 직접 구현하려면 init에서 모델을 만들고 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());
  }
}

블록 정보 반환

프러시저 정의와 프러시저 호출 블록은 getProcedureModel, isProcedureDef, getVarModels 메서드 다음은 후크는 Blockly 코드를 사용하여 프로시져 블록에 대한 정보를 가져옵니다.

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

업데이트 시 재렌더링 트리거

프러시저 정의와 프러시저 호출 블록은 doProcedureUpdate 메서드를 사용하여 지도 가장자리에 패딩을 추가할 수 있습니다. 이것은 데이터 모델이 호출하는 유인 요소로서 프러시저 블록을 사용하여 자체를 재렌더링할 수 있습니다.

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

커스텀 직렬화 추가

프러시저 블록의 직렬화는 두 가지 별도의 작업을 실행해야 합니다.

  1. JSON에서 로드할 때 블록은 참조를 가져와야 합니다. 이는 블록과 모델이 별도로 직렬화되기 때문입니다.
  2. 프러시저 블록을 복사하여 붙여넣을 때 블록이 직렬화되어야 합니다. 복제할 수 있도록 프로시져 모델의 전체 상태를 전달합니다.

이 두 가지는 모두 saveExtraStateloadExtraState를 통해 처리됩니다. 커스텀 프러시저 블록은 JSON을 사용할 때만 지원된다는 점에 유의하세요. 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();
      }
    }
  }
};

필요한 경우 프러시저 모델 수정

사용자가 프러시저 모델을 수정할 수 있는 기능을 추가할 수도 있습니다. 전화 거는 중 insertParameter, deleteParameter 또는 setReturnTypes 메서드 doProcedureUpdate를 통해 블록을 재렌더링하도록 자동으로 트리거합니다.

절차 모델을 수정하기 위해 UI를 만드는 옵션에는 뮤테이터( 내장 프러시저 블록 사용), 클릭 핸들러가 있는 이미지 필드 등 Blockly 등에 전적으로

도구 상자에 블록 추가

Blockly의 내장 동적 프러시저 카테고리는 Blockly의 내장 동적 프러시저에 따라 다릅니다. 프로시져 블록을 위한 것입니다. 따라서 차단에 액세스하려면 자체 맞춤 동적 광고 및 카테고리를 선택하고 도구 상자에 추가하세요.

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