-
Notifications
You must be signed in to change notification settings - Fork 176
/
ChannelSettingsPrompt.ts
131 lines (114 loc) · 6.3 KB
/
ChannelSettingsPrompt.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) John Nesky and contributing authors, distributed under the MIT license, see accompanying the LICENSE.md file.
import {Config} from "../synth/SynthConfig.js";
import {HTML} from "imperative-html/dist/esm/elements-strict.js";
import {SongDocument} from "./SongDocument.js";
import {Prompt} from "./Prompt.js";
import {ChangeGroup} from "./Change.js";
import {ChangePatternsPerChannel, ChangeInstrumentsFlags, ChangeChannelCount} from "./changes.js";
const {button, div, label, br, h2, input} = HTML;
export class ChannelSettingsPrompt implements Prompt {
private readonly _patternsStepper: HTMLInputElement = input({style: "width: 3em; margin-left: 1em;", type: "number", step: "1"});
private readonly _pitchChannelStepper: HTMLInputElement = input({style: "width: 3em; margin-left: 1em;", type: "number", step: "1"});
private readonly _drumChannelStepper: HTMLInputElement = input({style: "width: 3em; margin-left: 1em;", type: "number", step: "1"});
private readonly _layeredInstrumentsBox: HTMLInputElement = input({style: "width: 3em; margin-left: 1em;", type: "checkbox"});
private readonly _patternInstrumentsBox: HTMLInputElement = input({style: "width: 3em; margin-left: 1em;", type: "checkbox"});
private readonly _cancelButton: HTMLButtonElement = button({class: "cancelButton"});
private readonly _okayButton: HTMLButtonElement = button({class: "okayButton", style: "width:45%;"}, "Okay");
public readonly container: HTMLDivElement = div({class: "prompt noSelection", style: "width: 250px; text-align: right;"},
h2("Channel Settings"),
label({style: "display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},
"Pitch channels:",
this._pitchChannelStepper,
),
label({style: "display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},
"Drum channels:",
this._drumChannelStepper,
),
label({style: "display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},
"Available patterns per channel:",
this._patternsStepper,
),
label({style: "display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},
"Simultaneous instruments",
br(),
"per channel:",
this._layeredInstrumentsBox,
),
label({style: "display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},
"Different instruments",
br(),
"per pattern:",
this._patternInstrumentsBox,
),
div({style: "display: flex; flex-direction: row-reverse; justify-content: space-between;"},
this._okayButton,
),
this._cancelButton,
);
constructor(private _doc: SongDocument) {
this._patternsStepper.value = this._doc.song.patternsPerChannel + "";
this._patternsStepper.min = "1";
this._patternsStepper.max = Config.barCountMax + "";
this._pitchChannelStepper.value = this._doc.song.pitchChannelCount + "";
this._pitchChannelStepper.min = Config.pitchChannelCountMin + "";
this._pitchChannelStepper.max = Config.pitchChannelCountMax + "";
this._drumChannelStepper.value = this._doc.song.noiseChannelCount + "";
this._drumChannelStepper.min = Config.noiseChannelCountMin + "";
this._drumChannelStepper.max = Config.noiseChannelCountMax + "";
this._layeredInstrumentsBox.checked = this._doc.song.layeredInstruments;
this._patternInstrumentsBox.checked = this._doc.song.patternInstruments;
this._pitchChannelStepper.select();
setTimeout(()=>this._pitchChannelStepper.focus());
this._okayButton.addEventListener("click", this._saveChanges);
this._cancelButton.addEventListener("click", this._close);
this._patternsStepper.addEventListener("keypress", ChannelSettingsPrompt._validateKey);
this._pitchChannelStepper.addEventListener("keypress", ChannelSettingsPrompt._validateKey);
this._drumChannelStepper.addEventListener("keypress", ChannelSettingsPrompt._validateKey);
this._patternsStepper.addEventListener("blur", this._validateNumber);
this._pitchChannelStepper.addEventListener("blur", this._validateNumber);
this._drumChannelStepper.addEventListener("blur", this._validateNumber);
this.container.addEventListener("keydown", this._whenKeyPressed);
}
private _close = (): void => {
this._doc.undo();
}
public cleanUp = (): void => {
this._okayButton.removeEventListener("click", this._saveChanges);
this._cancelButton.removeEventListener("click", this._close);
this._patternsStepper.removeEventListener("keypress", ChannelSettingsPrompt._validateKey);
this._pitchChannelStepper.removeEventListener("keypress", ChannelSettingsPrompt._validateKey);
this._drumChannelStepper.removeEventListener("keypress", ChannelSettingsPrompt._validateKey);
this._patternsStepper.removeEventListener("blur", this._validateNumber);
this._pitchChannelStepper.removeEventListener("blur", this._validateNumber);
this._drumChannelStepper.removeEventListener("blur", this._validateNumber);
this.container.removeEventListener("keydown", this._whenKeyPressed);
}
private _whenKeyPressed = (event: KeyboardEvent): void => {
if ((<Element> event.target).tagName != "BUTTON" && event.keyCode == 13) { // Enter key
this._saveChanges();
}
}
private static _validateKey(event: KeyboardEvent): boolean {
const charCode = (event.which) ? event.which : event.keyCode;
if (charCode != 46 && charCode > 31 && (charCode < 48 || charCode > 57)) {
event.preventDefault();
return true;
}
return false;
}
private _validateNumber = (event: Event): void => {
const input: HTMLInputElement = <HTMLInputElement>event.target;
input.value = String(ChannelSettingsPrompt._validate(input));
}
private static _validate(input: HTMLInputElement): number {
return Math.floor(Math.max(Number(input.min), Math.min(Number(input.max), Number(input.value))));
}
private _saveChanges = (): void => {
const group: ChangeGroup = new ChangeGroup();
group.append(new ChangeInstrumentsFlags(this._doc, this._layeredInstrumentsBox.checked, this._patternInstrumentsBox.checked));
group.append(new ChangePatternsPerChannel(this._doc, ChannelSettingsPrompt._validate(this._patternsStepper)));
group.append(new ChangeChannelCount(this._doc, ChannelSettingsPrompt._validate(this._pitchChannelStepper), ChannelSettingsPrompt._validate(this._drumChannelStepper)));
this._doc.prompt = null;
this._doc.record(group, true);
}
}