প্রসঙ্গ মেনু

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

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

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

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

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

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

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

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

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

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

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

ব্যাপ্তি

Context menus are implemented by different types of components, including workspaces, workspace comments, connections, blocks, bubbles, and your own custom components. The context menus for each of these component types may contain different items, and items may behave differently based on the component type. Thus, the context menu system needs to know which component it was invoked on.

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

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 । display text একটি স্ট্রিং, অথবা HTML, অথবা এমন একটি ফাংশন হতে পারে যা একটি স্ট্রিং বা 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,
}

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

ব্লকলি কনটেক্সট মেনু আইটেমগুলির একটি অ্যারে তৈরি করার পরে, আপনি এটি পৃথক ব্লক বা ওয়ার্কস্পেসের জন্য কাস্টমাইজ করতে পারেন। এটি করার জন্য, 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. আপনার প্রসঙ্গ মেনু আইটেমগুলির জন্য রেজিস্ট্রিতে টেমপ্লেট যোগ করুন