Pour créer des blocs de procédure personnalisés, vous devez:
- Installez @blockly/block-shareable-procedures du plug-in, comme décrit dans les procédures d'utilisation .
- Utilisez le système de sérialisation JSON, comme expliqué dans la présentation. .
Ajouter des modèles de données à l'espace de travail
La définition de procédure et les blocs d'appelants de procédure font tous deux référence à des données de sauvegarde qui définit la signature de la procédure (nom, paramètres et retour). Vous bénéficiez ainsi d'une plus grande flexibilité dans la conception de votre application (par exemple, vous pouvez permettre de définir des procédures dans un espace de travail et de les référencer dans une autre).
Cela signifie que vous devrez ajouter les modèles de données de procédure à l'espace de travail pour que vos blocs fonctionnent. Vous pouvez le faire de plusieurs façons (par exemple, UI).
Pour ce faire, @blockly/block-shareable-procedures
Les blocs de définition de procédure créent de manière dynamique leurs modèles de données de sauvegarde.
lorsqu'ils sont instanciés dans l'espace de travail. Pour implémenter cela vous-même, vous devez
créer le modèle dans init
et le supprimer dans 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());
}
}
Renvoyer des informations sur les blocs
La définition de votre procédure et vos blocs d'appels de procédure doivent implémenter
getProcedureModel
, isProcedureDef
et getVarModels
. Ce sont les
hooks le code que Blockly utilise pour obtenir des informations sur vos blocs de procédure.
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 [];
},
};
Déclencher le nouveau rendu lors des mises à jour
La définition de votre procédure et vos blocs d'appels de procédure doivent implémenter
doProcedureUpdate
. C'est l'accroche que les modèles de données appellent pour indiquer à votre
les blocs de procédure pour qu'ils s'affichent à nouveau.
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...
}
};
Ajouter une sérialisation personnalisée
La sérialisation des blocs de procédure doit effectuer deux opérations distinctes.
- Lors du chargement à partir d'un fichier JSON, vos blocs doivent récupérer une référence à leur de sauvegarde, car les blocs et les modèles sont sérialisés séparément.
- Lorsque vous copiez et collez un bloc de procédure, le bloc doit être sérialisé l'état entier de son modèle de procédure afin qu'il puisse être répliqué.
Ces deux opérations sont gérées via saveExtraState
et loadExtraState
.
Là encore, les blocs de procédure personnalisée ne sont acceptés que si vous utilisez le fichier
Il suffit donc de définir des hooks de sérialisation 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();
}
}
}
};
Modifier le modèle de procédure (facultatif)
Vous pouvez également permettre aux utilisateurs de modifier le modèle de procédure. Appel en cours
l'élément insertParameter
, deleteParameter
ou setReturnTypes
méthodes
déclenche automatiquement le nouveau rendu de vos blocs (via doProcedureUpdate
).
Les options de création d'UI permettant de modifier le modèle de procédure incluent l'utilisation mutateurs (auquel cas des blocs de procédure intégrés), des champs d'image avec des gestionnaires de clics, entièrement externes à Blockly, etc.
Ajouter des volumes à la boîte à outils
La catégorie de procédure dynamique intégrée de Blockly est spécifique à la catégorie de procédure intégrée de Blockly blocs de procédure. Pour accéder à vos blocs, vous devez définir vos propres créations dynamiques personnalisées catégorie, puis ajoutez-la à votre boîte à outils.
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);