diff --git a/core/bubbles/textinput_bubble.ts b/core/bubbles/textinput_bubble.ts index 675dbb5398..befbb2f21b 100644 --- a/core/bubbles/textinput_bubble.ts +++ b/core/bubbles/textinput_bubble.ts @@ -9,6 +9,7 @@ import * as touch from '../touch.js'; import {browserEvents} from '../utils.js'; import {Coordinate} from '../utils/coordinate.js'; import * as dom from '../utils/dom.js'; +import * as drag from '../utils/drag.js'; import {Rect} from '../utils/rect.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; @@ -224,7 +225,8 @@ export class TextInputBubble extends Bubble { return; } - this.workspace.startDrag( + drag.start( + this.workspace, e, new Coordinate( this.workspace.RTL ? -this.getSize().width : this.getSize().width, @@ -264,7 +266,7 @@ export class TextInputBubble extends Bubble { /** Handles pointer move events on the resize target. */ private onResizePointerMove(e: PointerEvent) { - const delta = this.workspace.moveDrag(e); + const delta = drag.move(this.workspace, e); this.setSize( new Size(this.workspace.RTL ? -delta.x : delta.x, delta.y), false, diff --git a/core/comments/comment_view.ts b/core/comments/comment_view.ts index 72f72fa38b..bd90c75765 100644 --- a/core/comments/comment_view.ts +++ b/core/comments/comment_view.ts @@ -11,6 +11,7 @@ import * as layers from '../layers.js'; import * as touch from '../touch.js'; import {Coordinate} from '../utils/coordinate.js'; import * as dom from '../utils/dom.js'; +import * as drag from '../utils/drag.js'; import {Size} from '../utils/size.js'; import {Svg} from '../utils/svg.js'; import {WorkspaceSvg} from '../workspace_svg.js'; @@ -524,8 +525,8 @@ export class CommentView implements IRenderedElement { this.preResizeSize = this.getSize(); - // TODO(#7926): Move this into a utils file. - this.workspace.startDrag( + drag.start( + this.workspace, e, new Coordinate( this.workspace.RTL ? -this.getSize().width : this.getSize().width, @@ -569,8 +570,7 @@ export class CommentView implements IRenderedElement { /** Resizes the comment in response to a drag on the resize handle. */ private onResizePointerMove(e: PointerEvent) { - // TODO(#7926): Move this into a utils file. - const size = this.workspace.moveDrag(e); + const size = drag.move(this.workspace, e); this.setSizeWithoutFiringEvents( new Size(this.workspace.RTL ? -size.x : size.x, size.y), ); diff --git a/core/utils/drag.ts b/core/utils/drag.ts new file mode 100644 index 0000000000..a6322933bf --- /dev/null +++ b/core/utils/drag.ts @@ -0,0 +1,74 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import * as browserEvents from '../browser_events.js'; +import type {WorkspaceSvg} from '../workspace_svg.js'; +import {Coordinate} from './coordinate.js'; + +const workspaceToDragDelta: WeakMap = new WeakMap(); + +/** + * Convert from mouse coordinates to workspace coordinates. + * + * @param workspace The workspace where the pointer event is occurring. + * @param e The pointer event with the source coordinates. + */ +function mouseToWorkspacePoint( + workspace: WorkspaceSvg, + e: PointerEvent, +): SVGPoint { + const point = browserEvents.mouseToSvg( + e, + workspace.getParentSvg(), + workspace.getInverseScreenCTM(), + ); + // Fix scale of mouse event. + point.x /= workspace.scale; + point.y /= workspace.scale; + return point; +} + +/** + * Start tracking a drag of an object on this workspace by recording the offset + * between the pointer's current location and the object's starting location. + * + * Used for resizing block comments and workspace comments. + * + * @param workspace The workspace where the drag is occurring. + * @param e Pointer down event. + * @param xy Starting location of object. + */ +export function start( + workspace: WorkspaceSvg, + e: PointerEvent, + xy: Coordinate, +) { + const point = mouseToWorkspacePoint(workspace, e); + // Record the starting offset between the bubble's location and the mouse. + workspaceToDragDelta.set(workspace, Coordinate.difference(xy, point)); +} + +/** + * Compute the new position of a dragged object in this workspace based on the + * current pointer position and the offset between the pointer's starting + * location and the object's starting location. + * + * The start function should have be called previously, when the drag started. + * + * Used for resizing block comments and workspace comments. + * + * @param workspace The workspace where the drag is occurring. + * @param e Pointer move event. + * @returns New location of object. + */ +export function move(workspace: WorkspaceSvg, e: PointerEvent): Coordinate { + const point = mouseToWorkspacePoint(workspace, e); + const dragDelta = workspaceToDragDelta.get(workspace); + if (!dragDelta) { + throw new Error('Drag not initialized'); + } + return Coordinate.sum(dragDelta, point); +} diff --git a/core/workspace_svg.ts b/core/workspace_svg.ts index b8ef96292b..fed5e3cb16 100644 --- a/core/workspace_svg.ts +++ b/core/workspace_svg.ts @@ -63,6 +63,7 @@ import type {Trashcan} from './trashcan.js'; import * as arrayUtils from './utils/array.js'; import {Coordinate} from './utils/coordinate.js'; import * as dom from './utils/dom.js'; +import * as drag from './utils/drag.js'; import type {Metrics} from './utils/metrics.js'; import {Rect} from './utils/rect.js'; import {Size} from './utils/size.js'; @@ -181,9 +182,6 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { /** Vertical scroll value when scrolling started in pixel units. */ startScrollY = 0; - /** Distance from mouse to object being dragged. */ - private dragDeltaXY: Coordinate | null = null; - /** Current scale. */ scale = 1; @@ -1447,16 +1445,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @param xy Starting location of object. */ startDrag(e: PointerEvent, xy: Coordinate) { - // Record the starting offset between the bubble's location and the mouse. - const point = browserEvents.mouseToSvg( - e, - this.getParentSvg(), - this.getInverseScreenCTM(), - ); - // Fix scale of mouse event. - point.x /= this.scale; - point.y /= this.scale; - this.dragDeltaXY = Coordinate.difference(xy, point); + drag.start(this, e, xy); } /** @@ -1466,15 +1455,7 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * @returns New location of object. */ moveDrag(e: PointerEvent): Coordinate { - const point = browserEvents.mouseToSvg( - e, - this.getParentSvg(), - this.getInverseScreenCTM(), - ); - // Fix scale of mouse event. - point.x /= this.scale; - point.y /= this.scale; - return Coordinate.sum(this.dragDeltaXY!, point); + return drag.move(this, e); } /**