Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve collapse / uncollapse performance #6860

Merged
merged 3 commits into from
Mar 8, 2023
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
41 changes: 26 additions & 15 deletions core/block_svg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,

private translation = '';

/**
* The ID of the setTimeout callback for bumping neighbours, or 0 if no bump
* is currently scheduled.
*/
private bumpNeighboursPid = 0;

/**
* The location of the top left of this block (in workspace coordinates)
* relative to either its parent block, or the workspace origin if it has no
Expand All @@ -152,6 +158,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
*/
relativeCoords = new Coordinate(0, 0);


/**
* @param workspace The block's workspace.
* @param prototypeName Name of the language object containing type-specific
Expand Down Expand Up @@ -508,13 +515,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
return;
}
super.setCollapsed(collapsed);
if (!collapsed) {
this.updateCollapsed_();
} else if (this.rendered) {
this.render();
// Don't bump neighbours. Users like to store collapsed functions together
// and bumping makes them go out of alignment.
}
this.updateCollapsed_();
}

/**
Expand Down Expand Up @@ -1255,7 +1256,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
const removed = super.removeInput(name, opt_quiet);

if (this.rendered) {
this.render();
this.queueRender();
// Removing an input will cause the block to change shape.
this.bumpNeighbours();
}
Expand Down Expand Up @@ -1291,7 +1292,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
const input = super.appendInput_(type, name);

if (this.rendered) {
this.render();
this.queueRender();
// Adding an input will cause the block to change shape.
this.bumpNeighbours();
}
Expand Down Expand Up @@ -1441,7 +1442,16 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
* up on screen, because that creates confusion for end-users.
*/
override bumpNeighbours() {
this.getRootBlock().bumpNeighboursInternal();
if (this.bumpNeighboursPid) return;
const group = eventUtils.getGroup();

this.bumpNeighboursPid = setTimeout(() => {
const oldGroup = eventUtils.getGroup();
eventUtils.setGroup(group);
this.getRootBlock().bumpNeighboursInternal();
eventUtils.setGroup(oldGroup);
this.bumpNeighboursPid = 0;
}, config.bumpDelay);
}

/**
Expand Down Expand Up @@ -1496,11 +1506,7 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
eventUtils.setGroup(false);
}, config.bumpDelay / 2);

setTimeout(() => {
eventUtils.setGroup(group);
this.bumpNeighbours();
eventUtils.setGroup(false);
}, config.bumpDelay);
this.bumpNeighbours();
}

/**
Expand Down Expand Up @@ -1642,6 +1648,11 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
// TODO(#4592): Update all markers on the block.
this.workspace.getMarker(MarkerManager.LOCAL_MARKER)!.draw();
}
for (const input of this.inputList) {
for (const field of input.fieldRow) {
field.updateMarkers_();
}
}
}

/**
Expand Down
11 changes: 7 additions & 4 deletions core/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -962,9 +962,8 @@ export abstract class Field<T = any> implements IASTNodeLocationSvg,
forceRerender() {
this.isDirty_ = true;
if (this.sourceBlock_ && this.sourceBlock_.rendered) {
(this.sourceBlock_ as BlockSvg).render();
(this.sourceBlock_ as BlockSvg).queueRender();
(this.sourceBlock_ as BlockSvg).bumpNeighbours();
this.updateMarkers_();
}
}

Expand Down Expand Up @@ -1288,8 +1287,12 @@ export abstract class Field<T = any> implements IASTNodeLocationSvg,
this.markerSvg_ = markerSvg;
}

/** Redraw any attached marker or cursor svgs if needed. */
protected updateMarkers_() {
/**
* Redraw any attached marker or cursor svgs if needed.
*
* @internal
*/
updateMarkers_() {
const block = this.getSourceBlock();
if (!block) {
throw new UnattachedFieldError();
Expand Down
4 changes: 2 additions & 2 deletions core/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export class Input {
}

if (this.sourceBlock.rendered) {
(this.sourceBlock as BlockSvg).render();
(this.sourceBlock as BlockSvg).queueRender();
// Adding a field will cause the block to change shape.
this.sourceBlock.bumpNeighbours();
}
Expand All @@ -148,7 +148,7 @@ export class Input {
field.dispose();
this.fieldRow.splice(i, 1);
if (this.sourceBlock.rendered) {
(this.sourceBlock as BlockSvg).render();
(this.sourceBlock as BlockSvg).queueRender();
// Removing a field will cause the block to change shape.
this.sourceBlock.bumpNeighbours();
}
Expand Down
36 changes: 16 additions & 20 deletions tests/mocha/block_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1112,48 +1112,42 @@ suite('Blocks', function() {
suite('Add Connections Programmatically', function() {
test('Output', function() {
const block = createRenderedBlock(this.workspace, 'empty_block');
// this.workspace.newBlock('empty_block');
// block.initSvg();
// block.render();

block.setOutput(true);

this.clock.runAll();
chai.assert.equal(this.getOutputs().length, 1);
});
test('Value', function() {
const block = this.workspace.newBlock('empty_block');
block.initSvg();
block.render();
const block = createRenderedBlock(this.workspace, 'empty_block');

block.appendValueInput('INPUT');

this.clock.runAll();
chai.assert.equal(this.getInputs().length, 1);
});
test('Previous', function() {
const block = this.workspace.newBlock('empty_block');
block.initSvg();
block.render();
const block = createRenderedBlock(this.workspace, 'empty_block');

block.setPreviousStatement(true);

this.clock.runAll();
chai.assert.equal(this.getPrevious().length, 1);
});
test('Next', function() {
const block = this.workspace.newBlock('empty_block');
block.initSvg();
block.render();
const block = createRenderedBlock(this.workspace, 'empty_block');

block.setNextStatement(true);

this.clock.runAll();
chai.assert.equal(this.getNext().length, 1);
});
test('Statement', function() {
const block = this.workspace.newBlock('empty_block');
block.initSvg();
block.render();
const block = createRenderedBlock(this.workspace, 'empty_block');

block.appendStatementInput('STATEMENT');

this.clock.runAll();
chai.assert.equal(this.getNext().length, 1);
});
});
Expand Down Expand Up @@ -1719,8 +1713,10 @@ suite('Blocks', function() {
test('Add Input', function() {
const blockA = createRenderedBlock(this.workspace, 'empty_block');
blockA.setCollapsed(true);
assertCollapsed(blockA);

blockA.appendDummyInput('NAME');

this.clock.runAll();
assertCollapsed(blockA);
chai.assert.isNotNull(blockA.getInput('NAME'));
});
Expand Down Expand Up @@ -1794,20 +1790,20 @@ suite('Blocks', function() {
const blockA = createRenderedBlock(this.workspace, 'variable_block');

blockA.setCollapsed(true);
assertCollapsed(blockA, 'x');

const variable = this.workspace.getVariable('x', '');
this.workspace.renameVariableById(variable.getId(), 'y');

this.clock.runAll();
assertCollapsed(blockA, 'y');
});
test('Coalesce, Different Case', function() {
const blockA = createRenderedBlock(this.workspace, 'variable_block');

blockA.setCollapsed(true);
assertCollapsed(blockA, 'x');

const variable = this.workspace.createVariable('y');
this.workspace.renameVariableById(variable.getId(), 'X');

this.clock.runAll();
assertCollapsed(blockA, 'X');
});
});
Expand Down
1 change: 1 addition & 0 deletions tests/mocha/blocks/procedures_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ suite('Procedures', function() {
Blockly.Events.setGroup(false);

this.workspace.undo();
this.clock.runAll();

chai.assert.isTrue(
defBlock.getFieldValue('PARAMS').includes('param1'),
Expand Down
2 changes: 1 addition & 1 deletion tests/mocha/field_checkbox_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ suite('Checkbox Fields', function() {
workspace: {
keyboardAccessibilityMode: false,
},
render: function() {field.render_();},
queueRender: function() {field.render_();},
bumpNeighbours: function() {},
};
field.constants_ = {
Expand Down
2 changes: 1 addition & 1 deletion tests/mocha/input_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ suite('Inputs', function() {
'<block type="empty_block"/>'
), this.workspace);

this.renderStub = sinon.stub(this.block, 'render');
this.renderStub = sinon.stub(this.block, 'queueRender');
this.bumpNeighboursStub = sinon.stub(this.block, 'bumpNeighbours');

this.dummy = this.block.appendDummyInput('DUMMY');
Expand Down