Media key support (#294)
* Introduce type for KeystrokeAction * Increment dataModelVersion New property 'type' for KeystrokeAction * Mapping for media keys * Media key selecting support for KeypressTab * refactor: Use more meaningful name (selectedScancodeOption) * Store the keystroke type in key action type instead of a new field
This commit is contained in:
committed by
László Monda
parent
8e823b57b4
commit
efe7e95b3e
@@ -2,7 +2,7 @@
|
||||
<b class="setting-label">Scancode:</b>
|
||||
<select2
|
||||
[data]="scanCodeGroups"
|
||||
[value]="scanCode.toString()"
|
||||
[value]="selectedScancodeOption.id"
|
||||
(valueChanged)="onScancodeChange($event)"
|
||||
[width]="200"
|
||||
[options]="options"
|
||||
@@ -47,4 +47,4 @@
|
||||
<i class="fa fa-info-circle"></i>
|
||||
When a key is configured as layer switcher key, you can't assign other functions to it.
|
||||
To assign a scancode to the key, set the <em>Layer action</em> to <em>None</em>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { KeyAction, KeystrokeAction } from '../../../../config-serializer/config
|
||||
|
||||
import { Tab } from '../tab';
|
||||
import { MapperService } from '../../../../services/mapper.service';
|
||||
import { KeystrokeType } from '../../../../config-serializer/config-items/key-action/keystroke-type';
|
||||
|
||||
@Component({
|
||||
selector: 'keypress-tab',
|
||||
@@ -16,18 +17,18 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
@Input() defaultKeyAction: KeyAction;
|
||||
@Input() longPressEnabled: boolean;
|
||||
|
||||
private leftModifiers: string[];
|
||||
private rightModifiers: string[];
|
||||
leftModifiers: string[];
|
||||
rightModifiers: string[];
|
||||
|
||||
private leftModifierSelects: boolean[];
|
||||
private rightModifierSelects: boolean[];
|
||||
leftModifierSelects: boolean[];
|
||||
rightModifierSelects: boolean[];
|
||||
|
||||
private scanCodeGroups: Array<Select2OptionData>;
|
||||
private longPressGroups: Array<Select2OptionData>;
|
||||
private options: Select2Options;
|
||||
scanCodeGroups: Array<Select2OptionData>;
|
||||
longPressGroups: Array<Select2OptionData>;
|
||||
options: Select2Options;
|
||||
|
||||
private scanCode: number;
|
||||
private selectedLongPressIndex: number;
|
||||
selectedScancodeOption: Select2OptionData;
|
||||
selectedLongPressIndex: number;
|
||||
|
||||
constructor(private mapper: MapperService) {
|
||||
super();
|
||||
@@ -41,7 +42,7 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
this.longPressGroups = require('json-loader!./longPress.json');
|
||||
this.leftModifierSelects = Array(this.leftModifiers.length).fill(false);
|
||||
this.rightModifierSelects = Array(this.rightModifiers.length).fill(false);
|
||||
this.scanCode = 0;
|
||||
this.selectedScancodeOption = this.scanCodeGroups[0];
|
||||
this.selectedLongPressIndex = -1;
|
||||
this.options = {
|
||||
templateResult: this.scanCodeTemplateResult,
|
||||
@@ -70,11 +71,11 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
return (keystrokeAction) ? (keystrokeAction.scancode > 0 || keystrokeAction.modifierMask > 0) : false;
|
||||
}
|
||||
|
||||
onKeysCapture(event: {code: number, left: boolean[], right: boolean[]}) {
|
||||
onKeysCapture(event: { code: number, left: boolean[], right: boolean[] }) {
|
||||
if (event.code) {
|
||||
this.scanCode = event.code;
|
||||
this.selectedScancodeOption = this.findScancodeOptionByScancode(event.code, KeystrokeType.basic);
|
||||
} else {
|
||||
this.scanCode = 0;
|
||||
this.selectedScancodeOption = this.scanCodeGroups[0];
|
||||
}
|
||||
|
||||
this.leftModifierSelects = event.left;
|
||||
@@ -87,8 +88,8 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
return false;
|
||||
}
|
||||
const keystrokeAction: KeystrokeAction = <KeystrokeAction>keyAction;
|
||||
// Restore scancode
|
||||
this.scanCode = keystrokeAction.scancode || 0;
|
||||
// Restore selectedScancodeOption
|
||||
this.selectedScancodeOption = this.findScancodeOptionByScancode(keystrokeAction.scancode || 0, keystrokeAction.type);
|
||||
|
||||
const leftModifiersLength: number = this.leftModifiers.length;
|
||||
|
||||
@@ -112,8 +113,13 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
|
||||
toKeyAction(): KeystrokeAction {
|
||||
const keystrokeAction: KeystrokeAction = new KeystrokeAction();
|
||||
keystrokeAction.scancode = this.scanCode;
|
||||
|
||||
const scTypePair = this.toScancodeTypePair(this.selectedScancodeOption);
|
||||
keystrokeAction.scancode = scTypePair[0];
|
||||
if (scTypePair[1] === 'media') {
|
||||
keystrokeAction.type = KeystrokeType.shortMedia;
|
||||
} else {
|
||||
keystrokeAction.type = KeystrokeType[scTypePair[1]];
|
||||
}
|
||||
keystrokeAction.modifierMask = 0;
|
||||
const modifiers = this.leftModifierSelects.concat(this.rightModifierSelects).map(x => x ? 1 : 0);
|
||||
for (let i = 0; i < modifiers.length; ++i) {
|
||||
@@ -137,10 +143,10 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
if (state.additional && state.additional.explanation) {
|
||||
return jQuery(
|
||||
'<span class="select2-item">'
|
||||
+ '<span>' + state.text + '</span>'
|
||||
+ '<span class="scancode--searchterm"> '
|
||||
+ state.additional.explanation
|
||||
+ '</span>' +
|
||||
+ '<span>' + state.text + '</span>'
|
||||
+ '<span class="scancode--searchterm"> '
|
||||
+ state.additional.explanation
|
||||
+ '</span>' +
|
||||
'</span>'
|
||||
);
|
||||
} else {
|
||||
@@ -155,12 +161,65 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
this.validAction.emit(this.keyActionValid());
|
||||
}
|
||||
|
||||
onLongpressChange(event: {value: string}) {
|
||||
onLongpressChange(event: { value: string }) {
|
||||
this.selectedLongPressIndex = +event.value;
|
||||
}
|
||||
|
||||
onScancodeChange(event: {value: string}) {
|
||||
this.scanCode = +event.value;
|
||||
onScancodeChange(event: { value: string }) {
|
||||
const id: string = event.value;
|
||||
|
||||
// ng2-select2 should provide the selectedOption in an upcoming release
|
||||
// TODO: change this when it has become available
|
||||
this.selectedScancodeOption = this.findScancodeOptionById(id);
|
||||
|
||||
this.validAction.emit(this.keyActionValid());
|
||||
}
|
||||
|
||||
private findScancodeOptionBy(predicate: (option: Select2OptionData) => boolean): Select2OptionData {
|
||||
let selectedOption: Select2OptionData;
|
||||
|
||||
const scanCodeGroups: Select2OptionData[] = [...this.scanCodeGroups];
|
||||
while (scanCodeGroups.length > 0) {
|
||||
const scanCodeGroup = scanCodeGroups.shift();
|
||||
if (predicate(scanCodeGroup)) {
|
||||
selectedOption = scanCodeGroup;
|
||||
break;
|
||||
}
|
||||
scanCodeGroups.push(...scanCodeGroup.children);
|
||||
}
|
||||
return selectedOption;
|
||||
}
|
||||
|
||||
private findScancodeOptionById(id: string): Select2OptionData {
|
||||
return this.findScancodeOptionBy(option => option.id === id);
|
||||
}
|
||||
|
||||
private findScancodeOptionByScancode(scancode: number, type: KeystrokeType): Select2OptionData {
|
||||
const typeToFind: string = type === KeystrokeType.shortMedia || KeystrokeType.longMedia ? 'media' : KeystrokeType[type];
|
||||
return this.findScancodeOptionBy((option: Select2OptionData) => {
|
||||
const additional = option.additional;
|
||||
if (additional && additional.scancode === scancode && additional.type === typeToFind) {
|
||||
return true;
|
||||
} else if (+option.id === scancode) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private toScancodeTypePair(option: Select2OptionData): [number, string] {
|
||||
let scanCode: number;
|
||||
let type: string;
|
||||
if (option.additional) {
|
||||
scanCode = option.additional.scancode ? option.additional.scancode : 0;
|
||||
type = option.additional.type || 'basic';
|
||||
} else {
|
||||
scanCode = +option.id;
|
||||
type = 'basic';
|
||||
}
|
||||
|
||||
return [scanCode, type];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -559,7 +559,11 @@
|
||||
"children": [
|
||||
{
|
||||
"id": "127",
|
||||
"text": "Mute"
|
||||
"text": "Mute",
|
||||
"additional": {
|
||||
"type": "media",
|
||||
"scancode": 226
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "128",
|
||||
@@ -591,4 +595,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -220,7 +220,7 @@ export class SvgKeyboardKeyComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
if (!keyAction.hasActiveModifier() && keyAction.hasScancode()) {
|
||||
const scancode: number = keyAction.scancode;
|
||||
newLabelSource = this.mapper.scanCodeToText(scancode);
|
||||
newLabelSource = this.mapper.scanCodeToText(scancode, keyAction.type);
|
||||
if (this.mapper.hasScancodeIcon(scancode)) {
|
||||
this.labelSource = this.mapper.scanCodeToSvgImagePath(scancode);
|
||||
this.labelType = LabelTypes.SingleIcon;
|
||||
|
||||
@@ -131,7 +131,7 @@ export class SvgKeystrokeKeyComponent implements OnInit, OnChanges {
|
||||
let newLabelSource: string[];
|
||||
if (this.keystrokeAction.hasScancode()) {
|
||||
const scancode: number = this.keystrokeAction.scancode;
|
||||
newLabelSource = this.mapper.scanCodeToText(scancode);
|
||||
newLabelSource = this.mapper.scanCodeToText(scancode, this.keystrokeAction.type);
|
||||
if (newLabelSource) {
|
||||
if (newLabelSource.length === 1) {
|
||||
this.labelSource = newLabelSource[0];
|
||||
|
||||
@@ -245,7 +245,8 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
|
||||
|
||||
if (keystrokeAction.hasScancode()) {
|
||||
let value: string = keystrokeAction.scancode.toString();
|
||||
const scanCodeTexts: string = (this.mapper.scanCodeToText(keystrokeAction.scancode) || []).join(', ');
|
||||
const scanCodeTexts: string = (this.mapper.scanCodeToText(keystrokeAction.scancode, keystrokeAction.type) || [])
|
||||
.join(', ');
|
||||
if (scanCodeTexts.length > 0) {
|
||||
value += ' (' + scanCodeTexts + ')';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user