« get me outta code hell

mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
path: root/ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui.js')
-rw-r--r--ui.js75
1 files changed, 68 insertions, 7 deletions
diff --git a/ui.js b/ui.js
index 1331344..bf67b8e 100644
--- a/ui.js
+++ b/ui.js
@@ -351,12 +351,13 @@ class AppElement extends FocusElement {
         return [
           {label: playingTrack ? `("${playingTrack.name}")` : '(No track playing.)'},
           {divider: true},
+          {element: this.loopModeControl},
+          {element: this.volumeSlider},
+          {divider: true},
           playingTrack && {element: this.playingControl},
-          {element: this.loopingControl},
-          {element: this.loopQueueControl},
-          {element: this.pauseNextControl},
+          playingTrack && {element: this.loopingControl},
+          playingTrack && {element: this.pauseNextControl},
           {element: this.autoDJControl},
-          {element: this.volumeSlider},
           {divider: true},
           previous && {label: `Previous (${previous.name})`, action: () => this.SQP.playPrevious(playingTrack)},
           next && {label: `Next (${next.name})`, action: () => this.SQP.playNext(playingTrack)},
@@ -403,6 +404,20 @@ class AppElement extends FocusElement {
       getEnabled: () => this.config.canControlPlayback
     })
 
+    this.loopModeControl = new InlineListPickerElement('Loop mode', [
+      {value: 'end', label: 'Don\'t loop'},
+      {value: 'loop', label: 'Loop (same order)'},
+      {value: 'shuffle', label: 'Loop (shuffle)'}
+    ], {
+      setValue: val => {
+        if (this.SQP) {
+          this.SQP.queueEndMode = val
+        }
+      },
+      getValue: () => this.SQP && this.SQP.queueEndMode,
+      showContextMenu: this.showContextMenu
+    })
+
     this.pauseNextControl = new ToggleControl('Pause when this track ends?', {
       setValue: val => this.SQP.setPauseNextTrack(val),
       getValue: () => this.SQP.pauseNextTrack,
@@ -3153,13 +3168,27 @@ class InlineListPickerElement extends FocusElement {
   // next or previous. (That's the point, it's inline.) This element is mainly
   // useful in forms or ContextMenus.
 
-  constructor(labelText, options, showContextMenu = null) {
+  constructor(labelText, options, optsOrShowContextMenu = null) {
     super()
+
     this.labelText = labelText
     this.options = options
-    this.showContextMenu = showContextMenu
-    this.curIndex = 0
+
+    if (typeof optsOrShowContextMenu === 'function') {
+      this.showContextMenu = optsOrShowContextMenu
+    }
+
+    if (typeof optsOrShowContextMenu === 'object') {
+      const opts = optsOrShowContextMenu
+      this.showContextMenu = opts.showContextMenu
+      this.getValue = opts.getValue
+      this.setValue = opts.setValue
+    }
+
     this.keyboardIdentifier = this.labelText
+
+    this.curIndex = 0
+    this.refreshValue()
   }
 
   fixLayout() {
@@ -3244,11 +3273,26 @@ class InlineListPickerElement extends FocusElement {
     return false
   }
 
+
+  refreshValue() {
+    if (this.getValue) {
+      const value = this.getValue()
+      const index = this.options.findIndex(opt => opt.value === value)
+      if (index >= 0) {
+        this.curIndex = index
+      }
+    }
+  }
+
   nextOption() {
     this.curIndex++
     if (this.curIndex === this.options.length) {
       this.curIndex = 0
     }
+
+    if (this.setValue) {
+      this.setValue(this.curValue)
+    }
   }
 
   previousOption() {
@@ -3256,6 +3300,10 @@ class InlineListPickerElement extends FocusElement {
     if (this.curIndex < 0) {
       this.curIndex = this.options.length - 1
     }
+
+    if (this.setValue) {
+      this.setValue(this.curValue)
+    }
   }
 
   get curValue() {
@@ -3453,6 +3501,9 @@ class ToggleControl extends FocusElement {
   }
 
 
+  // Note: ToggleControl doesn't specify refreshValue because it doesn't have an
+  // internal state for the current value. It sets and draws based on the value
+  // getter provided externally.
   toggle() {
     this.setValue(!this.getValue())
   }
@@ -4716,6 +4767,16 @@ class ContextMenu extends FocusElement {
       return
     }
 
+    // Call refreshValue() on any items before they're shown, for items that
+    // provide it. (This is handy when reusing the same input across a menu that
+    // might be shown under different contexts.)
+    for (const item of items) {
+      const el = item.element
+      if (!el) continue
+      if (!el.refreshValue) continue
+      el.refreshValue()
+    }
+
     if (!this.root.selectedElement.directAncestors.includes(this)) {
       this.selectedBefore = this.root.selectedElement
     }