@visactor/vtable
Version:
canvas table width high performance
174 lines (172 loc) • 7.96 kB
JavaScript
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