fix: block initialization (#7777)

* fix: reorganize initialization

* chore: fix failing tests

* fix: tests

* chore: format

* chore: remove console trace
This commit is contained in:
Beka Westberg
2024-01-18 10:12:57 -08:00
parent 8c5f32b2f9
commit 5db9b5bf11
7 changed files with 43 additions and 22 deletions

View File

@@ -921,10 +921,9 @@ const PROCEDURE_CALL_COMMON = {
type: 'field_label',
text: this.arguments_[i],
}) as FieldLabel;
const input = this.appendValueInput('ARG' + i)
this.appendValueInput('ARG' + i)
.setAlign(Align.RIGHT)
.appendField(newField, 'ARGNAME' + i);
input.init();
}
}
// Remove deleted inputs.
@@ -937,7 +936,6 @@ const PROCEDURE_CALL_COMMON = {
if (this.arguments_.length) {
if (!this.getField('WITH')) {
topRow.appendField(Msg['PROCEDURES_CALL_BEFORE_PARAMS'], 'WITH');
topRow.init();
}
} else {
if (this.getField('WITH')) {

View File

@@ -191,6 +191,13 @@ export class Block implements IASTNodeLocation, IDeletable {
*/
private disposing = false;
/**
* Has this block been fully initialized? E.g. all fields initailized.
*
* @internal
*/
initialized = false;
private readonly xy_: Coordinate;
isInFlyout: boolean;
isInMutator: boolean;
@@ -373,13 +380,11 @@ export class Block implements IASTNodeLocation, IDeletable {
* change).
*/
initModel() {
if (this.initialized) return;
for (const input of this.inputList) {
for (const field of input.fieldRow) {
if (field.initModel) {
field.initModel();
}
}
input.initModel();
}
this.initialized = true;
}
/**

View File

@@ -163,6 +163,9 @@ export class BlockSvg
*/
constructor(workspace: WorkspaceSvg, prototypeName: string, opt_id?: string) {
super(workspace, prototypeName, opt_id);
if (!workspace.rendered) {
throw TypeError('Cannot create a rendered block in a headless workspace');
}
this.workspace = workspace;
this.svgGroup_ = dom.createSvgElement(Svg.G, {});
@@ -189,10 +192,8 @@ export class BlockSvg
* May be called more than once.
*/
initSvg() {
if (!this.workspace.rendered) {
throw TypeError('Workspace is headless.');
}
for (let i = 0, input; (input = this.inputList[i]); i++) {
if (this.initialized) return;
for (const input of this.inputList) {
input.init();
}
for (const icon of this.getIcons()) {
@@ -202,7 +203,7 @@ export class BlockSvg
this.applyColour();
this.pathObject.updateMovable(this.isMovable());
const svg = this.getSvgRoot();
if (!this.workspace.options.readOnly && !this.eventsInit_ && svg) {
if (!this.workspace.options.readOnly && svg) {
browserEvents.conditionalBind(
svg,
'pointerdown',
@@ -210,11 +211,11 @@ export class BlockSvg
this.onMouseDown_,
);
}
this.eventsInit_ = true;
if (!svg.parentNode) {
this.workspace.getCanvas().appendChild(svg);
}
this.initialized = true;
}
/**

View File

@@ -314,6 +314,7 @@ export abstract class Field<T = any>
this.setTooltip(this.tooltip_);
this.bindEvents_();
this.initModel();
this.applyColour();
}
/**

View File

@@ -103,10 +103,7 @@ export class Input {
}
field.setSourceBlock(this.sourceBlock);
if (this.sourceBlock.rendered) {
field.init();
field.applyColour();
}
if (this.sourceBlock.initialized) this.initField(field);
field.name = opt_name;
field.setVisible(this.isVisible());
@@ -270,11 +267,28 @@ export class Input {
/** Initialize the fields on this input. */
init() {
if (!this.sourceBlock.rendered) {
return; // Headless blocks don't need fields initialized.
for (const field of this.fieldRow) {
field.init();
}
for (let i = 0; i < this.fieldRow.length; i++) {
this.fieldRow[i].init();
}
/**
* Initializes the fields on this input for a headless block.
*
* @internal
*/
public initModel() {
for (const field of this.fieldRow) {
field.initModel();
}
}
/** Initializes the given field. */
private initField(field: Field) {
if (this.sourceBlock.rendered) {
field.init();
} else {
field.initModel();
}
}

View File

@@ -166,6 +166,7 @@ function shouldRenderRootBlock(block: BlockSvg): boolean {
*/
function renderBlock(block: BlockSvg) {
if (!dirtyBlocks.has(block)) return;
if (!block.initialized) return;
for (const child of block.getChildren(false)) {
renderBlock(child);
}

View File

@@ -33,6 +33,7 @@ suite('Render Management', function () {
getRelativeToSurfaceXY: () => ({x: 0, y: 0}),
updateComponentLocations: () => {},
bumpNeighbours: () => {},
initialized: true,
workspace: {
resizeContents: () => {},
},