पसंद के मुताबिक प्रक्रिया ब्लॉक बनाना

कस्टम प्रोसेस ब्लॉक बनाने के लिए, आपको ये काम करने होंगे:

  1. इस्तेमाल करने की प्रोसेस वाले पेज पर दिए गए तरीके के मुताबिक, @blockly/block-shareable-procedures प्लगिन इंस्टॉल करें.
  2. खास जानकारी देने वाले पेज में बताए गए तरीके के मुताबिक JSON सीरियलाइज़ेशन सिस्टम का इस्तेमाल करें.

फ़ाइल फ़ोल्डर में डेटा मॉडल जोड़ना

प्रोसेस की परिभाषा और प्रोसेस कॉलर ब्लॉक, दोनों एक बैकिंग डेटा मॉडल का रेफ़रंस देते हैं. यह मॉडल, प्रोसेस (नाम, पैरामीटर, और रिटर्न) के सिग्नेचर के बारे में बताता है. इससे ऐप्लिकेशन को डिज़ाइन करने में ज़्यादा आसानी होती है (उदाहरण के लिए, प्रक्रियाओं को एक फ़ाइल फ़ोल्डर में तय करने और दूसरे फ़ाइल फ़ोल्डर में रेफ़रंस देने की अनुमति दी जा सकती है).

इसका मतलब है कि ब्लॉक काम कर सकें, इसके लिए आपको फ़ाइल फ़ोल्डर में प्रोसेस के डेटा के मॉडल जोड़ने होंगे. इसके लिए कई तरीके अपनाए जा सकते हैं. जैसे, कस्टम यूज़र इंटरफ़ेस (यूआई).

@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.
    this.workpace.getProcedureMap().delete(model.getId());
  }
}

ब्लॉक के बारे में जानकारी दें

आपके प्रोसेस की परिभाषा और प्रोसेस के कॉल ब्लॉक के लिए, getProcedureModel, isProcedureDef, और getVarModels तरीकों को लागू करना होगा. ब्लॉकली कोड इन हुक का इस्तेमाल, आपके प्रोसेस ब्लॉक के बारे में जानकारी पाने के लिए करता है.

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. किसी प्रोसेस ब्लॉक को कॉपी करके चिपकाते समय, ब्लॉक को उसके प्रोसेस मॉडल की पूरी स्थिति को क्रम से लगाना होगा, ताकि उसकी कॉपी बनाई जा सके या उसकी डुप्लीकेट कॉपी बनाई जा सके.

ये दोनों चीज़ें saveExtraState और loadExtraState की ओर से मैनेज की जाती हैं. ध्यान दें कि कस्टम प्रोसेस ब्लॉक सिर्फ़ तब काम करते हैं, जब JSON सीरियलाइज़ेशन सिस्टम का इस्तेमाल किया जाता है. इसलिए, हमें सिर्फ़ JSON सीरीज़ के हुक तय करने की ज़रूरत है.

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

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

      // These properties are only necessary for pasting.
      'name': this.model.getName(),
      'parameters': this.model.getParameters().map((p) => {
        return {name: p.getName(), p.getId()};
      }),
      'returnTypes': this.model.getReturnTypes(),
    };
  },

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

    // Grab a reference to the existing procedure model.
    if (this.model.getId() != id && map.has(id) &&
        (this.isInsertionMarker || this.noBlockHasClaimedModel_(id))) {
      // Delete the 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']);
      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']));
    }
  },

  // We don't want to reference a model that some other procedure definition
  // is already referencing.
  noBlockHasClaimedModel_(procedureId) {
    const model =
      this.workspace.getProcedureMap().get(procedureId);
    return this.workspace.getAllBlocks(false).every(
      (block) =>
        !isProcedureBlock(block) ||
        !block.isProcedureDef() ||
        block.getProcedureModel() !== model);
  },
};

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 के ज़रिए).

प्रोसेस मॉडल में बदलाव करने के लिए, यूज़र इंटरफ़ेस (यूआई) बनाने के विकल्पों में ये विकल्प शामिल हैं: म्यूटर (जिसका इस्तेमाल पहले से मौजूद प्रोसेस ब्लॉक करती है), क्लिक हैंडलर के साथ इमेज फ़ील्ड, ब्लॉकली के लिए पूरी तरह से बाहरी चीज़ें वगैरह.

टूलबॉक्स में ब्लॉक जोड़ना

ब्लॉकली की बिल्ट-इन डाइनैमिक प्रोसेस कैटगरी, खास तौर पर ब्लॉकली के बिल्ट-इन प्रक्रिया ब्लॉक के लिए है. अपने ब्लॉक को ऐक्सेस करने के लिए, आपको अपनी कस्टम डाइनैमिक कैटगरी तय करनी होगी और उसे अपने टूलबॉक्स में जोड़ना होगा.

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