@blockdia/scratch-blocks 0.1.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.
Files changed (243) hide show
  1. package/.nvmrc +1 -0
  2. package/LICENSE +674 -0
  3. package/README.md +57 -0
  4. package/TRADEMARK +1 -0
  5. package/blockly_compressed_horizontal.js +2268 -0
  6. package/blockly_compressed_vertical.js +2296 -0
  7. package/blockly_uncompressed_horizontal.js +1212 -0
  8. package/blockly_uncompressed_vertical.js +1212 -0
  9. package/blocks_common/colour.js +61 -0
  10. package/blocks_common/math.js +159 -0
  11. package/blocks_common/matrix.js +54 -0
  12. package/blocks_common/note.js +58 -0
  13. package/blocks_common/text.js +57 -0
  14. package/blocks_compressed.js +37 -0
  15. package/blocks_compressed_horizontal.js +68 -0
  16. package/blocks_compressed_vertical.js +216 -0
  17. package/blocks_horizontal/control.js +212 -0
  18. package/blocks_horizontal/default_toolbox.js +139 -0
  19. package/blocks_horizontal/event.js +190 -0
  20. package/blocks_horizontal/wedo.js +325 -0
  21. package/blocks_vertical/control.js +532 -0
  22. package/blocks_vertical/data.js +666 -0
  23. package/blocks_vertical/default_toolbox.js +571 -0
  24. package/blocks_vertical/event.js +329 -0
  25. package/blocks_vertical/extensions.js +294 -0
  26. package/blocks_vertical/looks.js +591 -0
  27. package/blocks_vertical/motion.js +587 -0
  28. package/blocks_vertical/operators.js +470 -0
  29. package/blocks_vertical/procedures.js +1051 -0
  30. package/blocks_vertical/sensing.js +555 -0
  31. package/blocks_vertical/sound.js +246 -0
  32. package/blocks_vertical/vertical_extensions.js +289 -0
  33. package/build/gen_blocks.js +1 -0
  34. package/build/test_expect.js +1 -0
  35. package/build/test_input.js +1 -0
  36. package/build.py +647 -0
  37. package/cleanup.sh +101 -0
  38. package/core/block.js +1837 -0
  39. package/core/block_animations.js +107 -0
  40. package/core/block_drag_surface.js +299 -0
  41. package/core/block_dragger.js +424 -0
  42. package/core/block_events.js +531 -0
  43. package/core/block_render_svg_horizontal.js +892 -0
  44. package/core/block_render_svg_vertical.js +1734 -0
  45. package/core/block_svg.js +1355 -0
  46. package/core/blockly.js +620 -0
  47. package/core/blocks.js +37 -0
  48. package/core/bubble.js +664 -0
  49. package/core/bubble_dragger.js +285 -0
  50. package/core/colours.js +177 -0
  51. package/core/comment.js +293 -0
  52. package/core/comment_events.js +539 -0
  53. package/core/connection.js +776 -0
  54. package/core/connection_db.js +300 -0
  55. package/core/constants.js +408 -0
  56. package/core/contextmenu.js +534 -0
  57. package/core/css.js +1354 -0
  58. package/core/data_category.js +490 -0
  59. package/core/dragged_connection_manager.js +260 -0
  60. package/core/dropdowndiv.js +408 -0
  61. package/core/events.js +429 -0
  62. package/core/events_abstract.js +113 -0
  63. package/core/extensions.js +450 -0
  64. package/core/field.js +810 -0
  65. package/core/field_angle.js +410 -0
  66. package/core/field_checkbox.js +133 -0
  67. package/core/field_colour.js +253 -0
  68. package/core/field_colour_slider.js +387 -0
  69. package/core/field_date.js +353 -0
  70. package/core/field_dropdown.js +447 -0
  71. package/core/field_iconmenu.js +309 -0
  72. package/core/field_image.js +200 -0
  73. package/core/field_label.js +136 -0
  74. package/core/field_label_serializable.js +125 -0
  75. package/core/field_matrix.js +566 -0
  76. package/core/field_note.js +850 -0
  77. package/core/field_number.js +366 -0
  78. package/core/field_numberdropdown.js +77 -0
  79. package/core/field_textdropdown.js +164 -0
  80. package/core/field_textinput.js +675 -0
  81. package/core/field_textinput_removable.js +105 -0
  82. package/core/field_variable.js +385 -0
  83. package/core/field_variable_getter.js +185 -0
  84. package/core/field_vertical_separator.js +161 -0
  85. package/core/flyout_base.js +935 -0
  86. package/core/flyout_button.js +324 -0
  87. package/core/flyout_dragger.js +83 -0
  88. package/core/flyout_extension_category_header.js +159 -0
  89. package/core/flyout_horizontal.js +475 -0
  90. package/core/flyout_vertical.js +770 -0
  91. package/core/generator.js +426 -0
  92. package/core/gesture.js +1010 -0
  93. package/core/grid.js +227 -0
  94. package/core/icon.js +205 -0
  95. package/core/inject.js +496 -0
  96. package/core/input.js +285 -0
  97. package/core/insertion_marker_manager.js +678 -0
  98. package/core/intersection_observer.js +102 -0
  99. package/core/msg.js +62 -0
  100. package/core/mutator.js +426 -0
  101. package/core/names.js +198 -0
  102. package/core/options.js +244 -0
  103. package/core/procedures.js +739 -0
  104. package/core/rendered_connection.js +417 -0
  105. package/core/scratch_block_comment.js +646 -0
  106. package/core/scratch_blocks_utils.js +246 -0
  107. package/core/scratch_bubble.js +699 -0
  108. package/core/scratch_events.js +131 -0
  109. package/core/scratch_msgs.js +85 -0
  110. package/core/scrollbar.js +875 -0
  111. package/core/toolbox.js +803 -0
  112. package/core/tooltip.js +337 -0
  113. package/core/touch.js +226 -0
  114. package/core/trashcan.js +343 -0
  115. package/core/ui_events.js +91 -0
  116. package/core/ui_menu_utils.js +68 -0
  117. package/core/utils.js +825 -0
  118. package/core/variable_events.js +259 -0
  119. package/core/variable_map.js +415 -0
  120. package/core/variable_model.js +116 -0
  121. package/core/variables.js +674 -0
  122. package/core/warning.js +199 -0
  123. package/core/widgetdiv.js +344 -0
  124. package/core/workspace.js +673 -0
  125. package/core/workspace_audio.js +170 -0
  126. package/core/workspace_comment.js +426 -0
  127. package/core/workspace_comment_render_svg.js +706 -0
  128. package/core/workspace_comment_svg.js +609 -0
  129. package/core/workspace_drag_surface_svg.js +195 -0
  130. package/core/workspace_dragger.js +132 -0
  131. package/core/workspace_svg.js +2382 -0
  132. package/core/xml.js +930 -0
  133. package/core/zoom_controls.js +301 -0
  134. package/dist/horizontal.js +222 -0
  135. package/dist/vertical.js +222 -0
  136. package/dist/web/horizontal.js +232 -0
  137. package/dist/web/vertical.js +232 -0
  138. package/i18n/common.py +234 -0
  139. package/i18n/create_messages.py +162 -0
  140. package/i18n/create_scratch_msgs.js +69 -0
  141. package/i18n/dedup_json.py +73 -0
  142. package/i18n/js_to_json.js +46 -0
  143. package/i18n/js_to_json.py +136 -0
  144. package/i18n/json_to_js.js +52 -0
  145. package/i18n/json_to_js.py +185 -0
  146. package/i18n/sync_tx_translations.js +111 -0
  147. package/i18n/test_scratch_msgs.js +87 -0
  148. package/i18n/tests.py +47 -0
  149. package/i18n/xliff_to_json.py +232 -0
  150. package/local_build.sh +70 -0
  151. package/media/click.mp3 +0 -0
  152. package/media/click.ogg +0 -0
  153. package/media/click.wav +0 -0
  154. package/media/comment-arrow-down.svg +10 -0
  155. package/media/comment-arrow-up.svg +10 -0
  156. package/media/delete-x.svg +10 -0
  157. package/media/delete.mp3 +0 -0
  158. package/media/delete.ogg +0 -0
  159. package/media/delete.wav +0 -0
  160. package/media/dropdown-arrow-dark.svg +1 -0
  161. package/media/dropdown-arrow.svg +1 -0
  162. package/media/extensions/microbit-block-icon.svg +130 -0
  163. package/media/extensions/music-block-icon.svg +17 -0
  164. package/media/extensions/pen-block-icon.svg +19 -0
  165. package/media/extensions/wedo2-block-icon.svg +36 -0
  166. package/media/eyedropper.svg +22 -0
  167. package/media/green-flag.svg +17 -0
  168. package/media/handclosed.cur +0 -0
  169. package/media/handdelete.cur +0 -0
  170. package/media/handopen.cur +0 -0
  171. package/media/icons/arrow.svg +12 -0
  172. package/media/icons/arrow_button.svg +1 -0
  173. package/media/icons/control_forever.svg +1 -0
  174. package/media/icons/control_repeat.svg +1 -0
  175. package/media/icons/control_stop.svg +1 -0
  176. package/media/icons/control_wait.svg +1 -0
  177. package/media/icons/event_broadcast_blue.svg +1 -0
  178. package/media/icons/event_broadcast_coral.svg +1 -0
  179. package/media/icons/event_broadcast_green.svg +1 -0
  180. package/media/icons/event_broadcast_magenta.svg +1 -0
  181. package/media/icons/event_broadcast_orange.svg +1 -0
  182. package/media/icons/event_broadcast_purple.svg +1 -0
  183. package/media/icons/event_when-broadcast-received_blue.svg +1 -0
  184. package/media/icons/event_when-broadcast-received_coral.svg +1 -0
  185. package/media/icons/event_when-broadcast-received_green.svg +1 -0
  186. package/media/icons/event_when-broadcast-received_magenta.svg +1 -0
  187. package/media/icons/event_when-broadcast-received_orange.svg +1 -0
  188. package/media/icons/event_when-broadcast-received_purple.svg +1 -0
  189. package/media/icons/event_whenflagclicked.svg +1 -0
  190. package/media/icons/remove.svg +19 -0
  191. package/media/icons/set-led_blue.svg +1 -0
  192. package/media/icons/set-led_coral.svg +1 -0
  193. package/media/icons/set-led_green.svg +1 -0
  194. package/media/icons/set-led_magenta.svg +1 -0
  195. package/media/icons/set-led_mystery.svg +1 -0
  196. package/media/icons/set-led_orange.svg +1 -0
  197. package/media/icons/set-led_purple.svg +1 -0
  198. package/media/icons/set-led_white.svg +1 -0
  199. package/media/icons/set-led_yellow.svg +1 -0
  200. package/media/icons/wedo_motor-clockwise.svg +1 -0
  201. package/media/icons/wedo_motor-counterclockwise.svg +1 -0
  202. package/media/icons/wedo_motor-speed_fast.svg +1 -0
  203. package/media/icons/wedo_motor-speed_med.svg +1 -0
  204. package/media/icons/wedo_motor-speed_slow.svg +1 -0
  205. package/media/icons/wedo_when-distance_close.svg +1 -0
  206. package/media/icons/wedo_when-tilt-backward.svg +1 -0
  207. package/media/icons/wedo_when-tilt-forward.svg +1 -0
  208. package/media/icons/wedo_when-tilt-left.svg +1 -0
  209. package/media/icons/wedo_when-tilt-right.svg +1 -0
  210. package/media/icons/wedo_when-tilt.svg +1 -0
  211. package/media/repeat.svg +18 -0
  212. package/media/rotate-left.svg +1 -0
  213. package/media/rotate-right.svg +1 -0
  214. package/media/sprites.png +0 -0
  215. package/media/status-not-ready.svg +13 -0
  216. package/media/status-ready.svg +13 -0
  217. package/media/zoom-in.svg +1 -0
  218. package/media/zoom-out.svg +1 -0
  219. package/media/zoom-reset.svg +1 -0
  220. package/msg/js/en.js +290 -0
  221. package/msg/json/en.json +285 -0
  222. package/msg/messages.js +359 -0
  223. package/msg/scratch_msgs.js +22969 -0
  224. package/package.json +60 -0
  225. package/pull_from_blockly.sh +151 -0
  226. package/renovate.json5 +15 -0
  227. package/shim/blockly_compressed_horizontal-blocks_compressed.js +1 -0
  228. package/shim/blockly_compressed_horizontal.Blockly.js +1 -0
  229. package/shim/blockly_compressed_horizontal.goog.js +1 -0
  230. package/shim/blockly_compressed_horizontal.js +1 -0
  231. package/shim/blockly_compressed_vertical-blocks_compressed.js +1 -0
  232. package/shim/blockly_compressed_vertical.Blockly.js +1 -0
  233. package/shim/blockly_compressed_vertical.goog.js +1 -0
  234. package/shim/blockly_compressed_vertical.js +1 -0
  235. package/shim/blocks_compressed_horizontal-blockly_compressed_horizontal-messages.js +1 -0
  236. package/shim/blocks_compressed_horizontal.js +1 -0
  237. package/shim/blocks_compressed_vertical-blockly_compressed_vertical-messages.js +1 -0
  238. package/shim/blocks_compressed_vertical.js +1 -0
  239. package/shim/gh-pages.js +1 -0
  240. package/shim/horizontal.js +1 -0
  241. package/shim/index.js +17 -0
  242. package/shim/vertical.js +1 -0
  243. package/universal-python.js +82 -0
@@ -0,0 +1,475 @@
1
+ /**
2
+ * @license
3
+ * Visual Blocks Editor
4
+ *
5
+ * Copyright 2011 Google Inc.
6
+ * https://developers.google.com/blockly/
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */
20
+
21
+ /**
22
+ * @fileoverview Flyout tray containing blocks which may be created.
23
+ * @author fraser@google.com (Neil Fraser)
24
+ */
25
+ 'use strict';
26
+
27
+ goog.provide('Blockly.HorizontalFlyout');
28
+
29
+ goog.require('Blockly.Block');
30
+ goog.require('Blockly.Comment');
31
+ goog.require('Blockly.Events');
32
+ goog.require('Blockly.FlyoutButton');
33
+ goog.require('Blockly.Flyout');
34
+ goog.require('Blockly.WorkspaceSvg');
35
+ goog.require('goog.dom');
36
+ goog.require('goog.dom.animationFrame.polyfill');
37
+ goog.require('goog.events');
38
+ goog.require('goog.math.Rect');
39
+ goog.require('goog.userAgent');
40
+
41
+
42
+ /**
43
+ * Class for a flyout.
44
+ * @param {!Object} workspaceOptions Dictionary of options for the workspace.
45
+ * @extends {Blockly.Flyout}
46
+ * @constructor
47
+ */
48
+ Blockly.HorizontalFlyout = function(workspaceOptions) {
49
+ workspaceOptions.getMetrics = this.getMetrics_.bind(this);
50
+ workspaceOptions.setMetrics = this.setMetrics_.bind(this);
51
+
52
+ Blockly.HorizontalFlyout.superClass_.constructor.call(this, workspaceOptions);
53
+ /**
54
+ * Flyout should be laid out horizontally vs vertically.
55
+ * @type {boolean}
56
+ * @private
57
+ */
58
+ this.horizontalLayout_ = true;
59
+ };
60
+ goog.inherits(Blockly.HorizontalFlyout, Blockly.Flyout);
61
+
62
+ /**
63
+ * Return an object with all the metrics required to size scrollbars for the
64
+ * flyout. The following properties are computed:
65
+ * .viewHeight: Height of the visible rectangle,
66
+ * .viewWidth: Width of the visible rectangle,
67
+ * .contentHeight: Height of the contents,
68
+ * .contentWidth: Width of the contents,
69
+ * .viewTop: Offset of top edge of visible rectangle from parent,
70
+ * .contentTop: Offset of the top-most content from the y=0 coordinate,
71
+ * .absoluteTop: Top-edge of view.
72
+ * .viewLeft: Offset of the left edge of visible rectangle from parent,
73
+ * .contentLeft: Offset of the left-most content from the x=0 coordinate,
74
+ * .absoluteLeft: Left-edge of view.
75
+ * @return {Object} Contains size and position metrics of the flyout.
76
+ * @private
77
+ */
78
+ Blockly.HorizontalFlyout.prototype.getMetrics_ = function() {
79
+ if (!this.isVisible()) {
80
+ // Flyout is hidden.
81
+ return null;
82
+ }
83
+
84
+ try {
85
+ var optionBox = this.workspace_.getCanvas().getBBox();
86
+ } catch (e) {
87
+ // Firefox has trouble with hidden elements (Bug 528969).
88
+ var optionBox = {height: 0, y: 0, width: 0, x: 0};
89
+ }
90
+
91
+ var absoluteTop = this.SCROLLBAR_PADDING;
92
+ var absoluteLeft = this.SCROLLBAR_PADDING;
93
+ if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
94
+ absoluteTop = 0;
95
+ }
96
+ var viewHeight = this.height_;
97
+ if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) {
98
+ viewHeight += this.MARGIN;
99
+ }
100
+ var viewWidth = this.width_ - 2 * this.SCROLLBAR_PADDING;
101
+
102
+ var metrics = {
103
+ viewHeight: viewHeight,
104
+ viewWidth: viewWidth,
105
+ contentHeight: optionBox.height * this.workspace_.scale + 2 * this.MARGIN,
106
+ contentWidth: optionBox.width * this.workspace_.scale + 2 * this.MARGIN,
107
+ viewTop: -this.workspace_.scrollY,
108
+ viewLeft: -this.workspace_.scrollX,
109
+ contentTop: optionBox.y,
110
+ contentLeft: optionBox.x,
111
+ absoluteTop: absoluteTop,
112
+ absoluteLeft: absoluteLeft
113
+ };
114
+ return metrics;
115
+ };
116
+
117
+ /**
118
+ * Sets the translation of the flyout to match the scrollbars.
119
+ * @param {!Object} xyRatio Contains a y property which is a float
120
+ * between 0 and 1 specifying the degree of scrolling and a
121
+ * similar x property.
122
+ * @private
123
+ */
124
+ Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
125
+ var metrics = this.getMetrics_();
126
+ // This is a fix to an apparent race condition.
127
+ if (!metrics) {
128
+ return;
129
+ }
130
+
131
+ if (goog.isNumber(xyRatio.x)) {
132
+ this.workspace_.scrollX = -metrics.contentWidth * xyRatio.x;
133
+ }
134
+
135
+ this.workspace_.translate(this.workspace_.scrollX + metrics.absoluteLeft,
136
+ this.workspace_.scrollY + metrics.absoluteTop);
137
+
138
+ if (this.categoryScrollPositions) {
139
+ this.selectCategoryByScrollPosition(-this.workspace_.scrollX);
140
+ }
141
+ };
142
+
143
+ /**
144
+ * Move the flyout to the edge of the workspace.
145
+ */
146
+ Blockly.HorizontalFlyout.prototype.position = function() {
147
+ if (!this.isVisible()) {
148
+ return;
149
+ }
150
+ var targetWorkspaceMetrics = this.targetWorkspace_.getMetrics();
151
+ if (!targetWorkspaceMetrics) {
152
+ // Hidden components will return null.
153
+ return;
154
+ }
155
+ var edgeWidth = this.horizontalLayout_ ?
156
+ targetWorkspaceMetrics.viewWidth - 2 * this.CORNER_RADIUS :
157
+ this.width_ - this.CORNER_RADIUS;
158
+
159
+ var edgeHeight = this.horizontalLayout_ ?
160
+ this.height_ - this.CORNER_RADIUS :
161
+ targetWorkspaceMetrics.viewHeight - 2 * this.CORNER_RADIUS;
162
+
163
+ this.setBackgroundPath_(edgeWidth, edgeHeight);
164
+
165
+ var x = targetWorkspaceMetrics.absoluteLeft;
166
+ if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) {
167
+ x += targetWorkspaceMetrics.viewWidth;
168
+ x -= this.width_;
169
+ }
170
+
171
+ var y = targetWorkspaceMetrics.absoluteTop;
172
+ if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
173
+ y += targetWorkspaceMetrics.viewHeight;
174
+ y -= this.height_;
175
+ }
176
+
177
+ // Record the height for Blockly.Flyout.getMetrics_, or width if the layout is
178
+ // horizontal.
179
+ if (this.horizontalLayout_) {
180
+ this.width_ = targetWorkspaceMetrics.viewWidth;
181
+ } else {
182
+ this.height_ = targetWorkspaceMetrics.viewHeight;
183
+ }
184
+
185
+ this.svgGroup_.setAttribute("width", this.width_);
186
+ this.svgGroup_.setAttribute("height", this.height_);
187
+ var transform = 'translate(' + x + 'px,' + y + 'px)';
188
+ Blockly.utils.setCssTransform(this.svgGroup_, transform);
189
+
190
+ // Update the scrollbar (if one exists).
191
+ if (this.scrollbar_) {
192
+ // Set the scrollbars origin to be the top left of the flyout.
193
+ this.scrollbar_.setOrigin(x, y);
194
+ this.scrollbar_.resize();
195
+ }
196
+ // The blocks need to be visible in order to be laid out and measured correctly, but we don't
197
+ // want the flyout to show up until it's properly sized.
198
+ // Opacity is set to zero in show().
199
+ this.svgGroup_.style.opacity = 1;
200
+ };
201
+
202
+ /**
203
+ * Create and set the path for the visible boundaries of the flyout.
204
+ * @param {number} width The width of the flyout, not including the
205
+ * rounded corners.
206
+ * @param {number} height The height of the flyout, not including
207
+ * rounded corners.
208
+ * @private
209
+ */
210
+ Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function(width, height) {
211
+ var atTop = this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP;
212
+ // Start at top left.
213
+ var path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)];
214
+
215
+ if (atTop) {
216
+ // Top.
217
+ path.push('h', width + 2 * this.CORNER_RADIUS);
218
+ // Right.
219
+ path.push('v', height);
220
+ // Bottom.
221
+ path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
222
+ -this.CORNER_RADIUS, this.CORNER_RADIUS);
223
+ path.push('h', -1 * width);
224
+ // Left.
225
+ path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
226
+ -this.CORNER_RADIUS, -this.CORNER_RADIUS);
227
+ path.push('z');
228
+ } else {
229
+ // Top.
230
+ path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
231
+ this.CORNER_RADIUS, -this.CORNER_RADIUS);
232
+ path.push('h', width);
233
+ // Right.
234
+ path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1,
235
+ this.CORNER_RADIUS, this.CORNER_RADIUS);
236
+ path.push('v', height);
237
+ // Bottom.
238
+ path.push('h', -width - 2 * this.CORNER_RADIUS);
239
+ // Left.
240
+ path.push('z');
241
+ }
242
+ this.svgBackground_.setAttribute('d', path.join(' '));
243
+ };
244
+
245
+ /**
246
+ * Scroll the flyout to the top.
247
+ */
248
+ Blockly.HorizontalFlyout.prototype.scrollToStart = function() {
249
+ this.scrollbar_.set(this.RTL ? Infinity : 0);
250
+ };
251
+
252
+ /**
253
+ * Scroll the flyout to a position.
254
+ * @param {number} pos The targeted scroll position.
255
+ * @package
256
+ */
257
+ Blockly.HorizontalFlyout.prototype.scrollTo = function(pos) {
258
+ this.scrollTarget = pos * this.workspace_.scale;
259
+
260
+ // Make sure not to set the scroll target past the farthest point we can
261
+ // scroll to, i.e. the content width minus the view width
262
+ var metrics = this.workspace_.getMetrics();
263
+ var contentWidth = metrics.contentWidth;
264
+ var viewWidth = metrics.viewWidth;
265
+ this.scrollTarget = Math.min(this.scrollTarget, contentWidth - viewWidth);
266
+
267
+ this.startScrollAnimation();
268
+ };
269
+
270
+ /**
271
+ * Scroll the flyout.
272
+ * @param {!Event} e Mouse wheel scroll event.
273
+ * @private
274
+ */
275
+ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
276
+ // remove scrollTarget to stop auto scrolling in stepScrollAnimation
277
+ this.scrollTarget = null;
278
+
279
+ var delta = e.deltaX;
280
+
281
+ // If we're scrolling more vertically than horizontally, use the vertical
282
+ // scroll delta instead. This allows people using a mouse wheel (which can
283
+ // only scroll vertically) to scroll the horizontal flyout. It also allows
284
+ // trackpad users to scroll it by scrolling either horizontally or
285
+ // vertically.
286
+ if (Math.abs(e.deltaY) > Math.abs(delta)) {
287
+ delta = e.deltaY;
288
+ }
289
+
290
+ if (delta) {
291
+ // Firefox's mouse wheel deltas are a tenth that of Chrome/Safari.
292
+ // DeltaMode is 1 for a mouse wheel, but not for a trackpad scroll event
293
+ if (goog.userAgent.GECKO && (e.deltaMode === 1)) {
294
+ delta *= 10;
295
+ }
296
+ var metrics = this.getMetrics_();
297
+ var pos = metrics.viewLeft + delta;
298
+ var limit = metrics.contentWidth - metrics.viewWidth;
299
+ pos = Math.min(pos, limit);
300
+ pos = Math.max(pos, 0);
301
+ this.scrollbar_.set(pos);
302
+ // When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
303
+ Blockly.WidgetDiv.hide(true);
304
+ Blockly.DropDownDiv.hideWithoutAnimation();
305
+ }
306
+
307
+ // Don't scroll the page.
308
+ e.preventDefault();
309
+ // Don't propagate mousewheel event (zooming).
310
+ e.stopPropagation();
311
+ };
312
+
313
+ /**
314
+ * Lay out the blocks in the flyout.
315
+ * @param {!Array.<!Object>} contents The blocks and buttons to lay out.
316
+ * @param {!Array.<number>} gaps The visible gaps between blocks.
317
+ * @private
318
+ */
319
+ Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
320
+ this.workspace_.scale = this.targetWorkspace_.scale;
321
+ var margin = this.MARGIN;
322
+ var cursorX = margin;
323
+ var cursorY = margin;
324
+ if (this.RTL) {
325
+ contents = contents.reverse();
326
+ }
327
+
328
+ for (var i = 0, item; item = contents[i]; i++) {
329
+ if (item.type == 'block') {
330
+ var block = item.block;
331
+ var allBlocks = block.getDescendants(false);
332
+ for (var j = 0, child; child = allBlocks[j]; j++) {
333
+ // Mark blocks as being inside a flyout. This is used to detect and
334
+ // prevent the closure of the flyout if the user right-clicks on such a
335
+ // block.
336
+ child.isInFlyout = true;
337
+ }
338
+ var root = block.getSvgRoot();
339
+ var blockHW = block.getHeightWidth();
340
+
341
+ var moveX = cursorX;
342
+ if (this.RTL) {
343
+ moveX += blockHW.width;
344
+ }
345
+
346
+ block.moveBy(moveX, cursorY);
347
+ cursorX += blockHW.width + gaps[i];
348
+
349
+ // Create an invisible rectangle under the block to act as a button. Just
350
+ // using the block as a button is poor, since blocks have holes in them.
351
+ var rect = Blockly.utils.createSvgElement('rect', {'fill-opacity': 0}, null);
352
+ rect.tooltip = block;
353
+ Blockly.Tooltip.bindMouseEvents(rect);
354
+ // Add the rectangles under the blocks, so that the blocks' tooltips work.
355
+ this.workspace_.getCanvas().insertBefore(rect, block.getSvgRoot());
356
+ block.flyoutRect_ = rect;
357
+ this.backgroundButtons_[i] = rect;
358
+
359
+ this.addBlockListeners_(root, block, rect);
360
+ } else if (item.type == 'button') {
361
+ var button = item.button;
362
+ var buttonSvg = button.createDom();
363
+ button.moveTo(cursorX, cursorY);
364
+ button.show();
365
+ // Clicking on a flyout button or label is a lot like clicking on the
366
+ // flyout background.
367
+ this.listeners_.push(Blockly.bindEventWithChecks_(buttonSvg, 'mousedown',
368
+ this, this.onMouseDown_));
369
+
370
+
371
+ this.buttons_.push(button);
372
+ cursorX += (button.width + gaps[i]);
373
+ }
374
+ }
375
+ };
376
+
377
+ /**
378
+ * Determine if a drag delta is toward the workspace, based on the position
379
+ * and orientation of the flyout. This to decide if a new block should be
380
+ * created or if the flyout should scroll.
381
+ * @param {!goog.math.Coordinate} currentDragDeltaXY How far the pointer has
382
+ * moved from the position at mouse down, in pixel units.
383
+ * @return {boolean} true if the drag is toward the workspace.
384
+ * @package
385
+ */
386
+ Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function(currentDragDeltaXY) {
387
+ var dx = currentDragDeltaXY.x;
388
+ var dy = currentDragDeltaXY.y;
389
+ // Direction goes from -180 to 180, with 0 toward the right and 90 on top.
390
+ var dragDirection = Math.atan2(dy, dx) / Math.PI * 180;
391
+
392
+ var draggingTowardWorkspace = false;
393
+ var range = this.dragAngleRange_;
394
+ if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) {
395
+ // Horizontal at top.
396
+ if (dragDirection < 90 + range && dragDirection > 90 - range) {
397
+ draggingTowardWorkspace = true;
398
+ }
399
+ } else {
400
+ // Horizontal at bottom.
401
+ if (dragDirection > -90 - range && dragDirection < -90 + range) {
402
+ draggingTowardWorkspace = true;
403
+ }
404
+ }
405
+ return draggingTowardWorkspace;
406
+ };
407
+
408
+ /**
409
+ * Return the deletion rectangle for this flyout in viewport coordinates.
410
+ * @return {goog.math.Rect} Rectangle in which to delete.
411
+ */
412
+ Blockly.HorizontalFlyout.prototype.getClientRect = function() {
413
+ if (!this.svgGroup_) {
414
+ return null;
415
+ }
416
+
417
+ var flyoutRect = this.svgGroup_.getBoundingClientRect();
418
+ // BIG_NUM is offscreen padding so that blocks dragged beyond the shown flyout
419
+ // area are still deleted. Must be larger than the largest screen size,
420
+ // but be smaller than half Number.MAX_SAFE_INTEGER (not available on IE).
421
+ var BIG_NUM = 1000000000;
422
+ var y = flyoutRect.top;
423
+ var height = flyoutRect.height;
424
+
425
+ if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) {
426
+ return new goog.math.Rect(-BIG_NUM, y - BIG_NUM, BIG_NUM * 2,
427
+ BIG_NUM + height);
428
+ } else if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
429
+ return new goog.math.Rect(-BIG_NUM, y, BIG_NUM * 2,
430
+ BIG_NUM + height);
431
+ }
432
+ };
433
+
434
+ /**
435
+ * Compute height of flyout. Position button under each block.
436
+ * For RTL: Lay out the blocks right-aligned.
437
+ * @param {!Array<!Blockly.Block>} blocks The blocks to reflow.
438
+ */
439
+ Blockly.HorizontalFlyout.prototype.reflowInternal_ = function(blocks) {
440
+ this.workspace_.scale = this.targetWorkspace_.scale;
441
+ var flyoutHeight = 0;
442
+ for (var i = 0, block; block = blocks[i]; i++) {
443
+ flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height);
444
+ }
445
+ flyoutHeight += this.MARGIN * 1.5;
446
+ flyoutHeight *= this.workspace_.scale;
447
+ flyoutHeight += Blockly.Scrollbar.scrollbarThickness;
448
+ if (this.height_ != flyoutHeight) {
449
+ for (var i = 0, block; block = blocks[i]; i++) {
450
+ var blockHW = block.getHeightWidth();
451
+ if (block.flyoutRect_) {
452
+ block.flyoutRect_.setAttribute('width', blockHW.width);
453
+ block.flyoutRect_.setAttribute('height', blockHW.height);
454
+ // Rectangles behind blocks with output tabs are shifted a bit.
455
+ var blockXY = block.getRelativeToSurfaceXY();
456
+ block.flyoutRect_.setAttribute('y', blockXY.y);
457
+ block.flyoutRect_.setAttribute('x',
458
+ this.RTL ? blockXY.x - blockHW.width : blockXY.x);
459
+ // For hat blocks we want to shift them down by the hat height
460
+ // since the y coordinate is the corner, not the top of the hat.
461
+ var hatOffset =
462
+ block.startHat_ ? Blockly.BlockSvg.START_HAT_HEIGHT : 0;
463
+ if (hatOffset) {
464
+ block.moveBy(0, hatOffset);
465
+ }
466
+ block.flyoutRect_.setAttribute('y', blockXY.y);
467
+ }
468
+ }
469
+ // Record the height for .getMetrics_ and .position.
470
+ this.height_ = flyoutHeight;
471
+ // Call this since it is possible the trash and zoom buttons need
472
+ // to move. e.g. on a bottom positioned flyout when zoom is clicked.
473
+ this.targetWorkspace_.resize();
474
+ }
475
+ };