refactor: loads of sensible renaming

This commit is contained in:
Daniel Ledda
2022-04-03 14:29:56 +02:00
parent 1bfcd91132
commit 5b8e160608
31 changed files with 1364 additions and 1302 deletions

65
src/ui/Track/Track.css Normal file
View File

@@ -0,0 +1,65 @@
.track > * {
padding-right: 1em;
padding-left: 1em;
}
.vertical-mode .track > * {
padding-right: 0;
padding-left: 0;
}
.track-unit-block {
height: 2em;
}
.vertical-mode .track-unit-block {
height: auto;
width: 2em;
}
.track-title {
width: 3em;
line-height: 32px;
margin: 0;
}
.vertical-mode .track-title {
display: block;
width: auto;
text-align: center;
}
.track-spacer {
display: inline-block;
width: 1em;
height: 2em;
}
.vertical-mode .track-spacer {
display: block;
width: 2em;
height: 1em;
}
.track-main {
display: inline-flex;
}
.vertical-mode .track-main {
width: 2em;
margin-right: 4px;
display: block;
}
.track-settings-container {
display: flex;
}
.track {
width: max-content;
margin-bottom: 4px;
}
.vertical-mode .track {
display: inline-block;
}

177
src/ui/Track/TrackView.ts Normal file
View File

@@ -0,0 +1,177 @@
import UINode, {h, UINodeOptions} from "@/ui/UINode";
import Track, {TrackEvents} from "@/Track";
import ISubscriber from "@/Subscriber";
import TrackUnitView from "@/ui/TrackUnit/TrackUnitView";
import "./Track.css";
import {ISubscription} from "@/Publisher";
import Ref from "@/Ref";
export type TrackUINodeOptions = UINodeOptions & {
track: Track,
};
const EventTypeSubscriptions = [
TrackEvents.NewName,
TrackEvents.NewTimeSig,
TrackEvents.NewBarCount,
TrackEvents.DisplayTypeChanged,
TrackEvents.LoopLengthChanged,
];
type EventTypeSubscriptions = FlatArray<typeof EventTypeSubscriptions, 1>;
export default class TrackView extends UINode implements ISubscriber<EventTypeSubscriptions> {
private track!: Track;
private title = Ref.new<HTMLHeadingElement | null>(null);
private trackUnitViews: TrackUnitView[] = [];
private trackUnitViewBlock: HTMLElement | null = null;
private lastHoveredTrackUnitView: TrackUnitView | null = null;
private sub: ISubscription | null = null;
static deselectingUnits = false;
static selectingUnits = false;
constructor(options: TrackUINodeOptions) {
super(options);
this.setBeat(options.track);
}
setBeat(track: Track | null): void {
if (track) {
this.track = track;
this.sub?.unbind();
this.sub = this.track.addSubscriber(this, EventTypeSubscriptions);
this.redraw();
} else {
this.sub?.unbind();
}
}
notify(publisher: unknown, event: EventTypeSubscriptions): void {
switch (event) {
case TrackEvents.NewName:
this.title.val!.innerText = this.track.getName();
break;
case TrackEvents.NewTimeSig:
case TrackEvents.NewBarCount:
case TrackEvents.DisplayTypeChanged:
case TrackEvents.LoopLengthChanged:
this.setupTrackUnits();
break;
}
}
private rebuildTrackUnitViews() {
const trackUnitCount = this.track.getBarCount() * this.track.getTimeSigUp();
for (let i = 0; i < trackUnitCount; i++) {
const trackUnit = this.track.getUnitByIndex(i);
if (trackUnit) {
let view: TrackUnitView;
if (this.trackUnitViews[i]) {
view = this.trackUnitViews[i];
view.setUnit(trackUnit);
} else {
view = new TrackUnitView({trackUnit});
this.trackUnitViews.push(view);
view.onHover(() => this.onBeatViewHover(view));
view.onMouseDown((event: MouseEvent) => this.onTrackUnitClick(event.button, i));
}
}
}
const deadViews = this.trackUnitViews.splice(trackUnitCount, this.trackUnitViews.length - trackUnitCount);
deadViews.forEach(trackUnitView => trackUnitView.setUnit(null));
}
private onTrackUnitClick(button: number, index: number) {
if (button === 0) {
TrackView.selectingUnits = true;
this.track.getUnitByIndex(index)?.toggle();
} else if (button === 2) {
TrackView.deselectingUnits = true;
this.track.getUnitByIndex(index)?.setOn(false);
}
}
private onBeatViewHover(trackView: TrackUnitView) {
this.lastHoveredTrackUnitView = trackView;
if (TrackView.selectingUnits) {
this.lastHoveredTrackUnitView.turnOn();
} else if (TrackView.deselectingUnits) {
this.lastHoveredTrackUnitView.turnOff();
}
}
private buildTrackUnitViewBlock(): void {
const trackUnitNodes: HTMLElement[] = [];
for (let i = 0; i < this.trackUnitViews.length; i++) {
trackUnitNodes.push(this.trackUnitViews[i].render());
}
if (this.trackUnitViewBlock) {
this.trackUnitViewBlock.replaceChildren(...trackUnitNodes);
} else {
this.trackUnitViewBlock = h("div", {
classes: ["track-unit-block"],
}, [
...trackUnitNodes
]);
}
}
private respaceTrackUnits(): void {
if (!this.trackUnitViewBlock) {
return;
}
this.trackUnitViewBlock.querySelectorAll(".unit-spacer").forEach(spacer => spacer.remove());
const barLength = this.track.getTimeSigUp();
const barCount = this.track.getBarCount();
let bars = 0;
let i = -1;
let spacersInserted = false;
while (!spacersInserted) {
i += barLength;
const newSpacer = h("div", {classes: ["track-spacer"]});
const leftNeighbour = this.trackUnitViewBlock.children.item(i);
if (leftNeighbour) {
leftNeighbour.insertAdjacentElement("afterend", newSpacer);
} else {
break;
}
i++;
bars++;
if (bars === barCount) {
spacersInserted = true;
}
}
}
private setupTrackUnits(): void {
this.rebuildTrackUnitViews();
this.buildTrackUnitViewBlock();
this.respaceTrackUnits();
}
build(): HTMLElement {
this.setupTrackUnits();
if (!this.trackUnitViewBlock) {
throw new Error("Beat unit block setup failed!");
}
return h("div", {
classes: ["track"],
}, [
h("div", {
classes: ["track-main"],
}, [
h("h3", {
innerText: this.track.getName(),
saveTo: this.title,
classes: ["track-title"],
}),
this.trackUnitViewBlock,
]),
]);
}
}
window.addEventListener("mouseup", () => {
TrackView.selectingUnits = false;
TrackView.deselectingUnits = false;
});