From e0c9bc310f71a06b68fbb8b5d94ad816cb19fd93 Mon Sep 17 00:00:00 2001 From: ivanixgames Date: Thu, 20 Oct 2016 02:36:31 +0800 Subject: [PATCH 1/2] Add hotkey manager class and hook into SupCore class. --- SupCore/HotKeyMgr.ts | 397 +++++++++++++++++++++++++++++++++++++++++++ SupCore/SupCore.d.ts | 5 + SupCore/index.ts | 15 +- 3 files changed, 416 insertions(+), 1 deletion(-) create mode 100644 SupCore/HotKeyMgr.ts diff --git a/SupCore/HotKeyMgr.ts b/SupCore/HotKeyMgr.ts new file mode 100644 index 00000000..c15b2f3c --- /dev/null +++ b/SupCore/HotKeyMgr.ts @@ -0,0 +1,397 @@ + +// import KeyState from "../systems/game/SupEngine/src/Input.ts"; + +/* +interface KeyModifiers { + shiftKey: boolean, + ctlKey: boolean; + altKey: boolean; + shiftLeft: boolean; + shiftRight: boolean; + ctlLeft: boolean; + ctlRight: boolean; + altLeft: boolean; + altRight: boolean; +} +*/ +interface KeyDef { + str: string; + asc: number; +} +interface KeySet { + meta: KeyDef; + core: KeyDef; +} +interface KeyState { + isDown: boolean; + wasJustPressed: boolean; + wasJustAutoRepeated: boolean; + wasJustReleased: boolean; +} +export default class HotKeyMgr { + + keyEvent = { + DOM_VK_NULL: 0, + DOM_VK_CANCEL: 3, + DOM_VK_HELP: 6, + DOM_VK_BACK_SPACE: 8, + DOM_VK_TAB: 9, + DOM_VK_CLEAR: 12, + DOM_VK_RETURN: 13, + DOM_VK_ENTER: 14, + DOM_VK_SHIFT: 16, + DOM_VK_CONTROL: 17, + DOM_VK_ALT: 18, + DOM_VK_PAUSE: 19, + DOM_VK_CAPS_LOCK: 20, + DOM_VK_ESCAPE: 27, + DOM_VK_SPACE: 32, + DOM_VK_PAGE_UP: 33, + DOM_VK_PAGE_DOWN: 34, + DOM_VK_END: 35, + DOM_VK_HOME: 36, + DOM_VK_LEFT: 37, + DOM_VK_UP: 38, + DOM_VK_RIGHT: 39, + DOM_VK_DOWN: 40, + DOM_VK_PRINTSCREEN: 44, + DOM_VK_INSERT: 45, + DOM_VK_DELETE: 46, + DOM_VK_0: 48, + DOM_VK_1: 49, + DOM_VK_2: 50, + DOM_VK_3: 51, + DOM_VK_4: 52, + DOM_VK_5: 53, + DOM_VK_6: 54, + DOM_VK_7: 55, + DOM_VK_8: 56, + DOM_VK_9: 57, + DOM_VK_SEMICOLON: 59, + DOM_VK_EQUALS: 61, + DOM_VK_A: 65, + DOM_VK_B: 66, + DOM_VK_C: 67, + DOM_VK_D: 68, + DOM_VK_E: 69, + DOM_VK_F: 70, + DOM_VK_G: 71, + DOM_VK_H: 72, + DOM_VK_I: 73, + DOM_VK_J: 74, + DOM_VK_K: 75, + DOM_VK_L: 76, + DOM_VK_M: 77, + DOM_VK_N: 78, + DOM_VK_O: 79, + DOM_VK_P: 80, + DOM_VK_Q: 81, + DOM_VK_R: 82, + DOM_VK_S: 83, + DOM_VK_T: 84, + DOM_VK_U: 85, + DOM_VK_V: 86, + DOM_VK_W: 87, + DOM_VK_X: 88, + DOM_VK_Y: 89, + DOM_VK_Z: 90, + DOM_VK_CONTEXT_MENU: 93, + DOM_VK_NUMPAD0: 96, + DOM_VK_NUMPAD1: 97, + DOM_VK_NUMPAD2: 98, + DOM_VK_NUMPAD3: 99, + DOM_VK_NUMPAD4: 100, + DOM_VK_NUMPAD5: 101, + DOM_VK_NUMPAD6: 102, + DOM_VK_NUMPAD7: 103, + DOM_VK_NUMPAD8: 104, + DOM_VK_NUMPAD9: 105, + DOM_VK_MULTIPLY: 106, + DOM_VK_ADD: 107, + DOM_VK_SEPARATOR: 108, + DOM_VK_SUBTRACT: 109, + DOM_VK_DECIMAL: 110, + DOM_VK_DIVIDE: 111, + DOM_VK_F1: 112, + DOM_VK_F2: 113, + DOM_VK_F3: 114, + DOM_VK_F4: 115, + DOM_VK_F5: 116, + DOM_VK_F6: 117, + DOM_VK_F7: 118, + DOM_VK_F8: 119, + DOM_VK_F9: 120, + DOM_VK_F10: 121, + DOM_VK_F11: 122, + DOM_VK_F12: 123, + DOM_VK_F13: 124, + DOM_VK_F14: 125, + DOM_VK_F15: 126, + DOM_VK_F16: 127, + DOM_VK_F17: 128, + DOM_VK_F18: 129, + DOM_VK_F19: 130, + DOM_VK_F20: 131, + DOM_VK_F21: 132, + DOM_VK_F22: 133, + DOM_VK_F23: 134, + DOM_VK_F24: 135, + DOM_VK_NUM_LOCK: 144, + DOM_VK_SCROLL_LOCK: 145, + DOM_VK_COMMA: 188, + DOM_VK_PERIOD: 190, + DOM_VK_SLASH: 191, + DOM_VK_BACK_QUOTE: 192, + DOM_VK_OPEN_BRACKET: 219, + DOM_VK_BACK_SLASH: 220, + DOM_VK_CLOSE_BRACKET: 221, + DOM_VK_QUOTE: 222, + DOM_VK_META: 224, + + DOM_VK_SHIFT_LEFT: 256, + DOM_VK_SHIFT_RIGHT: 257, + DOM_VK_CONTROL_LEFT: 258, + DOM_VK_CONTROL_RIGHT: 259, + DOM_VK_ALT_LEFT: 260, + DOM_VK_ALT_RIGHT: 261 + }; + + + private keyset: { [contextName: string]: any } = {}; + private uniq: { [contextName: string]: any } = {}; + + constructor () { + Object.freeze(this.keyEvent); + } + + isModifier(vkstring: string) { + let rc = false; + switch(vkstring) { + case "DOM_VK_NULL": + case "DOM_VK_ALT": + case "DOM_VK_SHIFT": + case "DOM_VK_CONTROL": + case "DOM_VK_META": + case "DOM_VK_ALT_LEFT": + case "DOM_VK_SHIFT_LEFT": + case "DOM_VK_CONTROL_LEFT": + case "DOM_VK_ALT_RIGHT": + case "DOM_VK_SHIFT_RIGHT": + case "DOM_VK_CONTROL_RIGHT": + rc = true; + break; + } + return rc; + } + + decGroup(groupName: string): {ok: boolean, msg?: string} { + if (groupName == null) { + return {ok: false, msg: "missing groupName"}; + } + if (typeof groupName !== "string") { + return {ok: false, msg: "groupName must be string"}; + } + if (this.keyset[groupName] == null) { + this.keyset[groupName] = {}; + return {ok: true}; + } else { + return {ok: false, msg: "groupName already declared"}; + } + } + decAction(groupName: string, actionName: string): {ok: boolean, msg?: string} { + if (groupName == null) { + return {ok: false, msg: "missing groupName"}; + } + if (this.keyset[groupName] == null) { + return {ok: false, msg: "groupName " + groupName + " not declared"}; + } + if (actionName == null) { + return {ok: false, msg: "missing actionName"}; + } + if (typeof actionName !== "string") { + return {ok: false, msg: "actionName must be string"}; + } + + if (this.keyset[groupName][actionName] == null) { + this.keyset[groupName][actionName] = {meta: {}, core: {}}; + return {ok: true}; + } else { + return {ok: false, msg: "actionName already declared"}; + } + } + seqKeySet(groupName: string, actionName: string): {ok: boolean, msg?: string, str?: string} { + if (groupName == null) { + return {ok: false, msg: "missing groupName"}; + } + if (this.keyset[groupName] == null) { + return {ok: false, msg: "group " + groupName + " not declared" }; + } + if (actionName == null) { + return {ok: false, msg: "missing actionName" }; + } + if (typeof actionName !== "string") { + return {ok: false, msg: "actionName must be string" }; + } + let ks = this.keyset[groupName][actionName]; + if (ks == null) { + return {ok: false, msg: "action " + actionName + " not declared" }; + } + if (ks.meta == null || ks.meta.str == null) { + return {ok: false, msg: "action " + actionName + " not declared properly" }; + } + if (ks.core == null || ks.meta.str == null) { + return {ok: false, msg: "action " + actionName + " not declared properly" }; + } + // todo: validate str prop + let str = ks.meta.str + "+" + ks.core.str; + return {ok: true, str: str}; + + } + regKeySet(groupName: string, actionName: string, keyModDef: string, keyCodeDef: string ): {ok: boolean, msg?: string} { + if (groupName == null) { + return {ok: false, msg: "missing groupName" }; + } + if (this.keyset[groupName] == null) { + return {ok: false, msg: "group " + groupName + " not declared" }; + } + if (actionName == null) { + return {ok: false, msg: "missing actionName" }; + } + if (typeof actionName !== "string") { + return {ok: false, msg: "actionName must be string" }; + } + if (this.keyset[groupName][actionName] == null) { + return {ok: false, msg: "action " + actionName + " not declared" }; + } + if (this.keyset[groupName][actionName].meta == null) { + return {ok: false, msg: "action " + actionName + " not declared properly" }; + } + if (this.keyset[groupName][actionName].core == null) { + return {ok: false, msg: "action " + actionName + " not declared properly" }; + } + + if (typeof keyModDef !== "string") { + return {ok: false, msg: "keyModDef must be string" }; + } + if (typeof (this.keyEvent)[keyModDef] === "undefined") { + return {ok: false, msg: "keyModDef not valid" }; + } + + if (typeof keyCodeDef !== "string") { + return {ok: false, msg: "keyCodeDef must be string" }; + } + if (typeof (this.keyEvent)[keyCodeDef] === "undefined") { + return {ok: false, msg: "keyCodeDef not valid" }; + } + + if (!this.isModifier(keyModDef)) { + return {ok: false, msg: "keyModDef must be a modifier key or DOM_VK_NULL" }; + } + if (this.isModifier(keyCodeDef) && keyCodeDef !== "DOM_VK_NULL") { + return {ok: false, msg: "keyCodeDef cannot be a modifier key" }; + } + + let keySetStr = keyModDef + "+" + keyCodeDef; + + if (this.uniq[keySetStr] == null) { + this.uniq[keySetStr] = {group: groupName, fcn: actionName}; + } else { + return {ok: false, msg: "keyset [" + keySetStr + "] already assigned" }; + } + + let old = this.seqKeySet(groupName, actionName); + if (old.ok) { + if (this.uniq[old.str]) { + delete this.uniq[old.str]; + } + } + + let meta = { str: keyModDef, asc: (this.keyEvent)[keyModDef] }; + let core = { str: keyCodeDef, asc: (this.keyEvent)[keyCodeDef] }; + + this.keyset[groupName][actionName].meta = meta; + this.keyset[groupName][actionName].core = core; + + return {ok: true}; + } + clrKeySet(groupName: string, actionName: string ): {ok: boolean, msg?: string} { + + if (groupName == null) { + return {ok: false, msg: "missing groupName" }; + } + if (this.keyset[groupName] == null) { + return {ok: false, msg: "group [" + groupName + "] not registered" }; + } + if (actionName == null) { + return {ok: false, msg: "missing actionName" }; + } + if (typeof actionName !== "string") { + return {ok: false, msg: "actionName must be string" }; + } + if (this.keyset[groupName][actionName] == null) { + return {ok: false, msg: "action " + actionName + " not declared" }; + } + + let old = this.seqKeySet(groupName, actionName); + if (old.ok) { + if (this.uniq[old.str]) { + delete this.uniq[old.str]; + } + } + + this.keyset[groupName][actionName].meta = {}; + this.keyset[groupName][actionName].core = {}; + return {ok: true}; + } + getKeySet(groupName: string, actionName: string ): {ok: boolean, msg?: string, obj?: KeySet} { + + if (groupName == null) { + return {ok: false, msg: "missing groupName" }; + } + if (this.keyset[groupName] == null) { + return {ok: false, msg: "group [" + groupName + "] not registered" }; + } + if (actionName == null) { + return {ok: false, msg: "missing actionName" }; + } + if (typeof actionName !== "string") { + return {ok: false, msg: "actionName must be string" }; + } + if (this.keyset[groupName][actionName] == null) { + return {ok: false, msg: "action " + actionName + " not declared" }; + } + + let obj = this.keyset[groupName][actionName]; + return {ok: true, obj: obj}; + } + // IKBA: Input.KeyboardButton.Array + isKeySetActiveIKBA(keySet: KeySet, ikbArr: KeyState[] ) { + + let ke: any = this.keyEvent; + + let meta: KeyDef = keySet.meta; + let core: KeyDef = keySet.core; + + // simple test of both keymodifer and keycode in Input.KeyboardButton.Array[].isDown + + if (meta.asc !== ke.DOM_VK_NULL) { + if (ikbArr[meta.asc].isDown && ikbArr[core.asc].isDown) { + return true; + } + } + + // test when kmStr = "DOM_VK_NULL" + + if ( ikbArr[ke.DOM_VK_ALT].isDown || ikbArr[ke.DOM_VK_CONTROL].isDown || + ikbArr[ke.DOM_VK_SHIFT].isDown || ikbArr[ke.DOM_VK_META].isDown + ) { + return false; + } + if (ikbArr[core.asc].isDown) { + return true; + } + + return false; + } +} + diff --git a/SupCore/SupCore.d.ts b/SupCore/SupCore.d.ts index 6925f4f7..fb96b903 100644 --- a/SupCore/SupCore.d.ts +++ b/SupCore/SupCore.d.ts @@ -11,6 +11,11 @@ declare namespace SupCore { constructor(key: string, variables: { [key: string]: string; }); } + class HotKeyMgr { + + } + export let hotKeyMgr: HotKeyMgr; + namespace Data { export function hasDuplicateName(id: string, name: string, siblings: Array<{ id: string; name: string; }>): boolean; export function ensureUniqueName(id: string, name: string, siblings: Array<{ id: string; name: string; }>): string; diff --git a/SupCore/index.ts b/SupCore/index.ts index d357f497..e1636337 100644 --- a/SupCore/index.ts +++ b/SupCore/index.ts @@ -1,9 +1,22 @@ /// import * as Data from "./Data"; - export { Data }; + +import HotKeyMgr from "./HotKeyMgr"; + +if (typeof window === "object") { + if (window === window.top) { + this.hotKeyMgr = new HotKeyMgr(); + } else { + this.hotKeyMgr = (window).top.SupCore.hotKeyMgr; + } +} + + + + export * from "./systems"; export function log(message: string): void { From 9d2dff81eeb239e3d08847b3ca3b9ad85ddeb1bf Mon Sep 17 00:00:00 2001 From: ivanixgames Date: Mon, 24 Oct 2016 16:52:04 +0800 Subject: [PATCH 2/2] Cleaned up of HotkeyMgr class, which enables editing of default hotkey definitions --- SupCore/HotKeyMgr.ts | 330 +++++++++++++++++++++++++++++-------------- 1 file changed, 223 insertions(+), 107 deletions(-) diff --git a/SupCore/HotKeyMgr.ts b/SupCore/HotKeyMgr.ts index c15b2f3c..891379bd 100644 --- a/SupCore/HotKeyMgr.ts +++ b/SupCore/HotKeyMgr.ts @@ -1,26 +1,14 @@ // import KeyState from "../systems/game/SupEngine/src/Input.ts"; -/* -interface KeyModifiers { - shiftKey: boolean, - ctlKey: boolean; - altKey: boolean; - shiftLeft: boolean; - shiftRight: boolean; - ctlLeft: boolean; - ctlRight: boolean; - altLeft: boolean; - altRight: boolean; -} -*/ + interface KeyDef { str: string; asc: number; } interface KeySet { - meta: KeyDef; - core: KeyDef; + meta: KeyDef | {}; + core: KeyDef | {}; } interface KeyState { isDown: boolean; @@ -28,10 +16,32 @@ interface KeyState { wasJustAutoRepeated: boolean; wasJustReleased: boolean; } +interface PropAction { + [action: string]: any; +} +interface ResultOK { + ok: boolean; + msg?: string; +} +interface ResultActions { + ok: boolean; + msg?: string; + actions?: PropAction; +} +interface ResultKeySet { + ok: boolean; + msg?: string; + keySet?: KeySet; +} +interface ResultStr { + ok: boolean; + msg?: string; + str?: string; +} export default class HotKeyMgr { keyEvent = { - DOM_VK_NULL: 0, + DOM_VK_CANCEL: 3, DOM_VK_HELP: 6, DOM_VK_BACK_SPACE: 8, @@ -148,17 +158,19 @@ export default class HotKeyMgr { DOM_VK_QUOTE: 222, DOM_VK_META: 224, + DOM_VK_NULL: 255, DOM_VK_SHIFT_LEFT: 256, DOM_VK_SHIFT_RIGHT: 257, DOM_VK_CONTROL_LEFT: 258, DOM_VK_CONTROL_RIGHT: 259, DOM_VK_ALT_LEFT: 260, - DOM_VK_ALT_RIGHT: 261 - }; + DOM_VK_ALT_RIGHT: 261, + ARRAY_SIZE: 262 + }; - private keyset: { [contextName: string]: any } = {}; - private uniq: { [contextName: string]: any } = {}; + private keyset: { [name: string]: any } = {}; + private uniq: { [combo: string]: any } = {}; constructor () { Object.freeze(this.keyEvent); @@ -183,91 +195,137 @@ export default class HotKeyMgr { } return rc; } - - decGroup(groupName: string): {ok: boolean, msg?: string} { + _valGroupParm(groupName: string, groupExists?: boolean): ResultOK { if (groupName == null) { return {ok: false, msg: "missing groupName"}; } if (typeof groupName !== "string") { return {ok: false, msg: "groupName must be string"}; } - if (this.keyset[groupName] == null) { - this.keyset[groupName] = {}; + + if (!groupExists) { return {ok: true}; - } else { - return {ok: false, msg: "groupName already declared"}; - } - } - decAction(groupName: string, actionName: string): {ok: boolean, msg?: string} { - if (groupName == null) { - return {ok: false, msg: "missing groupName"}; } + if (this.keyset[groupName] == null) { return {ok: false, msg: "groupName " + groupName + " not declared"}; } + return {ok: true}; + } + _valActionParm(actionName: string): ResultOK { if (actionName == null) { return {ok: false, msg: "missing actionName"}; } if (typeof actionName !== "string") { return {ok: false, msg: "actionName must be string"}; } + return {ok: true}; + } + _validateParms(groupName: string, actionName: string, groupExists?: boolean, actionExists?: boolean, keySetDefined?: boolean): ResultOK { + let rc = this._valGroupParm(groupName); + if(!rc.ok) { + return rc; + } - if (this.keyset[groupName][actionName] == null) { - this.keyset[groupName][actionName] = {meta: {}, core: {}}; - return {ok: true}; - } else { - return {ok: false, msg: "actionName already declared"}; + rc = this._valActionParm(actionName); + if(!rc.ok) { + return rc; } - } - seqKeySet(groupName: string, actionName: string): {ok: boolean, msg?: string, str?: string} { - if (groupName == null) { - return {ok: false, msg: "missing groupName"}; + + if (!groupExists) { + return {ok: true}; } + if (this.keyset[groupName] == null) { - return {ok: false, msg: "group " + groupName + " not declared" }; - } - if (actionName == null) { - return {ok: false, msg: "missing actionName" }; + return {ok: false, msg: "groupName " + groupName + " not declared"}; } - if (typeof actionName !== "string") { - return {ok: false, msg: "actionName must be string" }; + + if (!actionExists) { + return {ok: true}; } + let ks = this.keyset[groupName][actionName]; + if (ks == null) { return {ok: false, msg: "action " + actionName + " not declared" }; } - if (ks.meta == null || ks.meta.str == null) { + if (ks.meta == null) { return {ok: false, msg: "action " + actionName + " not declared properly" }; } - if (ks.core == null || ks.meta.str == null) { + if (ks.core == null) { return {ok: false, msg: "action " + actionName + " not declared properly" }; } - // todo: validate str prop + + if (!keySetDefined) { + return {ok: true}; + } + + if (ks.meta == null || ks.meta.str == null) { + return {ok: false, msg: "meta not declared properly" }; + } + if (ks.core == null || ks.core.str == null) { + return {ok: false, msg: "core not declared properly" }; + } + + return {ok: true}; + } + seqKeySet(groupName: string, actionName: string): ResultStr { + + let rc = this._validateParms(groupName, actionName, true, true, true); + if (!rc.ok) { + return rc; + } + + let ks = this.keyset[groupName][actionName]; + // TODO: validate str prop let str = ks.meta.str + "+" + ks.core.str; return {ok: true, str: str}; } - regKeySet(groupName: string, actionName: string, keyModDef: string, keyCodeDef: string ): {ok: boolean, msg?: string} { - if (groupName == null) { - return {ok: false, msg: "missing groupName" }; + getActions(groupName: string): ResultActions { + + let rc = this._valGroupParm(groupName, true); + if(!rc.ok) { + return rc; } - if (this.keyset[groupName] == null) { - return {ok: false, msg: "group " + groupName + " not declared" }; + + return {ok: true, actions: this.keyset[groupName]}; + + } + decGroup(groupName: string): ResultOK { + + let rc = this._valGroupParm(groupName); + if(!rc.ok) { + return rc; } - if (actionName == null) { - return {ok: false, msg: "missing actionName" }; + if (this.keyset[groupName] == null) { + this.keyset[groupName] = {}; + return {ok: true}; + } else { + return {ok: false, msg: "groupName already declared"}; } - if (typeof actionName !== "string") { - return {ok: false, msg: "actionName must be string" }; + } + decAction(groupName: string, actionName: string): ResultKeySet { + let rc = this._validateParms(groupName, actionName, true, false); + if(!rc.ok) { + return rc; } + if (this.keyset[groupName][actionName] == null) { - return {ok: false, msg: "action " + actionName + " not declared" }; - } - if (this.keyset[groupName][actionName].meta == null) { - return {ok: false, msg: "action " + actionName + " not declared properly" }; + let keySet : KeySet = {meta: {}, core: {}}; + this.keyset[groupName][actionName] = keySet; + return {ok: true, keySet: keySet}; + } else { + return {ok: false, msg: "actionName already declared"}; } - if (this.keyset[groupName][actionName].core == null) { - return {ok: false, msg: "action " + actionName + " not declared properly" }; + } + + + setAction(groupName: string, actionName: string, keyModDef: string, keyCodeDef: string ): ResultKeySet { + + let rc = this._validateParms(groupName, actionName, true, true); + if(!rc.ok) { + return rc; } if (typeof keyModDef !== "string") { @@ -306,30 +364,19 @@ export default class HotKeyMgr { } } - let meta = { str: keyModDef, asc: (this.keyEvent)[keyModDef] }; - let core = { str: keyCodeDef, asc: (this.keyEvent)[keyCodeDef] }; + let keySet = this.keyset[groupName][actionName]; - this.keyset[groupName][actionName].meta = meta; - this.keyset[groupName][actionName].core = core; + keySet.meta = { str: keyModDef, asc: (this.keyEvent)[keyModDef] }; + keySet.core = { str: keyCodeDef, asc: (this.keyEvent)[keyCodeDef] }; + + return {ok: true, keySet: keySet}; - return {ok: true}; } - clrKeySet(groupName: string, actionName: string ): {ok: boolean, msg?: string} { + freeAction(groupName: string, actionName: string ): ResultOK { - if (groupName == null) { - return {ok: false, msg: "missing groupName" }; - } - if (this.keyset[groupName] == null) { - return {ok: false, msg: "group [" + groupName + "] not registered" }; - } - if (actionName == null) { - return {ok: false, msg: "missing actionName" }; - } - if (typeof actionName !== "string") { - return {ok: false, msg: "actionName must be string" }; - } - if (this.keyset[groupName][actionName] == null) { - return {ok: false, msg: "action " + actionName + " not declared" }; + let rc = this._validateParms(groupName, actionName, true, true); + if(!rc.ok) { + return rc; } let old = this.seqKeySet(groupName, actionName); @@ -339,44 +386,114 @@ export default class HotKeyMgr { } } - this.keyset[groupName][actionName].meta = {}; - this.keyset[groupName][actionName].core = {}; + let keySet = this.keyset[groupName][actionName]; + + keySet.meta = {}; + keySet.core = {}; + return {ok: true}; } - getKeySet(groupName: string, actionName: string ): {ok: boolean, msg?: string, obj?: KeySet} { + getKeySet(groupName: string, actionName: string ): ResultKeySet { - if (groupName == null) { - return {ok: false, msg: "missing groupName" }; + let rc = this._validateParms(groupName, actionName, true, true, true); + if(!rc.ok) { + return rc; } - if (this.keyset[groupName] == null) { - return {ok: false, msg: "group [" + groupName + "] not registered" }; + + let keySet = this.keyset[groupName][actionName]; + return {ok: true, keySet: keySet}; + + } + // + saveAction(groupName: string, actionName: string ): ResultKeySet { + + let rc = this._validateParms(groupName, actionName, true, true, true); + if(!rc.ok) { + return rc; } - if (actionName == null) { - return {ok: false, msg: "missing actionName" }; + + let keySet = this.keyset[groupName][actionName]; + + let ls = window.localStorage; + let dbKey = "hotkey." + groupName + "." + actionName; + let cfg = {meta: keySet.meta.str, core: keySet.core.str}; + ls.setItem(dbKey, JSON.stringify(cfg) ); + + return {ok: true, keySet: keySet}; + + } + clrAction(groupName: string, actionName: string ): ResultOK { + + let rc = this._validateParms(groupName, actionName, true, true, true); + if(!rc.ok) { + return rc; } - if (typeof actionName !== "string") { - return {ok: false, msg: "actionName must be string" }; + + let ls = window.localStorage; + let dbKey = "hotkey." + groupName + "." + actionName; + ls.removeItem(dbKey); + return {ok: true}; + } + loadConfig(groupName: string): ResultOK { + + let rc = this._valGroupParm(groupName, true); + if(!rc.ok) { + console.log("loadConfig: rc: " + rc.msg); + return rc; } - if (this.keyset[groupName][actionName] == null) { - return {ok: false, msg: "action " + actionName + " not declared" }; + + // TODO: + // - async load of config file for groupName (plugin) + // - load default for navigator.platform + + // For now, just load any localStorage preferences + + rc = this.getActions(groupName); + if (!rc.ok) { + return rc; + } + let actions = (rc).actions; + let ls = window.localStorage; + + for (let action in actions) { + if (actions.hasOwnProperty(action)) { + let dbKey = "hotkey." + groupName + "." + action; + let str = ls.getItem(dbKey); + if (str) { + let cfg = JSON.parse(str); + let rc = this.setAction(groupName, action, cfg.meta, cfg.core ); + if (!rc.ok) { + console.error("hotKeyMgr.loadConfig: " + groupName + ": " + rc.msg); + } + } + } } - let obj = this.keyset[groupName][actionName]; - return {ok: true, obj: obj}; } - // IKBA: Input.KeyboardButton.Array - isKeySetActiveIKBA(keySet: KeySet, ikbArr: KeyState[] ) { + // Test if KeyState in Input.KeyboardButton.Array + inKeyboardButtonArray(keySet: KeySet, ikbArr: KeyState[] ): boolean { + if (keySet.meta == null) { + console.error("hotKeyMgr.inKeyboardButtonArray: Warning: bad keySet.meta"); + return false; + } + if (keySet.core == null) { + console.error("hotKeyMgr.inKeyboardButtonArray: Warning: bad keySet.core"); + return false; + } let ke: any = this.keyEvent; - - let meta: KeyDef = keySet.meta; - let core: KeyDef = keySet.core; + let meta = keySet.meta; + let core = keySet.core; // simple test of both keymodifer and keycode in Input.KeyboardButton.Array[].isDown if (meta.asc !== ke.DOM_VK_NULL) { - if (ikbArr[meta.asc].isDown && ikbArr[core.asc].isDown) { - return true; + if (ikbArr[meta.asc].isDown) { + + if (core.asc === ke.DOM_VK_NULL || ikbArr[core.asc].isDown) { + return true; + } + } } @@ -394,4 +511,3 @@ export default class HotKeyMgr { return false; } } -