ShortcutRegistry.js 4.3 KB

1234567891011121314151617181920212223242526272829303132333435
  1. export default class ShortcutRegistry{constructor(actionRegistry,document){this._actionRegistry=actionRegistry;this._defaultKeyToActions=new Platform.Multimap();this._defaultActionToShortcut=new Platform.Multimap();this._registerBindings(document);}
  2. _applicableActions(key){return this._actionRegistry.applicableActions(this._defaultActionsForKey(key).valuesArray(),UI.context);}
  3. _defaultActionsForKey(key){return this._defaultKeyToActions.get(String(key));}
  4. globalShortcutKeys(){const keys=[];for(const key of this._defaultKeyToActions.keysArray()){const actions=this._defaultKeyToActions.get(key).valuesArray();const applicableActions=this._actionRegistry.applicableActions(actions,new UI.Context());if(applicableActions.length){keys.push(Number(key));}}
  5. return keys;}
  6. shortcutDescriptorsForAction(actionId){return this._defaultActionToShortcut.get(actionId).valuesArray();}
  7. keysForActions(actionIds){const result=[];for(let i=0;i<actionIds.length;++i){const descriptors=this.shortcutDescriptorsForAction(actionIds[i]);for(let j=0;j<descriptors.length;++j){result.push(descriptors[j].key);}}
  8. return result;}
  9. shortcutTitleForAction(actionId){const descriptors=this.shortcutDescriptorsForAction(actionId);if(descriptors.length){return descriptors[0].name;}}
  10. handleShortcut(event){this.handleKey(UI.KeyboardShortcut.makeKeyFromEvent(event),event.key,event);}
  11. eventMatchesAction(event,actionId){console.assert(this._defaultActionToShortcut.has(actionId),'Unknown action '+actionId);const key=UI.KeyboardShortcut.makeKeyFromEvent(event);return this._defaultActionToShortcut.get(actionId).valuesArray().some(descriptor=>descriptor.key===key);}
  12. addShortcutListener(element,actionId,listener,capture){console.assert(this._defaultActionToShortcut.has(actionId),'Unknown action '+actionId);element.addEventListener('keydown',event=>{if(!this.eventMatchesAction((event),actionId)||!listener.call(null)){return;}
  13. event.consume(true);},capture);}
  14. async handleKey(key,domKey,event){const keyModifiers=key>>8;const actions=this._applicableActions(key);if(!actions.length||isPossiblyInputKey()){return;}
  15. if(event){event.consume(true);}
  16. if(UI.Dialog.hasInstance()){return;}
  17. for(const action of actions){if(await action.execute()){return;}}
  18. function isPossiblyInputKey(){if(!event||!UI.isEditing()||/^F\d+|Control|Shift|Alt|Meta|Escape|Win|U\+001B$/.test(domKey)){return false;}
  19. if(!keyModifiers){return true;}
  20. const modifiers=UI.KeyboardShortcut.Modifiers;if(Host.isMac()){if(UI.KeyboardShortcut.makeKey('z',modifiers.Meta)===key){return true;}
  21. if(UI.KeyboardShortcut.makeKey('z',modifiers.Meta|modifiers.Shift)===key){return true;}}else{if(UI.KeyboardShortcut.makeKey('z',modifiers.Ctrl)===key){return true;}
  22. if(UI.KeyboardShortcut.makeKey('y',modifiers.Ctrl)===key){return true;}
  23. if(!Host.isWin()&&UI.KeyboardShortcut.makeKey('z',modifiers.Ctrl|modifiers.Shift)===key){return true;}}
  24. if((keyModifiers&(modifiers.Ctrl|modifiers.Alt))===(modifiers.Ctrl|modifiers.Alt)){return Host.isWin();}
  25. return!hasModifier(modifiers.Ctrl)&&!hasModifier(modifiers.Alt)&&!hasModifier(modifiers.Meta);}
  26. function hasModifier(mod){return!!(keyModifiers&mod);}}
  27. registerShortcut(actionId,shortcut){const descriptor=UI.KeyboardShortcut.makeDescriptorFromBindingShortcut(shortcut);if(!descriptor){return;}
  28. this._defaultActionToShortcut.set(actionId,descriptor);this._defaultKeyToActions.set(String(descriptor.key),actionId);}
  29. _registerBindings(document){const extensions=self.runtime.extensions('action');extensions.forEach(registerExtension,this);function registerExtension(extension){const descriptor=extension.descriptor();const bindings=descriptor['bindings'];for(let i=0;bindings&&i<bindings.length;++i){if(!platformMatches(bindings[i].platform)){continue;}
  30. const shortcuts=bindings[i]['shortcut'].split(/\s+/);shortcuts.forEach(this.registerShortcut.bind(this,descriptor['actionId']));}}
  31. function platformMatches(platformsString){if(!platformsString){return true;}
  32. const platforms=platformsString.split(',');let isMatch=false;const currentPlatform=Host.platform();for(let i=0;!isMatch&&i<platforms.length;++i){isMatch=platforms[i]===currentPlatform;}
  33. return isMatch;}}}
  34. export class ForwardedShortcut{}
  35. ForwardedShortcut.instance=new ForwardedShortcut();UI.shortcutRegistry;self.UI=self.UI||{};UI=UI||{};UI.ShortcutRegistry=ShortcutRegistry;UI.ShortcutRegistry.ForwardedShortcut=ForwardedShortcut;