diff options
Diffstat (limited to 'ui.js')
-rw-r--r-- | ui.js | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/ui.js b/ui.js index eb6b8f9..1bb74fc 100644 --- a/ui.js +++ b/ui.js @@ -235,6 +235,7 @@ class AppElement extends FocusElement { {divider: true}, this.playingTrack && {element: this.playingControl}, {element: this.loopingControl}, + {element: this.volumeSlider}, (next || previous) && {divider: true}, previous && {label: `Previous (${previous.name})`, action: () => this.playPreviousTrack(this.playingTrack)}, next && {label: `Next (${next.name})`, action: () => this.playNextTrack(this.playingTrack)}, @@ -263,6 +264,11 @@ class AppElement extends FocusElement { setValue: val => this.setLoop(val), getValue: () => this.player.isLooping }) + + this.volumeSlider = new SliderElement('Volume', { + setValue: val => this.setVolume(val), + getValue: () => this.player.volume + }) } selected() { @@ -720,6 +726,10 @@ class AppElement extends FocusElement { this.player.volDown(amount) } + setVolume(value) { + this.player.setVolume(value) + } + stopPlaying() { // We emit this so playTrack doesn't immediately start a new track. // We aren't *actually* about to play a new track. @@ -1822,6 +1832,132 @@ class InlineListPickerElement extends FocusElement { } } +class SliderElement extends FocusElement { + // Same general principle and usage as InlineListPickerElement, but for + // changing a numeric value. + + constructor(labelText, {setValue, getValue, maxValue = 100, percent = true}) { + super() + this.labelText = labelText + this.setValue = setValue + this.getValue = getValue + this.maxValue = maxValue + this.percent = percent + this.keyboardIdentifier = this.labelText + } + + fixLayout() { + const idealWidth = ansi.measureColumns( + this.labelText + + ' ' + this.getValueString(this.maxValue) + + ' ' + this.getNumString(this.maxValue) + + ' ' + ) + + this.w = Math.max(this.parent.contentW, idealWidth) + this.h = 1 + } + + drawTo(writable) { + if (this.isSelected) { + writable.write(ansi.invert()) + } + + let drawX = 0 + writable.write(ansi.moveCursor(this.absTop, this.absLeft)) + + writable.write(this.labelText + ' ') + drawX += ansi.measureColumns(this.labelText) + 1 + + writable.write(ansi.setAttributes([ansi.A_BRIGHT, ansi.C_BLUE])) + writable.write(' ') + drawX += 1 + + const valueString = this.getValueString(this.getValue()) + writable.write(valueString) + drawX += valueString.length + + const numString = this.getNumString(this.getValue()) + writable.write(' ' + numString + ' ') + drawX += numString.length + 2 + + writable.write(ansi.setForeground(ansi.C_RESET)) + writable.write(' '.repeat(Math.max(0, this.w - drawX))) + + writable.write(ansi.resetAttributes()) + } + + getValueString(value) { + const maxLength = 10 + + let length = Math.round(value / this.maxValue * maxLength) + + if (value < this.maxValue && length === maxLength) { + length-- + } + + if (value > 0 && length === 0) { + length++ + } + + return ( + '[' + + '-'.repeat(length) + + ' '.repeat(maxLength - length) + + ']' + ) + } + + getNumString(value) { + const maxValueString = Math.round(this.maxValue).toString() + const valueString = Math.round(value).toString() + const paddedString = valueString.padStart(maxValueString.length) + + return paddedString + (this.percent ? '%' : '') + } + + keyPressed(keyBuf) { + if (telc.isRight(keyBuf)) { + this.increment() + } else if (telc.isLeft(keyBuf)) { + this.decrement() + } else { + return true + } + return false + } + + clicked(button) { + if (button === 'left') { + if (this.isSelected) { + if (this.getValue() === this.maxValue) { + this.setValue(0) + } else { + this.increment() + } + } else { + this.root.select(this) + } + } else if (button === 'scroll-up') { + this.increment() + } else if (button === 'scroll-down') { + this.decrement() + } + } + + increment() { + this.setValue(this.getValue() + this.step) + } + + decrement() { + this.setValue(this.getValue() - this.step) + } + + get step() { + return this.maxValue / 10 + } +} + class ToggleControl extends FocusElement { constructor(labelText, {setValue, getValue}) { super() |