Skip to content

Commit e0196a8

Browse files
refactor: consolidate DragMover into Mover
1 parent b4fe52d commit e0196a8

File tree

3 files changed

+83
-221
lines changed

3 files changed

+83
-221
lines changed

src/actions/drag_mover.ts

Lines changed: 0 additions & 206 deletions
This file was deleted.

src/actions/mover.ts

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,25 @@ import {
1010
Connection,
1111
ContextMenuRegistry,
1212
ShortcutRegistry,
13+
WorkspaceSvg,
1314
common,
15+
registry,
1416
utils,
1517
} from 'blockly';
16-
import type {Block, BlockSvg, WorkspaceSvg} from 'blockly';
18+
import type {Block, BlockSvg, IDragger} from 'blockly';
1719
import {Navigation} from '../navigation';
1820

1921
const KeyCodes = utils.KeyCodes;
2022
const createSerializedKey = ShortcutRegistry.registry.createSerializedKey.bind(
2123
ShortcutRegistry.registry,
2224
);
2325

26+
/**
27+
* The distance to move an item, in workspace coordinates, when
28+
* making an unconstrained move.
29+
*/
30+
const UNCONSTRAINED_MOVE_DISTANCE = 20;
31+
2432
/**
2533
* Actions for moving blocks with keyboard shortcuts.
2634
*/
@@ -221,11 +229,19 @@ export class Mover {
221229
// Select and focus block.
222230
common.setSelected(block);
223231
cursor.setCurNode(ASTNode.createBlockNode(block));
224-
225-
// Additional implementation goes here.
226-
console.log('startMove');
227-
228-
this.moves.set(workspace, new MoveInfo(block));
232+
// Begin dragging block.
233+
const DraggerClass = registry.getClassFromOptions(
234+
registry.Type.BLOCK_DRAGGER,
235+
workspace.options,
236+
true,
237+
);
238+
if (!DraggerClass) throw new Error('no Dragger registered');
239+
const dragger = new DraggerClass(block, workspace);
240+
// Record that a move is in progress and start dragging.
241+
const info = new MoveInfo(block, dragger);
242+
this.moves.set(workspace, info);
243+
// Begin drag.
244+
dragger.onDragStart(info.fakePointerEvent('pointerdown'));
229245
return true;
230246
}
231247

@@ -241,8 +257,10 @@ export class Mover {
241257
const info = this.moves.get(workspace);
242258
if (!info) throw new Error('no move info for workspace');
243259

244-
// Additional implementation goes here.
245-
console.log('finishMove');
260+
info.dragger.onDragEnd(
261+
info.fakePointerEvent('pointerup'),
262+
new utils.Coordinate(0, 0),
263+
);
246264

247265
this.moves.delete(workspace);
248266
return true;
@@ -260,8 +278,18 @@ export class Mover {
260278
const info = this.moves.get(workspace);
261279
if (!info) throw new Error('no move info for workspace');
262280

263-
// Additional implementation goes here.
264-
console.log('abortMove');
281+
// Monkey patch dragger to trigger call to draggable.revertDrag.
282+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
283+
(info.dragger as any).shouldReturnToStart = () => true;
284+
const blockSvg = info.block as BlockSvg;
285+
286+
// Explicitly call `hidePreview` because it is not called in revertDrag.
287+
// @ts-expect-error Access to private property dragStrategy.
288+
blockSvg.dragStrategy.connectionPreviewer.hidePreview();
289+
info.dragger.onDragEnd(
290+
info.fakePointerEvent('pointerup'),
291+
new utils.Coordinate(0, 0),
292+
);
265293

266294
this.moves.delete(workspace);
267295
return true;
@@ -278,8 +306,11 @@ export class Mover {
278306
workspace: WorkspaceSvg,
279307
/* ... */
280308
) {
281-
console.log('moveConstrained');
282309
// Not yet implemented. Absorb keystroke to avoid moving cursor.
310+
alert(`Constrained movement not implemented.
311+
312+
Use ctrl+arrow or alt+arrow (option+arrow on macOS) for unconstrained move.
313+
Use enter to complete the move, or escape to abort.`);
283314
return true;
284315
}
285316

@@ -297,8 +328,16 @@ export class Mover {
297328
xDirection: number,
298329
yDirection: number,
299330
): boolean {
300-
console.log('moveUnconstrained');
301-
// Not yet implemented. Absorb keystroke to avoid moving cursor.
331+
if (!workspace) return false;
332+
const info = this.moves.get(workspace);
333+
if (!info) throw new Error('no move info for workspace');
334+
335+
info.totalDelta.x +=
336+
xDirection * UNCONSTRAINED_MOVE_DISTANCE * workspace.scale;
337+
info.totalDelta.y +=
338+
yDirection * UNCONSTRAINED_MOVE_DISTANCE * workspace.scale;
339+
340+
info.dragger.onDrag(info.fakePointerEvent('pointermove'), info.totalDelta);
302341
return true;
303342
}
304343

@@ -322,13 +361,42 @@ export class Mover {
322361
* Workspace.
323362
*/
324363
export class MoveInfo {
364+
/** Total distance moved, in screen pixels */
365+
totalDelta = new utils.Coordinate(0, 0);
325366
readonly parentNext: Connection | null;
326367
readonly parentInput: Connection | null;
327368
readonly startLocation: utils.Coordinate;
328369

329-
constructor(readonly block: Block) {
370+
constructor(
371+
readonly block: Block,
372+
readonly dragger: IDragger,
373+
) {
330374
this.parentNext = block.previousConnection?.targetConnection ?? null;
331375
this.parentInput = block.outputConnection?.targetConnection ?? null;
332376
this.startLocation = block.getRelativeToSurfaceXY();
333377
}
378+
379+
/**
380+
* Create a fake pointer event for dragging.
381+
*
382+
* @param type Which type of pointer event to create.
383+
* @returns A synthetic PointerEvent that can be consumed by Blockly's
384+
* dragging code.
385+
*/
386+
fakePointerEvent(type: string): PointerEvent {
387+
const workspace = this.block.workspace;
388+
if (!(workspace instanceof WorkspaceSvg)) throw new TypeError();
389+
390+
const blockCoords = utils.svgMath.wsToScreenCoordinates(
391+
workspace,
392+
new utils.Coordinate(
393+
this.startLocation.x + this.totalDelta.x,
394+
this.startLocation.y + this.totalDelta.y,
395+
),
396+
);
397+
return new PointerEvent(type, {
398+
clientX: blockCoords.x,
399+
clientY: blockCoords.y,
400+
});
401+
}
334402
}

src/navigation_controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import {ExitAction} from './actions/exit';
3434
import {EnterAction} from './actions/enter';
3535
import {DisconnectAction} from './actions/disconnect';
3636
import {ActionMenu} from './actions/action_menu';
37-
import {DragMover as Mover} from './actions/drag_mover';
37+
import {Mover} from './actions/mover';
3838

3939
const KeyCodes = BlocklyUtils.KeyCodes;
4040

0 commit comments

Comments
 (0)