Skip to content

Commit

Permalink
feat: add Transaction class
Browse files Browse the repository at this point in the history
  • Loading branch information
F-star committed Jun 11, 2024
1 parent 89a70fa commit b9eb891
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 142 deletions.
14 changes: 9 additions & 5 deletions packages/core/src/graphs/frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,15 @@ export class SuikaFrame extends SuikaGraphics<FrameAttrs> {
for (const child of this.getChildren()) {
const id = child.attrs.id;

if (!originAttrsMap.has(id)) {
originAttrsMap.set(id, {
transform: [...child.attrs.transform],
});
}
originAttrsMap.set(
id,
Object.assign(
{
transform: [...child.attrs.transform],
},
originAttrsMap.get(id) ?? {},
),
);

const tf = new Matrix(...child.attrs.transform).translate(
-boundingRect.x,
Expand Down
174 changes: 79 additions & 95 deletions packages/core/src/service/mutate_graphs_and_record.ts
Original file line number Diff line number Diff line change
@@ -1,145 +1,129 @@
import { cloneDeep } from '@suika/common';
import { type IMatrixArr, invertMatrix, multiplyMatrix } from '@suika/geo';

import { SetGraphsAttrsCmd } from '../commands/set_elements_attrs';
import { type Editor } from '../editor';
import { type SuikaGraphics, type SuikaRect } from '../graphs';
import { type SuikaRegularPolygon } from '../graphs/regular_polygon';
import { type SuikaStar } from '../graphs/star';
import { Transaction } from '../transaction';
import { GraphicsType } from '../type';

/**
* mutate elements and record to history
*/
export const MutateGraphsAndRecord = {
setX(editor: Editor, elements: SuikaGraphics[], newX: number) {
if (elements.length === 0) {
setX(editor: Editor, graphicsArr: SuikaGraphics[], val: number) {
if (graphicsArr.length === 0) {
return;
}

const prevAttrs: { transform: IMatrixArr }[] = new Array(elements.length);
for (let i = 0, len = elements.length; i < len; i++) {
const el = elements[i];
prevAttrs[i] = { transform: cloneDeep(el.attrs.transform) };
const parentInvertTf = invertMatrix(el.getParentWorldTransform());
const transaction = new Transaction(editor);

const tf = el.getWorldTransform();
tf[4] = newX;
el.updateAttrs({
transform: multiplyMatrix(parentInvertTf, tf),
for (const graphics of graphicsArr) {
transaction.recordOld(graphics.attrs.id, {
transform: cloneDeep(graphics.attrs.transform),
});

const tf = graphics.getWorldTransform();
tf[4] = val;

graphics.setWorldTransform(tf);
transaction.update(graphics.attrs.id, {
transform: cloneDeep(graphics.attrs.transform),
});
}
editor.commandManager.pushCommand(
new SetGraphsAttrsCmd(
'Update X of Elements',
elements,
elements.map((el) => ({ transform: el.attrs.transform })),
prevAttrs,
),
);

transaction.updateParentSize(graphicsArr);
transaction.commit('Update X of Elements');
},
setY(editor: Editor, elements: SuikaGraphics[], newY: number) {
if (elements.length === 0) {
setY(editor: Editor, graphicsArr: SuikaGraphics[], val: number) {
if (graphicsArr.length === 0) {
return;
}

const prevAttrs: { transform: IMatrixArr }[] = new Array(elements.length);
for (let i = 0, len = elements.length; i < len; i++) {
const el = elements[i];
prevAttrs[i] = { transform: cloneDeep(el.attrs.transform) };
const parentInvertTf = invertMatrix(el.getParentWorldTransform());
const transaction = new Transaction(editor);

const tf = el.getWorldTransform();
tf[5] = newY;
el.updateAttrs({
transform: multiplyMatrix(parentInvertTf, tf),
for (const graphics of graphicsArr) {
transaction.recordOld(graphics.attrs.id, {
transform: cloneDeep(graphics.attrs.transform),
});

const tf = graphics.getWorldTransform();
tf[5] = val;

graphics.setWorldTransform(tf);
transaction.update(graphics.attrs.id, {
transform: cloneDeep(graphics.attrs.transform),
});
}
editor.commandManager.pushCommand(
new SetGraphsAttrsCmd(
'Update Y of Elements',
elements,
elements.map((el) => ({ transform: el.attrs.transform })),
prevAttrs,
),
);

transaction.updateParentSize(graphicsArr);
transaction.commit('Update Y of Elements');
},
setWidth(editor: Editor, graphs: SuikaGraphics[], width: number) {
if (graphs.length === 0) {
setWidth(editor: Editor, graphicsArr: SuikaGraphics[], val: number) {
if (graphicsArr.length === 0) {
return;
}

const prevAttrs = graphs.map((el) => ({
width: el.attrs.width,
}));
graphs.forEach((graph) => {
graph.updateAttrs({ width });
});
editor.commandManager.pushCommand(
new SetGraphsAttrsCmd(
'Update Width of Elements',
graphs,
graphs.map((item) => ({
width: item.attrs.width,
})),
prevAttrs,
),
);
const transaction = new Transaction(editor);
for (const graphics of graphicsArr) {
transaction.recordOld(graphics.attrs.id, { width: graphics.attrs.width });
graphics.updateAttrs({ width: val });
transaction.update(graphics.attrs.id, { width: graphics.attrs.width });
}

transaction.updateParentSize(graphicsArr);
// FIXME: update children
transaction.commit('Update Width of Elements');
},
setHeight(editor: Editor, graphs: SuikaGraphics[], height: number) {
if (graphs.length === 0) {
setHeight(editor: Editor, graphicsArr: SuikaGraphics[], val: number) {
if (graphicsArr.length === 0) {
return;
}

const prevAttrs = graphs.map((el) => ({
height: el.attrs.height,
}));
graphs.forEach((graph) => {
graph.updateAttrs({
height,
const transaction = new Transaction(editor);
for (const graphics of graphicsArr) {
transaction.recordOld(graphics.attrs.id, {
height: graphics.attrs.height,
});
});
editor.commandManager.pushCommand(
new SetGraphsAttrsCmd(
'update Height of Elements',
graphs,
graphs.map((el) => ({
height: el.attrs.height,
})),
prevAttrs,
),
);
graphics.updateAttrs({ height: val });
transaction.update(graphics.attrs.id, { height: graphics.attrs.height });
}

transaction.updateParentSize(graphicsArr);
// FIXME: update children
transaction.commit('Update Height of Elements');
},
setRotation(editor: Editor, elements: SuikaGraphics[], rotation: number) {
if (elements.length === 0) {
setRotation(editor: Editor, graphicsArr: SuikaGraphics[], rotation: number) {
if (graphicsArr.length === 0) {
return;
}

const prevAttrs = elements.map((el) => ({
rotation: el.getRotate(),
}));
elements.forEach((el) => {
el.setRotate(rotation);
});
editor.commandManager.pushCommand(
new SetGraphsAttrsCmd(
'update Rotation',
elements,
{ rotation },
prevAttrs,
),
);
const transaction = new Transaction(editor);

for (const graphics of graphicsArr) {
transaction.recordOld(graphics.attrs.id, {
transform: cloneDeep(graphics.attrs.transform),
});
graphics.setRotate(rotation);
transaction.update(graphics.attrs.id, {
transform: cloneDeep(graphics.attrs.transform),
});
}

transaction.updateParentSize(graphicsArr);
transaction.commit('Update Rotation');
},
setCornerRadius(
editor: Editor,
elements: SuikaGraphics[],
graphicsArr: SuikaGraphics[],
cornerRadius: number,
) {
if (elements.length === 0) {
if (graphicsArr.length === 0) {
return;
}

const rectGraphics = elements.filter(
const rectGraphics = graphicsArr.filter(
(el) => el.type === GraphicsType.Rect,
) as SuikaRect[];

Expand Down
47 changes: 47 additions & 0 deletions packages/core/src/transaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { UpdateGraphicsAttrsCmd } from './commands';
import { type Editor } from './editor';
import { type GraphicsAttrs, type SuikaGraphics } from './graphs';
import { getParentIdSet } from './service/group_and_record';
import { updateParentSize } from './tools/tool_select/utils';

export class Transaction {
private originAttrsMap = new Map<string, Partial<GraphicsAttrs>>();
private updatedAttrsMap = new Map<string, Partial<GraphicsAttrs>>();
private removedIds = new Set<string>();

constructor(private editor: Editor) {}

recordOld(id: string, attrs: Partial<GraphicsAttrs>) {
this.originAttrsMap.set(id, attrs);
}

update(id: string, attrs: Partial<GraphicsAttrs>) {
this.updatedAttrsMap.set(id, attrs);
}

remove(id: string) {
this.removedIds.add(id);
}

updateParentSize(elements: SuikaGraphics[]) {
updateParentSize(
this.editor,
getParentIdSet(elements),
this.originAttrsMap,
this.updatedAttrsMap,
);
}

commit(desc: string) {
console.log(this);
this.editor.commandManager.pushCommand(
new UpdateGraphicsAttrsCmd(
desc,
this.editor,
this.originAttrsMap,
this.updatedAttrsMap,
this.removedIds,
),
);
}
}
1 change: 0 additions & 1 deletion packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from './canvas';
export * from './geo';
export * from './raf_throttle';
export * from './transform';
41 changes: 0 additions & 41 deletions packages/core/src/utils/transform.ts

This file was deleted.

0 comments on commit b9eb891

Please sign in to comment.