מקשי קיצור

‫Blockly מנהל רישום של מקשי קיצור שממפים מקשים (או שילובי מקשים כמו ctrl-C) לפעולות. המאגר מאוכלס מראש במספר קיצורי דרך, כמו ctrl-C ו-meta-C להעתקה. אפשר להוסיף קיצורי דרך לרישום ולמחוק ממנו קיצורי דרך.

איך מקשי קיצור פועלים

מאגר מקשי הקיצור מכיל אובייקטים שמדמים מקשי קיצור. כשמשתמש לוחץ על מקש (או על שילוב של מקשים), Blockly:

  1. המערכת בודקת את הרישום כדי לראות אם יש קיצורי דרך שחלים על המפתח. אם יותר מקיצור דרך אחד משתמש במקש, המערכת מנסה את קיצורי הדרך בסדר הפוך לסדר שבו הם נרשמו. כלומר, המערכת תנסה קודם את קיצור הדרך שנרשם לאחרונה.

  2. מפעיל את הפונקציה preconditionFn של קיצור הדרך, שקובעת אם קיצור הדרך רלוונטי למצב הנוכחי. לדוגמה, קיצור הדרך להעתקה חל על בלוקים אבל לא על סביבת העבודה. אם קיצור הדרך לא חל, Blockly מנסה את קיצור הדרך הבא ברשימה, אם יש כזה.

  3. מפעיל את הפונקציה callback של קיצור הדרך, שמבצעת את הפעולה של קיצור הדרך. לדוגמה, קיצור הדרך להעתקה יוצר עותק של האובייקט שמוצג כרגע, כמו בלוק. אם הפונקציה הזו מחזירה true, העיבוד נפסק. אם מוחזרת התוצאה false, ‏ Blockly מנסה את קיצור הדרך הבא ברשימה, אם יש כזה.

היקף

אובייקט Scope מזהה את רכיב Blockly שיש לו כרגע מיקוד. אובייקטים של היקף מועברים אל preconditionFn ו-callback, שמשתמשים בהם כדי להחליט אם קיצור דרך חל על רכיב מסוים, ואם כן, איך להחיל אותו.

כדי להשתמש באובייקט Scope, צריך להשתמש במאפיין focusedNode שלו. זהו אובייקט שמיישם את IFocusableNode. הממשק הזה מיושם על ידי כל רכיבי Blockly שהמשתמש יכול להתמקד בהם, כולל סביבות עבודה, בלוקים, שדות, הערות ורכיבים מותאמים אישית משלכם. מידע נוסף זמין במאמר בנושא מערכת המיקוד.

לדוגמה, preconditionFn יכול להשתמש ב-focusedNode כדי לוודא שמקש קיצור חל רק על בלוקים.

preconditionFn(workspace, scope) {
  return (scope.focusedNode instanceof Blockly.BlockSvg);
}

הממשק KeyboardShortcut

אובייקטים במאגר קיצורי הדרך מיישמים את הממשק KeyboardShortcut. המאפיינים הבאים כלולים בנתונים האלה.

name (חובה)

שם ייחודי לקיצור הדרך. המידע הזה לא גלוי למשתמשים ולא צריך להיות קריא. אין לתרגם אותו.

const logFieldsShortcut = {
  name: 'logFields',
  // ...
};

preconditionFn (אופציונלי)

‫Blockly קוראת לפונקציה הזו כדי להחליט אם קיצור דרך רלוונטי למצב הנוכחי. אם הפונקציה מחזירה true, ‏ Blockly קוראת לפונקציה callback. אם הפונקציה מחזירה false, Blockly מתעלם מקיצור הדרך הזה. לדוגמה:

const logFieldsShortcut = {
  // ...
  preconditionFn(workspace, scope) {
    // This shortcut only applies to blocks.
    return (scope.focusedNode instanceof Blockly.BlockSvg);
  },
  // ...
};

אם קיצור הדרך תמיד חל (לא נפוץ), אפשר להשמיט את הפונקציה הזו. קיצורי דרך לא יכולים להשמיט את הפונקציה הזו ואז לבצע פעולה על סמך תנאי ב-callback. כך אפשר למנוע מ-Blockly לבצע פעולות כמו בניית תפריטי עזרה לפי הקשר שמציגים קיצורי דרך רלוונטיים.

התקשרות חזרה (אופציונלי)

הפונקציה הזו מפעילה את הפעולה שמשויכת לקיצור הדרך. הפונקציה נקראת רק אם preconditionFn מחזירה true או לא קיימת. הפרמטרים שלו הם:

  • workspace: WorkspaceSvg הנוכחי.
  • e: ה-Event שיזם את קיצור הדרך.
  • shortcut: KeyboardShortcut עצמו.
  • scope: Scope שאליו מתייחס קיצור הדרך.

היא מחזירה true אם היא מצליחה ו-false אם היא נכשלת.

לדוגמה:

const logFieldsShortcut = {
  // ...
  callback(workspace, event, shortcut, scope) {
    // preconditionFn required focusedNode to be a BlockSvg.
    for (input of scope.focusedNode.inputList) {
      // Log the values of all named fields. (Label fields usually don't have names.)
      for (field of input.fieldRow) {
        if (field.name) {
          console.log(field.name + ': ' + field.getText());
        }
      }
    }
    return true;
  },
  // ...
};

למרות שcallback הוא אופציונלי, בדרך כלל אין סיבה לא להטמיע אותו.

keyCodes (אופציונלי)

מערך של מקשים (או שילובים של מקשים) שמפעילים את קיצור הדרך הזה. כדי לזהות מקשים, משתמשים בקודי המקשים ב-Blockly.utils.KeyCodes. לדוגמה:

const logFieldsShortcut = {
  // ...
  keyCodes: [Blockly.utils.KeyCodes.L],
  // ...
};

אם רוצים למפות מקשים נוספים לקיצור דרך קיים – לדוגמה, אם רוצים להוסיף מקשים לקיצור דרך שמוגדר כברירת מחדל – אפשר לקרוא ל-Blockly.ShortcutRegistry.registry.addKeyMapping. זה לא נפוץ.

שילובים של מקשים

אם מקש הקיצור מופעל על ידי שילוב של מקשים, כמו לחיצה בו-זמנית על Control ועל C, צריך ליצור קוד מקש סדרתי על ידי קריאה ל-Blockly.ShortcutRegistry.registry.createSerializedKey:

const ctrlC = Blockly.ShortcutRegistry.registry.createSerializedKey(
  Blockly.utils.KeyCodes.C,       // Keycode of main key
  [Blockly.utils.KeyCodes.CTRL],  // Array of modifier keys
);

const copyShortcut = {
  // ...
  keyCodes: [ctrlC], // Use the serialized keycode
  // ...
};

Control ו-Meta

ב-Windows, מקשי קיצור רבים מופעלים באמצעות המקש Control. ב-Mac, מקשי הקיצור האלה משתמשים במקש Command במקום, שמזוהה כקוד המקש META. כדי לתמוך בשתי מערכות ההפעלה, צריך לרשום את קיצורי הדרך עם קוד המקש CTRL ועם קוד המקש META.

const ctrlC = Blockly.ShortcutRegistry.registry.createSerializedKey(
  Blockly.utils.KeyCodes.C,
  [Blockly.utils.KeyCodes.CTRL],
);
const metaC = Blockly.ShortcutRegistry.registry.createSerializedKey(
  Blockly.utils.KeyCodes.C,
  [Blockly.utils.KeyCodes.META],
);

const copyShortcut = {
  // ...
  keyCodes: [ctrlC, metaC],
  // ...
};

הערה לגבי הטמעה

הגורמים המטפלים באירועים של מקלדת ב-Blockly משתמשים במאפיין keycode של KeyboardEvent למרות שהוא הוצא משימוש.

allowCollision (אופציונלי)

כברירת מחדל, אפשר להגדיר רק קיצור דרך אחד למקש או לשילוב מקשים מסוים. הגדרת המאפיין הזה לערך true מאפשרת לרשום מקש (או שילוב מקשים) גם אם כבר נרשם קיצור דרך עם אותו מקש (או שילוב מקשים).

שימו לב: המאפיין הזה רלוונטי רק כשמנסים לרשום את קיצור הדרך הזה. היא לא מונעת מקיצורי דרך אחרים להשתמש באותו מקש (או בשילוב מקשים). האפשרות לרשום אותם תלויה בערך של המאפיין allowCollision שלהם.

לא משנה כמה קיצורי דרך רשומים למקש או לשילוב מקשים מסוים, רק אחד מהם יופעל בהצלחה. המערכת מנסה להשתמש בקיצורי הדרך בסדר הפוך לסדר הרישום (מהאחרון שנרשם לראשון שנרשם). אחרי שאחת מהן מחזירה true מהקריאה החוזרת שלה, לא מתבצע ניסיון להשתמש בקיצורי דרך אחרים.

מטא-נתונים (אופציונלי)

זהו אובייקט שרירותי שמכיל מידע נוסף. הוא זמין ל-callback דרך הפרמטר shortcut.

הוספה, מחיקה ושינוי של קיצורי דרך

כדי להוסיף מקש קיצור חדש, קוראים ל-Blockly.ShortcutRegistry.registry.register:

Blockly.ShortcutRegistry.registry.register(logFieldsShortcut);

לפונקציה הזו יש פרמטר שני (allowOverrides) שמאפשר להחליף קיצור דרך קיים עם אותו שם כמו קיצור הדרך שלכם. שימו לב שהאפשרות הזו שונה מKeyboardShortcut.allowCollision, שמאפשרת להוסיף קיצור דרך עם שם אחר אבל עם אותו מקש או שילוב מקשים כמו קיצור דרך קיים.

כדי למחוק מקש קיצור, קוראים ל-Blockly.ShortcutRegistry.registry.unregister ומעבירים את השם של מקש הקיצור:

Blockly.ShortcutRegistry.registry.unregister('logFields');

אי אפשר לשנות את מקשי הקיצור במקום. במקום זאת, צריך למחוק את קיצור הדרך הקיים ולהוסיף קיצור דרך חדש. לדוגמה:

// Get the existing shortcut. getRegistry returns an object keyed by shortcut name.
const allShortcuts = Blockly.ShortcutRegistry.registry.getRegistry();
const modLogFieldsShortcut = allShortcuts[logFieldsShortcut.name];
// Apply the shortcut only to math blocks,
modLogFieldsShortcut.preconditionFn = function (workspace, scope) {
  return (scope.focusedNode instanceof Blockly.BlockSvg &&
          scope.focusedNode.type.startsWith('math_'));
}
// Delete the existing shortcut and add the modified shortcut.
Blockly.ShortcutRegistry.registry.unregister(logFieldsShortcut.name);
Blockly.ShortcutRegistry.registry.register(modLogFieldsShortcut);

קיצורי ברירת מחדל

מאגר קיצורי הדרך מאוכלס מראש במספר קיצורי דרך. אפשר למצוא אותם בכתובת https://github.com/google/blockly/blob/master/core/shortcut_items.ts. מקשי הקיצור מוגדרים בפונקציות registerXxxx.

מקשי קיצור לניווט במקלדת

תוסף הניווט באמצעות המקלדת מכיל קיצורי דרך שמאפשרים למשתמשים לנווט ב-Blockly באמצעות המקלדת, למשל באמצעות מקשי החיצים. ניווט באמצעות המקלדת חיוני למשתמשים שלא יכולים להשתמש בעכבר, כמו אנשים עם ליקויי ראייה או ליקויים מוטוריים. הוא שימושי גם למשתמשים מתקדמים שרוצים להשתמש במקשי קיצור כדי להתייעל.