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
19 changes: 18 additions & 1 deletion src/actions/mover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@ export class Mover {
info.fakePointerEvent('pointermove', direction),
info.totalDelta,
);

info.updateTotalDelta();
return true;
}

Expand Down Expand Up @@ -426,7 +428,7 @@ export class Mover {
* Workspace.
*/
export class MoveInfo {
/** Total distance moved, in screen pixels */
/** Total distance moved, in workspace units. */
totalDelta = new utils.Coordinate(0, 0);
readonly parentNext: Connection | null;
readonly parentInput: Connection | null;
Expand Down Expand Up @@ -468,4 +470,19 @@ export class MoveInfo {
tiltY: tilts.y,
});
}

/**
* The keyboard drag may have moved the block to an appropriate location
* for a preview. Update the saved delta to reflect the block's new
* location, so that it does not jump during the next unconstrained move.
*/
updateTotalDelta() {
const workspace = this.block.workspace;
if (!(workspace instanceof WorkspaceSvg)) throw new TypeError();

this.totalDelta = new utils.Coordinate(
this.block.relativeCoords.x - this.startLocation.x,
this.block.relativeCoords.y - this.startLocation.y,
);
}
}
16 changes: 11 additions & 5 deletions src/keyboard_drag_strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@ export class KeyboardDragStrategy extends dragging.BlockDragStrategy {
super.drag(newLoc);

// Handle the case when an unconstrained drag found a connection candidate.
// The next constrained move will resume the search from the current candidate
// location.
// @ts-expect-error connectionCandidate is private.
if (this.connectionCandidate) {
this.searchNode = ASTNode.createConnectionNode(
// @ts-expect-error connectionCandidate is private.
(this.connectionCandidate as ConnectionCandidate).neighbour,
// @ts-expect-error connectionCandidate is private.
const neighbour = (this.connectionCandidate as ConnectionCandidate)
.neighbour;
// The next constrained move will resume the search from the current
// candidate location.
this.searchNode = ASTNode.createConnectionNode(neighbour);
// The moving block will be positioned slightly down and to the
// right of the connection it found.
// @ts-expect-error block and startLoc are private.
this.block.moveDuringDrag(
new utils.Coordinate(neighbour.x + 10, neighbour.y + 10),
);
}
}
Expand Down
1 change: 1 addition & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
<option value="simpleCircle">simple circle</option>
<option value="sun">sun</option>
<option value="blank">blank canvas</option>
<option value="moreBlocks">more blocks</option>
</select>
</div>
<div>
Expand Down
166 changes: 166 additions & 0 deletions test/loadTestBlocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,171 @@ const simpleCircle = {
},
};

const moreBlocks = {
'blocks': {
'languageVersion': 0,
'blocks': [
{
'type': 'p5_setup',
'id': '5.{;T}3Qv}Awi:1M$:ut',
'x': 0,
'y': 75,
'deletable': false,
'inputs': {
'STATEMENTS': {
'block': {
'type': 'p5_canvas',
'id': 'spya_H-5F=K8+DhedX$y',
'deletable': false,
'movable': false,
'fields': {
'WIDTH': 400,
'HEIGHT': 400,
},
'next': {
'block': {
'type': 'p5_background_color',
'id': 'i/Hvi~^DYffkN/WpT_Ck',
'inputs': {
'COLOR': {
'shadow': {
'type': 'colour_picker',
'id': 'B:zpi7kg+.GF_Dutd9GL',
'fields': {
'COLOUR': '#9999ff',
},
},
},
},
},
},
},
},
},
},
{
'type': 'p5_draw',
'id': '3iI4f%2#Gmk}=OjI7(8h',
'x': 0,
'y': 332,
'deletable': false,
'inputs': {
'STATEMENTS': {
'block': {
'type': 'simple_circle',
'id': 'draw_circle_1',
'inline': true,
'inputs': {
'COLOR': {
'shadow': {
'type': 'colour_picker',
'id': 'gq(POne}j:hVw%C3t{vx',
'fields': {
'COLOUR': '#ffff00',
},
},
},
},
'next': {
'block': {
'type': 'text_print',
'id': 'J`*)bq?#`_Vq^X(DQF2t',
'inputs': {
'TEXT': {
'shadow': {
'type': 'text',
'id': '6fW_sIt1t|63j}nPE1ge',
'fields': {
'TEXT': 'abc',
},
},
},
},
'next': {
'block': {
'type': 'controls_if',
'id': ',rP|uDy,esfrOeQrk64u',
'inputs': {
'IF0': {
'block': {
'type': 'logic_negate',
'id': '8iH/,SwwTfk7iR;~m^s[',
},
},
'DO0': {
'block': {
'type': 'text_print',
'id': 'uSxT~QT8p%D2o)b~)Dki',
'inputs': {
'TEXT': {
'shadow': {
'type': 'text',
'id': 'j|)#Di2,(L^TK)iLI3LC',
'fields': {
'TEXT': 'abc',
},
},
'block': {
'type': 'math_arithmetic',
'id': 'mRTJ4D+(mjBnUy8c4KaT',
'fields': {
'OP': 'ADD',
},
'inputs': {
'A': {
'shadow': {
'type': 'math_number',
'id': 'hxGO;t4bA9$.~|E6Gy~H',
'fields': {
'NUM': 1,
},
},
},
'B': {
'shadow': {
'type': 'math_number',
'id': 'P,$Lqn5{mFE?R)#~v|/V',
'fields': {
'NUM': 1,
},
},
},
},
},
},
},
},
},
},
'next': {
'block': {
'type': 'text_print',
'id': '-bTQ2YVSuBS/SYn[C^LX',
'inputs': {
'TEXT': {
'shadow': {
'type': 'text',
'id': 'cy+0[WR6]O(x%Q;~c*0f',
'fields': {
'TEXT': 'abc',
},
},
},
},
},
},
},
},
},
},
},
},
},
},
],
},
};

/**
* Loads saved state from local storage into the given workspace.
* @param {Blockly.Workspace} workspace Blockly workspace to load into.
Expand All @@ -259,6 +424,7 @@ export const load = function (workspace, scenarioString) {
'blank': blankCanvas,
'sun': sunnyDay,
'simpleCircle': simpleCircle,
'moreBlocks': moreBlocks,
};

const data = JSON.stringify(scenarioMap[scenarioString]);
Expand Down