blockly 7.20211209.4 → 8.0.0
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 +852 -844
- package/blockly_compressed.js +669 -664
- 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 +41 -27
- package/blocks/text.js +22 -13
- package/blocks/variables.js +14 -3
- package/blocks/variables_dynamic.js +13 -3
- package/blocks_compressed.js +146 -141
- 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 +19 -9
- 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/dart_compressed.js +40 -43
- package/dart_compressed.js.map +1 -1
- 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/javascript_compressed.js +37 -39
- package/javascript_compressed.js.map +1 -1
- package/lua_compressed.js +39 -42
- package/lua_compressed.js.map +1 -1
- package/msg/az.js +2 -2
- package/msg/be.js +4 -4
- package/msg/cs.js +15 -15
- package/msg/de.js +1 -1
- package/msg/diq.js +1 -1
- package/msg/eo.js +1 -1
- package/msg/es.js +1 -1
- package/msg/fa.js +1 -1
- package/msg/fr.js +4 -4
- package/msg/he.js +1 -1
- package/msg/hr.js +2 -2
- package/msg/hy.js +2 -2
- package/msg/id.js +12 -12
- package/msg/inh.js +14 -14
- package/msg/ja.js +7 -7
- package/msg/lv.js +29 -29
- package/msg/pa.js +3 -3
- package/msg/smn.js +436 -0
- package/msg/te.js +1 -1
- package/msg/yue.js +1 -1
- package/msg/zh-hans.js +3 -3
- package/msg/zh-hant.js +3 -3
- package/package.json +7 -6
- package/php_compressed.js +38 -42
- package/php_compressed.js.map +1 -1
- package/python_compressed.js +26 -25
- package/python_compressed.js.map +1 -1
- package/blocks/all.js +0 -23
|
@@ -57,711 +57,719 @@ const {inputTypes} = goog.require('Blockly.inputTypes');
|
|
|
57
57
|
* This measure pass does not propagate changes to the block (although fields
|
|
58
58
|
* may choose to rerender when getSize() is called). However, calling it
|
|
59
59
|
* repeatedly may be expensive.
|
|
60
|
-
*
|
|
61
|
-
* @param {!Renderer} renderer The renderer in use.
|
|
62
|
-
* @param {!BlockSvg} block The block to measure.
|
|
63
|
-
* @constructor
|
|
64
|
-
* @package
|
|
65
60
|
* @alias Blockly.blockRendering.RenderInfo
|
|
66
61
|
*/
|
|
67
|
-
|
|
68
|
-
this.block_ = block;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* The block renderer in use.
|
|
72
|
-
* @type {!Renderer}
|
|
73
|
-
* @protected
|
|
74
|
-
*/
|
|
75
|
-
this.renderer_ = renderer;
|
|
76
|
-
|
|
62
|
+
class RenderInfo {
|
|
77
63
|
/**
|
|
78
|
-
* The renderer
|
|
79
|
-
* @
|
|
80
|
-
* @
|
|
64
|
+
* @param {!Renderer} renderer The renderer in use.
|
|
65
|
+
* @param {!BlockSvg} block The block to measure.
|
|
66
|
+
* @package
|
|
81
67
|
*/
|
|
82
|
-
|
|
68
|
+
constructor(renderer, block) {
|
|
69
|
+
this.block_ = block;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The block renderer in use.
|
|
73
|
+
* @type {!Renderer}
|
|
74
|
+
* @protected
|
|
75
|
+
*/
|
|
76
|
+
this.renderer_ = renderer;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The renderer's constant provider.
|
|
80
|
+
* @type {!ConstantProvider}
|
|
81
|
+
* @protected
|
|
82
|
+
*/
|
|
83
|
+
this.constants_ = this.renderer_.getConstants();
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A measurable representing the output connection if the block has one.
|
|
87
|
+
* Otherwise null.
|
|
88
|
+
* @type {OutputConnection}
|
|
89
|
+
*/
|
|
90
|
+
this.outputConnection = !block.outputConnection ?
|
|
91
|
+
null :
|
|
92
|
+
new OutputConnection(
|
|
93
|
+
this.constants_,
|
|
94
|
+
/** @type {!RenderedConnection} */ (block.outputConnection));
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Whether the block should be rendered as a single line, either because
|
|
98
|
+
* it's inline or because it has been collapsed.
|
|
99
|
+
* @type {boolean}
|
|
100
|
+
*/
|
|
101
|
+
this.isInline = block.getInputsInline() && !block.isCollapsed();
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Whether the block is collapsed.
|
|
105
|
+
* @type {boolean}
|
|
106
|
+
*/
|
|
107
|
+
this.isCollapsed = block.isCollapsed();
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Whether the block is an insertion marker. Insertion markers are the same
|
|
111
|
+
* shape as normal blocks, but don't show fields.
|
|
112
|
+
* @type {boolean}
|
|
113
|
+
*/
|
|
114
|
+
this.isInsertionMarker = block.isInsertionMarker();
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* True if the block should be rendered right-to-left.
|
|
118
|
+
* @type {boolean}
|
|
119
|
+
*/
|
|
120
|
+
this.RTL = block.RTL;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The height of the rendered block, including child blocks.
|
|
124
|
+
* @type {number}
|
|
125
|
+
*/
|
|
126
|
+
this.height = 0;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The width of the rendered block, including child blocks.
|
|
130
|
+
* @type {number}
|
|
131
|
+
*/
|
|
132
|
+
this.widthWithChildren = 0;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The width of the rendered block, excluding child blocks. This is the
|
|
136
|
+
* right edge of the block when rendered LTR.
|
|
137
|
+
* @type {number}
|
|
138
|
+
*/
|
|
139
|
+
this.width = 0;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
* @type {number}
|
|
144
|
+
*/
|
|
145
|
+
this.statementEdge = 0;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* An array of Row objects containing sizing information.
|
|
149
|
+
* @type {!Array<!Row>}
|
|
150
|
+
*/
|
|
151
|
+
this.rows = [];
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* An array of input rows on the block.
|
|
155
|
+
* @type {!Array<!InputRow>}
|
|
156
|
+
*/
|
|
157
|
+
this.inputRows = [];
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* An array of measurable objects containing hidden icons.
|
|
161
|
+
* @type {!Array<!Icon>}
|
|
162
|
+
*/
|
|
163
|
+
this.hiddenIcons = [];
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* An object with rendering information about the top row of the block.
|
|
167
|
+
* @type {!TopRow}
|
|
168
|
+
*/
|
|
169
|
+
this.topRow = new TopRow(this.constants_);
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* An object with rendering information about the bottom row of the block.
|
|
173
|
+
* @type {!BottomRow}
|
|
174
|
+
*/
|
|
175
|
+
this.bottomRow = new BottomRow(this.constants_);
|
|
176
|
+
|
|
177
|
+
// The position of the start point for drawing, relative to the block's
|
|
178
|
+
// location.
|
|
179
|
+
this.startX = 0;
|
|
180
|
+
this.startY = 0;
|
|
181
|
+
}
|
|
83
182
|
|
|
84
183
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* @
|
|
184
|
+
* Get the block renderer in use.
|
|
185
|
+
* @return {!Renderer} The block renderer in use.
|
|
186
|
+
* @package
|
|
88
187
|
*/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
this.constants_,
|
|
93
|
-
/** @type {RenderedConnection} */ (block.outputConnection));
|
|
188
|
+
getRenderer() {
|
|
189
|
+
return this.renderer_;
|
|
190
|
+
}
|
|
94
191
|
|
|
95
192
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
193
|
+
* Populate and return an object containing all sizing information needed to
|
|
194
|
+
* draw this block.
|
|
195
|
+
*
|
|
196
|
+
* This measure pass does not propagate changes to the block (although fields
|
|
197
|
+
* may choose to rerender when getSize() is called). However, calling it
|
|
198
|
+
* repeatedly may be expensive.
|
|
199
|
+
*
|
|
200
|
+
* @package
|
|
99
201
|
*/
|
|
100
|
-
|
|
202
|
+
measure() {
|
|
203
|
+
this.createRows_();
|
|
204
|
+
this.addElemSpacing_();
|
|
205
|
+
this.addRowSpacing_();
|
|
206
|
+
this.computeBounds_();
|
|
207
|
+
this.alignRowElements_();
|
|
208
|
+
this.finalize_();
|
|
209
|
+
}
|
|
101
210
|
|
|
102
211
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
212
|
+
* Create rows of Measurable objects representing all renderable parts of the
|
|
213
|
+
* block.
|
|
214
|
+
* @protected
|
|
105
215
|
*/
|
|
106
|
-
|
|
216
|
+
createRows_() {
|
|
217
|
+
this.populateTopRow_();
|
|
218
|
+
this.rows.push(this.topRow);
|
|
219
|
+
let activeRow = new InputRow(this.constants_);
|
|
220
|
+
this.inputRows.push(activeRow);
|
|
221
|
+
|
|
222
|
+
// Icons always go on the first row, before anything else.
|
|
223
|
+
const icons = this.block_.getIcons();
|
|
224
|
+
for (let i = 0, icon; (icon = icons[i]); i++) {
|
|
225
|
+
const iconInfo = new Icon(this.constants_, icon);
|
|
226
|
+
if (this.isCollapsed && icon.collapseHidden) {
|
|
227
|
+
this.hiddenIcons.push(iconInfo);
|
|
228
|
+
} else {
|
|
229
|
+
activeRow.elements.push(iconInfo);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
107
232
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
233
|
+
let lastInput = null;
|
|
234
|
+
// Loop across all of the inputs on the block, creating objects for anything
|
|
235
|
+
// that needs to be rendered and breaking the block up into visual rows.
|
|
236
|
+
for (let i = 0, input; (input = this.block_.inputList[i]); i++) {
|
|
237
|
+
if (!input.isVisible()) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (this.shouldStartNewRow_(input, lastInput)) {
|
|
241
|
+
// Finish this row and create a new one.
|
|
242
|
+
this.rows.push(activeRow);
|
|
243
|
+
activeRow = new InputRow(this.constants_);
|
|
244
|
+
this.inputRows.push(activeRow);
|
|
245
|
+
}
|
|
114
246
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
247
|
+
// All of the fields in an input go on the same row.
|
|
248
|
+
for (let j = 0, field; (field = input.fieldRow[j]); j++) {
|
|
249
|
+
activeRow.elements.push(new Field(this.constants_, field, input));
|
|
250
|
+
}
|
|
251
|
+
this.addInput_(input, activeRow);
|
|
252
|
+
lastInput = input;
|
|
253
|
+
}
|
|
120
254
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.height = 0;
|
|
255
|
+
if (this.isCollapsed) {
|
|
256
|
+
activeRow.hasJaggedEdge = true;
|
|
257
|
+
activeRow.elements.push(new JaggedEdge(this.constants_));
|
|
258
|
+
}
|
|
126
259
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
260
|
+
if (activeRow.elements.length || activeRow.hasDummyInput) {
|
|
261
|
+
this.rows.push(activeRow);
|
|
262
|
+
}
|
|
263
|
+
this.populateBottomRow_();
|
|
264
|
+
this.rows.push(this.bottomRow);
|
|
265
|
+
}
|
|
132
266
|
|
|
133
267
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
* @type {number}
|
|
268
|
+
* Create all non-spacer elements that belong on the top row.
|
|
269
|
+
* @package
|
|
137
270
|
*/
|
|
138
|
-
|
|
271
|
+
populateTopRow_() {
|
|
272
|
+
const hasPrevious = !!this.block_.previousConnection;
|
|
273
|
+
const hasHat = (this.block_.hat ? this.block_.hat === 'cap' :
|
|
274
|
+
this.constants_.ADD_START_HATS) &&
|
|
275
|
+
!this.outputConnection && !hasPrevious;
|
|
276
|
+
|
|
277
|
+
let cornerClass = this.topRow.hasLeftSquareCorner(this.block_) ?
|
|
278
|
+
SquareCorner :
|
|
279
|
+
RoundCorner;
|
|
280
|
+
this.topRow.elements.push(new cornerClass(this.constants_));
|
|
281
|
+
|
|
282
|
+
if (hasHat) {
|
|
283
|
+
const hat = new Hat(this.constants_);
|
|
284
|
+
this.topRow.elements.push(hat);
|
|
285
|
+
this.topRow.capline = hat.ascenderHeight;
|
|
286
|
+
} else if (hasPrevious) {
|
|
287
|
+
this.topRow.hasPreviousConnection = true;
|
|
288
|
+
this.topRow.connection = new PreviousConnection(
|
|
289
|
+
this.constants_,
|
|
290
|
+
/** @type {!RenderedConnection} */
|
|
291
|
+
(this.block_.previousConnection));
|
|
292
|
+
this.topRow.elements.push(this.topRow.connection);
|
|
293
|
+
}
|
|
139
294
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
* @type {number}
|
|
143
|
-
*/
|
|
144
|
-
this.statementEdge = 0;
|
|
295
|
+
const precedesStatement = this.block_.inputList.length &&
|
|
296
|
+
this.block_.inputList[0].type === inputTypes.STATEMENT;
|
|
145
297
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
298
|
+
// This is the minimum height for the row. If one of its elements has a
|
|
299
|
+
// greater height it will be overwritten in the compute pass.
|
|
300
|
+
if (precedesStatement && !this.block_.isCollapsed()) {
|
|
301
|
+
this.topRow.minHeight =
|
|
302
|
+
this.constants_.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT;
|
|
303
|
+
} else {
|
|
304
|
+
this.topRow.minHeight = this.constants_.TOP_ROW_MIN_HEIGHT;
|
|
305
|
+
}
|
|
151
306
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
this.inputRows = [];
|
|
307
|
+
cornerClass = this.topRow.hasRightSquareCorner(this.block_) ? SquareCorner :
|
|
308
|
+
RoundCorner;
|
|
309
|
+
this.topRow.elements.push(new cornerClass(this.constants_, 'right'));
|
|
310
|
+
}
|
|
157
311
|
|
|
158
312
|
/**
|
|
159
|
-
*
|
|
160
|
-
* @
|
|
313
|
+
* Create all non-spacer elements that belong on the bottom row.
|
|
314
|
+
* @package
|
|
161
315
|
*/
|
|
162
|
-
|
|
316
|
+
populateBottomRow_() {
|
|
317
|
+
this.bottomRow.hasNextConnection = !!this.block_.nextConnection;
|
|
318
|
+
|
|
319
|
+
const followsStatement = this.block_.inputList.length &&
|
|
320
|
+
this.block_.inputList[this.block_.inputList.length - 1].type ===
|
|
321
|
+
inputTypes.STATEMENT;
|
|
322
|
+
|
|
323
|
+
// This is the minimum height for the row. If one of its elements has a
|
|
324
|
+
// greater height it will be overwritten in the compute pass.
|
|
325
|
+
if (followsStatement) {
|
|
326
|
+
this.bottomRow.minHeight =
|
|
327
|
+
this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT;
|
|
328
|
+
} else {
|
|
329
|
+
this.bottomRow.minHeight = this.constants_.BOTTOM_ROW_MIN_HEIGHT;
|
|
330
|
+
}
|
|
163
331
|
|
|
164
|
-
|
|
165
|
-
* An object with rendering information about the top row of the block.
|
|
166
|
-
* @type {!TopRow}
|
|
167
|
-
*/
|
|
168
|
-
this.topRow = new TopRow(this.constants_);
|
|
332
|
+
const leftSquareCorner = this.bottomRow.hasLeftSquareCorner(this.block_);
|
|
169
333
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
334
|
+
if (leftSquareCorner) {
|
|
335
|
+
this.bottomRow.elements.push(new SquareCorner(this.constants_));
|
|
336
|
+
} else {
|
|
337
|
+
this.bottomRow.elements.push(new RoundCorner(this.constants_));
|
|
338
|
+
}
|
|
175
339
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
340
|
+
if (this.bottomRow.hasNextConnection) {
|
|
341
|
+
this.bottomRow.connection = new NextConnection(
|
|
342
|
+
this.constants_,
|
|
343
|
+
/** @type {!RenderedConnection} */ (this.block_.nextConnection));
|
|
344
|
+
this.bottomRow.elements.push(this.bottomRow.connection);
|
|
345
|
+
}
|
|
181
346
|
|
|
182
|
-
|
|
183
|
-
* Get the block renderer in use.
|
|
184
|
-
* @return {!Renderer} The block renderer in use.
|
|
185
|
-
* @package
|
|
186
|
-
*/
|
|
187
|
-
RenderInfo.prototype.getRenderer = function() {
|
|
188
|
-
return this.renderer_;
|
|
189
|
-
};
|
|
347
|
+
const rightSquareCorner = this.bottomRow.hasRightSquareCorner(this.block_);
|
|
190
348
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
* draw this block.
|
|
194
|
-
*
|
|
195
|
-
* This measure pass does not propagate changes to the block (although fields
|
|
196
|
-
* may choose to rerender when getSize() is called). However, calling it
|
|
197
|
-
* repeatedly may be expensive.
|
|
198
|
-
*
|
|
199
|
-
* @package
|
|
200
|
-
*/
|
|
201
|
-
RenderInfo.prototype.measure = function() {
|
|
202
|
-
this.createRows_();
|
|
203
|
-
this.addElemSpacing_();
|
|
204
|
-
this.addRowSpacing_();
|
|
205
|
-
this.computeBounds_();
|
|
206
|
-
this.alignRowElements_();
|
|
207
|
-
this.finalize_();
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Create rows of Measurable objects representing all renderable parts of the
|
|
212
|
-
* block.
|
|
213
|
-
* @protected
|
|
214
|
-
*/
|
|
215
|
-
RenderInfo.prototype.createRows_ = function() {
|
|
216
|
-
this.populateTopRow_();
|
|
217
|
-
this.rows.push(this.topRow);
|
|
218
|
-
let activeRow = new InputRow(this.constants_);
|
|
219
|
-
this.inputRows.push(activeRow);
|
|
220
|
-
|
|
221
|
-
// Icons always go on the first row, before anything else.
|
|
222
|
-
const icons = this.block_.getIcons();
|
|
223
|
-
for (let i = 0, icon; (icon = icons[i]); i++) {
|
|
224
|
-
const iconInfo = new Icon(this.constants_, icon);
|
|
225
|
-
if (this.isCollapsed && icon.collapseHidden) {
|
|
226
|
-
this.hiddenIcons.push(iconInfo);
|
|
349
|
+
if (rightSquareCorner) {
|
|
350
|
+
this.bottomRow.elements.push(new SquareCorner(this.constants_, 'right'));
|
|
227
351
|
} else {
|
|
228
|
-
|
|
352
|
+
this.bottomRow.elements.push(new RoundCorner(this.constants_, 'right'));
|
|
229
353
|
}
|
|
230
354
|
}
|
|
231
355
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
356
|
+
/**
|
|
357
|
+
* Add an input element to the active row, if needed, and record the type of
|
|
358
|
+
* the input on the row.
|
|
359
|
+
* @param {!Input} input The input to record information about.
|
|
360
|
+
* @param {!Row} activeRow The row that is currently being
|
|
361
|
+
* populated.
|
|
362
|
+
* @protected
|
|
363
|
+
*/
|
|
364
|
+
addInput_(input, activeRow) {
|
|
365
|
+
// Non-dummy inputs have visual representations onscreen.
|
|
366
|
+
if (this.isInline && input.type === inputTypes.VALUE) {
|
|
367
|
+
activeRow.elements.push(new InlineInput(this.constants_, input));
|
|
368
|
+
activeRow.hasInlineInput = true;
|
|
369
|
+
} else if (input.type === inputTypes.STATEMENT) {
|
|
370
|
+
activeRow.elements.push(new StatementInput(this.constants_, input));
|
|
371
|
+
activeRow.hasStatement = true;
|
|
372
|
+
} else if (input.type === inputTypes.VALUE) {
|
|
373
|
+
activeRow.elements.push(new ExternalValueInput(this.constants_, input));
|
|
374
|
+
activeRow.hasExternalInput = true;
|
|
375
|
+
} else if (input.type === inputTypes.DUMMY) {
|
|
376
|
+
// Dummy inputs have no visual representation, but the information is
|
|
377
|
+
// still important.
|
|
378
|
+
activeRow.minHeight = Math.max(
|
|
379
|
+
activeRow.minHeight,
|
|
380
|
+
input.getSourceBlock() && input.getSourceBlock().isShadow() ?
|
|
381
|
+
this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT :
|
|
382
|
+
this.constants_.DUMMY_INPUT_MIN_HEIGHT);
|
|
383
|
+
activeRow.hasDummyInput = true;
|
|
244
384
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
for (let j = 0, field; (field = input.fieldRow[j]); j++) {
|
|
248
|
-
activeRow.elements.push(new Field(this.constants_, field, input));
|
|
385
|
+
if (activeRow.align === null) {
|
|
386
|
+
activeRow.align = input.align;
|
|
249
387
|
}
|
|
250
|
-
this.addInput_(input, activeRow);
|
|
251
|
-
lastInput = input;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (this.isCollapsed) {
|
|
255
|
-
activeRow.hasJaggedEdge = true;
|
|
256
|
-
activeRow.elements.push(new JaggedEdge(this.constants_));
|
|
257
388
|
}
|
|
258
389
|
|
|
259
|
-
|
|
260
|
-
|
|
390
|
+
/**
|
|
391
|
+
* Decide whether to start a new row between the two Blockly.Inputs.
|
|
392
|
+
* @param {!Input} input The first input to consider
|
|
393
|
+
* @param {Input} lastInput The input that follows.
|
|
394
|
+
* @return {boolean} True if the next input should be rendered on a new row.
|
|
395
|
+
* @protected
|
|
396
|
+
*/
|
|
397
|
+
shouldStartNewRow_(input, lastInput) {
|
|
398
|
+
// If this is the first input, just add to the existing row.
|
|
399
|
+
// That row is either empty or has some icons in it.
|
|
400
|
+
if (!lastInput) {
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
// A statement input or an input following one always gets a new row.
|
|
404
|
+
if (input.type === inputTypes.STATEMENT ||
|
|
405
|
+
lastInput.type === inputTypes.STATEMENT) {
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
// Value and dummy inputs get new row if inputs are not inlined.
|
|
409
|
+
if (input.type === inputTypes.VALUE || input.type === inputTypes.DUMMY) {
|
|
410
|
+
return !this.isInline;
|
|
411
|
+
}
|
|
412
|
+
return false;
|
|
261
413
|
}
|
|
262
|
-
this.populateBottomRow_();
|
|
263
|
-
this.rows.push(this.bottomRow);
|
|
264
|
-
};
|
|
265
414
|
|
|
266
|
-
/**
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
415
|
+
/**
|
|
416
|
+
* Add horizontal spacing between and around elements within each row.
|
|
417
|
+
* @protected
|
|
418
|
+
*/
|
|
419
|
+
addElemSpacing_() {
|
|
420
|
+
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
421
|
+
const oldElems = row.elements;
|
|
422
|
+
row.elements = [];
|
|
423
|
+
// No spacing needed before the corner on the top row or the bottom row.
|
|
424
|
+
if (row.startsWithElemSpacer()) {
|
|
425
|
+
// There's a spacer before the first element in the row.
|
|
426
|
+
row.elements.push(new InRowSpacer(
|
|
427
|
+
this.constants_, this.getInRowSpacing_(null, oldElems[0])));
|
|
428
|
+
}
|
|
429
|
+
if (!oldElems.length) {
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
for (let e = 0; e < oldElems.length - 1; e++) {
|
|
433
|
+
row.elements.push(oldElems[e]);
|
|
434
|
+
const spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]);
|
|
435
|
+
row.elements.push(new InRowSpacer(this.constants_, spacing));
|
|
436
|
+
}
|
|
437
|
+
row.elements.push(oldElems[oldElems.length - 1]);
|
|
438
|
+
if (row.endsWithElemSpacer()) {
|
|
439
|
+
// There's a spacer after the last element in the row.
|
|
440
|
+
row.elements.push(new InRowSpacer(
|
|
441
|
+
this.constants_,
|
|
442
|
+
this.getInRowSpacing_(oldElems[oldElems.length - 1], null)));
|
|
443
|
+
}
|
|
444
|
+
}
|
|
291
445
|
}
|
|
292
446
|
|
|
293
|
-
|
|
294
|
-
|
|
447
|
+
/**
|
|
448
|
+
* Calculate the width of a spacer element in a row based on the previous and
|
|
449
|
+
* next elements in that row. For instance, extra padding is added between
|
|
450
|
+
* two editable fields.
|
|
451
|
+
* @param {Measurable} prev The element before the
|
|
452
|
+
* spacer.
|
|
453
|
+
* @param {Measurable} next The element after the spacer.
|
|
454
|
+
* @return {number} The size of the spacing between the two elements.
|
|
455
|
+
* @protected
|
|
456
|
+
*/
|
|
457
|
+
getInRowSpacing_(prev, next) {
|
|
458
|
+
if (!prev) {
|
|
459
|
+
// Statement input padding.
|
|
460
|
+
if (next && Types.isStatementInput(next)) {
|
|
461
|
+
return this.constants_.STATEMENT_INPUT_PADDING_LEFT;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
// Between inputs and the end of the row.
|
|
465
|
+
if (prev && Types.isInput(prev) && !next) {
|
|
466
|
+
if (Types.isExternalInput(prev)) {
|
|
467
|
+
return this.constants_.NO_PADDING;
|
|
468
|
+
} else if (Types.isInlineInput(prev)) {
|
|
469
|
+
return this.constants_.LARGE_PADDING;
|
|
470
|
+
} else if (Types.isStatementInput(prev)) {
|
|
471
|
+
return this.constants_.NO_PADDING;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
295
474
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
this.topRow.minHeight = this.constants_.TOP_ROW_MIN_HEIGHT;
|
|
303
|
-
}
|
|
475
|
+
// Spacing between a square corner and a previous or next connection
|
|
476
|
+
if (prev && Types.isLeftSquareCorner(prev) && next) {
|
|
477
|
+
if (Types.isPreviousConnection(next) || Types.isNextConnection(next)) {
|
|
478
|
+
return next.notchOffset;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
304
481
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
482
|
+
// Spacing between a rounded corner and a previous or next connection.
|
|
483
|
+
if (prev && Types.isLeftRoundedCorner(prev) && next) {
|
|
484
|
+
if (Types.isPreviousConnection(next) || Types.isNextConnection(next)) {
|
|
485
|
+
return next.notchOffset - this.constants_.CORNER_RADIUS;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
309
488
|
|
|
310
|
-
|
|
311
|
-
* Create all non-spacer elements that belong on the bottom row.
|
|
312
|
-
* @package
|
|
313
|
-
*/
|
|
314
|
-
RenderInfo.prototype.populateBottomRow_ = function() {
|
|
315
|
-
this.bottomRow.hasNextConnection = !!this.block_.nextConnection;
|
|
316
|
-
|
|
317
|
-
const followsStatement = this.block_.inputList.length &&
|
|
318
|
-
this.block_.inputList[this.block_.inputList.length - 1].type ===
|
|
319
|
-
inputTypes.STATEMENT;
|
|
320
|
-
|
|
321
|
-
// This is the minimum height for the row. If one of its elements has a
|
|
322
|
-
// greater height it will be overwritten in the compute pass.
|
|
323
|
-
if (followsStatement) {
|
|
324
|
-
this.bottomRow.minHeight =
|
|
325
|
-
this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT;
|
|
326
|
-
} else {
|
|
327
|
-
this.bottomRow.minHeight = this.constants_.BOTTOM_ROW_MIN_HEIGHT;
|
|
489
|
+
return this.constants_.MEDIUM_PADDING;
|
|
328
490
|
}
|
|
329
491
|
|
|
330
|
-
|
|
492
|
+
/**
|
|
493
|
+
* Figure out where the right edge of the block and right edge of statement
|
|
494
|
+
* inputs should be placed.
|
|
495
|
+
* @protected
|
|
496
|
+
*/
|
|
497
|
+
computeBounds_() {
|
|
498
|
+
let widestStatementRowFields = 0;
|
|
499
|
+
let blockWidth = 0;
|
|
500
|
+
let widestRowWithConnectedBlocks = 0;
|
|
501
|
+
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
502
|
+
row.measure();
|
|
503
|
+
blockWidth = Math.max(blockWidth, row.width);
|
|
504
|
+
if (row.hasStatement) {
|
|
505
|
+
const statementInput = row.getLastInput();
|
|
506
|
+
const innerWidth = row.width - statementInput.width;
|
|
507
|
+
widestStatementRowFields =
|
|
508
|
+
Math.max(widestStatementRowFields, innerWidth);
|
|
509
|
+
}
|
|
510
|
+
widestRowWithConnectedBlocks =
|
|
511
|
+
Math.max(widestRowWithConnectedBlocks, row.widthWithConnectedBlocks);
|
|
512
|
+
}
|
|
331
513
|
|
|
332
|
-
|
|
333
|
-
this.
|
|
334
|
-
} else {
|
|
335
|
-
this.bottomRow.elements.push(new RoundCorner(this.constants_));
|
|
336
|
-
}
|
|
514
|
+
this.statementEdge = widestStatementRowFields;
|
|
515
|
+
this.width = blockWidth;
|
|
337
516
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
this.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}
|
|
517
|
+
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
518
|
+
if (row.hasStatement) {
|
|
519
|
+
row.statementEdge = this.statementEdge;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
344
522
|
|
|
345
|
-
|
|
523
|
+
this.widthWithChildren = Math.max(blockWidth, widestRowWithConnectedBlocks);
|
|
346
524
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
525
|
+
if (this.outputConnection) {
|
|
526
|
+
this.startX = this.outputConnection.width;
|
|
527
|
+
this.width += this.outputConnection.width;
|
|
528
|
+
this.widthWithChildren += this.outputConnection.width;
|
|
529
|
+
}
|
|
351
530
|
}
|
|
352
|
-
};
|
|
353
531
|
|
|
354
|
-
/**
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
activeRow.minHeight,
|
|
378
|
-
input.getSourceBlock() && input.getSourceBlock().isShadow() ?
|
|
379
|
-
this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT :
|
|
380
|
-
this.constants_.DUMMY_INPUT_MIN_HEIGHT);
|
|
381
|
-
activeRow.hasDummyInput = true;
|
|
382
|
-
}
|
|
383
|
-
if (activeRow.align === null) {
|
|
384
|
-
activeRow.align = input.align;
|
|
532
|
+
/**
|
|
533
|
+
* Extra spacing may be necessary to make sure that the right sides of all
|
|
534
|
+
* rows line up. This can only be calculated after a first pass to calculate
|
|
535
|
+
* the sizes of all rows.
|
|
536
|
+
* @protected
|
|
537
|
+
*/
|
|
538
|
+
alignRowElements_() {
|
|
539
|
+
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
540
|
+
if (row.hasStatement) {
|
|
541
|
+
this.alignStatementRow_(
|
|
542
|
+
/** @type {!InputRow} */ (row));
|
|
543
|
+
} else {
|
|
544
|
+
const currentWidth = row.width;
|
|
545
|
+
const desiredWidth = this.getDesiredRowWidth_(row);
|
|
546
|
+
const missingSpace = desiredWidth - currentWidth;
|
|
547
|
+
if (missingSpace > 0) {
|
|
548
|
+
this.addAlignmentPadding_(row, missingSpace);
|
|
549
|
+
}
|
|
550
|
+
if (Types.isTopOrBottomRow(row)) {
|
|
551
|
+
row.widthWithConnectedBlocks = row.width;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
385
555
|
}
|
|
386
|
-
};
|
|
387
556
|
|
|
388
|
-
/**
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
// If this is the first input, just add to the existing row.
|
|
397
|
-
// That row is either empty or has some icons in it.
|
|
398
|
-
if (!lastInput) {
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
|
-
// A statement input or an input following one always gets a new row.
|
|
402
|
-
if (input.type === inputTypes.STATEMENT ||
|
|
403
|
-
lastInput.type === inputTypes.STATEMENT) {
|
|
404
|
-
return true;
|
|
405
|
-
}
|
|
406
|
-
// Value and dummy inputs get new row if inputs are not inlined.
|
|
407
|
-
if (input.type === inputTypes.VALUE || input.type === inputTypes.DUMMY) {
|
|
408
|
-
return !this.isInline;
|
|
557
|
+
/**
|
|
558
|
+
* Calculate the desired width of an input row.
|
|
559
|
+
* @param {!Row} _row The input row.
|
|
560
|
+
* @return {number} The desired width of the input row.
|
|
561
|
+
* @protected
|
|
562
|
+
*/
|
|
563
|
+
getDesiredRowWidth_(_row) {
|
|
564
|
+
return this.width - this.startX;
|
|
409
565
|
}
|
|
410
|
-
return false;
|
|
411
|
-
};
|
|
412
566
|
|
|
413
|
-
/**
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
if (!oldElems.length) {
|
|
428
|
-
continue;
|
|
429
|
-
}
|
|
430
|
-
for (let e = 0; e < oldElems.length - 1; e++) {
|
|
431
|
-
row.elements.push(oldElems[e]);
|
|
432
|
-
const spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]);
|
|
433
|
-
row.elements.push(new InRowSpacer(this.constants_, spacing));
|
|
434
|
-
}
|
|
435
|
-
row.elements.push(oldElems[oldElems.length - 1]);
|
|
436
|
-
if (row.endsWithElemSpacer()) {
|
|
437
|
-
// There's a spacer after the last element in the row.
|
|
438
|
-
row.elements.push(new InRowSpacer(
|
|
439
|
-
this.constants_,
|
|
440
|
-
this.getInRowSpacing_(oldElems[oldElems.length - 1], null)));
|
|
567
|
+
/**
|
|
568
|
+
* Modify the given row to add the given amount of padding around its fields.
|
|
569
|
+
* The exact location of the padding is based on the alignment property of the
|
|
570
|
+
* last input in the field.
|
|
571
|
+
* @param {!Row} row The row to add padding to.
|
|
572
|
+
* @param {number} missingSpace How much padding to add.
|
|
573
|
+
* @protected
|
|
574
|
+
*/
|
|
575
|
+
addAlignmentPadding_(row, missingSpace) {
|
|
576
|
+
const firstSpacer = row.getFirstSpacer();
|
|
577
|
+
const lastSpacer = row.getLastSpacer();
|
|
578
|
+
if (row.hasExternalInput || row.hasStatement) {
|
|
579
|
+
row.widthWithConnectedBlocks += missingSpace;
|
|
441
580
|
}
|
|
442
|
-
}
|
|
443
|
-
};
|
|
444
581
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
return this.constants_.STATEMENT_INPUT_PADDING_LEFT;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
// Between inputs and the end of the row.
|
|
463
|
-
if (prev && Types.isInput(prev) && !next) {
|
|
464
|
-
if (Types.isExternalInput(prev)) {
|
|
465
|
-
return this.constants_.NO_PADDING;
|
|
466
|
-
} else if (Types.isInlineInput(prev)) {
|
|
467
|
-
return this.constants_.LARGE_PADDING;
|
|
468
|
-
} else if (Types.isStatementInput(prev)) {
|
|
469
|
-
return this.constants_.NO_PADDING;
|
|
582
|
+
// Decide where the extra padding goes.
|
|
583
|
+
if (row.align === Align.LEFT) {
|
|
584
|
+
// Add padding to the end of the row.
|
|
585
|
+
lastSpacer.width += missingSpace;
|
|
586
|
+
} else if (row.align === Align.CENTRE) {
|
|
587
|
+
// Split the padding between the beginning and end of the row.
|
|
588
|
+
firstSpacer.width += missingSpace / 2;
|
|
589
|
+
lastSpacer.width += missingSpace / 2;
|
|
590
|
+
} else if (row.align === Align.RIGHT) {
|
|
591
|
+
// Add padding at the beginning of the row.
|
|
592
|
+
firstSpacer.width += missingSpace;
|
|
593
|
+
} else {
|
|
594
|
+
// Default to left-aligning.
|
|
595
|
+
lastSpacer.width += missingSpace;
|
|
470
596
|
}
|
|
597
|
+
row.width += missingSpace;
|
|
471
598
|
}
|
|
472
599
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
600
|
+
/**
|
|
601
|
+
* Align the elements of a statement row based on computed bounds.
|
|
602
|
+
* Unlike other types of rows, statement rows add space in multiple places.
|
|
603
|
+
* @param {!InputRow} row The statement row to resize.
|
|
604
|
+
* @protected
|
|
605
|
+
*/
|
|
606
|
+
alignStatementRow_(row) {
|
|
607
|
+
const statementInput = row.getLastInput();
|
|
608
|
+
let currentWidth = row.width - statementInput.width;
|
|
609
|
+
let desiredWidth = this.statementEdge;
|
|
610
|
+
// Add padding before the statement input.
|
|
611
|
+
const missingSpace = desiredWidth - currentWidth;
|
|
612
|
+
if (missingSpace > 0) {
|
|
613
|
+
this.addAlignmentPadding_(row, missingSpace);
|
|
477
614
|
}
|
|
615
|
+
// Also widen the statement input to reach to the right side of the
|
|
616
|
+
// block. Note that this does not add padding.
|
|
617
|
+
currentWidth = row.width;
|
|
618
|
+
desiredWidth = this.getDesiredRowWidth_(row);
|
|
619
|
+
statementInput.width += (desiredWidth - currentWidth);
|
|
620
|
+
statementInput.height = Math.max(statementInput.height, row.height);
|
|
621
|
+
row.width += (desiredWidth - currentWidth);
|
|
622
|
+
row.widthWithConnectedBlocks =
|
|
623
|
+
Math.max(row.width, this.statementEdge + row.connectedBlockWidths);
|
|
478
624
|
}
|
|
479
625
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Add spacers between rows and set their sizes.
|
|
628
|
+
* @protected
|
|
629
|
+
*/
|
|
630
|
+
addRowSpacing_() {
|
|
631
|
+
const oldRows = this.rows;
|
|
632
|
+
this.rows = [];
|
|
633
|
+
|
|
634
|
+
for (let r = 0; r < oldRows.length; r++) {
|
|
635
|
+
this.rows.push(oldRows[r]);
|
|
636
|
+
if (r !== oldRows.length - 1) {
|
|
637
|
+
this.rows.push(this.makeSpacerRow_(oldRows[r], oldRows[r + 1]));
|
|
638
|
+
}
|
|
484
639
|
}
|
|
485
640
|
}
|
|
486
641
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
501
|
-
row.measure();
|
|
502
|
-
blockWidth = Math.max(blockWidth, row.width);
|
|
503
|
-
if (row.hasStatement) {
|
|
504
|
-
const statementInput = row.getLastInput();
|
|
505
|
-
const innerWidth = row.width - statementInput.width;
|
|
506
|
-
widestStatementRowFields = Math.max(widestStatementRowFields, innerWidth);
|
|
507
|
-
}
|
|
508
|
-
widestRowWithConnectedBlocks =
|
|
509
|
-
Math.max(widestRowWithConnectedBlocks, row.widthWithConnectedBlocks);
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
this.statementEdge = widestStatementRowFields;
|
|
513
|
-
this.width = blockWidth;
|
|
514
|
-
|
|
515
|
-
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
516
|
-
if (row.hasStatement) {
|
|
517
|
-
row.statementEdge = this.statementEdge;
|
|
642
|
+
/**
|
|
643
|
+
* Create a spacer row to go between prev and next, and set its size.
|
|
644
|
+
* @param {!Row} prev The previous row.
|
|
645
|
+
* @param {!Row} next The next row.
|
|
646
|
+
* @return {!SpacerRow} The newly created spacer row.
|
|
647
|
+
* @protected
|
|
648
|
+
*/
|
|
649
|
+
makeSpacerRow_(prev, next) {
|
|
650
|
+
const height = this.getSpacerRowHeight_(prev, next);
|
|
651
|
+
const width = this.getSpacerRowWidth_(prev, next);
|
|
652
|
+
const spacer = new SpacerRow(this.constants_, height, width);
|
|
653
|
+
if (prev.hasStatement) {
|
|
654
|
+
spacer.followsStatement = true;
|
|
518
655
|
}
|
|
656
|
+
if (next.hasStatement) {
|
|
657
|
+
spacer.precedesStatement = true;
|
|
658
|
+
}
|
|
659
|
+
return spacer;
|
|
519
660
|
}
|
|
520
661
|
|
|
521
|
-
|
|
662
|
+
/**
|
|
663
|
+
* Calculate the width of a spacer row.
|
|
664
|
+
* @param {!Row} _prev The row before the spacer.
|
|
665
|
+
* @param {!Row} _next The row after the spacer.
|
|
666
|
+
* @return {number} The desired width of the spacer row between these two
|
|
667
|
+
* rows.
|
|
668
|
+
* @protected
|
|
669
|
+
*/
|
|
670
|
+
getSpacerRowWidth_(_prev, _next) {
|
|
671
|
+
return this.width - this.startX;
|
|
672
|
+
}
|
|
522
673
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
674
|
+
/**
|
|
675
|
+
* Calculate the height of a spacer row.
|
|
676
|
+
* @param {!Row} _prev The row before the spacer.
|
|
677
|
+
* @param {!Row} _next The row after the spacer.
|
|
678
|
+
* @return {number} The desired height of the spacer row between these two
|
|
679
|
+
* rows.
|
|
680
|
+
* @protected
|
|
681
|
+
*/
|
|
682
|
+
getSpacerRowHeight_(_prev, _next) {
|
|
683
|
+
return this.constants_.MEDIUM_PADDING;
|
|
527
684
|
}
|
|
528
|
-
};
|
|
529
685
|
|
|
530
|
-
/**
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
686
|
+
/**
|
|
687
|
+
* Calculate the centerline of an element in a rendered row.
|
|
688
|
+
* This base implementation puts the centerline at the middle of the row
|
|
689
|
+
* vertically, with no special cases. You will likely need extra logic to
|
|
690
|
+
* handle (at minimum) top and bottom rows.
|
|
691
|
+
* @param {!Row} row The row containing the element.
|
|
692
|
+
* @param {!Measurable} elem The element to place.
|
|
693
|
+
* @return {number} The desired centerline of the given element, as an offset
|
|
694
|
+
* from the top left of the block.
|
|
695
|
+
* @protected
|
|
696
|
+
*/
|
|
697
|
+
getElemCenterline_(row, elem) {
|
|
698
|
+
if (Types.isSpacer(elem)) {
|
|
699
|
+
return row.yPos + elem.height / 2;
|
|
700
|
+
}
|
|
701
|
+
if (Types.isBottomRow(row)) {
|
|
702
|
+
const bottomRow = /** @type {!BottomRow} */ (row);
|
|
703
|
+
const baseline =
|
|
704
|
+
bottomRow.yPos + bottomRow.height - bottomRow.descenderHeight;
|
|
705
|
+
if (Types.isNextConnection(elem)) {
|
|
706
|
+
return baseline + elem.height / 2;
|
|
547
707
|
}
|
|
548
|
-
|
|
549
|
-
|
|
708
|
+
return baseline - elem.height / 2;
|
|
709
|
+
}
|
|
710
|
+
if (Types.isTopRow(row)) {
|
|
711
|
+
const topRow = /** @type {!TopRow} */ (row);
|
|
712
|
+
if (Types.isHat(elem)) {
|
|
713
|
+
return topRow.capline - elem.height / 2;
|
|
550
714
|
}
|
|
715
|
+
return topRow.capline + elem.height / 2;
|
|
551
716
|
}
|
|
552
|
-
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
/**
|
|
556
|
-
* Calculate the desired width of an input row.
|
|
557
|
-
* @param {!Row} _row The input row.
|
|
558
|
-
* @return {number} The desired width of the input row.
|
|
559
|
-
* @protected
|
|
560
|
-
*/
|
|
561
|
-
RenderInfo.prototype.getDesiredRowWidth_ = function(_row) {
|
|
562
|
-
return this.width - this.startX;
|
|
563
|
-
};
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Modify the given row to add the given amount of padding around its fields.
|
|
567
|
-
* The exact location of the padding is based on the alignment property of the
|
|
568
|
-
* last input in the field.
|
|
569
|
-
* @param {Row} row The row to add padding to.
|
|
570
|
-
* @param {number} missingSpace How much padding to add.
|
|
571
|
-
* @protected
|
|
572
|
-
*/
|
|
573
|
-
RenderInfo.prototype.addAlignmentPadding_ = function(row, missingSpace) {
|
|
574
|
-
const firstSpacer = row.getFirstSpacer();
|
|
575
|
-
const lastSpacer = row.getLastSpacer();
|
|
576
|
-
if (row.hasExternalInput || row.hasStatement) {
|
|
577
|
-
row.widthWithConnectedBlocks += missingSpace;
|
|
717
|
+
return row.yPos + row.height / 2;
|
|
578
718
|
}
|
|
579
719
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
/**
|
|
599
|
-
* Align the elements of a statement row based on computed bounds.
|
|
600
|
-
* Unlike other types of rows, statement rows add space in multiple places.
|
|
601
|
-
* @param {!InputRow} row The statement row to resize.
|
|
602
|
-
* @protected
|
|
603
|
-
*/
|
|
604
|
-
RenderInfo.prototype.alignStatementRow_ = function(row) {
|
|
605
|
-
const statementInput = row.getLastInput();
|
|
606
|
-
let currentWidth = row.width - statementInput.width;
|
|
607
|
-
let desiredWidth = this.statementEdge;
|
|
608
|
-
// Add padding before the statement input.
|
|
609
|
-
const missingSpace = desiredWidth - currentWidth;
|
|
610
|
-
if (missingSpace > 0) {
|
|
611
|
-
this.addAlignmentPadding_(row, missingSpace);
|
|
612
|
-
}
|
|
613
|
-
// Also widen the statement input to reach to the right side of the
|
|
614
|
-
// block. Note that this does not add padding.
|
|
615
|
-
currentWidth = row.width;
|
|
616
|
-
desiredWidth = this.getDesiredRowWidth_(row);
|
|
617
|
-
statementInput.width += (desiredWidth - currentWidth);
|
|
618
|
-
statementInput.height = Math.max(statementInput.height, row.height);
|
|
619
|
-
row.width += (desiredWidth - currentWidth);
|
|
620
|
-
row.widthWithConnectedBlocks =
|
|
621
|
-
Math.max(row.width, this.statementEdge + row.connectedBlockWidths);
|
|
622
|
-
};
|
|
623
|
-
|
|
624
|
-
/**
|
|
625
|
-
* Add spacers between rows and set their sizes.
|
|
626
|
-
* @protected
|
|
627
|
-
*/
|
|
628
|
-
RenderInfo.prototype.addRowSpacing_ = function() {
|
|
629
|
-
const oldRows = this.rows;
|
|
630
|
-
this.rows = [];
|
|
631
|
-
|
|
632
|
-
for (let r = 0; r < oldRows.length; r++) {
|
|
633
|
-
this.rows.push(oldRows[r]);
|
|
634
|
-
if (r !== oldRows.length - 1) {
|
|
635
|
-
this.rows.push(this.makeSpacerRow_(oldRows[r], oldRows[r + 1]));
|
|
720
|
+
/**
|
|
721
|
+
* Record final position information on elements on the given row, for use in
|
|
722
|
+
* drawing. At minimum this records xPos and centerline on each element.
|
|
723
|
+
* @param {!Row} row The row containing the elements.
|
|
724
|
+
* @protected
|
|
725
|
+
*/
|
|
726
|
+
recordElemPositions_(row) {
|
|
727
|
+
let xCursor = row.xPos;
|
|
728
|
+
for (let j = 0, elem; (elem = row.elements[j]); j++) {
|
|
729
|
+
// Now that row heights are finalized, make spacers use the row height.
|
|
730
|
+
if (Types.isSpacer(elem)) {
|
|
731
|
+
elem.height = row.height;
|
|
732
|
+
}
|
|
733
|
+
elem.xPos = xCursor;
|
|
734
|
+
elem.centerline = this.getElemCenterline_(row, elem);
|
|
735
|
+
xCursor += elem.width;
|
|
636
736
|
}
|
|
637
737
|
}
|
|
638
|
-
};
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* Create a spacer row to go between prev and next, and set its size.
|
|
642
|
-
* @param {!Row} prev The previous row.
|
|
643
|
-
* @param {!Row} next The next row.
|
|
644
|
-
* @return {!SpacerRow} The newly created spacer row.
|
|
645
|
-
* @protected
|
|
646
|
-
*/
|
|
647
|
-
RenderInfo.prototype.makeSpacerRow_ = function(prev, next) {
|
|
648
|
-
const height = this.getSpacerRowHeight_(prev, next);
|
|
649
|
-
const width = this.getSpacerRowWidth_(prev, next);
|
|
650
|
-
const spacer = new SpacerRow(this.constants_, height, width);
|
|
651
|
-
if (prev.hasStatement) {
|
|
652
|
-
spacer.followsStatement = true;
|
|
653
|
-
}
|
|
654
|
-
if (next.hasStatement) {
|
|
655
|
-
spacer.precedesStatement = true;
|
|
656
|
-
}
|
|
657
|
-
return spacer;
|
|
658
|
-
};
|
|
659
|
-
|
|
660
|
-
/**
|
|
661
|
-
* Calculate the width of a spacer row.
|
|
662
|
-
* @param {!Row} _prev The row before the spacer.
|
|
663
|
-
* @param {!Row} _next The row after the spacer.
|
|
664
|
-
* @return {number} The desired width of the spacer row between these two rows.
|
|
665
|
-
* @protected
|
|
666
|
-
*/
|
|
667
|
-
RenderInfo.prototype.getSpacerRowWidth_ = function(_prev, _next) {
|
|
668
|
-
return this.width - this.startX;
|
|
669
|
-
};
|
|
670
738
|
|
|
671
|
-
/**
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
* from the top left of the block.
|
|
691
|
-
* @protected
|
|
692
|
-
*/
|
|
693
|
-
RenderInfo.prototype.getElemCenterline_ = function(row, elem) {
|
|
694
|
-
if (Types.isSpacer(elem)) {
|
|
695
|
-
return row.yPos + elem.height / 2;
|
|
696
|
-
}
|
|
697
|
-
if (Types.isBottomRow(row)) {
|
|
698
|
-
const baseline = row.yPos + row.height - row.descenderHeight;
|
|
699
|
-
if (Types.isNextConnection(elem)) {
|
|
700
|
-
return baseline + elem.height / 2;
|
|
739
|
+
/**
|
|
740
|
+
* Make any final changes to the rendering information object. In particular,
|
|
741
|
+
* store the y position of each row, and record the height of the full block.
|
|
742
|
+
* @protected
|
|
743
|
+
*/
|
|
744
|
+
finalize_() {
|
|
745
|
+
// Performance note: this could be combined with the draw pass, if the time
|
|
746
|
+
// that this takes is excessive. But it shouldn't be, because it only
|
|
747
|
+
// accesses and sets properties that already exist on the objects.
|
|
748
|
+
let widestRowWithConnectedBlocks = 0;
|
|
749
|
+
let yCursor = 0;
|
|
750
|
+
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
751
|
+
row.yPos = yCursor;
|
|
752
|
+
row.xPos = this.startX;
|
|
753
|
+
yCursor += row.height;
|
|
754
|
+
|
|
755
|
+
widestRowWithConnectedBlocks =
|
|
756
|
+
Math.max(widestRowWithConnectedBlocks, row.widthWithConnectedBlocks);
|
|
757
|
+
this.recordElemPositions_(row);
|
|
701
758
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
759
|
+
if (this.outputConnection && this.block_.nextConnection &&
|
|
760
|
+
this.block_.nextConnection.isConnected()) {
|
|
761
|
+
// Include width of connected block in value to stack width measurement.
|
|
762
|
+
widestRowWithConnectedBlocks = Math.max(
|
|
763
|
+
widestRowWithConnectedBlocks,
|
|
764
|
+
this.block_.nextConnection.targetBlock().getHeightWidth().width);
|
|
707
765
|
}
|
|
708
|
-
return row.capline + elem.height / 2;
|
|
709
|
-
}
|
|
710
|
-
return row.yPos + row.height / 2;
|
|
711
|
-
};
|
|
712
766
|
|
|
713
|
-
|
|
714
|
-
* Record final position information on elements on the given row, for use in
|
|
715
|
-
* drawing. At minimum this records xPos and centerline on each element.
|
|
716
|
-
* @param {!Row} row The row containing the elements.
|
|
717
|
-
* @protected
|
|
718
|
-
*/
|
|
719
|
-
RenderInfo.prototype.recordElemPositions_ = function(row) {
|
|
720
|
-
let xCursor = row.xPos;
|
|
721
|
-
for (let j = 0, elem; (elem = row.elements[j]); j++) {
|
|
722
|
-
// Now that row heights are finalized, make spacers use the row height.
|
|
723
|
-
if (Types.isSpacer(elem)) {
|
|
724
|
-
elem.height = row.height;
|
|
725
|
-
}
|
|
726
|
-
elem.xPos = xCursor;
|
|
727
|
-
elem.centerline = this.getElemCenterline_(row, elem);
|
|
728
|
-
xCursor += elem.width;
|
|
729
|
-
}
|
|
730
|
-
};
|
|
767
|
+
this.widthWithChildren = widestRowWithConnectedBlocks + this.startX;
|
|
731
768
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
* @protected
|
|
736
|
-
*/
|
|
737
|
-
RenderInfo.prototype.finalize_ = function() {
|
|
738
|
-
// Performance note: this could be combined with the draw pass, if the time
|
|
739
|
-
// that this takes is excessive. But it shouldn't be, because it only
|
|
740
|
-
// accesses and sets properties that already exist on the objects.
|
|
741
|
-
let widestRowWithConnectedBlocks = 0;
|
|
742
|
-
let yCursor = 0;
|
|
743
|
-
for (let i = 0, row; (row = this.rows[i]); i++) {
|
|
744
|
-
row.yPos = yCursor;
|
|
745
|
-
row.xPos = this.startX;
|
|
746
|
-
yCursor += row.height;
|
|
747
|
-
|
|
748
|
-
widestRowWithConnectedBlocks =
|
|
749
|
-
Math.max(widestRowWithConnectedBlocks, row.widthWithConnectedBlocks);
|
|
750
|
-
this.recordElemPositions_(row);
|
|
769
|
+
this.height = yCursor;
|
|
770
|
+
this.startY = this.topRow.capline;
|
|
771
|
+
this.bottomRow.baseline = yCursor - this.bottomRow.descenderHeight;
|
|
751
772
|
}
|
|
752
|
-
|
|
753
|
-
this.block_.nextConnection.isConnected()) {
|
|
754
|
-
// Include width of connected block in value to stack width measurement.
|
|
755
|
-
widestRowWithConnectedBlocks = Math.max(
|
|
756
|
-
widestRowWithConnectedBlocks,
|
|
757
|
-
this.block_.nextConnection.targetBlock().getHeightWidth().width);
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
this.widthWithChildren = widestRowWithConnectedBlocks + this.startX;
|
|
761
|
-
|
|
762
|
-
this.height = yCursor;
|
|
763
|
-
this.startY = this.topRow.capline;
|
|
764
|
-
this.bottomRow.baseline = yCursor - this.bottomRow.descenderHeight;
|
|
765
|
-
};
|
|
773
|
+
}
|
|
766
774
|
|
|
767
775
|
exports.RenderInfo = RenderInfo;
|