Update KeyboardMouseInputField (#1232)

* Assign missing type

* Update KeyboardMouseInputField to use an array instead of a string

* Use "modifiers" instead of "value" or "inputs"

* Simplify

* Add support for using keys

* Use bool args instead of a string
This commit is contained in:
toasted-nutbread 2021-01-14 17:54:09 -05:00 committed by GitHub
parent 5ae3acf6ff
commit 351d9b2e8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 131 additions and 75 deletions

View File

@ -27,7 +27,7 @@ class KeyboardMouseInputField extends EventDispatcher {
this._isPointerTypeSupported = isPointerTypeSupported; this._isPointerTypeSupported = isPointerTypeSupported;
this._keySeparator = ' + '; this._keySeparator = ' + ';
this._inputNameMap = new Map(DocumentUtil.getModifierKeys(os)); this._inputNameMap = new Map(DocumentUtil.getModifierKeys(os));
this._keyPriorities = new Map([ this._modifierPriorities = new Map([
['meta', -4], ['meta', -4],
['ctrl', -3], ['ctrl', -3],
['alt', -2], ['alt', -2],
@ -35,25 +35,29 @@ class KeyboardMouseInputField extends EventDispatcher {
]); ]);
this._mouseInputNamePattern = /^mouse(\d+)$/; this._mouseInputNamePattern = /^mouse(\d+)$/;
this._eventListeners = new EventListenerCollection(); this._eventListeners = new EventListenerCollection();
this._value = ''; this._key = null;
this._type = null; this._modifiers = [];
this._penPointerIds = new Set(); this._penPointerIds = new Set();
this._mouseModifiersSupported = false;
this._keySupported = false;
} }
get value() { get modifiers() {
return this._value; return this._modifiers;
} }
prepare(value, type) { prepare(key, modifiers, mouseModifiersSupported=false, keySupported=false) {
this.cleanup(); this.cleanup();
this._value = value; this._key = key;
const modifiers = this._splitValue(value); this._modifiers = this._sortModifiers(modifiers);
const {displayValue} = this._getInputStrings(modifiers); this._mouseModifiersSupported = mouseModifiersSupported;
this._keySupported = keySupported;
this._updateDisplayString();
const events = [ const events = [
[this._inputNode, 'keydown', this._onModifierKeyDown.bind(this), false] [this._inputNode, 'keydown', this._onModifierKeyDown.bind(this), false]
]; ];
if (type === 'modifierInputs' && this._mouseButton !== null) { if (mouseModifiersSupported && this._mouseButton !== null) {
events.push( events.push(
[this._mouseButton, 'mousedown', this._onMouseButtonMouseDown.bind(this), false], [this._mouseButton, 'mousedown', this._onMouseButtonMouseDown.bind(this), false],
[this._mouseButton, 'pointerdown', this._onMouseButtonPointerDown.bind(this), false], [this._mouseButton, 'pointerdown', this._onMouseButtonPointerDown.bind(this), false],
@ -64,7 +68,6 @@ class KeyboardMouseInputField extends EventDispatcher {
[this._mouseButton, 'contextmenu', this._onMouseButtonContextMenu.bind(this), false] [this._mouseButton, 'contextmenu', this._onMouseButtonContextMenu.bind(this), false]
); );
} }
this._inputNode.value = displayValue;
for (const args of events) { for (const args of events) {
this._eventListeners.addEventListener(...args); this._eventListeners.addEventListener(...args);
} }
@ -72,35 +75,33 @@ class KeyboardMouseInputField extends EventDispatcher {
cleanup() { cleanup() {
this._eventListeners.removeAllEventListeners(); this._eventListeners.removeAllEventListeners();
this._value = ''; this._modifiers = [];
this._type = null; this._key = null;
this._mouseModifiersSupported = false;
this._keySupported = false;
this._penPointerIds.clear(); this._penPointerIds.clear();
} }
clearInputs() { clearInputs() {
this._updateInputs([]); this._updateModifiers([], null);
} }
// Private // Private
_splitValue(value) { _sortModifiers(modifiers) {
return value.split(/[,;\s]+/).map((v) => v.trim().toLowerCase()).filter((v) => v.length > 0);
}
_sortInputs(inputs) {
const pattern = this._mouseInputNamePattern; const pattern = this._mouseInputNamePattern;
const keyPriorities = this._keyPriorities; const keyPriorities = this._modifierPriorities;
const inputInfos = inputs.map((value, index) => { const modifierInfos = modifiers.map((modifier, index) => {
const match = pattern.exec(value); const match = pattern.exec(modifier);
if (match !== null) { if (match !== null) {
return [value, 1, Number.parseInt(match[1], 10), index]; return [modifier, 1, Number.parseInt(match[1], 10), index];
} else { } else {
let priority = keyPriorities.get(value); let priority = keyPriorities.get(modifier);
if (typeof priority === 'undefined') { priority = 0; } if (typeof priority === 'undefined') { priority = 0; }
return [value, 0, priority, index]; return [modifier, 0, priority, index];
} }
}); });
inputInfos.sort((a, b) => { modifierInfos.sort((a, b) => {
let i = a[1] - b[1]; let i = a[1] - b[1];
if (i !== 0) { return i; } if (i !== 0) { return i; }
@ -113,36 +114,37 @@ class KeyboardMouseInputField extends EventDispatcher {
i = a[3] - b[3]; i = a[3] - b[3];
return i; return i;
}); });
return inputInfos.map(([value]) => value); return modifierInfos.map(([modifier]) => modifier);
} }
_getInputStrings(inputs) { _updateDisplayString() {
let value = '';
let displayValue = ''; let displayValue = '';
let first = true; let first = true;
for (const input of inputs) { for (const modifier of this._modifiers) {
const {name} = this._getInputName(input); const {name} = this._getModifierName(modifier);
if (first) { if (first) {
first = false; first = false;
} else { } else {
value += ', ';
displayValue += this._keySeparator; displayValue += this._keySeparator;
} }
value += input;
displayValue += name; displayValue += name;
} }
return {value, displayValue}; if (this._key !== null) {
if (!first) { displayValue += this._keySeparator; }
displayValue += this._key;
}
this._inputNode.value = displayValue;
} }
_getInputName(value) { _getModifierName(modifier) {
const pattern = this._mouseInputNamePattern; const pattern = this._mouseInputNamePattern;
const match = pattern.exec(value); const match = pattern.exec(modifier);
if (match !== null) { if (match !== null) {
return {name: `Mouse ${match[1]}`, type: 'mouse'}; return {name: `Mouse ${match[1]}`, type: 'mouse'};
} }
let name = this._inputNameMap.get(value); let name = this._inputNameMap.get(modifier);
if (typeof name === 'undefined') { name = value; } if (typeof name === 'undefined') { name = modifier; }
return {name, type: 'key'}; return {name, type: 'key'};
} }
@ -166,24 +168,40 @@ class KeyboardMouseInputField extends EventDispatcher {
return modifiers; return modifiers;
} }
_isModifierKey(keyName) {
switch (keyName) {
case 'Alt':
case 'Control':
case 'Meta':
case 'Shift':
return true;
default:
return false;
}
}
_onModifierKeyDown(e) { _onModifierKeyDown(e) {
e.preventDefault(); e.preventDefault();
const key = DocumentUtil.getKeyFromEvent(e); const key = DocumentUtil.getKeyFromEvent(e);
switch (key) { if (this._keySupported) {
case 'Escape': this._updateModifiers([...this._getModifierKeys(e)], this._isModifierKey(key) ? void 0 : key);
case 'Backspace': } else {
this.clearInputs(); switch (key) {
break; case 'Escape':
default: case 'Backspace':
this._addInputs(this._getModifierKeys(e)); this.clearInputs();
break; break;
default:
this._addModifiers(this._getModifierKeys(e));
break;
}
} }
} }
_onMouseButtonMouseDown(e) { _onMouseButtonMouseDown(e) {
e.preventDefault(); e.preventDefault();
this._addInputs(DocumentUtil.getActiveButtons(e)); this._addModifiers(DocumentUtil.getActiveButtons(e));
} }
_onMouseButtonPointerDown(e) { _onMouseButtonPointerDown(e) {
@ -200,7 +218,7 @@ class KeyboardMouseInputField extends EventDispatcher {
return; return;
} }
e.preventDefault(); e.preventDefault();
this._addInputs(DocumentUtil.getActiveButtons(e)); this._addModifiers(DocumentUtil.getActiveButtons(e));
} }
_onMouseButtonPointerOver(e) { _onMouseButtonPointerOver(e) {
@ -227,22 +245,41 @@ class KeyboardMouseInputField extends EventDispatcher {
e.preventDefault(); e.preventDefault();
} }
_addInputs(newInputs) { _addModifiers(newModifiers, newKey) {
const inputs = new Set(this._splitValue(this._value)); const modifiers = new Set(this._modifiers);
for (const input of newInputs) { for (const modifier of newModifiers) {
inputs.add(input); modifiers.add(modifier);
} }
this._updateInputs([...inputs]); this._updateModifiers([...modifiers], newKey);
} }
_updateInputs(inputs) { _updateModifiers(modifiers, newKey) {
inputs = this._sortInputs(inputs); modifiers = this._sortModifiers(modifiers);
const node = this._inputNode; let changed = false;
const {value, displayValue} = this._getInputStrings(inputs); if (typeof newKey !== 'undefined' && this._key !== newKey) {
node.value = displayValue; this._key = newKey;
if (this._value === value) { return; } changed = true;
this._value = value; }
this.trigger('change', {value, displayValue}); if (!this._areArraysEqual(this._modifiers, modifiers)) {
this._modifiers = modifiers;
changed = true;
}
this._updateDisplayString();
if (changed) {
this.trigger('change', {modifiers: this._modifiers, key: this._key});
}
}
_areArraysEqual(array1, array2) {
const length = array1.length;
if (length !== array2.length) { return false; }
for (let i = 0; i < length; ++i) {
if (array1[i] !== array2[i]) { return false; }
}
return true;
} }
} }

View File

@ -525,11 +525,12 @@ class ProfileConditionUI {
} }
} }
_onModifierInputChange({validate, normalize}, {value}) { _onModifierInputChange({validate, normalize}, {modifiers}) {
const okay = this._validateValue(value, validate); modifiers = this._joinModifiers(modifiers);
this._value = value; const okay = this._validateValue(modifiers, validate);
this._value = modifiers;
if (okay) { if (okay) {
const normalizedValue = this._normalizeValue(value, normalize); const normalizedValue = this._normalizeValue(modifiers, normalize);
this.settingsController.setGlobalSetting(this.getPath('value'), normalizedValue); this.settingsController.setGlobalSetting(this.getPath('value'), normalizedValue);
} }
} }
@ -589,7 +590,7 @@ class ProfileConditionUI {
let inputType = 'text'; let inputType = 'text';
let inputValue = value; let inputValue = value;
let inputStep = null; let inputStep = null;
let mouseButtonHidden = true; let showMouseButton = false;
const events = []; const events = [];
const inputData = {validate, normalize}; const inputData = {validate, normalize};
const node = this._valueInput; const node = this._valueInput;
@ -603,9 +604,9 @@ class ProfileConditionUI {
case 'modifierKeys': case 'modifierKeys':
case 'modifierInputs': case 'modifierInputs':
inputValue = null; inputValue = null;
mouseButtonHidden = (type !== 'modifierInputs'); showMouseButton = (type === 'modifierInputs');
this._kbmInputField = this._parent.parent.createKeyboardMouseInputField(node, this._mouseButton); this._kbmInputField = this._parent.parent.createKeyboardMouseInputField(node, this._mouseButton);
this._kbmInputField.prepare(value, type); this._kbmInputField.prepare(null, this._splitModifiers(value), showMouseButton, false);
events.push(['on', this._kbmInputField, 'change', this._onModifierInputChange.bind(this, inputData), false]); events.push(['on', this._kbmInputField, 'change', this._onModifierInputChange.bind(this, inputData), false]);
break; break;
default: // 'string' default: // 'string'
@ -624,7 +625,7 @@ class ProfileConditionUI {
} else { } else {
node.removeAttribute('step'); node.removeAttribute('step');
} }
this._mouseButtonContainer.hidden = mouseButtonHidden; this._mouseButtonContainer.hidden = !showMouseButton;
for (const args of events) { for (const args of events) {
this._inputEventListeners.addGeneric(...args); this._inputEventListeners.addGeneric(...args);
} }
@ -645,4 +646,12 @@ class ProfileConditionUI {
_removeSelf() { _removeSelf() {
this._parent.removeCondition(this); this._parent.removeCondition(this);
} }
_splitModifiers(modifiersString) {
return modifiersString.split(/[,;\s]+/).map((v) => v.trim().toLowerCase()).filter((v) => v.length > 0);
}
_joinModifiers(modifiersArray) {
return modifiersArray.join(', ');
}
} }

View File

@ -199,8 +199,8 @@ class ScanInputField {
const isPointerTypeSupported = this._isPointerTypeSupported.bind(this); const isPointerTypeSupported = this._isPointerTypeSupported.bind(this);
this._includeInputField = new KeyboardMouseInputField(includeInputNode, includeMouseButton, this._os, isPointerTypeSupported); this._includeInputField = new KeyboardMouseInputField(includeInputNode, includeMouseButton, this._os, isPointerTypeSupported);
this._excludeInputField = new KeyboardMouseInputField(excludeInputNode, excludeMouseButton, this._os, isPointerTypeSupported); this._excludeInputField = new KeyboardMouseInputField(excludeInputNode, excludeMouseButton, this._os, isPointerTypeSupported);
this._includeInputField.prepare(include, 'modifierInputs'); this._includeInputField.prepare(null, this._splitModifiers(include), true, false);
this._excludeInputField.prepare(exclude, 'modifierInputs'); this._excludeInputField.prepare(null, this._splitModifiers(exclude), true, false);
this._eventListeners.on(this._includeInputField, 'change', this._onIncludeValueChange.bind(this)); this._eventListeners.on(this._includeInputField, 'change', this._onIncludeValueChange.bind(this));
this._eventListeners.on(this._excludeInputField, 'change', this._onExcludeValueChange.bind(this)); this._eventListeners.on(this._excludeInputField, 'change', this._onExcludeValueChange.bind(this));
@ -230,12 +230,14 @@ class ScanInputField {
// Private // Private
_onIncludeValueChange({value}) { _onIncludeValueChange({modifiers}) {
this._parent.setProperty(this._index, 'include', value, true); modifiers = this._joinModifiers(modifiers);
this._parent.setProperty(this._index, 'include', modifiers, true);
} }
_onExcludeValueChange({value}) { _onExcludeValueChange({modifiers}) {
this._parent.setProperty(this._index, 'exclude', value, true); modifiers = this._joinModifiers(modifiers);
this._parent.setProperty(this._index, 'exclude', modifiers, true);
} }
_onRemoveClick(e) { _onRemoveClick(e) {
@ -296,4 +298,12 @@ class ScanInputField {
this._node.dataset.showAdvanced = `${showAdvanced}`; this._node.dataset.showAdvanced = `${showAdvanced}`;
this._parent.setProperty(this._index, 'options.showAdvanced', showAdvanced, false); this._parent.setProperty(this._index, 'options.showAdvanced', showAdvanced, false);
} }
_splitModifiers(modifiersString) {
return modifiersString.split(/[,;\s]+/).map((v) => v.trim().toLowerCase()).filter((v) => v.length > 0);
}
_joinModifiers(modifiersArray) {
return modifiersArray.join(', ');
}
} }