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