forked from mirror/ObjToSchematic
Slider hover fix, added vector spinbox for future
This commit is contained in:
parent
b66a489af2
commit
3f988c0654
@ -98,6 +98,8 @@ export class AppContext {
|
||||
this._ui = new UI(this);
|
||||
this._ui.build();
|
||||
this._ui.registerEvents();
|
||||
|
||||
// this._ui.disablePost(Action.Import);
|
||||
this._ui.disable(Action.Simplify);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ASSERT } from '../../util';
|
||||
import { ASSERT, getRandomID } from '../../util';
|
||||
|
||||
export class LabelElement {
|
||||
private _id: string;
|
||||
private _text: string;
|
||||
|
||||
constructor(id: string, text: string) {
|
||||
this._id = id;
|
||||
constructor(text: string) {
|
||||
this._id = getRandomID();
|
||||
this._text = text;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ export abstract class LabelledElement<Type> extends BaseUIElement<Type> {
|
||||
|
||||
public constructor(label: string) {
|
||||
super(label);
|
||||
this._labelElement = new LabelElement(label, label);
|
||||
this._labelElement = new LabelElement(label);
|
||||
}
|
||||
|
||||
public generateHTML() {
|
||||
|
@ -34,8 +34,21 @@ export class SliderElement extends LabelledElement<number> {
|
||||
|
||||
public registerEvents() {
|
||||
const element = document.getElementById(this._id) as HTMLDivElement;
|
||||
const elementBar = document.getElementById(this._id + '-bar') as HTMLDivElement;
|
||||
ASSERT(element !== null);
|
||||
|
||||
element.onmouseenter = () => {
|
||||
if (this._isEnabled) {
|
||||
element.classList.add('new-slider-hover');
|
||||
elementBar.classList.add('new-slider-bar-hover');
|
||||
}
|
||||
};
|
||||
|
||||
element.onmouseleave = () => {
|
||||
element.classList.remove('new-slider-hover');
|
||||
elementBar.classList.remove('new-slider-bar-hover');
|
||||
};
|
||||
|
||||
element.onmousedown = () => {
|
||||
this._dragging = true;
|
||||
};
|
||||
|
199
src/ui/elements/vector_spinbox.ts
Normal file
199
src/ui/elements/vector_spinbox.ts
Normal file
@ -0,0 +1,199 @@
|
||||
import { ASSERT, LOG } from '../../util';
|
||||
import { LabelledElement } from './labelled_element';
|
||||
import { Vector3 } from '../../vector';
|
||||
|
||||
/* eslint-disable */
|
||||
enum EAxis {
|
||||
None = 'none',
|
||||
X = 'x',
|
||||
Y = 'y',
|
||||
Z = 'z',
|
||||
};
|
||||
/* eslint-enable */
|
||||
|
||||
export class VectorSpinboxElement extends LabelledElement<Vector3> {
|
||||
private _mouseover: EAxis;
|
||||
private _dragging: EAxis;
|
||||
private _lastClientX: number;
|
||||
|
||||
public constructor(label: string, decimals: number, value: Vector3) {
|
||||
super(label);
|
||||
this._value = value;
|
||||
this._mouseover = EAxis.None;
|
||||
this._dragging = EAxis.None;
|
||||
this._lastClientX = 0.0;
|
||||
}
|
||||
|
||||
public generateInnerHTML() {
|
||||
ASSERT(this._value, 'Value not found');
|
||||
return `
|
||||
<div style="display: flex; flex-direction: row;">
|
||||
<div style="display: flex; flex-direction: row; width: 33%">
|
||||
<div class="spinbox-key" id="${this._id}-kx" style="background-color: #FF4C4C;">X</div>
|
||||
<div class="spinbox-value" id="${this._id}-vx">
|
||||
${this._value.x}
|
||||
</div>
|
||||
</div>
|
||||
<div class="invis-divider"></div>
|
||||
<div style="display: flex; flex-direction: row; width: 33%"">
|
||||
<div class="spinbox-key" id="${this._id}-ky" style="background-color: #34BF49;">Y</div>
|
||||
<div class="spinbox-value" id="${this._id}-vy">
|
||||
${this._value.y}
|
||||
</div>
|
||||
</div>
|
||||
<div class="invis-divider"></div>
|
||||
<div style="display: flex; flex-direction: row; width: 33%"">
|
||||
<div class="spinbox-key" id="${this._id}-kz" style="background-color: #0099E5;">Z</div>
|
||||
<div class="spinbox-value" id="${this._id}-vz">
|
||||
${this._value.z}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _registerAxis(axis: EAxis) {
|
||||
ASSERT(axis !== EAxis.None);
|
||||
|
||||
const elementXK = document.getElementById(this._id + '-k' + axis) as HTMLDivElement;
|
||||
const elementXV = document.getElementById(this._id + '-v' + axis) as HTMLDivElement;
|
||||
ASSERT(elementXK !== null && elementXV !== null);
|
||||
|
||||
elementXK.onmouseenter = () => {
|
||||
this._mouseover = axis;
|
||||
if (this._isEnabled) {
|
||||
elementXK.classList.add('spinbox-key-hover');
|
||||
elementXV.classList.add('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
|
||||
elementXV.onmouseenter = () => {
|
||||
this._mouseover = axis;
|
||||
if (this._isEnabled) {
|
||||
elementXK.classList.add('spinbox-key-hover');
|
||||
elementXV.classList.add('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
|
||||
elementXK.onmouseleave = () => {
|
||||
this._mouseover = EAxis.None;
|
||||
if (this._dragging !== axis) {
|
||||
elementXK.classList.remove('spinbox-key-hover');
|
||||
elementXV.classList.remove('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
|
||||
elementXV.onmouseleave = () => {
|
||||
this._mouseover = EAxis.None;
|
||||
if (this._dragging !== axis) {
|
||||
elementXK.classList.remove('spinbox-key-hover');
|
||||
elementXV.classList.remove('spinbox-value-hover');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public registerEvents() {
|
||||
this._registerAxis(EAxis.X);
|
||||
this._registerAxis(EAxis.Y);
|
||||
this._registerAxis(EAxis.Z);
|
||||
|
||||
document.addEventListener('mousedown', (e: any) => {
|
||||
if (this._isEnabled && this._mouseover !== EAxis.None) {
|
||||
this._dragging = this._mouseover;
|
||||
this._lastClientX = e.clientX;
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', (e: any) => {
|
||||
if (this._isEnabled && this._dragging !== EAxis.None) {
|
||||
this._updateValue(e);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseup', () => {
|
||||
const elementXK = document.getElementById(this._id + '-kx') as HTMLDivElement;
|
||||
const elementYK = document.getElementById(this._id + '-ky') as HTMLDivElement;
|
||||
const elementZK = document.getElementById(this._id + '-kz') as HTMLDivElement;
|
||||
const elementXV = document.getElementById(this._id + '-vx') as HTMLDivElement;
|
||||
const elementYV = document.getElementById(this._id + '-vy') as HTMLDivElement;
|
||||
const elementZV = document.getElementById(this._id + '-vz') as HTMLDivElement;
|
||||
|
||||
switch (this._dragging) {
|
||||
case EAxis.X:
|
||||
elementXK.classList.remove('spinbox-key-hover');
|
||||
elementXV.classList.remove('spinbox-value-hover');
|
||||
break;
|
||||
case EAxis.Y:
|
||||
elementYK.classList.remove('spinbox-key-hover');
|
||||
elementYV.classList.remove('spinbox-value-hover');
|
||||
break;
|
||||
case EAxis.Z:
|
||||
elementZK.classList.remove('spinbox-key-hover');
|
||||
elementZV.classList.remove('spinbox-value-hover');
|
||||
break;
|
||||
}
|
||||
this._dragging = EAxis.None;
|
||||
});
|
||||
}
|
||||
|
||||
private _updateValue(e: MouseEvent) {
|
||||
ASSERT(this._isEnabled, 'Not enabled');
|
||||
ASSERT(this._dragging !== EAxis.None, 'Dragging nothing');
|
||||
ASSERT(this._value, 'No value to update');
|
||||
|
||||
const deltaX = e.clientX - this._lastClientX;
|
||||
this._lastClientX = e.clientX;
|
||||
|
||||
switch (this._dragging) {
|
||||
case EAxis.X:
|
||||
this._value.x += deltaX;
|
||||
break;
|
||||
case EAxis.Y:
|
||||
this._value.y += deltaX;
|
||||
break;
|
||||
case EAxis.Z:
|
||||
this._value.z += deltaX;
|
||||
break;
|
||||
}
|
||||
|
||||
const elementXV = document.getElementById(this._id + '-vx') as HTMLDivElement;
|
||||
const elementYV = document.getElementById(this._id + '-vy') as HTMLDivElement;
|
||||
const elementZV = document.getElementById(this._id + '-vz') as HTMLDivElement;
|
||||
elementXV.innerHTML = this._value.x.toString();
|
||||
elementYV.innerHTML = this._value.y.toString();
|
||||
elementZV.innerHTML = this._value.z.toString();
|
||||
}
|
||||
|
||||
protected _onEnabledChanged() {
|
||||
super._onEnabledChanged();
|
||||
|
||||
LOG(this._label, 'is now enabled', this._isEnabled);
|
||||
|
||||
const keyElements = [
|
||||
document.getElementById(this._id + '-kx') as HTMLDivElement,
|
||||
document.getElementById(this._id + '-ky') as HTMLDivElement,
|
||||
document.getElementById(this._id + '-kz') as HTMLDivElement,
|
||||
];
|
||||
const valueElements = [
|
||||
document.getElementById(this._id + '-vx') as HTMLDivElement,
|
||||
document.getElementById(this._id + '-vy') as HTMLDivElement,
|
||||
document.getElementById(this._id + '-vz') as HTMLDivElement,
|
||||
];
|
||||
|
||||
if (this._isEnabled) {
|
||||
for (const keyElement of keyElements) {
|
||||
keyElement.classList.remove('spinbox-key-disabled');
|
||||
}
|
||||
for (const valueElement of valueElements) {
|
||||
valueElement.classList.remove('spinbox-value-disabled');
|
||||
}
|
||||
} else {
|
||||
for (const keyElement of keyElements) {
|
||||
keyElement.classList.add('spinbox-key-disabled');
|
||||
}
|
||||
for (const valueElement of valueElements) {
|
||||
valueElement.classList.add('spinbox-value-disabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import { FileInputElement } from './elements/file_input';
|
||||
import { ButtonElement } from './elements/button';
|
||||
import { OutputElement } from './elements/output';
|
||||
import { Action, AppContext } from '../app_context';
|
||||
import { LOG } from '../util';
|
||||
import { ASSERT, LOG } from '../util';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
@ -16,6 +16,8 @@ export interface Group {
|
||||
elementsOrder: string[];
|
||||
submitButton: ButtonElement;
|
||||
output: OutputElement;
|
||||
postElements?: { [key: string]: BaseUIElement<any> };
|
||||
postElementsOrder?: string[];
|
||||
}
|
||||
|
||||
export class UI {
|
||||
@ -155,6 +157,15 @@ export class UI {
|
||||
groupHTML += this._buildSubcomponent(element);
|
||||
}
|
||||
|
||||
let postGroupHTML = '';
|
||||
if (group.postElements) {
|
||||
ASSERT(group.postElementsOrder, 'No post elements order');
|
||||
for (const elementName of group.postElementsOrder) {
|
||||
const element = group.postElements[elementName];
|
||||
postGroupHTML += this._buildSubcomponent(element);
|
||||
}
|
||||
}
|
||||
|
||||
return `
|
||||
${groupHTML}
|
||||
<div class="item item-body">
|
||||
@ -167,6 +178,7 @@ export class UI {
|
||||
${group.output.generateHTML()}
|
||||
</div>
|
||||
</div>
|
||||
${postGroupHTML}
|
||||
`;
|
||||
}
|
||||
|
||||
@ -186,6 +198,13 @@ export class UI {
|
||||
element.registerEvents();
|
||||
}
|
||||
group.submitButton.registerEvents();
|
||||
if (group.postElements) {
|
||||
ASSERT(group.postElementsOrder);
|
||||
for (const elementName in group.postElements) {
|
||||
const element = group.postElements[elementName];
|
||||
element.registerEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,29 +216,55 @@ export class UI {
|
||||
return this._uiDull;
|
||||
}
|
||||
|
||||
public disable(action: Action) {
|
||||
for (let i = action; i < Action.MAX; ++i) {
|
||||
const key = this.uiOrder[i];
|
||||
this._setGroupEnabled(this._uiDull[key], false);
|
||||
}
|
||||
}
|
||||
|
||||
public enable(action: Action) {
|
||||
LOG('enabling', action);
|
||||
|
||||
// TODO: Remove once Simplify has been implemented
|
||||
/*
|
||||
if (action === Action.Simplify) {
|
||||
action = Action.Voxelise;
|
||||
}
|
||||
const key = this.uiOrder[action];
|
||||
this._setGroupEnabled(this._uiDull[key], true);
|
||||
*/
|
||||
const group = this._getActionGroup(action);
|
||||
for (const compName in group.elements) {
|
||||
group.elements[compName].setEnabled(true);
|
||||
}
|
||||
group.submitButton.setEnabled(true);
|
||||
// Enable the post elements of the previous group
|
||||
const prevGroup = this._getActionGroup(action - 1);
|
||||
if (prevGroup && prevGroup.postElements) {
|
||||
ASSERT(prevGroup.postElementsOrder);
|
||||
for (const postElementName in prevGroup.postElements) {
|
||||
prevGroup.postElements[postElementName].setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _setGroupEnabled(group: Group, isEnabled: boolean) {
|
||||
for (const compName in group.elements) {
|
||||
const comp = group.elements[compName];
|
||||
comp.setEnabled(isEnabled);
|
||||
}
|
||||
group.submitButton.setEnabled(isEnabled);
|
||||
if (!isEnabled) {
|
||||
public disable(action: Action) {
|
||||
for (let i = action; i < Action.MAX; ++i) {
|
||||
const group = this._getActionGroup(i);
|
||||
LOG('disabling', group.label);
|
||||
for (const compName in group.elements) {
|
||||
group.elements[compName].setEnabled(false);
|
||||
}
|
||||
group.submitButton.setEnabled(false);
|
||||
group.output.clearMessage();
|
||||
if (group.postElements) {
|
||||
LOG(group.label, 'has post-element');
|
||||
ASSERT(group.postElementsOrder);
|
||||
for (const postElementName in group.postElements) {
|
||||
LOG('disabling post-element', postElementName, 'for', group.label);
|
||||
group.postElements[postElementName].setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Disable the post elements of the previous group
|
||||
const prevGroup = this._getActionGroup(action - 1);
|
||||
if (prevGroup && prevGroup.postElements) {
|
||||
ASSERT(prevGroup.postElementsOrder);
|
||||
for (const postElementName in prevGroup.postElements) {
|
||||
prevGroup.postElements[postElementName].setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
81
styles.css
81
styles.css
@ -74,7 +74,7 @@ canvas {
|
||||
.item-header {
|
||||
background-color: #2F2F2F;
|
||||
color: #C6C6C6;
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
@ -150,10 +150,12 @@ select {
|
||||
font-weight: 300;
|
||||
color: #A8A8A8;
|
||||
background-color: #2F2F2F;
|
||||
border: 1px solid rgb(255, 255, 255, 0.0);
|
||||
}
|
||||
select:hover {
|
||||
select:hover:enabled {
|
||||
color: #C6C6C6;
|
||||
background-color: #383838;
|
||||
border: 1px solid rgb(255, 255, 255, 0.1);
|
||||
}
|
||||
select:disabled {
|
||||
background-color: #282828 !important;
|
||||
@ -188,6 +190,8 @@ select:disabled {
|
||||
color: #535353;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.new-slider {
|
||||
border-radius: 5px;
|
||||
font-family: 'Lexend', sans-serif;
|
||||
@ -196,20 +200,28 @@ select:disabled {
|
||||
cursor: ew-resize;
|
||||
height: 30px;
|
||||
font-size: 90%;
|
||||
border: 1px solid #1A1A1A;
|
||||
}
|
||||
.new-slider-hover {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
||||
background-color: #383838 !important;
|
||||
}
|
||||
.new-slider-disabled {
|
||||
background-color: #242424 !important;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.new-slider-bar {
|
||||
border-radius: 5px;
|
||||
height: 28px;
|
||||
background-color: var(--prim-color);
|
||||
border: 1px solid rgb(255, 255, 255, 0.0);
|
||||
}
|
||||
.new-slider-bar:hover {
|
||||
border: 1px solid rgb(255, 255, 255, 0.2);
|
||||
background-color: var(--prim-color-hover);
|
||||
}
|
||||
.new-slider-disabled {
|
||||
background-color: #242424;
|
||||
cursor: default !important;
|
||||
.new-slider-bar-hover {
|
||||
border: 1px solid rgb(255, 255, 255, 0.2) !important;
|
||||
background-color: var(--prim-color-hover) !important;
|
||||
}
|
||||
.new-slider-bar-disabled {
|
||||
background-color: var(--prim-color-disabled) !important;
|
||||
@ -217,6 +229,8 @@ select:disabled {
|
||||
border: 1px solid rgb(255, 255, 255, 0.0) !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.button {
|
||||
background-color: var(--prim-color);
|
||||
border-radius: 5px;
|
||||
@ -311,4 +325,53 @@ select:disabled {
|
||||
border: 1.5px solid rgb(156, 27, 27);
|
||||
transition-duration: 1s;
|
||||
color: rgb(156, 27, 27);
|
||||
}
|
||||
|
||||
.spinbox-key {
|
||||
border-radius: 5px 0px 0px 5px;
|
||||
height: calc(32px - 8.5px);
|
||||
color: #ffffffb9;
|
||||
padding: 8.5px 8px 0px 8px;
|
||||
font-size: 85%;
|
||||
font-weight: 400;
|
||||
border-width: 1px 0px 1px 1px;
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 0.0);
|
||||
}
|
||||
.spinbox-key-hover {
|
||||
border-color: rgba(255, 255, 255, 0.2) !important;
|
||||
filter: brightness(1.5);
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.spinbox-key-disabled {
|
||||
filter: brightness(0.4);
|
||||
}
|
||||
|
||||
.spinbox-value {
|
||||
background-color: #2F2F2F;
|
||||
border-radius: 0px 5px 5px 0px;
|
||||
flex-grow: 1;
|
||||
height: calc(32px - 8.5px);
|
||||
padding: 8.5px 0px 0px 0px;
|
||||
font-weight: 300;
|
||||
border-width: 1px 1px 1px 0px;
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 0.0);
|
||||
|
||||
color: #A8A8A8;
|
||||
align-self: center;
|
||||
text-align: center;
|
||||
}
|
||||
.spinbox-value-hover {
|
||||
border-color: rgba(255, 255, 255, 0.2) !important;
|
||||
background-color: #383838 !important;
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.spinbox-value-disabled {
|
||||
color: #535353;
|
||||
background-color: #242424 !important;
|
||||
}
|
||||
|
||||
.invis-divider {
|
||||
width: 6px;
|
||||
}
|
Loading…
Reference in New Issue
Block a user