প্রসঙ্গ মেনু

একটি প্রসঙ্গ মেনুতে কর্মের একটি তালিকা থাকে যা একজন ব্যবহারকারী একটি উপাদান যেমন একটি ওয়ার্কস্পেস, ব্লক বা ওয়ার্কস্পেস মন্তব্যে সম্পাদন করতে পারে। একটি টাচ ডিভাইসে ডান-ক্লিক বা দীর্ঘ প্রেসের প্রতিক্রিয়ায় প্রসঙ্গ মেনুটি দেখানো হয়। আপনি যদি @blockly/keyboard-navigation প্লাগইন ব্যবহার করেন, তাহলে এটি একটি কীবোর্ড শর্টকাট দিয়েও দেখানো হয়, যা ডিফল্ট হিসেবে Windows-এ Ctrl+Enter বা Mac-এ Command+Enter হয়।

একটি ব্লকের জন্য ডিফল্ট প্রসঙ্গ মেনু

কনটেক্সট মেনুগুলি এমন ক্রিয়াগুলি যোগ করার জন্য একটি ভাল জায়গা যা ব্যবহারকারী কদাচিৎ করে, যেমন একটি স্ক্রিনশট ডাউনলোড করা। আপনি যদি মনে করেন যে একটি ক্রিয়া আরও সাধারণভাবে ব্যবহার করা হবে, আপনি এটিকে আহ্বান করার জন্য একটি আরও আবিষ্কারযোগ্য উপায় তৈরি করতে চাইতে পারেন।

প্রসঙ্গ মেনুগুলি ওয়ার্কস্পেস, ব্লক, ওয়ার্কস্পেস মন্তব্য, বুদবুদ এবং সংযোগ দ্বারা সমর্থিত। আপনি এগুলিকে আপনার নিজস্ব কাস্টম উপাদানগুলিতে প্রয়োগ করতে পারেন। ব্লকলি স্ট্যান্ডার্ড প্রসঙ্গ মেনু প্রদান করে যা আপনি কাস্টমাইজ করতে পারেন। আপনি প্রতি-ওয়ার্কস্পেস বা প্রতি-ব্লক ভিত্তিতে ওয়ার্কস্পেস এবং ব্লকগুলিতে প্রসঙ্গ মেনুগুলি কাস্টমাইজ করতে পারেন।

প্রসঙ্গ মেনু কিভাবে কাজ করে

ব্লকলির একটি রেজিস্ট্রি রয়েছে যাতে সমস্ত সম্ভাব্য মেনু আইটেমের জন্য টেমপ্লেট রয়েছে। প্রতিটি টেমপ্লেট বর্ণনা করে কিভাবে একটি প্রসঙ্গ মেনুতে একটি আইটেম তৈরি করতে হয়। যখন ব্যবহারকারী একটি উপাদানে একটি প্রসঙ্গ মেনু আহ্বান করে, উপাদানটি:

  1. রেজিস্ট্রিকে মেনু আইটেমগুলির একটি অ্যারে তৈরি করতে বলে যা উপাদানটিতে প্রযোজ্য। রেজিস্ট্রি প্রতিটি টেমপ্লেটকে জিজ্ঞাসা করে যে এটি উপাদানটিতে প্রযোজ্য কিনা এবং যদি তাই হয়, অ্যারেতে একটি সংশ্লিষ্ট মেনু আইটেম যোগ করে।

  2. যদি কম্পোনেন্টটি একটি ওয়ার্কস্পেস বা ব্লক হয়, তাহলে চেক করে দেখুন যে নির্দিষ্ট ওয়ার্কস্পেস বা ব্লকে মেনুটি চালু করা হয়েছে প্রসঙ্গ মেনুটি কাস্টমাইজ করার জন্য একটি ফাংশন আছে কিনা। যদি তাই হয়, এটি অ্যারেটিকে ফাংশনে প্রেরণ করে, যা অ্যারের উপাদানগুলিকে যুক্ত, মুছতে বা সংশোধন করতে পারে।

  3. প্রসঙ্গ মেনু আইটেমগুলির (সম্ভবত পরিবর্তিত) অ্যারে ব্যবহার করে প্রসঙ্গ মেনু প্রদর্শন করে।

ব্লকলি ওয়ার্কস্পেস, ব্লক এবং ওয়ার্কস্পেস মন্তব্যের জন্য প্রসঙ্গ মেনুর জন্য টেমপ্লেটের একটি মানক সেট সংজ্ঞায়িত করে। এটি রেজিস্ট্রিতে ওয়ার্কস্পেস এবং ব্লকগুলির জন্য টেমপ্লেটগুলিকে প্রিলোড করে। আপনি যদি ওয়ার্কস্পেস মন্তব্যের জন্য টেমপ্লেটগুলি ব্যবহার করতে চান তবে আপনাকে অবশ্যই সেগুলিকে রেজিস্ট্রিতে লোড করতে হবে।

কীভাবে রেজিস্ট্রিতে টেমপ্লেটগুলি যুক্ত, মুছতে এবং সংশোধন করতে হয় সে সম্পর্কে তথ্যের জন্য, রেজিস্ট্রি কাস্টমাইজ করুন দেখুন।

ব্যাপ্তি

প্রসঙ্গ মেনুগুলি বিভিন্ন ধরণের উপাদান দ্বারা প্রয়োগ করা হয়, যার মধ্যে রয়েছে ওয়ার্কস্পেস, ওয়ার্কস্পেস মন্তব্য, সংযোগ, ব্লক, বুদবুদ এবং আপনার নিজস্ব কাস্টম উপাদান। এই প্রতিটি উপাদান প্রকারের জন্য প্রসঙ্গ মেনুতে বিভিন্ন আইটেম থাকতে পারে এবং উপাদানের প্রকারের উপর ভিত্তি করে আইটেমগুলি ভিন্নভাবে আচরণ করতে পারে। এইভাবে, কনটেক্সট মেনু সিস্টেমের জানা দরকার যে এটি কোন কম্পোনেন্টে চালু করা হয়েছে।

এটি মোকাবেলা করার জন্য, রেজিস্ট্রি একটি Scope অবজেক্ট ব্যবহার করে। যে উপাদানটির উপর প্রসঙ্গ মেনুটি চালু করা হয়েছিল তা focusedNode প্রপার্টিতে একটি বস্তু হিসাবে সংরক্ষণ করা হয় যা IFocusableNode প্রয়োগ করে। ( IFocusableNode সমস্ত উপাদান দ্বারা প্রয়োগ করা হয় যেগুলিতে ব্যবহারকারীরা ফোকাস করতে পারে, সেগুলি সহ যেগুলি প্রসঙ্গ মেনুগুলি প্রয়োগ করে৷ আরও তথ্যের জন্য, ফোকাস সিস্টেম দেখুন৷)

Scope অবজেক্টটি একটি টেমপ্লেটের বেশ কয়েকটি ফাংশনে প্রেরণ করা হয়। যে কোনো ফাংশনে Scope অবজেক্ট পাওয়া যায়, focusedNode প্রোপার্টিতে অবজেক্টের ধরনের উপর ভিত্তি করে আপনি সিদ্ধান্ত নিতে পারেন। উদাহরণস্বরূপ, আপনি উপাদানটি একটি ব্লক কিনা তা পরীক্ষা করতে পারেন:

if (scope.focusedNode instanceof Blockly.BlockSvg) {
  // do something with the block
}

Scope অবজেক্টের অন্যান্য ঐচ্ছিক বৈশিষ্ট্য রয়েছে যা আর ব্যবহারের জন্য সুপারিশ করা হয় না, তবে এখনও সেট করা হতে পারে:

  • block শুধুমাত্র তখনই সেট করা হয় যখন মেনুটি একটি BlockSvg হয়।
  • workspace শুধুমাত্র তখনই সেট করা হয় যদি কম্পোনেন্টটি একটি WorkspaceSvg হয়।
  • কম্পোনেন্টটি একটি RenderedWorkspaceComment হলেই comment সেট করা হয়।

এই বৈশিষ্ট্যগুলি সমস্ত ধরণের উপাদানগুলিকে কভার করে না যার একটি প্রসঙ্গ মেনু থাকতে পারে, তাই আপনার focusedNode সম্পত্তি ব্যবহার করতে পছন্দ করা উচিত।

রেজিস্ট্রি আইটেম প্রকার

টেমপ্লেটের ধরন রয়েছে ContextMenuRegistry.RegistryItem , যেটিতে নিম্নলিখিত বৈশিষ্ট্য রয়েছে। উল্লেখ্য যে preconditionFn , displayText , এবং callback বৈশিষ্ট্যগুলি separator সম্পত্তির সাথে পারস্পরিকভাবে একচেটিয়া।

আইডি

id বৈশিষ্ট্যটি একটি অনন্য স্ট্রিং হওয়া উচিত যা নির্দেশ করে যে আপনার প্রসঙ্গ মেনু আইটেমটি কী করে।

const collapseTemplate = {
  id: 'collapseBlock',
  // ...
};

পূর্বশর্ত ফাংশন

একটি প্রসঙ্গ মেনু আইটেম কখন এবং কীভাবে প্রদর্শিত হবে তা সীমাবদ্ধ করতে আপনি preconditionFn ব্যবহার করতে পারেন।

এটি স্ট্রিংগুলির একটি সেটের একটি ফেরত দেবে: 'enabled' , 'disabled' , বা 'hidden'

মান বর্ণনা ছবি
'enabled' দেখায় যে আইটেম সক্রিয়. একটি সক্ষম বিকল্প
'disabled' দেখায় যে আইটেম সক্রিয় নয়. একটি অক্ষম বিকল্প
'hidden' আইটেম লুকিয়ে রাখে।

preconditionFn একটি Scope পাস করেছে যা আপনি মেনুটি কোন ধরণের উপাদান খোলা হয়েছে এবং সেই উপাদানটির অবস্থা নির্ধারণ করতে ব্যবহার করতে পারেন।

উদাহরণস্বরূপ, আপনি একটি আইটেম শুধুমাত্র ব্লকের জন্য প্রদর্শিত হতে চাইতে পারেন, এবং শুধুমাত্র যখন সেই ব্লকগুলি একটি নির্দিষ্ট অবস্থায় থাকে:

const collapseTemplate = {
  // ...
  preconditionFn: (scope) => {
    if (scope.focusedNode instanceof Blockly.BlockSvg) {
      if (!scope.focusedNode.isCollapsed()) {
        // The component is a block and it is not already collapsed
        return 'enabled';
      } else {
        // The block is already collapsed
        return 'disabled';
      }
    }
    // The component is not a block
    return 'hidden';
  },
  // ...
}

পাঠ্য প্রদর্শন করুন

displayText হল মেনু আইটেমের অংশ হিসাবে ব্যবহারকারীকে যা দেখানো উচিত। ডিসপ্লে টেক্সট একটি স্ট্রিং, বা এইচটিএমএল, বা একটি ফাংশন হতে পারে যা একটি স্ট্রিং বা HTML প্রদান করে।

const collapseTemplate = {
  // ...
  displayText: 'Collapse block',
  // ...
};

আপনি যদি Blockly.Msg থেকে একটি অনুবাদ প্রদর্শন করতে চান তবে আপনাকে একটি ফাংশন ব্যবহার করতে হবে। আপনি যদি সরাসরি মান নির্ধারণ করার চেষ্টা করেন, তাহলে বার্তাগুলি লোড নাও হতে পারে এবং আপনি পরিবর্তে undefined একটি মান পাবেন৷

const collapseTemplate = {
  // ...
  displayText: () => Blockly.Msg['MY_COLLAPSE_BLOCK_TEXT'],
  // ...
};

আপনি যদি একটি ফাংশন ব্যবহার করেন তবে এটি একটি Scope মানও পাস করে। আপনি আপনার প্রদর্শন পাঠ্যে উপাদান সম্পর্কে তথ্য যোগ করতে এটি ব্যবহার করতে পারেন।

const collapseTemplate = {
  // ...
  displayText: (scope) => {
    if (scope.focusedNode instanceof Blockly.Block) {
      return `Collapse ${scope.focusedNode.type} block`;
    }
    // Shouldn't be possible, as our preconditionFn only shows this item for blocks
    return '';
  },
  // ...
}

ওজন

প্রসঙ্গ মেনু আইটেমগুলি যে ক্রমে প্রদর্শিত হবে তা weight নির্ধারণ করে। তালিকায় কম ইতিবাচক মানের তুলনায় আরও ইতিবাচক মান কম প্রদর্শিত হয়। (আপনি কল্পনা করতে পারেন যে উচ্চতর ওজনের আইটেমগুলি "ভারী" তাই তারা নীচে ডুবে যায়।)

const collapseTemplate = {
  // ...
  weight: 10,
  // ...
}

অন্তর্নির্মিত প্রসঙ্গ মেনু আইটেমগুলির ওজন 1 থেকে শুরু করে 1 দ্বারা বাড়তে থাকে৷

কলব্যাক ফাংশন

callback প্রপার্টি হল একটি ফাংশন যা আপনার প্রসঙ্গ মেনু আইটেমের ক্রিয়া সম্পাদন করে। এটি বিভিন্ন পরামিতি পাস করা হয়:

  • scope : একটি Scope অবজেক্ট যা মেনু খোলা থাকা উপাদানটির একটি রেফারেন্স প্রদান করে।
  • menuOpenEvent : যে Event প্রসঙ্গ মেনু খোলার সূত্রপাত করে। এটি একটি PointerEvent বা KeyboardEvent হতে পারে, ব্যবহারকারী কীভাবে মেনুটি খোলেন তার উপর নির্ভর করে।
  • menuSelectEvent : যে Event মেনু থেকে এই নির্দিষ্ট প্রসঙ্গ মেনু আইটেমটি নির্বাচন করেছে। এটি একটি PointerEvent বা KeyboardEvent হতে পারে, ব্যবহারকারী কীভাবে আইটেম নির্বাচন করেছেন তার উপর নির্ভর করে।
  • location : পিক্সেল স্থানাঙ্কের Coordinate যেখানে মেনু খোলা হয়েছিল। এটি আপনাকে, উদাহরণস্বরূপ, ক্লিক অবস্থানে একটি নতুন ব্লক তৈরি করতে দেয়।
const collapseTemplate = {
  // ...
  callback: (scope, menuOpenEvent, menuSelectEvent, location) => {
    if (scope.focusedNode instanceof Blockly.BlockSvg) {
      scope.focusedNode.collapse();
    }
  },
}

আপনি টেমপ্লেটগুলি ডিজাইন করার scope ব্যবহার করতে পারেন যা সেগুলি খোলা হয়েছে তার উপর নির্ভর করে ভিন্নভাবে কাজ করে:

const collapseTemplate = {
  // ...
  callback: (scope) => {
    if (scope.focusedNode instance of Blockly.BlockSvg) {
      // On a block, collapse just the block.
      const block = scope.focusedNode;
      block.collapse();
    } else if (scope.focusedNode instanceof Blockly.WorkspaceSvg) {
      // On a workspace, collapse all the blocks.
      let workspace = scope.focusedNode;
      collapseAllBlocks(workspace);
    }
  }
}

বিভাজক

separator বৈশিষ্ট্য প্রসঙ্গ মেনুতে একটি লাইন আঁকে।

separator বৈশিষ্ট্য সহ টেমপ্লেটগুলিতে preconditionFn , displayText , বা callback বৈশিষ্ট্য থাকতে পারে না এবং শুধুমাত্র scopeType বৈশিষ্ট্যের সাথে স্কোপ করা যেতে পারে৷ পরবর্তী নিষেধাজ্ঞার মানে হল এগুলি শুধুমাত্র ওয়ার্কস্পেস, ব্লক এবং ওয়ার্কস্পেস মন্তব্যের জন্য প্রসঙ্গ মেনুতে ব্যবহার করা যেতে পারে।

const separatorAfterCollapseBlockTemplate = {
  id: 'separatorAfterCollapseBlock',
  scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
  weight: 11, // Between the weights of the two items you want to separate.
  separator: true,
};

আপনার প্রসঙ্গ মেনুতে প্রতিটি বিভাজকের জন্য একটি আলাদা টেমপ্লেট প্রয়োজন। প্রতিটি বিভাজক অবস্থানের জন্য weight বৈশিষ্ট্য ব্যবহার করুন.

সুযোগের ধরন

scopeType প্রপার্টি বাতিল করা হয়েছে। পূর্বে, এটি একটি মেনু আইটেম একটি ব্লক, একটি ওয়ার্কস্পেস মন্তব্য, বা একটি কর্মক্ষেত্রের জন্য একটি প্রসঙ্গ মেনুতে দেখানো উচিত কিনা তা নির্ধারণ করতে ব্যবহৃত হত। যেহেতু প্রসঙ্গ মেনুগুলি অন্যান্য উপাদানগুলিতে খোলা যেতে পারে, তাই scopeType বৈশিষ্ট্যটি খুব সীমাবদ্ধ। পরিবর্তে, সংশ্লিষ্ট উপাদানগুলির জন্য আপনার বিকল্পটি দেখাতে বা লুকানোর জন্য আপনার preconditionFn ব্যবহার করা উচিত।

আপনার যদি বিদ্যমান প্রসঙ্গ মেনু টেমপ্লেট থাকে যা scopeType ব্যবহার করে, Blockly শুধুমাত্র উপযুক্ত উপাদানের জন্য আইটেমটি দেখাতে থাকবে।

const collapseTemplate = {
  // ...
  scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
  // ...
};

রেজিস্ট্রি কাস্টমাইজ করুন

আপনি রেজিস্ট্রিতে টেমপ্লেট যোগ, মুছতে বা সংশোধন করতে পারেন। আপনি contextmenu_items.ts এ ডিফল্ট টেমপ্লেটগুলি খুঁজে পেতে পারেন।

একটি টেমপ্লেট যোগ করুন

আপনি এটি নিবন্ধন করে রেজিস্ট্রিতে একটি টেমপ্লেট যোগ করতে পারেন। আপনি পৃষ্ঠা লোড একবার এটি করা উচিত. এটি আপনার ওয়ার্কস্পেস ইনজেক্ট করার আগে বা পরে ঘটতে পারে।

const collapseTemplate = { /* properties from above */ };
Blockly.ContextMenuRegistry.registry.register(collapseTemplate);

একটি টেমপ্লেট মুছুন

আপনি আইডি দ্বারা নিবন্ধনমুক্ত করে রেজিস্ট্রি থেকে একটি টেমপ্লেট সরাতে পারেন।

Blockly.ContextMenuRegistry.registry.unregister('someID');

একটি টেমপ্লেট পরিবর্তন করুন

আপনি একটি বিদ্যমান টেমপ্লেটটি রেজিস্ট্রি থেকে টেমপ্লেটটি পেয়ে এবং তারপরে এটিকে জায়গায় পরিবর্তন করে পরিবর্তন করতে পারেন।

const template = Blockly.ContextMenuRegistry.registry.getItem('someID');
template?.displayText = 'some other display text';

ব্লক প্রসঙ্গ মেনু অক্ষম করুন

ডিফল্টরূপে, ব্লকগুলির একটি প্রসঙ্গ মেনু থাকে যা ব্যবহারকারীদের ব্লক মন্তব্য বা ডুপ্লিকেট ব্লক যোগ করার মত কাজ করতে দেয়।

আপনি এটি করে একটি পৃথক ব্লকের প্রসঙ্গ মেনু নিষ্ক্রিয় করতে পারেন:

block.contextMenu = false;

একটি ব্লক প্রকারের JSON সংজ্ঞাতে, enableContextMenu কী ব্যবহার করুন:

{
  // ...,
  "enableContextMenu": false,
}

ব্লক টাইপ বা ওয়ার্কস্পেস প্রতি প্রসঙ্গ মেনু কাস্টমাইজ করুন

Blockly প্রসঙ্গ মেনু আইটেমগুলির একটি অ্যারে তৈরি করার পরে, আপনি পৃথক ব্লক বা ওয়ার্কস্পেসের জন্য এটি কাস্টমাইজ করতে পারেন। এটি করার জন্য, BlockSvg.customContextMenu বা WorkspaceSvg.configureContextMenu একটি ফাংশনে সেট করুন যা জায়গায় অ্যারে পরিবর্তন করে।

ব্লকে পাস করা অ্যারের অবজেক্টের ContextMenuOption টাইপ আছে বা LegacyContextMenuOption ইন্টারফেস প্রয়োগ করুন। ওয়ার্কস্পেসে পাস করা বস্তুর ContextMenuOption টাইপ আছে। ব্লকলি এই বস্তুগুলি থেকে নিম্নলিখিত বৈশিষ্ট্যগুলি ব্যবহার করে:

  • text : প্রদর্শন পাঠ্য।
  • enabled : false হলে, ধূসর পাঠ্য সহ আইটেমটি প্রদর্শন করুন।
  • callback : যখন আইটেমটি ক্লিক করা হয় তখন যে ফাংশনটি কল করা হবে।
  • separator : আইটেম একটি বিভাজক. অন্য তিনটি বৈশিষ্ট্যের সাথে পারস্পরিক একচেটিয়া।

সম্পত্তির ধরন এবং ফাংশন স্বাক্ষরের জন্য রেফারেন্স ডকুমেন্টেশন দেখুন।

উদাহরণস্বরূপ, এখানে একটি ফাংশন যা Hello, World! একটি কর্মক্ষেত্রের প্রসঙ্গ মেনুতে আইটেম:

workspace.configureContextMenu = function (menuOptions, e) {
  const item = {
    text: 'Hello, World!',
    enabled: true,
    callback: function () {
      alert('Hello, World!');
    },
  };
  // Add the item to the end of the context menu.
  menuOptions.push(item);
}

একটি কাস্টম অবজেক্টে একটি প্রসঙ্গ মেনু দেখান

আপনি এই পদক্ষেপগুলি অনুসরণ করে কাস্টম উপাদানগুলির জন্য প্রসঙ্গ মেনুগুলি উপস্থিত করতে পারেন:

  1. IFocusableNode প্রয়োগ করুন বা IFocusableNode প্রয়োগ করে এমন একটি ক্লাস প্রসারিত করুন। এই ইন্টারফেসটি আপনার উপাদান সনাক্ত করতে প্রসঙ্গ মেনু সিস্টেমে ব্যবহৃত হয়। এটি ব্যবহারকারীদের কীবোর্ড নেভিগেশন প্লাগইন ব্যবহার করে আপনার উপাদানে নেভিগেট করার অনুমতি দেয়।
  2. IContextMenu প্রয়োগ করুন, যাতে showContextMenu ফাংশন রয়েছে। এই ফাংশনটি রেজিস্ট্রি থেকে প্রসঙ্গ মেনু আইটেমগুলি পায়, মেনুটি দেখানোর জন্য স্ক্রিনে অবস্থান গণনা করে এবং শেষ পর্যন্ত মেনু দেখায় যদি দেখানোর মতো কোনো আইটেম থাকে।

    const MyBubble implements IFocusableNode, IContextMenu {
      ...
      showContextMenu(menuOpenEvent) {
        // Get the items from the context menu registry
        const scope = {focusedNode: this};
        const items = Blockly.ContextMenuRegistry.registry.getContextMenuOptions(scope, menuOpenEvent);
    
        // Return early if there are no items available
        if (!items.length) return;
    
        // Show the menu at the same location on screen as this component
        // The location is in pixel coordinates, so translate from workspace coordinates
        const location = Blockly.utils.svgMath.wsToScreenCoordinates(new Coordinate(this.x, this.y));
    
        // Show the context menu
        Blockly.ContextMenu.show(menuOpenEvent, items, this.workspace.RTL, this.workspace, location);
      }
    }
    
  3. একটি ইভেন্ট হ্যান্ডলার যোগ করুন যেটি showContextMenu কল করে যখন ব্যবহারকারী আপনার উপাদানটিতে ডান-ক্লিক করে। মনে রাখবেন যে কীবোর্ড নেভিগেশন প্লাগইন একটি ইভেন্ট হ্যান্ডলার প্রদান করে যা ব্যবহারকারী Ctrl+Enter (Windows) বা Command+Enter (Mac) চাপলে showContextMenu কল করে।

  4. আপনার প্রসঙ্গ মেনু আইটেমগুলির জন্য রেজিস্ট্রিতে টেমপ্লেট যোগ করুন