Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions packages/blockly/core/dragging/block_drag_strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ export class BlockDragStrategy implements IDragStrategy {
/** Used to persist an event group when snapping is done async. */
private originalEventGroup = '';

/**
* Map from block IDs to reason(s) why it was disabled, used to restore
* disabled state post-drag.
*/
private lastBlockDisabledReasons: Map<string, Set<string>> = new Map();

protected readonly BLOCK_CONNECTION_OFFSET = 10;

/**
Expand Down Expand Up @@ -338,6 +344,9 @@ export class BlockDragStrategy implements IDragStrategy {

this.block.setDragging(true);

// Enable all blocks including children.
this.enableAllDraggedBlocks(this.block);

// For keyboard-driven moves, cache a list of valid connection points for
// use in constrained moved mode.
if (e instanceof KeyboardEvent) {
Expand Down Expand Up @@ -885,6 +894,9 @@ export class BlockDragStrategy implements IDragStrategy {
);

this.block.setDragging(false);

// Re-disable the block for its original reasons.
this.redisableAllDraggedBlocks(this.block);
}

if (this.connectionCandidate) {
Expand Down Expand Up @@ -979,6 +991,8 @@ export class BlockDragStrategy implements IDragStrategy {
this.startParentConn = null;

this.block.setDragging(false);
// Re-disable the block for its original reasons.
this.redisableAllDraggedBlocks(this.block);
this.dragging = false;
aria.announceDynamicAriaState(Msg['ANNOUNCE_MOVE_CANCELED']);
}
Expand Down Expand Up @@ -1236,4 +1250,41 @@ export class BlockDragStrategy implements IDragStrategy {
? MoveMode.CONSTRAINED
: MoveMode.UNCONSTRAINED;
}

/**
* Enables the given block and its children.
* Stores the reasons each block was disabled so they can be restored.
*
* @param block The block to enable.
*/
private enableAllDraggedBlocks(block: BlockSvg) {
const oldUndo = eventUtils.getRecordUndo();
eventUtils.setRecordUndo(false);
this.lastBlockDisabledReasons.clear();
// getDescendants includes the block itself.
block.getDescendants(false).forEach((descendant) => {
const reasons = new Set(descendant.getDisabledReasons());
this.lastBlockDisabledReasons.set(descendant.id, reasons);
reasons.forEach((reason) => descendant.setDisabledReason(false, reason));
});
eventUtils.setRecordUndo(oldUndo);
}

/**
* Re-disables the given block and its children using their original
* disabled reasons.
*
* @param block The block to re-disable, if applicable.
*/
private redisableAllDraggedBlocks(block: BlockSvg) {
console.log('redisable');
const oldUndo = eventUtils.getRecordUndo();
eventUtils.setRecordUndo(false);
block.getDescendants(false).forEach((descendant) => {
this.lastBlockDisabledReasons.get(descendant.id)?.forEach((reason) => {
descendant.setDisabledReason(true, reason);
});
});
eventUtils.setRecordUndo(oldUndo);
}
}
46 changes: 46 additions & 0 deletions packages/blockly/tests/mocha/keyboard_movement_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,52 @@ suite('Keyboard-driven movement', function () {
cancelMove(this.workspace);
});

test('Enables disabled blocks during drag and reenables when committed', function () {
const ifBlock = this.workspace.newBlock('controls_if');
const repeatBlock = this.workspace.newBlock('controls_repeat');
ifBlock.initSvg();
ifBlock.render();
repeatBlock.initSvg();
repeatBlock.render();
repeatBlock.previousConnection.connect(
ifBlock.getInput('DO0').connection,
);

ifBlock.setDisabledReason(true, 'test');
assert.isFalse(ifBlock.isEnabled());

Blockly.getFocusManager().focusNode(ifBlock);
startMove(this.workspace);

assert.isTrue(ifBlock.isEnabled());

endMove(this.workspace);
assert.isFalse(ifBlock.isEnabled());
});

test('Enables disabled blocks during drag and reenables when cancelled', function () {
const ifBlock = this.workspace.newBlock('controls_if');
const repeatBlock = this.workspace.newBlock('controls_repeat');
ifBlock.initSvg();
ifBlock.render();
repeatBlock.initSvg();
repeatBlock.render();
repeatBlock.previousConnection.connect(
ifBlock.getInput('DO0').connection,
);

ifBlock.setDisabledReason(true, 'test');
assert.isFalse(ifBlock.isEnabled());

Blockly.getFocusManager().focusNode(ifBlock);
startMove(this.workspace);

assert.isTrue(ifBlock.isEnabled());

cancelMove(this.workspace);
assert.isFalse(ifBlock.isEnabled());
});

suite('Statement move tests', function () {
// Clear the workspace and load start blocks.
setup(function () {
Expand Down
Loading