blockly 7.20211209.4 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/blockly.d.ts +18963 -18432
- package/blockly.min.js +5 -4
- package/blockly_compressed.js +4 -3
- package/blockly_compressed.js.map +1 -1
- package/blocks/blocks.js +47 -0
- package/blocks/colour.js +13 -3
- package/blocks/lists.js +22 -13
- package/blocks/logic.js +13 -3
- package/blocks/loops.js +24 -11
- package/blocks/math.js +12 -3
- package/blocks/procedures.js +45 -32
- package/blocks/text.js +22 -13
- package/blocks/variables.js +14 -3
- package/blocks/variables_dynamic.js +13 -3
- package/blocks_compressed.js +1 -1
- package/blocks_compressed.js.map +1 -1
- package/core/block.js +1869 -1814
- package/core/block_drag_surface.js +201 -200
- package/core/block_dragger.js +377 -373
- package/core/block_svg.js +1593 -1479
- package/core/blockly.js +8 -22
- package/core/blocks.js +9 -2
- package/core/browser_events.js +22 -5
- package/core/bubble.js +841 -797
- package/core/bubble_dragger.js +213 -206
- package/core/bump_objects.js +2 -2
- package/core/clipboard.js +9 -9
- package/core/comment.js +353 -332
- package/core/common.js +46 -17
- package/core/component_manager.js +181 -174
- package/core/config.js +87 -0
- package/core/connection.js +595 -584
- package/core/connection_checker.js +242 -244
- package/core/connection_db.js +235 -230
- package/core/contextmenu.js +9 -6
- package/core/contextmenu_items.js +1 -2
- package/core/contextmenu_registry.js +93 -89
- package/core/css.js +474 -474
- package/core/delete_area.js +45 -42
- package/core/drag_target.js +57 -56
- package/core/dropdowndiv.js +153 -163
- package/core/events/events.js +2 -2
- package/core/events/events_abstract.js +89 -77
- package/core/events/events_block_base.js +37 -36
- package/core/events/events_block_change.js +130 -124
- package/core/events/events_block_create.js +73 -71
- package/core/events/events_block_delete.js +84 -82
- package/core/events/events_block_drag.js +50 -49
- package/core/events/events_block_move.js +147 -140
- package/core/events/events_bubble_open.js +51 -50
- package/core/events/events_click.js +48 -44
- package/core/events/events_comment_base.js +72 -69
- package/core/events/events_comment_change.js +63 -61
- package/core/events/events_comment_create.js +44 -42
- package/core/events/events_comment_delete.js +42 -40
- package/core/events/events_comment_move.js +106 -104
- package/core/events/events_marker_move.js +65 -64
- package/core/events/events_selected.js +46 -45
- package/core/events/events_theme_change.js +36 -35
- package/core/events/events_toolbox_item_select.js +46 -45
- package/core/events/events_trashcan_open.js +37 -36
- package/core/events/events_ui.js +47 -46
- package/core/events/events_ui_base.js +30 -29
- package/core/events/events_var_base.js +37 -36
- package/core/events/events_var_create.js +50 -48
- package/core/events/events_var_delete.js +50 -48
- package/core/events/events_var_rename.js +51 -49
- package/core/events/events_viewport.js +66 -65
- package/core/events/utils.js +29 -14
- package/core/events/workspace_events.js +49 -55
- package/core/extensions.js +4 -3
- package/core/field.js +1061 -997
- package/core/field_angle.js +462 -442
- package/core/field_checkbox.js +194 -182
- package/core/field_colour.js +519 -505
- package/core/field_dropdown.js +617 -598
- package/core/field_image.js +229 -220
- package/core/field_label.js +102 -91
- package/core/field_label_serializable.js +42 -41
- package/core/field_multilineinput.js +372 -358
- package/core/field_number.js +272 -253
- package/core/field_textinput.js +499 -467
- package/core/field_variable.js +458 -420
- package/core/flyout_base.js +1005 -952
- package/core/flyout_button.js +277 -260
- package/core/flyout_horizontal.js +304 -302
- package/core/flyout_metrics_manager.js +64 -64
- package/core/flyout_vertical.js +306 -300
- package/core/generator.js +459 -446
- package/core/gesture.js +829 -813
- package/core/grid.js +166 -163
- package/core/icon.js +168 -159
- package/core/inject.js +7 -5
- package/core/input.js +257 -248
- package/core/insertion_marker_manager.js +655 -624
- package/core/internal_constants.js +0 -129
- package/core/keyboard_nav/ast_node.js +605 -596
- package/core/keyboard_nav/basic_cursor.js +166 -165
- package/core/keyboard_nav/cursor.js +99 -97
- package/core/keyboard_nav/marker.js +83 -79
- package/core/keyboard_nav/tab_navigate_cursor.js +18 -23
- package/core/marker_manager.js +153 -141
- package/core/menu.js +377 -372
- package/core/menuitem.js +223 -217
- package/core/metrics_manager.js +403 -390
- package/core/mutator.js +468 -437
- package/core/names.js +229 -188
- package/core/options.js +290 -284
- package/core/procedures.js +29 -17
- package/core/registry.js +19 -16
- package/core/rendered_connection.js +482 -463
- package/core/renderers/common/block_rendering.js +9 -3
- package/core/renderers/common/constants.js +1119 -1112
- package/core/renderers/common/debug.js +14 -0
- package/core/renderers/common/debugger.js +338 -316
- package/core/renderers/common/drawer.js +380 -370
- package/core/renderers/common/i_path_object.js +2 -2
- package/core/renderers/common/info.js +626 -618
- package/core/renderers/common/marker_svg.js +579 -541
- package/core/renderers/common/path_object.js +203 -200
- package/core/renderers/common/renderer.js +220 -218
- package/core/renderers/geras/constants.js +36 -36
- package/core/renderers/geras/drawer.js +155 -147
- package/core/renderers/geras/highlight_constants.js +244 -238
- package/core/renderers/geras/highlighter.js +231 -179
- package/core/renderers/geras/info.js +392 -369
- package/core/renderers/geras/measurables/inline_input.js +25 -19
- package/core/renderers/geras/measurables/statement_input.js +23 -17
- package/core/renderers/geras/path_object.js +106 -121
- package/core/renderers/geras/renderer.js +96 -98
- package/core/renderers/measurables/base.js +30 -18
- package/core/renderers/measurables/bottom_row.js +83 -80
- package/core/renderers/measurables/connection.js +22 -15
- package/core/renderers/measurables/external_value_input.js +35 -22
- package/core/renderers/measurables/field.js +35 -20
- package/core/renderers/measurables/hat.js +18 -13
- package/core/renderers/measurables/icon.js +24 -17
- package/core/renderers/measurables/in_row_spacer.js +15 -13
- package/core/renderers/measurables/inline_input.js +43 -33
- package/core/renderers/measurables/input_connection.js +41 -28
- package/core/renderers/measurables/input_row.js +50 -44
- package/core/renderers/measurables/jagged_edge.js +14 -12
- package/core/renderers/measurables/next_connection.js +16 -14
- package/core/renderers/measurables/output_connection.js +26 -20
- package/core/renderers/measurables/previous_connection.js +16 -15
- package/core/renderers/measurables/round_corner.js +20 -18
- package/core/renderers/measurables/row.js +184 -168
- package/core/renderers/measurables/spacer_row.js +38 -23
- package/core/renderers/measurables/square_corner.js +18 -16
- package/core/renderers/measurables/statement_input.js +23 -20
- package/core/renderers/measurables/top_row.js +88 -85
- package/core/renderers/minimalist/constants.js +8 -7
- package/core/renderers/minimalist/drawer.js +11 -10
- package/core/renderers/minimalist/info.js +18 -18
- package/core/renderers/minimalist/renderer.js +40 -39
- package/core/renderers/thrasos/info.js +258 -248
- package/core/renderers/thrasos/renderer.js +20 -20
- package/core/renderers/zelos/constants.js +898 -873
- package/core/renderers/zelos/drawer.js +186 -169
- package/core/renderers/zelos/info.js +502 -479
- package/core/renderers/zelos/marker_svg.js +129 -115
- package/core/renderers/zelos/measurables/bottom_row.js +31 -30
- package/core/renderers/zelos/measurables/inputs.js +22 -21
- package/core/renderers/zelos/measurables/row_elements.js +14 -13
- package/core/renderers/zelos/measurables/top_row.js +34 -33
- package/core/renderers/zelos/path_object.js +181 -180
- package/core/renderers/zelos/renderer.js +91 -92
- package/core/scrollbar.js +759 -713
- package/core/scrollbar_pair.js +250 -245
- package/core/serialization/blocks.js +26 -10
- package/core/serialization/workspaces.js +3 -2
- package/core/shortcut_registry.js +286 -277
- package/core/sprites.js +31 -0
- package/core/theme.js +135 -141
- package/core/theme_manager.js +147 -143
- package/core/toolbox/category.js +602 -576
- package/core/toolbox/collapsible_category.js +226 -227
- package/core/toolbox/separator.js +70 -61
- package/core/toolbox/toolbox.js +934 -927
- package/core/toolbox/toolbox_item.js +115 -99
- package/core/tooltip.js +108 -35
- package/core/touch.js +8 -3
- package/core/touch_gesture.js +254 -251
- package/core/trashcan.js +606 -595
- package/core/utils/coordinate.js +97 -95
- package/core/utils/dom.js +2 -2
- package/core/utils/global.js +2 -0
- package/core/utils/rect.js +41 -37
- package/core/utils/sentinel.js +25 -0
- package/core/utils/size.js +30 -27
- package/core/utils/svg.js +18 -16
- package/core/variable_map.js +325 -341
- package/core/variable_model.js +55 -54
- package/core/variables.js +9 -2
- package/core/variables_dynamic.js +3 -1
- package/core/warning.js +126 -120
- package/core/widgetdiv.js +4 -4
- package/core/workspace.js +685 -664
- package/core/workspace_audio.js +124 -118
- package/core/workspace_comment.js +308 -298
- package/core/workspace_comment_svg.js +1029 -951
- package/core/workspace_drag_surface_svg.js +147 -140
- package/core/workspace_dragger.js +70 -71
- package/core/workspace_svg.js +2322 -2297
- package/core/xml.js +30 -20
- package/core/zoom_controls.js +431 -439
- package/generators/dart/colour.js +56 -64
- package/generators/dart/lists.js +61 -50
- package/generators/dart/math.js +160 -148
- package/generators/dart/text.js +83 -61
- package/generators/javascript/colour.js +37 -34
- package/generators/javascript/lists.js +50 -43
- package/generators/javascript/math.js +123 -139
- package/generators/javascript/text.js +67 -81
- package/generators/lua/colour.js +25 -23
- package/generators/lua/lists.js +97 -69
- package/generators/lua/logic.js +1 -2
- package/generators/lua/math.js +182 -144
- package/generators/lua/text.js +116 -99
- package/generators/php/colour.js +38 -32
- package/generators/php/lists.js +109 -89
- package/generators/php/math.js +90 -81
- package/generators/php/text.js +63 -61
- package/generators/python/colour.js +18 -18
- package/generators/python/lists.js +38 -30
- package/generators/python/loops.js +12 -8
- package/generators/python/math.js +104 -106
- package/generators/python/text.js +34 -30
- package/msg/smn.js +436 -0
- package/package.json +7 -6
- package/blocks/all.js +0 -23
package/core/connection_db.js
CHANGED
|
@@ -34,276 +34,281 @@ goog.require('Blockly.constants');
|
|
|
34
34
|
* Database of connections.
|
|
35
35
|
* Connections are stored in order of their vertical component. This way
|
|
36
36
|
* connections in an area may be looked up quickly using a binary search.
|
|
37
|
-
* @param {!IConnectionChecker} checker The workspace's
|
|
38
|
-
* connection type checker, used to decide if connections are valid during a
|
|
39
|
-
* drag.
|
|
40
|
-
* @constructor
|
|
41
37
|
* @alias Blockly.ConnectionDB
|
|
42
38
|
*/
|
|
43
|
-
|
|
39
|
+
class ConnectionDB {
|
|
44
40
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
41
|
+
* @param {!IConnectionChecker} checker The workspace's
|
|
42
|
+
* connection type checker, used to decide if connections are valid during
|
|
43
|
+
* a drag.
|
|
48
44
|
*/
|
|
49
|
-
|
|
45
|
+
constructor(checker) {
|
|
46
|
+
/**
|
|
47
|
+
* Array of connections sorted by y position in workspace units.
|
|
48
|
+
* @type {!Array<!RenderedConnection>}
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
this.connections_ = [];
|
|
52
|
+
/**
|
|
53
|
+
* The workspace's connection type checker, used to decide if connections
|
|
54
|
+
* are valid during a drag.
|
|
55
|
+
* @type {!IConnectionChecker}
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
this.connectionChecker_ = checker;
|
|
59
|
+
}
|
|
60
|
+
|
|
50
61
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* @
|
|
54
|
-
*
|
|
62
|
+
* Add a connection to the database. Should not already exist in the database.
|
|
63
|
+
* @param {!RenderedConnection} connection The connection to be added.
|
|
64
|
+
* @param {number} yPos The y position used to decide where to insert the
|
|
65
|
+
* connection.
|
|
66
|
+
* @package
|
|
55
67
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Add a connection to the database. Should not already exist in the database.
|
|
61
|
-
* @param {!RenderedConnection} connection The connection to be added.
|
|
62
|
-
* @param {number} yPos The y position used to decide where to insert the
|
|
63
|
-
* connection.
|
|
64
|
-
* @package
|
|
65
|
-
*/
|
|
66
|
-
ConnectionDB.prototype.addConnection = function(connection, yPos) {
|
|
67
|
-
const index = this.calculateIndexForYPos_(yPos);
|
|
68
|
-
this.connections_.splice(index, 0, connection);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Finds the index of the given connection.
|
|
73
|
-
*
|
|
74
|
-
* Starts by doing a binary search to find the approximate location, then
|
|
75
|
-
* linearly searches nearby for the exact connection.
|
|
76
|
-
* @param {!RenderedConnection} conn The connection to find.
|
|
77
|
-
* @param {number} yPos The y position used to find the index of the connection.
|
|
78
|
-
* @return {number} The index of the connection, or -1 if the connection was
|
|
79
|
-
* not found.
|
|
80
|
-
* @private
|
|
81
|
-
*/
|
|
82
|
-
ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) {
|
|
83
|
-
if (!this.connections_.length) {
|
|
84
|
-
return -1;
|
|
68
|
+
addConnection(connection, yPos) {
|
|
69
|
+
const index = this.calculateIndexForYPos_(yPos);
|
|
70
|
+
this.connections_.splice(index, 0, connection);
|
|
85
71
|
}
|
|
86
72
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Finds the index of the given connection.
|
|
75
|
+
*
|
|
76
|
+
* Starts by doing a binary search to find the approximate location, then
|
|
77
|
+
* linearly searches nearby for the exact connection.
|
|
78
|
+
* @param {!RenderedConnection} conn The connection to find.
|
|
79
|
+
* @param {number} yPos The y position used to find the index of the
|
|
80
|
+
* connection.
|
|
81
|
+
* @return {number} The index of the connection, or -1 if the connection was
|
|
82
|
+
* not found.
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
findIndexOfConnection_(conn, yPos) {
|
|
86
|
+
if (!this.connections_.length) {
|
|
87
|
+
return -1;
|
|
88
|
+
}
|
|
92
89
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (this.connections_[pointer] === conn) {
|
|
98
|
-
return pointer;
|
|
90
|
+
const bestGuess = this.calculateIndexForYPos_(yPos);
|
|
91
|
+
if (bestGuess >= this.connections_.length) {
|
|
92
|
+
// Not in list
|
|
93
|
+
return -1;
|
|
99
94
|
}
|
|
100
|
-
pointer--;
|
|
101
|
-
}
|
|
102
95
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
96
|
+
yPos = conn.y;
|
|
97
|
+
// Walk forward and back on the y axis looking for the connection.
|
|
98
|
+
let pointer = bestGuess;
|
|
99
|
+
while (pointer >= 0 && this.connections_[pointer].y === yPos) {
|
|
100
|
+
if (this.connections_[pointer] === conn) {
|
|
101
|
+
return pointer;
|
|
102
|
+
}
|
|
103
|
+
pointer--;
|
|
108
104
|
}
|
|
109
|
-
pointer++;
|
|
110
|
-
}
|
|
111
|
-
return -1;
|
|
112
|
-
};
|
|
113
105
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
ConnectionDB.prototype.calculateIndexForYPos_ = function(yPos) {
|
|
122
|
-
if (!this.connections_.length) {
|
|
123
|
-
return 0;
|
|
124
|
-
}
|
|
125
|
-
let pointerMin = 0;
|
|
126
|
-
let pointerMax = this.connections_.length;
|
|
127
|
-
while (pointerMin < pointerMax) {
|
|
128
|
-
const pointerMid = Math.floor((pointerMin + pointerMax) / 2);
|
|
129
|
-
if (this.connections_[pointerMid].y < yPos) {
|
|
130
|
-
pointerMin = pointerMid + 1;
|
|
131
|
-
} else if (this.connections_[pointerMid].y > yPos) {
|
|
132
|
-
pointerMax = pointerMid;
|
|
133
|
-
} else {
|
|
134
|
-
pointerMin = pointerMid;
|
|
135
|
-
break;
|
|
106
|
+
pointer = bestGuess;
|
|
107
|
+
while (pointer < this.connections_.length &&
|
|
108
|
+
this.connections_[pointer].y === yPos) {
|
|
109
|
+
if (this.connections_[pointer] === conn) {
|
|
110
|
+
return pointer;
|
|
111
|
+
}
|
|
112
|
+
pointer++;
|
|
136
113
|
}
|
|
114
|
+
return -1;
|
|
137
115
|
}
|
|
138
|
-
return pointerMin;
|
|
139
|
-
};
|
|
140
116
|
|
|
141
|
-
/**
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Finds the correct index for the given y position.
|
|
119
|
+
* @param {number} yPos The y position used to decide where to
|
|
120
|
+
* insert the connection.
|
|
121
|
+
* @return {number} The candidate index.
|
|
122
|
+
* @private
|
|
123
|
+
*/
|
|
124
|
+
calculateIndexForYPos_(yPos) {
|
|
125
|
+
if (!this.connections_.length) {
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
let pointerMin = 0;
|
|
129
|
+
let pointerMax = this.connections_.length;
|
|
130
|
+
while (pointerMin < pointerMax) {
|
|
131
|
+
const pointerMid = Math.floor((pointerMin + pointerMax) / 2);
|
|
132
|
+
if (this.connections_[pointerMid].y < yPos) {
|
|
133
|
+
pointerMin = pointerMid + 1;
|
|
134
|
+
} else if (this.connections_[pointerMid].y > yPos) {
|
|
135
|
+
pointerMax = pointerMid;
|
|
136
|
+
} else {
|
|
137
|
+
pointerMin = pointerMid;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return pointerMin;
|
|
151
142
|
}
|
|
152
|
-
this.connections_.splice(index, 1);
|
|
153
|
-
};
|
|
154
143
|
|
|
155
|
-
/**
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const currentY = connection.y;
|
|
167
|
-
|
|
168
|
-
// Binary search to find the closest y location.
|
|
169
|
-
let pointerMin = 0;
|
|
170
|
-
let pointerMax = db.length - 2;
|
|
171
|
-
let pointerMid = pointerMax;
|
|
172
|
-
while (pointerMin < pointerMid) {
|
|
173
|
-
if (db[pointerMid].y < currentY) {
|
|
174
|
-
pointerMin = pointerMid;
|
|
175
|
-
} else {
|
|
176
|
-
pointerMax = pointerMid;
|
|
144
|
+
/**
|
|
145
|
+
* Remove a connection from the database. Must already exist in DB.
|
|
146
|
+
* @param {!RenderedConnection} connection The connection to be removed.
|
|
147
|
+
* @param {number} yPos The y position used to find the index of the
|
|
148
|
+
* connection.
|
|
149
|
+
* @throws {Error} If the connection cannot be found in the database.
|
|
150
|
+
*/
|
|
151
|
+
removeConnection(connection, yPos) {
|
|
152
|
+
const index = this.findIndexOfConnection_(connection, yPos);
|
|
153
|
+
if (index === -1) {
|
|
154
|
+
throw Error('Unable to find connection in connectionDB.');
|
|
177
155
|
}
|
|
178
|
-
|
|
156
|
+
this.connections_.splice(index, 1);
|
|
179
157
|
}
|
|
180
158
|
|
|
181
|
-
const neighbours = [];
|
|
182
159
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* @
|
|
188
|
-
*
|
|
160
|
+
* Find all nearby connections to the given connection.
|
|
161
|
+
* Type checking does not apply, since this function is used for bumping.
|
|
162
|
+
* @param {!RenderedConnection} connection The connection whose
|
|
163
|
+
* neighbours should be returned.
|
|
164
|
+
* @param {number} maxRadius The maximum radius to another connection.
|
|
165
|
+
* @return {!Array<!RenderedConnection>} List of connections.
|
|
189
166
|
*/
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
167
|
+
getNeighbours(connection, maxRadius) {
|
|
168
|
+
const db = this.connections_;
|
|
169
|
+
const currentX = connection.x;
|
|
170
|
+
const currentY = connection.y;
|
|
171
|
+
|
|
172
|
+
// Binary search to find the closest y location.
|
|
173
|
+
let pointerMin = 0;
|
|
174
|
+
let pointerMax = db.length - 2;
|
|
175
|
+
let pointerMid = pointerMax;
|
|
176
|
+
while (pointerMin < pointerMid) {
|
|
177
|
+
if (db[pointerMid].y < currentY) {
|
|
178
|
+
pointerMin = pointerMid;
|
|
179
|
+
} else {
|
|
180
|
+
pointerMax = pointerMid;
|
|
181
|
+
}
|
|
182
|
+
pointerMid = Math.floor((pointerMin + pointerMax) / 2);
|
|
196
183
|
}
|
|
197
|
-
return dy < maxRadius;
|
|
198
|
-
}
|
|
199
184
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
185
|
+
const neighbours = [];
|
|
186
|
+
/**
|
|
187
|
+
* Computes if the current connection is within the allowed radius of
|
|
188
|
+
* another connection. This function is a closure and has access to outside
|
|
189
|
+
* variables.
|
|
190
|
+
* @param {number} yIndex The other connection's index in the database.
|
|
191
|
+
* @return {boolean} True if the current connection's vertical distance from
|
|
192
|
+
* the other connection is less than the allowed radius.
|
|
193
|
+
*/
|
|
194
|
+
function checkConnection_(yIndex) {
|
|
195
|
+
const dx = currentX - db[yIndex].x;
|
|
196
|
+
const dy = currentY - db[yIndex].y;
|
|
197
|
+
const r = Math.sqrt(dx * dx + dy * dy);
|
|
198
|
+
if (r <= maxRadius) {
|
|
199
|
+
neighbours.push(db[yIndex]);
|
|
200
|
+
}
|
|
201
|
+
return dy < maxRadius;
|
|
206
202
|
}
|
|
207
|
-
do {
|
|
208
|
-
pointerMax++;
|
|
209
|
-
} while (pointerMax < db.length && checkConnection_(pointerMax));
|
|
210
|
-
}
|
|
211
203
|
|
|
212
|
-
|
|
213
|
-
|
|
204
|
+
// Walk forward and back on the y axis looking for the closest x,y point.
|
|
205
|
+
pointerMin = pointerMid;
|
|
206
|
+
pointerMax = pointerMid;
|
|
207
|
+
if (db.length) {
|
|
208
|
+
while (pointerMin >= 0 && checkConnection_(pointerMin)) {
|
|
209
|
+
pointerMin--;
|
|
210
|
+
}
|
|
211
|
+
do {
|
|
212
|
+
pointerMax++;
|
|
213
|
+
} while (pointerMax < db.length && checkConnection_(pointerMax));
|
|
214
|
+
}
|
|
214
215
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
* Extremely fast; only looks at Y distance.
|
|
218
|
-
* @param {number} index Index in database of candidate connection.
|
|
219
|
-
* @param {number} baseY Reference connection's Y value.
|
|
220
|
-
* @param {number} maxRadius The maximum radius to another connection.
|
|
221
|
-
* @return {boolean} True if connection is in range.
|
|
222
|
-
* @private
|
|
223
|
-
*/
|
|
224
|
-
ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) {
|
|
225
|
-
return (Math.abs(this.connections_[index].y - baseY) <= maxRadius);
|
|
226
|
-
};
|
|
216
|
+
return neighbours;
|
|
217
|
+
}
|
|
227
218
|
|
|
228
|
-
/**
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
*/
|
|
240
|
-
ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, dxy) {
|
|
241
|
-
if (!this.connections_.length) {
|
|
242
|
-
// Don't bother.
|
|
243
|
-
return {connection: null, radius: maxRadius};
|
|
219
|
+
/**
|
|
220
|
+
* Is the candidate connection close to the reference connection.
|
|
221
|
+
* Extremely fast; only looks at Y distance.
|
|
222
|
+
* @param {number} index Index in database of candidate connection.
|
|
223
|
+
* @param {number} baseY Reference connection's Y value.
|
|
224
|
+
* @param {number} maxRadius The maximum radius to another connection.
|
|
225
|
+
* @return {boolean} True if connection is in range.
|
|
226
|
+
* @private
|
|
227
|
+
*/
|
|
228
|
+
isInYRange_(index, baseY, maxRadius) {
|
|
229
|
+
return (Math.abs(this.connections_[index].y - baseY) <= maxRadius);
|
|
244
230
|
}
|
|
245
231
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Find the closest compatible connection to this connection.
|
|
234
|
+
* @param {!RenderedConnection} conn The connection searching for a compatible
|
|
235
|
+
* mate.
|
|
236
|
+
* @param {number} maxRadius The maximum radius to another connection.
|
|
237
|
+
* @param {!Coordinate} dxy Offset between this connection's
|
|
238
|
+
* location in the database and the current location (as a result of
|
|
239
|
+
* dragging).
|
|
240
|
+
* @return {!{connection: RenderedConnection, radius: number}}
|
|
241
|
+
* Contains two properties: 'connection' which is either another
|
|
242
|
+
* connection or null, and 'radius' which is the distance.
|
|
243
|
+
*/
|
|
244
|
+
searchForClosest(conn, maxRadius, dxy) {
|
|
245
|
+
if (!this.connections_.length) {
|
|
246
|
+
// Don't bother.
|
|
247
|
+
return {connection: null, radius: maxRadius};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Stash the values of x and y from before the drag.
|
|
251
|
+
const baseY = conn.y;
|
|
252
|
+
const baseX = conn.x;
|
|
249
253
|
|
|
250
|
-
|
|
251
|
-
|
|
254
|
+
conn.x = baseX + dxy.x;
|
|
255
|
+
conn.y = baseY + dxy.y;
|
|
252
256
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
// calculateIndexForYPos_ finds an index for insertion, which is always
|
|
258
|
+
// after any block with the same y index. We want to search both forward
|
|
259
|
+
// and back, so search on both sides of the index.
|
|
260
|
+
const closestIndex = this.calculateIndexForYPos_(conn.y);
|
|
257
261
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
262
|
+
let bestConnection = null;
|
|
263
|
+
let bestRadius = maxRadius;
|
|
264
|
+
let temp;
|
|
261
265
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
266
|
+
// Walk forward and back on the y axis looking for the closest x,y point.
|
|
267
|
+
let pointerMin = closestIndex - 1;
|
|
268
|
+
while (pointerMin >= 0 && this.isInYRange_(pointerMin, conn.y, maxRadius)) {
|
|
269
|
+
temp = this.connections_[pointerMin];
|
|
270
|
+
if (this.connectionChecker_.canConnect(conn, temp, true, bestRadius)) {
|
|
271
|
+
bestConnection = temp;
|
|
272
|
+
bestRadius = temp.distanceFrom(conn);
|
|
273
|
+
}
|
|
274
|
+
pointerMin--;
|
|
269
275
|
}
|
|
270
|
-
pointerMin--;
|
|
271
|
-
}
|
|
272
276
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
let pointerMax = closestIndex;
|
|
278
|
+
while (pointerMax < this.connections_.length &&
|
|
279
|
+
this.isInYRange_(pointerMax, conn.y, maxRadius)) {
|
|
280
|
+
temp = this.connections_[pointerMax];
|
|
281
|
+
if (this.connectionChecker_.canConnect(conn, temp, true, bestRadius)) {
|
|
282
|
+
bestConnection = temp;
|
|
283
|
+
bestRadius = temp.distanceFrom(conn);
|
|
284
|
+
}
|
|
285
|
+
pointerMax++;
|
|
280
286
|
}
|
|
281
|
-
pointerMax++;
|
|
282
|
-
}
|
|
283
287
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
288
|
+
// Reset the values of x and y.
|
|
289
|
+
conn.x = baseX;
|
|
290
|
+
conn.y = baseY;
|
|
287
291
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
292
|
+
// If there were no valid connections, bestConnection will be null.
|
|
293
|
+
return {connection: bestConnection, radius: bestRadius};
|
|
294
|
+
}
|
|
291
295
|
|
|
292
|
-
/**
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
296
|
+
/**
|
|
297
|
+
* Initialize a set of connection DBs for a workspace.
|
|
298
|
+
* @param {!IConnectionChecker} checker The workspace's
|
|
299
|
+
* connection checker, used to decide if connections are valid during a
|
|
300
|
+
* drag.
|
|
301
|
+
* @return {!Array<!ConnectionDB>} Array of databases.
|
|
302
|
+
*/
|
|
303
|
+
static init(checker) {
|
|
304
|
+
// Create four databases, one for each connection type.
|
|
305
|
+
const dbList = [];
|
|
306
|
+
dbList[ConnectionType.INPUT_VALUE] = new ConnectionDB(checker);
|
|
307
|
+
dbList[ConnectionType.OUTPUT_VALUE] = new ConnectionDB(checker);
|
|
308
|
+
dbList[ConnectionType.NEXT_STATEMENT] = new ConnectionDB(checker);
|
|
309
|
+
dbList[ConnectionType.PREVIOUS_STATEMENT] = new ConnectionDB(checker);
|
|
310
|
+
return dbList;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
308
313
|
|
|
309
314
|
exports.ConnectionDB = ConnectionDB;
|
package/core/contextmenu.js
CHANGED
|
@@ -23,11 +23,13 @@ const clipboard = goog.require('Blockly.clipboard');
|
|
|
23
23
|
const deprecation = goog.require('Blockly.utils.deprecation');
|
|
24
24
|
const dom = goog.require('Blockly.utils.dom');
|
|
25
25
|
const eventUtils = goog.require('Blockly.Events.utils');
|
|
26
|
-
const internalConstants = goog.require('Blockly.internalConstants');
|
|
27
26
|
const userAgent = goog.require('Blockly.utils.userAgent');
|
|
28
27
|
const svgMath = goog.require('Blockly.utils.svgMath');
|
|
29
28
|
/* eslint-disable-next-line no-unused-vars */
|
|
30
29
|
const {Block} = goog.requireType('Blockly.Block');
|
|
30
|
+
/* eslint-disable-next-line no-unused-vars */
|
|
31
|
+
const {BlockSvg} = goog.requireType('Blockly.BlockSvg');
|
|
32
|
+
const {config} = goog.require('Blockly.config');
|
|
31
33
|
const {Coordinate} = goog.require('Blockly.utils.Coordinate');
|
|
32
34
|
const {MenuItem} = goog.require('Blockly.MenuItem');
|
|
33
35
|
const {Menu} = goog.require('Blockly.Menu');
|
|
@@ -262,15 +264,16 @@ const callbackFactory = function(block, xml) {
|
|
|
262
264
|
eventUtils.disable();
|
|
263
265
|
let newBlock;
|
|
264
266
|
try {
|
|
265
|
-
newBlock =
|
|
267
|
+
newBlock =
|
|
268
|
+
/** @type {!BlockSvg} */ (Xml.domToBlock(xml, block.workspace));
|
|
266
269
|
// Move the new block next to the old block.
|
|
267
270
|
const xy = block.getRelativeToSurfaceXY();
|
|
268
271
|
if (block.RTL) {
|
|
269
|
-
xy.x -=
|
|
272
|
+
xy.x -= config.snapRadius;
|
|
270
273
|
} else {
|
|
271
|
-
xy.x +=
|
|
274
|
+
xy.x += config.snapRadius;
|
|
272
275
|
}
|
|
273
|
-
xy.y +=
|
|
276
|
+
xy.y += config.snapRadius * 2;
|
|
274
277
|
newBlock.moveBy(xy.x, xy.y);
|
|
275
278
|
} finally {
|
|
276
279
|
eventUtils.enable();
|
|
@@ -339,7 +342,7 @@ exports.commentDuplicateOption = commentDuplicateOption;
|
|
|
339
342
|
* @alias Blockly.ContextMenu.workspaceCommentOption
|
|
340
343
|
*/
|
|
341
344
|
const workspaceCommentOption = function(ws, e) {
|
|
342
|
-
const WorkspaceCommentSvg = goog.module.get('Blockly.WorkspaceCommentSvg');
|
|
345
|
+
const {WorkspaceCommentSvg} = goog.module.get('Blockly.WorkspaceCommentSvg');
|
|
343
346
|
if (!WorkspaceCommentSvg) {
|
|
344
347
|
throw Error('Missing require for Blockly.WorkspaceCommentSvg');
|
|
345
348
|
}
|
|
@@ -239,8 +239,7 @@ const addDeletableBlocks_ = function(block, deleteList) {
|
|
|
239
239
|
if (block.isDeletable()) {
|
|
240
240
|
Array.prototype.push.apply(deleteList, block.getDescendants(false));
|
|
241
241
|
} else {
|
|
242
|
-
const children =
|
|
243
|
-
/** @type {!Array<!BlockSvg>} */ (block.getChildren(false));
|
|
242
|
+
const children = block.getChildren(false);
|
|
244
243
|
for (let i = 0; i < children.length; i++) {
|
|
245
244
|
addDeletableBlocks_(children[i], deleteList);
|
|
246
245
|
}
|