UNPKG

@visactor/vtable

Version:

canvas table width high performance

174 lines (172 loc) 7.96 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, _b; let sum = 0, currentBottomFrozenRowsHeight = 0, isBottomFrozenRowNoCache = !1; const bottomFrozenStartRow = this.table.rowCount > 0 && this.table.bottomFrozenRowCount > 0 ? this.table.rowCount - this.table.bottomFrozenRowCount : -1; 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), i >= bottomFrozenStartRow && -1 !== bottomFrozenStartRow && (currentBottomFrozenRowsHeight = sum, isBottomFrozenRowNoCache = i === bottomFrozenStartRow); } if (isBottomFrozenRowNoCache && (null === (_b = this.table.containerFit) || void 0 === _b ? void 0 : _b.height) && this.table.bottomFrozenRowCount) { const tableHeight = this.table.tableNoFrameHeight || 0; sum < tableHeight && (sum = tableHeight - this.table.getBottomFrozenRowsHeight() + currentBottomFrozenRowsHeight); } 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, values = []; for (let i = position; i <= lastIndex; i++) this.has(i) && (values.push({ position: i, value: this.get(i) }), this._remove(i)); isValid(value) && this.put(position, value); for (const {position: position, value: value} of values) this.put(position + 1, value); } getLastIndex() { return this._sort(), this._keys[this._keys.length - 1]; } delLast() { const lastIndex = this.getLastIndex(); this._remove(lastIndex); } delete(position) { for (let i = position; i <= this.getLastIndex(); i++) this.cumulativeSum.delete(i); const lastIndex = this.getLastIndex(); this.has(position) && this._remove(position); const values = []; for (let i = position + 1; i <= lastIndex; i++) this.has(i) && values.push({ position: i, value: this.get(i) }); for (const {position: position, value: value} of values) this._remove(position), this._add(position - 1, value); } 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 values = []; for (let i = sourceIndex + sourceCount - 1; i >= sourceIndex; i--) values.push({ position: i, value: this.get(i) }), this.delete(i); for (let i = 0; i < sourceCount; i++) this.insert(insertIndex, values[i].value); } } 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; } const tempI = high < 0 ? 0 : high; return arr[tempI] === elm ? tempI : -1; } //# sourceMappingURL=row-height-map.js.map