mirror of
https://github.com/dream-num/univer.git
synced 2026-09-24 15:32:18 +08:00
feat(drawing): add group facade api (#6944)
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* 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 { Injector, Univer } from '@univerjs/core';
|
||||
import type { ISheetDrawing } from '../../services/sheet-drawing.service';
|
||||
import { DrawingTypeEnum, ICommandService, RedoCommand, UndoCommand } from '@univerjs/core';
|
||||
import { InsertSheetDrawingCommand } from '../../commands/commands/insert-sheet-drawing.command';
|
||||
import { ISheetDrawingService } from '../../services/sheet-drawing.service';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { createSheetsDrawingTestBed } from '../../__tests__/create-sheets-drawing-test-bed';
|
||||
import { FWorksheetDrawingMixin } from '../f-worksheet';
|
||||
|
||||
describe('FWorksheetDrawingMixin group drawings', () => {
|
||||
let univer: Univer;
|
||||
let injector: Injector;
|
||||
|
||||
beforeEach(() => {
|
||||
const testBed = createSheetsDrawingTestBed();
|
||||
univer = testBed.univer;
|
||||
injector = testBed.injector;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
univer.dispose();
|
||||
});
|
||||
|
||||
it('groups drawings and exposes parent and child relationships', () => {
|
||||
const drawings = [
|
||||
createDrawing('drawing-1', 10),
|
||||
createDrawing('drawing-2', 80),
|
||||
];
|
||||
const commandService = injector.get(ICommandService);
|
||||
const sheetDrawingService = injector.get(ISheetDrawingService);
|
||||
const fWorksheet = createFacade(injector);
|
||||
|
||||
expect(commandService.syncExecuteCommand(InsertSheetDrawingCommand.id, { unitId: 'test', drawings })).toBe(true);
|
||||
|
||||
const groupId = fWorksheet.groupDrawings(['drawing-1', 'drawing-2'], 'group-1');
|
||||
|
||||
expect(groupId).toBe('group-1');
|
||||
expect(sheetDrawingService.getDrawingByParam({ unitId: 'test', subUnitId: 'sheet1', drawingId: 'group-1' })?.drawingType)
|
||||
.toBe(DrawingTypeEnum.DRAWING_GROUP);
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-1')).toBe(true);
|
||||
expect(fWorksheet.getDrawingParentGroup('drawing-1')?.drawingId).toBe('group-1');
|
||||
expect(fWorksheet.getDrawingGroupChildren('group-1').map((drawing: ISheetDrawing) => drawing.drawingId))
|
||||
.toEqual(['drawing-1', 'drawing-2']);
|
||||
});
|
||||
|
||||
it('does not group unsupported drawing types', () => {
|
||||
const drawings = [
|
||||
createDrawing('drawing-1', 10),
|
||||
createDrawing('chart-1', 80, DrawingTypeEnum.DRAWING_CHART),
|
||||
];
|
||||
const commandService = injector.get(ICommandService);
|
||||
const fWorksheet = createFacade(injector);
|
||||
|
||||
expect(commandService.syncExecuteCommand(InsertSheetDrawingCommand.id, { unitId: 'test', drawings })).toBe(true);
|
||||
|
||||
const groupId = fWorksheet.groupDrawings(['drawing-1', 'chart-1'], 'group-1');
|
||||
|
||||
expect(groupId).toBeNull();
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-1')).toBe(false);
|
||||
expect(fWorksheet.isDrawingGrouped('chart-1')).toBe(false);
|
||||
});
|
||||
|
||||
it('supports undo and redo for group and ungroup facade operations', async () => {
|
||||
const drawings = [
|
||||
createDrawing('drawing-1', 10),
|
||||
createDrawing('drawing-2', 80),
|
||||
];
|
||||
const commandService = injector.get(ICommandService);
|
||||
const sheetDrawingService = injector.get(ISheetDrawingService);
|
||||
const fWorksheet = createFacade(injector);
|
||||
|
||||
expect(commandService.syncExecuteCommand(InsertSheetDrawingCommand.id, { unitId: 'test', drawings })).toBe(true);
|
||||
expect(fWorksheet.groupDrawings(['drawing-1', 'drawing-2'], 'group-1')).toBe('group-1');
|
||||
|
||||
expect(await commandService.executeCommand(UndoCommand.id)).toBe(true);
|
||||
expect(sheetDrawingService.getDrawingByParam({ unitId: 'test', subUnitId: 'sheet1', drawingId: 'group-1' })).toBeUndefined();
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-1')).toBe(false);
|
||||
|
||||
expect(await commandService.executeCommand(RedoCommand.id)).toBe(true);
|
||||
expect(sheetDrawingService.getDrawingByParam({ unitId: 'test', subUnitId: 'sheet1', drawingId: 'group-1' })?.drawingType)
|
||||
.toBe(DrawingTypeEnum.DRAWING_GROUP);
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-1')).toBe(true);
|
||||
|
||||
expect(fWorksheet.ungroupDrawings(['group-1'])).toBe(true);
|
||||
expect(sheetDrawingService.getDrawingByParam({ unitId: 'test', subUnitId: 'sheet1', drawingId: 'group-1' })).toBeUndefined();
|
||||
|
||||
expect(await commandService.executeCommand(UndoCommand.id)).toBe(true);
|
||||
expect(sheetDrawingService.getDrawingByParam({ unitId: 'test', subUnitId: 'sheet1', drawingId: 'group-1' })?.drawingType)
|
||||
.toBe(DrawingTypeEnum.DRAWING_GROUP);
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-1')).toBe(true);
|
||||
});
|
||||
|
||||
it('does not group with duplicate drawing ids or an existing group id', () => {
|
||||
const drawings = [
|
||||
createDrawing('drawing-1', 10),
|
||||
createDrawing('drawing-2', 80),
|
||||
];
|
||||
const commandService = injector.get(ICommandService);
|
||||
const fWorksheet = createFacade(injector);
|
||||
|
||||
expect(commandService.syncExecuteCommand(InsertSheetDrawingCommand.id, { unitId: 'test', drawings })).toBe(true);
|
||||
|
||||
expect(fWorksheet.groupDrawings(['drawing-1', 'drawing-1'], 'group-1')).toBeNull();
|
||||
expect(fWorksheet.groupDrawings(['drawing-1', 'drawing-2'], 'drawing-1')).toBeNull();
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-1')).toBe(false);
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-2')).toBe(false);
|
||||
});
|
||||
|
||||
it('ungroups drawings and clears parent relationships', () => {
|
||||
const drawings = [
|
||||
createDrawing('drawing-1', 10),
|
||||
createDrawing('drawing-2', 80),
|
||||
];
|
||||
const commandService = injector.get(ICommandService);
|
||||
const sheetDrawingService = injector.get(ISheetDrawingService);
|
||||
const fWorksheet = createFacade(injector);
|
||||
|
||||
expect(commandService.syncExecuteCommand(InsertSheetDrawingCommand.id, { unitId: 'test', drawings })).toBe(true);
|
||||
expect(fWorksheet.groupDrawings(['drawing-1', 'drawing-2'], 'group-1')).toBe('group-1');
|
||||
|
||||
expect(fWorksheet.ungroupDrawings(['group-1'])).toBe(true);
|
||||
|
||||
expect(sheetDrawingService.getDrawingByParam({ unitId: 'test', subUnitId: 'sheet1', drawingId: 'group-1' })).toBeUndefined();
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-1')).toBe(false);
|
||||
expect(fWorksheet.isDrawingGrouped('drawing-2')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns nested group children when recursive is enabled', () => {
|
||||
const drawings = [
|
||||
createDrawing('drawing-1', 10),
|
||||
createDrawing('drawing-2', 80),
|
||||
createDrawing('drawing-3', 150),
|
||||
];
|
||||
const commandService = injector.get(ICommandService);
|
||||
const fWorksheet = createFacade(injector);
|
||||
|
||||
expect(commandService.syncExecuteCommand(InsertSheetDrawingCommand.id, { unitId: 'test', drawings })).toBe(true);
|
||||
expect(fWorksheet.groupDrawings(['drawing-1', 'drawing-2'], 'group-1')).toBe('group-1');
|
||||
expect(fWorksheet.groupDrawings(['group-1', 'drawing-3'], 'group-2')).toBe('group-2');
|
||||
|
||||
expect(fWorksheet.getDrawingGroupChildren('group-2').map((drawing: ISheetDrawing) => drawing.drawingId))
|
||||
.toEqual(['drawing-3', 'group-1']);
|
||||
const recursiveChildren = fWorksheet.getDrawingGroupChildren('group-2', true).map((drawing: ISheetDrawing) => drawing.drawingId);
|
||||
expect(recursiveChildren).toHaveLength(4);
|
||||
expect(recursiveChildren).toEqual(expect.arrayContaining(['drawing-1', 'drawing-2', 'drawing-3', 'group-1']));
|
||||
});
|
||||
});
|
||||
|
||||
function createFacade(injector: Injector): FWorksheetDrawingMixin {
|
||||
const instance = Object.create(FWorksheetDrawingMixin.prototype) as any;
|
||||
|
||||
instance._commandService = injector.get(ICommandService);
|
||||
instance._fWorkbook = { getId: () => 'test' };
|
||||
instance._workbook = { getUnitId: () => 'test' };
|
||||
instance._worksheet = { getSheetId: () => 'sheet1' };
|
||||
instance._injector = injector;
|
||||
|
||||
return instance as FWorksheetDrawingMixin;
|
||||
}
|
||||
|
||||
function createDrawing(drawingId: string, left: number, drawingType = DrawingTypeEnum.DRAWING_SHAPE): ISheetDrawing {
|
||||
return {
|
||||
unitId: 'test',
|
||||
subUnitId: 'sheet1',
|
||||
drawingId,
|
||||
drawingType,
|
||||
transform: {
|
||||
left,
|
||||
top: 20,
|
||||
width: 40,
|
||||
height: 30,
|
||||
},
|
||||
sheetTransform: {
|
||||
from: { row: 1, column: 1, rowOffset: 0, columnOffset: 0 },
|
||||
to: { row: 3, column: 3, rowOffset: 0, columnOffset: 0 },
|
||||
},
|
||||
axisAlignSheetTransform: {
|
||||
from: { row: 1, column: 1, rowOffset: 0, columnOffset: 0 },
|
||||
to: { row: 3, column: 3, rowOffset: 0, columnOffset: 0 },
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -15,12 +15,21 @@
|
||||
*/
|
||||
|
||||
import type { IFBlobSource } from '@univerjs/core/facade';
|
||||
import type { ISheetImage } from '@univerjs/sheets-drawing';
|
||||
import { DrawingTypeEnum, ImageSourceType } from '@univerjs/core';
|
||||
import { InsertSheetDrawingCommand, ISheetDrawingService, RemoveSheetDrawingCommand, SetSheetDrawingCommand } from '@univerjs/sheets-drawing';
|
||||
import type { IDrawingParam } from '@univerjs/core';
|
||||
import type { IDrawingGroupUpdateParam, IDrawingJsonUndo1 } from '@univerjs/drawing';
|
||||
import type { ISheetDrawing, ISheetImage } from '@univerjs/sheets-drawing';
|
||||
import { DrawingTypeEnum, generateRandomId, ImageSourceType, IUndoRedoService } from '@univerjs/core';
|
||||
import { getGroupState, transformObjectOutOfGroup } from '@univerjs/engine-render';
|
||||
import { DrawingApplyType, InsertSheetDrawingCommand, ISheetDrawingService, RemoveSheetDrawingCommand, SetDrawingApplyMutation, SetSheetDrawingCommand } from '@univerjs/sheets-drawing';
|
||||
import { FWorksheet } from '@univerjs/sheets/facade';
|
||||
import { FOverGridImage, FOverGridImageBuilder } from './f-over-grid-image';
|
||||
|
||||
const GROUPABLE_DRAWING_TYPES = new Set([
|
||||
DrawingTypeEnum.DRAWING_IMAGE,
|
||||
DrawingTypeEnum.DRAWING_SHAPE,
|
||||
DrawingTypeEnum.DRAWING_GROUP,
|
||||
]);
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
@@ -217,6 +226,166 @@ export interface IFWorksheetDrawingMixin {
|
||||
* ```
|
||||
*/
|
||||
newOverGridImage(): FOverGridImageBuilder;
|
||||
|
||||
/**
|
||||
* Group drawings on the current sheet.
|
||||
* @param {string[]} drawingIds - The drawing ids to group. At least two drawings are required.
|
||||
* @param {string} [groupId] - Optional group drawing id. If omitted, a new id will be generated.
|
||||
* @returns {string | null} The group id if the operation succeeds, otherwise null.
|
||||
* @example
|
||||
* ```ts
|
||||
* // Group two over-grid images on the active sheet.
|
||||
* const fWorkbook = univerAPI.getActiveWorkbook();
|
||||
* const fWorksheet = fWorkbook.getActiveSheet();
|
||||
* const image1 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(1)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* const image2 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(3)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* fWorksheet.insertImages([image1, image2]);
|
||||
* const groupId = fWorksheet.groupDrawings([image1.drawingId, image2.drawingId]);
|
||||
* console.log(groupId);
|
||||
* ```
|
||||
*/
|
||||
groupDrawings(drawingIds: string[], groupId?: string): string | null;
|
||||
|
||||
/**
|
||||
* Ungroup drawing groups on the current sheet.
|
||||
* @param {string[]} groupIds - The group drawing ids to ungroup.
|
||||
* @returns {boolean} true if the operation succeeds, otherwise false.
|
||||
* @example
|
||||
* ```ts
|
||||
* // Group two images, then ungroup the generated group.
|
||||
* const fWorkbook = univerAPI.getActiveWorkbook();
|
||||
* const fWorksheet = fWorkbook.getActiveSheet();
|
||||
* const image1 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(1)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* const image2 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(3)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* fWorksheet.insertImages([image1, image2]);
|
||||
* const groupId = fWorksheet.groupDrawings([image1.drawingId, image2.drawingId]);
|
||||
* if (groupId) {
|
||||
* const result = fWorksheet.ungroupDrawings([groupId]);
|
||||
* console.log(result);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
ungroupDrawings(groupIds: string[]): boolean;
|
||||
|
||||
/**
|
||||
* Get children of a drawing group on the current sheet.
|
||||
* @param {string} groupId - The group drawing id.
|
||||
* @param {boolean} [recursive] - Whether to return all descendants.
|
||||
* @returns {ISheetDrawing[]} The child drawings.
|
||||
* @example
|
||||
* ```ts
|
||||
* // Get the direct children of a drawing group.
|
||||
* const fWorkbook = univerAPI.getActiveWorkbook();
|
||||
* const fWorksheet = fWorkbook.getActiveSheet();
|
||||
* const image1 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(1)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* const image2 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(3)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* fWorksheet.insertImages([image1, image2]);
|
||||
* const groupId = fWorksheet.groupDrawings([image1.drawingId, image2.drawingId]);
|
||||
* if (groupId) {
|
||||
* const children = fWorksheet.getDrawingGroupChildren(groupId);
|
||||
* console.log(children.map((drawing) => drawing.drawingId));
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
getDrawingGroupChildren(groupId: string, recursive?: boolean): ISheetDrawing[];
|
||||
|
||||
/**
|
||||
* Get the parent group of a drawing on the current sheet.
|
||||
* @param {string} drawingId - The child drawing id.
|
||||
* @returns {ISheetDrawing | null} The parent group drawing, or null if the drawing is not grouped.
|
||||
* @example
|
||||
* ```ts
|
||||
* // Get the parent group of a drawing.
|
||||
* const fWorkbook = univerAPI.getActiveWorkbook();
|
||||
* const fWorksheet = fWorkbook.getActiveSheet();
|
||||
* const image1 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(1)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* const image2 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(3)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* fWorksheet.insertImages([image1, image2]);
|
||||
* fWorksheet.groupDrawings([image1.drawingId, image2.drawingId]);
|
||||
* const parentGroup = fWorksheet.getDrawingParentGroup(image1.drawingId);
|
||||
* console.log(parentGroup?.drawingId);
|
||||
* ```
|
||||
*/
|
||||
getDrawingParentGroup(drawingId: string): ISheetDrawing | null;
|
||||
|
||||
/**
|
||||
* Returns whether a drawing is inside a group on the current sheet.
|
||||
* @param {string} drawingId - The drawing id.
|
||||
* @returns {boolean} true if the drawing has a parent group.
|
||||
* @example
|
||||
* ```ts
|
||||
* // Check whether a drawing is inside a group.
|
||||
* const fWorkbook = univerAPI.getActiveWorkbook();
|
||||
* const fWorksheet = fWorkbook.getActiveSheet();
|
||||
* const image1 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(1)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* const image2 = await fWorksheet.newOverGridImage()
|
||||
* .setSource('https://avatars.githubusercontent.com/u/61444807?s=48&v=4', univerAPI.Enum.ImageSourceType.URL)
|
||||
* .setColumn(3)
|
||||
* .setRow(1)
|
||||
* .setWidth(100)
|
||||
* .setHeight(100)
|
||||
* .buildAsync();
|
||||
* fWorksheet.insertImages([image1, image2]);
|
||||
* fWorksheet.groupDrawings([image1.drawingId, image2.drawingId]);
|
||||
* const isGrouped = fWorksheet.isDrawingGrouped(image1.drawingId);
|
||||
* console.log(isGrouped);
|
||||
* ```
|
||||
*/
|
||||
isDrawingGrouped(drawingId: string): boolean;
|
||||
}
|
||||
|
||||
export class FWorksheetDrawingMixin extends FWorksheet implements IFWorksheetDrawingMixin {
|
||||
@@ -329,6 +498,199 @@ export class FWorksheetDrawingMixin extends FWorksheet implements IFWorksheetDra
|
||||
const subUnitId = this.getSheetId();
|
||||
return this._injector.createInstance(FOverGridImageBuilder, unitId, subUnitId);
|
||||
}
|
||||
|
||||
override groupDrawings(drawingIds: string[], groupId = generateRandomId(10)): string | null {
|
||||
const uniqueDrawingIds = Array.from(new Set(drawingIds));
|
||||
if (uniqueDrawingIds.length < 2) return null;
|
||||
|
||||
const unitId = this._fWorkbook.getId();
|
||||
const subUnitId = this.getSheetId();
|
||||
const sheetDrawingService = this._injector.get(ISheetDrawingService);
|
||||
if (sheetDrawingService.getDrawingByParam({ unitId, subUnitId, drawingId: groupId })) return null;
|
||||
|
||||
const drawings = uniqueDrawingIds.map((drawingId) => sheetDrawingService.getDrawingByParam({ unitId, subUnitId, drawingId }));
|
||||
|
||||
if (drawings.some((drawing) => !drawing)) return null;
|
||||
if (drawings.some((drawing) => !GROUPABLE_DRAWING_TYPES.has(drawing!.drawingType))) return null;
|
||||
|
||||
const validDrawings = drawings as ISheetDrawing[];
|
||||
const groupTransform = getGroupState(0, 0, validDrawings.map((drawing) => drawing.transform || {}));
|
||||
const groupParam = {
|
||||
unitId,
|
||||
subUnitId,
|
||||
drawingId: groupId,
|
||||
drawingType: DrawingTypeEnum.DRAWING_GROUP,
|
||||
transform: groupTransform,
|
||||
groupBaseBound: {
|
||||
left: groupTransform.left,
|
||||
top: groupTransform.top,
|
||||
width: groupTransform.width,
|
||||
height: groupTransform.height,
|
||||
},
|
||||
} as IDrawingParam;
|
||||
const children = validDrawings.map((drawing) => ({
|
||||
...drawing,
|
||||
groupId,
|
||||
})) as IDrawingParam[];
|
||||
|
||||
const result = this._applyGroupDrawingOperation([{
|
||||
parent: groupParam,
|
||||
children,
|
||||
}], DrawingApplyType.GROUP);
|
||||
|
||||
return result ? groupId : null;
|
||||
}
|
||||
|
||||
override ungroupDrawings(groupIds: string[]): boolean {
|
||||
const unitId = this._fWorkbook.getId();
|
||||
const subUnitId = this.getSheetId();
|
||||
const sheetDrawingService = this._injector.get(ISheetDrawingService);
|
||||
const groupParams: IDrawingGroupUpdateParam[] = [];
|
||||
|
||||
for (const groupId of groupIds) {
|
||||
const groupDrawing = sheetDrawingService.getDrawingByParam({ unitId, subUnitId, drawingId: groupId });
|
||||
if (!groupDrawing || groupDrawing.drawingType !== DrawingTypeEnum.DRAWING_GROUP) continue;
|
||||
|
||||
const groupTransform = groupDrawing.transform || { width: 0, height: 0 };
|
||||
const children = sheetDrawingService.getDrawingsByGroup({ unitId, subUnitId, drawingId: groupId })
|
||||
.map((drawing) => {
|
||||
const newTransform = transformObjectOutOfGroup(
|
||||
drawing.transform || {},
|
||||
groupTransform,
|
||||
groupTransform.width || 0,
|
||||
groupTransform.height || 0,
|
||||
groupDrawing.groupBaseBound
|
||||
);
|
||||
|
||||
return {
|
||||
...drawing,
|
||||
transform: {
|
||||
...drawing.transform,
|
||||
...newTransform,
|
||||
},
|
||||
groupId: undefined,
|
||||
};
|
||||
});
|
||||
|
||||
if (children.length > 0) {
|
||||
groupParams.push({
|
||||
parent: groupDrawing,
|
||||
children,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return this._applyGroupDrawingOperation(groupParams, DrawingApplyType.UNGROUP);
|
||||
}
|
||||
|
||||
override getDrawingGroupChildren(groupId: string, recursive = false): ISheetDrawing[] {
|
||||
const unitId = this._fWorkbook.getId();
|
||||
const subUnitId = this.getSheetId();
|
||||
const sheetDrawingService = this._injector.get(ISheetDrawingService);
|
||||
|
||||
if (!recursive) {
|
||||
return sheetDrawingService.getDrawingsByGroup({ unitId, subUnitId, drawingId: groupId }) as ISheetDrawing[];
|
||||
}
|
||||
|
||||
const nested = sheetDrawingService.getDrawingsByGroupNested({ unitId, subUnitId, drawingId: groupId });
|
||||
if (!nested) return [];
|
||||
|
||||
return [
|
||||
...(nested.flatChildren || []),
|
||||
...nested.groups.filter((group) => group.drawingId !== groupId),
|
||||
] as ISheetDrawing[];
|
||||
}
|
||||
|
||||
override getDrawingParentGroup(drawingId: string): ISheetDrawing | null {
|
||||
const unitId = this._fWorkbook.getId();
|
||||
const subUnitId = this.getSheetId();
|
||||
const sheetDrawingService = this._injector.get(ISheetDrawingService);
|
||||
const drawing = sheetDrawingService.getDrawingByParam({ unitId, subUnitId, drawingId });
|
||||
|
||||
if (!drawing?.groupId) return null;
|
||||
|
||||
const groupDrawing = sheetDrawingService.getDrawingByParam({ unitId, subUnitId, drawingId: drawing.groupId });
|
||||
if (!groupDrawing || groupDrawing.drawingType !== DrawingTypeEnum.DRAWING_GROUP) return null;
|
||||
|
||||
return groupDrawing;
|
||||
}
|
||||
|
||||
override isDrawingGrouped(drawingId: string): boolean {
|
||||
return this.getDrawingParentGroup(drawingId) !== null;
|
||||
}
|
||||
|
||||
private _applyGroupDrawingOperation(groupParams: IDrawingGroupUpdateParam[], type: DrawingApplyType.GROUP | DrawingApplyType.UNGROUP): boolean {
|
||||
if (groupParams.length === 0) return false;
|
||||
|
||||
const sheetDrawingService = this._injector.get(ISheetDrawingService);
|
||||
const commandService = this._commandService;
|
||||
const undoRedoService = this._injector.get(IUndoRedoService);
|
||||
const jsonOp = (type === DrawingApplyType.GROUP
|
||||
? sheetDrawingService.getGroupDrawingOp(groupParams)
|
||||
: sheetDrawingService.getUngroupDrawingOp(groupParams)) as IDrawingJsonUndo1;
|
||||
|
||||
const { unitId, subUnitId, undo, redo, objects } = jsonOp;
|
||||
const result = commandService.syncExecuteCommand(SetDrawingApplyMutation.id, { op: redo, unitId, subUnitId, objects, type });
|
||||
|
||||
if (result) {
|
||||
const inverseType = type === DrawingApplyType.GROUP ? DrawingApplyType.UNGROUP : DrawingApplyType.GROUP;
|
||||
undoRedoService.pushUndoRedo({
|
||||
unitID: unitId,
|
||||
undoMutations: [
|
||||
{ id: SetDrawingApplyMutation.id, params: { op: undo, unitId, subUnitId, objects: this._invertGroupOperationObjects(objects as IDrawingGroupUpdateParam[], type), type: inverseType } },
|
||||
],
|
||||
redoMutations: [
|
||||
{ id: SetDrawingApplyMutation.id, params: { op: redo, unitId, subUnitId, objects, type } },
|
||||
],
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private _invertGroupOperationObjects(groupParams: IDrawingGroupUpdateParam[], type: DrawingApplyType.GROUP | DrawingApplyType.UNGROUP): IDrawingGroupUpdateParam[] {
|
||||
return type === DrawingApplyType.GROUP
|
||||
? groupParams.map((groupParam) => {
|
||||
const { parent, children } = groupParam;
|
||||
const groupTransform = parent.transform || { width: 0, height: 0 };
|
||||
return {
|
||||
parent: {
|
||||
...parent,
|
||||
transform: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
},
|
||||
},
|
||||
children: children.map((child) => ({
|
||||
...child,
|
||||
transform: transformObjectOutOfGroup(
|
||||
child.transform || {},
|
||||
groupTransform,
|
||||
groupTransform.width || 0,
|
||||
groupTransform.height || 0,
|
||||
parent.groupBaseBound
|
||||
),
|
||||
groupId: undefined,
|
||||
})),
|
||||
};
|
||||
})
|
||||
: groupParams.map((groupParam) => {
|
||||
const { parent, children } = groupParam;
|
||||
const groupTransform = getGroupState(0, 0, children.map((child) => child.transform || {}));
|
||||
return {
|
||||
parent: {
|
||||
...parent,
|
||||
transform: groupTransform,
|
||||
},
|
||||
children: children.map((child) => ({
|
||||
...child,
|
||||
groupId: parent.drawingId,
|
||||
})),
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
FWorksheet.extend(FWorksheetDrawingMixin);
|
||||
|
||||
Reference in New Issue
Block a user