커스텀 프러시저 블록을 만들려면 다음 작업이 필요합니다.
- @blockly/block-shareable-procedures 설치 플러그인(사용 절차 설명 참조) 페이지를 참고하세요.
- 개요에 설명된 대로 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...
}
};
커스텀 직렬화 추가
프러시저 블록의 직렬화는 두 가지 별도의 작업을 실행해야 합니다.
- JSON에서 로드할 때 블록은 참조를 가져와야 합니다. 이는 블록과 모델이 별도로 직렬화되기 때문입니다.
- 프러시저 블록을 복사하여 붙여넣을 때 블록이 직렬화되어야 합니다. 복제할 수 있도록 프로시져 모델의 전체 상태를 전달합니다.
이 두 가지는 모두 saveExtraState
및 loadExtraState
를 통해 처리됩니다.
커스텀 프러시저 블록은 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);