« get me outta code hell

Label (tag) drawing system - mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2019-08-22 14:02:41 -0300
committerFlorrie <towerofnix@gmail.com>2019-08-22 14:02:41 -0300
commit40db0f1eb92af07cf12a5f28ce8bc3930bd6c6b0 (patch)
treedc7a3abc28ee9677905f56984ed6ec61f7ca8bae
parentc9f3eac0197a1d7469b3a9cf64351a8fb0bcba5b (diff)
Label (tag) drawing system
m---------tui-lib0
-rw-r--r--ui.js111
2 files changed, 105 insertions, 6 deletions
diff --git a/tui-lib b/tui-lib
-Subproject d809ba2081041504998ad3b77c66b24e051f945
+Subproject ddd817edd8d78311f811f3d0d06b138c0b29555
diff --git a/ui.js b/ui.js
index 19200e7..076974f 100644
--- a/ui.js
+++ b/ui.js
@@ -1539,13 +1539,28 @@ class BasicGrouplikeItemElement extends Button {
     return this._rightText
   }
 
+  getFormattedRightText() {
+    return this.rightText
+  }
+
+  getRightTextColumns() {
+    return ansi.measureColumns(this.rightText)
+  }
+
+  getMinLeftTextColumns() {
+    return 12
+  }
+
+  getLeftPadding() {
+    return 2
+  }
+
   computeText() {
-    // 3 = width of status line, basically
-    let w = this.w - this.x - 3
+    let w = this.w - this.x - this.getLeftPadding()
 
     // Also make space for the right text - if we choose to show it.
-    const rightTextCols = ansi.measureColumns(this.rightText)
-    const showRightText = (w - rightTextCols > 12)
+    const rightTextCols = this.getRightTextColumns()
+    const showRightText = (w - rightTextCols > this.getMinLeftTextColumns())
     if (showRightText) {
       w -= rightTextCols
     }
@@ -1558,7 +1573,7 @@ class BasicGrouplikeItemElement extends Button {
     }
 
     if (showRightText) {
-      text += this.rightText
+      text += this.getFormattedRightText()
     }
 
     text += ansi.resetAttributes()
@@ -1933,20 +1948,104 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
     this.item = item
     this.app = app
     this.hideMetadata = false
+    this.expandLabels = false
+    this.labelsSelected = false
   }
 
   drawTo(writable) {
+    this.rightText = ''
     if (!this.hideMetadata) {
       const metadata = this.app.backend.getMetadataFor(this.item)
       if (metadata) {
         const durationString = getTimeStringsFromSec(0, metadata.duration).duration
-        this.rightText = ` (${durationString}) `
+        this.rightText = `(${durationString}) `
       }
     }
 
     super.drawTo(writable)
   }
 
+  selected() {
+    this.computeText()
+  }
+
+  getLabelTexts() {
+    const separator = this.isSelected ? '' : ''
+    let labels = []
+    // let labels = ['Voice', 'Woof']
+    if (this.expandLabels && this.labelsSelected) {
+      labels = ['+', ...labels]
+    }
+    return labels.map((label, i) => {
+      return [
+        label,
+        separator + (this.expandLabels ? ' ' + label + ' ' : label[0])
+      ]
+    })
+  }
+
+  getLabelColor(label) {
+    if (label === '+') {
+      return ansi.C_BLACK
+    } else {
+      return 30 + (label.charCodeAt(0) % 7)
+    }
+  }
+
+  getFormattedRightText() {
+    const labelTexts = this.getLabelTexts()
+
+    if (labelTexts.length) {
+      const lastColor = this.getLabelColor(labelTexts[labelTexts.length - 1][0])
+      return (this.isSelected ? ' ' : '') +
+        ansi.resetAttributes() +
+        (this.isSelected ? '' : ' ') +
+        ansi.setAttributes(this.isSelected ? [ansi.A_BRIGHT, 7] : []) +
+        labelTexts.map(([ label, labelText ], i, arr) => {
+          let text = ''
+
+          if (this.isSelected) {
+            text += ansi.setBackground(this.getLabelColor(label))
+          } else {
+            text += ansi.setForeground(this.getLabelColor(label))
+          }
+
+          text += labelText[0]
+
+          // text += ansi.resetAttributes()
+          text += ansi.setForeground(ansi.C_RESET)
+          text += ansi.setBackground(this.getLabelColor(label))
+
+          text += labelText.slice(1)
+
+          return text
+        }).join('') +
+        ansi.setAttributes([ansi.A_RESET, this.isSelected ? 0 : lastColor]) +
+        '▎' +
+        ansi.resetAttributes() +
+        super.getFormattedRightText()
+    } else {
+      return super.getFormattedRightText()
+    }
+  }
+
+  getRightTextColumns() {
+    const labelTexts = this.getLabelTexts()
+
+    return labelTexts
+      .reduce((acc, [l, lt]) => acc + lt.length, 0) +
+      (labelTexts.length ? 2 : 0) +
+      super.getRightTextColumns()
+  }
+
+  getMinLeftTextColumns() {
+    return this.expandLabels ? 0 : super.getMinLeftTextColumns()
+  }
+
+  getLeftPadding() {
+    return 3
+  }
+
   keyPressed(keyBuf) {
     if (input.isDownload(keyBuf)) {
       this.emit('download')