import { Shape, Point } from 'remixed/model/l33t'; import { Command, CommandContext } from '.'; export class DragShapeCommand implements Command { private oldShapes: { [id: string]: Shape } | null = null; private updatedShape: Shape | null = null; constructor( private context: CommandContext, private shapeId: string, private dx: number, private dy: number, private canvasWidth: number, private canvasHeight: number ) {} execute(): void { const { shapes, setShapes, setSelectedShape } = this.context; this.oldShapes = { ...shapes }; const shape = shapes[this.shapeId]; if (!shape) return; // Calculate the bounding box of the shape const minX = Math.min(...shape.points.map(p => p.x)); const minY = Math.min(...shape.points.map(p => p.y)); const maxX = Math.max(...shape.points.map(p => p.x)); const maxY = Math.max(...shape.points.map(p => p.y)); // Calculate the actual dx and dy after boundary checks const actualDx = Math.max(-minX, Math.min(this.dx, this.canvasWidth - maxX)); const actualDy = Math.max(-minY, Math.min(this.dy, this.canvasHeight - maxY)); // Apply the actual dx and dy to all points this.updatedShape = { ...shape, points: shape.points.map(point => ({ x: point.x + actualDx, y: point.y + actualDy })) }; setShapes({ ...shapes, [this.shapeId]: this.updatedShape }); setSelectedShape(this.updatedShape); } undo(): void { if (this.oldShapes) { const { setShapes, setSelectedShape } = this.context; setShapes(this.oldShapes); // Find the shape that was originally dragged const originalShape = this.oldShapes[this.shapeId]; if (originalShape) { setSelectedShape(originalShape); } } } }