Seperate electron and web target building
This commit is contained in:
committed by
József Farkas
parent
517aed1b1c
commit
983eb72892
7
shared/src/components/popover/tab/index.ts
Normal file
7
shared/src/components/popover/tab/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export * from './tab';
|
||||
export { KeymapTabComponent } from './keymap';
|
||||
export { KeypressTabComponent } from './keypress';
|
||||
export { LayerTabComponent } from './layer';
|
||||
export { MacroTabComponent } from './macro';
|
||||
export { MouseTabComponent } from './mouse';
|
||||
export { NoneTabComponent } from './none';
|
||||
1
shared/src/components/popover/tab/keymap/index.ts
Normal file
1
shared/src/components/popover/tab/keymap/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './keymap-tab.component';
|
||||
@@ -0,0 +1,22 @@
|
||||
<template [ngIf]="keymapOptions.length === 0">
|
||||
<span> No keymaps are available to choose from. Create a keymap first! </span>
|
||||
</template>
|
||||
<template [ngIf]="keymapOptions.length > 0">
|
||||
<div>
|
||||
<b>Switch to keymap:</b>
|
||||
<select2
|
||||
[data]="keymapOptions"
|
||||
[value]="selectedKeymap?.abbreviation || -1"
|
||||
(valueChanged)="onChange($event)"
|
||||
[width]="'100%'"
|
||||
></select2>
|
||||
</div>
|
||||
<div>
|
||||
<div class="empty" *ngIf="!selectedKeymap?.abbreviation">
|
||||
<img src="./images/base-layer--blank.svg">
|
||||
</div>
|
||||
<svg-keyboard *ngIf="selectedKeymap?.abbreviation"
|
||||
[moduleConfig]="selectedKeymap.layers[0].modules">
|
||||
</svg-keyboard>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,43 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> span {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
margin-top: 2px;
|
||||
|
||||
b {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
select2 {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
> div:last-child {
|
||||
margin-top: 10px;
|
||||
|
||||
img {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
|
||||
img {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
|
||||
|
||||
import { Select2OptionData } from 'ng2-select2/ng2-select2';
|
||||
|
||||
import { KeyAction, SwitchKeymapAction } from '../../../../config-serializer/config-items/key-action';
|
||||
import { Keymap } from '../../../../config-serializer/config-items/Keymap';
|
||||
import { Tab } from '../tab';
|
||||
|
||||
@Component({
|
||||
selector: 'keymap-tab',
|
||||
template: require('./keymap-tab.component.html'),
|
||||
styles: [require('./keymap-tab.component.scss')],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class KeymapTabComponent extends Tab implements OnInit, OnChanges {
|
||||
@Input() defaultKeyAction: KeyAction;
|
||||
@Input() keymaps: Keymap[];
|
||||
|
||||
private keymapOptions: Array<Select2OptionData>;
|
||||
private selectedKeymap: Keymap;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.keymapOptions = [];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.keymapOptions = this.keymaps
|
||||
.map((keymap: Keymap): Select2OptionData => {
|
||||
return {
|
||||
id: keymap.abbreviation,
|
||||
text: keymap.name
|
||||
};
|
||||
});
|
||||
if (this.keymaps.length > 0) {
|
||||
this.selectedKeymap = this.keymaps[0];
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.fromKeyAction(this.defaultKeyAction);
|
||||
this.validAction.emit(true);
|
||||
}
|
||||
|
||||
// TODO: change to the correct type when the wrapper has added it.
|
||||
onChange(event: any) {
|
||||
if (event.value === '-1') {
|
||||
this.selectedKeymap = undefined;
|
||||
} else {
|
||||
this.selectedKeymap = this.keymaps.find((keymap: Keymap) => keymap.abbreviation === event.value);
|
||||
}
|
||||
}
|
||||
|
||||
keyActionValid(): boolean {
|
||||
return !!this.selectedKeymap;
|
||||
}
|
||||
|
||||
fromKeyAction(keyAction: KeyAction): boolean {
|
||||
if (!(keyAction instanceof SwitchKeymapAction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const switchKeymapAction: SwitchKeymapAction = <SwitchKeymapAction>keyAction;
|
||||
this.selectedKeymap = this.keymaps
|
||||
.find((keymap: Keymap) => keymap.abbreviation === switchKeymapAction.keymapAbbreviation);
|
||||
}
|
||||
|
||||
toKeyAction(): SwitchKeymapAction {
|
||||
if (!this.keyActionValid()) {
|
||||
throw new Error('KeyAction is not valid. No selected keymap!');
|
||||
}
|
||||
|
||||
const keymapAction = new SwitchKeymapAction();
|
||||
keymapAction.keymapAbbreviation = this.selectedKeymap.abbreviation;
|
||||
return keymapAction;
|
||||
}
|
||||
}
|
||||
1
shared/src/components/popover/tab/keypress/index.ts
Normal file
1
shared/src/components/popover/tab/keypress/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './keypress-tab.component';
|
||||
@@ -0,0 +1,50 @@
|
||||
<div class="scancode-options">
|
||||
<b class="setting-label">Scancode:</b>
|
||||
<select2
|
||||
[data]="scanCodeGroups"
|
||||
[value]="scanCode.toString()"
|
||||
(valueChanged)="onScancodeChange($event)"
|
||||
[width]="200"
|
||||
[options]="options"
|
||||
></select2>
|
||||
<capture-keystroke-button (capture)="onKeysCapture($event)"></capture-keystroke-button>
|
||||
</div>
|
||||
<div class="modifier-options">
|
||||
<b class="setting-label">Modifiers:</b>
|
||||
<div class="btn-toolbar modifiers">
|
||||
<div class="btn-group btn-group-sm modifiers__left">
|
||||
<button type="button" class="btn btn-default"
|
||||
*ngFor="let modifier of leftModifiers; let index = index"
|
||||
[class.btn-primary]="leftModifierSelects[index]"
|
||||
(click)="toggleModifier(false, index)"
|
||||
>
|
||||
{{modifier}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm modifiers__right">
|
||||
<button type="button" class="btn btn-default"
|
||||
*ngFor="let modifier of rightModifiers; let index = index"
|
||||
[class.btn-primary]="rightModifierSelects[index]"
|
||||
(click)="toggleModifier(true, index)"
|
||||
>
|
||||
{{modifier}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="long-press-container" *ngIf="longPressEnabled">
|
||||
<b class="setting-label">Long press action:</b>
|
||||
<select2 #longPressSelect
|
||||
[data]="longPressGroups"
|
||||
[value]="selectedLongPressIndex.toString()"
|
||||
(valueChanged)="onLongpressChange($event)"
|
||||
[width]="140"
|
||||
></select2>
|
||||
<icon name="question-circle" title="This action happens when the key is being held along with another key."></icon>
|
||||
</div>
|
||||
|
||||
<div class="disabled-state--text">
|
||||
<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>
|
||||
@@ -0,0 +1,78 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.scancode-options {
|
||||
margin-bottom: 10px;
|
||||
margin-top: 2px;
|
||||
> b {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.modifier-options {
|
||||
> b {
|
||||
position: relative;
|
||||
top: -9px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.btn-toolbar {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.long-press-container {
|
||||
display: flex;
|
||||
margin-top: 3rem;
|
||||
|
||||
> b {
|
||||
margin-right: 0.6em;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.secondary-role {
|
||||
width: 135px;
|
||||
}
|
||||
|
||||
icon {
|
||||
margin-left: 0.6em;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
&.disabled {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled-state--text {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -4rem;
|
||||
color: #31708f;
|
||||
padding-right: 40px;
|
||||
|
||||
.fa {
|
||||
font-size: 2.6rem;
|
||||
float: left;
|
||||
padding: 1rem 1.5rem 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
.scancode-options,
|
||||
.modifier-options,
|
||||
.long-press-container {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.disabled-state--text {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import { Component, Input, EventEmitter, OnChanges, Output } from '@angular/core';
|
||||
|
||||
import { Select2OptionData, Select2TemplateFunction } from 'ng2-select2';
|
||||
|
||||
import { KeyAction, KeystrokeAction } from '../../../../config-serializer/config-items/key-action';
|
||||
|
||||
import { Tab } from '../tab';
|
||||
import { MapperService } from '../../../../services/mapper.service';
|
||||
|
||||
@Component({
|
||||
selector: 'keypress-tab',
|
||||
template: require('./keypress-tab.component.html'),
|
||||
styles: [require('./keypress-tab.component.scss')]
|
||||
})
|
||||
export class KeypressTabComponent extends Tab implements OnChanges {
|
||||
@Input() defaultKeyAction: KeyAction;
|
||||
@Input() longPressEnabled: boolean;
|
||||
|
||||
private leftModifiers: string[];
|
||||
private rightModifiers: string[];
|
||||
|
||||
private leftModifierSelects: boolean[];
|
||||
private rightModifierSelects: boolean[];
|
||||
|
||||
private scanCodeGroups: Array<Select2OptionData>;
|
||||
private longPressGroups: Array<Select2OptionData>;
|
||||
private options: Select2Options;
|
||||
|
||||
private scanCode: number;
|
||||
private selectedLongPressIndex: number;
|
||||
|
||||
constructor(private mapper: MapperService) {
|
||||
super();
|
||||
this.leftModifiers = ['LShift', 'LCtrl', 'LSuper', 'LAlt'];
|
||||
this.rightModifiers = ['RShift', 'RCtrl', 'RSuper', 'RAlt'];
|
||||
this.scanCodeGroups = [{
|
||||
id: '0',
|
||||
text: 'None'
|
||||
}];
|
||||
this.scanCodeGroups = this.scanCodeGroups.concat(require('json!./scancodes.json'));
|
||||
this.longPressGroups = require('json!./longPress.json');
|
||||
this.leftModifierSelects = Array(this.leftModifiers.length).fill(false);
|
||||
this.rightModifierSelects = Array(this.rightModifiers.length).fill(false);
|
||||
this.scanCode = 0;
|
||||
this.selectedLongPressIndex = -1;
|
||||
this.options = {
|
||||
templateResult: this.scanCodeTemplateResult,
|
||||
matcher: (term: string, text: string, data: Select2OptionData) => {
|
||||
let found = text.toUpperCase().indexOf(term.toUpperCase()) > -1;
|
||||
|
||||
if (!found && data.additional && data.additional.explanation) {
|
||||
found = data.additional.explanation.toUpperCase().indexOf(term.toUpperCase()) > -1;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.fromKeyAction(this.defaultKeyAction);
|
||||
this.validAction.emit(this.keyActionValid());
|
||||
}
|
||||
|
||||
keyActionValid(keystrokeAction?: KeystrokeAction): boolean {
|
||||
if (!keystrokeAction) {
|
||||
keystrokeAction = this.toKeyAction();
|
||||
}
|
||||
|
||||
return (keystrokeAction) ? (keystrokeAction.scancode > 0 || keystrokeAction.modifierMask > 0) : false;
|
||||
}
|
||||
|
||||
onKeysCapture(event: {code: number, left: boolean[], right: boolean[]}) {
|
||||
if (event.code) {
|
||||
this.scanCode = event.code;
|
||||
} else {
|
||||
this.scanCode = 0;
|
||||
}
|
||||
|
||||
this.leftModifierSelects = event.left;
|
||||
this.rightModifierSelects = event.right;
|
||||
this.validAction.emit(this.keyActionValid());
|
||||
}
|
||||
|
||||
fromKeyAction(keyAction: KeyAction): boolean {
|
||||
if (!(keyAction instanceof KeystrokeAction)) {
|
||||
return false;
|
||||
}
|
||||
let keystrokeAction: KeystrokeAction = <KeystrokeAction>keyAction;
|
||||
// Restore scancode
|
||||
this.scanCode = keystrokeAction.scancode || 0;
|
||||
|
||||
let leftModifiersLength: number = this.leftModifiers.length;
|
||||
|
||||
// Restore modifiers
|
||||
for (let i = 0; i < leftModifiersLength; ++i) {
|
||||
this.leftModifierSelects[this.mapper.modifierMapper(i)] = ((keystrokeAction.modifierMask >> i) & 1) === 1;
|
||||
}
|
||||
|
||||
for (let i = leftModifiersLength; i < leftModifiersLength + this.rightModifierSelects.length; ++i) {
|
||||
let index: number = this.mapper.modifierMapper(i) - leftModifiersLength;
|
||||
this.rightModifierSelects[index] = ((keystrokeAction.modifierMask >> i) & 1) === 1;
|
||||
}
|
||||
|
||||
// Restore longPressAction
|
||||
if (keystrokeAction.longPressAction !== undefined) {
|
||||
this.selectedLongPressIndex = this.mapper.modifierMapper(keystrokeAction.longPressAction);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
toKeyAction(): KeystrokeAction {
|
||||
let keystrokeAction: KeystrokeAction = new KeystrokeAction();
|
||||
keystrokeAction.scancode = this.scanCode;
|
||||
|
||||
keystrokeAction.modifierMask = 0;
|
||||
let modifiers = this.leftModifierSelects.concat(this.rightModifierSelects).map(x => x ? 1 : 0);
|
||||
for (let i = 0; i < modifiers.length; ++i) {
|
||||
keystrokeAction.modifierMask |= modifiers[i] << this.mapper.modifierMapper(i);
|
||||
}
|
||||
|
||||
keystrokeAction.longPressAction = this.selectedLongPressIndex === -1
|
||||
? undefined
|
||||
: this.mapper.modifierMapper(this.selectedLongPressIndex);
|
||||
|
||||
if (this.keyActionValid(keystrokeAction)) {
|
||||
return keystrokeAction;
|
||||
}
|
||||
}
|
||||
|
||||
scanCodeTemplateResult: Select2TemplateFunction = (state: Select2OptionData): JQuery | string => {
|
||||
if (!state.id) {
|
||||
return state.text;
|
||||
}
|
||||
|
||||
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>'
|
||||
);
|
||||
} else {
|
||||
return jQuery('<span class="select2-item">' + state.text + '</span>');
|
||||
}
|
||||
}
|
||||
|
||||
toggleModifier(right: boolean, index: number) {
|
||||
let modifierSelects: boolean[] = right ? this.rightModifierSelects : this.leftModifierSelects;
|
||||
modifierSelects[index] = !modifierSelects[index];
|
||||
|
||||
this.validAction.emit(this.keyActionValid());
|
||||
}
|
||||
|
||||
onLongpressChange(event: {value: string}) {
|
||||
this.selectedLongPressIndex = +event.value;
|
||||
}
|
||||
|
||||
onScancodeChange(event: {value: string}) {
|
||||
this.scanCode = +event.value;
|
||||
this.validAction.emit(this.keyActionValid());
|
||||
}
|
||||
}
|
||||
60
shared/src/components/popover/tab/keypress/longPress.json
Normal file
60
shared/src/components/popover/tab/keypress/longPress.json
Normal file
@@ -0,0 +1,60 @@
|
||||
[
|
||||
{
|
||||
"id": "-1",
|
||||
"text": "None"
|
||||
},
|
||||
{
|
||||
"text": "Modifiers",
|
||||
"children": [
|
||||
{
|
||||
"id": "0",
|
||||
"text": "LShift"
|
||||
},
|
||||
{
|
||||
"id": "1",
|
||||
"text": "LCtrl"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"text": "LSuper"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"text": "LAlt"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"text": "RShift"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"text": "RCtrl"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"text": "RSuper"
|
||||
},
|
||||
{
|
||||
"id": "7",
|
||||
"text": "RAlt"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Layer switcher",
|
||||
"children": [
|
||||
{
|
||||
"id": "8",
|
||||
"text": "Mod"
|
||||
},
|
||||
{
|
||||
"id": "9",
|
||||
"text": "Mouse"
|
||||
},
|
||||
{
|
||||
"id": "10",
|
||||
"text": "Fn"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
594
shared/src/components/popover/tab/keypress/scancodes.json
Normal file
594
shared/src/components/popover/tab/keypress/scancodes.json
Normal file
File diff suppressed because it is too large
Load Diff
1
shared/src/components/popover/tab/layer/index.ts
Normal file
1
shared/src/components/popover/tab/layer/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './layer-tab.component';
|
||||
@@ -0,0 +1,20 @@
|
||||
<template [ngIf]="!isNotBase">
|
||||
<select (change)="toggleChanged($event.target.value)">
|
||||
<option *ngFor="let item of toggleData" [value]="item.id" [selected]="toggle === item.id">
|
||||
{{ item.text }}
|
||||
</option>
|
||||
</select>
|
||||
<span>the</span>
|
||||
<select (change)="layerChanged($event.target.value)">
|
||||
<option *ngFor="let item of layerData" [value]="item.id" [selected]="layer === item.id">
|
||||
{{ item.text }}
|
||||
</option>
|
||||
</select>
|
||||
<span [ngSwitch]="toggle">
|
||||
<template ngSwitchCase="true">layer by pressing this key.</template>
|
||||
<template ngSwitchDefault="false">layer by holding this key.</template>
|
||||
</span>
|
||||
</template>
|
||||
<template [ngIf]="isNotBase">
|
||||
<span> Layer switching is only possible from the base layer. </span>
|
||||
</template>
|
||||
@@ -0,0 +1,22 @@
|
||||
:host {
|
||||
display: flex;
|
||||
margin: 0 -5px;
|
||||
|
||||
&.no-base {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
> span,
|
||||
> select {
|
||||
margin: 0 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
background-color: #fff;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
padding: 4px 20px 4px 8px;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import { Component, EventEmitter, HostBinding, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
|
||||
import { KeyAction, LayerName, SwitchLayerAction } from '../../../../config-serializer/config-items/key-action';
|
||||
|
||||
import { Tab } from '../tab';
|
||||
|
||||
@Component({
|
||||
selector: 'layer-tab',
|
||||
template: require('./layer-tab.component.html'),
|
||||
styles: [require('./layer-tab.component.scss')]
|
||||
})
|
||||
export class LayerTabComponent extends Tab implements OnChanges {
|
||||
@Input() defaultKeyAction: KeyAction;
|
||||
@Input() currentLayer: number;
|
||||
|
||||
@HostBinding('class.no-base') isNotBase: boolean;
|
||||
|
||||
toggleData: { id: boolean, text: string }[] = [
|
||||
{
|
||||
id: false,
|
||||
text: 'Activate'
|
||||
},
|
||||
{
|
||||
id: true,
|
||||
text: 'Toggle'
|
||||
}
|
||||
];
|
||||
|
||||
layerData: { id: number, text: string }[] = [
|
||||
{
|
||||
id: 0,
|
||||
text: 'Mod'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
text: 'Fn'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
text: 'Mouse'
|
||||
}
|
||||
];
|
||||
|
||||
private toggle: boolean;
|
||||
private layer: LayerName;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.toggle = false;
|
||||
this.layer = LayerName.mod;
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['defaultKeyAction']) {
|
||||
this.fromKeyAction(this.defaultKeyAction);
|
||||
}
|
||||
|
||||
if (changes['currentLayer']) {
|
||||
this.isNotBase = this.currentLayer > 0;
|
||||
}
|
||||
|
||||
this.validAction.emit(true);
|
||||
}
|
||||
|
||||
keyActionValid(): boolean {
|
||||
return !this.isNotBase;
|
||||
}
|
||||
|
||||
fromKeyAction(keyAction: KeyAction): boolean {
|
||||
if (!(keyAction instanceof SwitchLayerAction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let switchLayerAction: SwitchLayerAction = <SwitchLayerAction>keyAction;
|
||||
this.toggle = switchLayerAction.isLayerToggleable;
|
||||
this.layer = switchLayerAction.layer;
|
||||
return true;
|
||||
}
|
||||
|
||||
toKeyAction(): SwitchLayerAction {
|
||||
let keyAction = new SwitchLayerAction();
|
||||
keyAction.isLayerToggleable = this.toggle;
|
||||
keyAction.layer = this.layer;
|
||||
if (!this.keyActionValid()) {
|
||||
throw new Error('KeyAction is invalid!');
|
||||
}
|
||||
return keyAction;
|
||||
}
|
||||
|
||||
toggleChanged(value: string) {
|
||||
this.toggle = value === 'true';
|
||||
}
|
||||
|
||||
layerChanged(value: number) {
|
||||
this.layer = +value;
|
||||
}
|
||||
}
|
||||
1
shared/src/components/popover/tab/macro/index.ts
Normal file
1
shared/src/components/popover/tab/macro/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './macro-tab.component';
|
||||
@@ -0,0 +1,16 @@
|
||||
<template [ngIf]="macroOptions.length === 0">
|
||||
<span> No macros are available to choose from. Create a macro first! </span>
|
||||
</template>
|
||||
<template [ngIf]="macroOptions.length > 0">
|
||||
<div class="macro-selector">
|
||||
<b> Play macro: </b>
|
||||
<select2 [data]="macroOptions" [value]="macroOptions[selectedMacroIndex].id" (valueChanged)="onChange($event)" [width]="'100%'"></select2>
|
||||
</div>
|
||||
<div class="macro-action-container">
|
||||
<div class="list-group">
|
||||
<macro-item *ngFor="let macroAction of macros[selectedMacroIndex].macroActions"
|
||||
[macroAction]="macroAction" [editable]="false">
|
||||
</macro-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,40 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> span {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.macro-selector {
|
||||
display: flex;
|
||||
margin-top: 2px;
|
||||
|
||||
b {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
select2 {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.macro-action-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 200px;
|
||||
max-height: 300px;
|
||||
margin: 20px 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ddd;
|
||||
|
||||
.list-group {
|
||||
margin-bottom: 0;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core';
|
||||
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
|
||||
import { Select2OptionData } from 'ng2-select2/ng2-select2';
|
||||
|
||||
import { KeyAction, PlayMacroAction } from '../../../../config-serializer/config-items/key-action';
|
||||
import { Macro } from '../../../../config-serializer/config-items/Macro';
|
||||
|
||||
import { Tab } from '../tab';
|
||||
|
||||
import { AppState } from '../../../../store/index';
|
||||
import { getMacroEntities } from '../../../../store/reducers/macro';
|
||||
|
||||
@Component({
|
||||
selector: 'macro-tab',
|
||||
template: require('./macro-tab.component.html'),
|
||||
styles: [require('./macro-tab.component.scss')]
|
||||
})
|
||||
export class MacroTabComponent extends Tab implements OnInit, OnChanges, OnDestroy {
|
||||
@Input() defaultKeyAction: KeyAction;
|
||||
|
||||
private macros: Macro[];
|
||||
private macroOptions: Array<Select2OptionData>;
|
||||
private selectedMacroIndex: number;
|
||||
private subscription: Subscription;
|
||||
|
||||
constructor(private store: Store<AppState>) {
|
||||
super();
|
||||
this.subscription = store.let(getMacroEntities())
|
||||
.subscribe((macros: Macro[]) => this.macros = macros);
|
||||
this.macroOptions = [];
|
||||
this.selectedMacroIndex = 0;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.macroOptions = this.macros.map(function (macro: Macro, index: number): Select2OptionData {
|
||||
return {
|
||||
id: index.toString(),
|
||||
text: macro.name
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.fromKeyAction(this.defaultKeyAction);
|
||||
this.validAction.emit(true);
|
||||
}
|
||||
|
||||
// TODO: change to the correct type when the wrapper has added it.
|
||||
onChange(event: any) {
|
||||
this.selectedMacroIndex = +event.value;
|
||||
}
|
||||
|
||||
keyActionValid(): boolean {
|
||||
return this.selectedMacroIndex >= 0;
|
||||
}
|
||||
|
||||
fromKeyAction(keyAction: KeyAction): boolean {
|
||||
if (!(keyAction instanceof PlayMacroAction)) {
|
||||
return false;
|
||||
}
|
||||
const playMacroAction: PlayMacroAction = <PlayMacroAction>keyAction;
|
||||
this.selectedMacroIndex = this.macros.findIndex(macro => playMacroAction.macroId === macro.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
toKeyAction(): PlayMacroAction {
|
||||
if (!this.keyActionValid()) {
|
||||
throw new Error('KeyAction is not valid. No selected macro!');
|
||||
}
|
||||
|
||||
const keymapAction = new PlayMacroAction();
|
||||
keymapAction.macroId = this.macros[this.selectedMacroIndex].id;
|
||||
return keymapAction;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
1
shared/src/components/popover/tab/mouse/index.ts
Normal file
1
shared/src/components/popover/tab/mouse/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './mouse-tab.component';
|
||||
110
shared/src/components/popover/tab/mouse/mouse-tab.component.html
Normal file
110
shared/src/components/popover/tab/mouse/mouse-tab.component.html
Normal file
@@ -0,0 +1,110 @@
|
||||
<div class="mouse-action col-sm-4">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li *ngFor="let page of pages; let i = index" [class.active]="selectedPageIndex === i" (click)="changePage(i)">
|
||||
<a> {{ page }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details col-sm-8" [ngSwitch]="selectedPageIndex">
|
||||
<div *ngSwitchCase="0" class="mouse__config mouse__config--move text-center">
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.moveUp"
|
||||
(click)="setMouseActionParam(MouseActionParam.moveUp)">
|
||||
<i class="fa fa-arrow-up"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.moveLeft"
|
||||
(click)="setMouseActionParam(MouseActionParam.moveLeft)">
|
||||
<i class="fa fa-arrow-left"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-lg btn-placeholder">
|
||||
<i class="fa fa-square"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.moveRight"
|
||||
(click)="setMouseActionParam(MouseActionParam.moveRight)">
|
||||
<i class="fa fa-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.moveDown"
|
||||
(click)="setMouseActionParam(MouseActionParam.moveDown)">
|
||||
<i class="fa fa-arrow-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="1" class="mouse__config mouse__config--scroll text-center">
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.scrollUp"
|
||||
(click)="setMouseActionParam(MouseActionParam.scrollUp)">
|
||||
<i class="fa fa-angle-double-up"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.scrollLeft"
|
||||
(click)="setMouseActionParam(MouseActionParam.scrollLeft)">
|
||||
<i class="fa fa-angle-double-left"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-lg btn-placeholder">
|
||||
<i class="fa fa-square"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.scrollRight"
|
||||
(click)="setMouseActionParam(MouseActionParam.scrollRight)">
|
||||
<i class="fa fa-angle-double-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button type="button" class="btn btn-default btn-lg"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.scrollDown"
|
||||
(click)="setMouseActionParam(MouseActionParam.scrollDown)">
|
||||
<i class="fa fa-angle-double-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="2" class="mouse__config mouse__config--click">
|
||||
<div class="btn-group col-xs-12" role="group">
|
||||
<button type="button" class="btn btn-default col-xs-4"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.leftClick"
|
||||
(click)="setMouseActionParam(MouseActionParam.leftClick)">Left</button>
|
||||
<button type="button" class="btn btn-default col-xs-4"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.middleClick"
|
||||
(click)="setMouseActionParam(MouseActionParam.middleClick)">Middle</button>
|
||||
<button type="button" class="btn btn-default col-xs-4"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.rightClick"
|
||||
(click)="setMouseActionParam(MouseActionParam.rightClick)">Right</button>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="3" class="mouse__config mouse__config--speed text-center">
|
||||
<div class="help-text--mouse-speed text-left">
|
||||
<p>Press this key along with mouse movement/scrolling to accelerate/decelerate the speed of the action.</p>
|
||||
</div>
|
||||
<div class="btn-group btn-group-lg" role="group">
|
||||
<button class="btn btn-default"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.decelerate"
|
||||
(click)="setMouseActionParam(MouseActionParam.decelerate)"
|
||||
>
|
||||
-
|
||||
<span>Decelerate</span>
|
||||
</button>
|
||||
<button class="btn btn-default"
|
||||
[class.btn-primary]="mouseActionParam === MouseActionParam.accelerate"
|
||||
(click)="setMouseActionParam(MouseActionParam.accelerate)"
|
||||
>
|
||||
+
|
||||
<span>Accelerate</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="help-text--mouse-speed last-help text-left">
|
||||
<p>You can set the multiplier in the <a [routerLink]="['/settings']" title="Settings">settings</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchDefault>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,85 @@
|
||||
@import '../../../../global-styles';
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
|
||||
&.popover-content {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mouse-action {
|
||||
.nav {
|
||||
border-right: 1px solid #ccc;
|
||||
|
||||
li {
|
||||
a {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
|
||||
&.selected {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
a {
|
||||
&.selected {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 0;
|
||||
right: -4rem;
|
||||
border-color: transparent transparent transparent $icon-hover;
|
||||
border-style: solid;
|
||||
border-width: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.help-text--mouse-speed {
|
||||
margin-bottom: 2rem;
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
.btn-placeholder {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mouse__config--speed {
|
||||
.btn-default {
|
||||
font-size: 25px;
|
||||
line-height: 22px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
|
||||
span {
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.help-text--mouse-speed.last-help {
|
||||
margin-bottom: 0;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
100
shared/src/components/popover/tab/mouse/mouse-tab.component.ts
Normal file
100
shared/src/components/popover/tab/mouse/mouse-tab.component.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
||||
|
||||
import { KeyAction, MouseAction, MouseActionParam } from '../../../../config-serializer/config-items/key-action';
|
||||
import { Tab } from '../tab';
|
||||
|
||||
@Component({
|
||||
selector: 'mouse-tab',
|
||||
template: require('./mouse-tab.component.html'),
|
||||
styles: [require('./mouse-tab.component.scss')]
|
||||
})
|
||||
export class MouseTabComponent extends Tab implements OnChanges {
|
||||
@Input() defaultKeyAction: KeyAction;
|
||||
|
||||
private mouseActionParam: MouseActionParam;
|
||||
private selectedPageIndex: number;
|
||||
/* tslint:disable:variable-name: It is an enum type. So it can start with uppercase. */
|
||||
/* tslint:disable:no-unused-variable: It is used in the template. */
|
||||
private MouseActionParam = MouseActionParam;
|
||||
/* tslint:enable:no-unused-variable tslint:enable:variable-name */
|
||||
|
||||
private pages: string[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.selectedPageIndex = 0;
|
||||
this.pages = ['Move', 'Scroll', 'Click', 'Speed'];
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.fromKeyAction(this.defaultKeyAction);
|
||||
this.validAction.emit(this.keyActionValid());
|
||||
}
|
||||
|
||||
keyActionValid(): boolean {
|
||||
return this.mouseActionParam !== undefined;
|
||||
}
|
||||
|
||||
fromKeyAction(keyAction: KeyAction): boolean {
|
||||
if (!(keyAction instanceof MouseAction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mouseAction: MouseAction = <MouseAction>keyAction;
|
||||
this.mouseActionParam = mouseAction.mouseAction;
|
||||
|
||||
if (mouseAction.mouseAction === MouseActionParam.moveUp) {
|
||||
this.selectedPageIndex = 0;
|
||||
}
|
||||
|
||||
switch (mouseAction.mouseAction) {
|
||||
case MouseActionParam.moveDown:
|
||||
case MouseActionParam.moveUp:
|
||||
case MouseActionParam.moveLeft:
|
||||
case MouseActionParam.moveRight:
|
||||
this.selectedPageIndex = 0;
|
||||
break;
|
||||
case MouseActionParam.scrollDown:
|
||||
case MouseActionParam.scrollUp:
|
||||
case MouseActionParam.scrollLeft:
|
||||
case MouseActionParam.scrollRight:
|
||||
this.selectedPageIndex = 1;
|
||||
break;
|
||||
case MouseActionParam.leftClick:
|
||||
case MouseActionParam.middleClick:
|
||||
case MouseActionParam.rightClick:
|
||||
this.selectedPageIndex = 2;
|
||||
break;
|
||||
case MouseActionParam.decelerate:
|
||||
case MouseActionParam.accelerate:
|
||||
this.selectedPageIndex = 3;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
toKeyAction(): MouseAction {
|
||||
let mouseAction: MouseAction = new MouseAction();
|
||||
mouseAction.mouseAction = this.mouseActionParam;
|
||||
return mouseAction;
|
||||
}
|
||||
|
||||
changePage(index: number) {
|
||||
if (index < -1 || index > 3) {
|
||||
console.error(`Invalid index error: ${index}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedPageIndex = index;
|
||||
this.mouseActionParam = undefined;
|
||||
this.validAction.emit(false);
|
||||
}
|
||||
|
||||
setMouseActionParam(mouseActionParam: MouseActionParam) {
|
||||
this.mouseActionParam = mouseActionParam;
|
||||
this.validAction.emit(true);
|
||||
}
|
||||
}
|
||||
1
shared/src/components/popover/tab/none/index.ts
Normal file
1
shared/src/components/popover/tab/none/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './none-tab.component';
|
||||
@@ -0,0 +1 @@
|
||||
This key is unassigned and has no functionality.
|
||||
@@ -0,0 +1,5 @@
|
||||
:host {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 2rem 0;
|
||||
}
|
||||
27
shared/src/components/popover/tab/none/none-tab.component.ts
Normal file
27
shared/src/components/popover/tab/none/none-tab.component.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Component, EventEmitter, OnChanges, Output } from '@angular/core';
|
||||
|
||||
import { Tab } from '../tab';
|
||||
|
||||
@Component({
|
||||
selector: 'none-tab',
|
||||
template: require('./none-tab.component.html'),
|
||||
styles: [require('./none-tab.component.scss')]
|
||||
})
|
||||
export class NoneTabComponent extends Tab implements OnChanges {
|
||||
ngOnChanges(event: any) {
|
||||
this.validAction.emit(true);
|
||||
}
|
||||
|
||||
keyActionValid(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
fromKeyAction(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
toKeyAction(): undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
11
shared/src/components/popover/tab/tab.ts
Normal file
11
shared/src/components/popover/tab/tab.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { EventEmitter, Output } from '@angular/core';
|
||||
|
||||
import { KeyAction } from '../../../config-serializer/config-items/key-action';
|
||||
|
||||
export abstract class Tab {
|
||||
@Output() validAction = new EventEmitter<boolean>();
|
||||
|
||||
abstract keyActionValid(): boolean;
|
||||
abstract fromKeyAction(keyAction: KeyAction): boolean;
|
||||
abstract toKeyAction(): KeyAction;
|
||||
}
|
||||
Reference in New Issue
Block a user