diff options
author | Florrie <towerofnix@gmail.com> | 2018-06-04 10:14:14 -0300 |
---|---|---|
committer | Florrie <towerofnix@gmail.com> | 2018-06-04 10:14:14 -0300 |
commit | 87819e1082d0edc28bbf38eded57ab992083458e (patch) | |
tree | 8664c720327d1ec4666189ee30d4f8b21f2d6e94 | |
parent | 1e6509ff61903b263b8c4afca79e71d659206cf3 (diff) |
Path listing
-rw-r--r-- | todo.txt | 1 | ||||
m--------- | tui-lib | 0 | ||||
-rw-r--r-- | ui.js | 109 |
3 files changed, 107 insertions, 3 deletions
diff --git a/todo.txt b/todo.txt index 42a5058..f682a1a 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,7 @@ TODO: A way to see the path of the currently selected item in any grouplike element. Each item in the path should be a button that, when pressed, makes the MAIN grouplike view navigate there. + (Done!) TODO: A "shuffle queue" button! diff --git a/tui-lib b/tui-lib -Subproject eae9716c237ad7c9602cc05f6babc6c2714e258 +Subproject a3df7cf7205d12ab5e6fc7b5746cae6c4a6a821 diff --git a/ui.js b/ui.js index 8e235a0..3090873 100644 --- a/ui.js +++ b/ui.js @@ -1,6 +1,6 @@ const { getDownloaderFor } = require('./downloaders') const { getPlayer } = require('./players') -const { parentSymbol, isGroup } = require('./playlist-utils') +const { parentSymbol, isGroup, isTrack, getItemPath } = require('./playlist-utils') const ansi = require('./tui-lib/util/ansi') const Button = require('./tui-lib/ui/form/Button') const DisplayElement = require('./tui-lib/ui/DisplayElement') @@ -48,6 +48,21 @@ class AppElement extends FocusElement { () => handleSelectFromMain(item))) this.grouplikeListingElement.on('queue', item => this.queueGrouplikeItem(item)) + const handleSelectFromPathElement = item => { + this.form.curIndex = this.form.inputs.indexOf(this.grouplikeListingElement) + this.root.select(this.grouplikeListingElement) + if (isGroup(item)) { + this.grouplikeListingElement.loadGrouplike(item) + } else if (item[parentSymbol]) { + this.grouplikeListingElement.loadGrouplike(item[parentSymbol]) + this.grouplikeListingElement.selectAndShow(item) + } + } + + this.paneLeft.addChild(this.grouplikeListingElement.pathElement) + this.form.addInput(this.grouplikeListingElement.pathElement, false) + this.grouplikeListingElement.pathElement.on('select', item => handleSelectFromPathElement(item)) + this.queueListingElement = new GrouplikeListingElement(this.recordStore) this.queueListingElement.loadGrouplike(this.queueGrouplike) this.paneRight.addChild(this.queueListingElement) @@ -57,6 +72,10 @@ class AppElement extends FocusElement { this.queueListingElement.on('select (space)', item => this.handleSpacePressed( () => this.playGrouplikeItem(item, false))) + this.paneRight.addChild(this.queueListingElement.pathElement) + this.form.addInput(this.queueListingElement.pathElement, false) + this.queueListingElement.pathElement.on('select', item => handleSelectFromPathElement(item)) + this.playbackPane = new Pane() this.addChild(this.playbackPane) @@ -89,8 +108,16 @@ class AppElement extends FocusElement { this.playbackPane.w = this.contentW this.playbackPane.h = this.contentH - this.playbackPane.y - this.grouplikeListingElement.fillParent() - this.queueListingElement.fillParent() + const fixListingLayout = listing => { + listing.fillParent() + listing.h-- + listing.pathElement.y = listing.parent.contentH - 1 + listing.pathElement.w = listing.parent.contentW + } + + fixListingLayout(this.grouplikeListingElement) + fixListingLayout(this.queueListingElement) + this.playbackInfoElement.fillParent() } @@ -318,6 +345,8 @@ class GrouplikeListingElement extends ListScrollForm { this.grouplike = null this.recordStore = recordStore + + this.pathElement = new PathElement() } keyPressed(keyBuf) { @@ -409,6 +438,18 @@ class GrouplikeListingElement extends ListScrollForm { } } + set curIndex(newIndex) { + this._curIndex = newIndex + + if (this.pathElement && this.inputs[this.curIndex]) { + this.pathElement.showItem(this.inputs[this.curIndex].item) + } + } + + get curIndex() { + return this._curIndex + } + get firstItemIndex() { return Math.min(this.inputs.length, 1) } @@ -486,6 +527,68 @@ class GrouplikeItemElement extends Button { } } +class PathElement extends ListScrollForm { + constructor() { + super('horizontal') + this.captureTab = false + } + + showItem(item) { + while (this.inputs.length) { + this.removeInput(this.inputs[0]) + } + + if (!isTrack(item) && !isGroup(item)) { + return + } + + const itemPath = getItemPath(item) + + for (const pathItem of itemPath) { + const isLast = pathItem === itemPath[itemPath.length - 1] + const element = new PathItemElement(pathItem, isLast) + element.on('select', () => this.emit('select', pathItem)) + element.fixLayout() + this.addInput(element) + } + + this.curIndex = this.inputs.length - 1 + + this.scrollToEnd() + this.fixLayout() + } +} + +class PathItemElement extends FocusElement { + constructor(item, isLast) { + super() + + this.item = item + this.isLast = isLast + + this.button = new Button(item.name || '(Unnamed)') + this.addChild(this.button) + + this.button.on('pressed', () => { + this.emit('select') + }) + + this.arrowLabel = new Label(isLast ? '' : ' > ') + this.addChild(this.arrowLabel) + } + + focused() { + this.root.select(this.button) + } + + fixLayout() { + this.button.fixLayout() + this.arrowLabel.fixLayout() + this.w = this.button.w + this.arrowLabel.w + this.arrowLabel.x = this.button.right + } +} + class PlaybackInfoElement extends DisplayElement { constructor() { super() |