« get me outta code hell

Dynamically create context menu instead of reusing - 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-25 18:02:35 -0300
committerFlorrie <towerofnix@gmail.com>2019-08-25 18:02:35 -0300
commit59d4eb91315b39e2ef4a46045cc6cbe2fd5657b2 (patch)
tree64b2eed690c4d45cf27ff3050a4f7843cf045c78
parent7bbda09051f06b2bed7d439143960a0a88199d10 (diff)
Dynamically create context menu instead of reusing
...a single one. This is working towards letting multiple context menus
be open at once.
-rw-r--r--ui.js42
1 files changed, 28 insertions, 14 deletions
diff --git a/ui.js b/ui.js
index f382cb2..6d49649 100644
--- a/ui.js
+++ b/ui.js
@@ -165,9 +165,10 @@ class AppElement extends FocusElement {
     this.editMode = false
 
     // We add this is a child later (so that it's on top of every element).
-    this.menu = new ContextMenu()
+    this.menuLayer = new DisplayElement()
+    this.showContextMenu = this.showContextMenu.bind(this)
 
-    this.menubar = new Menubar(this.menu)
+    this.menubar = new Menubar(this.showContextMenu)
     this.addChild(this.menubar)
 
     this.menubar.color = this.config.menubarColor
@@ -246,7 +247,7 @@ class AppElement extends FocusElement {
     this.setupDialog(this.alertDialog)
 
     // Should be placed on top of everything else!
-    this.addChild(this.menu)
+    this.addChild(this.menuLayer)
 
     this.whereControl = new InlineListPickerElement('Where?', [
       {value: 'next', label: 'After current song'},
@@ -491,6 +492,13 @@ class AppElement extends FocusElement {
     grouplikeListing.on('menu', (item, el) => this.showMenuForItemElement(el, grouplikeListing))
   }
 
+  showContextMenu(opts) {
+    const menu = new ContextMenu()
+    this.menuLayer.addChild(menu)
+    menu.show(opts)
+    return menu
+  }
+
   reveal(item) {
     if (!this.paneLeft.visible) {
       return
@@ -635,7 +643,7 @@ class AppElement extends FocusElement {
       ]
     }
 
-    this.menu.show({
+    this.showContextMenu({
       x: el.absLeft,
       y: el.absTop + 1,
       items
@@ -779,6 +787,8 @@ class AppElement extends FocusElement {
     this.updateQueueLengthLabel()
 
     this.playbackInfoElement.fillParent()
+
+    this.menuLayer.fillParent()
   }
 
   alignPartyLabel() {
@@ -2956,13 +2966,17 @@ class ContextMenu extends FocusElement {
 
   unselected() {
     this.selectedBefore = this.root.selectedElement
-    this.close()
+    if (this.visible) {
+      this.close()
+    }
   }
 
   close() {
     this.clearItems()
     this.visible = false
-    this.root.select(this.selectedBefore)
+    this.selectedBefore.root.select(this.selectedBefore)
+    this.parent.removeChild(this)
+    this.emit('closed')
   }
 
   clearItems() {
@@ -3126,10 +3140,11 @@ class KeyboardSelector {
 }
 
 class Menubar extends ListScrollForm {
-  constructor(contextMenu) {
+  constructor(showContextMenu) {
     super('horizontal')
 
-    this.contextMenu = contextMenu
+    this.showContextMenu = showContextMenu
+    this.contextMenu = null
     this.color = 4 // blue
     this.attribute = 2 // dim
   }
@@ -3137,7 +3152,7 @@ class Menubar extends ListScrollForm {
   select() {
     // The context menu disappears when it's deselected, so we really want to
     // use whatever element was selected before the menu was opened.
-    if (this.contextMenu.isSelected) {
+    if (this.contextMenu && this.contextMenu.isSelected) {
       // ...Unless it was the menubar that was already selected.
       if (!this.contextMenu.selectedBefore.directAncestors.includes(this)) {
         this.selectedBefore = this.contextMenu.selectedBefore
@@ -3149,10 +3164,6 @@ class Menubar extends ListScrollForm {
     this.root.select(this)
   }
 
-  selected() {
-    super.selected()
-  }
-
   keyPressed(keyBuf) {
     super.keyPressed(keyBuf)
 
@@ -3191,10 +3202,13 @@ class Menubar extends ListScrollForm {
       container.selected = () => this.root.select(button)
 
       button.on('pressed', () => {
-        this.contextMenu.show({
+        this.contextMenu = this.showContextMenu({
           x: container.absLeft, y: container.absY + 1,
           items: menuFn ? menuFn() : menuItems
         })
+        this.contextMenu.on('closed', () => {
+          this.contextMenu = null
+        })
       })
 
       this.addInput(container)