From c0298652afd4f3450315bc8a1c3cb5c1273b2622 Mon Sep 17 00:00:00 2001 From: Neil Fraser Date: Sun, 12 May 2024 23:16:26 +0200 Subject: [PATCH] feat: Add snapping to workspace comments. (#8070) Now that there are two things that snap (blocks and WS comments), the alignment code in being moved to a common place. --- core/block_svg.ts | 18 +++++------------- core/comments/rendered_workspace_comment.ts | 14 ++++++++++++++ core/grid.ts | 20 ++++++++++++++++++++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/core/block_svg.ts b/core/block_svg.ts index 8d8701602..e328f67ee 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -420,19 +420,11 @@ export class BlockSvg if (this.getParent()) return; if (this.isInFlyout) return; const grid = this.workspace.getGrid(); - if (!grid || !grid.shouldSnap()) return; - - const spacing = grid.getSpacing(); - const half = spacing / 2; - const xy = this.getRelativeToSurfaceXY(); - const dx = Math.round( - Math.round((xy.x - half) / spacing) * spacing + half - xy.x, - ); - const dy = Math.round( - Math.round((xy.y - half) / spacing) * spacing + half - xy.y, - ); - if (dx || dy) { - this.moveBy(dx, dy, ['snap']); + if (!grid?.shouldSnap()) return; + const currentXY = this.getRelativeToSurfaceXY(); + const alignedXY = grid.alignXY(currentXY); + if (alignedXY !== currentXY) { + this.moveTo(alignedXY, ['snap']); } } diff --git a/core/comments/rendered_workspace_comment.ts b/core/comments/rendered_workspace_comment.ts index 6fb8b9b66..a2b4d689f 100644 --- a/core/comments/rendered_workspace_comment.ts +++ b/core/comments/rendered_workspace_comment.ts @@ -138,6 +138,7 @@ export class RenderedWorkspaceComment override moveTo(location: Coordinate, reason?: string[] | undefined): void { super.moveTo(location, reason); this.view.moveTo(location); + this.snapToGrid(); } /** @@ -208,6 +209,7 @@ export class RenderedWorkspaceComment /** Ends the drag on the comment. */ endDrag(): void { + this.snapToGrid(); this.dragStrategy.endDrag(); } @@ -247,4 +249,16 @@ export class RenderedWorkspaceComment ); contextMenu.show(e, menuOptions, this.workspace.RTL); } + + /** Snap this comment to the nearest grid point. */ + snapToGrid(): void { + if (this.isDeadOrDying()) return; + const grid = this.workspace.getGrid(); + if (!grid?.shouldSnap()) return; + const currentXY = this.getRelativeToSurfaceXY(); + const alignedXY = grid.alignXY(currentXY); + if (alignedXY !== currentXY) { + this.moveTo(alignedXY, ['snap']); + } + } } diff --git a/core/grid.ts b/core/grid.ts index e495e220f..1a5de250e 100644 --- a/core/grid.ts +++ b/core/grid.ts @@ -13,6 +13,7 @@ // Former goog.module ID: Blockly.Grid import * as dom from './utils/dom.js'; +import {Coordinate} from './utils/coordinate.js'; import {Svg} from './utils/svg.js'; import {GridOptions} from './options.js'; @@ -184,6 +185,25 @@ export class Grid { this.pattern.setAttribute('y', `${y}`); } + /** + * Given a coordinate, return the nearest coordinate aligned to the grid. + * + * @param xy A workspace coordinate. + * @returns Workspace coordinate of nearest grid point. + * If there's no change, return the same coordinate object. + */ + alignXY(xy: Coordinate): Coordinate { + const spacing = this.getSpacing(); + const half = spacing / 2; + const x = Math.round(Math.round((xy.x - half) / spacing) * spacing + half); + const y = Math.round(Math.round((xy.y - half) / spacing) * spacing + half); + if (x === xy.x && y === xy.y) { + // No change. + return xy; + } + return new Coordinate(x, y); + } + /** * Create the DOM for the grid described by options. *