From 742d2543b88ad4cbb2fc9a859f093a57f32c1967 Mon Sep 17 00:00:00 2001 From: Florrie Date: Thu, 17 Oct 2019 12:57:24 -0300 Subject: Make ScrollBar an independent and published class It's no longer strictly connected to a ListScrollForm, and is published, so it's much easier to use as an element from the tui-lib API in any project now. --- ui/form/ListScrollForm.js | 115 +++------------------------------------------- 1 file changed, 7 insertions(+), 108 deletions(-) (limited to 'ui/form/ListScrollForm.js') diff --git a/ui/form/ListScrollForm.js b/ui/form/ListScrollForm.js index 78c376f..72e79df 100644 --- a/ui/form/ListScrollForm.js +++ b/ui/form/ListScrollForm.js @@ -1,9 +1,8 @@ const ansi = require('../../util/ansi') const telc = require('../../util/telchars') -const unic = require('../../util/unichars') -const DisplayElement = require('../DisplayElement') const Form = require('./Form') +const ScrollBar = require('./ScrollBar') module.exports = class ListScrollForm extends Form { // A form that lets the user scroll through a list of items. It @@ -21,7 +20,12 @@ module.exports = class ListScrollForm extends Form { this.scrollBarEnabled = enableScrollBar - this.scrollBar = new ScrollBar(this) + this.scrollBar = new ScrollBar({ + getLayoutType: () => this.layoutType, + getCurrentScroll: () => this.scrollItems, + getMaximumScroll: () => this.getScrollItemsLength(), + getTotalItems: () => this.inputs.length + }) this.scrollBarShown = false } @@ -297,108 +301,3 @@ module.exports = class ListScrollForm extends Form { } } } - -class ScrollBar extends DisplayElement { - constructor(listScrollForm) { - super() - - this.listScrollForm = listScrollForm - } - - fixLayout() { - // Normally we'd subtract one from contentW/contentH when setting the x/y - // position, but the scrollbar is actually displayed OUTSIDE of (adjacent - // to) the parent's content area. - if (this.listScrollForm.layoutType === 'vertical') { - this.h = this.listScrollForm.contentH - this.w = 1 - this.x = this.listScrollForm.contentW - this.y = 0 - } else { - this.h = 1 - this.w = this.listScrollForm.contentW - this.x = 0 - this.y = this.listScrollForm.contentH - } - } - - drawTo(writable) { - // Uuuurgh - this.fixLayout() - - // TODO: Horizontal layout! Not functionally a lot different, but I'm too - // lazy to write a test UI for it right now. - - const { - backwards: canScrollBackwards, - forwards: canScrollForwards - } = this.getScrollableDirections() - - // - 2 for extra UI elements (arrows) - const totalLength = this.h - 2 - - // ..[-----].. - // ^start| - // ^end - // - // Start and end should correspond to how much of the scroll area - // is currently visible. So, if you can see 60% of the full scroll length - // at a time, and you are scrolled 10% down, the start position of the - // handle should be 10% down, and it should extend 60% of the scrollbar - // length, to the 70% mark. - - const currentScroll = this.listScrollForm.scrollItems - const edgeLength = this.listScrollForm.contentH - const totalItems = this.listScrollForm.inputs.length - const itemsVisibleAtOnce = Math.min(totalItems, edgeLength) - const handleLength = itemsVisibleAtOnce / totalItems * totalLength - let handlePosition = Math.floor(totalLength / totalItems * currentScroll) - - // Silly peeve of mine: The handle should only be visibly touching the top - // or bottom of the scrollbar area if you're actually scrolled all the way - // to the start or end. Otherwise, it shouldn't be touching! There should - // visible space indicating that you can scroll in that direction - // (in addition to the arrows we show at the ends). - - if (canScrollBackwards && handlePosition === 0) { - handlePosition = 1 - } - - if (canScrollForwards && (handlePosition + handleLength) === edgeLength) { - handlePosition-- - } - - if (this.listScrollForm.layoutType === 'vertical') { - const start = this.absTop + handlePosition + 1 - for (let i = 0; i < handleLength; i++) { - writable.write(ansi.moveCursor(start + i, this.absLeft)) - writable.write(unic.BOX_V_DOUBLE) - } - - if (canScrollBackwards) { - writable.write(ansi.moveCursor(this.absTop, this.absLeft)) - writable.write(unic.ARROW_UP_DOUBLE) - } - - if (canScrollForwards) { - writable.write(ansi.moveCursor(this.absBottom, this.absLeft)) - writable.write(unic.ARROW_DOWN_DOUBLE) - } - } - } - - getScrollableDirections() { - const currentScroll = this.listScrollForm.scrollItems - const totalScroll = this.listScrollForm.getScrollItemsLength() - - return { - backwards: (currentScroll > 0), - forwards: (currentScroll < totalScroll) - } - } - - canScrollAtAll() { - const {backwards, forwards} = this.getScrollableDirections() - return backwards || forwards - } -} -- cgit 1.3.0-6-gf8a5