From 1c50d7fe834151b541f509a0137439937e853d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Farkas=20J=C3=B3zsef?= Date: Wed, 23 Nov 2016 22:36:38 +0100 Subject: [PATCH] Tooltip texts for key actions --- .../svg/wrap/svg-keyboard-wrap.component.ts | 145 ++++++++++++++++-- .../key-action/KeystrokeAction.ts | 13 ++ src/util/index.ts | 10 ++ 3 files changed, 151 insertions(+), 17 deletions(-) create mode 100644 src/util/index.ts diff --git a/src/components/svg/wrap/svg-keyboard-wrap.component.ts b/src/components/svg/wrap/svg-keyboard-wrap.component.ts index d6d2deab..151292ef 100644 --- a/src/components/svg/wrap/svg-keyboard-wrap.component.ts +++ b/src/components/svg/wrap/svg-keyboard-wrap.component.ts @@ -11,10 +11,31 @@ import { } from '@angular/core'; import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs/Observable'; -import { KeyAction, NoneAction } from '../../../config-serializer/config-items/key-action'; +import 'rxjs/add/observable/from'; +import 'rxjs/add/operator/filter'; +import 'rxjs/add/operator/first'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/switchMap'; + +import { MapperService } from '../../../services/mapper.service'; + +import { + KeyAction, + KeystrokeAction, + LayerName, + MouseAction, + MouseActionParam, + NoneAction, + PlayMacroAction, + SwitchKeymapAction, + SwitchLayerAction +} from '../../../config-serializer/config-items/key-action'; import { Keymap } from '../../../config-serializer/config-items/Keymap'; import { Layer } from '../../../config-serializer/config-items/Layer'; +import { LongPressAction } from '../../../config-serializer/config-items/LongPressAction'; +import { camelCaseToSentence, capitalizeFirstLetter } from '../../../util'; import { AppState } from '../../../store'; import { KeymapActions } from '../../../store/actions'; @@ -96,12 +117,10 @@ export class SvgKeyboardWrapComponent implements OnChanges { private keyEditConfig: { keyActions: KeyAction[], keyId: number }; private popoverInitKeyAction: KeyAction; private currentLayer: number = 0; - private tooltipData: { posTop: number, posLeft: number, content: {name: string, value: string}[], shown: boolean }; + private tooltipData: { posTop: number, posLeft: number, content: { name: string, value: string }[], shown: boolean }; private layers: Layer[]; - constructor( - private store: Store - ) { + constructor(private store: Store, private mapper: MapperService) { this.keyEditConfig = { keyActions: undefined, keyId: undefined @@ -181,22 +200,114 @@ export class SvgKeyboardWrapComponent implements OnChanges { posTop = position.top; } - // TODO connect with real data - let dummyData = [ - { - name: 'Key action', - value: 'o' - }, - { - name: 'Scancode', - value: '55' + let content: { + name: string, + value: string + }[] = []; + + if (keyAction instanceof KeystrokeAction) { + const keystrokeAction: KeystrokeAction = keyAction; + content.push({ + name: 'Action type', + value: 'Keystroke' + }); + + if (keystrokeAction.hasScancode()) { + let value: string = keystrokeAction.scancode.toString(); + const scanCodeTexts: string = (this.mapper.scanCodeToText(keystrokeAction.scancode) || []).join(', '); + if (scanCodeTexts.length > 0) { + value += ' (' + scanCodeTexts + ')'; + } + content.push({ + name: 'Scancode', + value + }); } - ]; + + if (keystrokeAction.hasActiveModifier()) { + content.push({ + name: 'Modifiers', + value: keystrokeAction.getModifierList().join(', ') + }); + } + + if (keystrokeAction.hasLongPressAction()) { + content.push({ + name: 'Long press', + value: LongPressAction[keystrokeAction.longPressAction] + }); + } + } else if (keyAction instanceof MouseAction) { + const mouseAction: MouseAction = keyAction; + content.push({ + name: 'Action type', + value: 'Mouse' + }); + content.push({ + name: 'Action', + value: camelCaseToSentence(MouseActionParam[mouseAction.mouseAction]) + }); + } else if (keyAction instanceof PlayMacroAction) { + const playMacroAction: PlayMacroAction = keyAction; + content.push({ + name: 'Action type', + value: 'Play macro' + }); + + content.push({ + name: 'Macro id', + value: playMacroAction.macroId.toString() + }); + + // Replace the macro id with the name + this.store + .select(appState => appState.macros) + .first() + .map(macroState => macroState.entities.filter(macro => { + return macro.id === playMacroAction.macroId; + })[0].name) + .subscribe(name => { + content[1] = { + name: 'Macro name', + value: name + }; + }); + } else if (keyAction instanceof SwitchKeymapAction) { + const switchKeymapAction: SwitchKeymapAction = keyAction; + content.push({ + name: 'Action type', + value: 'Switch keymap' + }); + content.push({ + name: 'Keymap', + value: '...' + }); + this.store + .select(appState => appState.keymaps) + .first() + .switchMap(keymaps => Observable.from(keymaps.entities)) + .filter(keymap => keymap.abbreviation === switchKeymapAction.keymapAbbreviation) + .subscribe(keymap => content[1].value = keymap.name); + } else if (keyAction instanceof SwitchLayerAction) { + const switchLayerAction: SwitchLayerAction = keyAction; + content.push({ + name: 'Action type', + value: 'Switch layer' + }); + content.push({ + name: 'Layer', + value: capitalizeFirstLetter(LayerName[switchLayerAction.layer]) + }); + content.push({ + name: 'Toogle', + value: switchLayerAction.isLayerToggleable ? 'On' : 'Off' + }); + } this.tooltipData = { posLeft: posLeft, - posTop: posTop, - content: dummyData, + posTop: posTop, + content, shown: true }; } diff --git a/src/config-serializer/config-items/key-action/KeystrokeAction.ts b/src/config-serializer/config-items/key-action/KeystrokeAction.ts index a59fd890..751f4228 100644 --- a/src/config-serializer/config-items/key-action/KeystrokeAction.ts +++ b/src/config-serializer/config-items/key-action/KeystrokeAction.ts @@ -17,6 +17,8 @@ interface JsObjectKeystrokeAction { longPressAction?: string; } +const MODIFIERS = ['LCtrl', 'LShift', 'LAlt', 'LSuper', 'RCtrl', 'RShift', 'RAlt', 'RSuper']; + export class KeystrokeAction extends KeyAction { @assertUInt8 @@ -140,4 +142,15 @@ export class KeystrokeAction extends KeyAction { hasOnlyOneActiveModifier(): boolean { return this.modifierMask !== 0 && !(this.modifierMask & this.modifierMask - 1); } + + getModifierList(): string[] { + let modifierList: string[] = []; + let modifierMask = this.modifierMask; + for (let i = 0; modifierMask !== 0; ++i, modifierMask >>= 1) { + if (modifierMask & 1) { + modifierList.push(MODIFIERS[i]); + } + } + return modifierList; + } } diff --git a/src/util/index.ts b/src/util/index.ts new file mode 100644 index 00000000..6172fb21 --- /dev/null +++ b/src/util/index.ts @@ -0,0 +1,10 @@ +// Source: http://stackoverflow.com/questions/13720256/javascript-regex-camelcase-to-sentence +export function camelCaseToSentence(camelCasedText: string): string { + return camelCasedText.replace(/^[a-z]|[A-Z]/g, function (v, i) { + return i === 0 ? v.toUpperCase() : ' ' + v.toLowerCase(); + }); +} + +export function capitalizeFirstLetter(text: string): string { + return text.charAt(0).toUpperCase() + text.slice(1); +}