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'; 16 17import {getPlatform, Hotkey, Key, parseHotkey, Platform} from '../base/hotkeys'; 18 19import {Icon} from './icon'; 20 21export interface HotkeyGlyphsAttrs { 22 hotkey: Hotkey; 23 spoof?: Platform; 24} 25 26// Renders a hotkey as a series of little keycaps. 27export class HotkeyGlyphs implements m.ClassComponent<HotkeyGlyphsAttrs> { 28 view({attrs}: m.Vnode<HotkeyGlyphsAttrs>) { 29 const {hotkey, spoof} = attrs; 30 31 const platform = getPlatform(spoof); 32 const result = parseHotkey(hotkey); 33 if (result) { 34 const {key, modifier} = result; 35 const hasMod = modifier.includes('Mod'); 36 const hasCtrl = modifier.includes('Ctrl'); 37 const hasAlt = modifier.includes('Alt'); 38 const hasShift = modifier.includes('Shift'); 39 40 return m( 41 'span.pf-hotkey', 42 hasMod && m('span.pf-keycap', glyphForMod(platform)), 43 hasCtrl && m('span.pf-keycap', glyphForCtrl(platform)), 44 hasAlt && m('span.pf-keycap', glyphForAlt(platform)), 45 hasShift && m('span.pf-keycap', glyphForShift()), 46 m('span.pf-keycap', glyphForKey(key, platform)), 47 ); 48 } else { 49 return m('span.pf-keycap', '???'); 50 } 51 } 52} 53 54export interface KeycapGlyphsAttrs { 55 keyValue: Key; 56 spoof?: Platform; 57} 58 59// Renders a single keycap. 60export class KeycapGlyph implements m.ClassComponent<KeycapGlyphsAttrs> { 61 view({attrs}: m.Vnode<KeycapGlyphsAttrs>) { 62 const {keyValue, spoof} = attrs; 63 const platform = getPlatform(spoof); 64 return m('span.pf-keycap', glyphForKey(keyValue, platform)); 65 } 66} 67 68function glyphForKey(key: Key, platform: Platform): m.Children { 69 if (key === 'Enter') { 70 return m(Icon, {icon: 'keyboard_return'}); 71 } else if (key === 'ArrowUp') { 72 return m(Icon, {icon: 'arrow_upward'}); 73 } else if (key === 'ArrowDown') { 74 return m(Icon, {icon: 'arrow_downward'}); 75 } else if (key === 'Space') { 76 return m(Icon, {icon: 'space_bar'}); 77 } else if (key === 'Escape') { 78 if (platform === 'Mac') { 79 return 'esc'; 80 } else { 81 return 'Esc'; 82 } 83 } else { 84 return key; 85 } 86} 87 88function glyphForMod(platform: Platform): m.Children { 89 if (platform === 'Mac') { 90 return m(Icon, {icon: 'keyboard_command_key'}); 91 } else { 92 return 'Ctrl'; 93 } 94} 95 96function glyphForShift(): m.Children { 97 return m(Icon, {icon: 'shift'}); 98} 99 100function glyphForCtrl(platform: Platform): m.Children { 101 if (platform === 'Mac') { 102 return m(Icon, {icon: 'keyboard_control_key'}); 103 } else { 104 return 'Ctrl'; 105 } 106} 107 108function glyphForAlt(platform: Platform): m.Children { 109 if (platform === 'Mac') { 110 return m(Icon, {icon: 'keyboard_option_key'}); 111 } else { 112 return 'Alt'; 113 } 114} 115