Skip to content

Commit

Permalink
feat: add auto col for dv render
Browse files Browse the repository at this point in the history
  • Loading branch information
lumixraku committed Oct 25, 2024
1 parent b090094 commit a343c41
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 19 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"Duplicatable",
"Dushusir",
"endindex",
"endregion",
"esbuild",
"Ethi",
"evented",
Expand Down
1 change: 1 addition & 0 deletions packages/data-validation/src/validators/base-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ import type { ICellCustomRender, ICellRenderContext } from '@univerjs/core';

export interface IBaseDataValidationWidget extends ICellCustomRender {
calcCellAutoHeight(info: ICellRenderContext): number | undefined;
calcCellAutoWidth(info: ICellRenderContext): number | undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ export class Font extends SheetExtension {
}
} else {
ctx.rectByPrecision(startX + 1 / scale, startY + 1 / scale, cellWidth - 2 / scale, cellHeight - 2 / scale);
// for normal cell, forbid text overflow cellarea
// for normal cell, forbid text overflow cell area
ctx.clip();
}
renderFontContext.startX = startX;
Expand Down
44 changes: 28 additions & 16 deletions packages/engine-render/src/components/sheets/sheet-skeleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ export class SpreadsheetSkeleton extends Skeleton {

// const mergedRanges = this.worksheet.getMergedCellRange(startRow, startColumn, endRow, endColumn);

const autoWidth = this._calculateColMaxWidth(colIndex);
const autoWidth = this._calculateColWidth(colIndex);
calculatedCols.add(colIndex);
results.push({
col: colIndex,
Expand All @@ -733,8 +733,7 @@ export class SpreadsheetSkeleton extends Skeleton {
* @param colIndex
* @returns {number} width
*/

private _calculateColMaxWidth(colIndex: number): number {
private _calculateColWidth(colIndex: number): number {
const MEASURE_EXTENT = 10000;
const MEASURE_EXTENT_FOR_PARAGRAPH = MEASURE_EXTENT / 10;
const worksheet = this.worksheet;
Expand Down Expand Up @@ -779,7 +778,8 @@ export class SpreadsheetSkeleton extends Skeleton {
};

const rowIdxArr = createRowSequence(checkStart, checkEnd, otherRowIndex);

const preColIndex = Math.max(0, colIndex - 1);
const currColWidth = this._columnWidthAccumulation[colIndex] - this._columnWidthAccumulation[preColIndex];
for (let i = 0; i < rowIdxArr.length; i++) {
const row = rowIdxArr[i];

Expand All @@ -797,7 +797,8 @@ export class SpreadsheetSkeleton extends Skeleton {
continue;
}
}
let measuredWidth = this.getMeasuredWidthByCell(cell);

let measuredWidth = this._getMeasuredWidthByCell(cell, currColWidth);

if (cell.fontRenderExtension) {
measuredWidth += ((cell.fontRenderExtension?.leftOffset || 0) + (cell.fontRenderExtension?.rightOffset || 0));
Expand All @@ -813,18 +814,24 @@ export class SpreadsheetSkeleton extends Skeleton {

// if there are no content in this column( measure result is 0), return current column width.
if (colWidth === 0) {
const preColIndex = Math.max(0, colIndex - 1);
return this._columnWidthAccumulation[colIndex] - this._columnWidthAccumulation[preColIndex];
return currColWidth;
}
return colWidth;
}

getMeasuredWidthByCell(cell: ICellDataForSheetInterceptor) {
/**
* For _calculateColMaxWidth
* @param cell
* @returns {number} width
*/
_getMeasuredWidthByCell(cell: ICellDataForSheetInterceptor, currColWidth: number) {
let measuredWidth = 0;
if (cell?.interceptorAutoWidth) {
const cellWidth = cell.interceptorAutoWidth();

// isSkip means the text in this cell would not rendering.
if (cell.fontRenderExtension?.isSkip && cell?.interceptorAutoWidth) {
const cellWidth = cell.interceptorAutoWidth?.();
if (cellWidth) {
return measuredWidth;
return cellWidth;
}
}

Expand All @@ -840,8 +847,13 @@ export class SpreadsheetSkeleton extends Skeleton {

const documentViewModel = new DocumentViewModel(documentModel);
const { vertexAngle: angle } = convertTextRotation(textRotation);
const cellStyle = this._styles.getStyleByCell(cell);

documentModel.updateDocumentDataPageSize(Infinity, Infinity);
if (cellStyle?.tb === WrapStrategy.WRAP) {
documentModel.updateDocumentDataPageSize(currColWidth, Infinity);
} else {
documentModel.updateDocumentDataPageSize(Infinity, Infinity);
}

const documentSkeleton = DocumentSkeleton.create(documentViewModel, this._localService);

Expand All @@ -862,10 +874,10 @@ export class SpreadsheetSkeleton extends Skeleton {
const absAngleInRad = Math.abs(degToRad(angle));

measuredWidth +=
t * Math.cos(absAngleInRad) +
r * Math.sin(absAngleInRad) +
b * Math.cos(absAngleInRad) +
l * Math.sin(absAngleInRad);
t * Math.sin(absAngleInRad) +
r * Math.cos(absAngleInRad) +
b * Math.sin(absAngleInRad) +
l * Math.cos(absAngleInRad);
}
return measuredWidth;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,37 @@ export class SheetsDataValidationRenderController extends RxDisposable {
};
return validator?.canvasRender?.calcCellAutoHeight?.(info);
},
interceptorAutoWidth: () => {
const skeleton = this._renderManagerService.getRenderById(unitId)
?.with(SheetSkeletonManagerService)
.getWorksheetSkeleton(subUnitId)
?.skeleton;
if (!skeleton) {
return undefined;
}
const mergeCell = skeleton.worksheet.getMergedCell(row, col);

const info: ICellRenderContext = {
data: {
...cell,
dataValidation: {
ruleId,
validStatus,
rule,
validator,
},
},
style: skeleton.getsStyles().getStyleByCell(cell),
primaryWithCoord: skeleton.getCellByIndex(mergeCell?.startRow ?? row, mergeCell?.startColumn ?? col),
unitId,
subUnitId,
row,
col,
workbook,
worksheet,
};
return validator?.canvasRender?.calcCellAutoWidth?.(info);
},
coverable: (cell?.coverable ?? true) && !(rule.type === DataValidationType.LIST || rule.type === DataValidationType.LIST_MULTIPLE),
});
},
Expand Down Expand Up @@ -390,4 +421,3 @@ export class SheetsDataValidationMobileRenderController extends RxDisposable {
});
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ export class CheckboxRender implements IBaseDataValidationWidget {
return (style?.fs ?? 10) * 1.6;
}

calcCellAutoWidth(info: ICellRenderContext): number | undefined {
const { style } = info;
return (style?.fs ?? 10) * 1.6;
}

private async _parseFormula(rule: IDataValidationRule, unitId: string, subUnitId: string): Promise<IFormulaResult> {
const { formula1 = CHECKBOX_FORMULA_1, formula2 = CHECKBOX_FORMULA_2 } = rule;
const results = await this._formulaService.getRuleFormulaResult(unitId, subUnitId, rule.uid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,32 @@ export class DropdownMultipleWidget implements IBaseDataValidationWidget {
return layout.cellAutoHeight;
}

calcCellAutoWidth(info: ICellRenderContext): number | undefined {
const { primaryWithCoord, style, data } = info;
const fontRenderExtension = data.fontRenderExtension;
const { leftOffset = 0, rightOffset = 0, topOffset = 0, downOffset = 0 } = fontRenderExtension || {};
const _cellBounding = primaryWithCoord.isMergedMainCell ? primaryWithCoord.mergeInfo : primaryWithCoord;
const cellBounding = {
startX: _cellBounding.startX + leftOffset,
endX: _cellBounding.endX - rightOffset,
startY: _cellBounding.startY + topOffset,
endY: _cellBounding.endY - downOffset,
};
const validation = data.dataValidation;
if (!validation) {
return undefined;
}
const cellWidth = cellBounding.endX - cellBounding.startX;
const cellHeight = cellBounding.endY - cellBounding.startY;
const cellValue = getCellValueOrigin(data) ?? '';
const { validator: _validator } = validation;
const validator = _validator as ListMultipleValidator;
const items = validator.parseCellValue(cellValue);
const fontStyle = getFontStyleString(style ?? undefined);
const layout = layoutDropdowns(items, fontStyle, cellWidth, cellHeight);
return layout.calcAutoWidth;
}

isHit(position: { x: number; y: number }, info: ICellRenderContext) {
const { primaryWithCoord } = info;
const cellBounding = primaryWithCoord.isMergedMainCell ? primaryWithCoord.mergeInfo : primaryWithCoord;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const ICON_SIZE = 4;
const ICON_PLACE = 14;
const MARGIN_H = 6;
const MARGIN_V = 4;
const RADIUS_BG = 8;
const DROP_DOWN_ICON_COLOR = '#565656';

const downPath = new Path2D('M3.32201 4.84556C3.14417 5.05148 2.85583 5.05148 2.67799 4.84556L0.134292 1.90016C-0.152586 1.56798 0.0505937 1 0.456301 1L5.5437 1C5.94941 1 6.15259 1.56798 5.86571 1.90016L3.32201 4.84556Z');
Expand Down Expand Up @@ -319,7 +320,7 @@ export class DropdownWidget implements IBaseDataValidationWidget {
width: rectWidth,
height: rectHeight,
fill: activeItem?.color || DROP_DOWN_DEFAULT_COLOR,
radius: 8,
radius: RADIUS_BG,
});
ctx.save();
ctx.translateWithPrecision(PADDING_H, 0);
Expand Down Expand Up @@ -410,6 +411,55 @@ export class DropdownWidget implements IBaseDataValidationWidget {
}
}

calcCellAutoWidth(info: ICellRenderContext): number | undefined {
const { primaryWithCoord, style, data } = info;
const cellRange = primaryWithCoord.isMergedMainCell ? primaryWithCoord.mergeInfo : primaryWithCoord;

const fontRenderExtension = data.fontRenderExtension;
const { leftOffset = 0, rightOffset = 0, topOffset = 0, downOffset = 0 } = fontRenderExtension || {};

const rule = data.dataValidation?.rule;
if (!rule) return;
if (rule.renderMode === DataValidationRenderMode.TEXT) return;

const cellBounding = {
startX: cellRange.startX + leftOffset,
endX: cellRange.endX - rightOffset,
startY: cellRange.startY + topOffset,
endY: cellRange.endY - downOffset,
};
const cellWidth = cellBounding.endX - cellBounding.startX;
const value = getCellValueOrigin(data);
const valueStr = `${value ?? ''}`;

let { tb, pd } = style || {};
const { l = DEFAULT_STYLES.pd.l, r = DEFAULT_STYLES.pd.r } = (pd ?? {});
tb = tb ?? WrapStrategy.WRAP;

let paddingAll = PADDING_H * 2 + ICON_PLACE;
switch (rule.renderMode) {
case DataValidationRenderMode.ARROW:
paddingAll = ICON_PLACE + MARGIN_H * 2 + r + l;
break;
case DataValidationRenderMode.CUSTOM:
paddingAll = ICON_PLACE + PADDING_H * 2 + RADIUS_BG * 2 + r + l; ;
break;
// default is CUSTOM
default:
paddingAll = ICON_PLACE + PADDING_H * 2 + RADIUS_BG * 2 + r + l;
}
const widthForTextLayout = cellWidth - paddingAll;
const { documentSkeleton, docModel } = createDocuments(valueStr, this._localeService, style);
if (tb === WrapStrategy.WRAP) {
docModel.updateDocumentDataPageSize(Math.max(widthForTextLayout, 1));
}

documentSkeleton.calculate();
documentSkeleton.getActualSize();
const textLayout = getDocsSkeletonPageSize(documentSkeleton)!;
return textLayout.width + paddingAll;
}

isHit(position: { x: number; y: number }, info: ICellRenderContext) {
const { data, subUnitId, row, col } = info;
const map = this._ensureMap(subUnitId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ export function layoutDropdowns(items: string[], fontStyle: IDocumentSkeletonFon
}
});
let totalHeight = 0;
let maxLineWidth = 0;
lines.forEach((line, index) => {
maxLineWidth = Math.max(maxLineWidth, line.width);
if (index === lines.length - 1) {
totalHeight += line.height;
} else {
Expand All @@ -108,5 +110,6 @@ export function layoutDropdowns(items: string[], fontStyle: IDocumentSkeletonFon
contentWidth,
contentHeight,
cellAutoHeight: totalHeight + CELL_PADDING_V * 2,
calcAutoWidth: maxLineWidth,
};
}

0 comments on commit a343c41

Please sign in to comment.