From a2a9ab1da47efe381ce26223996f1da5bd16ec1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Contet?= Date: Mon, 4 Sep 2023 19:33:42 +0200 Subject: [PATCH 1/3] fix: insertion marker position when connection is resized (#7426) --- core/block_svg.ts | 26 ++++++++++++++++++++++++++ core/insertion_marker_manager.ts | 3 +++ 2 files changed, 29 insertions(+) diff --git a/core/block_svg.ts b/core/block_svg.ts index 121ffa45f..049ce62c1 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -1536,6 +1536,32 @@ export class BlockSvg } } + /** + * Reposition a block after its connection has been resized, to match exactly the target block position. + * The block to position is usually either the first block in a dragged stack + * or an insertion marker. + * + * @param sourceConnection The connection on the moving block's stack. + * @param originalOffsetInBlock The connection original offset in its block, before the resize occured + * @internal + */ + repositionAfterConnectionResize( + sourceConnection: RenderedConnection, + originalOffsetInBlock: Coordinate, + ) { + // We only need to position the new block if it's before the existing one, + // otherwise its position is set by the previous block. + if ( + sourceConnection.type === ConnectionType.NEXT_STATEMENT || + sourceConnection.type === ConnectionType.INPUT_VALUE + ) { + const dx = originalOffsetInBlock.x - sourceConnection.getOffsetInBlock().x; + const dy = originalOffsetInBlock.y - sourceConnection.getOffsetInBlock().y; + + this.moveBy(dx, dy); + } + } + /** * Find all the blocks that are directly nested inside this one. * Includes value and statement inputs, as well as any following statement. diff --git a/core/insertion_marker_manager.ts b/core/insertion_marker_manager.ts index eb7189121..796995b1e 100644 --- a/core/insertion_marker_manager.ts +++ b/core/insertion_marker_manager.ts @@ -616,8 +616,11 @@ export class InsertionMarkerManager { // Connect() also renders the insertion marker. imConn.connect(closest); + let originalOffsetInBlock = imConn.getOffsetInBlock().clone(); + const imConnConst = imConn; renderManagement.finishQueuedRenders().then(() => { insertionMarker?.getSvgRoot().setAttribute('visibility', 'visible'); + insertionMarker?.repositionAfterConnectionResize(imConnConst, originalOffsetInBlock); }); this.markerConnection = imConn; From b95067b9499692d288447bbee19f08b8fa952998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Contet?= Date: Tue, 12 Sep 2023 11:11:31 +0200 Subject: [PATCH 2/3] chore: position insertion marker in a single function --- core/block_svg.ts | 39 ++++++++------------------------ core/insertion_marker_manager.ts | 8 +++---- 2 files changed, 13 insertions(+), 34 deletions(-) diff --git a/core/block_svg.ts b/core/block_svg.ts index 049ce62c1..f4445e939 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -1515,38 +1515,13 @@ export class BlockSvg * or an insertion marker. * * @param sourceConnection The connection on the moving block's stack. - * @param targetConnection The connection that should stay stationary as this - * block is positioned. + * @param originalOffsetToTarget The connection original offset to the target connection + * @param originalOffsetInBlock The connection original offset in its block * @internal */ positionNearConnection( sourceConnection: RenderedConnection, - targetConnection: RenderedConnection, - ) { - // We only need to position the new block if it's before the existing one, - // otherwise its position is set by the previous block. - if ( - sourceConnection.type === ConnectionType.NEXT_STATEMENT || - sourceConnection.type === ConnectionType.INPUT_VALUE - ) { - const dx = targetConnection.x - sourceConnection.x; - const dy = targetConnection.y - sourceConnection.y; - - this.moveBy(dx, dy); - } - } - - /** - * Reposition a block after its connection has been resized, to match exactly the target block position. - * The block to position is usually either the first block in a dragged stack - * or an insertion marker. - * - * @param sourceConnection The connection on the moving block's stack. - * @param originalOffsetInBlock The connection original offset in its block, before the resize occured - * @internal - */ - repositionAfterConnectionResize( - sourceConnection: RenderedConnection, + originalOffsetToTarget: {x: number; y: number}, originalOffsetInBlock: Coordinate, ) { // We only need to position the new block if it's before the existing one, @@ -1555,8 +1530,12 @@ export class BlockSvg sourceConnection.type === ConnectionType.NEXT_STATEMENT || sourceConnection.type === ConnectionType.INPUT_VALUE ) { - const dx = originalOffsetInBlock.x - sourceConnection.getOffsetInBlock().x; - const dy = originalOffsetInBlock.y - sourceConnection.getOffsetInBlock().y; + // First move the block to match the orginal target connection position + let dx = originalOffsetToTarget.x; + let dy = originalOffsetToTarget.y; + // Then adjust its position according to the connection resize + dx += originalOffsetInBlock.x - sourceConnection.getOffsetInBlock().x; + dy += originalOffsetInBlock.y - sourceConnection.getOffsetInBlock().y; this.moveBy(dx, dy); } diff --git a/core/insertion_marker_manager.ts b/core/insertion_marker_manager.ts index 796995b1e..1f531b7b5 100644 --- a/core/insertion_marker_manager.ts +++ b/core/insertion_marker_manager.ts @@ -611,16 +611,16 @@ export class InsertionMarkerManager { insertionMarker.queueRender(); renderManagement.triggerQueuedRenders(); - // Position so that the existing block doesn't move. - insertionMarker.positionNearConnection(imConn, closest); // Connect() also renders the insertion marker. imConn.connect(closest); - let originalOffsetInBlock = imConn.getOffsetInBlock().clone(); + const originalOffsetToTarget = {x: closest.x - imConn.x, y: closest.y - imConn.y} + const originalOffsetInBlock = imConn.getOffsetInBlock().clone(); const imConnConst = imConn; renderManagement.finishQueuedRenders().then(() => { + // Position so that the existing block doesn't move. + insertionMarker?.positionNearConnection(imConnConst, originalOffsetToTarget, originalOffsetInBlock); insertionMarker?.getSvgRoot().setAttribute('visibility', 'visible'); - insertionMarker?.repositionAfterConnectionResize(imConnConst, originalOffsetInBlock); }); this.markerConnection = imConn; From 36b00fb6607f0d22d2f1bfef9306bd1754ce5b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Contet?= Date: Wed, 13 Sep 2023 07:49:13 +0200 Subject: [PATCH 3/3] chore: format --- core/block_svg.ts | 4 ++-- core/insertion_marker_manager.ts | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/block_svg.ts b/core/block_svg.ts index f4445e939..b419122ba 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -1534,8 +1534,8 @@ export class BlockSvg let dx = originalOffsetToTarget.x; let dy = originalOffsetToTarget.y; // Then adjust its position according to the connection resize - dx += originalOffsetInBlock.x - sourceConnection.getOffsetInBlock().x; - dy += originalOffsetInBlock.y - sourceConnection.getOffsetInBlock().y; + dx += originalOffsetInBlock.x - sourceConnection.getOffsetInBlock().x; + dy += originalOffsetInBlock.y - sourceConnection.getOffsetInBlock().y; this.moveBy(dx, dy); } diff --git a/core/insertion_marker_manager.ts b/core/insertion_marker_manager.ts index 1f531b7b5..f6fb25faa 100644 --- a/core/insertion_marker_manager.ts +++ b/core/insertion_marker_manager.ts @@ -614,12 +614,19 @@ export class InsertionMarkerManager { // Connect() also renders the insertion marker. imConn.connect(closest); - const originalOffsetToTarget = {x: closest.x - imConn.x, y: closest.y - imConn.y} + const originalOffsetToTarget = { + x: closest.x - imConn.x, + y: closest.y - imConn.y, + }; const originalOffsetInBlock = imConn.getOffsetInBlock().clone(); const imConnConst = imConn; renderManagement.finishQueuedRenders().then(() => { // Position so that the existing block doesn't move. - insertionMarker?.positionNearConnection(imConnConst, originalOffsetToTarget, originalOffsetInBlock); + insertionMarker?.positionNearConnection( + imConnConst, + originalOffsetToTarget, + originalOffsetInBlock, + ); insertionMarker?.getSvgRoot().setAttribute('visibility', 'visible'); });