From d54498610d53e8c8a437a6adff0ced11b037afe7 Mon Sep 17 00:00:00 2001 From: Florrie Date: Sat, 15 Dec 2018 00:55:20 -0400 Subject: Optimize the h*ck out of ListScrollForm --- ui/form/ListScrollForm.js | 138 ++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 73 deletions(-) diff --git a/ui/form/ListScrollForm.js b/ui/form/ListScrollForm.js index d22cd35..0e230b5 100644 --- a/ui/form/ListScrollForm.js +++ b/ui/form/ListScrollForm.js @@ -26,41 +26,54 @@ module.exports = class ListScrollForm extends Form { fixLayout() { this.keepScrollInBounds() + const scrollItems = this.scrollItems + // The scrollItems property represents the item to the very left of where // we've scrolled, so we know right away that none of those will be - // visible and we won't bother iterating over them. - const itemsPastScroll = this.inputs.slice(this.scrollItems) - - // We do need to hide them, though. - const itemsBeforeScroll = this.inputs.slice(0, this.scrollItems) - for (const item of itemsBeforeScroll) { - item.visible = false + // visible and we won't bother iterating over them. We do need to hide + // them, though. + for (let i = 0; i < scrollItems; i++) { + this.inputs[i].visible = false } - // This variable stores how far along the respective axis (as defined by - // posProp) the next element should be. + // This variable stores how far along the respective axis (implied by + // layoutType) the next element should be. let nextPos = 0 - this.sizeProp = this.getSizeProp() + let formEdge + if (this.layoutType === 'horizontal') { + formEdge = this.contentW + } else { + formEdge = this.contentH + } - for (const item of itemsPastScroll) { + for (let i = scrollItems; i < this.inputs.length; i++) { + const item = this.inputs[i] item.fixLayout() - item[this.posProp] = nextPos - nextPos += item[this.sizeProp] + const curPos = nextPos + let curSize + if (this.layoutType === 'horizontal') { + item.x = curPos + curSize = item.w + } else { + item.y = curPos + curSize = item.h + } + nextPos += curSize // By default, the item should be visible.. item.visible = true // ..but the item's far edge is past the form's far edge, it isn't // fully visible and should be hidden. - if (item[this.posProp] + item[this.sizeProp] > this.formEdge) { + if (curPos + curSize > formEdge) { item.visible = false } // Same deal goes for the close edge. We can check it against 0 since // the close edge of the form's content is going to be 0, of course! - if (item[this.posProp] < 0) { + if (curPos < 0) { item.visible = false } } @@ -129,10 +142,17 @@ module.exports = class ListScrollForm extends Form { scrollSelectedElementIntoView() { const sel = this.inputs[this.curIndex] + let formEdge + if (this.layoutType === 'horizontal') { + formEdge = this.contentW + } else { + formEdge = this.contentH + } + // If the item is ahead of our view (either to the right of or below), // we should move the view so that the item is the farthest right (of all // the visible items). - if (this.getItemPos(sel) > this.formEdge + this.scrollSize) { + if (this.getItemPos(sel) > formEdge + this.scrollSize) { this.scrollElementIntoEndOfView(sel) } @@ -158,21 +178,28 @@ module.exports = class ListScrollForm extends Form { getScrollPositionOfElementAtEndOfView(element) { // We can decide how many items to scroll past by moving forward until // the item's far edge is visible. - const pos = this.getItemPos(element); - let edge = this.formEdge + const pos = this.getItemPos(element) + + let edge + if (this.layoutType === 'horizontal') { + edge = this.contentW + } else { + edge = this.contentH + } + for (let i = 0; i < this.inputs.length; i++) { if (pos <= edge) { - return i; + return i } - if (this.sizeProp === 'w') { - edge += this.inputs[i].w; + if (this.layoutType === 'horizontal') { + edge += this.inputs[i].w } else { - edge += this.inputs[i].h; + edge += this.inputs[i].h } } // No result? Well, it's at the end. - return this.inputs.length; + return this.inputs.length } scrollElementIntoEndOfView(element) { @@ -206,66 +233,31 @@ module.exports = class ListScrollForm extends Form { getItemPos(item) { // Gets the position of the item in an unscrolled view. - const index = this.inputs.indexOf(item); - let pos = 0; + const index = this.inputs.indexOf(item) + let pos = 0 for (let i = 0; i <= index; i++) { - if (this.sizeProp === 'w') { - pos += this.inputs[i].w; + if (this.layoutType === 'horizontal') { + pos += this.inputs[i].w } else { - pos += this.inputs[i].h; + pos += this.inputs[i].h } } - return pos; - } - - getSizeProp() { - // The property used to measure the size of an item. If the layoutType - // isn't valid (that is, 'horizontal' or 'vertical'), it'll return null. - - return ( - this.layoutType === 'horizontal' ? 'w' : - this.layoutType === 'vertical' ? 'h' : - null - ) - } - - get posProp() { - // The property used to position an item. Like sizeProp, returns null if - // the layoutType isn't valid. - - return ( - this.layoutType === 'horizontal' ? 'x' : - this.layoutType === 'vertical' ? 'y' : - null) - } - - get edgeProp() { - // The property used to get the far edge of the property. As with - // sizeProp, if the layoutType doesn't have an expected value, it'll - // return null. - - return ( - this.layoutType === 'horizontal' ? 'right' : - this.layoutType === 'vertical' ? 'bottom' : - null) - } - - get formEdge() { - // Returns the value of the far edge of this form. Items farther in the - // list (up to the edge) will be closer to this edge. - - return ( - this.layoutType === 'horizontal' ? this.contentW : - this.layoutType === 'vertical' ? this.contentH : - null) + return pos } get scrollSize() { // Gets the actual length made up by all of the items currently scrolled // past. - return this.inputs.slice(0, this.scrollItems) - .reduce((a, b) => a + b[this.sizeProp], 0) + let size = 0 + for (let i = 0; i < this.scrollItems; i++) { + if (this.layoutType === 'horizontal') { + size += this.inputs[i].w + } else { + size += this.inputs[i].h + } + } + return size } get contentW() { -- cgit 1.3.0-6-gf8a5