Skip to content

Commit

Permalink
Fix draw-to-insert into grid when going top-left of the origin (#6370)
Browse files Browse the repository at this point in the history
**Problem:**

Draw-to-insert into a grid does not work if the drag vector goes
top/left of the drag origin.

**Fix:**

Fix the origin calculation.
Also, I added a TODO in the code to improve this strategy in an
incremental PR.

| Before | After |
|-------|---------|
| ![Kapture 2024-09-13 at 17 40
56](https://github.com/user-attachments/assets/218fb02c-4e6e-476f-9376-c7a963598959)
| ![Kapture 2024-09-13 at 17 40
06](https://github.com/user-attachments/assets/9187b0bb-9c79-4859-93f4-168061da8de5)
|

Fixes #6369
  • Loading branch information
ruggi authored Sep 16, 2024
1 parent 9c636e6 commit 1798bb8
Showing 1 changed file with 29 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
import type { ElementPath } from 'utopia-shared/src/types'
import { MetadataUtils } from '../../../../core/model/element-metadata-utils'
import { stripNulls } from '../../../../core/shared/array-utils'
import * as EP from '../../../../core/shared/element-path'
import type {
CanvasPoint,
CanvasRectangle,
Size,
WindowRectangle,
} from '../../../../core/shared/math-utils'
import type { CanvasPoint, CanvasRectangle, Size } from '../../../../core/shared/math-utils'
import {
canvasPoint,
canvasRectangle,
canvasVector,
offsetPoint,
pointDifference,
roundRectangleToNearestWhole,
scaleVector,
size,
windowPoint,
} from '../../../../core/shared/math-utils'
import * as PP from '../../../../core/shared/property-path'
import { assertNever } from '../../../../core/shared/utils'
import { EditorModes, type InsertionSubject } from '../../../editor/editor-modes'
import { childInsertionPath } from '../../../editor/store/insertion-path'
import { deleteProperties } from '../../commands/delete-properties-command'
import type { InsertElementInsertionSubject } from '../../commands/insert-element-insertion-subject'
import { insertElementInsertionSubject } from '../../commands/insert-element-insertion-subject'
import { showGridControls } from '../../commands/show-grid-controls-command'
import { updateHighlightedViews } from '../../commands/update-highlighted-views-command'
import { wildcardPatch } from '../../commands/wildcard-patch-command'
import { controlsForGridPlaceholders } from '../../controls/grid-controls'
import { canvasPointToWindowPoint } from '../../dom-lookup'
import { canvasPointToWindowPoint, windowToCanvasCoordinates } from '../../dom-lookup'
import {
getWrapperWithGeneratedUid,
getWrappingCommands,
Expand All @@ -50,11 +46,6 @@ import {
import { getTargetCell, setGridPropsCommands } from './grid-helpers'
import { newReparentSubjects } from './reparent-helpers/reparent-strategy-helpers'
import { getReparentTargetUnified } from './reparent-helpers/reparent-strategy-parent-lookup'
import { stripNulls } from '../../../../core/shared/array-utils'
import { showGridControls } from '../../commands/show-grid-controls-command'
import * as PP from '../../../../core/shared/property-path'
import { propertyToDelete, updateBulkProperties } from '../../commands/set-property-command'
import { deleteProperties } from '../../commands/delete-properties-command'

export const gridDrawToInsertText: CanvasStrategyFactory = (
canvasState: InteractionCanvasState,
Expand Down Expand Up @@ -193,7 +184,11 @@ const gridDrawToInsertStrategyInner =

const { gridCellCoordinates, cellWindowRectangle } = newTargetCell

const offset = getOffsetFromGridCell(interactionData, canvasState, cellWindowRectangle)
const cellCanvasOrigin = windowToCanvasCoordinates(
canvasState.scale,
canvasState.canvasOffset,
cellWindowRectangle,
).canvasPositionRounded

const defaultSize =
interactionData.type === 'DRAG' &&
Expand All @@ -205,7 +200,7 @@ const gridDrawToInsertStrategyInner =
const insertionCommand = getInsertionCommand(
targetParent,
insertionSubject,
getFrameForInsertion(interactionData, defaultSize, offset),
getFrameForInsertion(interactionData, defaultSize, cellCanvasOrigin),
)

const gridTemplate = parent.specialSizeMeasurements.containerGridProperties
Expand Down Expand Up @@ -245,6 +240,9 @@ const gridDrawToInsertStrategyInner =
gridColumnStart: { numericalPosition: gridCellCoordinates.column },
gridRowEnd: { numericalPosition: gridCellCoordinates.row + 1 },
gridColumnEnd: { numericalPosition: gridCellCoordinates.column + 1 },
// TODO! this is currently going to assign the element to the cell the interaction started in,
// however it would be good to instead assign the element to _all_ cells overlapping with the final
// inserted frame.
}),
...wrappingCommands,
...stripNulls([
Expand Down Expand Up @@ -279,17 +277,22 @@ const gridDrawToInsertStrategyInner =
function getFrameForInsertion(
interactionData: DragInteractionData | HoverInteractionData,
defaultSize: Size,
offset: CanvasPoint,
cellOrigin: CanvasPoint,
): CanvasRectangle {
if (interactionData.type === 'DRAG') {
const origin = interactionData.drag ?? { x: defaultSize.width / 2, y: defaultSize.height / 2 }

const { x, y } = { x: offset.x - origin.x, y: offset.y - origin.y }
const dragStart = interactionData.dragStart
const mouseAt = {
x: interactionData.dragStart.x + (interactionData.drag?.x ?? 0),
y: interactionData.dragStart.y + (interactionData.drag?.y ?? 0),
}
const width = Math.abs(interactionData.drag?.x ?? defaultSize.width)
const height = Math.abs(interactionData.drag?.y ?? defaultSize.height)

const { width, height } =
interactionData.drag == null
? defaultSize
: { width: interactionData.drag.x, height: interactionData.drag.y }
const origin = canvasPoint({
x: Math.min(dragStart.x, mouseAt.x),
y: Math.min(dragStart.y, mouseAt.y),
})
const { x, y } = pointDifference(cellOrigin, origin)

return roundRectangleToNearestWhole(canvasRectangle({ x, y, width, height }))
}
Expand Down Expand Up @@ -347,30 +350,3 @@ function getGridCellUnderCursor(
mouseWindowPoint,
)
}

function getOffsetFromGridCell(
interactionData: DragInteractionData | HoverInteractionData,
canvasState: InteractionCanvasState,
cellWindowRectangle: WindowRectangle,
) {
const windowPointToUse =
interactionData.type === 'DRAG'
? offsetPoint(interactionData.dragStart, interactionData.drag ?? canvasVector({ x: 0, y: 0 }))
: interactionData.point

const mouseWindowPoint = canvasPointToWindowPoint(
windowPointToUse,
canvasState.scale,
canvasState.canvasOffset,
)

const { x, y } = scaleVector(
windowPoint({
x: mouseWindowPoint.x - cellWindowRectangle.x,
y: mouseWindowPoint.y - cellWindowRectangle.y,
}),
1 / canvasState.scale,
)

return canvasPoint({ x, y })
}

0 comments on commit 1798bb8

Please sign in to comment.