Files
ueblueprint/js/input/keyboard/KeyboardShortcut.js
BarsDev 6ba2705386 Large refactoring and new nodes
* Fix node reference when changing elements

* Fix ScriptVariables parsing

* Fix invariant text and niagara types

* Niagara convert nodes

* Move node tests to own files

* More Niagara tests

* Niagara float and smaller fixes

* More Decoding

* More decoding

* WIP

* Float is real

* WIP

* More types and colors

* Test case and small polish

* WIP

* WIP

* Fix niagara script variables merging

* Fix Niagara variables

* Fixing mirrored ExportPath

* Fix Export paths name adjustments

* Simplify arc calculation

* Simplify a bit arc calculation

* source / destionation => origin / target

* Minor refactoring

* Fix switched link position

* Rename some properties for uniformity

* Fix input escape

* Simplify test

* About window

* Dialog backdrop style

* About dialog touches

* Remove dependency and minot improvement

* Light mode

* Fix link location and css small improvement

* Link direction and minor fixes

* Some minor fixes and refactoring

* Refactoring WIP

* Shorting repetitive bits

* More tests

* Simplify linking tests
2025-02-07 00:36:03 +02:00

136 lines
4.4 KiB
JavaScript
Executable File

import Configuration from "../../Configuration.js"
import IInput from "../IInput.js"
import KeyBindingEntity from "../../entity/KeyBindingEntity.js"
/**
* @typedef {import("../IInput.js").Options & {
* activationKeys?: String | KeyBindingEntity | (String | KeyBindingEntity)[],
* consumeEvent?: Boolean,
* listenOnFocus?: Boolean,
* unlistenOnTextEdit?: Boolean,
* }} Options
*/
/**
* @template {Element} T
* @extends IInput<T>
*/
export default class KeyboardShortcut extends IInput {
static #ignoreEvent =
/** @param {KeyboardShortcut} self */
self => { }
/** @type {KeyBindingEntity[]} */
#activationKeys
pressedKey = ""
/**
* @param {T} target
* @param {Blueprint} blueprint
* @param {Options} options
*/
constructor(
target,
blueprint,
options = {},
onKeyDown = KeyboardShortcut.#ignoreEvent,
onKeyUp = KeyboardShortcut.#ignoreEvent
) {
options.activationKeys ??= []
options.consumeEvent ??= true
options.listenOnFocus ??= true
options.unlistenOnTextEdit ??= true // No shortcuts when inside of a text field
if (!(options.activationKeys instanceof Array)) {
options.activationKeys = [options.activationKeys]
}
options.activationKeys = options.activationKeys.map(v => {
if (v instanceof KeyBindingEntity) {
return v
}
if (v.constructor === String) {
const parsed = KeyBindingEntity.grammar.run(v)
if (parsed.status) {
return parsed.value
}
}
throw new Error("Unexpected key value")
})
super(target, blueprint, options)
this.onKeyDown = onKeyDown
this.onKeyUp = onKeyUp
this.#activationKeys = this.options.activationKeys ?? []
/** @param {KeyBindingEntity} keyEntry */
const wantsShift = keyEntry => keyEntry.bShift?.valueOf() || keyEntry.Key.valueOf() == "LeftShift" || keyEntry.Key.valueOf() == "RightShift"
/** @param {KeyBindingEntity} keyEntry */
const wantsCtrl = keyEntry => keyEntry.bCtrl?.valueOf() || keyEntry.Key.valueOf() == "LeftControl" || keyEntry.Key.valueOf() == "RightControl"
/** @param {KeyBindingEntity} keyEntry */
const wantsAlt = keyEntry => keyEntry.bAlt?.valueOf() || keyEntry.Key.valueOf() == "LeftAlt" || keyEntry.Key.valueOf() == "RightAlt"
let self = this
/** @param {KeyboardEvent} e */
this.keyDownHandler = e => {
if (
self.#activationKeys.some(keyEntry =>
wantsShift(keyEntry) == e.shiftKey
&& wantsCtrl(keyEntry) == e.ctrlKey
&& wantsAlt(keyEntry) == e.altKey
&& Configuration.Keys[keyEntry.Key.value] == e.code
)
) {
if (this.consumeEvent) {
e.preventDefault()
e.stopImmediatePropagation()
}
this.pressedKey = e.code
self.fire()
document.removeEventListener("keydown", self.keyDownHandler)
document.addEventListener("keyup", self.keyUpHandler)
}
}
/** @param {KeyboardEvent} e */
this.keyUpHandler = e => {
if (
self.#activationKeys.some(keyEntry =>
keyEntry.bShift?.valueOf() && e.key == "Shift"
|| keyEntry.bCtrl?.valueOf() && e.key == "Control"
|| keyEntry.bAlt?.valueOf() && e.key == "Alt"
|| keyEntry.bCmd?.valueOf() && e.key == "Meta"
|| Configuration.Keys[keyEntry.Key.value] == e.code
)
) {
if (this.consumeEvent) {
e.stopImmediatePropagation()
}
self.unfire()
this.pressedKey = ""
document.removeEventListener("keyup", this.keyUpHandler)
document.addEventListener("keydown", this.keyDownHandler)
}
}
}
listenEvents() {
document.addEventListener("keydown", this.keyDownHandler)
}
unlistenEvents() {
document.removeEventListener("keydown", this.keyDownHandler)
}
/* Subclasses can override */
fire() {
this.onKeyDown(this)
}
unfire() {
this.onKeyUp(this)
}
}