chore: merge develop into v11

This commit is contained in:
Beka Westberg
2024-03-12 16:10:59 +00:00
6 changed files with 138 additions and 62 deletions

View File

@@ -20,6 +20,7 @@ import type {BlockDefinition} from '../core/blocks.js';
export {
colour,
lists,
logic,
loops,
math,
procedures,
@@ -40,6 +41,7 @@ export const blocks: {[key: string]: BlockDefinition} = Object.assign(
loops.blocks,
math.blocks,
procedures.blocks,
texts.blocks,
variables.blocks,
variablesDynamic.blocks,
);

View File

@@ -69,8 +69,18 @@ export class BlockDragger implements IBlockDragger {
/** Whether the block would be deleted if dropped immediately. */
protected wouldDeleteBlock_ = false;
protected startXY_: Coordinate;
/** The parent block at the start of the drag. */
private startParentConn: RenderedConnection | null = null;
/**
* The child block at the start of the drag. Only gets set if
* `healStack` is true.
*/
private startChildConn: RenderedConnection | null = null;
/**
* @param block The block to drag.
* @param workspace The workspace to drag on.
@@ -126,6 +136,13 @@ export class BlockDragger implements IBlockDragger {
blockAnimation.disconnectUiStop();
if (this.shouldDisconnect_(healStack)) {
this.startParentConn =
this.draggingBlock_.outputConnection?.targetConnection ??
this.draggingBlock_.previousConnection?.targetConnection;
if (healStack) {
this.startChildConn =
this.draggingBlock_.nextConnection?.targetConnection;
}
this.disconnectBlock_(healStack, currentDragDeltaXY);
}
this.draggingBlock_.setDragging(true);
@@ -413,17 +430,10 @@ export class BlockDragger implements IBlockDragger {
.getLayerManager()
?.moveOffDragLayer(this.draggingBlock_, layers.BLOCK);
this.draggingBlock_.setDragging(false);
if (delta) {
// !preventMove
if (preventMove) {
this.moveToOriginalPosition();
} else if (delta) {
this.updateBlockAfterMove_();
} else {
// Blocks dragged directly from a flyout may need to be bumped into
// bounds.
bumpObjects.bumpIntoBounds(
this.draggingBlock_.workspace,
this.workspace_.getMetricsManager().getScrollMetrics(true),
this.draggingBlock_,
);
}
}
// Must dispose after `updateBlockAfterMove_` is called to not break the
@@ -434,6 +444,32 @@ export class BlockDragger implements IBlockDragger {
eventUtils.setGroup(false);
}
/**
* Moves the dragged block back to its original position before the start of
* the drag. Reconnects any parent and child blocks.
*/
private moveToOriginalPosition() {
this.startChildConn?.connect(this.draggingBlock_.nextConnection);
if (this.startParentConn) {
switch (this.startParentConn.type) {
case ConnectionType.INPUT_VALUE:
this.startParentConn.connect(this.draggingBlock_.outputConnection);
break;
case ConnectionType.NEXT_STATEMENT:
this.startParentConn.connect(this.draggingBlock_.previousConnection);
}
} else {
this.draggingBlock_.moveTo(this.startXY_, ['drag']);
// Blocks dragged directly from a flyout may need to be bumped into
// bounds.
bumpObjects.bumpIntoBounds(
this.draggingBlock_.workspace,
this.workspace_.getMetricsManager().getScrollMetrics(true),
this.draggingBlock_,
);
}
}
/**
* Calculates the drag delta and new location values after a block is dragged.
*

View File

@@ -282,7 +282,9 @@ export function defineBlocks(blocks: {[key: string]: BlockDefinition}) {
for (const type of Object.keys(blocks)) {
const definition = blocks[type];
if (type in Blocks) {
console.warn(`Block definiton "${type}" overwrites previous definition.`);
console.warn(
`Block definition "${type}" overwrites previous definition.`,
);
}
Blocks[type] = definition;
}

View File

@@ -66,12 +66,26 @@ export class Grid {
this.update(this.scale);
}
/**
* Get the spacing of the grid points (in px).
*
* @returns The spacing of the grid points.
*/
getSpacing(): number {
return this.spacing;
}
/** Sets the length of the grid lines. */
setLength(length: number) {
this.length = length;
this.update(this.scale);
}
/** Get the length of the grid lines (in px). */
getLength(): number {
return this.length;
}
/**
* Sets whether blocks should snap to the grid or not.
*
@@ -85,25 +99,14 @@ export class Grid {
}
/**
* Whether blocks should snap to the grid, based on the initial configuration.
* Whether blocks should snap to the grid.
*
* @returns True if blocks should snap, false otherwise.
* @internal
*/
shouldSnap(): boolean {
return this.snapToGrid;
}
/**
* Get the spacing of the grid points (in px).
*
* @returns The spacing of the grid points.
* @internal
*/
getSpacing(): number {
return this.spacing;
}
/**
* Get the ID of the pattern element, which should be randomized to avoid
* conflicts with other Blockly instances on the page.

View File

@@ -12,6 +12,8 @@ import * as blocks from './serialization/blocks.js';
import * as eventUtils from './events/utils.js';
import * as renderManagement from './render_management.js';
import * as registry from './registry.js';
import {Renderer as ZelosRenderer} from './renderers/zelos/renderer.js';
import {ConnectionType} from './connection_type.js';
/**
* An error message to throw if the block created by createMarkerBlock_ is
@@ -97,34 +99,18 @@ export class InsertionMarkerPreviewer implements IConnectionPreviewer {
throw Error(DUPLICATE_BLOCK_ERROR);
}
// Render disconnected from everything else so that we have a valid
// connection location.
marker.queueRender();
renderManagement.triggerQueuedRenders();
// Connect() also renders the insertion marker.
markerConn.connect(staticConn);
const originalOffsetToTarget = {
x: staticConn.x - markerConn.x,
y: staticConn.y - markerConn.y,
};
const originalOffsetInBlock = markerConn.getOffsetInBlock().clone();
renderManagement.finishQueuedRenders().then(() => {
// Position so that the existing block doesn't move.
marker?.positionNearConnection(
markerConn,
originalOffsetToTarget,
originalOffsetInBlock,
);
marker?.getSvgRoot().setAttribute('visibility', 'visible');
});
// TODO(7898): Instead of special casing, we should change the dragger to
// track the change in distance between the dragged connection and the
// static connection, so that it doesn't disconnect unless that
// (+ a bit) has been exceeded.
if (this.shouldUseMarkerPreview(draggedConn, staticConn)) {
this.markerConn = this.previewMarker(draggedConn, staticConn);
}
if (this.workspace.getRenderer().shouldHighlightConnection(staticConn)) {
staticConn.highlight();
}
this.markerConn = markerConn;
this.draggedConn = draggedConn;
this.staticConn = staticConn;
} finally {
@@ -132,6 +118,53 @@ export class InsertionMarkerPreviewer implements IConnectionPreviewer {
}
}
private shouldUseMarkerPreview(
_draggedConn: RenderedConnection,
staticConn: RenderedConnection,
): boolean {
return (
staticConn.type === ConnectionType.PREVIOUS_STATEMENT ||
staticConn.type === ConnectionType.NEXT_STATEMENT ||
!(this.workspace.getRenderer() instanceof ZelosRenderer)
);
}
private previewMarker(
draggedConn: RenderedConnection,
staticConn: RenderedConnection,
): RenderedConnection {
const dragged = draggedConn.getSourceBlock();
const marker = this.createInsertionMarker(dragged);
const markerConn = this.getMatchingConnection(dragged, marker, draggedConn);
if (!markerConn) {
throw Error('Could not create insertion marker to preview connection');
}
// Render disconnected from everything else so that we have a valid
// connection location.
marker.queueRender();
renderManagement.triggerQueuedRenders();
// Connect() also renders the insertion marker.
markerConn.connect(staticConn);
const originalOffsetToTarget = {
x: staticConn.x - markerConn.x,
y: staticConn.y - markerConn.y,
};
const originalOffsetInBlock = markerConn.getOffsetInBlock().clone();
renderManagement.finishQueuedRenders().then(() => {
// Position so that the existing block doesn't move.
marker?.positionNearConnection(
markerConn,
originalOffsetToTarget,
originalOffsetInBlock,
);
marker?.getSvgRoot().setAttribute('visibility', 'visible');
});
return markerConn;
}
private createInsertionMarker(origBlock: BlockSvg) {
const blockJson = blocks.save(origBlock, {
addCoordinates: false,

32
package-lock.json generated
View File

@@ -236,9 +236,9 @@
}
},
"node_modules/@eslint/js": {
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
"integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
"version": "8.57.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
"integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -351,13 +351,13 @@
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.13",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
"integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
"integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
"dev": true,
"dependencies": {
"@humanwhocodes/object-schema": "^2.0.1",
"debug": "^4.1.1",
"@humanwhocodes/object-schema": "^2.0.2",
"debug": "^4.3.1",
"minimatch": "^3.0.5"
},
"engines": {
@@ -378,9 +378,9 @@
}
},
"node_modules/@humanwhocodes/object-schema": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
"integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
"dev": true
},
"node_modules/@hyperjump/json-pointer": {
@@ -3951,16 +3951,16 @@
}
},
"node_modules/eslint": {
"version": "8.56.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
"integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
"version": "8.57.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
"integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.4",
"@eslint/js": "8.56.0",
"@humanwhocodes/config-array": "^0.11.13",
"@eslint/js": "8.57.0",
"@humanwhocodes/config-array": "^0.11.14",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
"@ungap/structured-clone": "^1.2.0",