tldraw/state/sessions/arrow-session.ts

123 lines
3.2 KiB
TypeScript
Raw Normal View History

2021-06-21 21:35:28 +00:00
import { ArrowShape, Data } from 'types'
import vec from 'utils/vec'
2021-05-31 19:13:43 +00:00
import BaseSession from './base-session'
import commands from 'state/commands'
2021-06-29 14:54:46 +00:00
import { deepClone, getBoundsFromPoints, setToArray } from 'utils'
2021-06-21 21:35:28 +00:00
import { getShapeUtils } from 'state/shape-utils'
2021-06-29 12:00:59 +00:00
import tld from 'utils/tld'
2021-05-31 19:13:43 +00:00
2021-06-04 16:14:01 +00:00
export default class ArrowSession extends BaseSession {
2021-05-31 19:13:43 +00:00
points: number[][]
origin: number[]
snapshot: ArrowSnapshot
isLocked: boolean
lockedDirection: 'horizontal' | 'vertical'
constructor(data: Data, id: string, point: number[], isLocked: boolean) {
super(data)
2021-06-21 21:35:28 +00:00
isLocked
2021-05-31 19:13:43 +00:00
this.origin = point
this.points = [[0, 0]]
this.snapshot = getArrowSnapshot(data, id)
}
2021-06-21 21:35:28 +00:00
update(data: Data, point: number[], isLocked = false): void {
2021-05-31 19:13:43 +00:00
const { id } = this.snapshot
const delta = vec.vec(this.origin, point)
if (isLocked) {
if (!this.isLocked && this.points.length > 1) {
this.isLocked = true
if (Math.abs(delta[0]) < Math.abs(delta[1])) {
this.lockedDirection = 'vertical'
} else {
this.lockedDirection = 'horizontal'
}
}
} else {
if (this.isLocked) {
this.isLocked = false
}
}
if (this.isLocked) {
if (this.lockedDirection === 'vertical') {
point[0] = this.origin[0]
} else {
point[1] = this.origin[1]
}
}
2021-06-29 12:00:59 +00:00
const shape = tld.getPage(data).shapes[id] as ArrowShape
2021-05-31 19:13:43 +00:00
2021-06-04 16:08:43 +00:00
getShapeUtils(shape).onHandleChange(shape, {
2021-05-31 19:13:43 +00:00
end: {
...shape.handles.end,
point: vec.sub(point, shape.point),
},
})
2021-06-04 16:08:43 +00:00
2021-06-29 12:00:59 +00:00
tld.updateParents(data, [shape.id])
2021-05-31 19:13:43 +00:00
}
2021-06-21 21:35:28 +00:00
cancel(data: Data): void {
2021-05-31 19:13:43 +00:00
const { id, initialShape } = this.snapshot
2021-06-29 12:00:59 +00:00
const shape = tld.getPage(data).shapes[id] as ArrowShape
2021-05-31 19:13:43 +00:00
getShapeUtils(shape)
2021-06-04 16:08:43 +00:00
.onHandleChange(shape, { end: initialShape.handles.end })
2021-06-02 15:05:44 +00:00
.setProperty(shape, 'point', initialShape.point)
2021-06-04 16:08:43 +00:00
2021-06-29 12:00:59 +00:00
tld.updateParents(data, [shape.id])
2021-05-31 19:13:43 +00:00
}
2021-06-21 21:35:28 +00:00
complete(data: Data): void {
2021-06-01 08:56:41 +00:00
const { id } = this.snapshot
2021-05-31 20:44:21 +00:00
2021-06-29 12:00:59 +00:00
const shape = tld.getPage(data).shapes[id] as ArrowShape
2021-05-31 20:44:21 +00:00
const { start, end, bend } = shape.handles
// Normalize point and handles
const bounds = getBoundsFromPoints([start.point, end.point])
const corner = [bounds.minX, bounds.minY]
const newPoint = vec.add(shape.point, corner)
const nextHandles = {
start: { ...start, point: vec.sub(start.point, corner) },
end: { ...end, point: vec.sub(end.point, corner) },
bend: { ...bend, point: vec.sub(bend.point, corner) },
}
getShapeUtils(shape)
.setProperty(shape, 'handles', nextHandles)
2021-06-02 15:05:44 +00:00
.setProperty(shape, 'point', newPoint)
2021-06-04 16:08:43 +00:00
.onHandleChange(shape, nextHandles)
2021-05-31 20:44:21 +00:00
2021-05-31 19:13:43 +00:00
commands.arrow(
data,
this.snapshot,
getArrowSnapshot(data, this.snapshot.id)
)
}
}
2021-06-21 21:35:28 +00:00
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
2021-05-31 19:13:43 +00:00
export function getArrowSnapshot(data: Data, id: string) {
2021-06-29 14:54:46 +00:00
const initialShape = deepClone(tld.getPage(data).shapes[id]) as ArrowShape
2021-05-31 19:13:43 +00:00
return {
id,
initialShape,
2021-06-29 12:00:59 +00:00
selectedIds: setToArray(tld.getSelectedIds(data)),
2021-05-31 19:13:43 +00:00
currentPageId: data.currentPageId,
}
}
export type ArrowSnapshot = ReturnType<typeof getArrowSnapshot>