Skip to content

Commit

Permalink
feat: format painter set merges
Browse files Browse the repository at this point in the history
  • Loading branch information
yuhongz committed Dec 7, 2023
1 parent 68c0425 commit b02e6d9
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type { ICommand, IMutationInfo, IRange, Worksheet } from '@univerjs/core';
import type { ICellData, ICommand, IMutationInfo, IRange, Worksheet } from '@univerjs/core';
import {
CommandType,
Dimension,
ICellData,
ICommandService,
IUndoRedoService,
IUniverInstanceService,
Expand Down Expand Up @@ -35,11 +34,11 @@ export interface IAddMergeCommandParams {
worksheetId: string;
}

function checkCellContentInRanges(worksheet: Worksheet, ranges: IRange[]): boolean {
export function checkCellContentInRanges(worksheet: Worksheet, ranges: IRange[]): boolean {
return ranges.some((range) => checkCellContentInRange(worksheet, range));
}

function checkCellContentInRange(worksheet: Worksheet, range: IRange): boolean {
export function checkCellContentInRange(worksheet: Worksheet, range: IRange): boolean {
const { startRow, startColumn, endColumn, endRow } = range;
const cellMatrix = worksheet.getMatrixWithMergedCells(startRow, startColumn, endRow, endColumn);

Expand All @@ -53,7 +52,7 @@ function checkCellContentInRange(worksheet: Worksheet, range: IRange): boolean {
return someCellGoingToBeRemoved;
}

function getClearContentMutationParamsForRanges(
export function getClearContentMutationParamsForRanges(
accessor: IAccessor,
workbookId: string,
worksheet: Worksheet,
Expand Down Expand Up @@ -92,7 +91,7 @@ function getClearContentMutationParamsForRanges(
};
}

function getClearContentMutationParamForRange(worksheet: Worksheet, range: IRange): ObjectMatrix<ICellData> {
export function getClearContentMutationParamForRange(worksheet: Worksheet, range: IRange): ObjectMatrix<ICellData> {
const { startRow, startColumn, endColumn, endRow } = range;
const cellMatrix = worksheet.getMatrixWithMergedCells(startRow, startColumn, endRow, endColumn);
const redoMatrix = new ObjectMatrix<ICellData>();
Expand Down
175 changes: 173 additions & 2 deletions packages/sheets-ui/src/commands/commands/set-format-painter.command.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
import type { ICommand } from '@univerjs/core';
import { CommandType, ICommandService } from '@univerjs/core';
import type { ICellData, ICommand, IMutationInfo, IRange, ObjectMatrixPrimitiveType } from '@univerjs/core';
import {
CommandType,
ICommandService,
isICellData,
IUndoRedoService,
IUniverInstanceService,
ObjectMatrix,
sequenceExecute,
Tools,
} from '@univerjs/core';
import type {
IAddWorksheetMergeMutationParams,
IRemoveWorksheetMergeMutationParams,
ISetRangeValuesMutationParams,
} from '@univerjs/sheets';
import {
AddMergeUndoMutationFactory,
AddWorksheetMergeMutation,
getAddMergeMutationRangeByType,
INTERCEPTOR_POINT,
RemoveMergeUndoMutationFactory,
RemoveWorksheetMergeMutation,
SelectionManagerService,
SetRangeValuesCommand,
SetRangeValuesMutation,
SetRangeValuesUndoMutationFactory,
SheetInterceptorService,
} from '@univerjs/sheets';
import type { IAccessor } from '@wendellhu/redi';

import { FormatPainterStatus, IFormatPainterService } from '../../services/format-painter/format-painter.service';
import { SetFormatPainterOperation } from '../operations/set-format-painter.operation';
import { checkCellContentInRanges, getClearContentMutationParamsForRanges } from './add-worksheet-merge.command';

export interface ISetFormatPainterCommandParams {
status: FormatPainterStatus;
Expand Down Expand Up @@ -43,3 +71,146 @@ export const SetOnceFormatPainterCommand: ICommand = {
return commandService.executeCommand(SetFormatPainterOperation.id, { status: newStatus });
},
};

export interface IApplyFormatPainterCommandParams {
worksheetId: string;
workbookId: string;
styleRange: IRange;
styleValues: ICellData[][];
mergeRanges: IRange[];
}

export const ApplyFormatPainterCommand: ICommand = {
type: CommandType.COMMAND,
id: 'sheet.command.apply-format-painter',
handler: async (accessor: IAccessor, params: IApplyFormatPainterCommandParams) => {
const commandService = accessor.get(ICommandService);
const undoRedoService = accessor.get(IUndoRedoService);
const univerInstanceService = accessor.get(IUniverInstanceService);
const selectionManagerService = accessor.get(SelectionManagerService);
const sheetInterceptorService = accessor.get(SheetInterceptorService);
const {
styleValues: value,
styleRange: range,
mergeRanges,
workbookId = univerInstanceService.getCurrentUniverSheetInstance().getUnitId(),
worksheetId = univerInstanceService.getCurrentUniverSheetInstance().getActiveSheet().getSheetId(),
} = params;

const currentSelections = range ? [range] : selectionManagerService.getSelectionRanges();
if (!currentSelections || !currentSelections.length) {
return false;
}

const cellValue = new ObjectMatrix<ICellData>();
let realCellValue: ObjectMatrixPrimitiveType<ICellData> | undefined;

if (Tools.isArray(value)) {
for (let i = 0; i < currentSelections.length; i++) {
const { startRow, startColumn, endRow, endColumn } = currentSelections[i];

for (let r = 0; r <= endRow - startRow; r++) {
for (let c = 0; c <= endColumn - startColumn; c++) {
cellValue.setValue(r + startRow, c + startColumn, value[r][c]);
}
}
}
} else if (isICellData(value)) {
for (let i = 0; i < currentSelections.length; i++) {
const { startRow, startColumn } = currentSelections[i];

cellValue.setValue(startRow, startColumn, value);
}
} else {
realCellValue = value as ObjectMatrixPrimitiveType<ICellData>;
}

const setRangeValuesMutationParams: ISetRangeValuesMutationParams = {
worksheetId,
workbookId,
cellValue: realCellValue ?? cellValue.getMatrix(),
};
const undoSetRangeValuesMutationParams: ISetRangeValuesMutationParams = SetRangeValuesUndoMutationFactory(
accessor,
setRangeValuesMutationParams
);

if (
!sheetInterceptorService.fetchThroughInterceptors(INTERCEPTOR_POINT.PERMISSION)(null, {
id: SetRangeValuesCommand.id,
params: setRangeValuesMutationParams,
})
) {
return false;
}

const setValueMutationResult = commandService.syncExecuteCommand(
SetRangeValuesMutation.id,
setRangeValuesMutationParams
);

const { undos: interceptorUndos, redos: interceptorRedos } = sheetInterceptorService.onCommandExecute({
id: SetRangeValuesCommand.id,
params: { ...setRangeValuesMutationParams, range: currentSelections },
});

// handle merge
const ranges = getAddMergeMutationRangeByType(mergeRanges);
const worksheet = univerInstanceService.getUniverSheetInstance(workbookId)!.getSheetBySheetId(worksheetId)!;

const mergeRedos: IMutationInfo[] = [];
const mergeUndos: IMutationInfo[] = [];

// First we should check if there are values in the going-to-be-merged cells.
const willRemoveSomeCell = checkCellContentInRanges(worksheet, ranges);

// prepare redo mutations
const removeMergeMutationParams: IRemoveWorksheetMergeMutationParams = {
workbookId,
worksheetId,
ranges,
};
const addMergeMutationParams: IAddWorksheetMergeMutationParams = {
workbookId,
worksheetId,
ranges,
};
mergeRedos.push({ id: RemoveWorksheetMergeMutation.id, params: removeMergeMutationParams });
mergeRedos.push({ id: AddWorksheetMergeMutation.id, params: addMergeMutationParams });

// prepare undo mutations
const undoRemoveMergeMutationParams = RemoveMergeUndoMutationFactory(accessor, removeMergeMutationParams);
const undoMutationParams = AddMergeUndoMutationFactory(accessor, addMergeMutationParams);
mergeUndos.push({ id: RemoveWorksheetMergeMutation.id, params: undoMutationParams });
mergeUndos.push({ id: AddWorksheetMergeMutation.id, params: undoRemoveMergeMutationParams });

// add set range values mutations to undo redo mutations
if (willRemoveSomeCell) {
const data = getClearContentMutationParamsForRanges(accessor, workbookId, worksheet, ranges);
mergeRedos.unshift(...data.redos);
mergeUndos.push(...data.undos);
}

const result = await sequenceExecute([...interceptorRedos, ...mergeRedos], commandService);

if (setValueMutationResult && result.result) {
undoRedoService.pushUndoRedo({
unitID: workbookId,
undoMutations: [
{ id: SetRangeValuesMutation.id, params: undoSetRangeValuesMutationParams },
...interceptorUndos,
...mergeUndos,
],
redoMutations: [
{ id: SetRangeValuesMutation.id, params: setRangeValuesMutationParams },
...interceptorRedos,
...mergeRedos,
],
});

return true;
}

return false;
},
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import type { ICellData, ICommandInfo, IRange } from '@univerjs/core';
import { Disposable, ICommandService, IUniverInstanceService, LifecycleStages, OnLifecycle } from '@univerjs/core';
import { CURSOR_TYPE, IRenderManagerService } from '@univerjs/engine-render';
import type { ISetRangeValuesCommandParams, ISetSelectionsOperationParams } from '@univerjs/sheets';
import { SelectionManagerService, SetRangeValuesCommand, SetSelectionsOperation } from '@univerjs/sheets';
import type { ISetSelectionsOperationParams } from '@univerjs/sheets';
import { SelectionManagerService, SetSelectionsOperation } from '@univerjs/sheets';
import { Inject } from '@wendellhu/redi';

import { SetOnceFormatPainterCommand } from '../../commands/commands/set-format-painter.command';
import type { IApplyFormatPainterCommandParams } from '../../commands/commands/set-format-painter.command';
import {
ApplyFormatPainterCommand,
SetOnceFormatPainterCommand,
} from '../../commands/commands/set-format-painter.command';
import { FormatPainterStatus, IFormatPainterService } from '../../services/format-painter/format-painter.service';
import { getSheetObject } from '../utils/component-tools';

Expand Down Expand Up @@ -60,7 +64,7 @@ export class FormatPainterController extends Disposable {
}

private _applyFormatPainter(range: IRange) {
const stylesMatrix = this._formatPainterService.getSelectionStyles();
const { styles: stylesMatrix, merges } = this._formatPainterService.getSelectionFormat();
const workbookId = this._currentUniverService.getCurrentUniverSheetInstance().getUnitId();
const worksheetId = this._currentUniverService.getCurrentUniverSheetInstance().getActiveSheet().getSheetId();
if (!stylesMatrix) return;
Expand All @@ -71,6 +75,7 @@ export class FormatPainterController extends Disposable {
const styleValues: ICellData[][] = Array.from({ length: range.endRow - range.startRow + 1 }, () =>
Array.from({ length: range.endColumn - range.startColumn + 1 }, () => ({}))
);
const mergeRanges: IRange[] = [];

styleValues.forEach((row, rowIndex) => {
row.forEach((col, colIndex) => {
Expand All @@ -84,14 +89,36 @@ export class FormatPainterController extends Disposable {
});
});

const setRangeValuesCommandParams: ISetRangeValuesCommandParams = {
merges.forEach((merge) => {
const relatedRange: IRange = {
startRow: merge.startRow - startRow,
startColumn: merge.startColumn - startColumn,
endRow: merge.endRow - startRow,
endColumn: merge.endColumn - startColumn,
};
const rowRepeats = Math.floor((range.endRow - range.startRow + 1) / styleRowsNum);
const colRepeats = Math.floor((range.endColumn - range.startColumn + 1) / styleColsNum);
for (let i = 0; i < rowRepeats; i++) {
for (let j = 0; j < colRepeats; j++) {
mergeRanges.push({
startRow: relatedRange.startRow + i * styleRowsNum + range.startRow,
startColumn: relatedRange.startColumn + j * styleColsNum + range.startColumn,
endRow: relatedRange.endRow + i * styleRowsNum + range.startRow,
endColumn: relatedRange.endColumn + j * styleColsNum + range.startColumn,
});
}
}
});

const ApplyFormatPainterCommandParams: IApplyFormatPainterCommandParams = {
worksheetId,
workbookId,
range,
value: styleValues,
styleRange: range,
styleValues,
mergeRanges,
};

this._commandService.executeCommand(SetRangeValuesCommand.id, setRangeValuesCommandParams);
this._commandService.executeCommand(ApplyFormatPainterCommand.id, ApplyFormatPainterCommandParams);
}

private _getSheetObject() {
Expand Down
2 changes: 2 additions & 0 deletions packages/sheets-ui/src/controllers/sheet-ui.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import { RefillCommand } from '../commands/commands/refill.command';
import { RenameSheetOperation } from '../commands/commands/rename.command';
import {
ApplyFormatPainterCommand,
SetInfiniteFormatPainterCommand,
SetOnceFormatPainterCommand,
} from '../commands/commands/set-format-painter.command';
Expand Down Expand Up @@ -247,6 +248,7 @@ export class SheetUIController extends Disposable {
SetFormatPainterOperation,
SetInfiniteFormatPainterCommand,
SetOnceFormatPainterCommand,
ApplyFormatPainterCommand,
SetScrollOperation,
SetScrollRelativeCommand,
SetSelectionFrozenCommand,
Expand Down
Loading

0 comments on commit b02e6d9

Please sign in to comment.