feat: allow Layer Switcher secondary roles only on base layer (#790)

This commit is contained in:
Róbert Kiss
2018-09-21 00:20:46 +02:00
committed by László Monda
parent eb421e0681
commit aa243ac7b0
5 changed files with 114 additions and 10 deletions

View File

@@ -1,9 +1,11 @@
import { assertUInt8, assertUInt16 } from '../assert'; import { assertUInt16, assertUInt8 } from '../assert';
import { UhkBuffer } from '../uhk-buffer'; import { UhkBuffer } from '../uhk-buffer';
import { Keymap } from './keymap'; import { Keymap } from './keymap';
import { Macro } from './macro'; import { Macro } from './macro';
import { ModuleConfiguration } from './module-configuration'; import { ModuleConfiguration } from './module-configuration';
import { ConfigSerializer } from '../config-serializer'; import { ConfigSerializer } from '../config-serializer';
import { KeystrokeAction } from './key-action';
import { SecondaryRoleAction } from './secondary-role-action';
export class UserConfiguration { export class UserConfiguration {
@@ -102,7 +104,9 @@ export class UserConfiguration {
return macro; return macro;
}); });
this.keymaps = jsonObject.keymaps.map((keymap: any) => new Keymap().fromJsonObject(keymap, this.macros)); this.keymaps = jsonObject.keymaps.map((keymap: any) => new Keymap().fromJsonObject(keymap, this.macros));
this.clean();
this.recalculateConfigurationLength(); this.recalculateConfigurationLength();
return this; return this;
} }
@@ -138,6 +142,8 @@ export class UserConfiguration {
this.keymaps = buffer.readArray<Keymap>(uhkBuffer => new Keymap().fromBinary(uhkBuffer, this.macros)); this.keymaps = buffer.readArray<Keymap>(uhkBuffer => new Keymap().fromBinary(uhkBuffer, this.macros));
ConfigSerializer.resolveSwitchKeymapActions(this.keymaps); ConfigSerializer.resolveSwitchKeymapActions(this.keymaps);
this.clean();
if (this.userConfigurationLength === 0) { if (this.userConfigurationLength === 0) {
this.recalculateConfigurationLength(); this.recalculateConfigurationLength();
} }
@@ -222,4 +228,30 @@ export class UserConfiguration {
this.deviceName = 'My UHK'; this.deviceName = 'My UHK';
} }
} }
/* Remove not allowed settings/bugs
* 1. Layer Switcher secondary roles allowed only on base layers
*/
private clean(): void {
for (const keymap of this.keymaps) {
for (let layerId = 1; layerId < keymap.layers.length; layerId++) {
const layer = keymap.layers[layerId];
for (const module of layer.modules) {
for (let keyActionId = 0; keyActionId < module.keyActions.length; keyActionId++) {
const keyAction = module.keyActions[keyActionId];
if (!keyAction || !(keyAction instanceof KeystrokeAction)) {
continue;
}
if (keyAction.secondaryRoleAction === SecondaryRoleAction.fn ||
keyAction.secondaryRoleAction === SecondaryRoleAction.mod ||
keyAction.secondaryRoleAction === SecondaryRoleAction.mouse) {
(keyAction as any)._secondaryRoleAction = undefined;
}
}
}
}
}
}
} }

View File

@@ -48,11 +48,13 @@
</div> </div>
<div [ngSwitch]="activeTab"> <div [ngSwitch]="activeTab">
<keypress-tab #tab *ngSwitchCase="tabName.Keypress" class="popover-content pr-10" <keypress-tab #tab *ngSwitchCase="tabName.Keypress" class="popover-content pr-10"
[defaultKeyAction]="defaultKeyAction" [defaultKeyAction]="shadowKeyAction"
[secondaryRoleEnabled]="true" [secondaryRoleEnabled]="true"
[allowRemapOnAllKeymapWarning]="true" [allowRemapOnAllKeymapWarning]="true"
[remapInfo]="remapInfo" [remapInfo]="remapInfo"
[showLayerSwitcherInSecondaryRoles]="currentLayer === 0"
(validAction)="keyActionValid=$event" (validAction)="keyActionValid=$event"
(keyActionChange)="keystrokeActionChange($event)"
></keypress-tab> ></keypress-tab>
<layer-tab #tab *ngSwitchCase="tabName.Layer" class="popover-content" <layer-tab #tab *ngSwitchCase="tabName.Layer" class="popover-content"
[defaultKeyAction]="defaultKeyAction" [defaultKeyAction]="defaultKeyAction"
@@ -87,10 +89,11 @@
</label> </label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label> <label [ngClass]="{ disabled: disableRemapOnAllLayer }">
<input type="checkbox" <input type="checkbox"
name="remapOnAllLayer" name="remapOnAllLayer"
[(ngModel)]="remapInfo.remapOnAllLayer" [(ngModel)]="remapInfo.remapOnAllLayer"
[disabled]="disableRemapOnAllLayer"
(ngModelChange)="remapInfoChange()"> Remap on all layers (ngModelChange)="remapInfoChange()"> Remap on all layers
</label> </label>
</div> </div>

View File

@@ -125,5 +125,10 @@
label { label {
margin-right: 5px; margin-right: 5px;
&.disabled {
cursor: not-allowed;
color: #959595;
}
} }
} }

View File

@@ -1,5 +1,6 @@
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef,
Component, Component,
ElementRef, ElementRef,
EventEmitter, EventEmitter,
@@ -24,6 +25,7 @@ import {
KeystrokeAction, KeystrokeAction,
MouseAction, MouseAction,
PlayMacroAction, PlayMacroAction,
SecondaryRoleAction,
SwitchKeymapAction, SwitchKeymapAction,
SwitchLayerAction SwitchLayerAction
} from 'uhk-common'; } from 'uhk-common';
@@ -104,10 +106,13 @@ export class PopoverComponent implements OnChanges {
topPosition: number = 0; topPosition: number = 0;
leftPosition: number = 0; leftPosition: number = 0;
animationState: string; animationState: string;
shadowKeyAction: KeyAction;
disableRemapOnAllLayer = false;
private readonly currentKeymap$ = new BehaviorSubject<Keymap>(undefined); private readonly currentKeymap$ = new BehaviorSubject<Keymap>(undefined);
constructor(store: Store<AppState>) { constructor(private store: Store<AppState>,
private cdRef: ChangeDetectorRef) {
this.animationState = 'closed'; this.animationState = 'closed';
this.keymaps$ = store.let(getKeymaps()) this.keymaps$ = store.let(getKeymaps())
.combineLatest(this.currentKeymap$) .combineLatest(this.currentKeymap$)
@@ -123,8 +128,10 @@ export class PopoverComponent implements OnChanges {
if (change['defaultKeyAction']) { if (change['defaultKeyAction']) {
let tab: TabName; let tab: TabName;
this.disableRemapOnAllLayer = false;
if (this.defaultKeyAction instanceof KeystrokeAction) { if (this.defaultKeyAction instanceof KeystrokeAction) {
this.keystrokeActionChange(this.defaultKeyAction);
tab = TabName.Keypress; tab = TabName.Keypress;
} else if (this.defaultKeyAction instanceof SwitchLayerAction) { } else if (this.defaultKeyAction instanceof SwitchLayerAction) {
tab = TabName.Layer; tab = TabName.Layer;
@@ -188,6 +195,9 @@ export class PopoverComponent implements OnChanges {
selectTab(tab: TabName): void { selectTab(tab: TabName): void {
this.activeTab = tab; this.activeTab = tab;
if (tab === TabName.Keypress) {
this.keystrokeActionChange(this.defaultKeyAction as KeystrokeAction);
}
} }
onOverlay() { onOverlay() {
@@ -198,6 +208,26 @@ export class PopoverComponent implements OnChanges {
this.selectedTab.remapInfoChanged(this.remapInfo); this.selectedTab.remapInfoChanged(this.remapInfo);
} }
keystrokeActionChange(keystrokeAction: KeystrokeAction): void {
this.shadowKeyAction = keystrokeAction;
const disableRemapOnAllLayer =
keystrokeAction &&
this.currentLayer === 0 &&
(keystrokeAction.secondaryRoleAction === SecondaryRoleAction.fn ||
keystrokeAction.secondaryRoleAction === SecondaryRoleAction.mod ||
keystrokeAction.secondaryRoleAction === SecondaryRoleAction.mouse);
if (this.disableRemapOnAllLayer !== disableRemapOnAllLayer) {
this.disableRemapOnAllLayer = disableRemapOnAllLayer;
if (disableRemapOnAllLayer) {
this.remapInfo.remapOnAllLayer = false;
}
this.cdRef.markForCheck();
}
}
private calculatePosition() { private calculatePosition() {
const offsetLeft: number = this.wrapPosition.left + 265; // 265 is a width of the side menu with a margin const offsetLeft: number = this.wrapPosition.left + 265; // 265 is a width of the side menu with a margin
const popover: HTMLElement = this.popoverHost.nativeElement; const popover: HTMLElement = this.popoverHost.nativeElement;

View File

@@ -1,4 +1,13 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges } from '@angular/core'; import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnChanges,
Output,
SimpleChanges
} from '@angular/core';
import { KeyAction, KeystrokeAction, KeystrokeType, SCANCODES, SECONDARY_ROLES } from 'uhk-common'; import { KeyAction, KeystrokeAction, KeystrokeType, SCANCODES, SECONDARY_ROLES } from 'uhk-common';
import { Tab } from '../tab'; import { Tab } from '../tab';
@@ -8,6 +17,16 @@ import { KeyModifierModel } from '../../../../models/key-modifier-model';
import { mapLeftRigthModifierToKeyActionModifier } from '../../../../util'; import { mapLeftRigthModifierToKeyActionModifier } from '../../../../util';
import { RemapInfo } from '../../../../models/remap-info'; import { RemapInfo } from '../../../../models/remap-info';
export const secondaryRoleFilter = (showLayerSwitchers: boolean) => {
return (data): boolean => {
if (showLayerSwitchers) {
return data;
}
return data.text !== 'Layer switcher';
};
};
@Component({ @Component({
selector: 'keypress-tab', selector: 'keypress-tab',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
@@ -19,12 +38,15 @@ export class KeypressTabComponent extends Tab implements OnChanges {
@Input() secondaryRoleEnabled: boolean; @Input() secondaryRoleEnabled: boolean;
@Input() allowRemapOnAllKeymapWarning: boolean; @Input() allowRemapOnAllKeymapWarning: boolean;
@Input() remapInfo: RemapInfo; @Input() remapInfo: RemapInfo;
@Input() showLayerSwitcherInSecondaryRoles: boolean;
@Output() keyActionChange = new EventEmitter<KeystrokeAction>();
leftModifiers: KeyModifierModel[]; leftModifiers: KeyModifierModel[];
rightModifiers: KeyModifierModel[]; rightModifiers: KeyModifierModel[];
scanCodeGroups: Array<SelectOptionData>; scanCodeGroups: Array<SelectOptionData>;
secondaryRoleGroups: Array<SelectOptionData>; secondaryRoleGroups: Array<SelectOptionData> = [];
selectedScancodeOption: SelectOptionData; selectedScancodeOption: SelectOptionData;
selectedSecondaryRoleIndex: number; selectedSecondaryRoleIndex: number;
@@ -41,14 +63,16 @@ export class KeypressTabComponent extends Tab implements OnChanges {
text: 'None' text: 'None'
}]; }];
this.scanCodeGroups = this.scanCodeGroups.concat(SCANCODES); this.scanCodeGroups = this.scanCodeGroups.concat(SCANCODES);
this.secondaryRoleGroups = SECONDARY_ROLES;
this.selectedScancodeOption = this.scanCodeGroups[0]; this.selectedScancodeOption = this.scanCodeGroups[0];
this.selectedSecondaryRoleIndex = -1; this.selectedSecondaryRoleIndex = -1;
} }
ngOnChanges() { ngOnChanges(changes: SimpleChanges) {
if (changes.showLayerSwitcherInSecondaryRoles) {
this.fillSecondaryRoles();
}
this.fromKeyAction(this.defaultKeyAction); this.fromKeyAction(this.defaultKeyAction);
this.keyActionChanged(); this.keyActionChanged(false);
} }
keyActionValid(keystrokeAction?: KeystrokeAction): boolean { keyActionValid(keystrokeAction?: KeystrokeAction): boolean {
@@ -124,6 +148,7 @@ export class KeypressTabComponent extends Tab implements OnChanges {
onSecondaryRoleChange(id: string) { onSecondaryRoleChange(id: string) {
this.selectedSecondaryRoleIndex = +id; this.selectedSecondaryRoleIndex = +id;
this.keyActionChanged();
} }
onScancodeChange(id: string) { onScancodeChange(id: string) {
@@ -200,10 +225,14 @@ export class KeypressTabComponent extends Tab implements OnChanges {
return [scanCode, type]; return [scanCode, type];
} }
private keyActionChanged(): void { private keyActionChanged(dispatch = true): void {
const keystrokeAction = this.toKeyAction(); const keystrokeAction = this.toKeyAction();
this.validAction.emit(this.keyActionValid(keystrokeAction)); this.validAction.emit(this.keyActionValid(keystrokeAction));
this.calculateRemapOnAllLayerWarningVisibility(keystrokeAction); this.calculateRemapOnAllLayerWarningVisibility(keystrokeAction);
if (dispatch) {
this.keyActionChange.emit(keystrokeAction);
}
} }
private calculateRemapOnAllLayerWarningVisibility(keystrokeAction: KeystrokeAction): void { private calculateRemapOnAllLayerWarningVisibility(keystrokeAction: KeystrokeAction): void {
@@ -214,4 +243,9 @@ export class KeypressTabComponent extends Tab implements OnChanges {
!keystrokeAction.hasScancode() && !keystrokeAction.hasScancode() &&
keystrokeAction.hasOnlyOneActiveModifier(); keystrokeAction.hasOnlyOneActiveModifier();
} }
private fillSecondaryRoles(): void {
this.secondaryRoleGroups = SECONDARY_ROLES
.filter(secondaryRoleFilter(this.showLayerSwitcherInSecondaryRoles));
}
} }