« get me outta code hell

Mouse support - 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>2018-12-08 02:38:04 -0400
committerFlorrie <towerofnix@gmail.com>2018-12-08 02:38:04 -0400
commit7a4e4aa8afb341ba3e2b949f71b6c2a05f743831 (patch)
tree181a002ea35d9f2c4630fff5081ca4a066ece23b
parentc85e1da7a905d76ab1c59f42c810c12cf0322fb3 (diff)
Mouse support
'Cuz hey, why not?
-rwxr-xr-xindex.js2
m---------tui-lib0
-rw-r--r--ui.js77
3 files changed, 60 insertions, 19 deletions
diff --git a/index.js b/index.js
index d6dbcee..15392bd 100755
--- a/index.js
+++ b/index.js
@@ -67,6 +67,8 @@ async function main() {
   root.h = size.height
   root.fixAllLayout()
 
+  process.stdout.write(ansi.startTrackingMouse())
+
   const flushable = new Flushable(process.stdout, true)
   flushable.resizeScreen(size)
   flushable.shouldShowCompressionStatistics = process.argv.includes('--show-ansi-stats')
diff --git a/tui-lib b/tui-lib
-Subproject ab193ed3fe91078551c0020e681a191e7b26a12
+Subproject 1f434c1ef11fa55bab1718ea4e3ca8d115c0dfb
diff --git a/ui.js b/ui.js
index 2fdbaed..1a64253 100644
--- a/ui.js
+++ b/ui.js
@@ -781,6 +781,13 @@ class GrouplikeListingElement extends Form {
     this.root.select(this.form)
   }
 
+  clicked(button) {
+    if (button === 'left') {
+      this.selected()
+      return false
+    }
+  }
+
   get selectable() {
     return this.form.selectable
   }
@@ -1055,27 +1062,50 @@ class InteractiveGrouplikeItemElement extends BasicGrouplikeItemElement {
     } else if (telc.isCaselessLetter(keyBuf, 'x')) {
       this.emit('remove')
     } else if (telc.isCaselessLetter(keyBuf, 'm') || telc.isCaselessLetter(keyBuf, 'f')) {
-      const editMode = this.recordStore.app.editMode
-      const anyMarked = editMode && !!this.recordStore.app.markGrouplike.items.length
-      this.emit('menu', {
-        x: this.absLeft,
-        y: this.absTop + 1,
-        items: [
-          editMode && {label: this.isMarked ? 'Unmark' : 'Mark', action: () => this.emit('mark')},
-          anyMarked && {label: 'Paste (above)', action: () => this.emit('paste', {where: 'above'})},
-          anyMarked && {label: 'Paste (below)', action: () => this.emit('paste', {where: 'below'})},
-          // anyMarked && !this.isReal && {label: 'Paste', action: () => this.emit('paste')}, // No "above" or "elow" in the label because the "fake" item/row will be replaced (it'll disappear, since there'll be an item in the group)
-          {label: 'Play', action: () => this.emit('queue', {where: 'next', play: true})},
-          {label: 'Play next', action: () => this.emit('queue', {where: 'next'})},
-          {label: 'Play at end', action: () => this.emit('queue', {where: 'end'})},
-          this.isGroup && {label: 'Play next, shuffled', action: () => this.emit('queue', {where: 'next', shuffle: true})},
-          this.isGroup && {label: 'Play at end, shuffled', action: () => this.emit('queue', {where: 'end', shuffle: true})},
-          {label: 'Remove from queue', action: () => this.emit('unqueue')}
-        ]
-      })
+      this.showMenu()
     }
   }
 
+  clicked(button) {
+    if (button === 'left') {
+      if (this.isSelected) {
+        if (this.isGroup) {
+          this.emit('browse')
+        } else {
+          this.emit('queue', {where: 'next', play: true})
+        }
+      } else {
+        this.parent.selectInput(this)
+      }
+      return false
+    } else if (button === 'right') {
+      this.parent.selectInput(this)
+      this.showMenu()
+      return false
+    }
+  }
+
+  showMenu() {
+    const editMode = this.recordStore.app.editMode
+    const anyMarked = editMode && !!this.recordStore.app.markGrouplike.items.length
+    this.emit('menu', {
+      x: this.absLeft,
+      y: this.absTop + 1,
+      items: [
+        editMode && {label: this.isMarked ? 'Unmark' : 'Mark', action: () => this.emit('mark')},
+        anyMarked && {label: 'Paste (above)', action: () => this.emit('paste', {where: 'above'})},
+        anyMarked && {label: 'Paste (below)', action: () => this.emit('paste', {where: 'below'})},
+        // anyMarked && !this.isReal && {label: 'Paste', action: () => this.emit('paste')}, // No "above" or "elow" in the label because the "fake" item/row will be replaced (it'll disappear, since there'll be an item in the group)
+        {label: 'Play', action: () => this.emit('queue', {where: 'next', play: true})},
+        {label: 'Play next', action: () => this.emit('queue', {where: 'next'})},
+        {label: 'Play at end', action: () => this.emit('queue', {where: 'end'})},
+        this.isGroup && {label: 'Play next, shuffled', action: () => this.emit('queue', {where: 'next', shuffle: true})},
+        this.isGroup && {label: 'Play at end, shuffled', action: () => this.emit('queue', {where: 'end', shuffle: true})},
+        {label: 'Remove from queue', action: () => this.emit('unqueue')}
+      ]
+    })
+  }
+
   writeStatus(writable) {
     if (this.isGroup) {
       // The ANSI attributes here will apply to the rest of the line, too.
@@ -1164,7 +1194,10 @@ class ListingJumpElement extends Form {
 
 class PathElement extends ListScrollForm {
   constructor() {
-    super('horizontal')
+    // TODO: Once we've got the horizontal scrollbar draw working, perhaps
+    // enable this? Well probably not. This is more a TODO to just, well,
+    // implement that horizontal scrollbar drawing anyway.
+    super('horizontal', false)
     this.captureTab = false
   }
 
@@ -1217,6 +1250,12 @@ class PathItemElement extends FocusElement {
     this.root.select(this.button)
   }
 
+  clicked(button) {
+    if (button === 'left') {
+      this.emit('select')
+    }
+  }
+
   fixLayout() {
     this.button.fixLayout()
     this.arrowLabel.fixLayout()