Skip to content

Commit 6bf1e6d

Browse files
Merge branch 'main' into floating-promises
2 parents 0390aff + f08551a commit 6bf1e6d

File tree

12 files changed

+535
-198
lines changed

12 files changed

+535
-198
lines changed

src/actions/enter.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ import {
1616
icons,
1717
FocusableTreeTraverser,
1818
renderManagement,
19+
comments,
20+
getFocusManager,
1921
} from 'blockly/core';
2022

2123
import type {Block} from 'blockly/core';
2224

2325
import * as Constants from '../constants';
2426
import type {Navigation} from '../navigation';
25-
import {Mover} from './mover';
27+
import {Mover, MoveType} from './mover';
2628
import {
2729
showConstrainedMovementHint,
2830
showHelpHint,
@@ -124,10 +126,13 @@ export class EnterAction {
124126
) {
125127
return !workspace.isReadOnly();
126128
}
127-
if (curNode instanceof BlockSvg) return true;
128129
// Returning true is sometimes incorrect for icons, but there's no API to check.
129-
if (curNode instanceof icons.Icon) return true;
130-
return false;
130+
return (
131+
curNode instanceof BlockSvg ||
132+
curNode instanceof icons.Icon ||
133+
curNode instanceof comments.CommentBarButton ||
134+
curNode instanceof comments.RenderedWorkspaceComment
135+
);
131136
}
132137

133138
/**
@@ -159,9 +164,20 @@ export class EnterAction {
159164
// opening a bubble of some sort. We then need to wait for the bubble to
160165
// appear before attempting to navigate into it.
161166
curNode.onClick();
162-
void renderManagement.finishQueuedRenders().then(() => {
163-
cursor?.in();
164-
});
167+
// This currently only works for MutatorIcons.
168+
// See icon_navigation_policy.
169+
if (curNode instanceof icons.MutatorIcon) {
170+
void renderManagement.finishQueuedRenders().then(() => {
171+
cursor?.in();
172+
});
173+
}
174+
return true;
175+
} else if (curNode instanceof comments.CommentBarButton) {
176+
curNode.performAction();
177+
return true;
178+
} else if (curNode instanceof comments.RenderedWorkspaceComment) {
179+
curNode.setCollapsed(false);
180+
getFocusManager().focusNode(curNode.getEditorFocusableNode());
165181
return true;
166182
}
167183
return false;
@@ -185,19 +201,28 @@ export class EnterAction {
185201
Events.setGroup(true);
186202
}
187203

188-
const stationaryNode = FocusableTreeTraverser.findFocusedNode(workspace);
204+
// If the workspace has never had focus default the stationary node.
205+
const stationaryNode =
206+
FocusableTreeTraverser.findFocusedNode(workspace) ??
207+
workspace.getRestoredFocusableNode(null);
189208
const newBlock = this.createNewBlock(workspace);
190209
if (!newBlock) return;
191210
const insertStartPoint = stationaryNode
192211
? this.navigation.findInsertStartPoint(stationaryNode, newBlock)
193212
: null;
213+
194214
if (workspace.getTopBlocks().includes(newBlock)) {
195215
this.positionNewTopLevelBlock(workspace, newBlock);
196216
}
197217

198218
workspace.setResizesEnabled(true);
199219

200-
this.mover.startMove(workspace, newBlock, insertStartPoint);
220+
this.mover.startMove(
221+
workspace,
222+
newBlock,
223+
MoveType.Insert,
224+
insertStartPoint,
225+
);
201226

202227
const isStartBlock =
203228
!newBlock.outputConnection &&

src/actions/move.ts

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@
55
*/
66

77
import {
8-
BlockSvg,
98
ContextMenuRegistry,
109
Msg,
1110
ShortcutRegistry,
1211
utils,
1312
WorkspaceSvg,
1413
keyboardNavigationController,
1514
getFocusManager,
15+
comments,
16+
IDraggable,
17+
IFocusableNode,
18+
IBoundedElement,
19+
ISelectable,
1620
} from 'blockly';
1721
import {Direction} from '../drag_direction';
18-
import {Mover} from './mover';
22+
import {Mover, MoveType} from './mover';
1923
import {getMenuItem} from '../shortcut_formatting';
2024

2125
const KeyCodes = utils.KeyCodes;
@@ -24,7 +28,7 @@ const createSerializedKey = ShortcutRegistry.registry.createSerializedKey.bind(
2428
);
2529

2630
/**
27-
* Actions for moving blocks with keyboard shortcuts.
31+
* Actions for moving workspace elements with keyboard shortcuts.
2832
*/
2933
export class MoveActions {
3034
constructor(private mover: Mover) {}
@@ -38,19 +42,22 @@ export class MoveActions {
3842
{
3943
name: 'start_move',
4044
preconditionFn: (workspace) => {
41-
const startBlock = this.getCurrentBlock(workspace);
42-
return !!startBlock && this.mover.canMove(workspace, startBlock);
45+
const startDraggable = this.getCurrentDraggable(workspace);
46+
return (
47+
!!startDraggable && this.mover.canMove(workspace, startDraggable)
48+
);
4349
},
4450
callback: (workspace) => {
4551
keyboardNavigationController.setIsActive(true);
46-
const startBlock = this.getCurrentBlock(workspace);
47-
// Focus the start block in case one of its fields or a shadow block
52+
const startDraggable = this.getCurrentDraggable(workspace);
53+
// Focus the root draggable in case one of its children
4854
// was focused when the move was triggered.
49-
if (startBlock) {
50-
getFocusManager().focusNode(startBlock);
55+
if (startDraggable) {
56+
getFocusManager().focusNode(startDraggable);
5157
}
5258
return (
53-
!!startBlock && this.mover.startMove(workspace, startBlock, null)
59+
!!startDraggable &&
60+
this.mover.startMove(workspace, startDraggable, MoveType.Move, null)
5461
);
5562
},
5663
keyCodes: [KeyCodes.M],
@@ -162,28 +169,52 @@ export class MoveActions {
162169
if (!workspace || menuOpenEvent instanceof PointerEvent)
163170
return 'hidden';
164171

165-
const startBlock = this.getCurrentBlock(workspace);
166-
return !!startBlock && this.mover.canMove(workspace, startBlock)
172+
const startDraggable = this.getCurrentDraggable(workspace);
173+
return !!startDraggable &&
174+
this.mover.canMove(workspace, startDraggable)
167175
? 'enabled'
168176
: 'disabled';
169177
},
170178
callback: (scope) => {
171179
const workspace = scope.block?.workspace as WorkspaceSvg | null;
172180
if (!workspace) return false;
173-
const startBlock = this.getCurrentBlock(workspace);
181+
const startDraggable = this.getCurrentDraggable(workspace);
174182
// Focus the start block in case one of its fields or a shadow block
175183
// was focused when the move was triggered.
176-
if (startBlock) {
177-
getFocusManager().focusNode(startBlock);
184+
if (startDraggable) {
185+
getFocusManager().focusNode(startDraggable);
178186
}
179187
return (
180-
!!startBlock && this.mover.startMove(workspace, startBlock, null)
188+
!!startDraggable &&
189+
this.mover.startMove(workspace, startDraggable, MoveType.Move, null)
181190
);
182191
},
183192
scopeType: ContextMenuRegistry.ScopeType.BLOCK,
184193
id: 'move',
185194
weight: 8.5,
186195
},
196+
{
197+
displayText: getMenuItem(
198+
Msg['MOVE_COMMENT'] ?? 'Move Comment',
199+
'start_move',
200+
),
201+
preconditionFn: (scope, menuOpenEvent) => {
202+
const comment = scope.comment;
203+
if (!comment) return 'hidden';
204+
205+
return this.mover.canMove(comment.workspace, comment)
206+
? 'enabled'
207+
: 'disabled';
208+
},
209+
callback: (scope) => {
210+
const comment = scope.comment;
211+
if (!comment) return false;
212+
this.mover.startMove(comment.workspace, comment, MoveType.Move, null);
213+
},
214+
scopeType: ContextMenuRegistry.ScopeType.COMMENT,
215+
id: 'move_comment',
216+
weight: 8.5,
217+
},
187218
];
188219

189220
for (const menuItem of menuItems) {
@@ -214,16 +245,21 @@ export class MoveActions {
214245
}
215246

216247
/**
217-
* Get the source block for the cursor location, or undefined if no
218-
* source block can be found.
248+
* Get the source draggable for the cursor location, or undefined if no
249+
* source draggable can be found.
219250
* If the cursor is on a shadow block, walks up the tree until it finds
220251
* a non-shadow block to drag.
221252
*
222253
* @param workspace The workspace to inspect for a cursor.
223-
* @returns The source block, or undefined if no appropriate block
254+
* @returns The source draggable, or undefined if no appropriate draggable
224255
* could be found.
225256
*/
226-
getCurrentBlock(workspace: WorkspaceSvg): BlockSvg | undefined {
257+
getCurrentDraggable(
258+
workspace: WorkspaceSvg,
259+
): (IDraggable & IFocusableNode & IBoundedElement & ISelectable) | undefined {
260+
const node = getFocusManager().getFocusedNode();
261+
if (node instanceof comments.RenderedWorkspaceComment) return node;
262+
227263
let block = workspace?.getCursor()?.getSourceBlock();
228264
if (!block) return undefined;
229265
while (block.isShadow()) {

0 commit comments

Comments
 (0)