Skip to content

Commit 34e9319

Browse files
chore: move workspace movement into a separate file (#281)
* chore: move workspace movement into a separate file * chore: blocklyUtils -> BlocklyUtils in ws_movement.ts
1 parent 07477f7 commit 34e9319

File tree

3 files changed

+140
-82
lines changed

3 files changed

+140
-82
lines changed

src/actions/ws_movement.ts

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {ASTNode, ShortcutRegistry, utils as BlocklyUtils} from 'blockly';
8+
import * as Constants from '../constants';
9+
import type {WorkspaceSvg} from 'blockly';
10+
11+
const KeyCodes = BlocklyUtils.KeyCodes;
12+
const createSerializedKey = ShortcutRegistry.registry.createSerializedKey.bind(
13+
ShortcutRegistry.registry,
14+
);
15+
16+
/**
17+
* Logic for free movement of the cursor on the workspace with keyboard
18+
* shortcuts.
19+
*/
20+
export class WorkspaceMovement {
21+
/**
22+
* Function provided by the navigation controller to say whether editing
23+
* is allowed.
24+
*/
25+
private canCurrentlyEdit: (ws: WorkspaceSvg) => boolean;
26+
27+
/**
28+
* The distance to move the cursor when the cursor is on the workspace.
29+
*/
30+
WS_MOVE_DISTANCE = 40;
31+
32+
constructor(canEdit: (ws: WorkspaceSvg) => boolean) {
33+
this.canCurrentlyEdit = canEdit;
34+
}
35+
36+
/**
37+
* Install these actions as both keyboard shortcuts and context menu items.
38+
*/
39+
install() {
40+
const shortcutList: {
41+
[name: string]: ShortcutRegistry.KeyboardShortcut;
42+
} = {
43+
/** Move the cursor on the workspace to the left. */
44+
wsMoveLeft: {
45+
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_LEFT,
46+
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
47+
callback: (workspace) => this.moveWSCursor(workspace, -1, 0),
48+
keyCodes: [createSerializedKey(KeyCodes.A, [KeyCodes.SHIFT])],
49+
},
50+
/** Move the cursor on the workspace to the right. */
51+
wsMoveRight: {
52+
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_RIGHT,
53+
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
54+
callback: (workspace) => this.moveWSCursor(workspace, 1, 0),
55+
keyCodes: [createSerializedKey(KeyCodes.D, [KeyCodes.SHIFT])],
56+
},
57+
58+
/** Move the cursor on the workspace up. */
59+
wsMoveUp: {
60+
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_UP,
61+
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
62+
callback: (workspace) => this.moveWSCursor(workspace, 0, -1),
63+
keyCodes: [createSerializedKey(KeyCodes.W, [KeyCodes.SHIFT])],
64+
},
65+
66+
/** Move the cursor on the workspace down. */
67+
wsMoveDown: {
68+
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_DOWN,
69+
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
70+
callback: (workspace) => this.moveWSCursor(workspace, 0, 1),
71+
keyCodes: [createSerializedKey(KeyCodes.S, [KeyCodes.SHIFT])],
72+
},
73+
};
74+
for (const shortcut of Object.values(shortcutList)) {
75+
ShortcutRegistry.registry.register(shortcut);
76+
}
77+
}
78+
79+
/**
80+
* Uninstall these actions.
81+
*/
82+
uninstall() {
83+
ShortcutRegistry.registry.unregister(
84+
Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_LEFT,
85+
);
86+
ShortcutRegistry.registry.unregister(
87+
Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_RIGHT,
88+
);
89+
ShortcutRegistry.registry.unregister(
90+
Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_UP,
91+
);
92+
ShortcutRegistry.registry.unregister(
93+
Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_DOWN,
94+
);
95+
}
96+
97+
/**
98+
* Moves the workspace cursor in the given direction.
99+
*
100+
* @param workspace The workspace the cursor is on.
101+
* @param xDirection -1 to move cursor left. 1 to move cursor right.
102+
* @param yDirection -1 to move cursor up. 1 to move cursor down.
103+
* @returns True if the current node is a workspace, false
104+
* otherwise.
105+
*/
106+
moveWSCursor(
107+
workspace: WorkspaceSvg,
108+
xDirection: number,
109+
yDirection: number,
110+
): boolean {
111+
const cursor = workspace.getCursor();
112+
if (!cursor) {
113+
return false;
114+
}
115+
const curNode = cursor.getCurNode();
116+
117+
if (curNode.getType() !== ASTNode.types.WORKSPACE) {
118+
return false;
119+
}
120+
121+
const wsCoord = curNode.getWsCoordinate();
122+
const newX = xDirection * this.WS_MOVE_DISTANCE + wsCoord.x;
123+
const newY = yDirection * this.WS_MOVE_DISTANCE + wsCoord.y;
124+
125+
cursor.setCurNode(
126+
ASTNode.createWorkspaceNode(
127+
workspace,
128+
new BlocklyUtils.Coordinate(newX, newY),
129+
)!,
130+
);
131+
return true;
132+
}
133+
}

src/navigation.ts

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ export class Navigation {
2929
*/
3030
workspaceStates: {[index: string]: Constants.STATE} = {};
3131

32-
/**
33-
* The distance to move the cursor when the cursor is on the workspace.
34-
*/
35-
WS_MOVE_DISTANCE = 40;
36-
3732
/**
3833
* The default coordinate to use when focusing on the workspace and no
3934
* blocks are present. In pixel coordinates, but will be converted to
@@ -1173,43 +1168,6 @@ export class Navigation {
11731168
console.error(msg);
11741169
}
11751170

1176-
/**
1177-
* Moves the workspace cursor in the given direction.
1178-
*
1179-
* @param workspace The workspace the cursor is on.
1180-
* @param xDirection -1 to move cursor left. 1 to move cursor right.
1181-
* @param yDirection -1 to move cursor up. 1 to move cursor down.
1182-
* @returns True if the current node is a workspace, false
1183-
* otherwise.
1184-
*/
1185-
moveWSCursor(
1186-
workspace: Blockly.WorkspaceSvg,
1187-
xDirection: number,
1188-
yDirection: number,
1189-
): boolean {
1190-
const cursor = workspace.getCursor();
1191-
if (!cursor) {
1192-
return false;
1193-
}
1194-
const curNode = cursor.getCurNode();
1195-
1196-
if (curNode.getType() !== Blockly.ASTNode.types.WORKSPACE) {
1197-
return false;
1198-
}
1199-
1200-
const wsCoord = curNode.getWsCoordinate();
1201-
const newX = xDirection * this.WS_MOVE_DISTANCE + wsCoord.x;
1202-
const newY = yDirection * this.WS_MOVE_DISTANCE + wsCoord.y;
1203-
1204-
cursor.setCurNode(
1205-
Blockly.ASTNode.createWorkspaceNode(
1206-
workspace,
1207-
new Blockly.utils.Coordinate(newX, newY),
1208-
)!,
1209-
);
1210-
return true;
1211-
}
1212-
12131171
/**
12141172
* Handles hitting the enter key on the workspace.
12151173
*

src/navigation_controller.ts

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {ShortcutDialog} from './shortcut_dialog';
2929
import {DeleteAction} from './actions/delete';
3030
import {InsertAction} from './actions/insert';
3131
import {Clipboard} from './actions/clipboard';
32+
import {WorkspaceMovement} from './actions/ws_movement';
3233

3334
const KeyCodes = BlocklyUtils.KeyCodes;
3435
const createSerializedKey = ShortcutRegistry.registry.createSerializedKey.bind(
@@ -60,6 +61,10 @@ export class NavigationController {
6061
this.canCurrentlyEdit.bind(this),
6162
);
6263

64+
workspaceMovement: WorkspaceMovement = new WorkspaceMovement(
65+
this.canCurrentlyEdit.bind(this),
66+
);
67+
6368
hasNavigationFocus: boolean = false;
6469

6570
/**
@@ -519,46 +524,6 @@ export class NavigationController {
519524
allowCollision: true,
520525
},
521526

522-
/** Move the cursor on the workspace to the left. */
523-
wsMoveLeft: {
524-
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_LEFT,
525-
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
526-
callback: (workspace) => {
527-
return this.navigation.moveWSCursor(workspace, -1, 0);
528-
},
529-
keyCodes: [createSerializedKey(KeyCodes.A, [KeyCodes.SHIFT])],
530-
},
531-
532-
/** Move the cursor on the workspace to the right. */
533-
wsMoveRight: {
534-
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_RIGHT,
535-
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
536-
callback: (workspace) => {
537-
return this.navigation.moveWSCursor(workspace, 1, 0);
538-
},
539-
keyCodes: [createSerializedKey(KeyCodes.D, [KeyCodes.SHIFT])],
540-
},
541-
542-
/** Move the cursor on the workspace up. */
543-
wsMoveUp: {
544-
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_UP,
545-
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
546-
callback: (workspace) => {
547-
return this.navigation.moveWSCursor(workspace, 0, -1);
548-
},
549-
keyCodes: [createSerializedKey(KeyCodes.W, [KeyCodes.SHIFT])],
550-
},
551-
552-
/** Move the cursor on the workspace down. */
553-
wsMoveDown: {
554-
name: Constants.SHORTCUT_NAMES.MOVE_WS_CURSOR_DOWN,
555-
preconditionFn: (workspace) => this.canCurrentlyEdit(workspace),
556-
callback: (workspace) => {
557-
return this.navigation.moveWSCursor(workspace, 0, 1);
558-
},
559-
keyCodes: [createSerializedKey(KeyCodes.S, [KeyCodes.SHIFT])],
560-
},
561-
562527
/** List all of the currently registered shortcuts. */
563528
announceShortcuts: {
564529
name: Constants.SHORTCUT_NAMES.LIST_SHORTCUTS,
@@ -714,6 +679,7 @@ export class NavigationController {
714679
}
715680
this.deleteAction.install();
716681
this.insertAction.install();
682+
this.workspaceMovement.install();
717683

718684
this.clipboard.install();
719685

@@ -734,6 +700,7 @@ export class NavigationController {
734700
this.deleteAction.uninstall();
735701
this.insertAction.uninstall();
736702
this.clipboard.uninstall();
703+
this.workspaceMovement.uninstall();
737704

738705
this.removeShortcutHandlers();
739706
this.navigation.dispose();

0 commit comments

Comments
 (0)