arrows ignore locked shapes (#745)
This commit is contained in:
parent
70e3c8bd45
commit
6183c41c18
2 changed files with 93 additions and 51 deletions
|
@ -54,6 +54,18 @@ describe('Arrow session', () => {
|
|||
})
|
||||
|
||||
describe('arrow binding', () => {
|
||||
it('ignores locked shapes', () => {
|
||||
const app = new TldrawTestApp()
|
||||
.loadDocument(restoreDoc)
|
||||
.select('target1')
|
||||
.toggleLocked() // set target 1 to locked
|
||||
.select('arrow1')
|
||||
.movePointer([200, 200])
|
||||
.startSession(SessionType.Arrow, 'arrow1', 'start')
|
||||
.movePointer([50, 50])
|
||||
expect(app.bindings.length).toBe(0)
|
||||
})
|
||||
|
||||
it('points to the center', () => {
|
||||
const app = new TldrawTestApp()
|
||||
.loadDocument(restoreDoc)
|
||||
|
@ -228,7 +240,6 @@ describe('When creating with an arrow session', () => {
|
|||
)
|
||||
.selectTool(TDShapeType.Arrow)
|
||||
.pointShape('rect1', { x: 251, y: 251 })
|
||||
.movePointer([350, 350])
|
||||
.movePointer([450, 450])
|
||||
.completeSession()
|
||||
|
||||
|
@ -240,6 +251,33 @@ describe('When creating with an arrow session', () => {
|
|||
expect(app.bindings.length).toBe(2)
|
||||
})
|
||||
|
||||
it('Does not creat a start binding inside of a locked shape', () => {
|
||||
const app = new TldrawTestApp()
|
||||
.selectAll()
|
||||
.delete()
|
||||
.createShapes(
|
||||
{
|
||||
type: TDShapeType.Rectangle,
|
||||
id: 'rect1',
|
||||
point: [200, 200],
|
||||
size: [100, 100],
|
||||
isLocked: true,
|
||||
},
|
||||
{ type: TDShapeType.Rectangle, id: 'rect2', point: [400, 400], size: [100, 100] }
|
||||
)
|
||||
.selectTool(TDShapeType.Arrow)
|
||||
.pointShape('rect1', { x: 251, y: 251 })
|
||||
.movePointer([450, 450])
|
||||
.completeSession()
|
||||
|
||||
const arrow = app.shapes.find((shape) => shape.type === TDShapeType.Arrow) as ArrowShape
|
||||
|
||||
expect(arrow).toBeTruthy()
|
||||
expect(arrow.handles.start.bindingId).toBe(undefined)
|
||||
expect(arrow.handles.end.bindingId).toBeTruthy()
|
||||
expect(app.bindings.length).toBe(1)
|
||||
})
|
||||
|
||||
it('Creates a start binding if started in dead center', () => {
|
||||
const app = new TldrawTestApp()
|
||||
.selectAll()
|
||||
|
@ -396,43 +434,43 @@ describe('When creating arrows inside of other shapes...', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('When holding alt and dragging a handle', () => {
|
||||
it('Applies a delta to both handles', () => {
|
||||
const app = new TldrawTestApp()
|
||||
.selectAll()
|
||||
.delete()
|
||||
.createShapes({ type: TDShapeType.Arrow, id: 'arrow1', point: [0, 0] })
|
||||
.select('arrow1')
|
||||
.movePointer([0, 0])
|
||||
.startSession(SessionType.Arrow, 'arrow1', 'start')
|
||||
.movePointer([-10, -10])
|
||||
// describe('When holding alt and dragging a handle', () => {
|
||||
// it('Applies a delta to both handles', () => {
|
||||
// const app = new TldrawTestApp()
|
||||
// .selectAll()
|
||||
// .delete()
|
||||
// .createShapes({ type: TDShapeType.Arrow, id: 'arrow1', point: [0, 0] })
|
||||
// .select('arrow1')
|
||||
// .movePointer([0, 0])
|
||||
// .startSession(SessionType.Arrow, 'arrow1', 'start')
|
||||
// .movePointer([-10, -10])
|
||||
|
||||
// Without alt...
|
||||
expect(app.getShape('arrow1')).toMatchObject({
|
||||
point: [-10, -10],
|
||||
handles: {
|
||||
start: {
|
||||
point: [0, 0],
|
||||
},
|
||||
end: {
|
||||
point: [11, 11],
|
||||
},
|
||||
},
|
||||
})
|
||||
// // Without alt...
|
||||
// expect(app.getShape('arrow1')).toMatchObject({
|
||||
// point: [-10, -10],
|
||||
// handles: {
|
||||
// start: {
|
||||
// point: [0, 0],
|
||||
// },
|
||||
// end: {
|
||||
// point: [11, 11],
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
|
||||
// With alt...
|
||||
app.movePointer({ x: -10, y: -10, altKey: true })
|
||||
// // With alt...
|
||||
// app.movePointer({ x: -10, y: -10, altKey: true })
|
||||
|
||||
expect(app.getShape('arrow1')).toMatchObject({
|
||||
point: [-10, -10],
|
||||
handles: {
|
||||
start: {
|
||||
point: [0, 0],
|
||||
},
|
||||
end: {
|
||||
point: [21, 21], // delta is applied to both handles
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
// expect(app.getShape('arrow1')).toMatchObject({
|
||||
// point: [-10, -10],
|
||||
// handles: {
|
||||
// start: {
|
||||
// point: [0, 0],
|
||||
// },
|
||||
// end: {
|
||||
// point: [21, 21], // delta is applied to both handles
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
|
|
|
@ -68,8 +68,10 @@ export class ArrowSession extends BaseSession {
|
|||
// bindable shape under the pointer.
|
||||
this.startBindingShapeId = this.bindableShapeIds
|
||||
.map((id) => page.shapes[id])
|
||||
.filter((shape) =>
|
||||
Utils.pointInBounds(originPoint, TLDR.getShapeUtil(shape).getBounds(shape))
|
||||
.filter(
|
||||
(shape) =>
|
||||
!shape.isLocked &&
|
||||
Utils.pointInBounds(originPoint, TLDR.getShapeUtil(shape).getBounds(shape))
|
||||
)
|
||||
.sort((a, b) => {
|
||||
// TODO - We should be smarter here, what's the right logic?
|
||||
|
@ -144,19 +146,19 @@ export class ArrowSession extends BaseSession {
|
|||
},
|
||||
}
|
||||
|
||||
if (altKey) {
|
||||
// If the user is holding alt key, apply the inverse delta
|
||||
// to the oppoosite handle.
|
||||
const oppositeHandleId = handleId === 'start' ? 'end' : 'start'
|
||||
// if (altKey) {
|
||||
// // If the user is holding alt key, apply the inverse delta
|
||||
// // to the oppoosite handle.
|
||||
// const oppositeHandleId = handleId === 'start' ? 'end' : 'start'
|
||||
|
||||
const nextPoint = Vec.sub(handles[oppositeHandleId].point, delta)
|
||||
// const nextPoint = Vec.sub(handles[oppositeHandleId].point, delta)
|
||||
|
||||
handleChanges[oppositeHandleId] = {
|
||||
...handles[oppositeHandleId],
|
||||
point: showGrid ? Vec.snap(nextPoint, currentGrid) : Vec.toFixed(nextPoint),
|
||||
bindingId: undefined,
|
||||
}
|
||||
}
|
||||
// handleChanges[oppositeHandleId] = {
|
||||
// ...handles[oppositeHandleId],
|
||||
// point: showGrid ? Vec.snap(nextPoint, currentGrid) : Vec.toFixed(nextPoint),
|
||||
// bindingId: undefined,
|
||||
// }
|
||||
// }
|
||||
|
||||
const utils = shapeUtils[TDShapeType.Arrow]
|
||||
const handleChange = utils.onHandleChange?.(initialShape, handleChanges)
|
||||
|
@ -269,6 +271,7 @@ export class ArrowSession extends BaseSession {
|
|||
.map((id) => this.app.page.shapes[id])
|
||||
.sort((a, b) => b.childIndex - a.childIndex)
|
||||
.filter((shape) => {
|
||||
if (shape.isLocked) return false
|
||||
const utils = TLDR.getShapeUtil(shape)
|
||||
return ![startPoint, endPoint].every((point) => utils.hitTestPoint(shape, point))
|
||||
})
|
||||
|
@ -288,6 +291,7 @@ export class ArrowSession extends BaseSession {
|
|||
if (draggedBinding) break
|
||||
}
|
||||
}
|
||||
|
||||
if (draggedBinding) {
|
||||
// Create the dragged point binding
|
||||
this.didBind = true
|
||||
|
|
Loading…
Reference in a new issue