« get me outta code hell

Add WrapLabel UI element - tui-lib - Pure Node.js library for making visual command-line programs (ala vim, ncdu)
about summary refs log tree commit diff
path: root/ui
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2018-06-12 23:55:06 -0300
committerFlorrie <towerofnix@gmail.com>2018-06-12 23:55:06 -0300
commitc5b3a076963517c93b6596f3e0a860be1d80ef80 (patch)
tree83bf575df2adb45227c39437d545a87347bad808 /ui
parent5ca7837f83be3c3ea1081db150ece49875fa61a0 (diff)
Add WrapLabel UI element
Diffstat (limited to 'ui')
-rw-r--r--ui/Label.js17
-rw-r--r--ui/WrapLabel.js44
2 files changed, 56 insertions, 5 deletions
diff --git a/ui/Label.js b/ui/Label.js
index 850edc0..faeee98 100644
--- a/ui/Label.js
+++ b/ui/Label.js
@@ -5,20 +5,23 @@ const DisplayElement = require('./DisplayElement')
 module.exports = class Label extends DisplayElement {
   // A simple text display. Automatically adjusts size to fit text.
 
-  constructor(text='') {
+  constructor(text = '') {
     super()
 
     this.text = text
     this.textAttributes = []
   }
 
+  fixLayout() {
+    this.w = this.text.length
+  }
+
   drawTo(writable) {
     if (this.textAttributes.length) {
       writable.write(ansi.setAttributes(this.textAttributes))
     }
 
-    writable.write(ansi.moveCursor(this.absTop, this.absLeft))
-    writable.write(this.text)
+    this.writeTextTo(writable)
 
     if (this.textAttributes.length) {
       writable.write(ansi.resetAttributes())
@@ -27,10 +30,14 @@ module.exports = class Label extends DisplayElement {
     super.drawTo(writable)
   }
 
+  writeTextTo(writable) {
+    writable.write(ansi.moveCursor(this.absTop, this.absLeft))
+    writable.write(this.text)
+  }
+
   set text(newText) {
     this._text = newText
-
-    this.w = newText.length
+    this.fixLayout()
   }
 
   get text() {
diff --git a/ui/WrapLabel.js b/ui/WrapLabel.js
new file mode 100644
index 0000000..babf462
--- /dev/null
+++ b/ui/WrapLabel.js
@@ -0,0 +1,44 @@
+const ansi = require('../util/ansi')
+const wrap = require('word-wrap')
+
+const Label = require('./Label')
+
+module.exports = class WrapLabel extends Label {
+  // A word-wrapping text display. Given a width, wraps text to fit.
+
+  constructor(...args) {
+    super(...args)
+  }
+
+  fixLayout() {
+    // Override Label.fixLayout to do nothing. We don't want to make the
+    // width of this label be set to the content of the text! (That would
+    // defeat the entire point of word wrapping.)
+  }
+
+  writeTextTo(writable) {
+    const lines = this.getWrappedLines()
+    for (let i = 0; i < lines.length; i++) {
+      writable.write(ansi.moveCursor(this.absTop + i, this.absLeft))
+      writable.write(lines[i])
+    }
+  }
+
+  getWrappedLines() {
+    if (this.text.trim().length === 0) {
+      return []
+    }
+
+    const options = {width: this.w, indent: ''}
+    return wrap(this.text, options).split('\n')
+      .map(l => l.trim())
+  }
+
+  get h() {
+    return this.getWrappedLines().length
+  }
+
+  set h(newHeight) {
+    // Do nothing. Height is computed on the fly.
+  }
+}