diff --git a/src/components/canvas/store/render.ts b/src/components/canvas/store/render.ts index 788062b2..b4750e8c 100644 --- a/src/components/canvas/store/render.ts +++ b/src/components/canvas/store/render.ts @@ -24,6 +24,7 @@ export class Render { render() { const rect = this.canvas.getBoundingClientRect() + const resp = this.store.dataSvc.getCellView( this.store.currSheetIdx, this.store.anchorX - BUFFER_SIZE, diff --git a/src/core/data/render.ts b/src/core/data/render.ts index af233c75..6297e59b 100644 --- a/src/core/data/render.ts +++ b/src/core/data/render.ts @@ -1,7 +1,8 @@ import {Range, StandardCell} from '@/core/standable' -import {CellInfo} from 'logisheets-web' +import {CellInfo, Value} from 'logisheets-web' import {StandardValue} from '../standable/value' import {LeftTop} from '../settings' +import {StandardStyle} from '../standable/style' export class RenderCell { get width() { @@ -19,10 +20,23 @@ export class RenderCell { this.position = position return this } - setInfo(info: CellInfo) { - const c = new StandardCell() - if (info.style) c.setStyle(info.style) - if (info.value) c.value = StandardValue.from(info.value) + setInfo( + info: CellInfo, + getStandardCell: () => StandardCell, + getStandardValue: () => StandardValue, + getStandardStyle: () => StandardStyle + ) { + const c = getStandardCell() + if (info.style) { + const style = getStandardStyle() + style.from(info.style) + c.setStyle(style) + } + if (info.value) { + const value = getStandardValue() + value.from(info.value) + c.value = value + } if (info.formula !== undefined) c.formula = info.formula this.info = c return this diff --git a/src/core/data/service.ts b/src/core/data/service.ts index 2c45a84c..930eead7 100644 --- a/src/core/data/service.ts +++ b/src/core/data/service.ts @@ -53,6 +53,7 @@ export interface DataService { getSheetDimension(sheetIdx: number): Resp + hasCellView(): boolean getCurrentCellView(sheetIdx: number): CellView getCurrentSheetIdx(): number @@ -71,6 +72,9 @@ export class DataServiceImpl implements DataService { ) { this._init() } + hasCellView(): boolean { + return this._cellViews.has(this.getCurrentSheetIdx()) + } public getSheetDimension(sheetIdx: number): Resp { return this._workbook.getSheetDimension(sheetIdx) diff --git a/src/core/data/view_manager.ts b/src/core/data/view_manager.ts index d1ac5b5a..ce03c085 100644 --- a/src/core/data/view_manager.ts +++ b/src/core/data/view_manager.ts @@ -2,11 +2,18 @@ import {pxToPt, pxToWidth, widthToPx} from '../rate' import {LeftTop} from '../settings' import {RenderCell} from './render' import {CellViewData, Rect, CellView} from './types' -import {Range, StandardColInfo, StandardRowInfo} from '@/core/standable' +import { + Range, + StandardCell, + StandardColInfo, + StandardRowInfo, +} from '@/core/standable' import {ptToPx, width2px} from '@/core/rate' import {DisplayWindowWithStartPoint, isErrorMessage} from 'logisheets-web' import {Resp, WorkbookClient} from './workbook' import {Pool} from '../pool' +import {StandardValue} from '../standable/value' +import {StandardStyle} from '../standable/style' /** * The `ViewManager` is responsible for efficiently and seamlessly generating `CellViewData`. @@ -67,7 +74,10 @@ export class ViewManager { return parseDisplayWindow( w as DisplayWindowWithStartPoint, this._pool.getRenderCell.bind(this._pool), - this._pool.getRange.bind(this._pool) + this._pool.getRange.bind(this._pool), + this._pool.getStandardCell.bind(this._pool), + this._pool.getStandardValue.bind(this._pool), + this._pool.getStandardStyle.bind(this._pool) ) }) @@ -125,7 +135,10 @@ export interface CellViewResponse { export function parseDisplayWindow( window: DisplayWindowWithStartPoint, getRenderCell: () => RenderCell, - getRange: () => Range + getRange: () => Range, + getStandardCell: () => StandardCell, + getStandardValue: () => StandardValue, + getStandardStyle: () => StandardStyle ): CellViewData { const xStart = width2px(window.startX) const yStart = ptToPx(window.startY) @@ -186,7 +199,12 @@ export function parseDisplayWindow( const renderCell = getRenderCell() .setPosition(position) .setCoordinate(corrdinate) - .setInfo(window.window.cells[idx]) + .setInfo( + window.window.cells[idx], + getStandardCell, + getStandardValue, + getStandardStyle + ) cells.push(renderCell) idx += 1 } diff --git a/src/core/pool.ts b/src/core/pool.ts index 122946ee..7fa37951 100644 --- a/src/core/pool.ts +++ b/src/core/pool.ts @@ -1,9 +1,12 @@ import {injectable} from 'inversify' import {CellView, RenderCell} from './data' -import {Range} from '@/core/standable' +import {Range, StandardCell} from '@/core/standable' +import {StandardValue} from './standable/value' +import {StandardStyle} from './standable/style' -const RENDER_CELL_COUNT = 1000 -const RANGE_COUNT = 2000 +const RENDER_CELL_COUNT = 5000 +const RANGE_COUNT = 6000 +const CACHE_NUMBER = 2 /** * This is an object pool used to manage the creation and reuse of frequently used objects, @@ -40,6 +43,9 @@ export class Pool { c.reset() this.releaseRange(c.position) this.releaseRange(c.coordinate) + if (c.info) { + this.releaseStandardCell(c.info) + } this._renderCells.push(c) } @@ -53,16 +59,58 @@ export class Pool { this._ranges.push(r) } - releaseCellView(cellView: CellView) { - cellView.rows.forEach((c) => { - this.releaseRenderCell(c) - }) - cellView.cols.forEach((c) => { - this.releaseRenderCell(c) - }) - cellView.cells.forEach((c) => { - this.releaseRenderCell(c) - }) + getStandardValue(): StandardValue { + if (this._standardValues.length > 0) + return this._standardValues.pop() as StandardValue + return new StandardValue() + } + + releaseStandardValue(v: StandardValue) { + v.cellValueOneof = undefined + this._standardValues.push(v) + } + + getStandardStyle(): StandardStyle { + if (this._standardStyles.length > 0) { + return this._standardStyles.pop() as StandardStyle + } + return new StandardStyle() + } + + releaseStandardStyle(s: StandardStyle) { + this._standardStyles.push(s) + } + + getStandardCell(): StandardCell { + if (this._standardCells.length > 0) + return this._standardCells.pop() as StandardCell + return new StandardCell() + } + + releaseStandardCell(c: StandardCell) { + if (c.value) this.releaseStandardValue(c.value) + if (c.style) this.releaseStandardStyle(c.style) + this._standardCells.push(c) + } + + releaseCellView(v: CellView) { + /** + * We don't really release the render cells at once since + * these render cells are still used in other places. + */ + if (this._cellViews.length >= CACHE_NUMBER) { + const cellView = this._cellViews.pop() as CellView + cellView.rows.forEach((c) => { + this.releaseRenderCell(c) + }) + cellView.cols.forEach((c) => { + this.releaseRenderCell(c) + }) + cellView.cells.forEach((c) => { + this.releaseRenderCell(c) + }) + } + this._cellViews.push(v) } private _renderCells = Array.from( @@ -71,4 +119,18 @@ export class Pool { ) private _ranges = Array.from({length: RANGE_COUNT}, () => new Range()) + private _standardCells = Array.from( + {length: RENDER_CELL_COUNT}, + () => new StandardCell() + ) + private _standardValues = Array.from( + {length: RENDER_CELL_COUNT}, + () => new StandardValue() + ) + private _standardStyles = Array.from( + {length: RENDER_CELL_COUNT}, + () => new StandardStyle() + ) + + private _cellViews: CellView[] = [] } diff --git a/src/core/standable/cell.ts b/src/core/standable/cell.ts index ee35f36d..dc067c7f 100644 --- a/src/core/standable/cell.ts +++ b/src/core/standable/cell.ts @@ -8,12 +8,8 @@ export class StandardCell { style?: StandardStyle value?: StandardValue formula = '' - setStyle(style?: Style) { - if (!style) { - this.style = undefined - return - } - this.style = StandardStyle.from(style) + setStyle(style?: StandardStyle) { + this.style = style } getFormattedText() { diff --git a/src/core/standable/style.ts b/src/core/standable/style.ts index 2d0dacde..505782e7 100644 --- a/src/core/standable/style.ts +++ b/src/core/standable/style.ts @@ -16,10 +16,9 @@ export class StandardStyle implements Style { fill!: Fill alignment!: CtCellAlignment formatter = '' - static from(style: Style) { - const s = new StandardStyle() - shallowCopy(style, s) - return s + from(style: Style) { + shallowCopy(style, this) + return this } getFont() { diff --git a/src/core/standable/value.ts b/src/core/standable/value.ts index 58dc7161..82169564 100644 --- a/src/core/standable/value.ts +++ b/src/core/standable/value.ts @@ -19,16 +19,18 @@ export class StandardValue { get valueStr() { return this.value.toString() } - static from(value: Value) { - const v = new StandardValue() + from(value: Value) { if (hasOwnProperty(value, 'str')) - v.cellValueOneof = {$case: 'str', str: value.str as string} + this.cellValueOneof = {$case: 'str', str: value.str as string} else if (hasOwnProperty(value, 'bool')) - v.cellValueOneof = {$case: 'bool', bool: value.bool as boolean} + this.cellValueOneof = {$case: 'bool', bool: value.bool as boolean} else if (hasOwnProperty(value, 'number')) - v.cellValueOneof = {$case: 'number', number: value.number as number} + this.cellValueOneof = { + $case: 'number', + number: value.number as number, + } else if (hasOwnProperty(value, 'error')) - v.cellValueOneof = {$case: 'error', error: value.error as string} - return v + this.cellValueOneof = {$case: 'error', error: value.error as string} + return this } }