mirror of
https://github.com/google/blockly.git
synced 2026-04-26 15:10:21 +02:00
feat: Add keyboard shortcut for duplicating blocks and workspace comments (#9727)
* feat: Add keyboard shortcut for duplicating blocks and workspace comments * test: Add tests * chore: Fix copypasta
This commit is contained in:
@@ -60,6 +60,7 @@ export enum names {
|
||||
PREVIOUS_STACK = 'previous_stack',
|
||||
INFORMATION = 'information',
|
||||
PERFORM_ACTION = 'perform_action',
|
||||
DUPLICATE = 'duplicate',
|
||||
CLEANUP = 'cleanup',
|
||||
}
|
||||
|
||||
@@ -871,6 +872,34 @@ export function registerPerformAction() {
|
||||
ShortcutRegistry.registry.register(performActionShortcut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers keyboard shortcut to duplicate a block or workspace comment.
|
||||
*/
|
||||
export function registerDuplicate() {
|
||||
const duplicateShortcut: KeyboardShortcut = {
|
||||
name: names.DUPLICATE,
|
||||
preconditionFn: (workspace, scope) => {
|
||||
const {focusedNode} = scope;
|
||||
return (
|
||||
!workspace.isDragging() &&
|
||||
!workspace.isReadOnly() &&
|
||||
(focusedNode instanceof BlockSvg ? focusedNode.isDuplicatable() : true)
|
||||
);
|
||||
},
|
||||
callback: (workspace, _e, _shortcut, scope) => {
|
||||
keyboardNavigationController.setIsActive(true);
|
||||
const copyable = isICopyable(scope.focusedNode) && scope.focusedNode;
|
||||
if (!copyable) return false;
|
||||
const data = copyable.toCopyData();
|
||||
if (!data) return false;
|
||||
return !!clipboard.paste(data, workspace);
|
||||
},
|
||||
keyCodes: [KeyCodes.D],
|
||||
allowCollision: true,
|
||||
};
|
||||
ShortcutRegistry.registry.register(duplicateShortcut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers keyboard shortcut to clean up the workspace.
|
||||
*/
|
||||
@@ -919,6 +948,7 @@ export function registerKeyboardNavigationShortcuts() {
|
||||
registerDisconnectBlock();
|
||||
registerStackNavigation();
|
||||
registerPerformAction();
|
||||
registerDuplicate();
|
||||
registerCleanup();
|
||||
}
|
||||
|
||||
|
||||
@@ -1232,6 +1232,64 @@ suite('Keyboard Shortcut Items', function () {
|
||||
});
|
||||
});
|
||||
|
||||
suite('Duplicate (D)', function () {
|
||||
test('Can duplicate blocks', function () {
|
||||
const block = this.workspace.newBlock('controls_if');
|
||||
Blockly.getFocusManager().focusNode(block);
|
||||
assert.equal(this.workspace.getTopBlocks().length, 1);
|
||||
const event = createKeyDownEvent(Blockly.utils.KeyCodes.D);
|
||||
this.workspace.getInjectionDiv().dispatchEvent(event);
|
||||
const topBlocks = this.workspace.getTopBlocks(true);
|
||||
assert.equal(topBlocks.length, 2);
|
||||
assert.notEqual(topBlocks[1], block);
|
||||
assert.equal(topBlocks[1].type, block.type);
|
||||
});
|
||||
|
||||
test('Can duplicate workspace comments', function () {
|
||||
const comment = this.workspace.newComment();
|
||||
comment.setText('Hello');
|
||||
Blockly.getFocusManager().focusNode(comment);
|
||||
assert.equal(this.workspace.getTopComments().length, 1);
|
||||
const event = createKeyDownEvent(Blockly.utils.KeyCodes.D);
|
||||
this.workspace.getInjectionDiv().dispatchEvent(event);
|
||||
const topComments = this.workspace.getTopComments(true);
|
||||
assert.equal(topComments.length, 2);
|
||||
assert.notEqual(topComments[1], comment);
|
||||
assert.equal(topComments[1].getText(), comment.getText());
|
||||
});
|
||||
|
||||
test('Does not duplicate blocks on a readonly workspace', function () {
|
||||
const block = this.workspace.newBlock('controls_if');
|
||||
this.workspace.setIsReadOnly(true);
|
||||
Blockly.getFocusManager().focusNode(block);
|
||||
assert.equal(this.workspace.getTopBlocks().length, 1);
|
||||
const event = createKeyDownEvent(Blockly.utils.KeyCodes.D);
|
||||
this.workspace.getInjectionDiv().dispatchEvent(event);
|
||||
assert.equal(this.workspace.getTopBlocks().length, 1);
|
||||
});
|
||||
|
||||
test('Does not duplicate blocks that are not duplicatable', function () {
|
||||
const block = this.workspace.newBlock('controls_if');
|
||||
this.workspace.options.maxBlocks = 1;
|
||||
assert.isFalse(block.isDuplicatable());
|
||||
assert.equal(this.workspace.getTopBlocks().length, 1);
|
||||
const event = createKeyDownEvent(Blockly.utils.KeyCodes.D);
|
||||
this.workspace.getInjectionDiv().dispatchEvent(event);
|
||||
assert.equal(this.workspace.getTopBlocks().length, 1);
|
||||
});
|
||||
|
||||
test('Does not duplicate workspace comments on a readonly workspace', function () {
|
||||
const comment = this.workspace.newComment();
|
||||
comment.setText('Hello');
|
||||
this.workspace.setIsReadOnly(true);
|
||||
Blockly.getFocusManager().focusNode(comment);
|
||||
assert.equal(this.workspace.getTopComments().length, 1);
|
||||
const event = createKeyDownEvent(Blockly.utils.KeyCodes.D);
|
||||
this.workspace.getInjectionDiv().dispatchEvent(event);
|
||||
assert.equal(this.workspace.getTopComments().length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Clean up workspace (C)', function () {
|
||||
test('Arranges all blocks in a vertical column', function () {
|
||||
this.workspace.newBlock('controls_if');
|
||||
|
||||
Reference in New Issue
Block a user