tldraw/state/sessions/translate-session.ts

121 lines
3.1 KiB
TypeScript
Raw Normal View History

2021-05-29 12:40:41 +00:00
import { Data } from 'types'
import * as vec from 'utils/vec'
import BaseSession from './base-session'
import commands from 'state/commands'
import { current } from 'immer'
import { v4 as uuid } from 'uuid'
import { getChildIndexAbove, getPage, getSelectedShapes } from 'utils/utils'
import { getShapeUtils } from 'lib/shape-utils'
2021-05-13 06:44:52 +00:00
export default class TranslateSession extends BaseSession {
delta = [0, 0]
origin: number[]
snapshot: TranslateSnapshot
2021-05-19 21:24:41 +00:00
isCloning = false
2021-05-13 06:44:52 +00:00
constructor(data: Data, point: number[]) {
2021-05-13 06:44:52 +00:00
super(data)
this.origin = point
this.snapshot = getTranslateSnapshot(data)
}
2021-05-20 08:19:13 +00:00
update(data: Data, point: number[], isAligned: boolean, isCloning: boolean) {
2021-05-19 21:24:41 +00:00
const { currentPageId, clones, initialShapes } = this.snapshot
const { shapes } = getPage(data, currentPageId)
2021-05-20 09:25:14 +00:00
2021-05-13 06:44:52 +00:00
const delta = vec.vec(this.origin, point)
2021-05-20 08:19:13 +00:00
if (isAligned) {
if (Math.abs(delta[0]) < Math.abs(delta[1])) {
delta[0] = 0
} else {
delta[1] = 0
}
}
2021-05-20 09:25:14 +00:00
if (isCloning) {
if (!this.isCloning) {
this.isCloning = true
data.selectedIds.clear()
for (const { id, point } of initialShapes) {
const shape = shapes[id]
2021-06-02 15:05:44 +00:00
getShapeUtils(shape).setProperty(shape, 'point', point)
2021-05-20 09:25:14 +00:00
}
for (const clone of clones) {
shapes[clone.id] = { ...clone }
data.selectedIds.add(clone.id)
}
2021-05-19 21:24:41 +00:00
}
2021-05-20 09:25:14 +00:00
for (const { id, point } of clones) {
const shape = shapes[id]
2021-06-02 15:05:44 +00:00
getShapeUtils(shape).setProperty(shape, 'point', vec.add(point, delta))
2021-05-19 21:24:41 +00:00
}
2021-05-20 09:25:14 +00:00
} else {
if (this.isCloning) {
this.isCloning = false
data.selectedIds.clear()
for (const { id } of initialShapes) {
data.selectedIds.add(id)
}
2021-05-19 21:24:41 +00:00
2021-05-20 09:25:14 +00:00
for (const clone of clones) {
delete shapes[clone.id]
}
}
for (const { id, point } of initialShapes) {
const shape = shapes[id]
2021-06-02 15:05:44 +00:00
getShapeUtils(shape).setProperty(shape, 'point', vec.add(point, delta))
2021-05-20 09:25:14 +00:00
}
2021-05-13 06:44:52 +00:00
}
}
cancel(data: Data) {
2021-05-19 21:24:41 +00:00
const { initialShapes, clones, currentPageId } = this.snapshot
const { shapes } = getPage(data, currentPageId)
2021-05-19 21:24:41 +00:00
2021-05-20 09:25:14 +00:00
for (const { id, point } of initialShapes) {
const shape = shapes[id]
2021-06-02 15:05:44 +00:00
getShapeUtils(shape).setProperty(shape, 'point', point)
2021-05-20 09:25:14 +00:00
}
for (const { id } of clones) {
delete shapes[id]
2021-05-13 06:44:52 +00:00
}
}
complete(data: Data) {
2021-05-29 12:54:33 +00:00
if (!this.snapshot.hasUnlockedShapes) return
2021-05-29 12:40:41 +00:00
2021-05-19 21:24:41 +00:00
commands.translate(
data,
this.snapshot,
getTranslateSnapshot(data),
this.isCloning
)
2021-05-13 06:44:52 +00:00
}
}
export function getTranslateSnapshot(data: Data) {
2021-05-23 13:46:04 +00:00
const cData = current(data)
2021-05-29 12:40:41 +00:00
const shapes = getSelectedShapes(cData).filter((shape) => !shape.isLocked)
2021-05-29 12:54:33 +00:00
const hasUnlockedShapes = shapes.length > 0
2021-05-19 21:24:41 +00:00
2021-05-13 06:44:52 +00:00
return {
2021-05-29 12:54:33 +00:00
hasUnlockedShapes,
currentPageId: data.currentPageId,
2021-05-20 09:25:14 +00:00
initialShapes: shapes.map(({ id, point }) => ({ id, point })),
2021-05-23 13:46:04 +00:00
clones: shapes.map((shape) => ({
...shape,
id: uuid(),
childIndex: getChildIndexAbove(cData, shape.id),
})),
2021-05-13 06:44:52 +00:00
}
}
export type TranslateSnapshot = ReturnType<typeof getTranslateSnapshot>