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:
József Farkas
2017-06-11 12:11:12 +02:00
committed by László Monda
parent 8e823b57b4
commit efe7e95b3e
13 changed files with 724 additions and 388 deletions

View File

@@ -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>

View File

@@ -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];
}
}

View File

@@ -559,7 +559,11 @@
"children": [
{
"id": "127",
"text": "Mute"
"text": "Mute",
"additional": {
"type": "media",
"scancode": 226
}
},
{
"id": "128",
@@ -591,4 +595,4 @@
}
]
}
]
]

View File

@@ -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;

View File

@@ -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];

View File

@@ -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 + ')';
}