forked from mirror/ObjToSchematic
* Added tooltips to toolbar buttons
* Refactored component styles for easier use with CSS selectors
This commit is contained in:
parent
2145c815f9
commit
8fb58815b9
@ -3,20 +3,21 @@ import * as path from 'path';
|
||||
import { ASSERT } from '../../util/error_util';
|
||||
import { UIUtil } from '../../util/ui_util';
|
||||
import { ConfigComponent } from './config';
|
||||
import { AppIcons } from '../icons';
|
||||
|
||||
export class FileComponent extends ConfigComponent<File, HTMLDivElement> {
|
||||
private _loadedFilePath: string;
|
||||
private _loadedFilePath: string | null;
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
this._loadedFilePath = '';
|
||||
this._loadedFilePath = null;
|
||||
}
|
||||
|
||||
protected override _generateInnerHTML() {
|
||||
return `
|
||||
<div class="input-file struct-prop" id="${this._getId()}">
|
||||
<input type="file" accept=".obj,,.glb" style="display: none;" id="${this._getId()}-input">
|
||||
${this._loadedFilePath}
|
||||
${this._loadedFilePath ?? 'No file chosen'}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@ -62,8 +63,12 @@ export class FileComponent extends ConfigComponent<File, HTMLDivElement> {
|
||||
}
|
||||
|
||||
protected override _updateStyles() {
|
||||
const parsedPath = path.parse(this._loadedFilePath);
|
||||
this._getElement().innerHTML = parsedPath.name + parsedPath.ext;
|
||||
if (this._loadedFilePath) {
|
||||
const parsedPath = path.parse(this._loadedFilePath);
|
||||
this._getElement().innerHTML = parsedPath.name + parsedPath.ext;
|
||||
} else {
|
||||
this._getElement().innerHTML = '<i>No file chosen</i>';
|
||||
}
|
||||
|
||||
UIUtil.updateStyles(this._getElement(), {
|
||||
isHovered: this.hovered,
|
||||
|
@ -22,17 +22,20 @@ export class HeaderComponent extends BaseComponent<HTMLDivElement> {
|
||||
this._githubButton = new ToolbarItemComponent({ id: 'gh', iconSVG: AppIcons.GITHUB })
|
||||
.onClick(() => {
|
||||
window.open('https://github.com/LucasDower/ObjToSchematic');
|
||||
});
|
||||
})
|
||||
.setTooltip('Open GitHub repo');
|
||||
|
||||
this._bugButton = new ToolbarItemComponent({ id: 'bug', iconSVG: AppIcons.BUG })
|
||||
.onClick(() => {
|
||||
window.open('https://github.com/LucasDower/ObjToSchematic/issues');
|
||||
});
|
||||
})
|
||||
.setTooltip('Open GitHub issues');
|
||||
|
||||
this._discordButton = new ToolbarItemComponent({ id: 'disc', iconSVG: AppIcons.DISCORD })
|
||||
.onClick(() => {
|
||||
window.open('https://discord.gg/McS2VrBZPD');
|
||||
});
|
||||
})
|
||||
.setTooltip('Open Discord server');
|
||||
}
|
||||
|
||||
// Header element shouldn't be
|
||||
|
@ -12,6 +12,7 @@ export type TToolbarItemParams = {
|
||||
export class ToolbarItemComponent extends BaseComponent<HTMLDivElement> {
|
||||
private _iconSVG: SVGSVGElement;
|
||||
private _label: string;
|
||||
private _tooltip: string | null;
|
||||
private _onClick?: () => void;
|
||||
private _isActive: boolean;
|
||||
private _grow: boolean;
|
||||
@ -33,6 +34,7 @@ export class ToolbarItemComponent extends BaseComponent<HTMLDivElement> {
|
||||
}
|
||||
|
||||
this._label = '';
|
||||
this._tooltip = null;
|
||||
}
|
||||
|
||||
public setGrow() {
|
||||
@ -90,6 +92,11 @@ export class ToolbarItemComponent extends BaseComponent<HTMLDivElement> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public setTooltip(text: string) {
|
||||
this._tooltip = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
public generateHTML() {
|
||||
if (this._grow) {
|
||||
return `
|
||||
@ -98,11 +105,20 @@ export class ToolbarItemComponent extends BaseComponent<HTMLDivElement> {
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
return `
|
||||
<div class="struct-prop container-icon-button" style="aspect-ratio: 1;" id="${this._getId()}">
|
||||
if (this._tooltip === null) {
|
||||
return `
|
||||
<div class="struct-prop container-icon-button " style="aspect-ratio: 1;" id="${this._getId()}">
|
||||
${this._iconSVG.outerHTML} ${this._label}
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
return `
|
||||
<div class="struct-prop container-icon-button hover-text" style="aspect-ratio: 1;" id="${this._getId()}">
|
||||
${this._iconSVG.outerHTML} ${this._label}
|
||||
<span class="tooltip-text left">${this._tooltip}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,8 @@ export class UI {
|
||||
})
|
||||
.isEnabled(() => {
|
||||
return Renderer.Get.getModelsAvailable() >= MeshType.TriangleMesh;
|
||||
}),
|
||||
})
|
||||
.setTooltip('View mesh'),
|
||||
'voxelMesh': new ToolbarItemComponent({ id: 'voxelMesh', iconSVG: AppIcons.VOXEL })
|
||||
.onClick(() => {
|
||||
Renderer.Get.setModelToUse(MeshType.VoxelMesh);
|
||||
@ -388,7 +389,8 @@ export class UI {
|
||||
})
|
||||
.isEnabled(() => {
|
||||
return Renderer.Get.getModelsAvailable() >= MeshType.VoxelMesh;
|
||||
}),
|
||||
})
|
||||
.setTooltip('View voxel mesh'),
|
||||
'blockMesh': new ToolbarItemComponent({ id: 'blockMesh', iconSVG: AppIcons.BLOCK })
|
||||
.onClick(() => {
|
||||
Renderer.Get.setModelToUse(MeshType.BlockMesh);
|
||||
@ -398,7 +400,8 @@ export class UI {
|
||||
})
|
||||
.isEnabled(() => {
|
||||
return Renderer.Get.getModelsAvailable() >= MeshType.BlockMesh;
|
||||
}),
|
||||
})
|
||||
.setTooltip('View block mesh'),
|
||||
},
|
||||
componentOrder: ['mesh', 'voxelMesh', 'blockMesh'],
|
||||
},
|
||||
@ -413,14 +416,16 @@ export class UI {
|
||||
})
|
||||
.isEnabled(() => {
|
||||
return Renderer.Get.getActiveMeshType() !== MeshType.None;
|
||||
}),
|
||||
})
|
||||
.setTooltip('Toggle grid'),
|
||||
'axes': new ToolbarItemComponent({ id: 'axes', iconSVG: AppIcons.AXES })
|
||||
.onClick(() => {
|
||||
Renderer.Get.toggleIsAxesEnabled();
|
||||
})
|
||||
.isActive(() => {
|
||||
return Renderer.Get.isAxesEnabled();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Toggle axes'),
|
||||
'night-vision': new ToolbarItemComponent({ id: 'night', iconSVG: AppIcons.BULB })
|
||||
.onClick(() => {
|
||||
Renderer.Get.toggleIsNightVisionEnabled();
|
||||
@ -430,7 +435,8 @@ export class UI {
|
||||
})
|
||||
.isEnabled(() => {
|
||||
return Renderer.Get.canToggleNightVision();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Toggle night vision'),
|
||||
},
|
||||
componentOrder: ['grid', 'axes', 'night-vision'],
|
||||
},
|
||||
@ -445,7 +451,8 @@ export class UI {
|
||||
})
|
||||
.isActive(() => {
|
||||
return Renderer.Get.isSliceViewerEnabled();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Toggle slice viewer'),
|
||||
'plus': new ToolbarItemComponent({ id: 'plus', iconSVG: AppIcons.PLUS })
|
||||
.onClick(() => {
|
||||
Renderer.Get.incrementSliceHeight();
|
||||
@ -453,7 +460,8 @@ export class UI {
|
||||
.isEnabled(() => {
|
||||
return Renderer.Get.isSliceViewerEnabled() &&
|
||||
Renderer.Get.canIncrementSliceHeight();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Decrement slice'),
|
||||
'minus': new ToolbarItemComponent({ id: 'minus', iconSVG: AppIcons.MINUS })
|
||||
.onClick(() => {
|
||||
Renderer.Get.decrementSliceHeight();
|
||||
@ -461,7 +469,8 @@ export class UI {
|
||||
.isEnabled(() => {
|
||||
return Renderer.Get.isSliceViewerEnabled() &&
|
||||
Renderer.Get.canDecrementSliceHeight();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Increment slice'),
|
||||
},
|
||||
componentOrder: ['slice', 'plus', 'minus'],
|
||||
},
|
||||
@ -476,15 +485,18 @@ export class UI {
|
||||
'zoomOut': new ToolbarItemComponent({ id: 'zout', iconSVG: AppIcons.MINUS })
|
||||
.onClick(() => {
|
||||
ArcballCamera.Get.onZoomOut();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Zoom out'),
|
||||
'zoomIn': new ToolbarItemComponent({ id: 'zin', iconSVG: AppIcons.PLUS })
|
||||
.onClick(() => {
|
||||
ArcballCamera.Get.onZoomIn();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Zoom in'),
|
||||
'reset': new ToolbarItemComponent({ id: 'reset', iconSVG: AppIcons.CENTRE })
|
||||
.onClick(() => {
|
||||
ArcballCamera.Get.reset();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Reset camera'),
|
||||
},
|
||||
componentOrder: ['zoomOut', 'zoomIn', 'reset'],
|
||||
},
|
||||
@ -496,14 +508,16 @@ export class UI {
|
||||
})
|
||||
.isActive(() => {
|
||||
return ArcballCamera.Get.isPerspective();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Perspective camera'),
|
||||
'orthographic': new ToolbarItemComponent({ id: 'orth', iconSVG: AppIcons.ORTHOGRAPHIC })
|
||||
.onClick(() => {
|
||||
ArcballCamera.Get.setCameraMode('orthographic');
|
||||
})
|
||||
.isActive(() => {
|
||||
return ArcballCamera.Get.isOrthographic();
|
||||
}),
|
||||
})
|
||||
.setTooltip('Orthographic camera'),
|
||||
},
|
||||
componentOrder: ['perspective', 'orthographic'],
|
||||
},
|
||||
|
@ -14,31 +14,24 @@ export namespace UIUtil {
|
||||
}
|
||||
|
||||
export function clearStyles(element: HTMLElement) {
|
||||
element.classList.remove('style-inactive-disabled');
|
||||
element.classList.remove('style-inactive-enabled');
|
||||
element.classList.remove('style-inactive-hover');
|
||||
element.classList.remove('style-active-disabled');
|
||||
element.classList.remove('style-active-enabled');
|
||||
element.classList.remove('style-active-hover');
|
||||
element.classList.remove('disabled');
|
||||
element.classList.remove('hover');
|
||||
element.classList.remove('active');
|
||||
}
|
||||
|
||||
export function updateStyles(element: HTMLElement, style: TStyleParams) {
|
||||
clearStyles(element);
|
||||
|
||||
let styleToApply = `style`;
|
||||
|
||||
styleToApply += style.isActive ? '-active' : '-inactive';
|
||||
|
||||
if (style.isEnabled) {
|
||||
if (style.isHovered) {
|
||||
styleToApply += '-hover';
|
||||
} else {
|
||||
styleToApply += '-enabled';
|
||||
}
|
||||
} else {
|
||||
styleToApply += '-disabled';
|
||||
if (style.isActive) {
|
||||
element.classList.add('active');
|
||||
}
|
||||
|
||||
element.classList.add(styleToApply);
|
||||
if (!style.isEnabled) {
|
||||
element.classList.add('disabled');
|
||||
}
|
||||
|
||||
if (style.isHovered && style.isEnabled) {
|
||||
element.classList.add('hover');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
88
styles.css
88
styles.css
@ -253,6 +253,9 @@ select {
|
||||
transition: width 0.2s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.struct-prop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -264,42 +267,49 @@ select {
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.style-inactive-disabled {
|
||||
.struct-prop.disabled {
|
||||
border-color: var(--gray-500);
|
||||
color: var(--text-dark);
|
||||
background: var(--gray-400);
|
||||
cursor: inherit;
|
||||
}
|
||||
.style-inactive-enabled {
|
||||
border-color: var(--gray-600);
|
||||
color: var(--text-standard);
|
||||
background: var(--gray-500);
|
||||
}
|
||||
.style-inactive-hover {
|
||||
|
||||
.struct-prop.hover {
|
||||
border-color: var(--gray-700);
|
||||
color: var(--text-light);
|
||||
background: var(--gray-600);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.style-active-disabled {
|
||||
.struct-prop:not(.disabled):not(.hover) {
|
||||
border-color: var(--gray-600);
|
||||
color: var(--text-standard);
|
||||
background: var(--gray-500);
|
||||
}
|
||||
|
||||
.struct-prop.active.disabled {
|
||||
border-color: var(--blue-450);
|
||||
color: var(--text-dim);
|
||||
background: var(--blue-400);
|
||||
cursor: inherit;
|
||||
}
|
||||
.style-active-enabled {
|
||||
border-color: var(--blue-600);
|
||||
color: var(--text-bright);
|
||||
background: var(--blue-500);
|
||||
}
|
||||
.style-active-hover {
|
||||
|
||||
.struct-prop.active.hover {
|
||||
border-color: var(--blue-700);
|
||||
color: var(--text-bright);
|
||||
background: var(--blue-600);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.struct-prop.active:not(.disabled):not(.hover) {
|
||||
border-color: var(--blue-600);
|
||||
color: var(--text-bright);
|
||||
background: var(--blue-500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.h-div {
|
||||
height: 0px;
|
||||
border-radius: 2px;
|
||||
@ -348,7 +358,7 @@ select {
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.spinbox-value.style-inactive-hover {
|
||||
.spinbox-value .inactive .hover {
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
@ -676,4 +686,52 @@ a {
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.tooltip-text {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--text-light);
|
||||
background-color: var(--gray-600);
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid var(--gray-700);
|
||||
transition: 0.15s;
|
||||
pointer-events: none;
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 0px 0px 16px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hover-text:hover:not(.disabled) .tooltip-text {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.top {
|
||||
top: -40px;
|
||||
left: -50%;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
top: 25px;
|
||||
left: -50%;
|
||||
}
|
||||
|
||||
.left {
|
||||
top: 1px;
|
||||
right: 120%;
|
||||
}
|
||||
|
||||
.right {
|
||||
top: 2px;
|
||||
left: 120%;
|
||||
}
|
||||
|
||||
.hover-text {
|
||||
position: relative;
|
||||
}
|
Loading…
Reference in New Issue
Block a user