diff --git a/.gitignore b/.gitignore
index 59218d55..a319be88 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@ npm-debug.log
dist
.idea
*.iml
+*.sublime-project
+*.sublime-workspace
diff --git a/package.json b/package.json
index 4e076518..4d31b0dd 100644
--- a/package.json
+++ b/package.json
@@ -36,16 +36,19 @@
"@angular/common": "2.0.0-rc.6",
"@angular/compiler": "2.0.0-rc.6",
"@angular/core": "2.0.0-rc.6",
+ "@angular/forms": "2.0.0-rc.6",
"@angular/platform-browser": "2.0.0-rc.6",
"@angular/platform-browser-dynamic": "2.0.0-rc.6",
"@angular/router": "3.0.0-rc.2",
"bootstrap": "^3.3.7",
"browser-stdout": "^1.3.0",
"core-js": "2.4.1",
+ "dragula": "^3.7.1",
"font-awesome": "^4.6.3",
"handlebars": "^4.0.5",
"jquery": "3.1.0",
"json-loader": "^0.5.4",
+ "ng2-dragula": "^1.2.0",
"ng2-select2": "0.4.2",
"rxjs": "5.0.0-beta.11",
"select2": "^4.0.3",
diff --git a/src/app.module.ts b/src/app.module.ts
index cc5004d9..6022dd55 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -1,14 +1,24 @@
import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
+import { DragulaModule } from 'ng2-dragula/ng2-dragula';
import { Select2Component } from 'ng2-select2/ng2-select2';
-import { MainAppComponent, appRoutingProviders, routing } from './main-app';
+import { ContenteditableDirective } from './directives/contenteditable';
import { KeymapAddComponent, KeymapComponent } from './components/keymap';
import { LayersComponent } from './components/layers';
import { LegacyLoaderComponent } from './components/legacy-loader';
-import { MacroComponent } from './components/macro';
+import {
+ MacroActionEditorComponent,
+ MacroComponent,
+ MacroDelayTabComponent,
+ MacroItemComponent,
+ MacroKeyTabComponent,
+ MacroMouseTabComponent,
+ MacroTextTabComponent
+} from './components/macro';
import { NotificationComponent } from './components/notification';
import { PopoverComponent } from './components/popover';
import {
@@ -19,7 +29,6 @@ import {
MouseTabComponent,
NoneTabComponent
} from './components/popover/tab';
-import { MacroItemComponent } from './components/popover/tab/macro';
import { CaptureKeystrokeButtonComponent } from './components/popover/widgets/capture-keystroke';
import { IconComponent } from './components/popover/widgets/icon';
import { SideMenuComponent } from './components/side-menu';
@@ -36,17 +45,17 @@ import {
} from './components/svg/keys';
import { SvgModuleComponent } from './components/svg/module';
import { SvgKeyboardWrapComponent } from './components/svg/wrap';
+import { MainAppComponent, appRoutingProviders, routing } from './main-app';
import { DataProviderService } from './services/data-provider.service';
import { MapperService } from './services/mapper.service';
-import {UhkConfigurationService} from './services/uhk-configuration.service';
+import { UhkConfigurationService } from './services/uhk-configuration.service';
@NgModule({
declarations: [
Select2Component,
MainAppComponent,
KeymapComponent,
- MacroComponent,
LegacyLoaderComponent,
NotificationComponent,
SvgIconTextKeyComponent,
@@ -73,10 +82,19 @@ import {UhkConfigurationService} from './services/uhk-configuration.service';
NoneTabComponent,
CaptureKeystrokeButtonComponent,
IconComponent,
- MacroItemComponent
+ MacroComponent,
+ MacroItemComponent,
+ MacroActionEditorComponent,
+ MacroDelayTabComponent,
+ MacroKeyTabComponent,
+ MacroMouseTabComponent,
+ MacroTextTabComponent,
+ ContenteditableDirective
],
imports: [
BrowserModule,
+ FormsModule,
+ DragulaModule,
routing
],
providers: [
diff --git a/src/components/macro/index.ts b/src/components/macro/index.ts
index 5e1543e6..1bf72a94 100644
--- a/src/components/macro/index.ts
+++ b/src/components/macro/index.ts
@@ -1,2 +1,5 @@
export * from './macro.component';
export * from './macro.routes';
+export * from './macro-item';
+export * from './macro-action-editor';
+export * from './macro-action-editor/tab';
diff --git a/src/components/macro/macro-action-editor/index.ts b/src/components/macro/macro-action-editor/index.ts
new file mode 100644
index 00000000..a236a40f
--- /dev/null
+++ b/src/components/macro/macro-action-editor/index.ts
@@ -0,0 +1 @@
+export { MacroActionEditorComponent } from './macro-action-editor.component';
diff --git a/src/components/macro/macro-action-editor/macro-action-editor.component.html b/src/components/macro/macro-action-editor/macro-action-editor.component.html
new file mode 100644
index 00000000..2d9428bc
--- /dev/null
+++ b/src/components/macro/macro-action-editor/macro-action-editor.component.html
@@ -0,0 +1,46 @@
+
\ No newline at end of file
diff --git a/src/components/macro/macro-action-editor/macro-action-editor.component.scss b/src/components/macro/macro-action-editor/macro-action-editor.component.scss
new file mode 100644
index 00000000..cc7983a1
--- /dev/null
+++ b/src/components/macro/macro-action-editor/macro-action-editor.component.scss
@@ -0,0 +1,80 @@
+.action--editor {
+ padding-top: 0;
+ padding-bottom: 0;
+ border-radius: 0;
+ border: 0;
+}
+
+.nav {
+ padding-bottom: 1rem;
+
+ li {
+ a {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+
+ &.selected {
+ font-style: italic;
+ }
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ &.active {
+ z-index: 2;
+
+ a {
+ &.selected {
+ font-style: normal;
+ }
+
+ &:after {
+ content: '';
+ display: block;
+ position: absolute;
+ width: 0;
+ height: 0;
+ top: 0;
+ right: -4rem;
+ border-color: transparent transparent transparent #337ab7;
+ border-style: solid;
+ border-width: 2rem;
+ }
+ }
+ }
+ }
+}
+
+.editor {
+ &__tabs,
+ &__tab-links {
+ padding-top: 1rem;
+ }
+
+ &__tabs {
+ border-left: 1px solid #ddd;
+ margin-left: -1.6rem;
+ padding-left: 3rem;
+ }
+
+ &__actions {
+ float: right;
+
+ &-container {
+ background: #f5f5f5;
+ border-top: 1px solid #ddd;
+ padding: 1rem 1.5rem;
+ }
+ }
+}
+
+.flex-button-wrapper {
+ display: flex;
+ flex-direction: row-reverse;
+}
+
+.flex-button {
+ align-self: flex-end;
+}
diff --git a/src/components/macro/macro-action-editor/macro-action-editor.component.ts b/src/components/macro/macro-action-editor/macro-action-editor.component.ts
new file mode 100644
index 00000000..b35d6443
--- /dev/null
+++ b/src/components/macro/macro-action-editor/macro-action-editor.component.ts
@@ -0,0 +1,107 @@
+import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+
+import {
+ EditableMacroAction,
+ MacroAction,
+ TextMacroAction,
+ macroActionType
+} from '../../../config-serializer/config-items/macro-action';
+import { MacroKeyTabComponent } from './tab/macro-key';
+
+enum TabName {
+ Keypress,
+ Text,
+ Mouse,
+ Delay
+};
+
+@Component({
+ selector: 'macro-action-editor',
+ template: require('./macro-action-editor.component.html'),
+ styles: [require('./macro-action-editor.component.scss')],
+ host: { 'class': 'macro-action-editor' }
+})
+export class MacroActionEditorComponent implements OnInit {
+ @Input() macroAction: MacroAction;
+
+ @Output() save = new EventEmitter();
+ @Output() cancel = new EventEmitter();
+
+ @ViewChild('tab') selectedTab: any;
+
+ private editableMacroAction: EditableMacroAction;
+ private activeTab: TabName;
+ /* 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 TabName = TabName;
+ /* tslint:enable:no-unused-variable */
+ /* tslint:enable:variable-name */
+
+ ngOnInit() {
+ let macroAction: MacroAction = this.macroAction ? this.macroAction : new TextMacroAction();
+ this.editableMacroAction = new EditableMacroAction(macroAction.toJsObject());
+ let tab: TabName = this.getTabName(this.editableMacroAction);
+ this.activeTab = tab;
+ }
+
+ onCancelClick(): void {
+ this.cancel.emit();
+ }
+
+ onSaveClick(): void {
+ try {
+ const action = this.editableMacroAction;
+ if (action.isKeyAction()) {
+ // Could updating the saved keys be done in a better way?
+ const tab = this.selectedTab as MacroKeyTabComponent;
+ action.fromKeyAction(tab.getKeyAction());
+ }
+ this.save.emit(action.toClass());
+ } catch (e) {
+ // TODO: show error dialog
+ console.error(e);
+ }
+ }
+
+ selectTab(tab: TabName): void {
+ this.activeTab = tab;
+ this.editableMacroAction.macroActionType = this.getTabMacroActionType(tab);
+ }
+
+ getTabName(action: EditableMacroAction): TabName {
+ switch (action.macroActionType) {
+ // Delay action
+ case macroActionType.DelayMacroAction:
+ return TabName.Delay;
+ // Text action
+ case macroActionType.TextMacroAction:
+ return TabName.Text;
+ // Keypress actions
+ case macroActionType.KeyMacroAction:
+ return TabName.Keypress;
+ // Mouse actions
+ case macroActionType.MouseButtonMacroAction:
+ case macroActionType.MoveMouseMacroAction:
+ case macroActionType.ScrollMouseMacroAction:
+ return TabName.Mouse;
+ default:
+ return TabName.Keypress;
+ }
+ }
+
+ getTabMacroActionType(tab: TabName): string {
+ switch (tab) {
+ case TabName.Delay:
+ return macroActionType.DelayMacroAction;
+ case TabName.Keypress:
+ return macroActionType.KeyMacroAction;
+ case TabName.Mouse:
+ return macroActionType.MouseButtonMacroAction;
+ case TabName.Text:
+ return macroActionType.TextMacroAction;
+ default:
+ throw new Error('Could not get macro action type');
+ }
+ }
+
+}
diff --git a/src/components/macro/macro-action-editor/tab/index.ts b/src/components/macro/macro-action-editor/tab/index.ts
new file mode 100644
index 00000000..1a9cd2b1
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/index.ts
@@ -0,0 +1,4 @@
+export { MacroDelayTabComponent } from './macro-delay';
+export { MacroKeyTabComponent } from './macro-key';
+export { MacroMouseTabComponent } from './macro-mouse';
+export { MacroTextTabComponent } from './macro-text';
diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/index.ts b/src/components/macro/macro-action-editor/tab/macro-delay/index.ts
new file mode 100644
index 00000000..39690db4
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-delay/index.ts
@@ -0,0 +1 @@
+export { MacroDelayTabComponent } from './macro-delay.component';
diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.html b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.html
new file mode 100644
index 00000000..3b45d463
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.html
@@ -0,0 +1,26 @@
+
+
+
+
Enter delay in seconds
+
+
+
+
+
+
Choose a preset
+ {{delay}}s
+
+
+
diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.scss b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.scss
new file mode 100644
index 00000000..91c61376
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.scss
@@ -0,0 +1,16 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ position: relative;
+}
+
+.macro-delay {
+ &__presets {
+ margin-top: 1rem;
+
+ button {
+ margin-right: 0.25rem;
+ margin-bottom: 0.25rem;
+ }
+ }
+}
diff --git a/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.ts b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.ts
new file mode 100644
index 00000000..f43385b1
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-delay/macro-delay.component.ts
@@ -0,0 +1,35 @@
+import { AfterViewInit, Component, ElementRef, Input, OnInit, Renderer, ViewChild } from '@angular/core';
+
+import { EditableMacroAction } from '../../../../../config-serializer/config-items/macro-action';
+
+const INITIAL_DELAY = 0.5; // In seconds
+
+@Component({
+ selector: 'macro-delay-tab',
+ template: require('./macro-delay.component.html'),
+ styles: [require('./macro-delay.component.scss')],
+ host: { 'class': 'macro__delay' }
+})
+export class MacroDelayTabComponent implements AfterViewInit, OnInit {
+ @Input() macroAction: EditableMacroAction;
+ @ViewChild('macroDelayInput') input: ElementRef;
+ private delay: number;
+ /* tslint:disable:no-unused-variable: It is used in the template. */
+ private presets: number[] = [0.3, 0.5, 0.8, 1, 2, 3, 4, 5];
+ /* tslint:enable:no-unused-variable */
+
+ constructor(private renderer: Renderer) { }
+
+ ngOnInit() {
+ this.delay = this.macroAction.delay > 0 ? this.macroAction.delay / 1000 : INITIAL_DELAY;
+ }
+
+ ngAfterViewInit() {
+ this.renderer.invokeElementMethod(this.input.nativeElement, 'focus');
+ }
+
+ setDelay(value: number): void {
+ this.delay = value;
+ this.macroAction.delay = this.delay * 1000;
+ }
+}
diff --git a/src/components/macro/macro-action-editor/tab/macro-key/index.ts b/src/components/macro/macro-action-editor/tab/macro-key/index.ts
new file mode 100644
index 00000000..f9fe969b
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-key/index.ts
@@ -0,0 +1 @@
+export { MacroKeyTabComponent } from './macro-key.component';
diff --git a/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.html b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.html
new file mode 100644
index 00000000..9437ceb0
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.html
@@ -0,0 +1,32 @@
+
+
+
+
+
Press key
+ Hold key
+ Release key
+
+
+
+
\ No newline at end of file
diff --git a/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.scss b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.scss
new file mode 100644
index 00000000..1929f3e8
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.scss
@@ -0,0 +1,25 @@
+.macro-key {
+ &__container {
+ padding: 0;
+ }
+
+ &__types {
+ margin-left: 0;
+ padding: 0 0 1rem;
+ }
+
+ &__action {
+ &-container {
+ margin-top: -1rem;
+ padding-top: 1rem;
+ border-left: 1px solid #ddd;
+ }
+
+ padding-left: 3rem;
+ padding-bottom: 1rem;
+ }
+}
+
+.fa {
+ min-width: 14px;
+}
diff --git a/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.ts b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.ts
new file mode 100644
index 00000000..1e3f0921
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-key/macro-key.component.ts
@@ -0,0 +1,74 @@
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
+
+import { KeyAction } from '../../../../../config-serializer/config-items/key-action';
+import { EditableMacroAction, MacroSubAction } from '../../../../../config-serializer/config-items/macro-action';
+import { KeypressTabComponent } from '../../../../popover/tab';
+import { Tab } from '../../../../popover/tab';
+
+enum TabName {
+ Keypress,
+ Hold,
+ Release
+}
+
+@Component({
+ selector: 'macro-key-tab',
+ template: require('./macro-key.component.html'),
+ styles: [
+ require('../../macro-action-editor.component.scss'),
+ require('./macro-key.component.scss')
+ ],
+ host: { 'class': 'macro__mouse' }
+})
+export class MacroKeyTabComponent implements OnInit {
+ @Input() macroAction: EditableMacroAction;
+ @ViewChild('tab') selectedTab: Tab;
+ @ViewChild('keypressTab') keypressTab: KeypressTabComponent;
+
+ private defaultKeyAction: KeyAction;
+
+ private activeTab: TabName;
+ /* 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 TabName = TabName;
+ /* tslint:enable:no-unused-variable */
+ /* tslint:enable:variable-name */
+
+ ngOnInit() {
+ this.defaultKeyAction = this.macroAction.toKeystrokeAction();
+ this.selectTab(this.getTabName(this.macroAction));
+ }
+
+ selectTab(tab: TabName): void {
+ this.activeTab = tab;
+ this.macroAction.action = this.getActionType(tab);
+ }
+
+ getTabName(action: EditableMacroAction): TabName {
+ if (!action.action || action.isOnlyPressAction()) {
+ return TabName.Keypress;
+ } else if (action.isOnlyHoldAction()) {
+ return TabName.Hold;
+ } else if (action.isOnlyReleaseAction()) {
+ return TabName.Release;
+ }
+ }
+
+ getActionType(tab: TabName): MacroSubAction {
+ switch (tab) {
+ case TabName.Keypress:
+ return MacroSubAction.press;
+ case TabName.Hold:
+ return MacroSubAction.hold;
+ case TabName.Release:
+ return MacroSubAction.release;
+ default:
+ throw new Error('Invalid tab type');
+ }
+ }
+
+ getKeyAction(): KeyAction {
+ return this.keypressTab.toKeyAction();
+ }
+
+}
diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/index.ts b/src/components/macro/macro-action-editor/tab/macro-mouse/index.ts
new file mode 100644
index 00000000..039a889d
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-mouse/index.ts
@@ -0,0 +1 @@
+export { MacroMouseTabComponent } from './macro-mouse.component';
diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.html b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.html
new file mode 100644
index 00000000..c5568cbd
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.html
@@ -0,0 +1,77 @@
+
+
+
+
+
Move pointer
+
Use negative values to move down or left from current position.
+
+
+
+
Scroll
+
Use negative values to move down or left from current position.
+
+
+
+
Click mouse button
+
Hold mouse button
+
Release mouse button
+
+ {{buttonLabel}}
+
+
+
+
\ No newline at end of file
diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.scss b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.scss
new file mode 100644
index 00000000..50596da0
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.scss
@@ -0,0 +1,43 @@
+.macro-mouse {
+ &__container {
+ padding: 0;
+ }
+
+ &__types {
+ border-right: 1px solid #ddd;
+ border-left: 0;
+ margin-top: -1rem;
+ margin-left: 0;
+ padding: 1rem 0;
+ }
+
+ &__actions {
+ padding-left: 3rem;
+ padding-bottom: 1rem;
+ }
+
+ &__buttons {
+ margin-top: 3rem;
+ margin-bottom: 1rem;
+ }
+}
+
+.fa {
+ min-width: 14px;
+}
+
+.form-horizontal {
+ .form-group {
+ margin: 0 0 0.5rem;
+ }
+
+ label {
+ display: inline-block;
+ margin-right: 0.5rem;
+ }
+
+ .form-control {
+ display: inline-block;
+ width: 60%;
+ }
+}
diff --git a/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.ts b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.ts
new file mode 100644
index 00000000..a0b3f468
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-mouse/macro-mouse.component.ts
@@ -0,0 +1,107 @@
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
+
+import { EditableMacroAction, MacroSubAction, macroActionType } from '../../../../../config-serializer/config-items/macro-action';
+import { Tab } from '../../../../popover/tab';
+
+enum TabName {
+ Move,
+ Scroll,
+ Click,
+ Hold,
+ Release
+}
+
+@Component({
+ selector: 'macro-mouse-tab',
+ template: require('./macro-mouse.component.html'),
+ styles: [
+ require('../../macro-action-editor.component.scss'),
+ require('./macro-mouse.component.scss')
+ ],
+ host: { 'class': 'macro__mouse' }
+})
+export class MacroMouseTabComponent implements OnInit {
+ @Input() macroAction: EditableMacroAction;
+ @ViewChild('tab') selectedTab: Tab;
+
+ private activeTab: TabName;
+ private buttonLabels: string[];
+ private selectedButtons: boolean[];
+ /* 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 TabName = TabName;
+ /* tslint:enable:no-unused-variable */
+ /* tslint:enable:variable-name */
+
+ constructor() {
+ this.buttonLabels = ['Left', 'Middle', 'Right'];
+ this.selectedButtons = Array(this.buttonLabels.length).fill(false);
+ }
+
+ ngOnInit() {
+ const tabName = this.getTabName(this.macroAction);
+ this.selectTab(tabName);
+ const buttonActions = [TabName.Click, TabName.Hold, TabName.Release];
+ if (buttonActions.includes(this.activeTab)) {
+ this.selectedButtons = this.macroAction.getMouseButtons();
+ }
+ }
+
+ selectTab(tab: TabName): void {
+ this.activeTab = tab;
+ this.macroAction.macroActionType = this.getMacroActionType(tab);
+ if (this.macroAction.macroActionType === macroActionType.MouseButtonMacroAction) {
+ this.macroAction.action = this.getAction(tab);
+ }
+ }
+
+ setMouseClick(index: number): void {
+ this.selectedButtons[index] = !this.selectedButtons[index];
+ this.macroAction.setMouseButtons(this.selectedButtons);
+ }
+
+ hasButton(index: number): boolean {
+ return this.selectedButtons[index];
+ }
+
+ getAction(tab: TabName): MacroSubAction {
+ switch (tab) {
+ case TabName.Click:
+ return MacroSubAction.press;
+ case TabName.Hold:
+ return MacroSubAction.hold;
+ case TabName.Release:
+ return MacroSubAction.release;
+ default:
+ throw new Error('Invalid tab name');
+ }
+ }
+
+ getTabName(action: EditableMacroAction): TabName {
+ if (action.macroActionType === macroActionType.MouseButtonMacroAction) {
+ if (!action.action || action.isOnlyPressAction()) {
+ return TabName.Click;
+ } else if (action.isOnlyPressAction()) {
+ return TabName.Hold;
+ } else if (action.isOnlyReleaseAction()) {
+ return TabName.Release;
+ }
+ } else if (action.macroActionType === macroActionType.MoveMouseMacroAction) {
+ return TabName.Move;
+ } else if (action.macroActionType === macroActionType.ScrollMouseMacroAction) {
+ return TabName.Scroll;
+ }
+ return TabName.Move;
+ }
+
+ getMacroActionType(tab: TabName): string {
+ if (tab === TabName.Click || tab === TabName.Hold || tab === TabName.Release) {
+ return macroActionType.MouseButtonMacroAction;
+ } else if (tab === TabName.Move) {
+ return macroActionType.MoveMouseMacroAction;
+ } else if (tab === TabName.Scroll) {
+ return macroActionType.ScrollMouseMacroAction;
+ }
+ }
+
+}
diff --git a/src/components/macro/macro-action-editor/tab/macro-text/index.ts b/src/components/macro/macro-action-editor/tab/macro-text/index.ts
new file mode 100644
index 00000000..913e5171
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-text/index.ts
@@ -0,0 +1 @@
+export { MacroTextTabComponent } from './macro-text.component';
diff --git a/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.html b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.html
new file mode 100644
index 00000000..ab8590ad
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.html
@@ -0,0 +1,5 @@
+
+
Type text
+
Input the text you want to type with this macro action.
+
+
\ No newline at end of file
diff --git a/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.scss b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.scss
new file mode 100644
index 00000000..b991040a
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.scss
@@ -0,0 +1,11 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ position: relative;
+}
+
+.macro__text-input {
+ width: 100%;
+ min-height: 10rem;
+ margin-bottom: 1rem;
+}
diff --git a/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.ts b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.ts
new file mode 100644
index 00000000..11d3a592
--- /dev/null
+++ b/src/components/macro/macro-action-editor/tab/macro-text/macro-text.component.ts
@@ -0,0 +1,28 @@
+import {
+ AfterViewInit,
+ Component,
+ ElementRef,
+ Input,
+ Renderer,
+ ViewChild
+} from '@angular/core';
+
+import { EditableMacroAction } from '../../../../../config-serializer/config-items/macro-action';
+
+@Component({
+ selector: 'macro-text-tab',
+ template: require('./macro-text.component.html'),
+ styles: [require('./macro-text.component.scss')],
+ host: { 'class': 'macro__text' }
+})
+export class MacroTextTabComponent implements AfterViewInit {
+ @Input() macroAction: EditableMacroAction;
+ @ViewChild('macroTextInput') input: ElementRef;
+
+ constructor(private renderer: Renderer) {}
+
+ ngAfterViewInit() {
+ this.renderer.invokeElementMethod(this.input.nativeElement, 'focus');
+ }
+
+}
diff --git a/src/components/macro/macro-item/index.ts b/src/components/macro/macro-item/index.ts
new file mode 100644
index 00000000..f9155da6
--- /dev/null
+++ b/src/components/macro/macro-item/index.ts
@@ -0,0 +1 @@
+export { MacroItemComponent } from './macro-item.component';
diff --git a/src/components/macro/macro-item/macro-item.component.html b/src/components/macro/macro-item/macro-item.component.html
new file mode 100644
index 00000000..b790ee61
--- /dev/null
+++ b/src/components/macro/macro-item/macro-item.component.html
@@ -0,0 +1,15 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/components/macro/macro-item/macro-item.component.scss b/src/components/macro/macro-item/macro-item.component.scss
new file mode 100644
index 00000000..a71b434e
--- /dev/null
+++ b/src/components/macro/macro-item/macro-item.component.scss
@@ -0,0 +1,53 @@
+:host {
+ &.macro-item:first-of-type {
+ .list-group-item {
+ border-radius: 4px 4px 0 0;
+ }
+ }
+
+ &.macro-item:last-of-type {
+ .list-group-item {
+ border-bottom: 0;
+ }
+ }
+
+ .action {
+ &--item {
+ display: flex;
+ flex-shrink: 0;
+ border: 0;
+ border-bottom: 1px solid #ddd;
+
+ icon {
+ margin: 0 5px;
+ }
+
+ > div {
+ display: flex;
+ flex: 1;
+ }
+
+ &:first-child {
+ border-radius: 0;
+ }
+
+ &.is-editing {
+ background: #f5f5f5;
+ }
+ }
+
+ &--movable {
+ &:hover {
+ cursor: move;
+ }
+ }
+ }
+
+ .macro-action-editor__container {
+ padding-top: 0;
+ padding-bottom: 0;
+ border-radius: 0;
+ border-left: 0;
+ border-right: 0;
+ }
+}
diff --git a/src/components/macro/macro-item/macro-item.component.ts b/src/components/macro/macro-item/macro-item.component.ts
new file mode 100644
index 00000000..c559ba61
--- /dev/null
+++ b/src/components/macro/macro-item/macro-item.component.ts
@@ -0,0 +1,195 @@
+import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
+
+import { KeyModifiers } from '../../../config-serializer/config-items/KeyModifiers';
+import {
+ DelayMacroAction,
+ KeyMacroAction,
+ MacroAction,
+ MouseButtonMacroAction,
+ MoveMouseMacroAction,
+ ScrollMouseMacroAction,
+ TextMacroAction
+} from '../../../config-serializer/config-items/macro-action';
+
+import { MapperService } from '../../../services/mapper.service';
+
+@Component({
+ selector: 'macro-item',
+ template: require('./macro-item.component.html'),
+ styles: [require('./macro-item.component.scss')],
+ host: { 'class': 'macro-item' }
+})
+export class MacroItemComponent implements OnInit, OnChanges {
+
+ @Input() macroAction: MacroAction;
+ @Input() editable: boolean;
+ @Input() deletable: boolean;
+ @Input() moveable: boolean;
+
+ @Output() save = new EventEmitter();
+ @Output() cancel = new EventEmitter();
+ @Output() edit = new EventEmitter();
+ @Output() delete = new EventEmitter();
+
+ private title: string;
+ private iconName: string;
+ private editing: boolean;
+
+ constructor(private mapper: MapperService) { }
+
+ ngOnInit() {
+ this.updateView();
+ if (!this.macroAction) {
+ this.editing = true;
+ }
+ }
+
+ ngOnChanges(changes: SimpleChanges) {
+ /* tslint:disable:no-string-literal */
+ if (changes['macroAction']) {
+ /* tslint:enable:no-string-literal */
+ this.updateView();
+ }
+ }
+
+ saveEditedAction(editedAction: MacroAction): void {
+ // @todo save this to keyboard
+ console.log('Saved action', editedAction);
+ this.macroAction = editedAction;
+ this.editing = false;
+ this.updateView();
+ this.save.emit(editedAction);
+ }
+
+ editAction(): void {
+ if (!this.editable) {
+ return;
+ }
+ this.editing = true;
+ this.edit.emit();
+ }
+
+ cancelEdit(): void {
+ this.editing = false;
+ this.cancel.emit();
+ }
+
+ deleteAction(): void {
+ this.delete.emit();
+ }
+
+ private updateView(): void {
+ if (!this.macroAction) {
+ this.title = 'New macro action';
+ } else if (this.macroAction instanceof DelayMacroAction) {
+ // Delay
+ this.iconName = 'clock';
+ let action: DelayMacroAction = this.macroAction as DelayMacroAction;
+ const delay = action.delay > 0 ? action.delay / 1000 : 0;
+ this.title = `Delay of ${delay}s`;
+ } else if (this.macroAction instanceof TextMacroAction) {
+ // Write text
+ let action: TextMacroAction = this.macroAction as TextMacroAction;
+ this.iconName = 'font';
+ this.title = `Write text: ${action.text}`;
+ } else if (this.macroAction instanceof KeyMacroAction) {
+ // Key pressed/held/released
+ const action: KeyMacroAction = this.macroAction as KeyMacroAction;
+ this.setKeyActionContent(action);
+ } else if (this.macroAction instanceof MouseButtonMacroAction) {
+ // Mouse button clicked/held/released
+ const action: MouseButtonMacroAction = this.macroAction as MouseButtonMacroAction;
+ this.setMouseButtonActionContent(action);
+ } else if (this.macroAction instanceof MoveMouseMacroAction || this.macroAction instanceof ScrollMouseMacroAction) {
+ // Mouse moved or scrolled
+ this.setMouseMoveScrollActionContent(this.macroAction);
+ } else {
+ this.title = this.macroAction.constructor.name;
+ }
+ }
+
+ private setKeyActionContent(action: KeyMacroAction): void {
+ if (!action.hasScancode() && !action.hasModifiers()) {
+ this.title = 'Invalid keypress';
+ return;
+ }
+
+ if (action.isPressAction()) {
+ // Press key
+ this.iconName = 'hand-pointer';
+ this.title = 'Press key: ';
+ } else if (action.isHoldAction()) {
+ // Hold key
+ this.iconName = 'hand-rock';
+ this.title = 'Hold key: ';
+ } else if (action.isReleaseAction()) {
+ // Release key
+ this.iconName = 'hand-paper';
+ this.title = 'Release key: ';
+ }
+
+ if (action.hasScancode()) {
+ const scancode: string = this.mapper.scanCodeToText(action.scancode).join(' ');
+ if (scancode) {
+ this.title += scancode;
+ }
+ }
+
+ if (action.hasModifiers()) {
+ // Press/hold/release modifiers
+ for (let i = KeyModifiers.leftCtrl; i !== KeyModifiers.rightGui; i <<= 1) {
+ if (action.isModifierActive(i)) {
+ this.title += ' ' + KeyModifiers[i];
+ }
+ }
+ }
+ }
+
+ private setMouseMoveScrollActionContent(action: MacroAction): void {
+ let typedAction: any;
+ if (action instanceof MoveMouseMacroAction) {
+ // Move mouse pointer
+ this.iconName = 'mouse-pointer';
+ this.title = 'Move pointer';
+ typedAction = this.macroAction as MoveMouseMacroAction;
+ } else {
+ // Scroll mouse
+ this.iconName = 'mouse-pointer';
+ this.title = 'Scroll';
+ typedAction = this.macroAction as ScrollMouseMacroAction;
+ }
+
+ let needAnd: boolean;
+ if (Math.abs(typedAction.x) !== 0) {
+ this.title += ` by ${Math.abs(typedAction.x)}px ${typedAction.x > 0 ? 'left' : 'right'}`;
+ needAnd = true;
+ }
+ if (Math.abs(typedAction.y) !== 0) {
+ this.title += ` ${needAnd ? 'and' : 'by'} ${Math.abs(typedAction.y)}px ${typedAction.y > 0 ? 'down' : 'up'}`;
+ }
+ }
+
+ private setMouseButtonActionContent(action: MouseButtonMacroAction): void {
+ // Press/hold/release mouse buttons
+ if (action.isOnlyPressAction()) {
+ this.iconName = 'mouse-pointer';
+ this.title = 'Click mouse button: ';
+ } else if (action.isOnlyHoldAction()) {
+ this.iconName = 'hand-rock';
+ this.title = 'Hold mouse button: ';
+ } else if (action.isOnlyReleaseAction()) {
+ this.iconName = 'hand-paper';
+ this.title = 'Release mouse button: ';
+ }
+
+ const buttonLabels: string[] = ['Left', 'Middle', 'Right'];
+ const selectedButtons: boolean[] = action.getMouseButtons();
+ const selectedButtonLabels: string[] = [];
+ selectedButtons.forEach((isSelected, idx) => {
+ if (isSelected && buttonLabels[idx]) {
+ selectedButtonLabels.push(buttonLabels[idx]);
+ }
+ });
+ this.title += selectedButtonLabels.join(', ');
+ }
+}
diff --git a/src/components/macro/macro.component.html b/src/components/macro/macro.component.html
index a7c4ea8b..5e8a17e1 100644
--- a/src/components/macro/macro.component.html
+++ b/src/components/macro/macro.component.html
@@ -1,74 +1,38 @@
-
-
-
-
- Macro1
-
-
-
-
-
-
- Move pointer by 100px leftward
-
-
-
-
-
-
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
- labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
- dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
- sit amet.
-
-
-
-
- Press letter A
-
-
-
-
-
- Press Alt+Tab
-
-
-
-
-
- Delay of 235ms
-
-
-
-
-
- Press button 1
-
-
-
-
-
- Scroll by 150px downward
-
-
-
+
+
+
+ {{macro.name}}
+
+
+
+
+
+
+
+
-
+
-
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
- labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
- dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor
- sit amet.
+
Remember to save your changes!
- Save
- Cancel
+ Save macro
+ Discard changes
diff --git a/src/components/macro/macro.component.scss b/src/components/macro/macro.component.scss
index ab3f7d22..b1e1f861 100644
--- a/src/components/macro/macro.component.scss
+++ b/src/components/macro/macro.component.scss
@@ -1,3 +1,20 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+
+ .list-container {
+ display: flex;
+ flex: 1;
+
+ > div {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ }
+ }
+}
+
.main-wrapper {
width: 500px;
}
@@ -6,33 +23,50 @@ h1 {
margin-bottom: 3rem;
}
-.action--item {
- padding-left: 8px;
+.action {
+ &--edit__form {
+ background-color: #fff;
+ margin-left: -0.5rem;
+ margin-right: -15px;
+ margin-top: 15px;
+ padding-top: 15px;
+ border-top: 1px solid #ddd;
+ }
+
+ &--item {
+ padding-left: 8px;
+
+ &.active,
+ &.active:hover {
+ background-color: white;
+ font-weight: bold;
+ color: black;
+ border-color: black;
+ z-index: 10;
+ }
+ }
}
-.action--item.active,
-.action--item.active:hover {
- background-color: white;
- font-weight: bold;
- color: black;
- border-color: black;
- z-index: 10;
+.macro__name {
+ border-bottom: 2px dotted #999;
+ padding: 0 0.5rem;
+ margin: 0 0.25rem;
}
.macro-settings {
border: 1px solid black;
border-top-color: #999;
z-index: 100;
-}
-.macro-settings .helper {
- position: absolute;
- display: block;
- height: 13px;
- background: #fff;
- width: 100%;
- left: 0;
- top: -14px;
+ .helper {
+ position: absolute;
+ display: block;
+ height: 13px;
+ background: #fff;
+ width: 100%;
+ left: 0;
+ top: -14px;
+ }
}
.action--item.active.callout,
@@ -40,38 +74,18 @@ h1 {
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.5);
}
+.macro-actions-container {
+ overflow: auto;
+ margin-bottom: 0;
+ border-radius: 4px 4px 0 0;
+ border: 1px solid #ddd;
+ border-bottom: 0;
+}
+
.list-group-item .move-handle:hover {
cursor: move;
}
-.action--edit {
- float: right;
-}
-
-.action--edit:hover {
- color: #337ab7;
- cursor: pointer;
-}
-
-.action--trash {
- float: right;
- margin-right: 1rem;
-}
-
-.action--trash:hover {
- color: #d9534f;
- cursor: pointer;
-}
-
-.action--edit__form {
- background-color: #fff;
- margin-left: -0.5rem;
- margin-right: -15px;
- margin-top: 15px;
- padding-top: 15px;
- border-top: 1px solid #ddd;
-}
-
.flex-button-wrapper {
display: flex;
flex-direction: row-reverse;
@@ -81,13 +95,22 @@ h1 {
align-self: flex-end;
}
-.add-new__action-item:hover {
- cursor: pointer;
+.add-new__action-container {
+ border-top: 1px solid #ddd;
}
-.add-new__action-item--link,
-.add-new__action-item--link:active,
-.add-new__action-item--link:hover {
- text-decoration: none;
- color: #337ab7;
+.add-new__action-item {
+ border-radius: 0 0 4px 4px;
+ border-top: 0;
+
+ &:hover {
+ cursor: pointer;
+ }
+
+ &--link,
+ &--link:active,
+ &--link:hover {
+ text-decoration: none;
+ color: #337ab7;
+ }
}
diff --git a/src/components/macro/macro.component.ts b/src/components/macro/macro.component.ts
index 945dacc6..c3fa4f48 100644
--- a/src/components/macro/macro.component.ts
+++ b/src/components/macro/macro.component.ts
@@ -1,12 +1,116 @@
-import { Component } from '@angular/core';
+import { Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+import { Subscription } from 'rxjs/Subscription';
+
+import { DragulaService } from 'ng2-dragula/ng2-dragula';
+
+import { Macro } from '../../config-serializer/config-items/Macro';
+import { MacroAction } from '../../config-serializer/config-items/macro-action';
+import { MacroItemComponent } from './macro-item/macro-item.component';
+
+import { UhkConfigurationService } from '../../services/uhk-configuration.service';
@Component({
selector: 'macro',
template: require('./macro.component.html'),
- styles: [require('./macro.component.scss')]
+ styles: [require('./macro.component.scss')],
+ viewProviders: [DragulaService]
})
-export class MacroComponent {
+export class MacroComponent implements OnInit, OnDestroy {
+ @ViewChildren(MacroItemComponent) macroItems: QueryList
;
- constructor() {
+ private macro: Macro;
+
+ private routeSubscription: Subscription;
+ private hasChanges: boolean = false;
+ private dragEnabled: boolean;
+
+ constructor(
+ private uhkConfigurationService: UhkConfigurationService,
+ private route: ActivatedRoute,
+ private dragulaService: DragulaService
+ ) {
+ /* tslint:disable:no-unused-variable: Used by Dragula. */
+ dragulaService.setOptions('macroActions', {
+ moves: function (el: any, container: any, handle: any) {
+ return handle.className.includes('action--movable');
+ }
+ });
+ /* tslint:enable:no-unused-variable */
}
+
+ ngOnInit() {
+ this.routeSubscription = this.route.params.subscribe((params: { id: string }) => {
+ const id: number = Number(params.id);
+ this.macro = this.getMacro(id);
+ this.dragEnabled = true;
+ this.hasChanges = false;
+ });
+ }
+
+ getMacro(id: number): Macro {
+ const config = this.uhkConfigurationService.getUhkConfiguration();
+ const macro: Macro = config.macros.elements.find(item => item.id === id);
+ if (macro) {
+ // Clone macro for editing
+ return new Macro().fromJsObject(macro.toJsObject());
+ }
+ // @todo replace with notification
+ throw new Error('Macro not found');
+ }
+
+ saveMacro() {
+ // @todo Save macro to keyboard
+ }
+
+ addAction() {
+ this.hideOtherActionEditors(this.macro.macroActions.elements.length);
+ this.macro.macroActions.elements.push(undefined);
+ }
+
+ discardChanges() {
+ const id: number = this.macro.id;
+ this.macro = this.getMacro(id);
+ this.hasChanges = false;
+ }
+
+ hideOtherActionEditors(index: number) {
+ this.macroItems.toArray().forEach((macroItem: MacroItemComponent, idx: number) => {
+ if (idx !== index) {
+ macroItem.cancelEdit();
+ }
+ });
+ }
+
+ onNameChange() {
+ this.hasChanges = true;
+ }
+
+ onEditAction(index: number) {
+ // Hide other editors when clicking edit button of a macro action
+ this.hideOtherActionEditors(index);
+ this.dragEnabled = false;
+ }
+
+ onCancelEditAction() {
+ this.dragEnabled = true;
+ }
+
+ onSaveAction(macroAction: MacroAction, index: number) {
+ this.dragEnabled = true;
+ this.hasChanges = true;
+ this.macro.macroActions.elements[index] = macroAction;
+ }
+
+ onDeleteAction(index: number) {
+ // @ todo show confirm action dialog
+ this.macro.macroActions.elements.splice(index, 1);
+ this.hasChanges = true;
+ }
+
+ ngOnDestroy() {
+ this.routeSubscription.unsubscribe();
+ }
+
}
diff --git a/src/components/popover/popover.component.html b/src/components/popover/popover.component.html
index 5d08b10e..311904c7 100644
--- a/src/components/popover/popover.component.html
+++ b/src/components/popover/popover.component.html
@@ -42,7 +42,7 @@
-
+
diff --git a/src/components/popover/tab/keypress/keypress-tab.component.html b/src/components/popover/tab/keypress/keypress-tab.component.html
index b4492276..c0ea90d6 100644
--- a/src/components/popover/tab/keypress/keypress-tab.component.html
+++ b/src/components/popover/tab/keypress/keypress-tab.component.html
@@ -21,7 +21,7 @@
-
+
Long press action:
diff --git a/src/components/popover/tab/keypress/keypress-tab.component.ts b/src/components/popover/tab/keypress/keypress-tab.component.ts
index 3879a0d4..271485d8 100644
--- a/src/components/popover/tab/keypress/keypress-tab.component.ts
+++ b/src/components/popover/tab/keypress/keypress-tab.component.ts
@@ -13,6 +13,7 @@ import {Tab} from '../tab';
})
export class KeypressTabComponent implements OnInit, Tab {
@Input() defaultKeyAction: KeyAction;
+ @Input() longPressEnabled: boolean;
private leftModifiers: string[];
private rightModifiers: string[];
diff --git a/src/components/popover/tab/macro/index.ts b/src/components/popover/tab/macro/index.ts
index 58cac3e1..ef6b932a 100644
--- a/src/components/popover/tab/macro/index.ts
+++ b/src/components/popover/tab/macro/index.ts
@@ -1,2 +1 @@
-export * from './macro-item.component';
export * from './macro-tab.component';
diff --git a/src/components/popover/tab/macro/macro-item.component.html b/src/components/popover/tab/macro/macro-item.component.html
deleted file mode 100644
index 06ed0384..00000000
--- a/src/components/popover/tab/macro/macro-item.component.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
{{ title }}
-
-
\ No newline at end of file
diff --git a/src/components/popover/tab/macro/macro-item.component.scss b/src/components/popover/tab/macro/macro-item.component.scss
deleted file mode 100644
index 25b3534f..00000000
--- a/src/components/popover/tab/macro/macro-item.component.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-:host {
- display: flex;
- flex-shrink: 0;
-
- icon {
- margin: 0 5px;
- }
-
- div {
- display: flex;
- flex: 1;
- }
-}
diff --git a/src/components/popover/tab/macro/macro-item.component.ts b/src/components/popover/tab/macro/macro-item.component.ts
deleted file mode 100644
index 09da57d4..00000000
--- a/src/components/popover/tab/macro/macro-item.component.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-///
-
-import { Component, Input, OnChanges, OnInit } from '@angular/core';
-
-import {KeyModifiers} from '../../../../config-serializer/config-items/KeyModifiers';
-import {
- DelayMacroAction,
- KeyMacroAction,
- MacroAction,
- MoveMouseMacroAction,
- ScrollMouseMacroAction,
- TextMacroAction
-} from '../../../../config-serializer/config-items/macro-action';
-
-import {MapperService} from '../../../../services/mapper.service';
-
-@Component({
- selector: 'macro-item',
- template: require('./macro-item.component.html'),
- styles: [require('./macro-item.component.scss')]
-})
-export class MacroItemComponent implements OnInit, OnChanges {
-
- @Input() macroAction: MacroAction;
- @Input() editable: boolean;
- @Input() deletable: boolean;
- @Input() moveable: boolean;
-
- private iconName: string;
- private title: string;
-
- constructor(private mapper: MapperService) { }
-
- ngOnInit() {
- this.updateView();
- }
-
- ngOnChanges() {
- // TODO: check if macroAction changed
- this.updateView();
- }
-
- private updateView(): void {
-
- this.title = this.macroAction.constructor.name;
- if (this.macroAction instanceof MoveMouseMacroAction) {
- this.iconName = 'mouse-pointer';
- this.title = 'Move pointer';
-
- let action: MoveMouseMacroAction = this.macroAction as MoveMouseMacroAction;
- let needAnd: boolean;
- if (Math.abs(action.x) > 0) {
- this.title += ` by ${Math.abs(action.x)}px ${action.x > 0 ? 'left' : 'right'}ward`;
- needAnd = true;
- }
- if (Math.abs(action.y) > 0) {
- this.title += ` ${needAnd ? 'and' : 'by'} ${Math.abs(action.y)}px ${action.y > 0 ? 'down' : 'up'}ward`;
- }
- } else if (this.macroAction instanceof DelayMacroAction) {
- this.iconName = 'clock';
- let action: DelayMacroAction = this.macroAction as DelayMacroAction;
- this.title = `Delay of ${action.delay}ms`;
- } else if (this.macroAction instanceof TextMacroAction) {
- let action: TextMacroAction = this.macroAction as TextMacroAction;
- this.title = `Write text: ${action.text}`;
- } else if (this.macroAction instanceof ScrollMouseMacroAction) {
- this.iconName = 'mouse-pointer';
- this.title = 'Scroll';
- let action: ScrollMouseMacroAction = this.macroAction as ScrollMouseMacroAction;
- let needAnd: boolean;
- if (Math.abs(action.x) > 0) {
- this.title += ` by ${Math.abs(action.x)}px ${action.x > 0 ? 'left' : 'right'}ward`;
- needAnd = true;
- }
- if (Math.abs(action.y) > 0) {
- this.title += ` ${needAnd ? 'and' : 'by'} ${Math.abs(action.y)}px ${action.y > 0 ? 'down' : 'up'}ward`;
- }
- } else if (this.macroAction instanceof KeyMacroAction) {
- const keyMacroAction: KeyMacroAction =
this.macroAction;
- this.title += 'KeyMacroAction: ';
- if (keyMacroAction.isPressAction()) {
- this.title = 'Press';
- } else if (keyMacroAction.isHoldAction()) {
- this.title = 'Hold';
- } else {
- this.title = 'Release';
- }
- if (keyMacroAction.hasScancode()) {
- this.title += ' ' + this.mapper.scanCodeToText(keyMacroAction.scancode).join(' ');
- }
- this.iconName = 'square';
-
- for (let i = KeyModifiers.leftCtrl; i !== KeyModifiers.rightCtrl; i <<= 1) {
- if (keyMacroAction.isModifierActive(i)) {
- this.title += ' ' + KeyModifiers[i];
- }
- }
- }
- // TODO: finish for all MacroAction
- }
-
-}
diff --git a/src/components/popover/tab/macro/macro-tab.component.html b/src/components/popover/tab/macro/macro-tab.component.html
index 8552b7bb..075d63ad 100644
--- a/src/components/popover/tab/macro/macro-tab.component.html
+++ b/src/components/popover/tab/macro/macro-tab.component.html
@@ -2,10 +2,12 @@
Play macro:
-
+
\ No newline at end of file
diff --git a/src/components/popover/tab/macro/macro-tab.component.scss b/src/components/popover/tab/macro/macro-tab.component.scss
index 94a91b20..aac3085a 100644
--- a/src/components/popover/tab/macro/macro-tab.component.scss
+++ b/src/components/popover/tab/macro/macro-tab.component.scss
@@ -25,22 +25,16 @@
margin: 20px 0;
overflow-x: hidden;
overflow-y: auto;
+ border-radius: 4px;
+ border: 1px solid #ddd;
- macro-item {
- border: 1px solid #ddd;
- padding: 10px;
- margin-bottom: -1px;
+ &.inactive {
+ border: 0;
}
- macro-item:first-child {
- border-top-left-radius: 4px;
- border-top-right-radius: 4px;
- }
-
- macro-item:last-child {
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
+ .list-group {
margin-bottom: 0;
+ border: 0;
}
}
}
diff --git a/src/components/popover/tab/mouse/mouse-tab.component.ts b/src/components/popover/tab/mouse/mouse-tab.component.ts
index 0e4fd85c..4ca8f3f0 100644
--- a/src/components/popover/tab/mouse/mouse-tab.component.ts
+++ b/src/components/popover/tab/mouse/mouse-tab.component.ts
@@ -1,7 +1,6 @@
import {Component, Input, OnInit} from '@angular/core';
import {KeyAction, MouseAction, MouseActionParam} from '../../../../config-serializer/config-items/key-action';
-
import {Tab} from '../tab';
@Component({
diff --git a/src/components/popover/widgets/icon/icon.component.html b/src/components/popover/widgets/icon/icon.component.html
index 0264ad81..5c9037b9 100644
--- a/src/components/popover/widgets/icon/icon.component.html
+++ b/src/components/popover/widgets/icon/icon.component.html
@@ -1,8 +1,12 @@
+
+
+
+
diff --git a/src/components/popover/widgets/icon/icon.component.scss b/src/components/popover/widgets/icon/icon.component.scss
index f9b77422..fc014389 100644
--- a/src/components/popover/widgets/icon/icon.component.scss
+++ b/src/components/popover/widgets/icon/icon.component.scss
@@ -2,3 +2,21 @@
display: flex;
align-items: center;
}
+
+.action {
+
+ &--edit {
+ &:hover {
+ color: #337ab7;
+ cursor: pointer;
+ }
+ }
+
+ &--trash {
+ &:hover {
+ color: #d9534f;
+ cursor: pointer;
+ }
+ }
+
+}
diff --git a/src/components/side-menu/side-menu.component.html b/src/components/side-menu/side-menu.component.html
index 7f984448..d4a36b79 100644
--- a/src/components/side-menu/side-menu.component.html
+++ b/src/components/side-menu/side-menu.component.html
@@ -19,7 +19,7 @@