[fix] restore bg option, fix calculations (#1765)
This PR fixes a bug introduced with #1751 where pointing the bounds of rotated selections would not correctly hit the bounds background. ### Change Type - [x] `patch` — Bug fix ### Test Plan 1. Create a rotated selection. 2. Point into the bounds background - [x] Unit Tests
This commit is contained in:
parent
56cf77a8cd
commit
28b92c5e76
7 changed files with 114 additions and 22 deletions
|
@ -1736,6 +1736,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|||
getOutlineSegments(shape: Shape): Vec2d[][];
|
||||
hideResizeHandles: TLShapeUtilFlag<Shape>;
|
||||
hideRotateHandle: TLShapeUtilFlag<Shape>;
|
||||
hideSelectionBoundsBg: TLShapeUtilFlag<Shape>;
|
||||
hideSelectionBoundsFg: TLShapeUtilFlag<Shape>;
|
||||
abstract indicator(shape: Shape): any;
|
||||
isAspectRatioLocked: TLShapeUtilFlag<Shape>;
|
||||
|
|
|
@ -149,6 +149,13 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|||
*/
|
||||
hideRotateHandle: TLShapeUtilFlag<Shape> = () => false
|
||||
|
||||
/**
|
||||
* Whether the shape should hide its selection bounds background when selected.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
hideSelectionBoundsBg: TLShapeUtilFlag<Shape> = () => false
|
||||
|
||||
/**
|
||||
* Whether the shape should hide its selection bounds foreground when selected.
|
||||
*
|
||||
|
|
|
@ -99,13 +99,10 @@ export const TldrawSelectionForeground: TLSelectionForegroundComponent = track(
|
|||
onlyShape &&
|
||||
editor.isShapeOfType<TLTextShape>(onlyShape, 'text'))
|
||||
|
||||
if (
|
||||
onlyShape &&
|
||||
editor.isShapeOfType<TLEmbedShape>(onlyShape, 'embed') &&
|
||||
shouldDisplayBox &&
|
||||
IS_FIREFOX
|
||||
) {
|
||||
shouldDisplayBox = false
|
||||
if (onlyShape && shouldDisplayBox) {
|
||||
if (IS_FIREFOX && editor.isShapeOfType<TLEmbedShape>(onlyShape, 'embed')) {
|
||||
shouldDisplayBox = false
|
||||
}
|
||||
}
|
||||
|
||||
const showCropHandles =
|
||||
|
|
|
@ -64,6 +64,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
|
|||
override canSnap = () => true
|
||||
override hideResizeHandles: TLShapeUtilFlag<TLArrowShape> = () => true
|
||||
override hideRotateHandle: TLShapeUtilFlag<TLArrowShape> = () => true
|
||||
override hideSelectionBoundsBg: TLShapeUtilFlag<TLArrowShape> = () => true
|
||||
override hideSelectionBoundsFg: TLShapeUtilFlag<TLArrowShape> = () => true
|
||||
|
||||
override getDefaultProps(): TLArrowShape['props'] {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
Editor,
|
||||
HIT_TEST_MARGIN,
|
||||
StateNode,
|
||||
TLClickEventInfo,
|
||||
|
@ -8,7 +9,9 @@ import {
|
|||
TLShape,
|
||||
TLTextShape,
|
||||
Vec2d,
|
||||
VecLike,
|
||||
createShapeId,
|
||||
pointInPolygon,
|
||||
} from '@tldraw/editor'
|
||||
import { getHitShapeOnCanvasPointerDown } from '../../selection-logic/getHitShapeOnCanvasPointerDown'
|
||||
import { getShouldEnterCropMode } from '../../selection-logic/getShouldEnterCropModeOnPointerDown'
|
||||
|
@ -60,24 +63,22 @@ export class Idle extends StateNode {
|
|||
}
|
||||
|
||||
const {
|
||||
onlySelectedShape,
|
||||
selectedShapeIds,
|
||||
inputs: { currentPagePoint },
|
||||
} = this.editor
|
||||
|
||||
if (selectedShapeIds.length > 0) {
|
||||
// If there's only one shape selected, and if that shape's
|
||||
// geometry is open, then don't test the selection background
|
||||
if (
|
||||
selectedShapeIds.length > 1 ||
|
||||
this.editor.getGeometry(selectedShapeIds[0]).isClosed
|
||||
) {
|
||||
if (this.editor.selectionBounds?.containsPoint(currentPagePoint)) {
|
||||
this.onPointerDown({
|
||||
...info,
|
||||
target: 'selection',
|
||||
})
|
||||
return
|
||||
}
|
||||
if (
|
||||
selectedShapeIds.length > 1 ||
|
||||
(onlySelectedShape &&
|
||||
!this.editor.getShapeUtil(onlySelectedShape).hideSelectionBoundsBg(onlySelectedShape))
|
||||
) {
|
||||
if (isPointInRotatedSelectionBounds(this.editor, currentPagePoint)) {
|
||||
this.onPointerDown({
|
||||
...info,
|
||||
target: 'selection',
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,3 +512,16 @@ export class Idle extends StateNode {
|
|||
export const MAJOR_NUDGE_FACTOR = 10
|
||||
export const MINOR_NUDGE_FACTOR = 1
|
||||
export const GRID_INCREMENT = 5
|
||||
|
||||
function isPointInRotatedSelectionBounds(editor: Editor, point: VecLike) {
|
||||
const { selectionBounds } = editor
|
||||
if (!selectionBounds) return false
|
||||
|
||||
const { selectionRotation } = editor
|
||||
if (!selectionRotation) return selectionBounds.containsPoint(point)
|
||||
|
||||
return pointInPolygon(
|
||||
point,
|
||||
selectionBounds.corners.map((c) => Vec2d.RotWith(c, selectionBounds.point, selectionRotation))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -69,7 +69,11 @@ export function selectOnCanvasPointerUp(editor: Editor) {
|
|||
} else {
|
||||
// Otherwise, we clear the selction because the user selected
|
||||
// nothing instead of their current selection.
|
||||
editor.selectNone()
|
||||
|
||||
if (selectedShapeIds.length > 0) {
|
||||
editor.mark('selecting none')
|
||||
editor.selectNone()
|
||||
}
|
||||
|
||||
// If the click was inside of the current focused group, then
|
||||
// we keep that focused group; otherwise we clear the focused
|
||||
|
|
|
@ -195,6 +195,74 @@ describe('when shape is hollow', () => {
|
|||
editor.pointerUp()
|
||||
expect(editor.selectedShapeIds).toEqual([])
|
||||
})
|
||||
|
||||
it('drags draw shape child', () => {
|
||||
editor
|
||||
.selectAll()
|
||||
.deleteShapes(editor.selectedShapeIds)
|
||||
.setCurrentTool('draw')
|
||||
.pointerMove(500, 500)
|
||||
.pointerDown()
|
||||
.pointerMove(501, 501)
|
||||
.pointerMove(550, 550)
|
||||
.pointerMove(599, 599)
|
||||
.pointerMove(600, 600)
|
||||
.pointerUp()
|
||||
.selectAll()
|
||||
.setCurrentTool('select')
|
||||
|
||||
expect(editor.selectedShapeIds.length).toBe(1)
|
||||
|
||||
// Not inside of the shape but inside of the selection bounds
|
||||
editor.pointerMove(510, 590)
|
||||
expect(editor.hoveredShapeId).toBe(null)
|
||||
|
||||
// Draw shapes have `hideSelectionBoundsBg` set to false
|
||||
editor.pointerDown()
|
||||
editor.expectToBeIn('select.pointing_selection')
|
||||
editor.pointerUp()
|
||||
|
||||
editor.selectAll()
|
||||
editor.rotateSelection(Math.PI)
|
||||
editor.setCurrentTool('select')
|
||||
editor.pointerMove(590, 510)
|
||||
|
||||
editor.pointerDown()
|
||||
editor.expectToBeIn('select.pointing_selection')
|
||||
editor.pointerUp()
|
||||
})
|
||||
|
||||
it('does not drag arrow shape', () => {
|
||||
editor
|
||||
.selectAll()
|
||||
.deleteShapes(editor.selectedShapeIds)
|
||||
.setCurrentTool('arrow')
|
||||
.pointerMove(500, 500)
|
||||
.pointerDown()
|
||||
.pointerMove(600, 600)
|
||||
.pointerUp()
|
||||
.selectAll()
|
||||
.setCurrentTool('select')
|
||||
|
||||
expect(editor.selectedShapeIds.length).toBe(1)
|
||||
|
||||
// Not inside of the shape but inside of the selection bounds
|
||||
editor.pointerMove(510, 590)
|
||||
expect(editor.hoveredShapeId).toBe(null)
|
||||
|
||||
// Arrow shapes have `hideSelectionBoundsBg` set to true
|
||||
editor.pointerDown()
|
||||
editor.expectToBeIn('select.pointing_canvas')
|
||||
|
||||
editor.selectAll()
|
||||
editor.rotateSelection(Math.PI)
|
||||
editor.setCurrentTool('select')
|
||||
editor.pointerMove(590, 510)
|
||||
|
||||
editor.pointerDown()
|
||||
editor.expectToBeIn('select.pointing_canvas')
|
||||
editor.pointerUp()
|
||||
})
|
||||
})
|
||||
|
||||
describe('when shape is a frame', () => {
|
||||
|
|
Loading…
Reference in a new issue