La creazione di blocchi di procedure personalizzate richiede quanto segue:
- Installa @blockly/block-shareable-procedures come descritto nelle procedure di utilizzo .
- Utilizza il sistema di serializzazione JSON, come spiegato nella panoramica .
Aggiungi modelli dei dati all'area di lavoro
Sia la definizione della procedura che i blocchi del chiamante della procedura fanno riferimento a un dato di supporto modello che definisce la firma della procedura (nome, parametri ). Ciò garantisce una maggiore flessibilità nella progettazione dell'applicazione (ad es. puoi consentire di definire le procedure in un'area di lavoro e di fare riferimento in un'altra).
Ciò significa che dovrai aggiungere i modelli dei dati di procedura all'area di lavoro per far funzionare i blocchi. Puoi farlo in molti modi (ad es., modelli UI).
Per farlo, @blockly/block-shareable-procedures
avere blocchi di definizione delle procedure creano dinamicamente i propri modelli dei dati di supporto
quando viene creata un'istanza nell'area di lavoro. Per implementarlo personalmente,
crea il modello in init
ed eliminalo in 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());
}
}
Restituisci informazioni sui blocchi
La definizione e i blocchi di chiamata della procedura devono implementare
Metodi getProcedureModel
, isProcedureDef
e getVarModels
. Queste sono le
hook Il codice di Blockly utilizza per ottenere informazioni sui blocchi delle procedure.
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 [];
},
};
Attiva il rendering agli aggiornamenti
La definizione e i blocchi di chiamata della procedura devono implementare
doProcedureUpdate
. Questo è l'hook della chiamata dei modelli di dati per indicare
blocchi di procedure per eseguire nuovamente il rendering.
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...
}
};
Aggiungi serializzazione personalizzata
La serializzazione per i blocchi di procedura deve fare due cose separate.
- Quando carichi da JSON, i tuoi blocchi dovranno recuperare un riferimento al loro di base, perché i blocchi e i modelli sono serializzati separatamente.
- Quando si copia e incolla un blocco di procedura, il blocco deve essere serializzato l'intero stato del modello di procedura, in modo che possa essere replicato.
Entrambi questi aspetti vengono gestiti tramite saveExtraState
e loadExtraState
.
Ricorda che i blocchi di procedure personalizzate sono supportati solo quando si utilizza il formato JSON
di serializzazione, quindi dobbiamo solo definire gli hook di serializzazione 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();
}
}
}
};
Facoltativamente, modifica il modello della procedura
Puoi anche consentire agli utenti di modificare il modello di procedura. Chiamata in corso
insertParameter
, deleteParameter
o setReturnTypes
metodi
attiverà automaticamente il rendering dei tuoi blocchi (tramite doProcedureUpdate
).
Le opzioni per creare interfacce utente per modificare il modello di procedura includono l'uso mutatori (che l'uso di blocchi di procedura integrati), campi immagine con gestori di clic, qualcosa completamente esterne a Blockly, ecc.
Aggiungere blocchi agli strumenti
La categoria di procedure dinamiche integrate di Blockly è specifica per la funzionalità integrata di Blockly i blocchi delle procedure. Per poter accedere ai blocchi, devi definire personalizzate dinamiche personalizzate categoria e aggiungila al set di strumenti.
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);