« get me outta code hell

Add basic Element class - tui-lib - Pure Node.js library for making visual command-line programs (ala vim, ncdu)
about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2019-09-16 10:34:40 -0300
committerFlorrie <towerofnix@gmail.com>2019-09-16 10:34:40 -0300
commiteb3b83fa2d56f3c85ac0d5c9b62223f6bd297940 (patch)
tree19b44f8249b56ec6d71f91ae83ce71c27a37be25
parent3b94a56ecad81980448cb1f7f78acd8e58ab0c67 (diff)
Add basic Element class
-rw-r--r--ui/DisplayElement.js73
-rw-r--r--ui/Element.js80
2 files changed, 82 insertions, 71 deletions
diff --git a/ui/DisplayElement.js b/ui/DisplayElement.js
index b27772e..fab957e 100644
--- a/ui/DisplayElement.js
+++ b/ui/DisplayElement.js
@@ -1,7 +1,7 @@
-const EventEmitter = require('events')
+const Element = require('./Element')
 const exception = require('../util/exception')
 
-module.exports = class DisplayElement extends EventEmitter {
+module.exports = class DisplayElement extends Element {
   // A general class that handles dealing with screen coordinates, the tree
   // of elements, and other common stuff.
   //
@@ -18,9 +18,6 @@ module.exports = class DisplayElement extends EventEmitter {
     this[DisplayElement.lastDrawValues] = {}
     this[DisplayElement.scheduledDraw] = false
 
-    this.children = []
-    this.parent = null
-
     this.visible = true
 
     this.x = 0
@@ -138,54 +135,6 @@ module.exports = class DisplayElement extends EventEmitter {
     Object.assign(this[DisplayElement.lastDrawValues], this[DisplayElement.drawValues])
   }
 
-  eachDescendant(fn) {
-    // Run a function on this element, all of its children, all of their
-    // children, etc.
-    fn(this)
-    for (const child of this.children) {
-      child.eachDescendant(fn)
-    }
-  }
-
-  addChild(child, afterIndex = this.children.length, {fixLayout = true} = {}) {
-    // TODO Don't let a direct ancestor of this be added as a child. Don't
-    // let itself be one of its childs either!
-
-    if (child === this) {
-      throw exception(
-        'EINVALIDHIERARCHY', 'An element cannot be a child of itself')
-    }
-
-    child.parent = this
-
-    if (afterIndex === this.children.length) {
-      this.children.push(child)
-    } else {
-      this.children.splice(afterIndex, 0, child)
-    }
-
-    if (fixLayout) {
-      child.fixLayout()
-    }
-  }
-
-  removeChild(child, {fixLayout = true} = {}) {
-    // Removes the given child element from the children list of this
-    // element. It won't be rendered in the future. If the given element
-    // isn't a direct child of this element, nothing will happen.
-
-    if (child.parent !== this) {
-      return
-    }
-
-    child.parent = null
-    this.children.splice(this.children.indexOf(child), 1)
-
-    if (fixLayout) {
-      this.fixLayout()
-    }
-  }
-
   centerInParent() {
     // Utility function to center this element in its parent. Must be called
     // only when it has a parent. Set the width and height of the element
@@ -247,24 +196,6 @@ module.exports = class DisplayElement extends EventEmitter {
     }
   }
 
-  get root() {
-    let el = this
-    while (el.parent) {
-      el = el.parent
-    }
-    return el
-  }
-
-  get directAncestors() {
-    const ancestors = []
-    let el = this
-    while (el.parent) {
-      el = el.parent
-      ancestors.push(el)
-    }
-    return ancestors
-  }
-
   getElementAt(x, y) {
     // Gets the topmost element at the provided absolute coordinate.
     // Note that elements which are not visible or have the clickThrough
diff --git a/ui/Element.js b/ui/Element.js
new file mode 100644
index 0000000..c5beb59
--- /dev/null
+++ b/ui/Element.js
@@ -0,0 +1,80 @@
+const EventEmitter = require('events')
+
+module.exports = class Element extends EventEmitter {
+  // The basic class containing methods for working with an element hierarchy.
+  // Generally speaking, you usually want to extend DisplayElement instead of
+  // this class.
+
+  constructor() {
+    super()
+
+    this.children = []
+    this.parent = null
+  }
+
+  eachDescendant(fn) {
+    // Run a function on this element, all of its children, all of their
+    // children, etc.
+    fn(this)
+    for (const child of this.children) {
+      child.eachDescendant(fn)
+    }
+  }
+
+  addChild(child, afterIndex = this.children.length, {fixLayout = true} = {}) {
+    // TODO Don't let a direct ancestor of this be added as a child. Don't
+    // let itself be one of its childs either!
+
+    if (child === this) {
+      throw exception(
+        'EINVALIDHIERARCHY', 'An element cannot be a child of itself')
+    }
+
+    child.parent = this
+
+    if (afterIndex === this.children.length) {
+      this.children.push(child)
+    } else {
+      this.children.splice(afterIndex, 0, child)
+    }
+
+    if (fixLayout) {
+      child.fixLayout()
+    }
+  }
+
+  removeChild(child, {fixLayout = true} = {}) {
+    // Removes the given child element from the children list of this
+    // element. It won't be rendered in the future. If the given element
+    // isn't a direct child of this element, nothing will happen.
+
+    if (child.parent !== this) {
+      return
+    }
+
+    child.parent = null
+    this.children.splice(this.children.indexOf(child), 1)
+
+    if (fixLayout) {
+      this.fixLayout()
+    }
+  }
+
+  get root() {
+    let el = this
+    while (el.parent) {
+      el = el.parent
+    }
+    return el
+  }
+
+  get directAncestors() {
+    const ancestors = []
+    let el = this
+    while (el.parent) {
+      el = el.parent
+      ancestors.push(el)
+    }
+    return ancestors
+  }
+}