UNPKG

@visactor/vtable

Version:

canvas table width high performance

168 lines (166 loc) 7.69 kB
import { isValid } from "@visactor/vutils"; export class NumberRangeMap { constructor(table) { this.isUpdate = !1, this._keys = [], this._sorted = !1, this.data = new Map, this._keys.length = 0, this.cumulativeSum = new Map, this.difference = new Map, this.totalSum = 0, this.table = table; } get length() { return this.data.size; } clear() { this._keys = [], this.data.clear(), this.cumulativeSum.clear(), this.difference.clear(), this.totalSum = 0; } clearRange() { this.cumulativeSum.clear(), this.difference.clear(); } add(position, value) { if (!isValid(value)) return; const defaultValue = this.table.getRowHeight(position); this.data.has(position) || (this._keys.push(position), this._sorted = !1), this.data.set(position, value), this.totalSum += value, this.updateDifference(position, value - defaultValue); } remove(position) { if (this.data.has(position)) { const value = this.data.get(position); this.data.delete(position); const index = this._keys.indexOf(position); -1 !== index && this._keys.splice(index, 1), this.totalSum -= value; const defaultValue = this.table.getRowHeight(position); this.updateDifference(position, defaultValue - value); } } put(position, newValue) { if (isValid(newValue)) if (this.data.has(position)) { const oldValue = this.data.get(position); if (oldValue === newValue) return; this.data.set(position, newValue); const difference = newValue - oldValue; this.totalSum += difference, this.updateDifference(position, difference); } else this.add(position, newValue); } get(position) { return this.data.get(position); } has(position) { return this.data.has(position); } _sort() { const {_keys: keys} = this; this._sorted || (keys.sort(((a, b) => a < b ? -1 : a > b ? 1 : 0)), this._sorted = !0); } updateDifference(position, difference) { var _a; const oldDifference = null !== (_a = this.difference.get(position)) && void 0 !== _a ? _a : 0; this.difference.set(position, oldDifference + difference), this.update(); } getSumInRange(start, end) { return this.calculatePrefixSum(end) - this.calculatePrefixSum(start - 1); } updateCumulativeSum(position, difference) { for (const [pos, sum] of this.cumulativeSum) pos >= position && this.cumulativeSum.set(pos, sum + difference); } calculatePrefixSum(position) { if (position < 0) return 0; if (this.cumulativeSum.has(position)) { let cache = this.cumulativeSum.get(position); for (const [pos, difference] of this.difference) pos <= position && (cache += difference); return cache; } return this.dealDiffenence(), this.getCumulativeSum(position); } getCumulativeSum(position) { var _a; let sum = 0; for (let i = position; i >= 0; i--) { if (this.cumulativeSum.has(i)) { sum += this.cumulativeSum.get(i); break; } sum += null !== (_a = this.data.get(i)) && void 0 !== _a ? _a : this.table.getRowHeight(i); } return this.cumulativeSum.set(position, sum), sum; } update() { this.isUpdate || (this.isUpdate = !0, setTimeout((() => { this.dealDiffenence(), this.isUpdate = !1; }), 0)); } dealDiffenence() { for (const [sumPos] of this.cumulativeSum) for (const [difPos, difference] of this.difference) if (sumPos >= difPos) { const oldSum = this.cumulativeSum.get(sumPos); this.cumulativeSum.set(sumPos, oldSum + difference); } this.difference.clear(); } insert(position, value) { for (let i = position; i <= this.getLastIndex(); i++) this.cumulativeSum.delete(i); const lastIndex = this.getLastIndex() + 1; this.adjustOrder(position, position + 1, lastIndex - position), isValid(value) && this.put(position, value); } getLastIndex() { return this._sort(), this._keys[this._keys.length - 1]; } delLast() { const lastIndex = this.getLastIndex(); this.remove(lastIndex); } delete(position) { if (!this.has(position)) return; for (let i = position; i <= this.getLastIndex(); i++) this.cumulativeSum.delete(i); const lastIndex = this.getLastIndex(); this.adjustOrder(position + 1, position, lastIndex - position), this.delLast(); } adjustOrder(sourceIndex, targetIndex, moveCount) { this.clearRange(), this._sort(); const {_keys: keys} = this; if (sourceIndex > targetIndex) { const sourceVals = []; for (let i = indexFirst(keys, sourceIndex + moveCount - 1); i >= 0; i--) { const key = keys[i]; if (key >= sourceIndex) sourceVals.push(this.get(key)); else if (targetIndex <= key && key < sourceIndex) this.put(key + moveCount, this.get(key)); else if (key < targetIndex) break; } for (let i = 0; i < moveCount; i++) this.put(targetIndex + i, sourceVals[moveCount - 1 - i]); } const {length: length} = keys; if (sourceIndex < targetIndex) { const sourceVals = []; for (let i = indexFirst(keys, sourceIndex); i < length; i++) { const key = keys[i]; if (key >= sourceIndex && key < sourceIndex + moveCount) sourceVals.push(this.get(key)); else if (sourceIndex + moveCount <= key && key <= targetIndex) this.put(key - moveCount, this.get(key)); else if (key > targetIndex) break; } for (let i = 0; i < moveCount; i++) this.put(targetIndex + i, sourceVals[i]); } } exchangeOrder(sourceIndex, sourceCount, targetIndex, targetCount, insertIndex) { const {_keys: keys} = this; if (this._sorted || (keys.sort(((a, b) => a < b ? -1 : a > b ? 1 : 0)), this._sorted = !0), sourceIndex > targetIndex) { const targetVals = [], sourceVals = []; for (let i = indexFirst(keys, targetIndex); i < indexFirst(keys, sourceIndex) + sourceCount; i++) { const key = keys[i]; key >= sourceIndex && key < sourceIndex + sourceCount ? sourceVals.push(this.get(key)) : targetVals.push(this.get(key)); } for (let i = 0; i < sourceCount; i++) this.put(insertIndex + i, sourceVals[i]); for (let i = 0; i < targetVals.length; i++) this.put(insertIndex + sourceCount + i, targetVals[i]); } else { const targetVals = [], sourceVals = []; for (let i = indexFirst(keys, sourceIndex); i < indexFirst(keys, targetIndex) + targetCount; i++) { const key = keys[i]; key >= sourceIndex && key < sourceIndex + sourceCount ? sourceVals.push(this.get(key)) : targetVals.push(this.get(key)); } for (let i = 0; i < sourceCount; i++) this.put(insertIndex + i, sourceVals[i]); for (let i = 0; i < targetVals.length; i++) this.put(sourceIndex + i, targetVals[i]); } } } function indexFirst(arr, elm) { let low = 0, high = arr.length - 1; for (;low <= high; ) { const i = Math.floor((low + high) / 2); if (arr[i] === elm) return i; arr[i] > elm ? high = i - 1 : low = i + 1; } return high < 0 ? 0 : high; } //# sourceMappingURL=row-height-map.js.map