« get me outta code hell

Optimize the h*ck out of ListScrollForm - 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/form
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2018-12-15 00:55:20 -0400
committerFlorrie <towerofnix@gmail.com>2018-12-15 00:55:20 -0400
commitd54498610d53e8c8a437a6adff0ced11b037afe7 (patch)
treec085125d820297452141fc992bb0294fe14ed6bf /ui/form
parentae2c9e19d72ecc701d9ce64ae44cbe1f1e77413b (diff)
Optimize the h*ck out of ListScrollForm
Diffstat (limited to 'ui/form')
-rw-r--r--ui/form/ListScrollForm.js138
1 files changed, 65 insertions, 73 deletions
diff --git a/ui/form/ListScrollForm.js b/ui/form/ListScrollForm.js
index d22cd35..0e230b5 100644
--- a/ui/form/ListScrollForm.js
+++ b/ui/form/ListScrollForm.js
@@ -26,41 +26,54 @@ module.exports = class ListScrollForm extends Form {
   fixLayout() {
     this.keepScrollInBounds()
 
+    const scrollItems = this.scrollItems
+
     // The scrollItems property represents the item to the very left of where
     // we've scrolled, so we know right away that none of those will be
-    // visible and we won't bother iterating over them.
-    const itemsPastScroll = this.inputs.slice(this.scrollItems)
-
-    // We do need to hide them, though.
-    const itemsBeforeScroll = this.inputs.slice(0, this.scrollItems)
-    for (const item of itemsBeforeScroll) {
-      item.visible = false
+    // visible and we won't bother iterating over them. We do need to hide
+    // them, though.
+    for (let i = 0; i < scrollItems; i++) {
+      this.inputs[i].visible = false
     }
 
-    // This variable stores how far along the respective axis (as defined by
-    // posProp) the next element should be.
+    // This variable stores how far along the respective axis (implied by
+    // layoutType) the next element should be.
     let nextPos = 0
 
-    this.sizeProp = this.getSizeProp()
+    let formEdge
+    if (this.layoutType === 'horizontal') {
+      formEdge = this.contentW
+    } else {
+      formEdge = this.contentH
+    }
 
-    for (const item of itemsPastScroll) {
+    for (let i = scrollItems; i < this.inputs.length; i++) {
+      const item = this.inputs[i]
       item.fixLayout()
 
-      item[this.posProp] = nextPos
-      nextPos += item[this.sizeProp]
+      const curPos = nextPos
+      let curSize
+      if (this.layoutType === 'horizontal') {
+        item.x = curPos
+        curSize = item.w
+      } else {
+        item.y = curPos
+        curSize = item.h
+      }
+      nextPos += curSize
 
       // By default, the item should be visible..
       item.visible = true
 
       // ..but the item's far edge is past the form's far edge, it isn't
       // fully visible and should be hidden.
-      if (item[this.posProp] + item[this.sizeProp] > this.formEdge) {
+      if (curPos + curSize > formEdge) {
         item.visible = false
       }
 
       // Same deal goes for the close edge. We can check it against 0 since
       // the close edge of the form's content is going to be 0, of course!
-      if (item[this.posProp] < 0) {
+      if (curPos < 0) {
         item.visible = false
       }
     }
@@ -129,10 +142,17 @@ module.exports = class ListScrollForm extends Form {
   scrollSelectedElementIntoView() {
     const sel = this.inputs[this.curIndex]
 
+    let formEdge
+    if (this.layoutType === 'horizontal') {
+      formEdge = this.contentW
+    } else {
+      formEdge = this.contentH
+    }
+
     // If the item is ahead of our view (either to the right of or below),
     // we should move the view so that the item is the farthest right (of all
     // the visible items).
-    if (this.getItemPos(sel) > this.formEdge + this.scrollSize) {
+    if (this.getItemPos(sel) > formEdge + this.scrollSize) {
       this.scrollElementIntoEndOfView(sel)
     }
 
@@ -158,21 +178,28 @@ module.exports = class ListScrollForm extends Form {
   getScrollPositionOfElementAtEndOfView(element) {
     // We can decide how many items to scroll past by moving forward until
     // the item's far edge is visible.
-    const pos = this.getItemPos(element);
-    let edge = this.formEdge
+    const pos = this.getItemPos(element)
+
+    let edge
+    if (this.layoutType === 'horizontal') {
+      edge = this.contentW
+    } else {
+      edge = this.contentH
+    }
+
     for (let i = 0; i < this.inputs.length; i++) {
       if (pos <= edge) {
-        return i;
+        return i
       }
 
-      if (this.sizeProp === 'w') {
-        edge += this.inputs[i].w;
+      if (this.layoutType === 'horizontal') {
+        edge += this.inputs[i].w
       } else {
-        edge += this.inputs[i].h;
+        edge += this.inputs[i].h
       }
     }
     // No result? Well, it's at the end.
-    return this.inputs.length;
+    return this.inputs.length
   }
 
   scrollElementIntoEndOfView(element) {
@@ -206,66 +233,31 @@ module.exports = class ListScrollForm extends Form {
   getItemPos(item) {
     // Gets the position of the item in an unscrolled view.
 
-    const index = this.inputs.indexOf(item);
-    let pos = 0;
+    const index = this.inputs.indexOf(item)
+    let pos = 0
     for (let i = 0; i <= index; i++) {
-      if (this.sizeProp === 'w') {
-        pos += this.inputs[i].w;
+      if (this.layoutType === 'horizontal') {
+        pos += this.inputs[i].w
       } else {
-        pos += this.inputs[i].h;
+        pos += this.inputs[i].h
       }
     }
-    return pos;
-  }
-
-  getSizeProp() {
-    // The property used to measure the size of an item. If the layoutType
-    // isn't valid (that is, 'horizontal' or 'vertical'), it'll return null.
-
-    return (
-      this.layoutType === 'horizontal' ? 'w' :
-      this.layoutType === 'vertical' ? 'h' :
-      null
-    )
-  }
-
-  get posProp() {
-    // The property used to position an item. Like sizeProp, returns null if
-    // the layoutType isn't valid.
-
-    return (
-      this.layoutType === 'horizontal' ? 'x' :
-      this.layoutType === 'vertical' ? 'y' :
-      null)
-  }
-
-  get edgeProp() {
-    // The property used to get the far edge of the property. As with
-    // sizeProp, if the layoutType doesn't have an expected value, it'll
-    // return null.
-
-    return (
-      this.layoutType === 'horizontal' ? 'right' :
-      this.layoutType === 'vertical' ? 'bottom' :
-      null)
-  }
-
-  get formEdge() {
-    // Returns the value of the far edge of this form. Items farther in the
-    // list (up to the edge) will be closer to this edge.
-
-    return (
-      this.layoutType === 'horizontal' ? this.contentW :
-      this.layoutType === 'vertical' ? this.contentH :
-      null)
+    return pos
   }
 
   get scrollSize() {
     // Gets the actual length made up by all of the items currently scrolled
     // past.
 
-    return this.inputs.slice(0, this.scrollItems)
-      .reduce((a, b) => a + b[this.sizeProp], 0)
+    let size = 0
+    for (let i = 0; i < this.scrollItems; i++) {
+      if (this.layoutType === 'horizontal') {
+        size += this.inputs[i].w
+      } else {
+        size += this.inputs[i].h
+      }
+    }
+    return size
   }
 
   get contentW() {