feat(ui): macro ui improvement (#473)
* Remove the "Input the text you want to type with this macro action." sentence from the type text macro action. * Move pointer and Scroll enhancement * remove the extra vertical space above the mouse buttons * macro delay enhancement * not allow user select on a few elements * fill the macro, keymap name the all space in the header
This commit is contained in:
committed by
László Monda
parent
bd49e26978
commit
9885439b10
@@ -26,7 +26,7 @@
|
||||
|
||||
"unit-case": "lower",
|
||||
"unit-no-unknown": true,
|
||||
"unit-whitelist": ["px", "%", "deg", "ms", "em", "rem", "vh", "vv", "s"],
|
||||
"unit-whitelist": ["px", "%", "deg", "ms", "em", "rem", "vh", "vv", "s", "ch"],
|
||||
|
||||
"value-list-comma-space-after": "always-single-line",
|
||||
"value-list-comma-space-before": "never",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
type="text"
|
||||
(change)="editKeymapName($event.target.value)"
|
||||
(keyup.enter)="name.blur()"
|
||||
(keyup)="calculateHeaderTextWidth($event.target.value)"
|
||||
/> keymap
|
||||
(<input #abbr cancelable
|
||||
class="keymap__abbrev pane-title__abbrev"
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
HostListener,
|
||||
Input,
|
||||
OnChanges,
|
||||
Output,
|
||||
@@ -16,6 +17,7 @@ import { Store } from '@ngrx/store';
|
||||
|
||||
import { AppState } from '../../../store';
|
||||
import { KeymapActions } from '../../../store/actions';
|
||||
import * as util from '../../../util';
|
||||
|
||||
const DEFAULT_TRASH_TITLE = '<span class="text-nowrap">Delete keymap</span>';
|
||||
|
||||
@@ -50,6 +52,11 @@ export class KeymapHeaderComponent implements OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
windowResize(): void {
|
||||
this.calculateHeaderTextWidth(this.keymap.name);
|
||||
}
|
||||
|
||||
setDefault() {
|
||||
if (!this.keymap.isDefault) {
|
||||
this.store.dispatch(KeymapActions.setDefault(this.keymap.abbreviation));
|
||||
@@ -103,8 +110,16 @@ export class KeymapHeaderComponent implements OnChanges {
|
||||
this.downloadClick.emit();
|
||||
}
|
||||
|
||||
calculateHeaderTextWidth(text): void {
|
||||
const htmlInput = this.keymapName.nativeElement as HTMLInputElement;
|
||||
const maxWidth = htmlInput.parentElement.offsetWidth - 530;
|
||||
const textWidth = util.getContentWidth(window.getComputedStyle(htmlInput), text);
|
||||
this.renderer.setStyle(htmlInput, 'width', Math.min(maxWidth, textWidth) + 'px');
|
||||
}
|
||||
|
||||
private setName(): void {
|
||||
this.renderer.setProperty(this.keymapName.nativeElement, 'value', this.keymap.name);
|
||||
this.calculateHeaderTextWidth(this.keymap.name);
|
||||
}
|
||||
|
||||
private setAbbreviation() {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
a {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
user-select: none;
|
||||
|
||||
&.selected {
|
||||
font-style: italic;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<div class="macro-delay">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h4>Enter delay in seconds</h4>
|
||||
<h4>Delay</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<div class="col-xs-12">
|
||||
<div class="form-group">
|
||||
<input #macroDelayInput
|
||||
type="number"
|
||||
min="0"
|
||||
@@ -13,14 +14,17 @@
|
||||
step="0.1"
|
||||
placeholder="Delay amount"
|
||||
class="form-control"
|
||||
[value]="delay"
|
||||
(change)="setDelay(macroDelayInput.value)">
|
||||
[ngModel]="delay"
|
||||
(ngModelChange)="setDelay(macroDelayInput.value)">
|
||||
<label>seconds</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row macro-delay__presets">
|
||||
<div class="col-xs-12">
|
||||
<h6>Choose a preset</h6>
|
||||
<button *ngFor="let delay of presets" class="btn btn-sm btn-default" (click)="setDelay(delay)">{{delay}}s</button>
|
||||
<button *ngFor="let delay of presets" class="btn btn-sm btn-default" (click)="setDelay(delay)">{{delay}}s
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,3 +14,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
width: 16ch;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,19 @@ export class MacroDelayTabComponent extends MacroBaseComponent implements OnInit
|
||||
@Input() macroAction: DelayMacroAction;
|
||||
@ViewChild('macroDelayInput') input: ElementRef;
|
||||
|
||||
delay: number;
|
||||
presets: number[] = [0.3, 0.5, 0.8, 1, 2, 3, 4, 5];
|
||||
|
||||
get delay(): number {
|
||||
return this._delay;
|
||||
}
|
||||
|
||||
set delay(value: number) {
|
||||
this._delay = value;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
private _delay: number;
|
||||
|
||||
constructor() { super(); }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -33,12 +43,11 @@ export class MacroDelayTabComponent extends MacroBaseComponent implements OnInit
|
||||
this.macroAction = new DelayMacroAction();
|
||||
}
|
||||
this.delay = this.macroAction.delay > 0 ? this.macroAction.delay / 1000 : INITIAL_DELAY;
|
||||
this.validate(); // initial validation as it has defaults
|
||||
}
|
||||
|
||||
setDelay(value: number): void {
|
||||
this.delay = value;
|
||||
this.macroAction.delay = this.delay * 1000;
|
||||
this._delay = value;
|
||||
this.macroAction.delay = this._delay * 1000;
|
||||
this.validate();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,29 +36,55 @@
|
||||
<div class="col-xs-9 macro-mouse__actions" [ngSwitch]="activeTab">
|
||||
<div #tab *ngSwitchCase="TabName.Move">
|
||||
<h4>Move pointer</h4>
|
||||
<p>Use negative values to move down or left from current position.</p>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="move-mouse-x">X</label>
|
||||
<input id="move-mouse-x" type="number" class="form-control" [(ngModel)]="macroAction['x']" (keyup)="validate()"> pixels
|
||||
<label for="move-mouse-x">X:</label>
|
||||
<input id="move-mouse-x"
|
||||
type="number"
|
||||
class="form-control"
|
||||
[(ngModel)]="macroAction['x']"
|
||||
(keyup)="validate()"
|
||||
min="-9999"
|
||||
max="9999"
|
||||
maxlength="4"> pixels
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="move-mouse-y">Y</label>
|
||||
<input id="move-mouse-y" type="number" class="form-control" [(ngModel)]="macroAction['y']" (keyup)="validate()"> pixels
|
||||
<label for="move-mouse-y">Y:</label>
|
||||
<input id="move-mouse-y"
|
||||
type="number"
|
||||
class="form-control"
|
||||
[(ngModel)]="macroAction['y']"
|
||||
(keyup)="validate()"
|
||||
min="-9999"
|
||||
max="9999"
|
||||
maxlength="4"> pixels
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div #tab *ngSwitchCase="TabName.Scroll">
|
||||
<h4>Scroll</h4>
|
||||
<p>Use negative values to move down or left from current position.</p>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label for="scroll-mouse-x">X</label>
|
||||
<input id="scroll-mouse-x" type="number" class="form-control" [(ngModel)]="macroAction['x']" (keyup)="validate()"> pixels
|
||||
<label for="scroll-mouse-x">X:</label>
|
||||
<input id="scroll-mouse-x"
|
||||
type="number"
|
||||
class="form-control"
|
||||
[(ngModel)]="macroAction['x']"
|
||||
(keyup)="validate()"
|
||||
min="-9999"
|
||||
max="9999"
|
||||
maxlength="4"> pixels
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="scroll-mouse-y">Y</label>
|
||||
<input id="scroll-mouse-y" type="number" class="form-control" [(ngModel)]="macroAction['y']" (keyup)="validate()"> pixels
|
||||
<label for="scroll-mouse-y">Y:</label>
|
||||
<input id="scroll-mouse-y"
|
||||
type="number"
|
||||
class="form-control"
|
||||
[(ngModel)]="macroAction['y']"
|
||||
(keyup)="validate()"
|
||||
min="-9999"
|
||||
max="9999"
|
||||
maxlength="4"> pixels
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,11 +92,12 @@
|
||||
<h4 *ngIf="activeTab === TabName.Click">Click mouse button</h4>
|
||||
<h4 *ngIf="activeTab === TabName.Hold">Hold mouse button</h4>
|
||||
<h4 *ngIf="activeTab === TabName.Release">Release mouse button</h4>
|
||||
<div class="btn-group macro-mouse__buttons">
|
||||
<div class="btn-group">
|
||||
<button *ngFor="let buttonLabel of buttonLabels; let buttonIndex = index"
|
||||
class="btn btn-default"
|
||||
[class.btn-primary]="hasButton(buttonIndex)"
|
||||
(click)="setMouseClick(buttonIndex)">{{buttonLabel}}</button>
|
||||
(click)="setMouseClick(buttonIndex)">{{buttonLabel}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
padding-left: 3rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.fa {
|
||||
@@ -38,6 +33,6 @@
|
||||
|
||||
.form-control {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
width: 10ch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ enum TabName {
|
||||
'../../macro-action-editor.component.scss',
|
||||
'./macro-mouse.component.scss'
|
||||
],
|
||||
host: { 'class': 'macro__mouse' }
|
||||
host: {'class': 'macro__mouse'}
|
||||
})
|
||||
export class MacroMouseTabComponent extends MacroBaseComponent implements OnInit {
|
||||
@Input() macroAction: MouseMacroAction;
|
||||
@@ -130,14 +130,14 @@ export class MacroMouseTabComponent extends MacroBaseComponent implements OnInit
|
||||
switch (this.macroAction.constructor) {
|
||||
case MoveMouseMacroAction:
|
||||
case ScrollMouseMacroAction:
|
||||
const { x, y } = this.macroAction as MoveMouseMacroAction;
|
||||
return x !== undefined && x !== null && y !== undefined && y !== null;
|
||||
const {x, y} = this.macroAction as MoveMouseMacroAction;
|
||||
return x !== undefined && x !== null && y !== undefined && y !== null &&
|
||||
(x !== 0 || y !== 0) && x < 10000 && x > -10000 && y < 10000 && y > -10000;
|
||||
case MouseButtonMacroAction:
|
||||
const { mouseButtonsMask } = this.macroAction as MouseButtonMacroAction;
|
||||
const {mouseButtonsMask} = this.macroAction as MouseButtonMacroAction;
|
||||
return !!mouseButtonsMask;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<div>
|
||||
<h4>Type text</h4>
|
||||
<p>Input the text you want to type with this macro action.</p>
|
||||
<textarea #macroTextInput name="macro-text" (change)="onTextChange()"
|
||||
(keyup)="validate()" class="macro__text-input">{{ macroAction?.text }}</textarea>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
type="text"
|
||||
(change)="editMacroName($event.target.value)"
|
||||
(keyup.enter)="macroName.blur()"
|
||||
/>
|
||||
(keyup)="calculateHeaderTextWidth($event.target.value)">
|
||||
<i class="glyphicon glyphicon-trash macro__remove pull-right" title=""
|
||||
data-toggle="tooltip"
|
||||
data-placement="bottom"
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
border-bottom: 2px dotted #999;
|
||||
padding: 0;
|
||||
margin: 0 0.25rem;
|
||||
width: 330px;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:focus {
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
HostListener,
|
||||
Input,
|
||||
OnChanges,
|
||||
Renderer2,
|
||||
@@ -13,7 +14,8 @@ import { Store } from '@ngrx/store';
|
||||
import { Macro } from 'uhk-common';
|
||||
|
||||
import { MacroActions } from '../../../store/actions';
|
||||
import { AppState } from '../../../store/index';
|
||||
import { AppState } from '../../../store';
|
||||
import * as util from '../../../util';
|
||||
|
||||
@Component({
|
||||
selector: 'macro-header',
|
||||
@@ -43,6 +45,11 @@ export class MacroHeaderComponent implements AfterViewInit, OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
windowResize(): void {
|
||||
this.calculateHeaderTextWidth(this.macro.name);
|
||||
}
|
||||
|
||||
removeMacro() {
|
||||
this.store.dispatch(MacroActions.removeMacro(this.macro.id));
|
||||
}
|
||||
@@ -60,12 +67,20 @@ export class MacroHeaderComponent implements AfterViewInit, OnChanges {
|
||||
this.store.dispatch(MacroActions.editMacroName(this.macro.id, name));
|
||||
}
|
||||
|
||||
calculateHeaderTextWidth(text): void {
|
||||
const htmlInput = this.macroName.nativeElement as HTMLInputElement;
|
||||
const maxWidth = htmlInput.parentElement.offsetWidth * 0.8;
|
||||
const textWidth = util.getContentWidth(window.getComputedStyle(htmlInput), text);
|
||||
this.renderer.setStyle(htmlInput, 'width', Math.min(maxWidth, textWidth) + 'px');
|
||||
}
|
||||
|
||||
private setFocusOnName() {
|
||||
this.macroName.nativeElement.select();
|
||||
}
|
||||
|
||||
private setName(): void {
|
||||
this.renderer.setProperty(this.macroName.nativeElement, 'value', this.macro.name);
|
||||
this.calculateHeaderTextWidth(this.macro.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
flex-shrink: 0;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
user-select: none;
|
||||
|
||||
icon {
|
||||
margin: 0 5px;
|
||||
|
||||
17
packages/uhk-web/src/app/util/html-helper.ts
Normal file
17
packages/uhk-web/src/app/util/html-helper.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
let canvas: HTMLCanvasElement;
|
||||
|
||||
export function getContentWidth(style: CSSStyleDeclaration, text: string): number {
|
||||
if (!text) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!canvas) {
|
||||
canvas = document.createElement('canvas');
|
||||
}
|
||||
|
||||
const context = canvas.getContext('2d');
|
||||
context.font = style.font;
|
||||
const metrics = context.measureText(text);
|
||||
|
||||
return metrics.width;
|
||||
}
|
||||
1
packages/uhk-web/src/app/util/index.ts
Normal file
1
packages/uhk-web/src/app/util/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './html-helper';
|
||||
Reference in New Issue
Block a user