@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,699 @@
1
+ /**
2
+ * @license
3
+ * Visual Blocks Editor
4
+ *
5
+ * Copyright 2018 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 Object representing a UI bubble.
23
+ * @author kchadha@scratch.mit.edu (Karishma Chadha)
24
+ */
25
+ 'use strict';
26
+
27
+ goog.provide('Blockly.ScratchBubble');
28
+
29
+ goog.require('Blockly.Touch');
30
+ goog.require('Blockly.Workspace');
31
+ goog.require('goog.dom');
32
+ goog.require('goog.math');
33
+ goog.require('goog.math.Coordinate');
34
+ goog.require('goog.userAgent');
35
+
36
+
37
+ /**
38
+ * Class for Scratch comment UI bubble.
39
+ * @param {!Blockly.ScratchBlockComment} comment The comment this bubble belongs
40
+ * to.
41
+ * @param {!Blockly.WorkspaceSvg} workspace The workspace on which to draw the
42
+ * bubble.
43
+ * @param {!Element} content SVG content for the bubble.
44
+ * @param {!goog.math.Coordinate} anchorXY Absolute position of bubble's anchor
45
+ * point.
46
+ * @param {?number} bubbleWidth Width of bubble, or null if not resizable.
47
+ * @param {?number} bubbleHeight Height of bubble, or null if not resizable.
48
+ * @param {?number} bubbleX X position of bubble
49
+ * @param {?number} bubbleY Y position of bubble
50
+ * @param {?boolean} minimized Whether or not this comment bubble is minimized
51
+ * (only the top bar displays), defaults to false if not provided.
52
+ * @extends {Blockly.Bubble}
53
+ * @constructor
54
+ */
55
+ Blockly.ScratchBubble = function(comment, workspace, content, anchorXY,
56
+ bubbleWidth, bubbleHeight, bubbleX, bubbleY, minimized) {
57
+
58
+ // Needed for Events
59
+ /**
60
+ * The comment this bubble belongs to.
61
+ * @type {Blockly.ScratchBlockComment}
62
+ * @package
63
+ */
64
+ this.comment = comment;
65
+
66
+ this.workspace_ = workspace;
67
+ this.content_ = content;
68
+ this.x = bubbleX;
69
+ this.y = bubbleY;
70
+ this.isMinimized_ = minimized || false;
71
+ var canvas = workspace.getBubbleCanvas();
72
+ canvas.appendChild(this.createDom_(content, !!(bubbleWidth && bubbleHeight),
73
+ this.isMinimized_));
74
+
75
+ this.setAnchorLocation(anchorXY);
76
+ if (!bubbleWidth || !bubbleHeight) {
77
+ var bBox = /** @type {SVGLocatable} */ (this.content_).getBBox();
78
+ bubbleWidth = bBox.width + 2 * Blockly.ScratchBubble.BORDER_WIDTH;
79
+ bubbleHeight = bBox.height + 2 * Blockly.ScratchBubble.BORDER_WIDTH;
80
+ }
81
+ this.setBubbleSize(bubbleWidth, bubbleHeight);
82
+
83
+ // Render the bubble.
84
+ this.positionBubble_();
85
+ this.renderArrow_();
86
+ this.rendered_ = true;
87
+
88
+ if (!workspace.options.readOnly) {
89
+ Blockly.bindEventWithChecks_(
90
+ this.minimizeArrow_, 'mousedown', this, this.minimizeArrowMouseDown_, true);
91
+ Blockly.bindEventWithChecks_(
92
+ this.minimizeArrow_, 'mouseout', this, this.minimizeArrowMouseOut_, true);
93
+ Blockly.bindEventWithChecks_(
94
+ this.minimizeArrow_, 'mouseup', this, this.minimizeArrowMouseUp_, true);
95
+ Blockly.bindEventWithChecks_(
96
+ this.deleteIcon_, 'mousedown', this, this.deleteMouseDown_, true);
97
+ Blockly.bindEventWithChecks_(
98
+ this.deleteIcon_, 'mouseout', this, this.deleteMouseOut_, true);
99
+ Blockly.bindEventWithChecks_(
100
+ this.deleteIcon_, 'mouseup', this, this.deleteMouseUp_, true);
101
+ Blockly.bindEventWithChecks_(
102
+ this.commentTopBar_, 'mousedown', this, this.bubbleMouseDown_);
103
+ Blockly.bindEventWithChecks_(
104
+ this.bubbleBack_, 'mousedown', this, this.bubbleMouseDown_);
105
+ if (this.resizeGroup_) {
106
+ Blockly.bindEventWithChecks_(
107
+ this.resizeGroup_, 'mousedown', this, this.resizeMouseDown_);
108
+ Blockly.bindEventWithChecks_(
109
+ this.resizeGroup_, 'mouseup', this, this.resizeMouseUp_);
110
+ }
111
+ }
112
+
113
+ this.setAutoLayout(false);
114
+ this.moveTo(this.x, this.y);
115
+ };
116
+ goog.inherits(Blockly.ScratchBubble, Blockly.Bubble);
117
+
118
+ /**
119
+ * Width of the border around the bubble.
120
+ * @package
121
+ */
122
+ Blockly.ScratchBubble.BORDER_WIDTH = 1;
123
+
124
+ /**
125
+ * Thickness of the line connecting the bubble
126
+ * to the block.
127
+ * @private
128
+ */
129
+ Blockly.ScratchBubble.LINE_THICKNESS = 1;
130
+
131
+ /**
132
+ * The height of the comment top bar.
133
+ * @package
134
+ */
135
+ Blockly.ScratchBubble.TOP_BAR_HEIGHT = 32;
136
+
137
+ /**
138
+ * The size of the minimize arrow icon in the comment top bar.
139
+ * @private
140
+ */
141
+ Blockly.ScratchBubble.MINIMIZE_ICON_SIZE = 32;
142
+
143
+ /**
144
+ * The size of the delete icon in the comment top bar.
145
+ * @private
146
+ */
147
+ Blockly.ScratchBubble.DELETE_ICON_SIZE = 32;
148
+
149
+ /**
150
+ * The inset for the top bar icons.
151
+ * @private
152
+ */
153
+ Blockly.ScratchBubble.TOP_BAR_ICON_INSET = 0;
154
+
155
+
156
+ /**
157
+ * The inset for the top bar icons.
158
+ * @private
159
+ */
160
+ Blockly.ScratchBubble.RESIZE_SIZE = 16;
161
+
162
+ /**
163
+ * The bottom corner padding of the resize handle touch target.
164
+ * Extends slightly outside the comment box.
165
+ * @private
166
+ */
167
+ Blockly.ScratchBubble.RESIZE_CORNER_PAD = 4;
168
+
169
+ /**
170
+ * The top/side padding around resize handle touch target.
171
+ * Extends about one extra "diagonal" above resize handle.
172
+ * @private
173
+ */
174
+ Blockly.ScratchBubble.RESIZE_OUTER_PAD = 8;
175
+
176
+ /**
177
+ * Create the bubble's DOM.
178
+ * @param {!Element} content SVG content for the bubble.
179
+ * @param {boolean} hasResize Add diagonal resize gripper if true.
180
+ * @param {boolean} minimized Whether the bubble is minimized
181
+ * @return {!Element} The bubble's SVG group.
182
+ * @private
183
+ */
184
+ Blockly.ScratchBubble.prototype.createDom_ = function(content, hasResize, minimized) {
185
+ this.bubbleGroup_ = Blockly.utils.createSvgElement('g', {}, null);
186
+ this.bubbleArrow_ = Blockly.utils.createSvgElement('line',
187
+ {'stroke-linecap': 'round'},
188
+ this.bubbleGroup_);
189
+ this.bubbleBack_ = Blockly.utils.createSvgElement('rect',
190
+ {
191
+ 'class': 'blocklyDraggable scratchCommentRect',
192
+ 'x': 0,
193
+ 'y': 0,
194
+ 'rx': 4 * Blockly.ScratchBubble.BORDER_WIDTH,
195
+ 'ry': 4 * Blockly.ScratchBubble.BORDER_WIDTH
196
+ },
197
+ this.bubbleGroup_);
198
+
199
+ this.labelText_ = content.labelText;
200
+ this.createCommentTopBar_();
201
+
202
+ // Comment Text Editor
203
+ this.commentEditor_ = content.commentEditor;
204
+ this.bubbleGroup_.appendChild(this.commentEditor_);
205
+
206
+ // Comment Resize Handle
207
+ if (hasResize) {
208
+ this.createResizeHandle_();
209
+ } else {
210
+ this.resizeGroup_ = null;
211
+ }
212
+
213
+ // Show / hide relevant things based on minimized state
214
+ if (minimized) {
215
+ this.minimizeArrow_.setAttributeNS('http://www.w3.org/1999/xlink',
216
+ 'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'comment-arrow-up.svg');
217
+ this.commentEditor_.setAttribute('display', 'none');
218
+ this.resizeGroup_.setAttribute('display', 'none');
219
+ } else {
220
+ this.minimizeArrow_.setAttributeNS('http://www.w3.org/1999/xlink',
221
+ 'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'comment-arrow-down.svg');
222
+ this.topBarLabel_.setAttribute('display', 'none');
223
+ }
224
+
225
+ return this.bubbleGroup_;
226
+ };
227
+
228
+ /**
229
+ * Create the comment top bar and its contents.
230
+ * @private
231
+ */
232
+ Blockly.ScratchBubble.prototype.createCommentTopBar_ = function() {
233
+ this.commentTopBar_ = Blockly.utils.createSvgElement('rect',
234
+ {
235
+ 'class': 'blocklyDraggable scratchCommentTopBar',
236
+ 'rx': Blockly.ScratchBubble.BORDER_WIDTH,
237
+ 'ry': Blockly.ScratchBubble.BORDER_WIDTH,
238
+ 'height': Blockly.ScratchBubble.TOP_BAR_HEIGHT
239
+ }, this.bubbleGroup_);
240
+
241
+ this.createTopBarIcons_();
242
+ this.createTopBarLabel_();
243
+ };
244
+
245
+ /**
246
+ * Create the minimize toggle and delete icons that in the comment top bar.
247
+ * @private
248
+ */
249
+ Blockly.ScratchBubble.prototype.createTopBarIcons_ = function() {
250
+ var topBarMiddleY = (Blockly.ScratchBubble.TOP_BAR_HEIGHT / 2) +
251
+ Blockly.ScratchBubble.BORDER_WIDTH;
252
+
253
+ // Minimize Toggle Icon in Comment Top Bar
254
+ var xInset = Blockly.ScratchBubble.TOP_BAR_ICON_INSET;
255
+ this.minimizeArrow_ = Blockly.utils.createSvgElement('image',
256
+ {
257
+ 'x': xInset,
258
+ 'y': topBarMiddleY - Blockly.ScratchBubble.MINIMIZE_ICON_SIZE / 2,
259
+ 'width': Blockly.ScratchBubble.MINIMIZE_ICON_SIZE,
260
+ 'height': Blockly.ScratchBubble.MINIMIZE_ICON_SIZE
261
+ }, this.bubbleGroup_);
262
+
263
+ // Delete Icon in Comment Top Bar
264
+ this.deleteIcon_ = Blockly.utils.createSvgElement('image',
265
+ {
266
+ 'x': xInset,
267
+ 'y': topBarMiddleY - Blockly.ScratchBubble.DELETE_ICON_SIZE / 2,
268
+ 'width': Blockly.ScratchBubble.DELETE_ICON_SIZE,
269
+ 'height': Blockly.ScratchBubble.DELETE_ICON_SIZE
270
+ }, this.bubbleGroup_);
271
+ this.deleteIcon_.setAttributeNS('http://www.w3.org/1999/xlink',
272
+ 'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'delete-x.svg');
273
+ };
274
+
275
+ /**
276
+ * Create the comment top bar label. This is the truncated comment text
277
+ * that shows when comment is minimized.
278
+ * @private
279
+ */
280
+ Blockly.ScratchBubble.prototype.createTopBarLabel_ = function() {
281
+ this.topBarLabel_ = Blockly.utils.createSvgElement('text',
282
+ {
283
+ 'class': 'scratchCommentText',
284
+ 'x': this.width_ / 2,
285
+ 'y': (Blockly.ScratchBubble.TOP_BAR_HEIGHT / 2) + Blockly.ScratchBubble.BORDER_WIDTH,
286
+ 'text-anchor': 'middle',
287
+ 'dominant-baseline': 'middle'
288
+ }, this.bubbleGroup_);
289
+
290
+ var labelTextNode = document.createTextNode(this.labelText_);
291
+ this.topBarLabel_.appendChild(labelTextNode);
292
+ };
293
+
294
+ /**
295
+ * Create the comment resize handle.
296
+ * @private
297
+ */
298
+ Blockly.ScratchBubble.prototype.createResizeHandle_ = function() {
299
+ this.resizeGroup_ = Blockly.utils.createSvgElement('g',
300
+ {'class': this.workspace_.RTL ?
301
+ 'scratchCommentResizeSW' : 'scratchCommentResizeSE'},
302
+ this.bubbleGroup_);
303
+ var resizeSize = Blockly.ScratchBubble.RESIZE_SIZE;
304
+ var outerPad = Blockly.ScratchBubble.RESIZE_OUTER_PAD;
305
+ var cornerPad = Blockly.ScratchBubble.RESIZE_CORNER_PAD;
306
+ // Build an (invisible) triangle that will catch resizes. It is padded on the
307
+ // top/left by outerPad, and padded down/right by cornerPad.
308
+ Blockly.utils.createSvgElement('polygon',
309
+ {
310
+ 'points': [
311
+ -outerPad, resizeSize + cornerPad,
312
+ resizeSize + cornerPad, resizeSize + cornerPad,
313
+ resizeSize + cornerPad, -outerPad
314
+ ].join(' ')
315
+ },
316
+ this.resizeGroup_);
317
+ Blockly.utils.createSvgElement('line',
318
+ {
319
+ 'class': 'blocklyResizeLine',
320
+ 'x1': resizeSize / 3, 'y1': resizeSize - 1,
321
+ 'x2': resizeSize - 1, 'y2': resizeSize / 3
322
+ }, this.resizeGroup_);
323
+ Blockly.utils.createSvgElement('line',
324
+ {
325
+ 'class': 'blocklyResizeLine',
326
+ 'x1': resizeSize * 2 / 3,
327
+ 'y1': resizeSize - 1,
328
+ 'x2': resizeSize - 1,
329
+ 'y2': resizeSize * 2 / 3
330
+ }, this.resizeGroup_);
331
+ };
332
+
333
+ /**
334
+ * Show the context menu for this bubble.
335
+ * @param {!Event} e Mouse event.
336
+ * @private
337
+ */
338
+ Blockly.ScratchBubble.prototype.showContextMenu_ = function(e) {
339
+ if (this.workspace_.options.readOnly) {
340
+ return;
341
+ }
342
+
343
+ if (this.contextMenuCallback_) {
344
+ this.contextMenuCallback_(e);
345
+ }
346
+ };
347
+
348
+ /**
349
+ * Handle a mouse-down on bubble's minimize icon.
350
+ * @param {!Event} e Mouse up event.
351
+ * @private
352
+ */
353
+ Blockly.ScratchBubble.prototype.minimizeArrowMouseDown_ = function(e) {
354
+ // Set a property indicating that this comment's minimize arrow got a mouse
355
+ // down event. This property will get reset if the mouse leaves the icon or
356
+ // when a mouse up occurs on this icon after this mouse down.
357
+ this.shouldToggleMinimize_ = true;
358
+ e.stopPropagation();
359
+ };
360
+
361
+ /**
362
+ * Handle a mouse-out on bubble's minimize icon.
363
+ * @param {!Event} _e Mouse up event.
364
+ * @private
365
+ */
366
+ Blockly.ScratchBubble.prototype.minimizeArrowMouseOut_ = function(_e) {
367
+ // If the mouse has left the minimize arrow icon, the
368
+ // shouldToggleMinimize property should get reset to false.
369
+ this.shouldToggleMinimize_ = false;
370
+ };
371
+
372
+ /**
373
+ * Handle a mouse-up on bubble's minimize icon.
374
+ * @param {!Event} e Mouse up event.
375
+ * @private
376
+ */
377
+ Blockly.ScratchBubble.prototype.minimizeArrowMouseUp_ = function(e) {
378
+ // First check if this icon had a mouse down event
379
+ // on it and that the mouse never left the icon
380
+ if (this.shouldToggleMinimize_) {
381
+ this.shouldToggleMinimize_ = false;
382
+
383
+ if (this.minimizeToggleCallback_) {
384
+ this.minimizeToggleCallback_.call(this);
385
+ }
386
+ }
387
+ e.stopPropagation();
388
+ };
389
+
390
+ /**
391
+ * Handle a mouse-down on bubble's delete icon.
392
+ * @param {!Event} e Mouse up event.
393
+ * @private
394
+ */
395
+ Blockly.ScratchBubble.prototype.deleteMouseDown_ = function(e) {
396
+ this.shouldDelete_ = true;
397
+ e.stopPropagation();
398
+ };
399
+
400
+ /**
401
+ * Handle a mouse-out on bubble's delete icon.
402
+ * @param {!Event} _e Mouse out event.
403
+ * @private
404
+ */
405
+ Blockly.ScratchBubble.prototype.deleteMouseOut_ = function(_e) {
406
+ // If the mouse has left the delete icon, the shouldDelete_ property
407
+ // should get reset to false.
408
+ this.shouldDelete_ = false;
409
+ };
410
+
411
+ /**
412
+ * Handle a mouse-up on bubble's delete icon.
413
+ * @param {!Event} e Mouse up event.
414
+ * @private
415
+ */
416
+ Blockly.ScratchBubble.prototype.deleteMouseUp_ = function(e) {
417
+ // First check that this is actually the same icon that had a mouse down event
418
+ // on it and that the mouse never left the icon
419
+ if (this.shouldDelete_) {
420
+ this.shouldDelete_ = false;
421
+
422
+ if (this.deleteCallback_) {
423
+ this.deleteCallback_.call(this);
424
+ }
425
+ }
426
+ e.stopPropagation();
427
+ };
428
+
429
+ /**
430
+ * Handle a mouse-down on bubble's resize corner.
431
+ * @param {!Event} e Mouse down event.
432
+ * @private
433
+ */
434
+ Blockly.ScratchBubble.prototype.resizeMouseDown_ = function(e) {
435
+ this.resizeStartSize_ = {width: this.width_, height: this.height_};
436
+ this.workspace_.setResizesEnabled(false);
437
+ Blockly.ScratchBubble.superClass_.resizeMouseDown_.call(this, e);
438
+ };
439
+
440
+ /**
441
+ * Handle a mouse-up on bubble's resize corner.
442
+ * @param {!Event} _e Mouse up event.
443
+ * @private
444
+ */
445
+ Blockly.ScratchBubble.prototype.resizeMouseUp_ = function(_e) {
446
+ var oldHW = this.resizeStartSize_;
447
+ this.resizeStartSize_ = null;
448
+ if (this.width_ == oldHW.width && this.height_ == oldHW.height) {
449
+ return;
450
+ }
451
+ // Fire a change event for the new width/height after
452
+ // resize mouse up
453
+ Blockly.Events.fire(new Blockly.Events.CommentChange(
454
+ this.comment, {width: oldHW.width , height: oldHW.height},
455
+ {width: this.width_, height: this.height_}));
456
+
457
+ this.workspace_.setResizesEnabled(true);
458
+ };
459
+
460
+ /**
461
+ * Set the minimized state of the bubble.
462
+ * @param {boolean} minimize Whether the bubble should be minimized
463
+ * @param {?string} labelText Optional label text for the comment top bar
464
+ * when it is minimized.
465
+ * @package
466
+ */
467
+ Blockly.ScratchBubble.prototype.setMinimized = function(minimize, labelText) {
468
+ if (minimize == this.isMinimized_) {
469
+ return;
470
+ }
471
+ if (minimize) {
472
+ this.isMinimized_ = true;
473
+ // Change minimize icon
474
+ this.minimizeArrow_.setAttributeNS('http://www.w3.org/1999/xlink',
475
+ 'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'comment-arrow-up.svg');
476
+ // Hide text area
477
+ this.commentEditor_.setAttribute('display', 'none');
478
+ // Hide resize handle if it exists
479
+ if (this.resizeGroup_) {
480
+ this.resizeGroup_.setAttribute('display', 'none');
481
+ }
482
+ if (labelText && this.labelText_ != labelText) {
483
+ // Update label and display
484
+ this.topBarLabel_.textContent = labelText;
485
+ }
486
+ Blockly.utils.removeAttribute(this.topBarLabel_, 'display');
487
+ } else {
488
+ this.isMinimized_ = false;
489
+ // Change minimize icon
490
+ this.minimizeArrow_.setAttributeNS('http://www.w3.org/1999/xlink',
491
+ 'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'comment-arrow-down.svg');
492
+ // Hide label
493
+ this.topBarLabel_.setAttribute('display', 'none');
494
+ // Show text area
495
+ Blockly.utils.removeAttribute(this.commentEditor_, 'display');
496
+ // Display resize handle if it exists
497
+ if (this.resizeGroup_) {
498
+ Blockly.utils.removeAttribute(this.resizeGroup_, 'display');
499
+ }
500
+ }
501
+ };
502
+
503
+ /**
504
+ * Register a function as a callback event for when the bubble is minimized.
505
+ * @param {!Function} callback The function to call on resize.
506
+ * @package
507
+ */
508
+ Blockly.ScratchBubble.prototype.registerMinimizeToggleEvent = function(callback) {
509
+ this.minimizeToggleCallback_ = callback;
510
+ };
511
+
512
+ /**
513
+ * Register a function as a callback event for when the bubble is resized.
514
+ * @param {!Function} callback The function to call on resize.
515
+ * @package
516
+ */
517
+ Blockly.ScratchBubble.prototype.registerDeleteEvent = function(callback) {
518
+ this.deleteCallback_ = callback;
519
+ };
520
+
521
+ /**
522
+ * Register a function as a callback to show the context menu for this comment.
523
+ * @param {!Function} callback The function to call on resize.
524
+ * @package
525
+ */
526
+ Blockly.ScratchBubble.prototype.registerContextMenuCallback = function(callback) {
527
+ this.contextMenuCallback_ = callback;
528
+ };
529
+
530
+ /**
531
+ * Notification that the anchor has moved.
532
+ * Update the arrow and bubble accordingly.
533
+ * @param {!goog.math.Coordinate} xy Absolute location.
534
+ * @package
535
+ */
536
+ Blockly.ScratchBubble.prototype.setAnchorLocation = function(xy) {
537
+ var event = new Blockly.Events.CommentMove(this.comment);
538
+ this.anchorXY_ = xy;
539
+ if (this.rendered_) {
540
+ this.positionBubble_();
541
+ }
542
+ event.recordNew();
543
+ Blockly.Events.fire(event);
544
+ };
545
+
546
+ /**
547
+ * Move the bubble group to the specified location in workspace coordinates.
548
+ * @param {number} x The x position to move to.
549
+ * @param {number} y The y position to move to.
550
+ * @package
551
+ */
552
+ Blockly.ScratchBubble.prototype.moveTo = function(x, y) {
553
+ Blockly.ScratchBubble.superClass_.moveTo.call(this, x, y);
554
+ this.updatePosition_(x, y);
555
+ };
556
+
557
+ /**
558
+ * Size this bubble.
559
+ * @param {number} width Width of the bubble.
560
+ * @param {number} height Height of the bubble.
561
+ * @package
562
+ */
563
+ Blockly.ScratchBubble.prototype.setBubbleSize = function(width, height) {
564
+ var doubleBorderWidth = 2 * Blockly.ScratchBubble.BORDER_WIDTH;
565
+ // Minimum size of a bubble.
566
+ width = Math.max(width, doubleBorderWidth + 50);
567
+ height = Math.max(height, Blockly.ScratchBubble.TOP_BAR_HEIGHT);
568
+ this.width_ = width;
569
+ this.height_ = height;
570
+ this.bubbleBack_.setAttribute('width', width);
571
+ this.bubbleBack_.setAttribute('height', height);
572
+ this.commentTopBar_.setAttribute('width', width);
573
+ this.commentTopBar_.setAttribute('height', Blockly.ScratchBubble.TOP_BAR_HEIGHT);
574
+ if (this.workspace_.RTL) {
575
+ this.minimizeArrow_.setAttribute('x', width -
576
+ (Blockly.ScratchBubble.MINIMIZE_ICON_SIZE) -
577
+ Blockly.ScratchBubble.TOP_BAR_ICON_INSET);
578
+ } else {
579
+ this.deleteIcon_.setAttribute('x', width -
580
+ Blockly.ScratchBubble.DELETE_ICON_SIZE -
581
+ Blockly.ScratchBubble.TOP_BAR_ICON_INSET);
582
+ }
583
+ if (this.resizeGroup_) {
584
+ var resizeSize = Blockly.ScratchBubble.RESIZE_SIZE;
585
+ if (this.workspace_.RTL) {
586
+ // Mirror the resize group.
587
+ this.resizeGroup_.setAttribute('transform', 'translate(' +
588
+ (resizeSize + doubleBorderWidth) + ',' +
589
+ (this.height_ - doubleBorderWidth - resizeSize) + ') scale(-1, 1)');
590
+ } else {
591
+ this.resizeGroup_.setAttribute('transform', 'translate(' +
592
+ (this.width_ - doubleBorderWidth - resizeSize) + ',' +
593
+ (this.height_ - doubleBorderWidth - resizeSize) + ')');
594
+ }
595
+ }
596
+ if (this.isMinimized_) {
597
+ this.topBarLabel_.setAttribute('x', this.width_ / 2);
598
+ this.topBarLabel_.setAttribute('y', this.height_ / 2);
599
+ }
600
+ if (this.rendered_) {
601
+ this.positionBubble_();
602
+ this.renderArrow_();
603
+ }
604
+ // Allow the contents to resize.
605
+ if (this.resizeCallback_) {
606
+ this.resizeCallback_();
607
+ }
608
+ };
609
+
610
+ /**
611
+ * Draw the line between the bubble and the origin.
612
+ * @private
613
+ */
614
+ Blockly.ScratchBubble.prototype.renderArrow_ = function() {
615
+ // Find the relative coordinates of the top bar center of the bubble.
616
+ var relBubbleX = this.width_ / 2;
617
+ var relBubbleY = Blockly.ScratchBubble.TOP_BAR_HEIGHT / 2;
618
+ // Find the relative coordinates of the center of the anchor.
619
+ var relAnchorX = -this.relativeLeft_;
620
+ var relAnchorY = -this.relativeTop_;
621
+ if (relBubbleX != relAnchorX || relBubbleY != relAnchorY) {
622
+ // Compute the angle of the arrow's line.
623
+ var rise = relAnchorY - relBubbleY;
624
+ var run = relAnchorX - relBubbleX;
625
+ if (this.workspace_.RTL) {
626
+ run *= -1;
627
+ run -= this.width_;
628
+ }
629
+
630
+ var baseX1 = relBubbleX;
631
+ var baseY1 = relBubbleY;
632
+
633
+ this.bubbleArrow_.setAttribute('x1', baseX1);
634
+ this.bubbleArrow_.setAttribute('y1', baseY1);
635
+ this.bubbleArrow_.setAttribute('x2', baseX1 + run);
636
+ this.bubbleArrow_.setAttribute('y2', baseY1 + rise);
637
+ this.bubbleArrow_.setAttribute('stroke-width', Blockly.ScratchBubble.LINE_THICKNESS);
638
+ }
639
+ };
640
+
641
+ /**
642
+ * Change the colour of a bubble.
643
+ * @param {string} hexColour Hex code of colour.
644
+ * @package
645
+ */
646
+ Blockly.ScratchBubble.prototype.setColour = function(hexColour) {
647
+ this.bubbleBack_.setAttribute('stroke', hexColour);
648
+ this.bubbleArrow_.setAttribute('stroke', hexColour);
649
+ };
650
+
651
+ /**
652
+ * Move this bubble during a drag, taking into account whether or not there is
653
+ * a drag surface.
654
+ * @param {?Blockly.BlockDragSurfaceSvg} dragSurface The surface that carries
655
+ * rendered items during a drag, or null if no drag surface is in use.
656
+ * @param {!goog.math.Coordinate} newLoc The location to translate to, in
657
+ * workspace coordinates.
658
+ * @package
659
+ */
660
+ Blockly.ScratchBubble.prototype.moveDuringDrag = function(dragSurface, newLoc) {
661
+ if (dragSurface) {
662
+ dragSurface.translateSurface(newLoc.x, newLoc.y);
663
+ this.updatePosition_(newLoc.x, newLoc.y);
664
+ } else {
665
+ this.moveTo(newLoc.x, newLoc.y);
666
+ }
667
+ };
668
+
669
+ /**
670
+ * Update the relative left and top of the bubble after a move.
671
+ * @param {number} x The x position of the bubble
672
+ * @param {number} y The y position of the bubble
673
+ * @private
674
+ */
675
+ Blockly.ScratchBubble.prototype.updatePosition_ = function(x, y) {
676
+ // Relative left is the distance *and* direction to get from the comment
677
+ // anchor position on the block to the starting edge of the comment (e.g.
678
+ // the left edge of the comment in LTR and the right edge of the comment in RTL)
679
+ if (this.workspace_.RTL) {
680
+ // we want relativeLeft_ to actually be the distance from the anchor point to the *right* edge of the comment in RTL
681
+ this.relativeLeft_ = this.anchorXY_.x - x;
682
+ } else {
683
+ this.relativeLeft_ = x - this.anchorXY_.x;
684
+ }
685
+ this.relativeTop_ = y - this.anchorXY_.y;
686
+ this.renderArrow_();
687
+ };
688
+
689
+ /**
690
+ * Dispose of this bubble.
691
+ * @package
692
+ */
693
+ Blockly.ScratchBubble.prototype.dispose = function() {
694
+ Blockly.ScratchBubble.superClass_.dispose.call(this);
695
+ this.topBarLabel_ = null;
696
+ this.commentTopBar_ = null;
697
+ this.minimizeArrow_ = null;
698
+ this.deleteIcon_ = null;
699
+ };