1// Copyright (C) 2023 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import m from 'mithril'; 16import {getPlatform, Hotkey, Key, parseHotkey, Platform} from '../base/hotkeys'; 17import {Icon} from './icon'; 18 19export interface HotkeyGlyphsAttrs { 20 hotkey: Hotkey; 21 spoof?: Platform; 22} 23 24// Renders a hotkey as a series of little keycaps. 25export class HotkeyGlyphs implements m.ClassComponent<HotkeyGlyphsAttrs> { 26 view({attrs}: m.Vnode<HotkeyGlyphsAttrs>) { 27 const {hotkey, spoof} = attrs; 28 29 const platform = spoof || getPlatform(); 30 const result = parseHotkey(hotkey); 31 if (result) { 32 const {key, modifier} = result; 33 const hasMod = modifier.includes('Mod'); 34 const hasCtrl = modifier.includes('Ctrl'); 35 const hasAlt = modifier.includes('Alt'); 36 const hasShift = modifier.includes('Shift'); 37 38 return m( 39 'span.pf-hotkey', 40 hasMod && m('span.pf-keycap', glyphForMod(platform)), 41 hasCtrl && m('span.pf-keycap', glyphForCtrl(platform)), 42 hasAlt && m('span.pf-keycap', glyphForAlt(platform)), 43 hasShift && m('span.pf-keycap', glyphForShift()), 44 m('span.pf-keycap', glyphForKey(key, platform)), 45 ); 46 } else { 47 return m('span.pf-keycap', '???'); 48 } 49 } 50} 51 52export interface KeycapGlyphsAttrs { 53 keyValue: Key; 54 spoof?: Platform; 55} 56 57// Renders a single keycap. 58export class KeycapGlyph implements m.ClassComponent<KeycapGlyphsAttrs> { 59 view({attrs}: m.Vnode<KeycapGlyphsAttrs>) { 60 const {keyValue, spoof} = attrs; 61 const platform = spoof || getPlatform(); 62 return m('span.pf-keycap', glyphForKey(keyValue, platform)); 63 } 64} 65 66function glyphForKey(key: Key, platform: Platform): m.Children { 67 if (key === 'Enter') { 68 return m(Icon, {icon: 'keyboard_return'}); 69 } else if (key === 'ArrowUp') { 70 return m(Icon, {icon: 'arrow_upward'}); 71 } else if (key === 'ArrowDown') { 72 return m(Icon, {icon: 'arrow_downward'}); 73 } else if (key === 'Space') { 74 return m(Icon, {icon: 'space_bar'}); 75 } else if (key === 'Escape') { 76 if (platform === 'Mac') { 77 return 'esc'; 78 } else { 79 return 'Esc'; 80 } 81 } else { 82 return key; 83 } 84} 85 86function glyphForMod(platform: Platform): m.Children { 87 if (platform === 'Mac') { 88 return m(Icon, {icon: 'keyboard_command_key'}); 89 } else { 90 return 'Ctrl'; 91 } 92} 93 94function glyphForShift(): m.Children { 95 return m(Icon, {icon: 'shift'}); 96} 97 98function glyphForCtrl(platform: Platform): m.Children { 99 if (platform === 'Mac') { 100 return m(Icon, {icon: 'keyboard_control_key'}); 101 } else { 102 return 'Ctrl'; 103 } 104} 105 106function glyphForAlt(platform: Platform): m.Children { 107 if (platform === 'Mac') { 108 return m(Icon, {icon: 'keyboard_option_key'}); 109 } else { 110 return 'Alt'; 111 } 112} 113