diff --git a/common/shared/eslint/index.js b/common/shared/eslint/index.js
index 2ef4db46739..b40f039bd0a 100644
--- a/common/shared/eslint/index.js
+++ b/common/shared/eslint/index.js
@@ -217,7 +217,7 @@ exports.specPreset = () => {
exports.jsdocPreset = () => {
return {
- files: ['**/*.{ts,tsx}'],
+ files: ['**/facade/*.{ts,tsx}'],
rules: {
...jsdoc.configs.recommended.rules,
},
diff --git a/docs/tldr/skeleton.svg b/docs/tldr/skeleton.svg
new file mode 100644
index 00000000000..eebe86e8184
--- /dev/null
+++ b/docs/tldr/skeleton.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 4ce572c3d07..66fa373d9b3 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -196,3 +196,7 @@ export { type BBox, type IRTreeItem, RBush, RTree } from './shared/r-tree';
export { type IUniverConfig, Univer } from './univer';
export { isNodeEnv } from './shared/tools';
+export { Skeleton } from './skeleton.ts';
+export { getCellCoordByIndexSimple as getCellPositionByIndex, getCellWithCoordByIndexCore, SheetSkeleton } from './sheets/sheet-skeleton';
+export type { IGetRowColByPosOptions } from './sheets/sheet-skeleton';
+export type { IPosition } from './sheets/typedef.ts';
diff --git a/packages/core/src/services/resource-manager/resource-manager.service.ts b/packages/core/src/services/resource-manager/resource-manager.service.ts
index 31faf391d72..7f4da1d33da 100644
--- a/packages/core/src/services/resource-manager/resource-manager.service.ts
+++ b/packages/core/src/services/resource-manager/resource-manager.service.ts
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-import { Subject } from 'rxjs';
-import { Disposable, toDisposable } from '../../shared/lifecycle';
import type { UniverInstanceType } from '../../common/unit';
import type { IResources } from '../resource-manager/type';
import type { IResourceHook, IResourceManagerService, IResourceName } from './type';
+import { Subject } from 'rxjs';
+import { Disposable, toDisposable } from '../../shared/lifecycle';
export class ResourceManagerService extends Disposable implements IResourceManagerService {
private _resourceMap = new Map();
diff --git a/packages/core/src/sheets/sheet-skeleton.ts b/packages/core/src/sheets/sheet-skeleton.ts
new file mode 100644
index 00000000000..1a1d0e444d1
--- /dev/null
+++ b/packages/core/src/sheets/sheet-skeleton.ts
@@ -0,0 +1,1225 @@
+/**
+ * Copyright 2023-present DreamNum Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* eslint-disable no-param-reassign */
+import type { IObjectArrayPrimitiveType, Nullable } from '../shared';
+import type {
+ IDocumentData,
+ IDocumentRenderConfig,
+ IPaddingData,
+} from '../types/interfaces';
+import type { Styles } from './styles';
+import type {
+ ICellData,
+ ICellInfo,
+ ICellWithCoord,
+ IColumnData,
+ IPosition,
+ IRange,
+ IRowData,
+ ISelectionCell,
+ IWorksheetData,
+} from './typedef';
+import type { Worksheet } from './worksheet';
+import { Inject, Injector } from '@wendellhu/redi';
+import { IS_ROW_STYLE_PRECEDE_COLUMN_STYLE } from '../common/const';
+import { DocumentDataModel } from '../docs/data-model/document-data-model';
+import { IConfigService } from '../services/config/config.service';
+import { IContextService } from '../services/context/context.service';
+import { LocaleService } from '../services/locale/locale.service';
+import { isCellCoverable, ObjectMatrix, searchArray, Tools } from '../shared';
+import { ImageCacheMap } from '../shared/cache/image-cache';
+import { getIntersectRange } from '../shared/range';
+import { Skeleton } from '../skeleton';
+import { BooleanNumber, HorizontalAlign } from '../types/enum';
+
+export interface IGetRowColByPosOptions {
+ closeFirst?: boolean;
+
+ /**
+ * For searchArray(rowHeightAccumulation) & searchArray(colWidthAccumulation)
+ * true means return first matched index in matched sequence.
+ * default return last index in matched sequence.
+ */
+ firstMatch?: boolean;
+}
+
+export const RENDER_RAW_FORMULA_KEY = 'RENDER_RAW_FORMULA';
+export class SheetSkeleton extends Skeleton {
+ /**
+ * @deprecated avoid use `IWorksheetData` directly, use API provided by `Worksheet`, otherwise
+ * `ViewModel` will be not working.
+ */
+ protected _worksheetData: IWorksheetData;
+ protected _renderRawFormula = false;
+ protected _cellData: ObjectMatrix>;
+ protected _imageCacheMap: ImageCacheMap;
+ /**
+ * Whether the row style precedes the column style.
+ */
+ protected _isRowStylePrecedeColumnStyle = false;
+ constructor(
+ readonly worksheet: Worksheet,
+ protected _styles: Styles,
+ @Inject(LocaleService) _localeService: LocaleService,
+ @IContextService protected readonly _contextService: IContextService,
+ @IConfigService protected readonly _configService: IConfigService,
+ @Inject(Injector) protected _injector: Injector
+ ) {
+ super(_localeService);
+ this._worksheetData = this.worksheet.getConfig();
+ this._cellData = this.worksheet.getCellMatrix();
+ this._imageCacheMap = new ImageCacheMap(this._injector);
+
+ this.init();
+ }
+
+ init() {
+ this._isRowStylePrecedeColumnStyle = this._configService.getConfig(IS_ROW_STYLE_PRECEDE_COLUMN_STYLE) ?? false;
+ }
+
+ _resetCache() {
+ //
+ }
+
+ /**
+ * @deprecated should never expose a property that is provided by another module!
+ */
+ getWorksheetConfig(): IWorksheetData {
+ return this._worksheetData;
+ }
+
+ /**
+ * Get which Workbook and Worksheet this skeleton is attached to.
+ * @returns [unitId, sheetId]
+ */
+ getLocation(): [string, string] {
+ return [this.worksheet.getUnitId(), this.worksheet.getSheetId()];
+ }
+
+ private _rowTotalHeight = 0;
+ private _columnTotalWidth = 0;
+ private _rowHeaderWidth = 0;
+ private _columnHeaderHeight = 0;
+ private _rowHeightAccumulation: number[] = [];
+ private _columnWidthAccumulation: number[] = [];
+ private _marginTop: number = 0;
+ private _marginLeft: number = 0;
+ /** Scale of Scene */
+ protected _scaleX: number;
+ protected _scaleY: number;
+ /** Viewport scrolled value */
+ protected _scrollX: number;
+ /** Viewport scrolled value */
+ protected _scrollY: number;
+
+ get rowHeightAccumulation(): number[] {
+ return this._rowHeightAccumulation;
+ }
+
+ get rowTotalHeight(): number {
+ return this._rowTotalHeight;
+ }
+
+ get columnWidthAccumulation(): number[] {
+ return this._columnWidthAccumulation;
+ }
+
+ get columnTotalWidth(): number {
+ return this._columnTotalWidth;
+ }
+
+ get rowHeaderWidth(): number {
+ return this._rowHeaderWidth;
+ }
+
+ get columnHeaderHeight(): number {
+ return this._columnHeaderHeight;
+ }
+
+ setMarginLeft(left: number): void {
+ this._marginLeft = left;
+ }
+
+ setMarginTop(top: number): void {
+ this._marginTop = top;
+ }
+
+ setScale(value: number, valueY?: number): void {
+ this._updateLayout();
+ this._scaleX = value;
+ this._scaleY = valueY || value;
+ this._updateLayout();
+ }
+
+ setScroll(scrollX?: number, scrollY?: number) {
+ if (Tools.isDefine(scrollX)) {
+ this._scrollX = scrollX;
+ }
+ if (Tools.isDefine(scrollY)) {
+ this._scrollY = scrollY;
+ }
+ }
+
+ get scrollX(): number {
+ return this._scrollX;
+ }
+
+ get scrollY(): number {
+ return this._scrollY;
+ }
+
+ get scaleX(): number {
+ return this._scaleX;
+ }
+
+ get scaleY(): number {
+ return this._scaleY;
+ }
+
+ get rowHeaderWidthAndMarginLeft(): number {
+ return this.rowHeaderWidth + this._marginLeft;
+ }
+
+ get columnHeaderHeightAndMarginTop(): number {
+ return this.columnHeaderHeight + this._marginTop;
+ }
+
+ get imageCacheMap(): ImageCacheMap {
+ return this._imageCacheMap;
+ }
+
+ private _generateRowMatrixCache(
+ rowCount: number,
+ rowData: IObjectArrayPrimitiveType>,
+ defaultRowHeight: number
+ ): { rowTotalHeight: number; rowHeightAccumulation: number[] } {
+ let rowTotalHeight = 0;
+ const rowHeightAccumulation: number[] = [];
+ const data = rowData;
+ for (let r = 0; r < rowCount; r++) {
+ let rowHeight = defaultRowHeight;
+
+ if (this.worksheet.getRowFiltered(r)) {
+ rowHeight = 0;
+ } else if (data[r] != null) {
+ const rowDataItem = data[r];
+ if (!rowDataItem) {
+ continue;
+ }
+
+ const { h = defaultRowHeight, ah, ia } = rowDataItem;
+ if (
+ (ia == null || ia === BooleanNumber.TRUE) &&
+ typeof ah === 'number'
+ ) {
+ rowHeight = ah;
+ } else {
+ rowHeight = h;
+ }
+
+ if (rowDataItem.hd === BooleanNumber.TRUE) {
+ rowHeight = 0;
+ }
+ }
+
+ rowTotalHeight += rowHeight;
+
+ rowHeightAccumulation.push(rowTotalHeight);
+ }
+
+ return {
+ rowTotalHeight,
+ rowHeightAccumulation,
+ };
+ }
+
+ /**
+ * Calc columnWidthAccumulation by columnData
+ * @param colCount
+ * @param columnData
+ * @param defaultColumnWidth
+ */
+ private _generateColumnMatrixCache(
+ colCount: number,
+ columnData: IObjectArrayPrimitiveType>,
+ defaultColumnWidth: number
+ ): { columnTotalWidth: number; columnWidthAccumulation: number[] } {
+ let columnTotalWidth = 0;
+ const columnWidthAccumulation: number[] = [];
+
+ const data = columnData;
+
+ for (let c = 0; c < colCount; c++) {
+ let columnWidth = defaultColumnWidth;
+
+ if (data[c] != null) {
+ const columnDataItem = data[c];
+
+ if (!columnDataItem) {
+ continue;
+ }
+ if (columnDataItem.w != null) {
+ columnWidth = columnDataItem.w;
+ }
+
+ if (columnDataItem.hd === BooleanNumber.TRUE) {
+ columnWidth = 0;
+ }
+ }
+
+ columnTotalWidth += columnWidth;
+ columnWidthAccumulation.push(columnTotalWidth);
+ }
+
+ return {
+ columnTotalWidth,
+ columnWidthAccumulation,
+ };
+ }
+
+ intersectMergeRange(row: number, column: number): boolean {
+ const mergedData = this.worksheet.getMergedCell(row, column);
+ return Boolean(mergedData);
+ }
+
+ //eslint-disable-next-line complexity
+ protected _getOverflowBound(
+ row: number,
+ startColumn: number,
+ endColumn: number,
+ contentWidth: number,
+ horizontalAlign = HorizontalAlign.LEFT
+ ): number {
+ let cumWidth = 0;
+ if (startColumn > endColumn) {
+ const columnCount = this._columnWidthAccumulation.length - 1;
+ for (let i = startColumn; i >= endColumn; i--) {
+ const column = i;
+ const cell = this.worksheet.getCell(row, column);
+ if (
+ (!isCellCoverable(cell) && column !== startColumn) ||
+ this.intersectMergeRange(row, column)
+ ) {
+ if (column === startColumn) {
+ return column;
+ }
+ return column + 1 > columnCount ? columnCount : column + 1;
+ }
+ const { startX, endX } = getCellWithCoordByIndexCore(
+ row,
+ column,
+ this.rowHeightAccumulation,
+ this.columnWidthAccumulation
+ );
+
+ // For center alignment, the current cell's width needs to be divided in half for comparison.
+ if (
+ horizontalAlign === HorizontalAlign.CENTER &&
+ column === startColumn
+ ) {
+ cumWidth += (endX - startX) / 2;
+ } else {
+ cumWidth += endX - startX;
+ }
+
+ if (contentWidth < cumWidth) {
+ return column;
+ }
+ }
+ return startColumn;
+ }
+ for (let i = startColumn; i <= endColumn; i++) {
+ const column = i;
+ const cell = this.worksheet.getCell(row, column);
+ if (
+ (!isCellCoverable(cell) && column !== startColumn) ||
+ this.intersectMergeRange(row, column)
+ ) {
+ if (column === startColumn) {
+ return column;
+ }
+
+ return column - 1 < 0 ? 0 : column - 1;
+ }
+ const { startX, endX } = getCellWithCoordByIndexCore(
+ row,
+ column,
+ this.rowHeightAccumulation,
+ this.columnWidthAccumulation
+ );
+
+ if (
+ horizontalAlign === HorizontalAlign.CENTER &&
+ column === startColumn
+ ) {
+ cumWidth += (endX - startX) / 2;
+ } else {
+ cumWidth += endX - startX;
+ }
+
+ if (contentWidth < cumWidth) {
+ return column;
+ }
+ }
+ return endColumn;
+ }
+
+ /**
+ * Calculate data for row col & cell position.
+ * This method should be called whenever a sheet is dirty.
+ * Update position value to this._rowHeaderWidth & this._rowHeightAccumulation & this._columnHeaderHeight & this._columnWidthAccumulation.
+ */
+ protected _updateLayout(): void {
+ if (!this.dirty) {
+ return;
+ }
+
+ const {
+ rowData,
+ columnData,
+ defaultRowHeight,
+ defaultColumnWidth,
+ rowCount,
+ columnCount,
+ rowHeader,
+ columnHeader,
+ } = this._worksheetData;
+
+ const { rowTotalHeight, rowHeightAccumulation } =
+ this._generateRowMatrixCache(rowCount, rowData, defaultRowHeight);
+
+ const { columnTotalWidth, columnWidthAccumulation } =
+ this._generateColumnMatrixCache(
+ columnCount,
+ columnData,
+ defaultColumnWidth
+ );
+
+ this._rowHeaderWidth =
+ rowHeader.hidden !== BooleanNumber.TRUE
+ ? this._dynamicallyUpdateRowHeaderWidth(rowHeader)
+ : 0;
+ this._columnHeaderHeight =
+ columnHeader.hidden !== BooleanNumber.TRUE
+ ? columnHeader.height
+ : 0;
+
+ this._rowTotalHeight = rowTotalHeight;
+ this._rowHeightAccumulation = rowHeightAccumulation;
+ this._columnTotalWidth = columnTotalWidth;
+ this._columnWidthAccumulation = columnWidthAccumulation;
+
+ this.makeDirty(false);
+ }
+
+ /**
+ * Refresh cache after markDirty by SheetSkeletonManagerService.reCalculate()
+ * @param bounds
+ */
+ calculate(): Nullable {
+ this._resetCache();
+ this._updateLayout();
+
+ return this;
+ }
+
+ private _dynamicallyUpdateRowHeaderWidth(rowHeader: {
+ width: number;
+ }): number {
+ const SIZE_BY_EACH_CHARACTER = 8;
+ const widthByComputation =
+ `${this.worksheet.getRowCount()}`.length * SIZE_BY_EACH_CHARACTER;
+ return Math.max(rowHeader.width, widthByComputation);
+ }
+
+ protected _hasUnMergedCellInRow(
+ rowIndex: number,
+ startColumn: number,
+ endColumn: number
+ ): boolean {
+ const mergeData = this.worksheet.getMergeData();
+ if (!mergeData) {
+ return false;
+ }
+
+ for (let i = startColumn; i <= endColumn; i++) {
+ const { isMerged, isMergedMainCell } =
+ this.worksheet.getCellInfoInMergeData(rowIndex, i);
+
+ if (!isMerged && !isMergedMainCell) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * expand curr range if it's intersect with merge range.
+ * @param range
+ * @returns {IRange} expanded range because merge info.
+ */
+ expandRangeByMerge(range: IRange): IRange {
+ let { startRow, startColumn, endRow, endColumn } = range;
+ const mergeData = this._worksheetData.mergeData;
+ if (!mergeData) {
+ return {
+ startRow,
+ startColumn,
+ endRow,
+ endColumn,
+ };
+ }
+
+ let isSearching = true;
+ const searchedMarge = new ObjectMatrix();
+
+ // the loop breaks when there are not merged cells intersect with the current range
+ // NOTE: what about the performance issue?
+ while (isSearching) {
+ isSearching = false;
+
+ for (let i = 0; i < mergeData.length; i++) {
+ const {
+ startRow: mainStartRow,
+ startColumn: mainStartColumn,
+ endRow: mainEndRow,
+ endColumn: mainEndColumn,
+ } = mergeData[i];
+
+ if (searchedMarge.getValue(mainStartRow, mainStartColumn)) {
+ continue;
+ }
+
+ const rect1 = {
+ startColumn,
+ startRow,
+ endColumn,
+ endRow,
+ };
+
+ const rect2 = {
+ startColumn: mainStartColumn,
+ startRow: mainStartRow,
+ endColumn: mainEndColumn,
+ endRow: mainEndRow,
+ };
+
+ if (getIntersectRange(rect1, rect2)) {
+ startRow = Math.min(startRow, mainStartRow);
+ startColumn = Math.min(startColumn, mainStartColumn);
+ endRow = Math.max(endRow, mainEndRow);
+ endColumn = Math.max(endColumn, mainEndColumn);
+ searchedMarge.setValue(mainStartRow, mainStartColumn, true);
+ isSearching = true;
+ }
+ }
+ }
+
+ return {
+ startRow,
+ startColumn,
+ endRow,
+ endColumn,
+ } as IRange;
+ }
+
+ getColumnCount(): number {
+ return this._columnWidthAccumulation.length;
+ }
+
+ getRowCount(): number {
+ return this._rowHeightAccumulation.length;
+ }
+
+ /**
+ * New version to get merge data.
+ * @param row
+ * @param column
+ * @returns {ISelectionCell} The cell info with merge data
+ */
+ // protected _getCellMergeInfo(row: number, column: number): ISelectionCell {
+ // return this.worksheet.getCellInfoInMergeData(row, column);
+ // }
+
+ /**
+ * @deprecated use getNoMergeCellWithCoordByIndex instead.
+ * @param rowIndex
+ * @param columnIndex
+ * @param header
+ * @returns
+ */
+ getNoMergeCellPositionByIndex(
+ rowIndex: number,
+ columnIndex: number,
+ header: boolean = true
+ ) {
+ return this.getNoMergeCellWithCoordByIndex(rowIndex, columnIndex, header);
+ }
+
+ /**
+ * Original name: getNoMergeCellPositionByIndex
+ * @param rowIndex
+ * @param columnIndex
+ */
+ getNoMergeCellWithCoordByIndex(
+ rowIndex: number,
+ columnIndex: number,
+ header: boolean = true
+ ): IPosition {
+ const {
+ rowHeightAccumulation,
+ columnWidthAccumulation,
+ rowHeaderWidthAndMarginLeft,
+ columnHeaderHeightAndMarginTop,
+ } = this;
+
+ let { startY, endY, startX, endX } = getCellWithCoordByIndexCore(
+ rowIndex,
+ columnIndex,
+ rowHeightAccumulation,
+ columnWidthAccumulation
+ );
+
+ if (header) {
+ startY += columnHeaderHeightAndMarginTop;
+ endY += columnHeaderHeightAndMarginTop;
+ startX += rowHeaderWidthAndMarginLeft;
+ endX += rowHeaderWidthAndMarginLeft;
+ }
+
+ return {
+ startY,
+ endY,
+ startX,
+ endX,
+ };
+ }
+
+ /**
+ * @deprecated use getNoMergeCellWithCoordByIndex(row, col, false)
+ * @param rowIndex
+ * @param columnIndex
+ */
+ getNoMergeCellPositionByIndexWithNoHeader(
+ rowIndex: number,
+ columnIndex: number
+ ): IPosition {
+ const { rowHeightAccumulation, columnWidthAccumulation } = this;
+
+ const { startY, endY, startX, endX } = getCellWithCoordByIndexCore(
+ rowIndex,
+ columnIndex,
+ rowHeightAccumulation,
+ columnWidthAccumulation
+ );
+
+ return {
+ startY,
+ endY,
+ startX,
+ endX,
+ };
+ }
+
+ /**
+ *
+ * @param offsetY scaled offset y
+ * @param scaleY scale y
+ * @param scrollXY
+ * @param scrollXY.x
+ * @param scrollXY.y
+ */
+ getRowIndexByOffsetY(
+ offsetY: number,
+ scaleY: number,
+ scrollXY: { x: number; y: number },
+ options?: IGetRowColByPosOptions
+ ): number {
+ const { rowHeightAccumulation } = this;
+ offsetY = getTransformOffsetY(
+ offsetY,
+ scaleY,
+ scrollXY,
+ this.columnHeaderHeightAndMarginTop
+ );
+
+ let row = searchArray(
+ rowHeightAccumulation,
+ offsetY,
+ options?.firstMatch
+ );
+
+ if (options?.closeFirst) {
+ // check if upper row was closer than current
+ if (
+ Math.abs(rowHeightAccumulation[row] - offsetY) <
+ Math.abs(offsetY - (rowHeightAccumulation[row - 1] ?? 0))
+ ) {
+ row = row + 1;
+ }
+ }
+
+ return row;
+ }
+
+ /**
+ * Get column index by offset x.
+ * @param offsetX scaled offset x
+ * @param scaleX scale x
+ * @param scrollXY scrollXY
+ * @returns column index
+ */
+ getColumnIndexByOffsetX(
+ evtOffsetX: number,
+ scaleX: number,
+ scrollXY: { x: number; y: number },
+ options?: IGetRowColByPosOptions
+ ): number {
+ const offsetX = getTransformOffsetX(
+ evtOffsetX,
+ scaleX,
+ scrollXY,
+ this.rowHeaderWidthAndMarginLeft
+ );
+ const { columnWidthAccumulation } = this;
+ let column = searchArray(
+ columnWidthAccumulation,
+ offsetX,
+ options?.firstMatch
+ );
+
+ if (options?.closeFirst) {
+ // check if upper column was closer than current
+ if (
+ Math.abs(columnWidthAccumulation[column] - offsetX) <
+ Math.abs(offsetX - (columnWidthAccumulation[column - 1] ?? 0))
+ ) {
+ column = column + 1;
+ }
+ }
+
+ return column;
+ }
+
+ /**
+ * Get cell index by offset(o)
+ * @param offsetX position X in viewport.
+ * @param offsetY position Y in viewport.
+ * @param scaleX render scene scale x-axis, scene.getAncestorScale
+ * @param scaleY render scene scale y-axis, scene.getAncestorScale
+ * @param scrollXY render viewport scroll {x, y}, scene.getScrollXYByRelativeCoords, scene.getScrollXY
+ * @param scrollXY.x
+ * @param scrollXY.y
+ * @returns {row, col}
+ */
+ getCellIndexByOffset(
+ offsetX: number,
+ offsetY: number,
+ scaleX: number,
+ scaleY: number,
+ scrollXY: { x: number; y: number },
+ options?: IGetRowColByPosOptions
+ ): { row: number; column: number } {
+ const row = this.getRowIndexByOffsetY(
+ offsetY,
+ scaleY,
+ scrollXY,
+ options
+ );
+ const column = this.getColumnIndexByOffsetX(
+ offsetX,
+ scaleX,
+ scrollXY,
+ options
+ );
+
+ return {
+ row,
+ column,
+ };
+ }
+
+ /**
+ * Unlike getCellWithCoordByOffset, returning data doesn't include coord.
+ * @param offsetX
+ * @param offsetY
+ * @param scaleX
+ * @param scaleY
+ * @param scrollXY
+ */
+ getCellByOffset(
+ offsetX: number,
+ offsetY: number,
+ scaleX: number,
+ scaleY: number,
+ scrollXY: { x: number; y: number }
+ ): Nullable {
+ const cellIndex = this?.getCellIndexByOffset(
+ offsetX,
+ offsetY,
+ scaleX,
+ scaleY,
+ scrollXY,
+ { firstMatch: true } // for visible
+ );
+ if (!cellIndex) return null;
+
+ const selectionCell: ISelectionCell =
+ this.worksheet.getCellInfoInMergeData(
+ cellIndex.row,
+ cellIndex.column
+ );
+ return selectionCell;
+ }
+
+ /**
+ * Return cell information corresponding to the current coordinates, including the merged cell object.
+ *
+ * @param row Specified Row Coordinate
+ * @param column Specified Column Coordinate
+ */
+ getCellWithCoordByIndex(
+ row: number,
+ column: number,
+ header: boolean = true
+ ): ICellWithCoord {
+ const {
+ rowHeightAccumulation,
+ columnWidthAccumulation,
+ rowHeaderWidthAndMarginLeft,
+ columnHeaderHeightAndMarginTop,
+ } = this;
+
+ const primary: ICellWithCoord = getCellWithCoordByIndexCore(
+ row,
+ column,
+ rowHeightAccumulation,
+ columnWidthAccumulation,
+ this.worksheet.getCellInfoInMergeData(row, column)
+ );
+ const { isMerged, isMergedMainCell } = primary;
+ let { startY, endY, startX, endX, mergeInfo } = primary;
+
+ let offsetX = rowHeaderWidthAndMarginLeft;
+ let offsetY = columnHeaderHeightAndMarginTop;
+ if (header === false) {
+ offsetX = 0;
+ offsetY = 0;
+ }
+
+ startY += offsetY;
+ endY += offsetY;
+ startX += offsetX;
+ endX += offsetX;
+
+ mergeInfo.startY += offsetY;
+ mergeInfo.endY += offsetY;
+ mergeInfo.startX += offsetX;
+ mergeInfo.endX += offsetX;
+
+ // mergeInfo = mergeInfoOffset(mergeInfo, rowHeaderWidthAndMarginLeft, columnHeaderHeightAndMarginTop);
+
+ return {
+ actualRow: row,
+ actualColumn: column,
+ startX,
+ startY,
+ endX,
+ endY,
+ isMerged,
+ isMergedMainCell,
+ mergeInfo,
+ };
+ }
+
+ /**
+ * Get cell by pos(offsetX, offsetY). Combine getCellIndexByOffset and then getCellWithCoordByIndex.
+ *
+ * options.matchFirst true means get cell would skip all invisible cells.
+ * @param offsetX position X in viewport.
+ * @param offsetY position Y in viewport.
+ * @param scaleX render scene scale x-axis, scene.getAncestorScale
+ * @param scaleY render scene scale y-axis, scene.getAncestorScale
+ * @param scrollXY render viewportScroll {x, y}
+ * @param options {IGetRowColByPosOptions}
+ * @returns {ICellWithCoord} Selection data with coordinates
+ */
+ getCellWithCoordByOffset(
+ offsetX: number,
+ offsetY: number,
+ scaleX: number,
+ scaleY: number,
+ scrollXY: { x: number; y: number },
+ options?: IGetRowColByPosOptions
+ ): ICellWithCoord {
+ const { row, column } = this.getCellIndexByOffset(
+ offsetX,
+ offsetY,
+ scaleX,
+ scaleY,
+ scrollXY,
+ options
+ );
+
+ return this.getCellWithCoordByIndex(row, column);
+ }
+
+ /**
+ * Original name: getOffsetByPositionX
+ * @param column
+ * @returns
+ */
+ getOffsetByColumn(column: number): number {
+ const { columnWidthAccumulation, rowHeaderWidthAndMarginLeft } = this;
+
+ const lastColumnIndex = columnWidthAccumulation.length - 1;
+ const columnValue = columnWidthAccumulation[column];
+ if (columnValue != null) {
+ return columnValue + rowHeaderWidthAndMarginLeft;
+ }
+
+ if (column < 0) {
+ return rowHeaderWidthAndMarginLeft;
+ }
+
+ return (
+ columnWidthAccumulation[lastColumnIndex] +
+ rowHeaderWidthAndMarginLeft
+ );
+ }
+
+ /**
+ * Original name: getOffsetByPositionY
+ * @param row
+ */
+ getOffsetByRow(row: number): number {
+ const { rowHeightAccumulation, columnHeaderHeightAndMarginTop } = this;
+ const lastRowIndex = rowHeightAccumulation.length - 1;
+ const rowValue = rowHeightAccumulation[row];
+ if (rowValue != null) {
+ return rowValue + columnHeaderHeightAndMarginTop;
+ }
+
+ if (row < 0) {
+ return columnHeaderHeightAndMarginTop;
+ }
+
+ return (
+ rowHeightAccumulation[lastRowIndex] + columnHeaderHeightAndMarginTop
+ );
+ }
+
+ /**
+ * Original name: getDecomposedOffset
+ * @param offsetX
+ * @param offsetY
+ */
+ getOffsetRelativeToRowCol(
+ offsetX: number,
+ offsetY: number
+ ): {
+ row: number;
+ column: number;
+ columnOffset: number;
+ rowOffset: number;
+ } {
+ const column = searchArray(this.columnWidthAccumulation, offsetX);
+ let columnOffset = 0;
+ if (column === 0) {
+ columnOffset = offsetX;
+ } else {
+ columnOffset = offsetX - this._columnWidthAccumulation[column - 1];
+ }
+
+ const row = searchArray(this.rowHeightAccumulation, offsetY);
+ let rowOffset = 0;
+ if (row === 0) {
+ rowOffset = offsetY;
+ } else {
+ rowOffset = offsetY - this._rowHeightAccumulation[row - 1];
+ }
+ return {
+ row,
+ column,
+ columnOffset,
+ rowOffset,
+ };
+ }
+
+ protected _updateConfigAndGetDocumentModel(
+ documentData: IDocumentData,
+ horizontalAlign: HorizontalAlign,
+ paddingData: IPaddingData,
+ renderConfig?: IDocumentRenderConfig
+ ): Nullable {
+ if (!renderConfig) {
+ return;
+ }
+
+ if (!documentData.body?.dataStream) {
+ return;
+ }
+
+ if (!documentData.documentStyle) {
+ documentData.documentStyle = {};
+ }
+
+ documentData.documentStyle.marginTop = paddingData.t ?? 0;
+ documentData.documentStyle.marginBottom = paddingData.b ?? 2;
+ documentData.documentStyle.marginLeft = paddingData.l ?? 2;
+ documentData.documentStyle.marginRight = paddingData.r ?? 2;
+
+ // Fix https://github.com/dream-num/univer/issues/1586
+ documentData.documentStyle.pageSize = {
+ width: Number.POSITIVE_INFINITY,
+ height: Number.POSITIVE_INFINITY,
+ };
+
+ documentData.documentStyle.renderConfig = {
+ ...documentData.documentStyle.renderConfig,
+ ...renderConfig,
+ };
+
+ const paragraphs = documentData.body.paragraphs || [];
+
+ for (const paragraph of paragraphs) {
+ if (!paragraph.paragraphStyle) {
+ paragraph.paragraphStyle = {};
+ }
+
+ paragraph.paragraphStyle.horizontalAlign = horizontalAlign;
+ }
+
+ return new DocumentDataModel(documentData);
+ }
+
+ override dispose(): void {
+ super.dispose();
+
+ this._rowHeightAccumulation = [];
+ this._columnWidthAccumulation = [];
+ this._rowTotalHeight = 0;
+ this._columnTotalWidth = 0;
+ this._rowHeaderWidth = 0;
+ this._columnHeaderHeight = 0;
+
+ this._worksheetData = null as unknown as IWorksheetData;
+ this._cellData = null as unknown as ObjectMatrix>;
+ this._styles = null as unknown as Styles;
+ }
+}
+
+/**
+ * Only the coordinates of the corresponding cells in rows and columns are considered, without taking into account the merged data.
+ *
+ * Original name: getCellPositionByIndexSimple
+ * @param row
+ * @param column
+ * @param rowHeightAccumulation
+ * @param columnWidthAccumulation
+ */
+export function getCellCoordByIndexSimple(
+ row: number,
+ column: number,
+ rowHeightAccumulation: number[],
+ columnWidthAccumulation: number[]
+): IPosition {
+ const startRow = row - 1;
+ const startColumn = column - 1;
+
+ const startY = rowHeightAccumulation[startRow] || 0;
+ let endY = rowHeightAccumulation[row];
+
+ if (endY == null) {
+ endY = rowHeightAccumulation[rowHeightAccumulation.length - 1];
+ }
+
+ const startX = columnWidthAccumulation[startColumn] || 0;
+ let endX = columnWidthAccumulation[column];
+
+ if (endX == null) {
+ endX = columnWidthAccumulation[columnWidthAccumulation.length - 1];
+ }
+
+ return {
+ startY,
+ endY,
+ startX,
+ endX,
+ };
+}
+
+/**
+ * @description Get the cell position information of the specified row and column, including the position of the cell and the merge info
+ * @param {number} row The row index of the cell
+ * @param {number} column The column index of the cell
+ * @param {number[]} rowHeightAccumulation The accumulated height of each row
+ * @param {number[]} columnWidthAccumulation The accumulated width of each column
+ * @param {ICellInfo} mergeData The merge information of the cell
+ * @returns {ICellWithCoord} The cell position information of the specified row and column, including the position information of the cell and the merge information of the cell
+ */
+// eslint-disable-next-line max-lines-per-function
+export function getCellWithCoordByIndexCore(
+ row: number,
+ column: number,
+ rowHeightAccumulation: number[],
+ columnWidthAccumulation: number[],
+ mergeDataInfo: Nullable
+): ICellWithCoord {
+ row = Tools.clamp(row, 0, rowHeightAccumulation.length - 1);
+ column = Tools.clamp(column, 0, columnWidthAccumulation.length - 1);
+ // eslint-disable-next-line prefer-const
+ let { startY, endY, startX, endX } = getCellCoordByIndexSimple(
+ row,
+ column,
+ rowHeightAccumulation,
+ columnWidthAccumulation
+ );
+
+ if (!mergeDataInfo) {
+ return {
+ startY,
+ endY,
+ startX,
+ endX,
+ isMerged: false,
+ isMergedMainCell: false,
+ actualRow: row,
+ actualColumn: column,
+ mergeInfo: {
+ startY,
+ endY,
+ startX,
+ endX,
+ startRow: row,
+ startColumn: column,
+ endRow: row,
+ endColumn: column,
+ },
+ };
+ }
+
+ const {
+ isMerged,
+ isMergedMainCell,
+ startRow,
+ startColumn,
+ endRow,
+ endColumn,
+ } = mergeDataInfo;
+
+ let mergeInfo = {
+ startRow,
+ startColumn,
+ endRow,
+ endColumn,
+ startY,
+ endY,
+ startX,
+ endX,
+ };
+
+ const rowAccumulationCount = rowHeightAccumulation.length - 1;
+ const columnAccumulationCount = columnWidthAccumulation.length - 1;
+
+ if (isMerged && startRow !== -1 && startColumn !== -1) {
+ const mergeStartY = rowHeightAccumulation[startRow - 1] || 0;
+ const mergeEndY =
+ rowHeightAccumulation[endRow] ||
+ rowHeightAccumulation[rowAccumulationCount];
+
+ const mergeStartX = columnWidthAccumulation[startColumn - 1] || 0;
+ const mergeEndX =
+ columnWidthAccumulation[endColumn] ||
+ columnWidthAccumulation[columnAccumulationCount];
+ mergeInfo = {
+ ...mergeInfo,
+ startY: mergeStartY,
+ endY: mergeEndY,
+ startX: mergeStartX,
+ endX: mergeEndX,
+ };
+ } else if (!isMerged && endRow !== -1 && endColumn !== -1) {
+ const mergeEndY =
+ rowHeightAccumulation[endRow] ||
+ rowHeightAccumulation[rowAccumulationCount];
+ const mergeEndX =
+ columnWidthAccumulation[endColumn] ||
+ columnWidthAccumulation[columnAccumulationCount];
+
+ mergeInfo = {
+ ...mergeInfo,
+ startY,
+ endY: mergeEndY,
+ startX,
+ endX: mergeEndX,
+ };
+ }
+
+ return {
+ isMerged,
+ isMergedMainCell,
+ actualRow: row,
+ actualColumn: column,
+ startY,
+ endY,
+ startX,
+ endX,
+ mergeInfo,
+ } as ICellWithCoord;
+}
+
+/**
+ * Get x in sheet coordinate. Already handled scrolling and zooming.
+ * @param offsetX Offset value from PointerEvent in canvas element.
+ * @param scaleX from scene.getAncestorScale
+ * @param scrollXY Scroll value of viewport
+ * @returns {number} x in sheet coordinate.
+ */
+export function getTransformOffsetX(
+ offsetX: number,
+ scaleX: number,
+ scrollXY: { x: number; y: number },
+ rowHeaderWidth: number
+): number {
+ const { x: scrollX } = scrollXY;
+
+ // so we should map physical positions to ideal positions
+ const afterOffsetX = offsetX / scaleX + scrollX - rowHeaderWidth; //this.rowHeaderWidthAndMarginLeft;
+
+ return afterOffsetX;
+}
+
+/**
+ * @param offsetY
+ * @param scaleY
+ * @param scrollXY
+ */
+export function getTransformOffsetY(
+ offsetY: number,
+ scaleY: number,
+ scrollXY: { x: number; y: number },
+ columnHeight: number
+): number {
+ const { y: scrollY } = scrollXY;
+
+ // these values are not affected by zooming (ideal positions)
+ offsetY = offsetY / scaleY + scrollY - columnHeight; //this.columnHeaderHeightAndMarginTop;
+
+ return offsetY;
+}
diff --git a/packages/core/src/sheets/util.ts b/packages/core/src/sheets/util.ts
index 9258b8d3d91..ecb77b00e13 100644
--- a/packages/core/src/sheets/util.ts
+++ b/packages/core/src/sheets/util.ts
@@ -24,6 +24,11 @@ import { Rectangle } from '../shared';
import { type CellValueType, HorizontalAlign, type TextDirection, VerticalAlign, WrapStrategy } from '../types/enum';
import { CustomRangeType, type IDocumentData, type IPaddingData, type IStyleBase, type IStyleData, type ITextRotation, type ITextStyle } from '../types/interfaces';
+export interface IFontLocale {
+ fontList: string[];
+ defaultFontSize: number;
+}
+
export const isRangesEqual = (oldRanges: IRange[], ranges: IRange[]): boolean => {
return ranges.length === oldRanges.length && !oldRanges.some((oldRange) => ranges.some((range) => !Rectangle.equals(range, oldRange)));
};
diff --git a/packages/engine-render/src/components/skeleton.ts b/packages/core/src/skeleton.ts
similarity index 90%
rename from packages/engine-render/src/components/skeleton.ts
rename to packages/core/src/skeleton.ts
index c959cc3c85d..7b5479cf353 100644
--- a/packages/engine-render/src/components/skeleton.ts
+++ b/packages/core/src/skeleton.ts
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-import type { IFontLocale } from '../basics/interfaces';
-import { Disposable, Inject, LocaleService } from '@univerjs/core';
+import type { IFontLocale } from './sheets/util';
+import { Inject } from '@wendellhu/redi';
+import { LocaleService } from './services/locale/locale.service';
+import { Disposable } from './shared/lifecycle';
export class Skeleton extends Disposable {
private _fontLocale!: IFontLocale;
diff --git a/packages/engine-render/src/basics/interfaces.ts b/packages/engine-render/src/basics/interfaces.ts
index d85dfc23400..acdc27e6380 100644
--- a/packages/engine-render/src/basics/interfaces.ts
+++ b/packages/engine-render/src/basics/interfaces.ts
@@ -58,6 +58,12 @@ export interface IRect extends ISize, IOffset {
points: Vector2[];
}
+/**
+ * width
+ * height
+ * scaleX
+ * scaleY
+ */
export interface ISceneTransformState extends ISize, IScale {}
export enum TRANSFORM_CHANGE_OBSERVABLE_TYPE {
diff --git a/packages/engine-render/src/basics/tools.ts b/packages/engine-render/src/basics/tools.ts
index 912ebfd8be4..bcbb2a52230 100644
--- a/packages/engine-render/src/basics/tools.ts
+++ b/packages/engine-render/src/basics/tools.ts
@@ -528,7 +528,7 @@ export function getCellPositionByIndex(
* @param {number} column The column index of the cell
* @param {number[]} rowHeightAccumulation The accumulated height of each row
* @param {number[]} columnWidthAccumulation The accumulated width of each column
- * @param {ICellInfo} mergeData The merge information of the cell
+ * @param {ICellInfo} mergeDataInfo The merge information of the cell
* @returns {ICellWithCoord} The cell position information of the specified row and column, including the position information of the cell and the merge information of the cell
*/
export function getCellWithCoordByIndexCore(
@@ -706,13 +706,13 @@ export function pixelToPt(px: number) {
}
/**
- * 当前单元格在任意一个 viewRanges 中
+ * Is cell in view ranges.
* @param ranges
* @param rowIndex
* @param colIndex
- * @returns
+ * @returns boolean
*/
-export function inViewRanges(ranges: IRange[], rowIndex: number, colIndex: number) {
+export function inViewRanges(ranges: IRange[], rowIndex: number, colIndex: number): boolean {
for (const range of ranges) {
if (rowIndex >= range.startRow && rowIndex <= range.endRow &&
colIndex >= range.startColumn && colIndex <= range.endColumn) {
@@ -722,36 +722,6 @@ export function inViewRanges(ranges: IRange[], rowIndex: number, colIndex: numbe
return false;
}
-/**
- * 在非下方区域中
- * @param ranges
- * @param rowIndex
- */
-export function inCurrentAndAboveViewRanges(ranges: IRange[], rowIndex: number) {
- for (const range of ranges) {
- if (rowIndex > range.endRow) {
- return false;
- }
- }
- return true;
-}
-
-/**
- * row 在任意一个 Range 中
- * @param ranges
- * @param rowIndex
- */
-export function inRowViewRanges(ranges: IRange[], rowIndex: number) {
- let flag = false;
- for (const range of ranges) {
- if (rowIndex >= range.startRow && rowIndex <= range.endRow) {
- flag = true;
- break;
- }
- }
- return flag;
-}
-
/**
* If there is an intersection in ranges to the mainRanges, extend it to the first set of ranges.
* @param {IRange[]} mainRanges target ranges
@@ -778,7 +748,9 @@ export function clampRange(range: IRange, maxRow: number, maxColumn: number) {
};
}
-// Get system highlight color in rgb format.
+/**
+ * Get system highlight color in rgb format.
+ */
export function getSystemHighlightColor() {
const hiddenEle = document.createElement('div');
hiddenEle.style.width = '0';
diff --git a/packages/engine-render/src/components/docs/layout/doc-skeleton.ts b/packages/engine-render/src/components/docs/layout/doc-skeleton.ts
index 90603ef8b0c..a836c290642 100644
--- a/packages/engine-render/src/components/docs/layout/doc-skeleton.ts
+++ b/packages/engine-render/src/components/docs/layout/doc-skeleton.ts
@@ -25,10 +25,9 @@ import type { IDocsConfig, INodeInfo, INodePosition, INodeSearch } from '../../.
import type { IViewportInfo, Vector2 } from '../../../basics/vector2';
import type { DocumentViewModel } from '../view-model/document-view-model';
import type { ILayoutContext } from './tools';
-import { PRESET_LIST_TYPE, SectionType } from '@univerjs/core';
+import { PRESET_LIST_TYPE, SectionType, Skeleton } from '@univerjs/core';
import { Subject } from 'rxjs';
import { DocumentSkeletonPageType, GlyphType, LineType, PageLayoutType } from '../../../basics/i-document-skeleton-cached';
-import { Skeleton } from '../../skeleton';
import { Liquid } from '../liquid';
import { DocumentEditArea } from '../view-model/document-view-model';
import { dealWithSection } from './block/section';
diff --git a/packages/engine-render/src/components/index.ts b/packages/engine-render/src/components/index.ts
index 0e4c91ef075..b2490abde2b 100644
--- a/packages/engine-render/src/components/index.ts
+++ b/packages/engine-render/src/components/index.ts
@@ -17,6 +17,5 @@
export * from './component';
export * from './extension';
export * from './sheets';
-export { RENDER_RAW_FORMULA_KEY } from './sheets/sheet-skeleton';
-export * from './skeleton';
+export { RENDER_RAW_FORMULA_KEY } from './sheets/sheet.render-skeleton';
export * from './slides';
diff --git a/packages/engine-render/src/components/sheets/column-header.ts b/packages/engine-render/src/components/sheets/column-header.ts
index b351b956b6d..65c7297ba13 100644
--- a/packages/engine-render/src/components/sheets/column-header.ts
+++ b/packages/engine-render/src/components/sheets/column-header.ts
@@ -20,7 +20,7 @@ import type { Nullable } from '@univerjs/core';
import type { IViewportInfo, Vector2 } from '../../basics/vector2';
import type { UniverRenderingContext } from '../../context';
import type { ColumnHeaderLayout, IColumnsHeaderCfgParam } from './extensions/column-header-layout';
-import type { SpreadsheetSkeleton } from './sheet-skeleton';
+import type { SpreadsheetSkeleton } from './sheet.render-skeleton';
import { SheetColumnHeaderExtensionRegistry } from '../extension';
import { SpreadsheetHeader } from './sheet-component';
diff --git a/packages/engine-render/src/components/sheets/extensions/background.ts b/packages/engine-render/src/components/sheets/extensions/background.ts
index db08e1af7bc..4b3efb904de 100644
--- a/packages/engine-render/src/components/sheets/extensions/background.ts
+++ b/packages/engine-render/src/components/sheets/extensions/background.ts
@@ -17,7 +17,7 @@
import type { ICellWithCoord, IRange, IScale, ObjectMatrix } from '@univerjs/core';
import type { UniverRenderingContext } from '../../../context';
import type { IDrawInfo } from '../../extension';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
+import type { SpreadsheetSkeleton } from '../sheet.render-skeleton';
import type { Spreadsheet } from '../spreadsheet';
import { Range } from '@univerjs/core';
import { fixLineWidthByScale, getColor, inViewRanges } from '../../../basics/tools';
diff --git a/packages/engine-render/src/components/sheets/extensions/border.ts b/packages/engine-render/src/components/sheets/extensions/border.ts
index d7280f7e22f..f84e043eee0 100644
--- a/packages/engine-render/src/components/sheets/extensions/border.ts
+++ b/packages/engine-render/src/components/sheets/extensions/border.ts
@@ -19,7 +19,7 @@ import type { UniverRenderingContext } from '../../../context';
import type { IDrawInfo } from '../../extension';
import type { BorderCache, BorderCacheItem } from '../interfaces';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
+import type { SpreadsheetSkeleton } from '../sheet.render-skeleton';
import { BorderStyleTypes, Range } from '@univerjs/core';
import { BORDER_TYPE as BORDER_LTRB, COLOR_BLACK_RGB, FIX_ONE_PIXEL_BLUR_OFFSET } from '../../../basics/const';
import { drawDiagonalLineByBorderType, drawLineByBorderType, getLineWidth, setLineType } from '../../../basics/draw';
diff --git a/packages/engine-render/src/components/sheets/extensions/column-header-layout.ts b/packages/engine-render/src/components/sheets/extensions/column-header-layout.ts
index bae1a2b7b2a..08290110a6e 100644
--- a/packages/engine-render/src/components/sheets/extensions/column-header-layout.ts
+++ b/packages/engine-render/src/components/sheets/extensions/column-header-layout.ts
@@ -18,7 +18,7 @@ import type { IScale } from '@univerjs/core';
import type { UniverRenderingContext } from '../../../context';
import type { IAColumnCfg, IAColumnCfgObj, IColumnStyleCfg } from '../interfaces';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
+import type { SpreadsheetSkeleton } from '../sheet.render-skeleton';
import { numberToABC } from '@univerjs/core';
import { DEFAULT_FONTFACE_PLANE, FIX_ONE_PIXEL_BLUR_OFFSET, MIDDLE_CELL_POS_MAGIC_NUMBER } from '../../../basics/const';
import { getColor } from '../../../basics/tools';
diff --git a/packages/engine-render/src/components/sheets/extensions/custom.ts b/packages/engine-render/src/components/sheets/extensions/custom.ts
index 5732ddd4bcb..765c2abd44f 100644
--- a/packages/engine-render/src/components/sheets/extensions/custom.ts
+++ b/packages/engine-render/src/components/sheets/extensions/custom.ts
@@ -16,7 +16,7 @@
import type { IRange, IScale } from '@univerjs/core';
import type { UniverRenderingContext } from '../../../context';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
+import type { SpreadsheetSkeleton } from '../sheet.render-skeleton';
import { Range, sortRules } from '@univerjs/core';
import { SpreadsheetExtensionRegistry } from '../../extension';
import { SheetExtension } from './sheet-extension';
@@ -83,7 +83,7 @@ export class Custom extends SheetExtension {
const renderInfo = {
data: cellData,
- style: skeleton.getsStyles().getStyleByCell(cellData),
+ style: skeleton.getStyles().getStyleByCell(cellData),
primaryWithCoord,
subUnitId,
row,
diff --git a/packages/engine-render/src/components/sheets/extensions/font.ts b/packages/engine-render/src/components/sheets/extensions/font.ts
index 18233cc7cd1..feab656cd46 100644
--- a/packages/engine-render/src/components/sheets/extensions/font.ts
+++ b/packages/engine-render/src/components/sheets/extensions/font.ts
@@ -23,14 +23,13 @@ import type { Documents } from '../../docs/document';
import type { IDrawInfo } from '../../extension';
import type { IFontCacheItem } from '../interfaces';
import type { SheetComponent } from '../sheet-component';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
import { HorizontalAlign, Range, VerticalAlign, WrapStrategy } from '@univerjs/core';
import { FIX_ONE_PIXEL_BLUR_OFFSET } from '../../../basics';
import { VERTICAL_ROTATE_ANGLE } from '../../../basics/text-rotation';
import { clampRange, inViewRanges } from '../../../basics/tools';
import { SpreadsheetExtensionRegistry } from '../../extension';
import { EXPAND_SIZE_FOR_RENDER_OVERFLOW, FONT_EXTENSION_Z_INDEX } from '../constants';
-import { getDocsSkeletonPageSize } from '../sheet-skeleton';
+import { getDocsSkeletonPageSize, type SpreadsheetSkeleton } from '../sheet.render-skeleton';
import { SheetExtension } from './sheet-extension';
const UNIQUE_KEY = 'DefaultFontExtension';
@@ -139,6 +138,7 @@ export class Font extends SheetExtension {
Range.foreach(range, (row, col) => {
const index = spreadsheetSkeleton.worksheet.getSpanModel().getMergeDataIndex(row, col);
+ // put all merged cells to another pass to render. -1 means not merged.
if (index !== -1) {
return;
}
diff --git a/packages/engine-render/src/components/sheets/extensions/marker.ts b/packages/engine-render/src/components/sheets/extensions/marker.ts
index 36e92240a46..dea84a9b530 100644
--- a/packages/engine-render/src/components/sheets/extensions/marker.ts
+++ b/packages/engine-render/src/components/sheets/extensions/marker.ts
@@ -16,7 +16,7 @@
import type { IRange, IScale } from '@univerjs/core';
import type { UniverRenderingContext } from '../../../context';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
+import type { SpreadsheetSkeleton } from '../sheet.render-skeleton';
import { Range } from '@univerjs/core';
import { SpreadsheetExtensionRegistry } from '../../extension';
import { SheetExtension } from './sheet-extension';
diff --git a/packages/engine-render/src/components/sheets/extensions/row-header-layout.ts b/packages/engine-render/src/components/sheets/extensions/row-header-layout.ts
index bcc594a3c60..cd8c9b61dd4 100644
--- a/packages/engine-render/src/components/sheets/extensions/row-header-layout.ts
+++ b/packages/engine-render/src/components/sheets/extensions/row-header-layout.ts
@@ -18,7 +18,7 @@ import type { IScale } from '@univerjs/core';
import type { UniverRenderingContext } from '../../../context';
import type { IARowCfg, IARowCfgObj, IColumnStyleCfg, IRowStyleCfg } from '../interfaces';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
+import type { SpreadsheetSkeleton } from '../sheet.render-skeleton';
import { DEFAULT_FONTFACE_PLANE, FIX_ONE_PIXEL_BLUR_OFFSET, MIDDLE_CELL_POS_MAGIC_NUMBER } from '../../../basics/const';
import { getColor } from '../../../basics/tools';
import { SheetRowHeaderExtensionRegistry } from '../../extension';
diff --git a/packages/engine-render/src/components/sheets/extensions/sheet-extension.ts b/packages/engine-render/src/components/sheets/extensions/sheet-extension.ts
index 11410d2c654..9ba399d6525 100644
--- a/packages/engine-render/src/components/sheets/extensions/sheet-extension.ts
+++ b/packages/engine-render/src/components/sheets/extensions/sheet-extension.ts
@@ -15,7 +15,7 @@
*/
import type { IRange } from '@univerjs/core';
-import type { SpreadsheetSkeleton } from '../sheet-skeleton';
+import type { SpreadsheetSkeleton } from '../sheet.render-skeleton';
import { Rectangle } from '@univerjs/core';
import { ComponentExtension } from '../../extension';
diff --git a/packages/engine-render/src/components/sheets/index.ts b/packages/engine-render/src/components/sheets/index.ts
index d0f83cfbe9b..9603bde0949 100644
--- a/packages/engine-render/src/components/sheets/index.ts
+++ b/packages/engine-render/src/components/sheets/index.ts
@@ -20,5 +20,5 @@ export * from './extensions';
export * from './interfaces';
export * from './row-header';
export * from './sheet-component';
-export * from './sheet-skeleton';
+export * from './sheet.render-skeleton';
export * from './spreadsheet';
diff --git a/packages/engine-render/src/components/sheets/row-header.ts b/packages/engine-render/src/components/sheets/row-header.ts
index eab3eef615a..e4b4ed0fb85 100644
--- a/packages/engine-render/src/components/sheets/row-header.ts
+++ b/packages/engine-render/src/components/sheets/row-header.ts
@@ -18,7 +18,7 @@ import type { Nullable } from '@univerjs/core';
import type { IViewportInfo, Vector2 } from '../../basics/vector2';
import type { UniverRenderingContext } from '../../context';
import type { IRowsHeaderCfgParam, RowHeaderLayout } from './extensions/row-header-layout';
-import type { SpreadsheetSkeleton } from './sheet-skeleton';
+import type { SpreadsheetSkeleton } from './sheet.render-skeleton';
import { SheetRowHeaderExtensionRegistry } from '../extension';
import { SpreadsheetHeader } from './sheet-component';
diff --git a/packages/engine-render/src/components/sheets/sheet-component.ts b/packages/engine-render/src/components/sheets/sheet-component.ts
index 2cb76d98286..b899d3b3248 100644
--- a/packages/engine-render/src/components/sheets/sheet-component.ts
+++ b/packages/engine-render/src/components/sheets/sheet-component.ts
@@ -19,7 +19,7 @@ import type { IRange, Nullable } from '@univerjs/core';
import type { IViewportInfo, Vector2 } from '../../basics/vector2';
import type { UniverRenderingContext } from '../../context';
import type { SHEET_EXTENSION_TYPE } from './extensions/sheet-extension';
-import type { SpreadsheetSkeleton } from './sheet-skeleton';
+import type { SpreadsheetSkeleton } from './sheet.render-skeleton';
import { RENDER_CLASS_TYPE } from '../../basics/const';
import { RenderComponent } from '../component';
diff --git a/packages/engine-render/src/components/sheets/sheet-skeleton.ts b/packages/engine-render/src/components/sheets/sheet.render-skeleton.ts
similarity index 64%
rename from packages/engine-render/src/components/sheets/sheet-skeleton.ts
rename to packages/engine-render/src/components/sheets/sheet.render-skeleton.ts
index 136d42691a3..cf5524c2a00 100644
--- a/packages/engine-render/src/components/sheets/sheet-skeleton.ts
+++ b/packages/engine-render/src/components/sheets/sheet.render-skeleton.ts
@@ -16,56 +16,51 @@
import type {
BorderStyleTypes,
+ DocumentDataModel,
IBorderStyleData,
ICellData,
ICellDataForSheetInterceptor,
ICellInfo,
ICellWithCoord,
IColAutoWidthInfo,
- IColumnData,
IColumnRange,
- IDocumentData,
- IDocumentRenderConfig,
- IObjectArrayPrimitiveType,
+ IGetRowColByPosOptions,
IPaddingData,
- IPosition,
IRange,
IRowAutoHeightInfo,
- IRowData,
IRowRange,
- ISelectionCell,
ISize,
IStyleData,
ITextRotation,
- IWorksheetData,
Nullable,
Styles,
VerticalAlign,
- Worksheet } from '@univerjs/core';
+
+ Worksheet,
+} from '@univerjs/core';
import type { IDocumentSkeletonColumn } from '../../basics/i-document-skeleton-cached';
-import type { IBoundRectNoAngle, IPoint, IViewportInfo } from '../../basics/vector2';
+import type { ITransformChangeState } from '../../basics/interfaces';
+import type { IBoundRectNoAngle, IViewportInfo } from '../../basics/vector2';
+import type { Scene } from '../../scene';
import {
addLinkToDocumentModel,
BooleanNumber,
CellValueType,
composeStyles,
DEFAULT_STYLES,
- DocumentDataModel,
extractPureTextFromCell,
getColorStyle,
HorizontalAlign,
IConfigService,
IContextService,
- ImageCacheMap,
Inject,
Injector,
- IS_ROW_STYLE_PRECEDE_COLUMN_STYLE,
- isCellCoverable,
isNullCell,
isWhiteColor,
LocaleService,
ObjectMatrix,
searchArray,
+ SheetSkeleton,
Tools,
WrapStrategy,
} from '@univerjs/core';
@@ -75,74 +70,15 @@ import { getRotateOffsetAndFarthestHypotenuse } from '../../basics/draw';
import { convertTextRotation, VERTICAL_ROTATE_ANGLE } from '../../basics/text-rotation';
import {
degToRad,
- getCellPositionByIndex,
- getCellWithCoordByIndexCore,
getFontStyleString,
- isRectIntersect,
} from '../../basics/tools';
import { DocumentSkeleton } from '../docs/layout/doc-skeleton';
import { columnIterator } from '../docs/layout/tools';
import { DocumentViewModel } from '../docs/view-model/document-view-model';
-import { Skeleton } from '../skeleton';
import { EXPAND_SIZE_FOR_RENDER_OVERFLOW, MEASURE_EXTENT, MEASURE_EXTENT_FOR_PARAGRAPH } from './constants';
import { type BorderCache, type IFontCacheItem, type IStylesCache, SHEET_VIEWPORT_KEY } from './interfaces';
import { createDocumentModelWithStyle, extractOtherStyle, getFontFormat } from './util';
-/**
- * Obtain the height and width of a cell's text, taking into account scenarios with rotated text.
- * @param documentSkeleton Data of the document's ViewModel
- * @param angleInDegree The rotation angle of an Excel cell, it's **degree**
- */
-export function getDocsSkeletonPageSize(documentSkeleton: DocumentSkeleton, angleInDegree: number = 0): Nullable> {
- const skeletonData = documentSkeleton?.getSkeletonData();
- const angle = degToRad(angleInDegree);
-
- if (!skeletonData) {
- return null;
- }
- const { pages } = skeletonData;
- const lastPage = pages[pages.length - 1];
- const { width, height } = lastPage;
-
- if (angle === 0) {
- return { width, height };
- }
-
- if (Math.abs(angle) === Math.PI / 2) {
- return { width: height, height: width };
- }
-
- let allRotatedWidth = 0;
- let allRotatedHeight = 0;
-
- const widthArray: Array<{ rotatedWidth: number; spaceWidth: number }> = [];
-
- columnIterator([lastPage], (column: IDocumentSkeletonColumn) => {
- const { lines, width: columnWidth, spaceWidth } = column;
-
- const { rotatedHeight, rotatedWidth } = getRotateOffsetAndFarthestHypotenuse(lines, columnWidth, angle);
-
- allRotatedHeight += rotatedHeight;
-
- widthArray.push({ rotatedWidth, spaceWidth });
- });
-
- const widthCount = widthArray.length;
-
- for (let i = 0; i < widthCount; i++) {
- const { rotatedWidth } = widthArray[i];
-
- if (i === 0) {
- allRotatedWidth += rotatedWidth;
- }
- }
-
- return {
- width: allRotatedWidth,
- height: allRotatedHeight,
- };
-}
-
interface ICellDocumentModelOption {
isDeepClone?: boolean;
displayRawFormula?: boolean;
@@ -181,17 +117,6 @@ export interface ICacheItem {
border: boolean;
}
-export interface IGetRowColByPosOptions {
- closeFirst?: boolean;
-
- /**
- * For searchArray(rowHeightAccumulation) & searchArray(colWidthAccumulation)
- * true means return first matched index in matched sequence.
- * default return last index in matched sequence.
- */
- firstMatch?: boolean;
-}
-
export interface IGetPosByRowColOptions {
closeFirst?: boolean;
@@ -202,15 +127,7 @@ export interface IGetPosByRowColOptions {
firstMatch?: boolean;
}
-export class SpreadsheetSkeleton extends Skeleton {
- private _rowHeightAccumulation: number[] = [];
- private _columnWidthAccumulation: number[] = [];
-
- private _rowTotalHeight = 0;
- private _columnTotalWidth = 0;
- private _rowHeaderWidth = 0;
- private _columnHeaderHeight = 0;
-
+export class SpreadsheetSkeleton extends SheetSkeleton {
/**
* Range viewBounds. only update by viewBounds.
* It would change multiple times in one frame if there is multiple viewport (after freeze row&col)
@@ -242,68 +159,50 @@ export class SpreadsheetSkeleton extends Skeleton {
private _showGridlines: BooleanNumber = BooleanNumber.TRUE;
private _gridlinesColor: string | undefined = undefined;
- private _marginTop: number = 0;
- private _marginLeft: number = 0;
-
- private _imageCacheMap: ImageCacheMap;
- /**
- * Whether the row style precedes the column style.
- */
- private _isRowStylePrecedeColumnStyle = false;
-
- private _renderRawFormula = false;
-
- /**
- * @deprecated avoid use `IWorksheetData` directly, use API provided by `Worksheet`, otherwise
- * `ViewModel` will be not working.
- */
- private _worksheetData: IWorksheetData;
- private _cellData: ObjectMatrix>;
+ private _scene: Nullable = null;
constructor(
- readonly worksheet: Worksheet,
- private _styles: Styles,
+ worksheet: Worksheet,
+ _styles: Styles,
@Inject(LocaleService) _localeService: LocaleService,
- @IContextService private readonly _contextService: IContextService,
- @IConfigService private readonly _configService: IConfigService,
- @Inject(Injector) private _injector: Injector
+ @IContextService _contextService: IContextService,
+ @IConfigService _configService: IConfigService,
+ @Inject(Injector) _injector: Injector
) {
- super(_localeService);
- this._worksheetData = this.worksheet.getConfig();
- this._cellData = this.worksheet.getCellMatrix();
-
- this._imageCacheMap = new ImageCacheMap(this._injector);
- this._updateLayout();
- this._initContextListener();
- this._isRowStylePrecedeColumnStyle = this._configService.getConfig(IS_ROW_STYLE_PRECEDE_COLUMN_STYLE) ?? false;
- }
-
- get rowHeightAccumulation(): number[] {
- return this._rowHeightAccumulation;
+ super(worksheet, _styles, _localeService, _contextService, _configService, _injector);
}
- get rowTotalHeight(): number {
- return this._rowTotalHeight;
- }
-
- get columnWidthAccumulation(): number[] {
- return this._columnWidthAccumulation;
+ override init() {
+ this._updateLayout();
+ this.disposeWithMe(
+ this._contextService.subscribeContextValue$(RENDER_RAW_FORMULA_KEY).pipe(
+ startWith(false),
+ distinctUntilChanged()
+ ).subscribe((renderRaw) => {
+ this._renderRawFormula = renderRaw;
+ this._resetCache();
+ this.makeDirty(true);
+ })
+ );
}
- get columnTotalWidth(): number {
- return this._columnTotalWidth;
- }
+ setScene(scene: Scene) {
+ this._scene = scene;
- get rowHeaderWidth(): number {
- return this._rowHeaderWidth;
+ this._scene.onTransformChange$.subscribeEvent((param: ITransformChangeState) => {
+ this.setScale(param.value.scaleX || 1, param.value.scaleY);
+ });
}
- get columnHeaderHeight(): number {
- return this._columnHeaderHeight;
- }
+ override _updateLayout() {
+ const {
+ showGridlines,
+ gridlinesColor,
+ } = this._worksheetData;
- get imageCacheMap(): ImageCacheMap {
- return this._imageCacheMap;
+ this._showGridlines = showGridlines;
+ this._gridlinesColor = gridlinesColor;
+ super._updateLayout(); // make dirty false
}
/**
@@ -322,10 +221,6 @@ export class SpreadsheetSkeleton extends Skeleton {
return this._cacheRangeMap.get(viewportKey);
}
- // get dataMergeCache(): IRange[] {
- // return this._dataMergeCache;
- // }
-
get stylesCache(): IStylesCache {
return this._stylesCache;
}
@@ -342,34 +237,15 @@ export class SpreadsheetSkeleton extends Skeleton {
return this._gridlinesColor;
}
- get mergeData(): IRange[] {
- return this._worksheetData.mergeData;
- }
-
- get rowHeaderWidthAndMarginLeft(): number {
- return this.rowHeaderWidth + this._marginLeft;
- }
-
- get columnHeaderHeightAndMarginTop(): number {
- return this.columnHeaderHeight + this._marginTop;
- }
-
override dispose(): void {
super.dispose();
- this._rowHeightAccumulation = [];
- this._columnWidthAccumulation = [];
- this._rowTotalHeight = 0;
- this._columnTotalWidth = 0;
- this._rowHeaderWidth = 0;
- this._columnHeaderHeight = 0;
this._drawingRange = {
startRow: -1,
endRow: -1,
startColumn: -1,
endColumn: -1,
};
- // this._dataMergeCache = [];
this._stylesCache = {
background: {},
backgroundPositions: new ObjectMatrix(),
@@ -380,52 +256,19 @@ export class SpreadsheetSkeleton extends Skeleton {
this._handleBgMatrix.reset();
this._handleBorderMatrix.reset();
this._overflowCache.reset();
-
- this._worksheetData = null as unknown as IWorksheetData;
- this._cellData = null as unknown as ObjectMatrix>;
- this._styles = null as unknown as Styles;
}
/**
* @deprecated should never expose a property that is provided by another module!
*/
- getsStyles(): Styles {
+ getStyles(): Styles {
return this._styles;
}
- /**
- * Get which Workbook and Worksheet this skeleton is attached to.
- * @returns [unitId, sheetId]
- */
- getLocation(): [string, string] {
- return [this.worksheet.getUnitId(), this.worksheet.getSheetId()];
- }
-
- private _initContextListener(): void {
- this.disposeWithMe(
- this._contextService.subscribeContextValue$(RENDER_RAW_FORMULA_KEY).pipe(
- startWith(false),
- distinctUntilChanged()
- ).subscribe((renderRaw) => {
- this._renderRawFormula = renderRaw;
- this._resetCache();
- this.makeDirty(true);
- })
- );
- }
-
setOverflowCache(value: ObjectMatrix): void {
this._overflowCache = value;
}
- setMarginLeft(left: number): void {
- this._marginLeft = left;
- }
-
- setMarginTop(top: number): void {
- this._marginTop = top;
- }
-
getFont(rowIndex: number, columnIndex: number): Nullable {
const fontCache = this.stylesCache.fontMatrix;
if (!fontCache) {
@@ -444,7 +287,7 @@ export class SpreadsheetSkeleton extends Skeleton {
* @returns boolean
*/
updateVisibleRange(vpInfo?: IViewportInfo): boolean {
- if (!this._worksheetData || !this._rowHeightAccumulation || !this._columnWidthAccumulation) {
+ if (!this._worksheetData || !this.rowHeightAccumulation || !this.columnWidthAccumulation) {
return false;
}
@@ -474,7 +317,7 @@ export class SpreadsheetSkeleton extends Skeleton {
*/
setStylesCache(vpInfo?: IViewportInfo): Nullable {
if (!this._worksheetData) return;
- if (!this._rowHeightAccumulation || !this._columnWidthAccumulation) return;
+ if (!this.rowHeightAccumulation || !this.columnWidthAccumulation) return;
this.updateVisibleRange(vpInfo);
@@ -516,34 +359,6 @@ export class SpreadsheetSkeleton extends Skeleton {
return this;
}
- /**
- * Refresh cache after markDirty by SheetSkeletonManagerService.reCalculate()
- * @param bounds
- */
- calculate(): Nullable {
- this._resetCache();
- this._updateLayout();
-
- return this;
- }
-
- private _hasUnMergedCellInRow(rowIndex: number, startColumn: number, endColumn: number): boolean {
- const mergeData = this.worksheet.getMergeData();
- if (!mergeData) {
- return false;
- }
-
- for (let i = startColumn; i <= endColumn; i++) {
- const { isMerged, isMergedMainCell } = this.worksheet.getCellInfoInMergeData(rowIndex, i);
-
- if (!isMerged && !isMergedMainCell) {
- return true;
- }
- }
-
- return false;
- }
-
//#region auto height
/**
* Calc all auto height by getDocsSkeletonPageSize in ranges
@@ -746,14 +561,14 @@ export class SpreadsheetSkeleton extends Skeleton {
const rowIdxArr = createRowSequence(checkStartRow, checkEndRow, otherRowIndex);
const preColIndex = Math.max(0, colIndex - 1);
- let currColWidth = this._columnWidthAccumulation[colIndex] - this._columnWidthAccumulation[preColIndex];
+ let currColWidth = this.columnWidthAccumulation[colIndex] - this.columnWidthAccumulation[preColIndex];
if (colIndex === 0) {
- currColWidth = this._columnWidthAccumulation[colIndex];
+ currColWidth = this.columnWidthAccumulation[colIndex];
}
for (let i = 0; i < rowIdxArr.length; i++) {
const row = rowIdxArr[i];
- const { isMerged, isMergedMainCell } = this._getCellMergeInfo(colIndex, row);
+ const { isMerged, isMergedMainCell } = this.worksheet.getCellInfoInMergeData(colIndex, row);
if (isMerged && !isMergedMainCell) continue;
if (!this.worksheet.getRowVisible(row)) continue;
const cell = worksheet.getCell(row, colIndex);
@@ -780,7 +595,7 @@ export class SpreadsheetSkeleton extends Skeleton {
/**
* For _calculateColMaxWidth
* @param cell
- * @returns {number} width
+ * @returns {number} currColWidth
*/
_getMeasuredWidthByCell(cell: ICellDataForSheetInterceptor, currColWidth: number) {
let measuredWidth = 0;
@@ -841,159 +656,24 @@ export class SpreadsheetSkeleton extends Skeleton {
};
//#endregion
- /**
- * Calculate data for row col & cell position.
- * This method should be called whenever a sheet is dirty.
- * Update position value to this._rowHeaderWidth & this._rowHeightAccumulation & this._columnHeaderHeight & this._columnWidthAccumulation.
- */
- private _updateLayout(): void {
- if (!this.dirty) {
- return;
- }
-
- const {
- rowData,
- columnData,
- defaultRowHeight,
- defaultColumnWidth,
- rowCount,
- columnCount,
- rowHeader,
- columnHeader,
- showGridlines,
- gridlinesColor,
- } = this._worksheetData;
-
- const { rowTotalHeight, rowHeightAccumulation } = this._generateRowMatrixCache(
- rowCount,
- rowData,
- defaultRowHeight
- );
-
- const { columnTotalWidth, columnWidthAccumulation } = this._generateColumnMatrixCache(
- columnCount,
- columnData,
- defaultColumnWidth
- );
-
- this._rowHeaderWidth = rowHeader.hidden !== BooleanNumber.TRUE ? this._dynamicallyUpdateRowHeaderWidth(rowHeader) : 0;
- this._columnHeaderHeight = columnHeader.hidden !== BooleanNumber.TRUE ? columnHeader.height : 0;
-
- this._rowTotalHeight = rowTotalHeight;
- this._rowHeightAccumulation = rowHeightAccumulation;
- this._columnTotalWidth = columnTotalWidth;
- this._columnWidthAccumulation = columnWidthAccumulation;
- this._showGridlines = showGridlines;
- this._gridlinesColor = gridlinesColor;
-
- this.makeDirty(false);
- }
-
- private _dynamicallyUpdateRowHeaderWidth(rowHeader: { width: number }): number {
- const SIZE_BY_EACH_CHARACTER = 8;
- const widthByComputation = (`${this.worksheet.getRowCount()}`.length * SIZE_BY_EACH_CHARACTER);
- return Math.max(rowHeader.width, widthByComputation);
- }
-
/**
* @deprecated use `getRangeByViewport` instead.
* @param bounds
*/
getRangeByBounding(bounds?: IViewportInfo): IRange {
- return this._getRangeByViewBounding(this._rowHeightAccumulation, this._columnWidthAccumulation, bounds?.cacheBound);
+ return this._getRangeByViewBounding(this.rowHeightAccumulation, this.columnWidthAccumulation, bounds?.cacheBound);
}
getRangeByViewport(vpInfo?: IViewportInfo): IRange {
- return this._getRangeByViewBounding(this._rowHeightAccumulation, this._columnWidthAccumulation, vpInfo?.viewBound);
+ return this._getRangeByViewBounding(this.rowHeightAccumulation, this.columnWidthAccumulation, vpInfo?.viewBound);
}
getCacheRangeByViewport(vpInfo?: IViewportInfo): IRange {
- return this._getRangeByViewBounding(this._rowHeightAccumulation, this._columnWidthAccumulation, vpInfo?.cacheBound);
+ return this._getRangeByViewBounding(this.rowHeightAccumulation, this.columnWidthAccumulation, vpInfo?.cacheBound);
}
getRangeByViewBound(bound?: IBoundRectNoAngle): IRange {
- return this._getRangeByViewBounding(this._rowHeightAccumulation, this._columnWidthAccumulation, bound);
- }
-
- /**
- * @deprecated should never expose a property that is provided by another module!
- * @returns
- */
- getWorksheetConfig(): IWorksheetData {
- return this._worksheetData;
- }
-
- getMergeBounding(startRow: number, startColumn: number, endRow: number, endColumn: number): IRange {
- const mergeData = this._worksheetData.mergeData;
- if (!mergeData) {
- return {
- startRow,
- startColumn,
- endRow,
- endColumn,
- };
- }
-
- let isSearching = true;
- const searchedMarge = new ObjectMatrix();
-
- // the loop breaks when there are not merged cells intersect with the current range
- // NOTE: what about the performance issue?
- while (isSearching) {
- isSearching = false;
-
- for (let i = 0; i < mergeData.length; i++) {
- const {
- startRow: mainStartRow,
- startColumn: mainStartColumn,
- endRow: mainEndRow,
- endColumn: mainEndColumn,
- } = mergeData[i];
-
- if (searchedMarge.getValue(mainStartRow, mainStartColumn)) {
- continue;
- }
-
- const rect1 = {
- left: startColumn,
- top: startRow,
- right: endColumn,
- bottom: endRow,
- };
-
- const rect2 = {
- left: mainStartColumn,
- top: mainStartRow,
- right: mainEndColumn,
- bottom: mainEndRow,
- };
-
- if (isRectIntersect(rect1, rect2)) {
- startRow = Math.min(startRow, mainStartRow);
- startColumn = Math.min(startColumn, mainStartColumn);
- endRow = Math.max(endRow, mainEndRow);
- endColumn = Math.max(endColumn, mainEndColumn);
- searchedMarge.setValue(mainStartRow, mainStartColumn, true);
- isSearching = true;
- }
- }
- }
-
- return {
- startRow,
- startColumn,
- endRow,
- endColumn,
- };
- }
-
- /**
- * expand curr range if it's intersect with merge range.
- * @param range
- * @returns {IRange} expanded range because merge info.
- */
- expandRangeByMerge(range: IRange): IRange {
- return this.getMergeBounding(range.startRow, range.startColumn, range.endRow, range.endColumn);
+ return this._getRangeByViewBounding(this.rowHeightAccumulation, this.columnWidthAccumulation, bound);
}
appendToOverflowCache(row: number, column: number, startColumn: number, endColumn: number): void {
@@ -1005,14 +685,6 @@ export class SpreadsheetSkeleton extends Skeleton {
});
}
- getColumnCount(): number {
- return this._columnWidthAccumulation.length;
- }
-
- getRowCount(): number {
- return this._rowHeightAccumulation.length;
- }
-
getOverflowPosition(
contentSize: Required,
horizontalAlign: HorizontalAlign,
@@ -1039,65 +711,6 @@ export class SpreadsheetSkeleton extends Skeleton {
};
}
- getNoMergeCellPositionByIndex(rowIndex: number, columnIndex: number): IPosition {
- const {
- rowHeightAccumulation,
- columnWidthAccumulation,
- rowHeaderWidthAndMarginLeft,
- columnHeaderHeightAndMarginTop,
- } = this;
-
- // const rowCount = this.getRowCount();
-
- // const columnCount = this.getColumnCount();
-
- // if (rowIndex >= rowCount || rowIndex < 0 || columnIndex >= columnCount || columnIndex < 0) {
- // return {
- // startY: -100,
- // endY: -100,
- // startX: -100,
- // endX: -100,
- // };
- // }
-
- let { startY, endY, startX, endX } = getCellPositionByIndex(
- rowIndex,
- columnIndex,
- rowHeightAccumulation,
- columnWidthAccumulation
- );
-
- startY += columnHeaderHeightAndMarginTop;
- endY += columnHeaderHeightAndMarginTop;
- startX += rowHeaderWidthAndMarginLeft;
- endX += rowHeaderWidthAndMarginLeft;
-
- return {
- startY,
- endY,
- startX,
- endX,
- };
- }
-
- getNoMergeCellPositionByIndexWithNoHeader(rowIndex: number, columnIndex: number): IPosition {
- const { rowHeightAccumulation, columnWidthAccumulation } = this;
-
- const { startY, endY, startX, endX } = getCellPositionByIndex(
- rowIndex,
- columnIndex,
- rowHeightAccumulation,
- columnWidthAccumulation
- );
-
- return {
- startY,
- endY,
- startX,
- endX,
- };
- }
-
/**
* Get cell by pos(offsetX, offsetY).
* @deprecated Please use `getCellWithCoordByOffset` instead.
@@ -1112,31 +725,6 @@ export class SpreadsheetSkeleton extends Skeleton {
return this.getCellWithCoordByOffset(offsetX, offsetY, scaleX, scaleY, scrollXY);
}
- /**
- * Get cell by pos(offsetX, offsetY).
- *
- * options.matchFirst true means get cell would skip all invisible cells.
- * @param offsetX position X in viewport.
- * @param offsetY position Y in viewport.
- * @param scaleX render scene scale x-axis, scene.getAncestorScale
- * @param scaleY render scene scale y-axis, scene.getAncestorScale
- * @param scrollXY render viewportScroll {x, y}
- * @param options {IGetRowColByPosOptions}
- * @returns {ICellWithCoord} Selection data with coordinates
- */
- getCellWithCoordByOffset(
- offsetX: number,
- offsetY: number,
- scaleX: number,
- scaleY: number,
- scrollXY: { x: number; y: number },
- options?: IGetRowColByPosOptions
- ): ICellWithCoord {
- const { row, column } = this.getCellIndexByOffset(offsetX, offsetY, scaleX, scaleY, scrollXY, options);
-
- return this.getCellWithCoordByIndex(row, column);
- }
-
/**
* This method has the same implementation as `getCellIndexByOffset`,
* but uses a different name to maintain backward compatibility with previous calls.
@@ -1154,55 +742,6 @@ export class SpreadsheetSkeleton extends Skeleton {
return this.getCellIndexByOffset(offsetX, offsetY, scaleX, scaleY, scrollXY, options);
}
- /**
- * Get cell index by offset(o)
- * @param offsetX position X in viewport.
- * @param offsetY position Y in viewport.
- * @param scaleX render scene scale x-axis, scene.getAncestorScale
- * @param scaleY render scene scale y-axis, scene.getAncestorScale
- * @param scrollXY render viewport scroll {x, y}, scene.getScrollXYByRelativeCoords, scene.getScrollXY
- * @param scrollXY.x
- * @param scrollXY.y
- * @returns cell index
- */
- getCellIndexByOffset(
- offsetX: number,
- offsetY: number,
- scaleX: number,
- scaleY: number,
- scrollXY: { x: number; y: number },
- options?: IGetRowColByPosOptions
- ): { row: number; column: number } {
- const row = this.getRowIndexByOffsetY(offsetY, scaleY, scrollXY, options);
- const column = this.getColumnIndexByOffsetX(offsetX, scaleX, scrollXY, options);
-
- return {
- row,
- column,
- };
- }
-
- getCellByOffset(
- offsetX: number,
- offsetY: number,
- scaleX: number,
- scaleY: number,
- scrollXY: { x: number; y: number }
- ): Nullable {
- const cellIndex = this?.getCellIndexByOffset(
- offsetX,
- offsetY,
- scaleX,
- scaleY,
- scrollXY,
- { firstMatch: true } // for visible
- );
- if (!cellIndex) return null;
-
- const selectionCell = this.worksheet.getCellInfoInMergeData(cellIndex.row, cellIndex.column);
- return selectionCell;
- }
-
getCellWithMergeInfoByIndex(row: number, column: number): Nullable {
const selectionCell = this.worksheet.getCellInfoInMergeData(row, column);
return selectionCell;
@@ -1216,28 +755,6 @@ export class SpreadsheetSkeleton extends Skeleton {
return this.getColumnIndexByOffsetX(offsetX, scaleX, scrollXY, options);
}
- /**
- * Get column index by offset x.
- * @param offsetX scaled offset x
- * @param scaleX scale x
- * @param scrollXY scrollXY
- * @returns column index
- */
- getColumnIndexByOffsetX(evtOffsetX: number, scaleX: number, scrollXY: { x: number; y: number }, options?: IGetRowColByPosOptions): number {
- const offsetX = this.getTransformOffsetX(evtOffsetX, scaleX, scrollXY);
- const { columnWidthAccumulation } = this;
- let column = searchArray(columnWidthAccumulation, offsetX, options?.firstMatch);
-
- if (options?.closeFirst) {
- // check if upper column was closer than current
- if (Math.abs(columnWidthAccumulation[column] - offsetX) < Math.abs(offsetX - (columnWidthAccumulation[column - 1] ?? 0))) {
- column = column + 1;
- }
- }
-
- return column;
- }
-
/**
* Same as getRowIndexByOffsetY
* @deprecated Please use `getRowIndexByOffsetY` method instead.
@@ -1246,79 +763,6 @@ export class SpreadsheetSkeleton extends Skeleton {
return this.getRowIndexByOffsetY(offsetY, scaleY, scrollXY, options);
}
- /**
- *
- * @param offsetY scaled offset y
- * @param scaleY scale y
- * @param scrollXY
- * @param scrollXY.x
- * @param scrollXY.y
- */
- getRowIndexByOffsetY(offsetY: number, scaleY: number, scrollXY: { x: number; y: number }, options?: IGetRowColByPosOptions): number {
- const { rowHeightAccumulation } = this;
- offsetY = this.getTransformOffsetY(offsetY, scaleY, scrollXY);
-
- let row = searchArray(rowHeightAccumulation, offsetY, options?.firstMatch);
-
- if (options?.closeFirst) {
- // check if upper row was closer than current
- if (Math.abs(rowHeightAccumulation[row] - offsetY) < Math.abs(offsetY - (rowHeightAccumulation[row - 1] ?? 0))) {
- row = row + 1;
- }
- }
-
- return row;
- }
-
- getTransformOffsetX(offsetX: number, scaleX: number, scrollXY: { x: number; y: number }): number {
- const { x: scrollX } = scrollXY;
-
- // so we should map physical positions to ideal positions
- const afterOffsetX = offsetX / scaleX + scrollX - this.rowHeaderWidthAndMarginLeft;
-
- return afterOffsetX;
- }
-
- getTransformOffsetY(offsetY: number, scaleY: number, scrollXY: { x: number; y: number }): number {
- const { y: scrollY } = scrollXY;
-
- // these values are not affected by zooming (ideal positions)
- offsetY = offsetY / scaleY + scrollY - this.columnHeaderHeightAndMarginTop;
-
- return offsetY;
- }
-
- getOffsetByPositionX(column: number): number {
- const { columnWidthAccumulation, rowHeaderWidthAndMarginLeft } = this;
-
- const lastColumnIndex = columnWidthAccumulation.length - 1;
- const columnValue = columnWidthAccumulation[column];
- if (columnValue != null) {
- return columnValue + rowHeaderWidthAndMarginLeft;
- }
-
- if (column < 0) {
- return rowHeaderWidthAndMarginLeft;
- }
-
- return columnWidthAccumulation[lastColumnIndex] + rowHeaderWidthAndMarginLeft;
- }
-
- getOffsetByPositionY(row: number): number {
- const { rowHeightAccumulation, columnHeaderHeightAndMarginTop } = this;
- const lastRowIndex = rowHeightAccumulation.length - 1;
- const rowValue = rowHeightAccumulation[row];
- if (rowValue != null) {
- return rowValue + columnHeaderHeightAndMarginTop;
- }
-
- if (row < 0) {
- return columnHeaderHeightAndMarginTop;
- }
-
- return rowHeightAccumulation[lastRowIndex] + columnHeaderHeightAndMarginTop;
- }
-
/**
* Same as getCellWithCoordByIndex, but uses a different name to maintain backward compatibility with previous calls.
* @deprecated Please use `getCellWithCoordByIndex` instead.
@@ -1336,84 +780,6 @@ export class SpreadsheetSkeleton extends Skeleton {
return this.getCellWithCoordByIndex(row, column, false);
}
- /**
- * Return cell information corresponding to the current coordinates, including the merged cell object.
- *
- * @param row Specified Row Coordinate
- * @param column Specified Column Coordinate
- */
- getCellWithCoordByIndex(row: number, column: number, header: boolean = true): ICellWithCoord {
- const {
- rowHeightAccumulation,
- columnWidthAccumulation,
- rowHeaderWidthAndMarginLeft,
- columnHeaderHeightAndMarginTop,
- } = this;
-
- const primary: ICellWithCoord = getCellWithCoordByIndexCore(
- row,
- column,
- rowHeightAccumulation,
- columnWidthAccumulation,
- this.worksheet.getCellInfoInMergeData(row, column)
- );
- const { isMerged, isMergedMainCell } = primary;
- let { startY, endY, startX, endX, mergeInfo } = primary;
-
- let offsetX = rowHeaderWidthAndMarginLeft;
- let offsetY = columnHeaderHeightAndMarginTop;
- if (header === false) {
- offsetX = 0;
- offsetY = 0;
- }
-
- startY += offsetY;
- endY += offsetY;
- startX += offsetX;
- endX += offsetX;
-
- mergeInfo.startY += offsetY;
- mergeInfo.endY += offsetY;
- mergeInfo.startX += offsetX;
- mergeInfo.endX += offsetX;
-
- // mergeInfo = mergeInfoOffset(mergeInfo, rowHeaderWidthAndMarginLeft, columnHeaderHeightAndMarginTop);
-
- return {
- actualRow: row,
- actualColumn: column,
- startX,
- startY,
- endX,
- endY,
- isMerged,
- isMergedMainCell,
- mergeInfo,
- };
- }
-
- /**
- * convert canvas content position to physical position in screen
- * @param offsetX
- * @param scaleX
- * @param scrollXY
- */
- convertTransformToOffsetX(offsetX: number, scaleX: number, scrollXY: { x: number; y: number }): number {
- const { x: scrollX } = scrollXY;
- return (offsetX - scrollX) * scaleX;
- }
-
- /**
- * convert canvas content position to physical position in screen
- * @param offsetY
- * @param scaleY
- * @param scrollXY
- */
- convertTransformToOffsetY(offsetY: number, scaleY: number, scrollXY: { x: number; y: number }): number {
- const { y: scrollY } = scrollXY;
- return (offsetY - scrollY) * scaleY;
- }
-
/**
* Only used for cell edit, and no need to rotate text when edit cell content!
* @deprecated use same method in worksheet.
@@ -1573,30 +939,6 @@ export class SpreadsheetSkeleton extends Skeleton {
};
}
- getDecomposedOffset(offsetX: number, offsetY: number): { row: number; column: number; columnOffset: number; rowOffset: number } {
- const column = searchArray(this._columnWidthAccumulation, offsetX);
- let columnOffset = 0;
- if (column === 0) {
- columnOffset = offsetX;
- } else {
- columnOffset = offsetX - this._columnWidthAccumulation[column - 1];
- }
-
- const row = searchArray(this._rowHeightAccumulation, offsetY);
- let rowOffset = 0;
- if (row === 0) {
- rowOffset = offsetY;
- } else {
- rowOffset = offsetY - this._rowHeightAccumulation[row - 1];
- }
- return {
- row,
- column,
- columnOffset,
- rowOffset,
- };
- }
-
/**
* Calculate the overflow of cell text. If there is no value on either side of the cell,
* the text content of this cell can be drawn to both sides, not limited by the cell's width.
@@ -1642,13 +984,11 @@ export class SpreadsheetSkeleton extends Skeleton {
}
if (vertexAngle !== 0) {
- const { startY, endY, startX, endX } = getCellWithCoordByIndexCore(
+ const { startY, endY, startX, endX } = this.getCellWithCoordByIndex(
row,
- column,
- this.rowHeightAccumulation,
- this.columnWidthAccumulation,
- this.worksheet.getCellInfoInMergeData(row, column)
+ column
);
+
const cellWidth = endX - startX;
const cellHeight = endY - startY;
@@ -1675,12 +1015,9 @@ export class SpreadsheetSkeleton extends Skeleton {
return true;
}
- const { startY, endY } = getCellWithCoordByIndexCore(
+ const { startY, endY } = this.getCellWithCoordByIndex(
row,
- column,
- this.rowHeightAccumulation,
- this.columnWidthAccumulation,
- this.worksheet.getCellInfoInMergeData(row, column)
+ column
);
const cellHeight = endY - startY;
@@ -1747,167 +1084,6 @@ export class SpreadsheetSkeleton extends Skeleton {
} as IRange;
}
- private _generateRowMatrixCache(
- rowCount: number,
- rowData: IObjectArrayPrimitiveType>,
- defaultRowHeight: number
- ): { rowTotalHeight: number; rowHeightAccumulation: number[] } {
- let rowTotalHeight = 0;
- const rowHeightAccumulation: number[] = [];
- const data = rowData;
- for (let r = 0; r < rowCount; r++) {
- let rowHeight = defaultRowHeight;
-
- if (this.worksheet.getRowFiltered(r)) {
- rowHeight = 0;
- } else if (data[r] != null) {
- const rowDataItem = data[r];
- if (!rowDataItem) {
- continue;
- }
-
- const { h = defaultRowHeight, ah, ia } = rowDataItem;
- if ((ia == null || ia === BooleanNumber.TRUE) && typeof ah === 'number') {
- rowHeight = ah;
- } else {
- rowHeight = h;
- }
-
- if (rowDataItem.hd === BooleanNumber.TRUE) {
- rowHeight = 0;
- }
- }
-
- rowTotalHeight += rowHeight;
-
- rowHeightAccumulation.push(rowTotalHeight);
- }
-
- return {
- rowTotalHeight,
- rowHeightAccumulation,
- };
- }
-
- /**
- * Calc columnWidthAccumulation by columnData
- * @param colCount
- * @param columnData
- * @param defaultColumnWidth
- */
- private _generateColumnMatrixCache(
- colCount: number,
- columnData: IObjectArrayPrimitiveType>,
- defaultColumnWidth: number
- ): { columnTotalWidth: number; columnWidthAccumulation: number[] } {
- let columnTotalWidth = 0;
- const columnWidthAccumulation: number[] = [];
-
- const data = columnData;
-
- for (let c = 0; c < colCount; c++) {
- let columnWidth = defaultColumnWidth;
-
- if (data[c] != null) {
- const columnDataItem = data[c];
-
- if (!columnDataItem) {
- continue;
- }
- if (columnDataItem.w != null) {
- columnWidth = columnDataItem.w;
- }
-
- if (columnDataItem.hd === BooleanNumber.TRUE) {
- columnWidth = 0;
- }
- }
-
- columnTotalWidth += columnWidth;
- columnWidthAccumulation.push(columnTotalWidth);
- }
-
- return {
- columnTotalWidth,
- columnWidthAccumulation,
- };
- }
-
- //eslint-disable-next-line complexity
- private _getOverflowBound(
- row: number,
- startColumn: number,
- endColumn: number,
- contentWidth: number,
- horizontalAlign = HorizontalAlign.LEFT
- ): number {
- let cumWidth = 0;
- if (startColumn > endColumn) {
- const columnCount = this._columnWidthAccumulation.length - 1;
- for (let i = startColumn; i >= endColumn; i--) {
- const column = i;
- const cell = this.worksheet.getCell(row, column);
- if ((!isCellCoverable(cell) && column !== startColumn) || this.intersectMergeRange(row, column)) {
- if (column === startColumn) {
- return column;
- }
- return column + 1 > columnCount ? columnCount : column + 1;
- }
- const { startX, endX } = getCellPositionByIndex(
- row,
- column,
- this.rowHeightAccumulation,
- this.columnWidthAccumulation
- );
-
- // For center alignment, the current cell's width needs to be divided in half for comparison.
- if (horizontalAlign === HorizontalAlign.CENTER && column === startColumn) {
- cumWidth += (endX - startX) / 2;
- } else {
- cumWidth += endX - startX;
- }
-
- if (contentWidth < cumWidth) {
- return column;
- }
- }
- return startColumn;
- }
- for (let i = startColumn; i <= endColumn; i++) {
- const column = i;
- const cell = this.worksheet.getCell(row, column);
- if ((!isCellCoverable(cell) && column !== startColumn) || this.intersectMergeRange(row, column)) {
- if (column === startColumn) {
- return column;
- }
-
- return column - 1 < 0 ? 0 : column - 1;
- }
- const { startX, endX } = getCellPositionByIndex(
- row,
- column,
- this.rowHeightAccumulation,
- this.columnWidthAccumulation
- );
-
- if (horizontalAlign === HorizontalAlign.CENTER && column === startColumn) {
- cumWidth += (endX - startX) / 2;
- } else {
- cumWidth += endX - startX;
- }
-
- if (contentWidth < cumWidth) {
- return column;
- }
- }
- return endColumn;
- }
-
- intersectMergeRange(row: number, column: number): boolean {
- const mergedData = this.worksheet.getMergedCell(row, column);
- return Boolean(mergedData);
- }
-
/**
* Get the current row and column segment visible merge data.
* @returns {IRange} The visible merge data
@@ -1936,7 +1112,8 @@ export class SpreadsheetSkeleton extends Skeleton {
/**
* Any changes to sheet model would reset cache.
*/
- private _resetCache(): void {
+ override _resetCache(): void {
+ super._resetCache();
this._stylesCache = {
background: {},
backgroundPositions: new ObjectMatrix(),
@@ -1944,9 +1121,10 @@ export class SpreadsheetSkeleton extends Skeleton {
fontMatrix: new ObjectMatrix(),
border: new ObjectMatrix(),
};
- this._handleBgMatrix.reset();
- this._handleBorderMatrix.reset();
- this._overflowCache.reset();
+
+ this._handleBgMatrix?.reset();
+ this._handleBorderMatrix?.reset();
+ this._overflowCache?.reset();
}
_setBorderStylesCache(row: number, col: number, style: Nullable, options: {
@@ -2036,7 +1214,6 @@ export class SpreadsheetSkeleton extends Skeleton {
horizontalAlign,
wrapStrategy,
imageCacheMap: this._imageCacheMap,
- fontRenderExtension: cell?.fontRenderExtension,
};
this._stylesCache.fontMatrix.setValue(row, col, config);
this._calculateOverflowCell(row, col, config);
@@ -2099,53 +1276,6 @@ export class SpreadsheetSkeleton extends Skeleton {
this._setFontStylesCache(row, col, { ...cell, ...{ s: style } });
}
- private _updateConfigAndGetDocumentModel(
- documentData: IDocumentData,
- horizontalAlign: HorizontalAlign,
- paddingData: IPaddingData,
- renderConfig?: IDocumentRenderConfig
- ): Nullable {
- if (!renderConfig) {
- return;
- }
-
- if (!documentData.body?.dataStream) {
- return;
- }
-
- if (!documentData.documentStyle) {
- documentData.documentStyle = {};
- }
-
- documentData.documentStyle.marginTop = paddingData.t ?? 0;
- documentData.documentStyle.marginBottom = paddingData.b ?? 2;
- documentData.documentStyle.marginLeft = paddingData.l ?? 2;
- documentData.documentStyle.marginRight = paddingData.r ?? 2;
-
- // Fix https://github.com/dream-num/univer/issues/1586
- documentData.documentStyle.pageSize = {
- width: Number.POSITIVE_INFINITY,
- height: Number.POSITIVE_INFINITY,
- };
-
- documentData.documentStyle.renderConfig = {
- ...documentData.documentStyle.renderConfig,
- ...renderConfig,
- };
-
- const paragraphs = documentData.body.paragraphs || [];
-
- for (const paragraph of paragraphs) {
- if (!paragraph.paragraphStyle) {
- paragraph.paragraphStyle = {};
- }
-
- paragraph.paragraphStyle.horizontalAlign = horizontalAlign;
- }
-
- return new DocumentDataModel(documentData);
- }
-
/**
* pro/issues/344
* In Excel, for the border rendering of merged cells to take effect, the outermost cells need to have the same border style.
@@ -2267,43 +1397,6 @@ export class SpreadsheetSkeleton extends Skeleton {
};
}
- /**
- * New version to get merge data.
- * @param row
- * @param column
- * @returns {ISelectionCell} The cell info with merge data
- */
- private _getCellMergeInfo(row: number, column: number): ISelectionCell {
- return this.worksheet.getCellInfoInMergeData(row, column);
- }
-
- getDistanceFromTopLeft(row: number, col: number): IPoint {
- return {
- x: this._offsetXToCol(col),
- y: this._offsetYToRow(row),
- };
- }
-
- /**
- * Distance from top left to row
- * @param row
- */
- private _offsetYToRow(row: number): number {
- const arr = this._rowHeightAccumulation;
- const i = Math.max(0, row - 1);
- return arr[i];
- }
-
- /**
- * Distance from top left to col
- * @param col
- */
- private _offsetXToCol(col: number): number {
- const arr = this._columnWidthAccumulation;
- const i = Math.max(0, col - 1);
- return arr[i];
- }
-
getHiddenRowsInRange(range: IRowRange) {
const hiddenRows = [];
for (let i = range.startRow; i <= range.endRow; i++) {
@@ -2324,3 +1417,88 @@ export class SpreadsheetSkeleton extends Skeleton {
return hiddenCols;
}
}
+
+/**
+ * convert canvas content position to physical position in screen
+ * @param offsetX
+ * @param scaleX
+ * @param scrollXY
+ */
+export function convertTransformToOffsetX(
+ offsetX: number,
+ scaleX: number,
+ scrollXY: { x: number; y: number }
+): number {
+ const { x: scrollX } = scrollXY;
+ return (offsetX - scrollX) * scaleX;
+}
+
+/**
+ * convert canvas content position to physical position in screen
+ * @param offsetY
+ * @param scaleY
+ * @param scrollXY
+ */
+export function convertTransformToOffsetY(
+ offsetY: number,
+ scaleY: number,
+ scrollXY: { x: number; y: number }
+): number {
+ const { y: scrollY } = scrollXY;
+ return (offsetY - scrollY) * scaleY;
+}
+
+/**
+ * Obtain the height and width of a cell's text, taking into account scenarios with rotated text.
+ * @param documentSkeleton Data of the document's ViewModel
+ * @param angleInDegree The rotation angle of an Excel cell, it's **degree**
+ */
+export function getDocsSkeletonPageSize(documentSkeleton: DocumentSkeleton, angleInDegree: number = 0): Nullable> {
+ const skeletonData = documentSkeleton?.getSkeletonData();
+ const angle = degToRad(angleInDegree);
+
+ if (!skeletonData) {
+ return null;
+ }
+ const { pages } = skeletonData;
+ const lastPage = pages[pages.length - 1];
+ const { width, height } = lastPage;
+
+ if (angle === 0) {
+ return { width, height };
+ }
+
+ if (Math.abs(angle) === Math.PI / 2) {
+ return { width: height, height: width };
+ }
+
+ let allRotatedWidth = 0;
+ let allRotatedHeight = 0;
+
+ const widthArray: Array<{ rotatedWidth: number; spaceWidth: number }> = [];
+
+ columnIterator([lastPage], (column: IDocumentSkeletonColumn) => {
+ const { lines, width: columnWidth, spaceWidth } = column;
+
+ const { rotatedHeight, rotatedWidth } = getRotateOffsetAndFarthestHypotenuse(lines, columnWidth, angle);
+
+ allRotatedHeight += rotatedHeight;
+
+ widthArray.push({ rotatedWidth, spaceWidth });
+ });
+
+ const widthCount = widthArray.length;
+
+ for (let i = 0; i < widthCount; i++) {
+ const { rotatedWidth } = widthArray[i];
+
+ if (i === 0) {
+ allRotatedWidth += rotatedWidth;
+ }
+ }
+
+ return {
+ width: allRotatedWidth,
+ height: allRotatedHeight,
+ };
+}
diff --git a/packages/engine-render/src/components/sheets/spreadsheet.ts b/packages/engine-render/src/components/sheets/spreadsheet.ts
index bd42edc89e6..695b879a5c5 100644
--- a/packages/engine-render/src/components/sheets/spreadsheet.ts
+++ b/packages/engine-render/src/components/sheets/spreadsheet.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import type { IRange, Nullable } from '@univerjs/core';
+import type { IPosition, IRange, Nullable } from '@univerjs/core';
import type { IBoundRectNoAngle, IViewportInfo, Vector2 } from '../../basics/vector2';
import type { Canvas } from '../../canvas';
import type { UniverRenderingContext2D } from '../../context';
@@ -26,10 +26,10 @@ import type { Background } from './extensions/background';
import type { Border } from './extensions/border';
import type { Font } from './extensions/font';
import type { IPaintForRefresh, IPaintForScrolling, SHEET_VIEWPORT_KEY } from './interfaces';
-import type { SpreadsheetSkeleton } from './sheet-skeleton';
+import type { SpreadsheetSkeleton } from './sheet.render-skeleton';
import { BooleanNumber, sortRules, Tools } from '@univerjs/core';
import { FIX_ONE_PIXEL_BLUR_OFFSET, RENDER_CLASS_TYPE } from '../../basics/const';
-import { getCellPositionByIndex, getColor } from '../../basics/tools';
+import { getColor } from '../../basics/tools';
import { Documents } from '../docs/document';
import { SpreadsheetExtensionRegistry } from '../extension';
import { sheetContentViewportKeys, sheetHeaderViewportKeys } from './constants';
@@ -173,32 +173,33 @@ export class Spreadsheet extends SheetComponent {
return false;
}
- override getNoMergeCellPositionByIndex(rowIndex: number, columnIndex: number) {
- const spreadsheetSkeleton = this.getSkeleton();
- if (!spreadsheetSkeleton) {
- return;
+ override getNoMergeCellPositionByIndex(rowIndex: number, columnIndex: number): IPosition {
+ const skeleton = this.getSkeleton();
+ if (!skeleton) {
+ return { startX: 0, startY: 0, endX: 0, endY: 0 };
}
- const { rowHeightAccumulation, columnWidthAccumulation, rowHeaderWidth, columnHeaderHeight } =
- spreadsheetSkeleton;
-
- let { startY, endY, startX, endX } = getCellPositionByIndex(
- rowIndex,
- columnIndex,
- rowHeightAccumulation,
- columnWidthAccumulation
- );
-
- startY += columnHeaderHeight;
- endY += columnHeaderHeight;
- startX += rowHeaderWidth;
- endX += rowHeaderWidth;
-
- return {
- startY,
- endY,
- startX,
- endX,
- };
+ return skeleton.getNoMergeCellWithCoordByIndex(rowIndex, columnIndex);
+ // const { rowHeightAccumulation, columnWidthAccumulation, rowHeaderWidth, columnHeaderHeight } =
+ // spreadsheetSkeleton;
+
+ // let { startY, endY, startX, endX } = getCellWithCoordByIndexCore(
+ // rowIndex,
+ // columnIndex,
+ // rowHeightAccumulation,
+ // columnWidthAccumulation
+ // );
+
+ // startY += columnHeaderHeight;
+ // endY += columnHeaderHeight;
+ // startX += rowHeaderWidth;
+ // endX += rowHeaderWidth;
+
+ // return {
+ // startY,
+ // endY,
+ // startX,
+ // endX,
+ // };
}
override getScrollXYByRelativeCoords(coord: Vector2) {
@@ -236,7 +237,7 @@ export class Spreadsheet extends SheetComponent {
}
override getSelectionBounding(startRow: number, startColumn: number, endRow: number, endColumn: number) {
- return this.getSkeleton()?.getMergeBounding(startRow, startColumn, endRow, endColumn);
+ return this.getSkeleton()?.expandRangeByMerge({ startRow, startColumn, endRow, endColumn });
}
/**
diff --git a/packages/engine-render/src/components/sheets/util.ts b/packages/engine-render/src/components/sheets/util.ts
index 37b933025ce..0c91628e763 100644
--- a/packages/engine-render/src/components/sheets/util.ts
+++ b/packages/engine-render/src/components/sheets/util.ts
@@ -17,7 +17,7 @@
import type { CellValueType, IDocumentData, IPaddingData, IStyleBase, IStyleData, ITextRotation, ITextStyle, Nullable, TextDirection } from '@univerjs/core';
import { DEFAULT_EMPTY_DOCUMENT_VALUE, DocumentDataModel, HorizontalAlign, VerticalAlign, WrapStrategy } from '@univerjs/core';
import { convertTextRotation } from '../../basics/text-rotation';
-import { DEFAULT_PADDING_DATA } from './sheet-skeleton';
+import { DEFAULT_PADDING_DATA } from './sheet.render-skeleton';
export interface ICellStyle {
textRotation?: ITextRotation;
diff --git a/packages/engine-render/src/engine.ts b/packages/engine-render/src/engine.ts
index c7d1bf5eb75..51dc51212f8 100644
--- a/packages/engine-render/src/engine.ts
+++ b/packages/engine-render/src/engine.ts
@@ -234,7 +234,7 @@ export class Engine extends Disposable {
}
addScene(sceneInstance: Scene): Scene {
- const sceneKey = (sceneInstance as any).sceneKey;
+ const sceneKey = sceneInstance.sceneKey;
if (this.hasScene(sceneKey)) {
console.warn('Scenes has same key, it will be covered');
}
diff --git a/packages/engine-render/src/index.ts b/packages/engine-render/src/index.ts
index b0e1026aff3..6767213e040 100644
--- a/packages/engine-render/src/index.ts
+++ b/packages/engine-render/src/index.ts
@@ -34,7 +34,7 @@ export { DocumentViewModel } from './components/docs/view-model/document-view-mo
export { DocumentEditArea } from './components/docs/view-model/document-view-model';
export { parseDataStreamToTree } from './components/docs/view-model/document-view-model';
export { getLastColumn } from './components/docs/layout/tools';
-export { DEFAULT_PADDING_DATA } from './components/sheets/sheet-skeleton';
+export { DEFAULT_PADDING_DATA } from './components/sheets/sheet.render-skeleton';
export * from './context';
export * from './custom';
export * from './engine';
@@ -48,5 +48,4 @@ export { type IChangeObserverConfig } from './scene.transformer';
export * from './scene-viewer';
export * from './scroll-timer';
export * from './shape';
-export { ThinEngine } from './thin-engine';
export * from './viewport';
diff --git a/packages/engine-render/src/scene.ts b/packages/engine-render/src/scene.ts
index 256d41e5776..cb095f4dc41 100644
--- a/packages/engine-render/src/scene.ts
+++ b/packages/engine-render/src/scene.ts
@@ -17,7 +17,7 @@
import type { IKeyValue, Nullable } from '@univerjs/core';
import type { BaseObject } from './base-object';
import type { IDragEvent, IKeyboardEvent, IMouseEvent, IPointerEvent, IWheelEvent } from './basics/i-events';
-import type { IObjectFullState, ISceneTransformState, ITransformChangeState } from './basics/interfaces';
+import type { ISceneTransformState, ITransformChangeState } from './basics/interfaces';
import type { ITransformerConfig } from './basics/transformer-config';
import type { Vector2 } from './basics/vector2';
import type { Canvas } from './canvas';
@@ -47,7 +47,13 @@ export interface ISceneInputControlOptions {
}
export class Scene extends Disposable {
private _sceneKey: string = '';
+ /**
+ * Width of scene content, does not affected by zoom.
+ */
private _width: number = 100;
+ /**
+ * Height of scene content, does not affected by zoom.
+ */
private _height: number = 100;
private _scaleX: number = 1;
private _scaleY: number = 1;
@@ -131,7 +137,7 @@ export class Scene extends Disposable {
this.disposeWithMe(
toDisposable(
this._parent?.onTransformChange$.subscribeEvent((_change: ITransformChangeState) => {
- this._setTransForm();
+ this._transformHandler();
})
)
);
@@ -189,6 +195,9 @@ export class Scene extends Disposable {
this._scaleY = scaleY;
}
+ /**
+ * ancestorScaleX means this.scaleX * ancestorScaleX
+ */
get ancestorScaleX() {
const p = this.getParent();
let pScale = 1;
@@ -198,6 +207,9 @@ export class Scene extends Disposable {
return this.scaleX * pScale;
}
+ /**
+ * ancestorScaleY means this.scaleY * ancestorScaleY
+ */
get ancestorScaleY() {
const p = this.getParent();
let pScale = 1;
@@ -207,6 +219,20 @@ export class Scene extends Disposable {
return this.scaleY * pScale;
}
+ getAncestorScale() {
+ // const { scaleX = 1, scaleY = 1 } = this;
+ // this.classType is always 'Scene', this if is always false
+ // if (this.classType === RENDER_CLASS_TYPE.SCENE_VIEWER) {
+ // scaleX = this.ancestorScaleX || 1;
+ // scaleY = this.ancestorScaleY || 1;
+ // }
+
+ return {
+ scaleX: this.ancestorScaleX || 1,
+ scaleY: this.ancestorScaleY || 1,
+ };
+ }
+
get ancestorLeft() {
const p = this.getParent();
let pOffsetX = 0;
@@ -306,6 +332,11 @@ export class Scene extends Disposable {
this.resetCursor();
}
+ /**
+ * @deprecated use transformByState instead.
+ * @param width
+ * @param height
+ */
resize(width?: number, height?: number) {
const preWidth = this.width;
if (width !== undefined) {
@@ -317,7 +348,7 @@ export class Scene extends Disposable {
this.height = height;
}
- this._setTransForm();
+ this._transformHandler();
this.onTransformChange$.emitEvent({
type: TRANSFORM_CHANGE_OBSERVABLE_TYPE.resize,
value: {
@@ -330,7 +361,12 @@ export class Scene extends Disposable {
return this;
}
- setScaleValue(scaleX: number, scaleY: number) {
+ /**
+ * Unlike @scale, this method doesn't emit event.
+ * @param scaleX
+ * @param scaleY
+ */
+ setScaleValueOnly(scaleX: number, scaleY: number) {
if (scaleX !== undefined) {
this.scaleX = scaleX;
}
@@ -348,16 +384,10 @@ export class Scene extends Disposable {
*/
scale(scaleX?: number, scaleY?: number) {
const preScaleX = this.scaleX;
- if (scaleX !== undefined) {
- this.scaleX = scaleX;
- }
-
const preScaleY = this.scaleY;
- if (scaleY !== undefined) {
- this.scaleY = scaleY;
- }
+ this.setScaleValueOnly(scaleX || 1, scaleY || 1);
- this._setTransForm();
+ this._transformHandler();
this.onTransformChange$.emitEvent({
type: TRANSFORM_CHANGE_OBSERVABLE_TYPE.scale,
value: {
@@ -370,22 +400,22 @@ export class Scene extends Disposable {
}
/**
- * current scale plus offset, relative
+ * Apply scaleXY base on current scaleX and scaleY
*/
- scaleBy(scaleX?: number, scaleY?: number) {
+ scaleBy(deltaScaleX?: number, deltaScaleY?: number) {
const preScaleX = this.scaleX;
- if (scaleX !== undefined) {
- this.scaleX += scaleX;
+ if (deltaScaleX !== undefined) {
+ this.scaleX += deltaScaleX; // @TODO lumixraku why not this.scaleX *= deltaScaleX ???
}
const preScaleY = this.scaleY;
- if (scaleY !== undefined) {
- this.scaleY += scaleY;
+ if (deltaScaleY !== undefined) {
+ this.scaleY += deltaScaleY;
}
this.scaleX = precisionTo(this.scaleX, 1);
this.scaleY = precisionTo(this.scaleY, 1);
- this._setTransForm();
+ this._transformHandler();
this.onTransformChange$.emitEvent({
type: TRANSFORM_CHANGE_OBSERVABLE_TYPE.scale,
value: {
@@ -402,20 +432,20 @@ export class Scene extends Disposable {
* @param state
*/
transformByState(state: ISceneTransformState) {
- const optionKeys = Object.keys(state);
- const preKeys: IObjectFullState = {};
- if (optionKeys.length === 0) {
+ const transformStateKeys = Object.keys(state);
+ const preKeys: ISceneTransformState = {};
+ if (transformStateKeys.length === 0) {
return;
}
- optionKeys.forEach((pKey) => {
+ transformStateKeys.forEach((pKey) => {
if (state[pKey as keyof ISceneTransformState] !== undefined) {
(preKeys as IKeyValue)[pKey] = this[pKey as keyof Scene];
(this as IKeyValue)[pKey] = state[pKey as keyof ISceneTransformState];
}
});
- this._setTransForm();
+ this._transformHandler();
this.onTransformChange$.emitEvent({
type: TRANSFORM_CHANGE_OBSERVABLE_TYPE.all,
@@ -871,20 +901,6 @@ export class Scene extends Disposable {
this._viewports = [];
}
- getAncestorScale() {
- let { scaleX = 1, scaleY = 1 } = this;
-
- if (this.classType === RENDER_CLASS_TYPE.SCENE_VIEWER) {
- scaleX = this.ancestorScaleX || 1;
- scaleY = this.ancestorScaleY || 1;
- }
-
- return {
- scaleX,
- scaleY,
- };
- }
-
getPrecisionScale() {
const pixelRatio = this.getEngine()?.getPixelRatio() || 1;
const { scaleX, scaleY } = this.getAncestorScale();
@@ -1193,7 +1209,14 @@ export class Scene extends Disposable {
return defaultLayer;
}
- private _setTransForm() {
+ /**
+ * Triggered when scale, resize of scene.
+ * origin name: _setTransForm
+ *
+ */
+ private _transformHandler() {
+ // why not use this.ancestorScaleXY ?
+ // if parent scale changed, this.ancestorScaleXY will remain same.
const composeResult = Transform.create().composeMatrix({
scaleX: this.scaleX,
scaleY: this.scaleY,
diff --git a/packages/engine-render/src/thin-engine.ts b/packages/engine-render/src/thin-engine.ts
deleted file mode 100644
index 8c6fa68add1..00000000000
--- a/packages/engine-render/src/thin-engine.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * Copyright 2023-present DreamNum Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import type { IDisposable } from '@univerjs/core';
-import type { CURSOR_TYPE } from './basics/const';
-
-import type { IEvent } from './basics/i-events';
-import type { ITransformChangeState } from './basics/interfaces';
-import type { Canvas } from './canvas';
-import { Disposable, EventSubject } from '@univerjs/core';
-import { RENDER_CLASS_TYPE } from './basics/const';
-
-// FIXME: ThinEngine and ThinScene should be removed
-
-export abstract class ThinEngine extends Disposable {
- onInputChanged$ = new EventSubject();
-
- onTransformChange$ = new EventSubject();
-
- private _scenes: { [sceneKey: string]: T } = {};
-
- private _activeScene: T | null = null;
-
- get classType() {
- return RENDER_CLASS_TYPE.ENGINE;
- }
-
- get activeScene() {
- return this._activeScene;
- }
-
- get width() {
- return 0;
- }
-
- get height() {
- return 0;
- }
-
- getScenes() {
- return this._scenes;
- }
-
- getScene(sceneKey: string): T | null {
- return this._scenes[sceneKey];
- }
-
- hasScene(sceneKey: string): boolean {
- return sceneKey in this._scenes;
- }
-
- addScene(sceneInstance: T): T {
- const sceneKey = (sceneInstance as any).sceneKey;
- if (this.hasScene(sceneKey)) {
- console.warn('Scenes has similar key, it will be covered');
- }
- // const newScene = new Scene(this);
- this._scenes[sceneKey] = sceneInstance;
- return sceneInstance;
- }
-
- setActiveScene(sceneKey: string): T | null {
- const scene = this.getScene(sceneKey);
- if (scene) {
- this._activeScene = scene;
- }
- return scene;
- }
-
- abstract setRemainCapture(): void;
-
- hasActiveScene(): boolean {
- return this._activeScene != null;
- }
-
- override dispose() {
- super.dispose();
-
- const scenes = { ...this.getScenes() };
- const sceneKeys = Object.keys(scenes);
- sceneKeys.forEach((key) => {
- (scenes[key] as any).dispose();
- });
- this._scenes = {};
- }
-
- getParent() {}
-
- // TODO @lumixraku, it seems delete scene with key.
- remainScene(key: string) {
- const scenes = this.getScenes();
- if (scenes[key]) {
- const scene = scenes[key];
- delete scenes[key];
- return scene;
- }
- }
-
- abstract clearCanvas(): void;
-
- abstract getCanvas(): Canvas;
-
- abstract getCanvasElement(): HTMLCanvasElement;
-
- abstract setCanvasCursor(val: CURSOR_TYPE): void;
-
- abstract getPixelRatio(): number;
-}
diff --git a/packages/facade/src/apis/__tests__/create-test-bed.ts b/packages/facade/src/apis/__tests__/create-test-bed.ts
index 97ee8fcb46b..aa78352b081 100644
--- a/packages/facade/src/apis/__tests__/create-test-bed.ts
+++ b/packages/facade/src/apis/__tests__/create-test-bed.ts
@@ -39,6 +39,7 @@ import {
RangeProtectionRuleModel,
RefRangeService,
SheetInterceptorService,
+ SheetSkeletonService,
SheetsSelectionsService,
WorkbookPermissionService,
WorksheetPermissionService,
@@ -166,6 +167,7 @@ export function createFacadeTestBed(workbookData?: IWorkbookData, dependencies?:
injector.add([SheetsRenderService]);
injector.add([IShortcutService, { useClass: ShortcutService }]);
injector.add([IPlatformService, { useClass: PlatformService }]);
+ injector.add([SheetSkeletonService]);
injector.add([SheetSkeletonManagerService]);
injector.add([FormulaDataModel]);
injector.add([LexerTreeBuilder]);
diff --git a/packages/facade/src/apis/sheets/__tests__/create-worksheet-test-bed.ts b/packages/facade/src/apis/sheets/__tests__/create-worksheet-test-bed.ts
index d95e471c0b0..270b5be8201 100644
--- a/packages/facade/src/apis/sheets/__tests__/create-worksheet-test-bed.ts
+++ b/packages/facade/src/apis/sheets/__tests__/create-worksheet-test-bed.ts
@@ -39,6 +39,7 @@ import {
RangeProtectionRuleModel,
RefRangeService,
SheetInterceptorService,
+ SheetSkeletonService,
SheetsSelectionsService,
WorkbookPermissionService,
WorksheetPermissionService,
@@ -159,6 +160,7 @@ export function createWorksheetTestBed(workbookData?: IWorkbookData, dependencie
injector.add([SheetsRenderService]);
injector.add([IShortcutService, { useClass: ShortcutService }]);
injector.add([IPlatformService, { useClass: PlatformService }]);
+ injector.add([SheetSkeletonService]);
injector.add([SheetSkeletonManagerService]);
injector.add([FormulaDataModel]);
injector.add([LexerTreeBuilder]);
diff --git a/packages/sheets-data-validation-ui/src/controllers/dv-render.controller.ts b/packages/sheets-data-validation-ui/src/controllers/dv-render.controller.ts
index e383c16ca3d..adf43c224d5 100644
--- a/packages/sheets-data-validation-ui/src/controllers/dv-render.controller.ts
+++ b/packages/sheets-data-validation-ui/src/controllers/dv-render.controller.ts
@@ -191,7 +191,7 @@ export class SheetsDataValidationRenderController extends RxDisposable {
interceptorAutoHeight: () => {
const skeleton = this._renderManagerService.getRenderById(unitId)
?.with(SheetSkeletonManagerService)
- .getWorksheetSkeleton(subUnitId)
+ .getSkeletonParam(subUnitId)
?.skeleton;
if (!skeleton) {
return undefined;
@@ -200,7 +200,7 @@ export class SheetsDataValidationRenderController extends RxDisposable {
const info: ICellRenderContext = {
data: cell,
- style: skeleton.getsStyles().getStyleByCell(cell),
+ style: skeleton.getStyles().getStyleByCell(cell),
primaryWithCoord: skeleton.getCellWithCoordByIndex(mergeCell?.startRow ?? row, mergeCell?.startColumn ?? col),
unitId,
subUnitId,
@@ -214,7 +214,7 @@ export class SheetsDataValidationRenderController extends RxDisposable {
interceptorAutoWidth: () => {
const skeleton = this._renderManagerService.getRenderById(unitId)
?.with(SheetSkeletonManagerService)
- .getWorksheetSkeleton(subUnitId)
+ .getSkeletonParam(subUnitId)
?.skeleton;
if (!skeleton) {
return undefined;
@@ -223,7 +223,7 @@ export class SheetsDataValidationRenderController extends RxDisposable {
const info: ICellRenderContext = {
data: cell,
- style: skeleton.getsStyles().getStyleByCell(cell),
+ style: skeleton.getStyles().getStyleByCell(cell),
primaryWithCoord: skeleton.getCellWithCoordByIndex(mergeCell?.startRow ?? row, mergeCell?.startColumn ?? col),
unitId,
subUnitId,
@@ -341,7 +341,7 @@ export class SheetsDataValidationMobileRenderController extends RxDisposable {
interceptorAutoHeight: () => {
const skeleton = this._renderManagerService.getRenderById(unitId)
?.with(SheetSkeletonManagerService)
- .getWorksheetSkeleton(subUnitId)
+ .getSkeletonParam(subUnitId)
?.skeleton;
if (!skeleton) {
return undefined;
@@ -350,7 +350,7 @@ export class SheetsDataValidationMobileRenderController extends RxDisposable {
const info: ICellRenderContext = {
data: cell,
- style: skeleton.getsStyles().getStyleByCell(cell),
+ style: skeleton.getStyles().getStyleByCell(cell),
primaryWithCoord: skeleton.getCellWithCoordByIndex(mergeCell?.startRow ?? row, mergeCell?.startColumn ?? col),
unitId,
subUnitId,
diff --git a/packages/sheets-data-validation-ui/src/controllers/dv-rerender.controller.ts b/packages/sheets-data-validation-ui/src/controllers/dv-rerender.controller.ts
index 82f10cb8eff..c02edba5f40 100644
--- a/packages/sheets-data-validation-ui/src/controllers/dv-rerender.controller.ts
+++ b/packages/sheets-data-validation-ui/src/controllers/dv-rerender.controller.ts
@@ -41,7 +41,7 @@ export class SheetsDataValidationReRenderController extends Disposable implement
sheetIds.add(value.subUnitId);
});
sheetIds.forEach((sheetId) => {
- this._sheetSkeletonManagerService.getWorksheetSkeleton(sheetId)?.skeleton.makeDirty(true);
+ this._sheetSkeletonManagerService.getSkeletonParam(sheetId)?.skeleton.makeDirty(true);
});
this._context.mainComponent?.makeForceDirty();
};
diff --git a/packages/sheets-drawing-ui/src/controllers/sheet-drawing-printing.controller.ts b/packages/sheets-drawing-ui/src/controllers/sheet-drawing-printing.controller.ts
index f866ec8f95e..b7381371e08 100644
--- a/packages/sheets-drawing-ui/src/controllers/sheet-drawing-printing.controller.ts
+++ b/packages/sheets-drawing-ui/src/controllers/sheet-drawing-printing.controller.ts
@@ -65,7 +65,7 @@ export class SheetDrawingPrintingController extends Disposable {
return next(range);
}
- const skeleton = renderer.with(SheetSkeletonManagerService).getWorksheetSkeleton(subUnitId);
+ const skeleton = renderer.with(SheetSkeletonManagerService).getSkeletonParam(subUnitId);
if (!skeleton) {
return next(range);
}
diff --git a/packages/sheets-drawing-ui/src/controllers/sheet-drawing-update.controller.ts b/packages/sheets-drawing-ui/src/controllers/sheet-drawing-update.controller.ts
index 56e33b54d2e..8a07df03cd8 100644
--- a/packages/sheets-drawing-ui/src/controllers/sheet-drawing-update.controller.ts
+++ b/packages/sheets-drawing-ui/src/controllers/sheet-drawing-update.controller.ts
@@ -57,7 +57,7 @@ export function getDrawingSizeByCell(
return false;
}
const skeletonManagerService = currentRender.with(SheetSkeletonManagerService);
- const skeleton = skeletonManagerService.getWorksheetSkeleton(location.subUnitId)?.skeleton;
+ const skeleton = skeletonManagerService.getSkeletonParam(location.subUnitId)?.skeleton;
if (skeleton == null) {
return false;
}
diff --git a/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts b/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts
index 1937b209f34..592411e4cbb 100644
--- a/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts
+++ b/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts
@@ -286,7 +286,7 @@ export class SheetCanvasFloatDomManagerService extends Disposable {
return;
}
- const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getWorksheetSkeleton(subUnitId);
+ const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getSkeletonParam(subUnitId);
if (!skeleton) {
return;
}
@@ -436,7 +436,7 @@ export class SheetCanvasFloatDomManagerService extends Disposable {
const map = this._ensureMap(unitId, subUnitId);
const ids = Array.from(map.keys());
const target = getSheetCommandTarget(this._univerInstanceService, { unitId, subUnitId });
- const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getWorksheetSkeleton(subUnitId);
+ const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getSkeletonParam(subUnitId);
if (!renderObject || !target || !skeleton) {
return;
}
diff --git a/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts b/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts
index 0111c0778db..9399eafc429 100644
--- a/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts
+++ b/packages/sheets-formula-ui/src/views/range-selector/hooks/useHighlight.ts
@@ -61,7 +61,7 @@ export function useSheetHighlight(unitId: string) {
const currentSheetId = worksheet.getSheetId();
const getSheetIdByName = (name: string) => workbook?.getSheetBySheetName(name)?.getSheetId();
- const skeleton = sheetSkeletonManagerService?.getWorksheetSkeleton(currentSheetId)?.skeleton;
+ const skeleton = sheetSkeletonManagerService?.getSkeletonParam(currentSheetId)?.skeleton;
if (!skeleton) return;
for (let i = 0, len = refSelections.length; i < len; i++) {
diff --git a/packages/sheets-hyper-link-ui/src/controllers/popup.controller.ts b/packages/sheets-hyper-link-ui/src/controllers/popup.controller.ts
index e3b4aac22ff..99e41fdd675 100644
--- a/packages/sheets-hyper-link-ui/src/controllers/popup.controller.ts
+++ b/packages/sheets-hyper-link-ui/src/controllers/popup.controller.ts
@@ -122,7 +122,7 @@ export class SheetsHyperLinkPopupController extends Disposable {
}
const skeleton = renderer?.with(SheetSkeletonManagerService)
- .getWorksheetSkeleton(subUnitId)
+ .getSkeletonParam(subUnitId)
?.skeleton;
const currentCol = col;
@@ -210,7 +210,7 @@ export class SheetsHyperLinkPopupController extends Disposable {
const rect = customRange.rects[customRange.rects.length - 1];
const skeleton = this._renderManagerService.getRenderById(unitId)
?.with(SheetSkeletonManagerService)
- .getWorksheetSkeleton(sheetId)
+ .getSkeletonParam(sheetId)
?.skeleton;
if (!skeleton || !rect) {
return;
diff --git a/packages/sheets-hyper-link/src/controllers/set-range.controller.ts b/packages/sheets-hyper-link/src/controllers/set-range.controller.ts
index d95738fce38..09219f02e62 100644
--- a/packages/sheets-hyper-link/src/controllers/set-range.controller.ts
+++ b/packages/sheets-hyper-link/src/controllers/set-range.controller.ts
@@ -154,7 +154,7 @@ export class SheetHyperLinkSetRangeController extends Disposable {
return next(cell);
}
// const renderer = this._renderManagerService.getRenderById(unitId);
- // const skeleton = renderer?.with(SheetSkeletonManagerService).getWorksheetSkeleton(subUnitId);
+ // const skeleton = renderer?.with(SheetSkeletonManagerService).getSkeletonParam(subUnitId);
// if (!skeleton) {
// return next(cell);
// }
diff --git a/packages/sheets-thread-comment-ui/src/controllers/sheets-thread-comment-popup.controller.ts b/packages/sheets-thread-comment-ui/src/controllers/sheets-thread-comment-popup.controller.ts
index 9beff43e9d7..68edd9398d2 100644
--- a/packages/sheets-thread-comment-ui/src/controllers/sheets-thread-comment-popup.controller.ts
+++ b/packages/sheets-thread-comment-ui/src/controllers/sheets-thread-comment-popup.controller.ts
@@ -63,7 +63,7 @@ export class SheetsThreadCommentPopupController extends Disposable {
private _handleSelectionChange(selections: ISelectionWithStyle[], unitId: string, subUnitId: string) {
const range = selections[0]?.range;
const render = this._renderManagerService.getRenderById(unitId);
- const skeleton = render?.with(SheetSkeletonManagerService).getWorksheetSkeleton(subUnitId)?.skeleton;
+ const skeleton = render?.with(SheetSkeletonManagerService).getSkeletonParam(subUnitId)?.skeleton;
if (!skeleton) {
return;
}
diff --git a/packages/sheets-ui/src/commands/commands/__tests__/create-selection-command-test-bed.ts b/packages/sheets-ui/src/commands/commands/__tests__/create-selection-command-test-bed.ts
index 769a9a445d7..547cf91942b 100644
--- a/packages/sheets-ui/src/commands/commands/__tests__/create-selection-command-test-bed.ts
+++ b/packages/sheets-ui/src/commands/commands/__tests__/create-selection-command-test-bed.ts
@@ -17,7 +17,7 @@
import type { IWorkbookData } from '@univerjs/core';
import { Disposable, DisposableCollection, ICommandService, LocaleType, UniverInstanceType } from '@univerjs/core';
import { IRenderManagerService, RenderManagerService } from '@univerjs/engine-render';
-import { CancelFrozenCommand, SetFrozenMutation, SetSelectionsOperation } from '@univerjs/sheets';
+import { CancelFrozenCommand, SetFrozenMutation, SetSelectionsOperation, SheetSkeletonService } from '@univerjs/sheets';
import { SheetScrollManagerService } from '../../../services/scroll-manager.service';
import { SelectAllService } from '../../../services/select-all/select-all.service';
@@ -193,6 +193,7 @@ export function createFrozenCommandTestBed(workbookData?: IWorkbookData) {
const injector = univer.__getInjector();
// NOTE: this is a hack. Please refer to ./services/clipboard/__tests__/clipboard-test-bed.ts
+ const mockSheetSkService = new SheetSkeletonService(injector);
const fakeSheetSkeletonManagerService = new SheetSkeletonManagerService({
unit: sheet,
unitId,
@@ -203,7 +204,7 @@ export function createFrozenCommandTestBed(workbookData?: IWorkbookData) {
mainComponent: null as any,
components: null as any,
isMainScene: true,
- }, injector);
+ }, injector, mockSheetSkService);
injector.add([SheetSkeletonManagerService, { useValue: fakeSheetSkeletonManagerService }]);
injector.get(IRenderManagerService).addRender(unitId, {
diff --git a/packages/sheets-ui/src/commands/commands/__tests__/set-frozen.command.spec.ts b/packages/sheets-ui/src/commands/commands/__tests__/set-frozen.command.spec.ts
index 03e1e61798e..cd06f2aa218 100644
--- a/packages/sheets-ui/src/commands/commands/__tests__/set-frozen.command.spec.ts
+++ b/packages/sheets-ui/src/commands/commands/__tests__/set-frozen.command.spec.ts
@@ -15,10 +15,11 @@
*/
import type { IFreeze, Injector, IWorkbookData, Univer, Workbook } from '@univerjs/core';
+import type { IScrollStateWithSearchParam } from '../../../services/scroll-manager.service';
import { ICommandService, IUniverInstanceService, RANGE_TYPE, UniverInstanceType } from '@univerjs/core';
import { CancelFrozenCommand, SheetsSelectionsService } from '@univerjs/sheets';
-import { afterEach, beforeEach, describe, expect, it } from 'vitest';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { SheetScrollManagerService } from '../../../services/scroll-manager.service';
import {
SetColumnFrozenCommand,
@@ -34,7 +35,7 @@ describe('Test commands used for change selections', () => {
let selectionManagerService: SheetsSelectionsService;
let scrollManagerService: SheetScrollManagerService;
- const currentInfo = {
+ const searchParam = {
unitId: 'test',
sheetId: 'sheet1',
};
@@ -68,13 +69,15 @@ describe('Test commands used for change selections', () => {
}
const scrollTo = (startRow: number, startColumn: number, offsetX = 0, offsetY = 0) => {
- scrollManagerService.setScrollInfoAndEmitEvent({
+ const scrollInfo = {
sheetViewStartRow: startRow,
sheetViewStartColumn: startColumn,
offsetX,
offsetY,
- ...currentInfo,
- });
+ ...searchParam,
+ };
+ scrollManagerService.emitRawScrollParam(scrollInfo);
+ scrollManagerService.setValidScrollState(scrollInfo);
};
const getFreeze = () => {
@@ -97,9 +100,15 @@ describe('Test commands used for change selections', () => {
commandService = get(ICommandService);
selectionManagerService = get(SheetsSelectionsService);
scrollManagerService = get(SheetScrollManagerService);
- scrollManagerService.setSearchParamAndRefresh({
- ...currentInfo,
+ scrollManagerService.setSearchParam({
+ ...searchParam,
});
+ const scrollState = scrollManagerService.getScrollStateByParam(searchParam);
+ const scrollStateWithSheetId: IScrollStateWithSearchParam = {
+ ...scrollState!,
+ ...searchParam,
+ };
+ scrollManagerService.emitRawScrollParam(scrollStateWithSheetId);
}
afterEach(disposeTestBed);
diff --git a/packages/sheets-ui/src/commands/operations/scroll.operation.ts b/packages/sheets-ui/src/commands/operations/scroll.operation.ts
index 1efd2f66ac3..bf428791759 100644
--- a/packages/sheets-ui/src/commands/operations/scroll.operation.ts
+++ b/packages/sheets-ui/src/commands/operations/scroll.operation.ts
@@ -39,7 +39,7 @@ export const SetScrollOperation: IOperation = {
// const worksheet = workbook!.getSheetBySheetId(sheetId);
// const { xSplit, ySplit } = worksheet!.getConfig().freeze;
- scrollManagerService.setScrollInfoAndEmitEvent({
+ scrollManagerService.emitRawScrollParam({
unitId,
sheetId,
offsetX,
diff --git a/packages/sheets-ui/src/common/utils.ts b/packages/sheets-ui/src/common/utils.ts
index 8d09820eae0..98ac1fd4415 100644
--- a/packages/sheets-ui/src/common/utils.ts
+++ b/packages/sheets-ui/src/common/utils.ts
@@ -188,9 +188,9 @@ export function transformPosition2Offset(x: number, y: number, scene: Scene, ske
const freeze = worksheet.getFreeze();
const { startColumn, startRow, xSplit, ySplit } = freeze;
// freeze start
- const startSheetView = skeleton.getNoMergeCellPositionByIndexWithNoHeader(startRow - ySplit, startColumn - xSplit);
+ const startSheetView = skeleton.getNoMergeCellWithCoordByIndex(startRow - ySplit, startColumn - xSplit, false);
// freeze end
- const endSheetView = skeleton.getNoMergeCellPositionByIndexWithNoHeader(startRow, startColumn);
+ const endSheetView = skeleton.getNoMergeCellWithCoordByIndex(startRow, startColumn, false);
const { rowHeaderWidth, columnHeaderHeight } = skeleton;
const freezeWidth = endSheetView.startX - startSheetView.startX;
const freezeHeight = endSheetView.startY - startSheetView.startY;
@@ -301,10 +301,10 @@ export function getHoverCellPosition(currentRender: IRender, workbook: Workbook,
};
const position: IPosition = {
- startX: (skeleton.getOffsetByPositionX(anchorCell.startColumn - 1) - scrollXY.x) * scaleX,
- endX: (skeleton.getOffsetByPositionX(anchorCell.endColumn) - scrollXY.x) * scaleX,
- startY: (skeleton.getOffsetByPositionY(anchorCell.startRow - 1) - scrollXY.y) * scaleY,
- endY: (skeleton.getOffsetByPositionY(anchorCell.endRow) - scrollXY.y) * scaleY,
+ startX: (skeleton.getOffsetByColumn(anchorCell.startColumn - 1) - scrollXY.x) * scaleX,
+ endX: (skeleton.getOffsetByColumn(anchorCell.endColumn) - scrollXY.x) * scaleX,
+ startY: (skeleton.getOffsetByRow(anchorCell.startRow - 1) - scrollXY.y) * scaleY,
+ endY: (skeleton.getOffsetByRow(anchorCell.endRow) - scrollXY.y) * scaleY,
};
return {
diff --git a/packages/sheets-ui/src/controllers/auto-height.controller.ts b/packages/sheets-ui/src/controllers/auto-height.controller.ts
index c1a3e32cf94..6b0259d60a6 100644
--- a/packages/sheets-ui/src/controllers/auto-height.controller.ts
+++ b/packages/sheets-ui/src/controllers/auto-height.controller.ts
@@ -61,13 +61,13 @@ export class AutoHeightController extends Disposable {
const subUnitId = worksheet.getSheetId();
const sheetSkeletonService = this._renderManagerService.getRenderById(unitId)!.with(SheetSkeletonManagerService);
- if (!subUnitId || !sheetSkeletonService.getCurrent()) {
+ if (!subUnitId || !sheetSkeletonService.getCurrentParam()) {
return {
redos: [],
undos: [],
};
}
- const { skeleton } = sheetSkeletonService.getCurrent()!;
+ const { skeleton } = sheetSkeletonService.getCurrentParam()!;
const rowsAutoHeightInfo = skeleton.calculateAutoHeightInRange(ranges);
const redoParams: ISetWorksheetRowAutoHeightMutationParams = {
diff --git a/packages/sheets-ui/src/controllers/auto-width.controller.ts b/packages/sheets-ui/src/controllers/auto-width.controller.ts
index 55efee3f6fc..e7b92b7f7ac 100644
--- a/packages/sheets-ui/src/controllers/auto-width.controller.ts
+++ b/packages/sheets-ui/src/controllers/auto-width.controller.ts
@@ -72,9 +72,9 @@ export class AutoWidthController extends Disposable {
const { unitId, subUnitId, worksheet } = target;
const sheetSkeletonService = this._renderManagerService.getRenderById(unitId)!.with(SheetSkeletonManagerService);
- if (!sheetSkeletonService.getCurrent()) return defaultValue;
+ if (!sheetSkeletonService.getCurrentParam()) return defaultValue;
- const { skeleton } = sheetSkeletonService.getCurrent()!;
+ const { skeleton } = sheetSkeletonService.getCurrentParam()!;
const colsAutoWidthInfo: IColAutoWidthInfo[] = skeleton.calculateAutoWidthInRange(params.ranges);
const colWidthObject: IObjectArrayPrimitiveType> = {};
diff --git a/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts b/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts
index 6229004c9b6..f72ec918024 100644
--- a/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts
+++ b/packages/sheets-ui/src/controllers/cell-custom-render.controller.ts
@@ -119,7 +119,7 @@ export class CellCustomRenderController extends Disposable implements IRenderMod
const info: ICellRenderContext = {
data: cellData,
- style: skeleton.getsStyles().getStyleByCell(cellData),
+ style: skeleton.getStyles().getStyleByCell(cellData),
primaryWithCoord: skeleton.getCellWithCoordByIndex(cellIndex.actualRow, cellIndex.actualCol),
unitId,
subUnitId,
@@ -197,7 +197,7 @@ export class CellCustomRenderController extends Disposable implements IRenderMod
};
this.disposeWithMe(this._sheetSkeletonManagerService.currentSkeleton$.subscribe(handleSkeletonChange));
- handleSkeletonChange(this._sheetSkeletonManagerService.getCurrent());
+ handleSkeletonChange(this._sheetSkeletonManagerService.getCurrentParam());
this.disposeWithMe(disposableCollection);
}
}
diff --git a/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts b/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts
index 33b7e2268c0..39a51bd9304 100644
--- a/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts
+++ b/packages/sheets-ui/src/controllers/clipboard/clipboard.controller.ts
@@ -553,7 +553,7 @@ export class SheetClipboardController extends RxDisposable {
}
private _generateDocumentDataModelSnapshot(snapshot: Partial) {
- const currentSkeleton = this._renderManagerService.withCurrentTypeOfUnit(UniverInstanceType.UNIVER_SHEET, SheetSkeletonManagerService)?.getCurrent();
+ const currentSkeleton = this._renderManagerService.withCurrentTypeOfUnit(UniverInstanceType.UNIVER_SHEET, SheetSkeletonManagerService)?.getCurrentParam();
if (currentSkeleton == null) {
return null;
}
diff --git a/packages/sheets-ui/src/controllers/drag-render.controller.ts b/packages/sheets-ui/src/controllers/drag-render.controller.ts
index fbd137abe52..acaa7bb8ebf 100644
--- a/packages/sheets-ui/src/controllers/drag-render.controller.ts
+++ b/packages/sheets-ui/src/controllers/drag-render.controller.ts
@@ -58,7 +58,7 @@ export class DragRenderController extends Disposable implements IRenderModule, I
});
};
- handleSkeletonChange(this._sheetSkeletonManagerService.getCurrent());
+ handleSkeletonChange(this._sheetSkeletonManagerService.getCurrentParam());
this.disposeWithMe(this._sheetSkeletonManagerService.currentSkeleton$.subscribe((skeletonParam) => {
handleSkeletonChange(skeletonParam);
}));
diff --git a/packages/sheets-ui/src/controllers/force-string-render.controller.ts b/packages/sheets-ui/src/controllers/force-string-render.controller.ts
index 793cd599fae..20c21d73fd8 100644
--- a/packages/sheets-ui/src/controllers/force-string-render.controller.ts
+++ b/packages/sheets-ui/src/controllers/force-string-render.controller.ts
@@ -46,7 +46,7 @@ export class ForceStringRenderController extends RxDisposable implements IRender
priority: 10,
effect: InterceptorEffectEnum.Style,
handler: (cell, pos, next) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (!skeleton) {
return next(cell);
}
diff --git a/packages/sheets-ui/src/controllers/hover-render.controller.ts b/packages/sheets-ui/src/controllers/hover-render.controller.ts
index 575040d21dc..c6df51e70e3 100644
--- a/packages/sheets-ui/src/controllers/hover-render.controller.ts
+++ b/packages/sheets-ui/src/controllers/hover-render.controller.ts
@@ -79,7 +79,7 @@ export class HoverRenderController extends Disposable implements IRenderModule {
}));
};
- handleSkeletonChange(this._sheetSkeletonManagerService.getCurrent());
+ handleSkeletonChange(this._sheetSkeletonManagerService.getCurrentParam());
this.disposeWithMe(this._sheetSkeletonManagerService.currentSkeleton$.subscribe((skeletonParam) => {
handleSkeletonChange(skeletonParam);
}));
diff --git a/packages/sheets-ui/src/controllers/render-controllers/editor-bridge.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/editor-bridge.render-controller.ts
index 6ffe1e4d6c5..949e3da9939 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/editor-bridge.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/editor-bridge.render-controller.ts
@@ -102,7 +102,7 @@ export class EditorBridgeRenderController extends RxDisposable implements IRende
const unitId = this._context.unitId;
const sheetId = this._context.unit.getActiveSheet()?.getSheetId();
if (!sheetId) return;
- const mergeInfo = this._sheetSkeletonManagerService.getWorksheetSkeleton(sheetId)?.skeleton.getCellWithCoordByIndex(primary.actualRow, primary.actualColumn);
+ const mergeInfo = this._sheetSkeletonManagerService.getSkeletonParam(sheetId)?.skeleton.getCellWithCoordByIndex(primary.actualRow, primary.actualColumn);
const newPrimary: ISelectionCell = mergeInfo
? {
actualRow: mergeInfo.actualRow,
diff --git a/packages/sheets-ui/src/controllers/render-controllers/freeze.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/freeze.render-controller.ts
index cbbfaa4123b..53c4c208897 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/freeze.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/freeze.render-controller.ts
@@ -14,6 +14,22 @@
* limitations under the License.
*/
+import type { ICommandInfo, IFreeze, IRange, IStyleSheet, IWorksheetData, Nullable, Workbook } from '@univerjs/core';
+import type { IMouseEvent, IPointerEvent, IRenderContext, IRenderModule, Viewport } from '@univerjs/engine-render';
+import type {
+ IInsertColCommandParams,
+ IInsertRowCommandParams,
+ IMoveColsCommandParams,
+ IMoveRowsCommandParams,
+ IRemoveRowColCommandParams,
+ ISetColHiddenMutationParams,
+ ISetFrozenMutationParams,
+ ISetRowHiddenMutationParams,
+ ISetWorksheetColWidthMutationParams,
+ ISetWorksheetRowAutoHeightMutationParams,
+ ISetWorksheetRowHeightMutationParams,
+} from '@univerjs/sheets';
+import type { IViewportScrollState } from '../../services/scroll-manager.service';
import {
ColorKit,
createInterceptorKey,
@@ -28,6 +44,7 @@ import {
toDisposable,
} from '@univerjs/core';
import { CURSOR_TYPE, Rect, SHEET_VIEWPORT_KEY, TRANSFORM_CHANGE_OBSERVABLE_TYPE, Vector2 } from '@univerjs/engine-render';
+
import {
InsertColCommand,
InsertRangeMoveDownCommand,
@@ -52,30 +69,13 @@ import {
SheetsSelectionsService,
} from '@univerjs/sheets';
import { Subscription } from 'rxjs';
-import type { ICommandInfo, IFreeze, IRange, IStyleSheet, IWorksheetData, Nullable, Workbook } from '@univerjs/core';
-import type { IMouseEvent, IPointerEvent, IRenderContext, IRenderModule, Viewport } from '@univerjs/engine-render';
-
-import type {
- IInsertColCommandParams,
- IInsertRowCommandParams,
- IMoveColsCommandParams,
- IMoveRowsCommandParams,
- IRemoveRowColCommandParams,
- ISetColHiddenMutationParams,
- ISetFrozenMutationParams,
- ISetRowHiddenMutationParams,
- ISetWorksheetColWidthMutationParams,
- ISetWorksheetRowAutoHeightMutationParams,
- ISetWorksheetRowHeightMutationParams,
-} from '@univerjs/sheets';
import { ScrollCommand } from '../../commands/commands/set-scroll.command';
import { SetZoomRatioOperation } from '../../commands/operations/set-zoom-ratio.operation';
-import { SHEET_COMPONENT_HEADER_LAYER_INDEX } from '../../common/keys';
+import { SHEET_COMPONENT_HEADER_LAYER_INDEX } from '../../common/keys';
import { SheetScrollManagerService } from '../../services/scroll-manager.service';
import { SheetSkeletonManagerService } from '../../services/sheet-skeleton-manager.service';
import { getCoordByOffset, getSheetObject } from '../utils/component-tools';
-import type { IViewportScrollState } from '../../services/scroll-manager.service';
enum FREEZE_DIRECTION_TYPE {
ROW,
@@ -197,7 +197,7 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
const config = freezeConfig ?? this._getFreeze();
if (config == null) return null;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
const { startRow: freezeRow, startColumn: freezeColumn } = config;
const position = this._getPositionByIndex(freezeRow, freezeColumn);
@@ -398,7 +398,7 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
return;
}
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -469,7 +469,7 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
freezeObjectMainRect: Rect,
freezeDirectionType: FREEZE_DIRECTION_TYPE = FREEZE_DIRECTION_TYPE.ROW
) {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -794,7 +794,7 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
xSplit: number = 0,
resetScroll = ResetScrollType.ALL
) {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -854,9 +854,9 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
}
// freeze start
- const startSheetView = skeleton.getNoMergeCellPositionByIndexWithNoHeader(row - ySplit, column - xSplit);
+ const startSheetView = skeleton.getNoMergeCellWithCoordByIndex(row - ySplit, column - xSplit, false);
// freeze end
- const endSheetView = skeleton.getNoMergeCellPositionByIndexWithNoHeader(row, column);
+ const endSheetView = skeleton.getNoMergeCellWithCoordByIndex(row, column, false);
viewMainLeftTop.disable();
viewMainTop.disable();
@@ -1545,8 +1545,8 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
return;
}
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
- const position = skeleton?.getNoMergeCellPositionByIndex(row, column);
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
+ const position = skeleton?.getNoMergeCellWithCoordByIndex(row, column);
if (skeleton == null) {
return;
}
@@ -1566,7 +1566,7 @@ export class HeaderFreezeRenderController extends Disposable implements IRenderM
private _getFreeze() {
const config: IWorksheetData | undefined = this._sheetSkeletonManagerService
- .getCurrent()
+ .getCurrentParam()
?.skeleton
.getWorksheetConfig();
diff --git a/packages/sheets-ui/src/controllers/render-controllers/header-menu.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/header-menu.render-controller.ts
index bae867efe02..db4349aa8d9 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/header-menu.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/header-menu.render-controller.ts
@@ -124,7 +124,7 @@ export class HeaderMenuRenderController extends Disposable implements IRenderMod
initialType === HEADER_HOVER_TYPE.ROW ? spreadsheetRowHeader : spreadsheetColumnHeader;
const pointerMoveHandler = (evt: IPointerEvent | IMouseEvent) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
diff --git a/packages/sheets-ui/src/controllers/render-controllers/header-move.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/header-move.render-controller.ts
index f2f7f47ffb1..c1f75764556 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/header-move.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/header-move.render-controller.ts
@@ -126,7 +126,7 @@ export class HeaderMoveRenderController extends Disposable implements IRenderMod
// only style cursor style when pointer move
const pointerMoveHandler = (evt: IPointerEvent | IMouseEvent) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -166,7 +166,7 @@ export class HeaderMoveRenderController extends Disposable implements IRenderMod
const pointerDownHandler = (evt: IPointerEvent | IMouseEvent, state: EventState) => {
if (state.isStopPropagation) return;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -356,7 +356,7 @@ export class HeaderMoveRenderController extends Disposable implements IRenderMod
initialType: RANGE_TYPE.ROW | RANGE_TYPE.COLUMN
) {
const scene = this._context.scene;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -377,7 +377,7 @@ export class HeaderMoveRenderController extends Disposable implements IRenderMod
const { row, column } = moveActualSelection;
- const startCell = skeleton.getNoMergeCellPositionByIndex(row, column);
+ const startCell = skeleton.getNoMergeCellWithCoordByIndex(row, column);
const { startX: cellStartX, startY: cellStartY, endX: cellEndX, endY: cellEndY } = startCell;
diff --git a/packages/sheets-ui/src/controllers/render-controllers/header-resize.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/header-resize.render-controller.ts
index 98285680ed9..8b6dc0aac44 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/header-resize.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/header-resize.render-controller.ts
@@ -160,7 +160,7 @@ export class HeaderResizeRenderController extends Disposable implements IRenderM
};
const pointerMoveEvent = (evt: IPointerEvent | IMouseEvent, _state: EventState) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null || this._rowResizeRect == null || this._columnResizeRect == null) {
return;
}
@@ -307,7 +307,7 @@ export class HeaderResizeRenderController extends Disposable implements IRenderM
this.disposeWithMe(
eventBindingObject.onPointerDown$.subscribeEvent((evt: IPointerEvent | IMouseEvent) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) return;
const scene = this._context.scene;
@@ -326,9 +326,9 @@ export class HeaderResizeRenderController extends Disposable implements IRenderM
this._startOffsetY = transformCoord.y;
- const currentOffsetX = skeleton.getOffsetByPositionX(this._currentColumn);
- const currentOffsetY = skeleton.getOffsetByPositionY(this._currentRow);
- const cell = skeleton.getNoMergeCellPositionByIndex(this._currentRow, this._currentColumn);
+ const currentOffsetX = skeleton.getOffsetByColumn(this._currentColumn);
+ const currentOffsetY = skeleton.getOffsetByRow(this._currentRow);
+ const cell = skeleton.getNoMergeCellWithCoordByIndex(this._currentRow, this._currentColumn);
let isStartMove = false;
let moveChangeX = 0;
@@ -488,7 +488,7 @@ export class HeaderResizeRenderController extends Disposable implements IRenderM
const scene = this._context.scene;
scene.resetCursor();
- const sk = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const sk = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (!sk) return;
const startRow = 0;
diff --git a/packages/sheets-ui/src/controllers/render-controllers/header-unhide.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/header-unhide.render-controller.ts
index 55ef3b54fce..b5998a53ab5 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/header-unhide.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/header-unhide.render-controller.ts
@@ -116,7 +116,7 @@ export class HeaderUnhideRenderController extends RxDisposable {
}
private _update(workbook: Workbook, worksheet: Worksheet): void {
- const skeleton = this._sheetSkeletonManagerService.getWorksheetSkeleton(worksheet.getSheetId())?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getSkeletonParam(worksheet.getSheetId())?.skeleton;
if (!skeleton) return;
// steps to render the unhide button for the current worksheet
diff --git a/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-contextmenu.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-contextmenu.render-controller.ts
index 473c11c536f..c1f327811a2 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-contextmenu.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-contextmenu.render-controller.ts
@@ -46,7 +46,7 @@ export class SheetContextMenuMobileRenderController extends Disposable implement
let listenToSelectionChangeEvent = false;
this.disposeWithMe(this._selectionManagerService.selectionMoveStart$.subscribe(() => listenToSelectionChangeEvent = true));
this.disposeWithMe(this._selectionManagerService.selectionMoveEnd$.subscribe((selectionWithStyleList: ISelectionWithStyle[]) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
if (!skeleton || !selectionWithStyleList || listenToSelectionChangeEvent === false) {
return;
}
diff --git a/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-scroll.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-scroll.render-controller.ts
index 1f7a23d77db..d41e8e07abe 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-scroll.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/mobile/mobile-scroll.render-controller.ts
@@ -150,7 +150,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
}
private _getFreeze(): Nullable {
- const snapshot: IWorksheetData | undefined = this._sheetSkeletonManagerService.getCurrent()?.skeleton.getWorksheetConfig();
+ const snapshot: IWorksheetData | undefined = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton.getWorksheetConfig();
if (snapshot == null) {
return;
}
@@ -181,7 +181,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
return;
}
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (!skeleton) return;
// data source: scroll-manager.service.ts@_scrollInfo
@@ -208,7 +208,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
this.disposeWithMe(
viewportMain.onScrollAfter$.subscribeEvent((scrollAfterParam: IScrollObserverParam) => {
if (!scrollAfterParam) return;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) return;
const sheetObject = this._getSheetObject();
if (skeleton == null || sheetObject == null) return;
@@ -216,19 +216,22 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
const { viewportScrollX, viewportScrollY, scrollX, scrollY } = scrollAfterParam;
// according to the actual scroll position, the most suitable row, column and offset combination is recalculated.
- const { row, column, rowOffset, columnOffset } = skeleton.getDecomposedOffset(
+ const { row, column, rowOffset, columnOffset } = skeleton.getOffsetRelativeToRowCol(
viewportScrollX,
viewportScrollY
);
- const scrollInfo = {
+ const scrollInfo: IViewportScrollState = {
sheetViewStartRow: row,
sheetViewStartColumn: column,
offsetX: columnOffset,
offsetY: rowOffset,
+ viewportScrollX,
+ viewportScrollY,
+ scrollX, scrollY,
};
// lastestScrollInfo derived from viewportScrollX, viewportScrollY from onScrollAfter$
- this._scrollManagerService.setScrollStateToCurrSheet(scrollInfo);
+ this._scrollManagerService.setValidScrollStateToCurrSheet(scrollInfo);
this._scrollManagerService.validViewportScrollInfo$.next({
...scrollInfo,
scrollX,
@@ -245,7 +248,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
//#region scroll by bar
this.disposeWithMe(
viewportMain.onScrollByBar$.subscribeEvent((param) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null || param.isTrigger === false) {
return;
}
@@ -258,7 +261,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
const freeze = this._getFreeze();
- const { row, column, rowOffset, columnOffset } = skeleton.getDecomposedOffset(
+ const { row, column, rowOffset, columnOffset } = skeleton.getOffsetRelativeToRowCol(
viewportScrollX,
viewportScrollY
);
@@ -422,7 +425,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
if (!worksheet) return;
const zoomRatio = worksheet.getZoomRatio() || 1;
- scene?.setScaleValue(zoomRatio, zoomRatio);
+ scene?.setScaleValueOnly(zoomRatio, zoomRatio);
scene?.transformByState({
width: rowHeaderWidthAndMarginLeft + columnTotalWidth,
height: columnHeaderHeightAndMarginTop + rowTotalHeight,
@@ -493,7 +496,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
return;
}
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -503,7 +506,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
// eslint-disable-next-line max-lines-per-function, complexity
private _scrollToCell(row: number, column: number): boolean {
- const { rowHeightAccumulation, columnWidthAccumulation } = this._sheetSkeletonManagerService.getCurrent()?.skeleton ?? {};
+ const { rowHeightAccumulation, columnWidthAccumulation } = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton ?? {};
if (rowHeightAccumulation == null || columnWidthAccumulation == null) return false;
@@ -513,7 +516,7 @@ export class MobileSheetsScrollRenderController extends Disposable implements IR
const viewport = scene.getViewport(SHEET_VIEWPORT_KEY.VIEW_MAIN);
if (viewport == null) return false;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) return false;
const worksheet = this._context.unit.getActiveSheet();
diff --git a/packages/sheets-ui/src/controllers/render-controllers/scroll.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/scroll.render-controller.ts
index 3cbda7bb85f..195876aa1f5 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/scroll.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/scroll.render-controller.ts
@@ -126,7 +126,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
this.disposeWithMe(
toDisposable(
this._scrollManagerService.rawScrollInfo$.subscribe((rawScrollInfo: Nullable) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (!skeleton) return;
if (rawScrollInfo == null) {
@@ -159,7 +159,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
this.disposeWithMe(
// set scrollInfo, the event is triggered in viewport@_scrollToScrollbarPos
viewportMain.onScrollAfter$.subscribeEvent((scrollAfterParam: IScrollObserverParam) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null || scrollAfterParam.isTrigger === false) {
return;
}
@@ -173,18 +173,22 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
const { viewportScrollX, viewportScrollY, scrollX, scrollY } = scrollAfterParam;
// according to the actual scroll position, the most suitable row, column and offset combination is recalculated.
- const { row, column, rowOffset, columnOffset } = skeleton.getDecomposedOffset(
+ const { row, column, rowOffset, columnOffset } = skeleton.getOffsetRelativeToRowCol(
viewportScrollX,
viewportScrollY
);
- const scrollInfo = {
+ const scrollInfo: IViewportScrollState = {
sheetViewStartRow: row,
sheetViewStartColumn: column,
offsetX: columnOffset,
offsetY: rowOffset,
+ viewportScrollX,
+ viewportScrollY,
+ scrollX,
+ scrollY,
};
- this._scrollManagerService.setScrollStateToCurrSheet(scrollInfo);
+ this._scrollManagerService.setValidScrollStateToCurrSheet(scrollInfo);
//#endregion
this._scrollManagerService.validViewportScrollInfo$.next({
@@ -194,7 +198,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
scrollX,
scrollY,
});
- // snapshot is diff by diff people!
+ // snapshot is diff by diff users!
// this._scrollManagerService.setScrollInfoToSnapshot({ ...lastestScrollInfo, viewportScrollX, viewportScrollY });
})
);
@@ -204,7 +208,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
this.disposeWithMe(
// get scrollByBar event from viewport and exec ScrollCommand.id.
viewportMain.onScrollByBar$.subscribeEvent((param) => {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null || param.isTrigger === false) {
return;
}
@@ -215,7 +219,9 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
}
const { viewportScrollX = 0, viewportScrollY = 0 } = param;
- const { row, column, rowOffset, columnOffset } = skeleton.getDecomposedOffset(
+ const freeze = this._getFreeze();
+
+ const { row, column, rowOffset, columnOffset } = skeleton.getOffsetRelativeToRowCol(
viewportScrollX,
viewportScrollY
);
@@ -255,7 +261,8 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
viewportMain.viewportScrollX = 0;
viewportMain.viewportScrollY = 0;
}
- this._updateSceneSize(param as unknown as ISheetSkeletonManagerParam);
+ // why handle size in scroll controller?
+ // this._updateSceneSize(param as unknown as ISheetSkeletonManagerParam);
}
})));
}
@@ -369,7 +376,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
}
private _getFreeze(): Nullable {
- const snapshot: IWorksheetData | undefined = this._sheetSkeletonManagerService.getCurrent()?.skeleton.getWorksheetConfig();
+ const snapshot: IWorksheetData | undefined = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton.getWorksheetConfig();
if (snapshot == null) {
return;
}
@@ -396,8 +403,9 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
const worksheet = workbook.getActiveSheet();
if (!worksheet) return;
- const zoomRatio = worksheet.getZoomRatio() || 1;
- scene?.setScaleValue(zoomRatio, zoomRatio);
+ // @TODO lumixraku why handle zoom in scroll.render-controller ???
+ // const zoomRatio = worksheet.getZoomRatio() || 1;
+ // scene?.setScaleValueOnly(zoomRatio, zoomRatio);
scene?.transformByState({
width: rowHeaderWidthAndMarginLeft + columnTotalWidth,
height: columnHeaderHeightAndMarginTop + rowTotalHeight,
@@ -469,7 +477,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
return;
}
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) {
return;
}
@@ -481,7 +489,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
// For arrow key to active cell cause scrolling.
// eslint-disable-next-line max-lines-per-function, complexity
private _scrollToCell(row: number, column: number, forceTop = false, forceLeft = false) {
- const { rowHeightAccumulation, columnWidthAccumulation } = this._sheetSkeletonManagerService.getCurrent()?.skeleton ?? {};
+ const { rowHeightAccumulation, columnWidthAccumulation } = this._sheetSkeletonManagerService.getCurrentSkeleton() ?? {};
if (rowHeightAccumulation == null || columnWidthAccumulation == null) return false;
@@ -491,7 +499,7 @@ export class SheetsScrollRenderController extends Disposable implements IRenderM
const viewport = scene.getViewport(SHEET_VIEWPORT_KEY.VIEW_MAIN);
if (viewport == null) return false;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
if (skeleton == null) return false;
const worksheet = this._context.unit.getActiveSheet();
diff --git a/packages/sheets-ui/src/controllers/render-controllers/sheet.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/sheet.render-controller.ts
index fc4527f0485..6a5c550bf64 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/sheet.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/sheet.render-controller.ts
@@ -238,6 +238,7 @@ export class SheetRenderController extends RxDisposable implements IRenderModule
private _initViewports(scene: Scene, rowHeader: { width: number }, columnHeader: { height: number }) {
const bufferEdgeX = 100;
const bufferEdgeY = 100;
+
const viewMain = new Viewport(SHEET_VIEWPORT_KEY.VIEW_MAIN, scene, {
left: rowHeader.width,
top: columnHeader.height,
@@ -488,7 +489,7 @@ export class SheetRenderController extends RxDisposable implements IRenderModule
}
private _rangeToBounds(ranges: IRange[]) {
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
const { rowHeightAccumulation, columnWidthAccumulation, rowHeaderWidth, columnHeaderHeight } = skeleton;
const dirtyBounds: IViewportInfos[] = [];
diff --git a/packages/sheets-ui/src/controllers/render-controllers/skeleton.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/skeleton.render-controller.ts
index abbdeff9fa1..6134f0b4409 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/skeleton.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/skeleton.render-controller.ts
@@ -14,22 +14,51 @@
* limitations under the License.
*/
-import type { Workbook } from '@univerjs/core';
-import type { IRenderContext, IRenderModule } from '@univerjs/engine-render';
+import type { Nullable, Workbook } from '@univerjs/core';
+import type { ISheetSkeletonManagerParam } from '../../services/sheet-skeleton-manager.service';
import { Disposable, Inject } from '@univerjs/core';
+import { type IRenderContext, IRenderManagerService, type IRenderModule } from '@univerjs/engine-render';
import { SheetSkeletonManagerService } from '../../services/sheet-skeleton-manager.service';
export class SheetSkeletonRenderController extends Disposable implements IRenderModule {
constructor(
private readonly _context: IRenderContext,
- @Inject(SheetSkeletonManagerService) private readonly _sheetSkeletonManagerService: SheetSkeletonManagerService
+ @Inject(SheetSkeletonManagerService) private readonly _sheetSkeletonManagerService: SheetSkeletonManagerService,
+ @IRenderManagerService private readonly _renderManagerService: IRenderManagerService
) {
super();
this.disposeWithMe(this._context.unit.sheetDisposed$.subscribe((sheet) => {
- this._sheetSkeletonManagerService.disposeSkeleton({
- sheetId: sheet.getSheetId(),
- });
+ this._sheetSkeletonManagerService.disposeSkeleton(sheet.getSheetId());
}));
+
+ this._sheetSkeletonManagerService.currentSkeletonBefore$.subscribe((param: Nullable) => {
+ this._updateSceneSize(param);
+ });
+ }
+
+ private _updateSceneSize(param: Nullable) {
+ if (param == null) {
+ return;
+ }
+
+ const { unitId } = this._context;
+ const { skeleton } = param;
+ const scene = this._renderManagerService.getRenderById(unitId)?.scene;
+
+ if (skeleton == null || scene == null) {
+ return;
+ }
+
+ const { rowTotalHeight, columnTotalWidth, rowHeaderWidthAndMarginLeft, columnHeaderHeightAndMarginTop } =
+ skeleton;
+ const workbook = this._context.unit;
+ const worksheet = workbook.getActiveSheet();
+ if (!worksheet) return;
+
+ scene?.transformByState({
+ width: rowHeaderWidthAndMarginLeft + columnTotalWidth,
+ height: columnHeaderHeightAndMarginTop + rowTotalHeight,
+ });
}
}
diff --git a/packages/sheets-ui/src/controllers/render-controllers/zoom.render-controller.ts b/packages/sheets-ui/src/controllers/render-controllers/zoom.render-controller.ts
index 7ca1bead4dc..2e12f382160 100644
--- a/packages/sheets-ui/src/controllers/render-controllers/zoom.render-controller.ts
+++ b/packages/sheets-ui/src/controllers/render-controllers/zoom.render-controller.ts
@@ -52,6 +52,7 @@ export class SheetsZoomRenderController extends Disposable implements IRenderMod
const scene = this._getSheetObject().scene;
this.disposeWithMe(
+ // hold ctrl & mousewheel ---> zoom
scene.onMouseWheel$.subscribeEvent((e: IWheelEvent) => {
if (!e.ctrlKey || !this._contextService.getContextValue(FOCUSING_SHEET)) {
return;
@@ -106,12 +107,12 @@ export class SheetsZoomRenderController extends Disposable implements IRenderMod
}
/**
- * Zoom scene, resize viewport and then setScrollInfo
+ * Triggered when zoom and switch sheet.
* @param zoomRatio
*/
private _updateViewZoom(zoomRatio: number) {
const sheetObject = this._getSheetObject();
- sheetObject?.scene.scale(zoomRatio, zoomRatio);
+ sheetObject?.scene.transformByState({ scaleX: zoomRatio, scaleY: zoomRatio });
sheetObject?.spreadsheet.makeForceDirty();
}
diff --git a/packages/sheets-ui/src/controllers/utils/component-tools.ts b/packages/sheets-ui/src/controllers/utils/component-tools.ts
index 8604bd03717..a53b8f3465c 100644
--- a/packages/sheets-ui/src/controllers/utils/component-tools.ts
+++ b/packages/sheets-ui/src/controllers/utils/component-tools.ts
@@ -127,7 +127,7 @@ export function getCoordByOffset(
const { row, column } = moveActualSelection;
- const startCell = skeleton.getNoMergeCellPositionByIndex(row, column);
+ const startCell = skeleton.getNoMergeCellWithCoordByIndex(row, column);
const { startX, startY, endX, endY } = startCell;
diff --git a/packages/sheets-ui/src/facade/f-range.ts b/packages/sheets-ui/src/facade/f-range.ts
index 85a2f020446..0ac25708954 100644
--- a/packages/sheets-ui/src/facade/f-range.ts
+++ b/packages/sheets-ui/src/facade/f-range.ts
@@ -124,7 +124,7 @@ class FRangeSheetsUIMixin extends FRange implements IFRangeSheetsUIMixin {
const subUnitId = this._worksheet.getSheetId();
const skeleton = renderManagerService.getRenderById(unitId)!
.with(SheetSkeletonManagerService)
- .getWorksheetSkeleton(subUnitId)!.skeleton;
+ .getSkeletonParam(subUnitId)!.skeleton;
return skeleton.getCellWithCoordByIndex(this._range.startRow, this._range.startColumn);
}
diff --git a/packages/sheets-ui/src/plugin.ts b/packages/sheets-ui/src/plugin.ts
index 0b92202e1de..0a0b425e0f4 100644
--- a/packages/sheets-ui/src/plugin.ts
+++ b/packages/sheets-ui/src/plugin.ts
@@ -57,6 +57,7 @@ import { HeaderResizeRenderController } from './controllers/render-controllers/h
import { HeaderUnhideRenderController } from './controllers/render-controllers/header-unhide.render-controller';
import { SheetsScrollRenderController } from './controllers/render-controllers/scroll.render-controller';
import { SheetRenderController } from './controllers/render-controllers/sheet.render-controller';
+import { SheetSkeletonRenderController } from './controllers/render-controllers/skeleton.render-controller';
import { SheetsZoomRenderController } from './controllers/render-controllers/zoom.render-controller';
import { SheetUIController } from './controllers/sheet-ui.controller';
import { StatusBarController } from './controllers/status-bar.controller';
@@ -209,6 +210,7 @@ export class UniverSheetsUIPlugin extends Plugin {
private _registerRenderBasics(): void {
([
[SheetSkeletonManagerService],
+ [SheetSkeletonRenderController],
[SheetRenderController],
[ISheetSelectionRenderService, { useClass: SheetSelectionRenderService }],
] as Dependency[]).forEach((m) => {
diff --git a/packages/sheets-ui/src/services/auto-fill/auto-fill.service.ts b/packages/sheets-ui/src/services/auto-fill/auto-fill.service.ts
index 548014729db..f541e5fb597 100644
--- a/packages/sheets-ui/src/services/auto-fill/auto-fill.service.ts
+++ b/packages/sheets-ui/src/services/auto-fill/auto-fill.service.ts
@@ -482,7 +482,7 @@ export class AutoFillService extends Disposable implements IAutoFillService {
private _getAutoHeightUndoRedos(unitId: string, subUnitId: string, ranges: IRange[]) {
const sheetSkeletonService = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService);
- const skeleton = sheetSkeletonService?.getCurrent()?.skeleton;
+ const skeleton = sheetSkeletonService?.getCurrentParam()?.skeleton;
if (!skeleton) return { redos: [], undos: [] };
const rowsAutoHeightInfo = skeleton.calculateAutoHeightInRange(ranges);
diff --git a/packages/sheets-ui/src/services/canvas-pop-manager.service.ts b/packages/sheets-ui/src/services/canvas-pop-manager.service.ts
index 14096787981..c508a49667a 100644
--- a/packages/sheets-ui/src/services/canvas-pop-manager.service.ts
+++ b/packages/sheets-ui/src/services/canvas-pop-manager.service.ts
@@ -225,9 +225,7 @@ export class SheetCanvasPopManagerService extends Disposable {
const unitId = workbook.getUnitId();
const subUnitId = worksheet.getSheetId();
- const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getOrCreateSkeleton({
- sheetId: subUnitId,
- });
+ const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).ensureSkeleton(subUnitId);
const currentRender = this._renderManagerService.getRenderById(unitId);
if (!currentRender || !skeleton) {
@@ -283,9 +281,7 @@ export class SheetCanvasPopManagerService extends Disposable {
return null;
}
- const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getOrCreateSkeleton({
- sheetId: subUnitId,
- });
+ const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).ensureSkeleton(subUnitId);
const currentRender = this._renderManagerService.getRenderById(unitId);
if (!currentRender || !skeleton) {
@@ -336,9 +332,7 @@ export class SheetCanvasPopManagerService extends Disposable {
return null;
}
- const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getOrCreateSkeleton({
- sheetId: subUnitId,
- });
+ const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).ensureSkeleton(subUnitId);
const currentRender = this._renderManagerService.getRenderById(unitId);
if (!currentRender || !skeleton) {
@@ -391,9 +385,7 @@ export class SheetCanvasPopManagerService extends Disposable {
return null;
}
const currentRender = this._renderManagerService.getRenderById(unitId);
- const skeleton = currentRender?.with(SheetSkeletonManagerService).getOrCreateSkeleton({
- sheetId: subUnitId,
- });
+ const skeleton = currentRender?.with(SheetSkeletonManagerService).ensureSkeleton(subUnitId);
const sheetSelectionRenderService = currentRender?.with(ISheetSelectionRenderService);
if (!currentRender || !skeleton || !sheetSelectionRenderService) {
diff --git a/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-test-bed.ts b/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-test-bed.ts
index 83a4b012f6f..d4deb4bc0d1 100644
--- a/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-test-bed.ts
+++ b/packages/sheets-ui/src/services/clipboard/__tests__/clipboard-test-bed.ts
@@ -20,7 +20,7 @@ import type { Dependency, IDisposable, IWorkbookData } from '@univerjs/core';
import { DisposableCollection, ILogService, Inject, Injector, IUniverInstanceService, LocaleService, LocaleType, LogLevel, Plugin, Univer, UniverInstanceType } from '@univerjs/core';
import { CalculateFormulaService, DefinedNamesService, FormulaCurrentConfigService, FormulaDataModel, FormulaRuntimeService, ICalculateFormulaService, IDefinedNamesService, IFormulaCurrentConfigService, IFormulaRuntimeService, LexerTreeBuilder } from '@univerjs/engine-formula';
import { IRenderManagerService, RenderManagerService } from '@univerjs/engine-render';
-import { SheetInterceptorService, SheetsSelectionsService } from '@univerjs/sheets';
+import { SheetInterceptorService, SheetSkeletonService, SheetsSelectionsService } from '@univerjs/sheets';
import {
BrowserClipboardService,
@@ -594,6 +594,7 @@ export function clipboardTestBed(workbookData?: IWorkbookData, dependencies?: De
// NOTE: This is pretty hack for the test. But with these hacks we can avoid to create
// real canvas-environment in univerjs/sheets-ui. If some we have to do that, this hack could be removed.
+ const mockSheetSkService = new SheetSkeletonService(injector);
const fakeSheetSkeletonManagerService = new SheetSkeletonManagerService({
unit: sheet,
unitId: 'test',
@@ -603,7 +604,7 @@ export function clipboardTestBed(workbookData?: IWorkbookData, dependencies?: De
mainComponent: null as any,
components: null as any,
isMainScene: true,
- }, injector);
+ }, injector, mockSheetSkService);
injector.add([SheetSkeletonManagerService, { useValue: fakeSheetSkeletonManagerService }]);
injector.get(IRenderManagerService).addRender('test', {
diff --git a/packages/sheets-ui/src/services/clipboard/__tests__/sheet-paste.spec.ts b/packages/sheets-ui/src/services/clipboard/__tests__/sheet-paste.spec.ts
index a719d71e9c4..1683674f622 100644
--- a/packages/sheets-ui/src/services/clipboard/__tests__/sheet-paste.spec.ts
+++ b/packages/sheets-ui/src/services/clipboard/__tests__/sheet-paste.spec.ts
@@ -107,7 +107,7 @@ describe('Test clipboard', () => {
const worksheet = get(IUniverInstanceService).getUnit('test')?.getSheetBySheetId('sheet1');
if (!worksheet) return false;
const htmlToUSM = new HtmlToUSMService({
- getCurrentSkeleton: () => sheetSkeletonManagerService.getCurrent(),
+ getCurrentSkeleton: () => sheetSkeletonManagerService.getCurrentParam(),
});
const htmlPath = path.join(__dirname, 'assets', 'html', 'excel-base-sample.html');
const html = getHTMLString(htmlPath);
@@ -119,7 +119,7 @@ describe('Test clipboard', () => {
const worksheet = get(IUniverInstanceService).getUnit('test')?.getSheetBySheetId('sheet1');
if (!worksheet) return false;
const htmlToUSM = new HtmlToUSMService({
- getCurrentSkeleton: () => sheetSkeletonManagerService.getCurrent(),
+ getCurrentSkeleton: () => sheetSkeletonManagerService.getCurrentParam(),
});
const htmlPath = path.join(__dirname, 'assets', 'html', 'google-base-sample.html');
const html = getHTMLString(htmlPath);
diff --git a/packages/sheets-ui/src/services/clipboard/clipboard.service.ts b/packages/sheets-ui/src/services/clipboard/clipboard.service.ts
index f0d9fcba86b..e920fa17486 100644
--- a/packages/sheets-ui/src/services/clipboard/clipboard.service.ts
+++ b/packages/sheets-ui/src/services/clipboard/clipboard.service.ts
@@ -142,7 +142,7 @@ export class SheetClipboardService extends Disposable implements ISheetClipboard
) {
super();
this._htmlToUSM = new HtmlToUSMService({
- getCurrentSkeleton: () => this._renderManagerService.withCurrentTypeOfUnit(UniverInstanceType.UNIVER_SHEET, SheetSkeletonManagerService)?.getCurrent(),
+ getCurrentSkeleton: () => this._renderManagerService.withCurrentTypeOfUnit(UniverInstanceType.UNIVER_SHEET, SheetSkeletonManagerService)?.getCurrentParam(),
});
this._usmToHtml = new USMToHtmlService();
diff --git a/packages/sheets-ui/src/services/drag-manager.service.ts b/packages/sheets-ui/src/services/drag-manager.service.ts
index a1476a9d75a..26ed5c0d2b9 100644
--- a/packages/sheets-ui/src/services/drag-manager.service.ts
+++ b/packages/sheets-ui/src/services/drag-manager.service.ts
@@ -78,7 +78,7 @@ export class DragManagerService extends Disposable {
const currentRender = this._renderManagerService.getRenderById(workbook.getUnitId());
if (!currentRender) return;
- const skeletonParam = currentRender.with(SheetSkeletonManagerService).getCurrent();
+ const skeletonParam = currentRender.with(SheetSkeletonManagerService).getCurrentParam();
const scrollManagerService = currentRender.with(SheetScrollManagerService);
const scrollInfo = scrollManagerService.getCurrentScrollState();
diff --git a/packages/sheets-ui/src/services/editor-bridge.service.ts b/packages/sheets-ui/src/services/editor-bridge.service.ts
index ce7b4161a3e..40190033b77 100644
--- a/packages/sheets-ui/src/services/editor-bridge.service.ts
+++ b/packages/sheets-ui/src/services/editor-bridge.service.ts
@@ -36,7 +36,7 @@ import {
UniverInstanceType,
} from '@univerjs/core';
import { getCanvasOffsetByEngine, IEditorService } from '@univerjs/docs-ui';
-import { convertTextRotation, DeviceInputEventType, IRenderManagerService } from '@univerjs/engine-render';
+import { convertTextRotation, convertTransformToOffsetX, convertTransformToOffsetY, DeviceInputEventType, IRenderManagerService } from '@univerjs/engine-render';
import { BEFORE_CELL_EDIT, IRefSelectionsService, SheetInterceptorService } from '@univerjs/sheets';
import { BehaviorSubject, map, switchMap } from 'rxjs';
import { ISheetSelectionRenderService } from './selection/base-selection-render.service';
@@ -188,7 +188,7 @@ export class EditorBridgeService extends Disposable implements IEditorBridgeServ
const ru = this._renderManagerService.getCurrentTypeOfRenderer(UniverInstanceType.UNIVER_SHEET);
if (!ru) return;
- const skeleton = ru.with(SheetSkeletonManagerService).getWorksheetSkeleton(currentEditCell.sheetId)?.skeleton;
+ const skeleton = ru.with(SheetSkeletonManagerService).getSkeletonParam(currentEditCell.sheetId)?.skeleton;
const selectionRenderService = ru.with(ISheetSelectionRenderService);
if (!skeleton) return;
if (!this._currentEditCellState) return;
@@ -207,10 +207,10 @@ export class EditorBridgeService extends Disposable implements IEditorBridgeServ
const { scaleX, scaleY } = scene.getAncestorScale();
const scrollXY = scene.getViewportScrollXY(selectionRenderService.getViewPort());
- startX = skeleton.convertTransformToOffsetX(startX, scaleX, scrollXY);
- startY = skeleton.convertTransformToOffsetY(startY, scaleY, scrollXY);
- endX = skeleton.convertTransformToOffsetX(endX, scaleX, scrollXY);
- endY = skeleton.convertTransformToOffsetY(endY, scaleY, scrollXY);
+ startX = convertTransformToOffsetX(startX, scaleX, scrollXY);
+ startY = convertTransformToOffsetY(startY, scaleY, scrollXY);
+ endX = convertTransformToOffsetX(endX, scaleX, scrollXY);
+ endY = convertTransformToOffsetY(endY, scaleY, scrollXY);
if (resetSizeOnly && this._currentEditCellLayout) {
endX = endX - startX + this._currentEditCellLayout.position.startX;
@@ -322,10 +322,10 @@ export class EditorBridgeService extends Disposable implements IEditorBridgeServ
const { scaleX, scaleY } = scene.getAncestorScale();
const scrollXY = scene.getViewportScrollXY(selectionRenderService.getViewPort());
- startX = skeleton.convertTransformToOffsetX(startX, scaleX, scrollXY);
- startY = skeleton.convertTransformToOffsetY(startY, scaleY, scrollXY);
- endX = skeleton.convertTransformToOffsetX(endX, scaleX, scrollXY);
- endY = skeleton.convertTransformToOffsetY(endY, scaleY, scrollXY);
+ startX = convertTransformToOffsetX(startX, scaleX, scrollXY);
+ startY = convertTransformToOffsetY(startY, scaleY, scrollXY);
+ endX = convertTransformToOffsetX(endX, scaleX, scrollXY);
+ endY = convertTransformToOffsetY(endY, scaleY, scrollXY);
const workbook = this._univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_SHEET)!;
const worksheet = workbook.getActiveSheet();
diff --git a/packages/sheets-ui/src/services/editor/cell-editor-resize.service.ts b/packages/sheets-ui/src/services/editor/cell-editor-resize.service.ts
index 967b9d7687b..047729b8e76 100644
--- a/packages/sheets-ui/src/services/editor/cell-editor-resize.service.ts
+++ b/packages/sheets-ui/src/services/editor/cell-editor-resize.service.ts
@@ -358,7 +358,7 @@ export class SheetCellEditorResizeService extends Disposable implements IRenderM
const editCellState = this._editorBridgeService.getEditCellState();
if (!editCellState) return;
- const skeleton = this._sheetSkeletonManagerService.getWorksheetSkeleton(editCellState.sheetId)?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getSkeletonParam(editCellState.sheetId)?.skeleton;
if (!skeleton) return;
const { row, column, scaleX, scaleY, position, canvasOffset } = editCellState;
const maxSize = this._getEditorMaxSize(position, canvasOffset);
diff --git a/packages/sheets-ui/src/services/hover-manager.service.ts b/packages/sheets-ui/src/services/hover-manager.service.ts
index 1aa3750b368..298e1991022 100644
--- a/packages/sheets-ui/src/services/hover-manager.service.ts
+++ b/packages/sheets-ui/src/services/hover-manager.service.ts
@@ -208,7 +208,7 @@ export class HoverManagerService extends Disposable {
const currentRender = this._renderManagerService.getRenderById(workbook.getUnitId());
if (!currentRender) return null;
- const skeletonParam = currentRender.with(SheetSkeletonManagerService).getWorksheetSkeleton(worksheet.getSheetId());
+ const skeletonParam = currentRender.with(SheetSkeletonManagerService).getSkeletonParam(worksheet.getSheetId());
if (!skeletonParam) return null;
const scrollManagerService = currentRender.with(SheetScrollManagerService);
diff --git a/packages/sheets-ui/src/services/scroll-manager.service.ts b/packages/sheets-ui/src/services/scroll-manager.service.ts
index 2d667ab851b..a7805ff9dd6 100644
--- a/packages/sheets-ui/src/services/scroll-manager.service.ts
+++ b/packages/sheets-ui/src/services/scroll-manager.service.ts
@@ -75,7 +75,7 @@ export type IScrollStateMap = Map>;
*/
export class SheetScrollManagerService implements IRenderModule {
/**
- * a map holds all scroll info for each sheet
+ * a map holds all scroll info for each sheet(valid value)
*/
private readonly _scrollStateMap: IScrollStateMap = new Map();
/**
@@ -111,16 +111,35 @@ export class SheetScrollManagerService implements IRenderModule {
this._rawScrollInfo$.complete();
}
- setSearchParam(param: IScrollStateSearchParam) {
- this._searchParamForScroll = param;
+ calcViewportScrollFromRowColOffset(scrollInfo: Nullable) {
+ if (!scrollInfo) {
+ return {
+ viewportScrollX: 0,
+ viewportScrollY: 0,
+ };
+ }
+
+ let { sheetViewStartColumn, sheetViewStartRow, offsetX, offsetY } = scrollInfo;
+ sheetViewStartRow = sheetViewStartRow || 0;
+ offsetY = offsetY || 0;
+
+ const skeleton = this._sheetSkeletonManagerService.getCurrentSkeleton();
+ const rowAcc = skeleton?.rowHeightAccumulation[sheetViewStartRow - 1] || 0;
+ const colAcc = skeleton?.columnWidthAccumulation[sheetViewStartColumn - 1] || 0;
+ const viewportScrollX = colAcc + offsetX;
+ const viewportScrollY = rowAcc + offsetY;
+
+ return {
+ viewportScrollX,
+ viewportScrollY,
+ };
}
- setSearchParamAndRefresh(param: IScrollStateSearchParam) {
+ setSearchParam(param: IScrollStateSearchParam) {
this._searchParamForScroll = param;
- this._scrollStateNext(param);
}
- getScrollStateByParam(param: IScrollStateSearchParam): Readonly {
+ getScrollStateByParam(param: IScrollStateSearchParam): Readonly> {
return this._getCurrentScroll(param);
}
@@ -128,20 +147,24 @@ export class SheetScrollManagerService implements IRenderModule {
return this._getCurrentScroll(this._searchParamForScroll);
}
+ setValidScrollState(param: IScrollStateWithSearchParam) {
+ this._setScrollState(param);
+ }
+
/**
- * Set scrollInfo by SetScrollOperation, call by ScrollCommand.id.
+ * emit raw scrollInfo by SetScrollOperation, call by ScrollCommand.id.
+ * raw scrollInfo means not handled by limit scroll method.
* @param param
*/
- setScrollInfoAndEmitEvent(param: IScrollStateWithSearchParam) {
- this._setScrollState(param);
- this._scrollStateNext(param);
+ emitRawScrollParam(param: IScrollStateWithSearchParam) {
+ this._emitRawScroll(param);
}
/**
- * Set _scrollStateMap but no _scrollInfo$.next
+ * Set _scrollStateMap
* @param scroll
*/
- setScrollStateToCurrSheet(scroll: IScrollState) {
+ setValidScrollStateToCurrSheet(scroll: IViewportScrollState) {
if (this._searchParamForScroll == null) {
return;
}
@@ -150,6 +173,12 @@ export class SheetScrollManagerService implements IRenderModule {
...this._searchParamForScroll,
...scroll,
});
+
+ const sheetId = this._searchParamForScroll.sheetId;
+ const sheetSkeleton = this._sheetSkeletonManagerService.getSkeleton(sheetId);
+ if (sheetSkeleton) {
+ sheetSkeleton.setScroll(scroll.viewportScrollX, scroll.viewportScrollY);
+ }
}
clear(): void {
@@ -159,30 +188,10 @@ export class SheetScrollManagerService implements IRenderModule {
this._clearByParamAndNotify(this._searchParamForScroll);
}
- calcViewportScrollFromRowColOffset(scrollInfo: Nullable) {
- if (!scrollInfo) {
- return {
- viewportScrollX: 0,
- viewportScrollY: 0,
- };
- }
-
- let { sheetViewStartColumn, sheetViewStartRow, offsetX, offsetY } = scrollInfo;
- sheetViewStartRow = sheetViewStartRow || 0;
- offsetY = offsetY || 0;
-
- const skeleton = this._sheetSkeletonManagerService.getCurrentSkeleton();
- const rowAcc = skeleton?.rowHeightAccumulation[sheetViewStartRow - 1] || 0;
- const colAcc = skeleton?.columnWidthAccumulation[sheetViewStartColumn - 1] || 0;
- const viewportScrollX = colAcc + offsetX;
- const viewportScrollY = rowAcc + offsetY;
-
- return {
- viewportScrollX,
- viewportScrollY,
- };
- }
-
+ /**
+ * scroll
+ * @param scrollInfo
+ */
private _setScrollState(scrollInfo: IScrollStateWithSearchParam): void {
const { unitId, sheetId, sheetViewStartColumn, sheetViewStartRow, offsetX, offsetY } = scrollInfo;
@@ -209,7 +218,12 @@ export class SheetScrollManagerService implements IRenderModule {
offsetY: 0,
});
- this._scrollStateNext(param);
+ this._emitRawScroll({
+ sheetViewStartRow: 0,
+ sheetViewStartColumn: 0,
+ offsetX: 0,
+ offsetY: 0,
+ });
}
private _getCurrentScroll(param: Nullable): IScrollState {
@@ -227,10 +241,7 @@ export class SheetScrollManagerService implements IRenderModule {
return currScrollState || emptyState;
}
- private _scrollStateNext(param: IScrollStateSearchParam): void {
- const scrollInfo = this._getCurrentScroll(param);
-
- // subscriber can be found in scrollManagerService.rawScrollInfo$.subscribe
- this._rawScrollInfo$.next(scrollInfo);
+ private _emitRawScroll(param: IScrollState): void {
+ this._rawScrollInfo$.next(param);
}
}
diff --git a/packages/sheets-ui/src/services/selection/base-selection-render.service.ts b/packages/sheets-ui/src/services/selection/base-selection-render.service.ts
index dd019402736..8bd18b01260 100644
--- a/packages/sheets-ui/src/services/selection/base-selection-render.service.ts
+++ b/packages/sheets-ui/src/services/selection/base-selection-render.service.ts
@@ -373,7 +373,7 @@ export class BaseSelectionRenderService extends Disposable implements ISheetSele
}
protected _getFreeze(): Nullable {
- const freeze = this._sheetSkeletonManagerService.getCurrent()?.skeleton.getWorksheetConfig().freeze;
+ const freeze = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton.getWorksheetConfig().freeze;
return freeze;
}
@@ -808,7 +808,7 @@ export class BaseSelectionRenderService extends Disposable implements ISheetSele
//@region other range type
const { row, column } = skeleton.getCellIndexByOffset(offsetX, offsetY, scaleX, scaleY, scrollXY);
- const startCell = skeleton.getNoMergeCellPositionByIndex(row, column);
+ const startCell = skeleton.getNoMergeCellWithCoordByIndex(row, column);
const { startX, startY, endX, endY } = startCell;
const rangeWithCoord: IRangeWithCoord = {
diff --git a/packages/sheets-ui/src/services/selection/mobile-selection-render.service.ts b/packages/sheets-ui/src/services/selection/mobile-selection-render.service.ts
index 32e6d4432bd..10ead8ba9a9 100644
--- a/packages/sheets-ui/src/services/selection/mobile-selection-render.service.ts
+++ b/packages/sheets-ui/src/services/selection/mobile-selection-render.service.ts
@@ -148,7 +148,7 @@ export class MobileSheetsSelectionRenderService extends BaseSelectionRenderServi
spreadsheetRowHeader?.onPointerUp$.subscribeEvent((evt: IPointerEvent | IMouseEvent, _state: EventState) => {
if (this._normalSelectionDisabled()) return;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
const { row } = getCoordByOffset(evt.offsetX, evt.offsetY, scene, skeleton);
const matchSelectionData = isThisRowSelected(this._workbookSelections.getCurrentSelections(), row);
if (matchSelectionData) return;
@@ -162,7 +162,7 @@ export class MobileSheetsSelectionRenderService extends BaseSelectionRenderServi
spreadsheetColumnHeader?.onPointerUp$.subscribeEvent((evt: IPointerEvent | IMouseEvent, _state: EventState) => {
if (this._normalSelectionDisabled()) return;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
const { column } = getCoordByOffset(evt.offsetX, evt.offsetY, scene, skeleton);
const matchSelectionData = isThisColSelected(this._workbookSelections.getCurrentSelections(), column);
if (matchSelectionData) return;
@@ -179,7 +179,7 @@ export class MobileSheetsSelectionRenderService extends BaseSelectionRenderServi
this._reset(); // remove all other selections
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
const selectionWithStyle = selectionDataForSelectAll(skeleton);
this._addSelectionControlByModelData(selectionWithStyle);
// pointerup --> create selection
@@ -707,7 +707,7 @@ export class MobileSheetsSelectionRenderService extends BaseSelectionRenderServi
if (activeControl == null) {
return;
}
- const skeleton = this._sheetSkeletonManagerService.getCurrent()?.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()?.skeleton;
const sheetContentHeight = skeleton?.rowTotalHeight;
const sheetContentWidth = skeleton?.columnTotalWidth;
const rangeType = activeControl.rangeType;
diff --git a/packages/sheets-ui/src/services/selection/selection-render.service.ts b/packages/sheets-ui/src/services/selection/selection-render.service.ts
index f130ebbc191..a0a8620c314 100644
--- a/packages/sheets-ui/src/services/selection/selection-render.service.ts
+++ b/packages/sheets-ui/src/services/selection/selection-render.service.ts
@@ -92,7 +92,7 @@ export class SheetSelectionRenderService extends BaseSelectionRenderService impl
if (this.isSelectionDisabled()) return;
if (this.inRefSelectionMode()) return;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
const { row } = getCoordByOffset(evt.offsetX, evt.offsetY, scene, skeleton);
const matchSelectionData = isThisRowSelected(this._workbookSelections.getCurrentSelections(), row);
if (matchSelectionData) return;
@@ -108,7 +108,7 @@ export class SheetSelectionRenderService extends BaseSelectionRenderService impl
if (this.isSelectionDisabled()) return;
if (this.inRefSelectionMode()) return;
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
const { column } = getCoordByOffset(evt.offsetX, evt.offsetY, scene, skeleton);
const matchSelectionData = isThisColSelected(this._workbookSelections.getCurrentSelections(), column);
if (matchSelectionData) return;
@@ -126,7 +126,7 @@ export class SheetSelectionRenderService extends BaseSelectionRenderService impl
this._reset(); // remove all other selections
- const skeleton = this._sheetSkeletonManagerService.getCurrent()!.skeleton;
+ const skeleton = this._sheetSkeletonManagerService.getCurrentParam()!.skeleton;
const selectionWithStyle = selectionDataForSelectAll(skeleton);
this._addSelectionControlByModelData(selectionWithStyle);
this.refreshSelectionMoveEnd();
diff --git a/packages/sheets-ui/src/services/selection/selection-shape-extension.ts b/packages/sheets-ui/src/services/selection/selection-shape-extension.ts
index e5246d168cd..30d280cc5a8 100644
--- a/packages/sheets-ui/src/services/selection/selection-shape-extension.ts
+++ b/packages/sheets-ui/src/services/selection/selection-shape-extension.ts
@@ -129,7 +129,7 @@ export class SelectionShapeExtension {
private _getFreeze() {
const renderManagerService = this._injector.get(IRenderManagerService);
const freeze = renderManagerService.withCurrentTypeOfUnit(UniverInstanceType.UNIVER_SHEET, SheetSkeletonManagerService)
- ?.getCurrent()
+ ?.getCurrentParam()
?.skeleton
.getWorksheetConfig()
.freeze;
@@ -243,8 +243,8 @@ export class SelectionShapeExtension {
style: null,
};
const selectionWithCoord = attachSelectionWithCoord(selection, this._skeleton);
- const startCell = this._skeleton.getNoMergeCellPositionByIndex(startRow, startColumn);
- const endCell = this._skeleton.getNoMergeCellPositionByIndex(endRow, endColumn);
+ const startCell = this._skeleton.getNoMergeCellWithCoordByIndex(startRow, startColumn);
+ const endCell = this._skeleton.getNoMergeCellWithCoordByIndex(endRow, endColumn);
const startY = startCell?.startY || 0;
const endY = endCell?.endY || 0;
const startX = startCell?.startX || 0;
@@ -709,8 +709,8 @@ export class SelectionShapeExtension {
isLighten = rulerValue.isLighten;
}
- const startCell = this._skeleton.getNoMergeCellPositionByIndex(startRow, startColumn);
- const endCell = this._skeleton.getNoMergeCellPositionByIndex(endRow, endColumn);
+ const startCell = this._skeleton.getNoMergeCellWithCoordByIndex(startRow, startColumn);
+ const endCell = this._skeleton.getNoMergeCellWithCoordByIndex(endRow, endColumn);
const startY = startCell?.startY || 0;
const endY = endCell?.endY || 0;
diff --git a/packages/sheets-ui/src/services/selection/util.ts b/packages/sheets-ui/src/services/selection/util.ts
index 969201bbd3e..1ae962a3c05 100644
--- a/packages/sheets-ui/src/services/selection/util.ts
+++ b/packages/sheets-ui/src/services/selection/util.ts
@@ -35,8 +35,8 @@ export function attachRangeWithCoord(skeleton: SpreadsheetSkeleton, range: IRang
const _startColumn = endColumn < startColumn ? endColumn : startColumn;
const _endColumn = endColumn < startColumn ? startColumn : endColumn;
- const startCell = skeleton.getNoMergeCellPositionByIndex(_startRow, _startColumn);
- const endCell = skeleton.getNoMergeCellPositionByIndex(_endRow, _endColumn);
+ const startCell = skeleton.getNoMergeCellWithCoordByIndex(_startRow, _startColumn);
+ const endCell = skeleton.getNoMergeCellWithCoordByIndex(_endRow, _endColumn);
return {
startRow,
@@ -71,9 +71,9 @@ export function attachSelectionWithCoord(selection: ISelectionWithStyle, skeleto
export function attachPrimaryWithCoord(skeleton: SpreadsheetSkeleton, primary: ISelectionCell): ICellWithCoord {
const { actualRow, actualColumn, isMerged, isMergedMainCell, startRow, startColumn, endRow, endColumn } = primary;
- const cellPosition = skeleton.getNoMergeCellPositionByIndex(actualRow, actualColumn);
- const startCell = skeleton.getNoMergeCellPositionByIndex(startRow, startColumn);
- const endCell = skeleton.getNoMergeCellPositionByIndex(endRow, endColumn);
+ const cellPosition = skeleton.getNoMergeCellWithCoordByIndex(actualRow, actualColumn);
+ const startCell = skeleton.getNoMergeCellWithCoordByIndex(startRow, startColumn);
+ const endCell = skeleton.getNoMergeCellWithCoordByIndex(endRow, endColumn);
return {
actualRow,
diff --git a/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts b/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts
index 350d755d3a7..cc6284e12fc 100644
--- a/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts
+++ b/packages/sheets-ui/src/services/sheet-skeleton-manager.service.ts
@@ -15,12 +15,14 @@
*/
import type { IRange, IRangeWithCoord, Nullable, Workbook, Worksheet } from '@univerjs/core';
-import type { IRenderContext, IRenderModule } from '@univerjs/engine-render';
+import type { IRenderContext, IRenderModule, Scene } from '@univerjs/engine-render';
import { Disposable, Inject, Injector } from '@univerjs/core';
import { SpreadsheetSkeleton } from '@univerjs/engine-render';
+import { SheetSkeletonService } from '@univerjs/sheets';
import { BehaviorSubject } from 'rxjs';
import { attachRangeWithCoord } from './selection/util';
+ // Why need this SkParam? what is Param used for? Could unitId & sheetId & dirty in skeleton itself ?
export interface ISheetSkeletonManagerParam {
unitId: string;
sheetId: string;
@@ -35,21 +37,13 @@ export interface ISheetSkeletonManagerSearch {
}
/**
- * This service manages the drawing of the sheet's viewModel (skeleton).
- *
- * Each time there is a content change, it will trigger the viewModel of the render to recalculate.
- *
- * Each application and sub-table has its own viewModel (skeleton).
- *
- * The viewModel is also a temporary storage variable, which does not need to be persisted,
- * so it is managed uniformly through the service.
+ * SheetSkeletonManagerService is registered in a render unit
*/
export class SheetSkeletonManagerService extends Disposable implements IRenderModule {
- private _currentSkeletonSearchParam: ISheetSkeletonManagerSearch = {
- sheetId: '',
- };
+ private _sheetId: string = '';
- private _sheetSkeletonParam: ISheetSkeletonManagerParam[] = [];
+ // @TODO lumixraku, why need this? How about put dirty & sheetId & unitId in skeleton itself z?
+ private _sheetSkeletonParamStore: Map = new Map();
private readonly _currentSkeleton$ = new BehaviorSubject>(null);
readonly currentSkeleton$ = this._currentSkeleton$.asObservable();
@@ -62,7 +56,8 @@ export class SheetSkeletonManagerService extends Disposable implements IRenderMo
constructor(
private readonly _context: IRenderContext,
- @Inject(Injector) private readonly _injector: Injector
+ @Inject(Injector) private readonly _injector: Injector,
+ @Inject(SheetSkeletonService) private readonly _sheetSkService: SheetSkeletonService
) {
// empty
super();
@@ -70,7 +65,7 @@ export class SheetSkeletonManagerService extends Disposable implements IRenderMo
this.disposeWithMe(() => {
this._currentSkeletonBefore$.complete();
this._currentSkeleton$.complete();
- this._sheetSkeletonParam = [];
+ this._sheetSkeletonParamStore = new Map();
});
this._initRemoveSheet();
@@ -78,54 +73,89 @@ export class SheetSkeletonManagerService extends Disposable implements IRenderMo
private _initRemoveSheet() {
this.disposeWithMe(this._context.unit.sheetDisposed$.subscribe((sheet) => {
- this.disposeSkeleton({
- sheetId: sheet.getSheetId(),
- });
+ this.disposeSkeleton(sheet.getSheetId());
}));
}
getCurrentSkeleton(): Nullable {
- return this.getCurrent()?.skeleton;
+ return this.getCurrentParam()?.skeleton;
}
+ /**
+ * @deprecated use `getCurrentSkeleton` instead.
+ */
getCurrent(): Nullable {
- return this._getSkeleton(this._currentSkeletonSearchParam);
+ return this.getCurrentParam();
+ }
+
+ /**
+ * get ISheetSkeletonManagerParam from _currentSkeletonSearchParam
+ * @returns
+ */
+ getCurrentParam(): Nullable {
+ return this._getSkeletonParam(this._sheetId);
}
+ /**
+ * Get skeleton by sheetId
+ * @param sheetId
+ */
+ getSkeleton(sheetId: string): Nullable {
+ return this._getSkeleton(sheetId);
+ }
+
+ /**
+ * Get SkeletonParam by sheetId
+ * @param sheetId
+ */
+ getSkeletonParam(sheetId: string): Nullable {
+ return this._getSkeletonParam(sheetId);
+ }
+
+ /**
+ * @deprecated use `getSkeleton` instead.
+ */
getWorksheetSkeleton(sheetId: string): Nullable {
- return this._getSkeleton({ sheetId });
+ return this.getSkeletonParam(sheetId);
}
/**
* unitId is never read?
+ * why ?? what does unitId for ??? no need unitId this service is registered in render unit already.
*/
- getUnitSkeleton(unitId: string, sheetId: string): Nullable {
- const param = this._getSkeleton({ sheetId });
- if (param != null) {
- param.unitId = unitId;
- }
- return param;
- }
+ // getUnitSkeleton(sheetId: string): Nullable {
+ // const param = this._getSkeleton(sheetId);
+ // // if (param) {
+ // // param.unitId = unitId;
+ // // }
+ // return param;
+ // }
setCurrent(searchParam: ISheetSkeletonManagerSearch): Nullable {
- this._setCurrent(searchParam);
+ this._setCurrent(searchParam.sheetId);
+ }
+
+ setSkeletonParam(sheetId: string, skp: ISheetSkeletonManagerParam) {
+ this._sheetSkService.setSkeleton(skp.unitId, sheetId, skp.skeleton);
+ this._sheetSkeletonParamStore.set(sheetId, skp);
}
- private _setCurrent(searchParam: ISheetSkeletonManagerSearch): Nullable {
- const param = this._getSkeleton(searchParam);
+ private _setCurrent(sheetId: string): Nullable {
+ this._sheetId = sheetId;
+ const skParam = this._getSkeletonParam(sheetId);
const unitId = this._context.unitId;
- if (param != null) {
- this._reCalculate(param);
+ if (skParam != null) {
+ this.reCalculate(skParam);
} else {
- const { sheetId } = searchParam;
const workbook = this._context.unit;
- const worksheet = workbook.getSheetBySheetId(searchParam.sheetId);
+ const worksheet = workbook.getSheetBySheetId(sheetId);
if (worksheet == null) {
return;
}
- const skeleton = this._buildSkeleton(worksheet);
- this._sheetSkeletonParam.push({
+ const scene = this._context.scene;
+ const skeleton = this._buildSkeleton(worksheet, scene);
+ this.setSkeletonParam(sheetId, {
unitId,
sheetId,
skeleton,
@@ -133,22 +163,19 @@ export class SheetSkeletonManagerService extends Disposable implements IRenderMo
});
}
- this._currentSkeletonSearchParam = searchParam;
- const sheetId = this._currentSkeletonSearchParam.sheetId;
- const sheetSkeletonManagerParam = this.getUnitSkeleton(unitId, sheetId);
+ const sheetSkeletonManagerParam = this._getSkeletonParam(sheetId);
this._currentSkeletonBefore$.next(sheetSkeletonManagerParam);
this._currentSkeleton$.next(sheetSkeletonManagerParam);
}
- reCalculate() {
- const param = this.getCurrent();
+ // @TODO why need this function? How about caller get skeleton and call sk.calculate()?
+ reCalculate(param?: Nullable) {
+ if (!param) {
+ param = this.getCurrentParam();
+ }
if (param == null) {
return;
}
- this._reCalculate(param);
- }
-
- private _reCalculate(param: ISheetSkeletonManagerParam) {
if (param.dirty) {
param.skeleton.makeDirty(true);
param.dirty = false;
@@ -162,29 +189,37 @@ export class SheetSkeletonManagerService extends Disposable implements IRenderMo
* @param state
*/
makeDirty(searchParm: ISheetSkeletonManagerSearch, state: boolean = true) {
- const param = this._getSkeleton(searchParm);
+ const param = this._getSkeletonParam(searchParm.sheetId);
if (param == null) {
return;
}
param.dirty = state;
}
+ /**
+ * @deprecated Use function `ensureSkeleton` instead.
+ * @param searchParam
+ */
getOrCreateSkeleton(searchParam: ISheetSkeletonManagerSearch) {
- const skeleton = this._getSkeleton(searchParam);
+ return this.ensureSkeleton(searchParam.sheetId);
+ }
+
+ ensureSkeleton(sheetId: string) {
+ const skeleton = this._getSkeletonParam(sheetId);
if (skeleton) {
return skeleton.skeleton;
}
const workbook = this._context.unit;
- const worksheet = workbook.getSheetBySheetId(searchParam.sheetId);
+ const worksheet = workbook.getSheetBySheetId(sheetId);
if (!worksheet) {
return;
}
const newSkeleton = this._buildSkeleton(worksheet);
- this._sheetSkeletonParam.push({
+ this.setSkeletonParam(sheetId, {
unitId: this._context.unitId,
- sheetId: searchParam.sheetId,
+ sheetId,
skeleton: newSkeleton,
dirty: false,
});
@@ -192,12 +227,12 @@ export class SheetSkeletonManagerService extends Disposable implements IRenderMo
return newSkeleton;
}
- disposeSkeleton(searchParm: ISheetSkeletonManagerSearch) {
- const index = this._sheetSkeletonParam.findIndex((param) => param.sheetId === searchParm.sheetId);
- if (index > -1) {
- const skeleton = this._sheetSkeletonParam[index];
- skeleton.skeleton.dispose();
- this._sheetSkeletonParam.splice(index, 1);
+ disposeSkeleton(sheetId: string) {
+ const skParam = this.getSkeletonParam(sheetId);
+ if (skParam) {
+ skParam.skeleton.dispose();
+ this._sheetSkeletonParamStore.delete(sheetId);
+ this._sheetSkService.deleteSkeleton(skParam.unitId, sheetId);
}
}
@@ -209,22 +244,25 @@ export class SheetSkeletonManagerService extends Disposable implements IRenderMo
return attachRangeWithCoord(skeleton, range);
}
- private _getSkeleton(searchParm: ISheetSkeletonManagerSearch): Nullable {
- const item = this._sheetSkeletonParam.find((param) => param.sheetId === searchParm.sheetId);
- if (item != null) {
- item.commandId = searchParm.commandId;
- }
-
+ private _getSkeletonParam(sheetId: string): Nullable {
+ const item = this._sheetSkeletonParamStore.get(sheetId);
return item;
}
- private _buildSkeleton(worksheet: Worksheet) {
+ private _getSkeleton(sheetId: string): Nullable {
+ const param = this._getSkeletonParam(sheetId);
+ return param ? param.skeleton : null;
+ }
+
+ private _buildSkeleton(worksheet: Worksheet, scene: Nullable) {
const spreadsheetSkeleton = this._injector.createInstance(
SpreadsheetSkeleton,
worksheet,
this._context.unit.getStyles()
);
-
+ if (scene) {
+ spreadsheetSkeleton.setScene(scene);
+ }
return spreadsheetSkeleton;
}
}
diff --git a/packages/sheets-ui/src/services/utils/doc-skeleton-util.ts b/packages/sheets-ui/src/services/utils/doc-skeleton-util.ts
index 2f0aca24ac9..ed466c818bf 100644
--- a/packages/sheets-ui/src/services/utils/doc-skeleton-util.ts
+++ b/packages/sheets-ui/src/services/utils/doc-skeleton-util.ts
@@ -212,7 +212,7 @@ export const getCustomRangePosition = (injector: Injector, unitId: string, subUn
}
const currentRender = renderManagerService.getRenderById(workbook.getUnitId());
- const skeletonParam = currentRender?.with(SheetSkeletonManagerService).getWorksheetSkeleton(worksheet.getSheetId());
+ const skeletonParam = currentRender?.with(SheetSkeletonManagerService).getSkeletonParam(worksheet.getSheetId());
const skeleton = skeletonParam?.skeleton;
@@ -282,7 +282,7 @@ export const getEditingCustomRangePosition = (injector: Injector, unitId: string
}
const docSkeleton = renderer.with(DocSkeletonManagerService).getSkeleton();
- const sheetSkeleton = sheetRenderer.with(SheetSkeletonManagerService).getWorksheetSkeleton(sheetId)?.skeleton;
+ const sheetSkeleton = sheetRenderer.with(SheetSkeletonManagerService).getSkeletonParam(sheetId)?.skeleton;
if (!docSkeleton || !sheetSkeleton) {
return null;
diff --git a/packages/sheets-ui/src/services/utils/drawing-position-util.ts b/packages/sheets-ui/src/services/utils/drawing-position-util.ts
index 9840745963b..33d93d75f7b 100644
--- a/packages/sheets-ui/src/services/utils/drawing-position-util.ts
+++ b/packages/sheets-ui/src/services/utils/drawing-position-util.ts
@@ -26,7 +26,7 @@ export function convertPositionSheetOverGridToAbsolute(unitId: string, subUnitId
const { column: fromColumn, columnOffset: fromColumnOffset, row: fromRow, rowOffset: fromRowOffset } = from;
const { column: toColumn, columnOffset: toColumnOffset, row: toRow, rowOffset: toRowOffset } = to;
- const skeleton = sheetSkeletonManagerService.getOrCreateSkeleton({ sheetId: subUnitId });
+ const skeleton = sheetSkeletonManagerService.ensureSkeleton(subUnitId);
if (skeleton == null) {
throw new Error('No current skeleton');
@@ -77,7 +77,7 @@ export function convertPositionSheetOverGridToAbsolute(unitId: string, subUnitId
export function convertPositionCellToSheetOverGrid(unitId: string, subUnitId: string, cellOverGridPosition: ICellOverGridPosition, width: number, height: number, selectionRenderService: ISheetSelectionRenderService, sheetSkeletonManagerService: SheetSkeletonManagerService) {
const { column: fromColumn, columnOffset: fromColumnOffset, row: fromRow, rowOffset: fromRowOffset } = cellOverGridPosition;
- const skeleton = sheetSkeletonManagerService.getOrCreateSkeleton({ sheetId: subUnitId });
+ const skeleton = sheetSkeletonManagerService.ensureSkeleton(subUnitId);
if (skeleton == null) {
throw new Error('No current skeleton');
diff --git a/packages/sheets-ui/src/views/operate-container/AutoFillPopupMenu.tsx b/packages/sheets-ui/src/views/operate-container/AutoFillPopupMenu.tsx
index 9fd35cd61a5..699b5ed790d 100644
--- a/packages/sheets-ui/src/views/operate-container/AutoFillPopupMenu.tsx
+++ b/packages/sheets-ui/src/views/operate-container/AutoFillPopupMenu.tsx
@@ -17,7 +17,7 @@
import type { ICommandInfo, IExecutionOptions } from '@univerjs/core';
import { ICommandService, IUniverInstanceService, LocaleService, toDisposable, useDependency } from '@univerjs/core';
import { DropdownLegacy } from '@univerjs/design';
-import { IRenderManagerService } from '@univerjs/engine-render';
+import { convertTransformToOffsetX, convertTransformToOffsetY, IRenderManagerService } from '@univerjs/engine-render';
import { Autofill, CheckMarkSingle, MoreDownSingle } from '@univerjs/icons';
import clsx from 'clsx';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
@@ -161,10 +161,10 @@ export const AutoFillPopupMenu: React.FC<{}> = () => {
const scaleY = scene?.scaleY;
const scrollXY = scene?.getViewportScrollXY(viewport);
if (!scaleX || !scene || !scaleX || !scaleY || !scrollXY) return null;
- const x = skeleton?.getNoMergeCellPositionByIndex(anchor.row, anchor.col).endX || 0;
- const y = skeleton?.getNoMergeCellPositionByIndex(anchor.row, anchor.col).endY || 0;
- const relativeX = skeleton?.convertTransformToOffsetX(x, scaleX, scrollXY);
- const relativeY = skeleton?.convertTransformToOffsetY(y, scaleY, scrollXY);
+ const x = skeleton?.getNoMergeCellWithCoordByIndex(anchor.row, anchor.col).endX || 0;
+ const y = skeleton?.getNoMergeCellWithCoordByIndex(anchor.row, anchor.col).endY || 0;
+ const relativeX = convertTransformToOffsetX(x, scaleX, scrollXY);
+ const relativeY = convertTransformToOffsetY(y, scaleY, scrollXY);
if (relativeX == null || relativeY == null) return null;
const onVisibleChange = (visible: boolean) => {
diff --git a/packages/sheets/src/index.ts b/packages/sheets/src/index.ts
index 4b517076aca..deca27470e5 100644
--- a/packages/sheets/src/index.ts
+++ b/packages/sheets/src/index.ts
@@ -434,4 +434,6 @@ export { type ISetWorksheetActiveOperationParams, SetWorksheetActiveOperation }
export { type IToggleCellCheckboxCommandParams, ToggleCellCheckboxCommand } from './commands/commands/toggle-checkbox.command';
export { SCOPE_WORKBOOK_VALUE_DEFINED_NAME } from './controllers/defined-name-data.controller';
export type { ICellOverGridPosition, ISheetOverGridPosition } from './basics/cell-position';
+
+export { SheetSkeletonService } from './skeleton/skeleton.service';
// #endregion
diff --git a/packages/sheets/src/sheets-plugin.ts b/packages/sheets/src/sheets-plugin.ts
index 47981e1a079..6d6282e2eb7 100644
--- a/packages/sheets/src/sheets-plugin.ts
+++ b/packages/sheets/src/sheets-plugin.ts
@@ -46,6 +46,7 @@ import { SheetRangeThemeService } from './services/range-theme-service';
import { RefRangeService } from './services/ref-range/ref-range.service';
import { SheetsSelectionsService } from './services/selections/selection.service';
import { SheetInterceptorService } from './services/sheet-interceptor/sheet-interceptor.service';
+import { SheetSkeletonService } from './skeleton/skeleton.service';
const PLUGIN_NAME = 'SHEET_PLUGIN';
@@ -92,6 +93,7 @@ export class UniverSheetsPlugin extends Plugin {
[INumfmtService, { useClass: NumfmtService }],
[SheetInterceptorService],
[SheetRangeThemeService],
+ [SheetSkeletonService],
// controllers
[BasicWorksheetController],
@@ -142,6 +144,7 @@ export class UniverSheetsPlugin extends Plugin {
[WorkbookPermissionService],
[WorksheetPermissionService],
[SheetPermissionViewModelController],
+ [SheetSkeletonService],
]);
}
diff --git a/packages/sheets/src/skeleton/skeleton.service.ts b/packages/sheets/src/skeleton/skeleton.service.ts
new file mode 100644
index 00000000000..344d6c336e1
--- /dev/null
+++ b/packages/sheets/src/skeleton/skeleton.service.ts
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2023-present DreamNum Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import type { Nullable, SheetSkeleton } from '@univerjs/core';
+import { Disposable, Inject, Injector } from '@univerjs/core';
+
+export class SheetSkeletonService extends Disposable {
+ private _sheetSkeletonStore: Map> = new Map();
+
+ constructor(
+ @Inject(Injector) readonly _injector: Injector
+ ) {
+ // empty
+ super();
+
+ this.disposeWithMe(() => {
+ this._sheetSkeletonStore = new Map();
+ });
+ }
+
+ getSkeleton(unitId: string, subUnitId: string): Nullable {
+ if (!this._sheetSkeletonStore.has(unitId)) {
+ return undefined;
+ }
+ return this._sheetSkeletonStore.get(unitId)!.get(subUnitId);
+ }
+
+ setSkeleton(unitId: string, subUnitId: string, skeleton: SheetSkeleton) {
+ if (!this._sheetSkeletonStore.has(unitId)) {
+ this._sheetSkeletonStore.set(unitId, new Map());
+ }
+ this._sheetSkeletonStore.get(unitId)!.set(subUnitId, skeleton);
+ }
+
+ deleteSkeleton(unitId: string, subUnitId: string) {
+ if (!this._sheetSkeletonStore.has(unitId)) {
+ return;
+ }
+ this._sheetSkeletonStore.get(unitId)!.delete(subUnitId);
+ }
+}