nodeskini 1.0.0 → 1.0.2

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 (534) hide show
  1. package/blocklySkini/archive/blocklyControleur.js +87 -0
  2. package/blocklySkini/archive/blocklySkini.js +84 -0
  3. package/blocklySkini/archive/blocklyhop.js +75 -0
  4. package/blocklySkini/archive/clientControleurBlocly.js +170 -0
  5. package/blocklySkini/archive/index.html +76 -0
  6. package/blocklySkini/archive/testHHsuspend.txt +89 -0
  7. package/blocklySkini/archive/testHHtrap.txt +262 -0
  8. package/blocklySkini/archive/testOrchestration.txt +177 -0
  9. package/blocklySkini/archive/testOrchestration.xml +447 -0
  10. package/blocklySkini/archive/testOrchestration2.xml +456 -0
  11. package/blocklySkini/blockly/README.md +77 -0
  12. package/blocklySkini/blockly/blockly.d.ts +21480 -0
  13. package/blocklySkini/blockly/blockly.js +25 -0
  14. package/blocklySkini/blockly/blockly.min.js +2188 -0
  15. package/blocklySkini/blockly/blockly_compressed.js +1455 -0
  16. package/blocklySkini/blockly/blockly_compressed.js.map +1 -0
  17. package/blocklySkini/blockly/blocks/colour.js +122 -0
  18. package/blocklySkini/blockly/blocks/lists.js +862 -0
  19. package/blocklySkini/blockly/blocks/logic.js +635 -0
  20. package/blocklySkini/blockly/blocks/loops.js +357 -0
  21. package/blocklySkini/blockly/blocks/math.js +566 -0
  22. package/blocklySkini/blockly/blocks/procedures.js +1072 -0
  23. package/blocklySkini/blockly/blocks/text.js +923 -0
  24. package/blocklySkini/blockly/blocks/variables.js +163 -0
  25. package/blocklySkini/blockly/blocks/variables_dynamic.js +180 -0
  26. package/blocklySkini/blockly/blocks.d.ts +15 -0
  27. package/blocklySkini/blockly/blocks.js +27 -0
  28. package/blocklySkini/blockly/blocks_compressed.js +182 -0
  29. package/blocklySkini/blockly/blocks_compressed.js.map +1 -0
  30. package/blocklySkini/blockly/browser.js +36 -0
  31. package/blocklySkini/blockly/core/block.js +2010 -0
  32. package/blocklySkini/blockly/core/block_animations.js +203 -0
  33. package/blocklySkini/blockly/core/block_drag_surface.js +212 -0
  34. package/blocklySkini/blockly/core/block_dragger.js +378 -0
  35. package/blocklySkini/blockly/core/block_events.js +548 -0
  36. package/blocklySkini/blockly/core/block_svg.js +1763 -0
  37. package/blocklySkini/blockly/core/blockly.js +674 -0
  38. package/blocklySkini/blockly/core/blocks.js +23 -0
  39. package/blocklySkini/blockly/core/bubble.js +880 -0
  40. package/blocklySkini/blockly/core/bubble_dragger.js +274 -0
  41. package/blocklySkini/blockly/core/comment.js +439 -0
  42. package/blocklySkini/blockly/core/components/component.js +554 -0
  43. package/blocklySkini/blockly/core/components/tree/basenode.js +895 -0
  44. package/blocklySkini/blockly/core/components/tree/treecontrol.js +332 -0
  45. package/blocklySkini/blockly/core/components/tree/treenode.js +172 -0
  46. package/blocklySkini/blockly/core/connection.js +682 -0
  47. package/blocklySkini/blockly/core/connection_checker.js +285 -0
  48. package/blocklySkini/blockly/core/connection_db.js +295 -0
  49. package/blocklySkini/blockly/core/constants.js +277 -0
  50. package/blocklySkini/blockly/core/contextmenu.js +307 -0
  51. package/blocklySkini/blockly/core/contextmenu_items.js +534 -0
  52. package/blocklySkini/blockly/core/contextmenu_registry.js +165 -0
  53. package/blocklySkini/blockly/core/css.js +549 -0
  54. package/blocklySkini/blockly/core/dropdowndiv.js +776 -0
  55. package/blocklySkini/blockly/core/events.js +387 -0
  56. package/blocklySkini/blockly/core/events_abstract.js +106 -0
  57. package/blocklySkini/blockly/core/extensions.js +450 -0
  58. package/blocklySkini/blockly/core/field.js +1162 -0
  59. package/blocklySkini/blockly/core/field_angle.js +562 -0
  60. package/blocklySkini/blockly/core/field_checkbox.js +220 -0
  61. package/blocklySkini/blockly/core/field_colour.js +664 -0
  62. package/blocklySkini/blockly/core/field_dropdown.js +760 -0
  63. package/blocklySkini/blockly/core/field_image.js +286 -0
  64. package/blocklySkini/blockly/core/field_label.js +130 -0
  65. package/blocklySkini/blockly/core/field_label_serializable.js +69 -0
  66. package/blocklySkini/blockly/core/field_multilineinput.js +299 -0
  67. package/blocklySkini/blockly/core/field_number.js +317 -0
  68. package/blocklySkini/blockly/core/field_registry.js +66 -0
  69. package/blocklySkini/blockly/core/field_textinput.js +616 -0
  70. package/blocklySkini/blockly/core/field_variable.js +463 -0
  71. package/blocklySkini/blockly/core/flyout_base.js +1071 -0
  72. package/blocklySkini/blockly/core/flyout_button.js +325 -0
  73. package/blocklySkini/blockly/core/flyout_dragger.js +76 -0
  74. package/blocklySkini/blockly/core/flyout_horizontal.js +388 -0
  75. package/blocklySkini/blockly/core/flyout_vertical.js +397 -0
  76. package/blocklySkini/blockly/core/generator.js +482 -0
  77. package/blocklySkini/blockly/core/gesture.js +993 -0
  78. package/blocklySkini/blockly/core/grid.js +222 -0
  79. package/blocklySkini/blockly/core/icon.js +206 -0
  80. package/blocklySkini/blockly/core/inject.js +487 -0
  81. package/blocklySkini/blockly/core/input.js +296 -0
  82. package/blocklySkini/blockly/core/insertion_marker_manager.js +700 -0
  83. package/blocklySkini/blockly/core/interfaces/i_accessibility.js +72 -0
  84. package/blocklySkini/blockly/core/interfaces/i_bounded_element.js +31 -0
  85. package/blocklySkini/blockly/core/interfaces/i_bubble.js +83 -0
  86. package/blocklySkini/blockly/core/interfaces/i_connection_checker.js +94 -0
  87. package/blocklySkini/blockly/core/interfaces/i_contextmenu.js +26 -0
  88. package/blocklySkini/blockly/core/interfaces/i_copyable.js +40 -0
  89. package/blocklySkini/blockly/core/interfaces/i_deletable.js +27 -0
  90. package/blocklySkini/blockly/core/interfaces/i_deletearea.js +28 -0
  91. package/blocklySkini/blockly/core/interfaces/i_flyout.js +178 -0
  92. package/blocklySkini/blockly/core/interfaces/i_movable.js +27 -0
  93. package/blocklySkini/blockly/core/interfaces/i_registrable.js +22 -0
  94. package/blocklySkini/blockly/core/interfaces/i_registrable_field.js +31 -0
  95. package/blocklySkini/blockly/core/interfaces/i_selectable.js +43 -0
  96. package/blocklySkini/blockly/core/interfaces/i_styleable.js +33 -0
  97. package/blocklySkini/blockly/core/interfaces/i_toolbox.js +131 -0
  98. package/blocklySkini/blockly/core/interfaces/i_toolbox_item.js +148 -0
  99. package/blocklySkini/blockly/core/keyboard_nav/action.js +26 -0
  100. package/blocklySkini/blockly/core/keyboard_nav/ast_node.js +684 -0
  101. package/blocklySkini/blockly/core/keyboard_nav/basic_cursor.js +208 -0
  102. package/blocklySkini/blockly/core/keyboard_nav/cursor.js +170 -0
  103. package/blocklySkini/blockly/core/keyboard_nav/flyout_cursor.js +106 -0
  104. package/blocklySkini/blockly/core/keyboard_nav/key_map.js +190 -0
  105. package/blocklySkini/blockly/core/keyboard_nav/marker.js +120 -0
  106. package/blocklySkini/blockly/core/keyboard_nav/navigation.js +1084 -0
  107. package/blocklySkini/blockly/core/keyboard_nav/tab_navigate_cursor.js +48 -0
  108. package/blocklySkini/blockly/core/marker_manager.js +183 -0
  109. package/blocklySkini/blockly/core/menu.js +465 -0
  110. package/blocklySkini/blockly/core/menuitem.js +280 -0
  111. package/blocklySkini/blockly/core/msg.js +31 -0
  112. package/blocklySkini/blockly/core/mutator.js +555 -0
  113. package/blocklySkini/blockly/core/names.js +186 -0
  114. package/blocklySkini/blockly/core/options.js +365 -0
  115. package/blocklySkini/blockly/core/procedures.js +404 -0
  116. package/blocklySkini/blockly/core/registry.js +265 -0
  117. package/blocklySkini/blockly/core/rendered_connection.js +565 -0
  118. package/blocklySkini/blockly/core/renderers/common/block_rendering.js +81 -0
  119. package/blocklySkini/blockly/core/renderers/common/constants.js +1256 -0
  120. package/blocklySkini/blockly/core/renderers/common/debugger.js +431 -0
  121. package/blocklySkini/blockly/core/renderers/common/drawer.js +468 -0
  122. package/blocklySkini/blockly/core/renderers/common/i_path_object.js +151 -0
  123. package/blocklySkini/blockly/core/renderers/common/info.js +775 -0
  124. package/blocklySkini/blockly/core/renderers/common/marker_svg.js +687 -0
  125. package/blocklySkini/blockly/core/renderers/common/path_object.js +279 -0
  126. package/blocklySkini/blockly/core/renderers/common/renderer.js +301 -0
  127. package/blocklySkini/blockly/core/renderers/geras/constants.js +64 -0
  128. package/blocklySkini/blockly/core/renderers/geras/drawer.js +205 -0
  129. package/blocklySkini/blockly/core/renderers/geras/highlight_constants.js +311 -0
  130. package/blocklySkini/blockly/core/renderers/geras/highlighter.js +256 -0
  131. package/blocklySkini/blockly/core/renderers/geras/info.js +483 -0
  132. package/blocklySkini/blockly/core/renderers/geras/measurables/inputs.js +67 -0
  133. package/blocklySkini/blockly/core/renderers/geras/path_object.js +177 -0
  134. package/blocklySkini/blockly/core/renderers/geras/renderer.js +138 -0
  135. package/blocklySkini/blockly/core/renderers/measurables/base.js +44 -0
  136. package/blocklySkini/blockly/core/renderers/measurables/connections.js +114 -0
  137. package/blocklySkini/blockly/core/renderers/measurables/inputs.js +160 -0
  138. package/blocklySkini/blockly/core/renderers/measurables/row_elements.js +185 -0
  139. package/blocklySkini/blockly/core/renderers/measurables/rows.js +532 -0
  140. package/blocklySkini/blockly/core/renderers/measurables/types.js +349 -0
  141. package/blocklySkini/blockly/core/renderers/minimalist/constants.js +29 -0
  142. package/blocklySkini/blockly/core/renderers/minimalist/drawer.js +32 -0
  143. package/blocklySkini/blockly/core/renderers/minimalist/info.js +45 -0
  144. package/blocklySkini/blockly/core/renderers/minimalist/renderer.js +70 -0
  145. package/blocklySkini/blockly/core/renderers/thrasos/info.js +338 -0
  146. package/blocklySkini/blockly/core/renderers/thrasos/renderer.js +45 -0
  147. package/blocklySkini/blockly/core/renderers/zelos/constants.js +1002 -0
  148. package/blocklySkini/blockly/core/renderers/zelos/drawer.js +233 -0
  149. package/blocklySkini/blockly/core/renderers/zelos/info.js +587 -0
  150. package/blocklySkini/blockly/core/renderers/zelos/marker_svg.js +148 -0
  151. package/blocklySkini/blockly/core/renderers/zelos/measurables/inputs.js +47 -0
  152. package/blocklySkini/blockly/core/renderers/zelos/measurables/row_elements.js +37 -0
  153. package/blocklySkini/blockly/core/renderers/zelos/measurables/rows.js +108 -0
  154. package/blocklySkini/blockly/core/renderers/zelos/path_object.js +244 -0
  155. package/blocklySkini/blockly/core/renderers/zelos/renderer.js +130 -0
  156. package/blocklySkini/blockly/core/requires.js +84 -0
  157. package/blocklySkini/blockly/core/scrollbar.js +880 -0
  158. package/blocklySkini/blockly/core/theme/classic.js +87 -0
  159. package/blocklySkini/blockly/core/theme/dark.js +33 -0
  160. package/blocklySkini/blockly/core/theme/deuteranopia.js +104 -0
  161. package/blocklySkini/blockly/core/theme/highcontrast.js +119 -0
  162. package/blocklySkini/blockly/core/theme/modern.js +108 -0
  163. package/blocklySkini/blockly/core/theme/tritanopia.js +103 -0
  164. package/blocklySkini/blockly/core/theme/zelos.js +106 -0
  165. package/blocklySkini/blockly/core/theme.js +236 -0
  166. package/blocklySkini/blockly/core/theme_manager.js +197 -0
  167. package/blocklySkini/blockly/core/toolbox/category.js +690 -0
  168. package/blocklySkini/blockly/core/toolbox/collapsible_category.js +294 -0
  169. package/blocklySkini/blockly/core/toolbox/separator.js +123 -0
  170. package/blocklySkini/blockly/core/toolbox/toolbox.js +984 -0
  171. package/blocklySkini/blockly/core/toolbox/toolbox_item.js +145 -0
  172. package/blocklySkini/blockly/core/toolbox.js +943 -0
  173. package/blocklySkini/blockly/core/tooltip.js +387 -0
  174. package/blocklySkini/blockly/core/touch.js +255 -0
  175. package/blocklySkini/blockly/core/touch_gesture.js +325 -0
  176. package/blocklySkini/blockly/core/trashcan.js +661 -0
  177. package/blocklySkini/blockly/core/ui_events.js +85 -0
  178. package/blocklySkini/blockly/core/utils/aria.js +167 -0
  179. package/blocklySkini/blockly/core/utils/colour.js +208 -0
  180. package/blocklySkini/blockly/core/utils/coordinate.js +125 -0
  181. package/blocklySkini/blockly/core/utils/deprecation.js +34 -0
  182. package/blocklySkini/blockly/core/utils/dom.js +391 -0
  183. package/blocklySkini/blockly/core/utils/global.js +37 -0
  184. package/blocklySkini/blockly/core/utils/idgenerator.js +33 -0
  185. package/blocklySkini/blockly/core/utils/keycodes.js +164 -0
  186. package/blocklySkini/blockly/core/utils/math.js +56 -0
  187. package/blocklySkini/blockly/core/utils/metrics.js +124 -0
  188. package/blocklySkini/blockly/core/utils/object.js +73 -0
  189. package/blocklySkini/blockly/core/utils/rect.js +54 -0
  190. package/blocklySkini/blockly/core/utils/size.js +58 -0
  191. package/blocklySkini/blockly/core/utils/string.js +284 -0
  192. package/blocklySkini/blockly/core/utils/style.js +281 -0
  193. package/blocklySkini/blockly/core/utils/svg.js +181 -0
  194. package/blocklySkini/blockly/core/utils/svg_paths.js +142 -0
  195. package/blocklySkini/blockly/core/utils/toolbox.js +401 -0
  196. package/blocklySkini/blockly/core/utils/useragent.js +110 -0
  197. package/blocklySkini/blockly/core/utils/xml.js +79 -0
  198. package/blocklySkini/blockly/core/utils.js +652 -0
  199. package/blocklySkini/blockly/core/variable_events.js +248 -0
  200. package/blocklySkini/blockly/core/variable_map.js +414 -0
  201. package/blocklySkini/blockly/core/variable_model.js +95 -0
  202. package/blocklySkini/blockly/core/variables.js +571 -0
  203. package/blocklySkini/blockly/core/variables_dynamic.js +100 -0
  204. package/blocklySkini/blockly/core/warning.js +200 -0
  205. package/blocklySkini/blockly/core/widgetdiv.js +241 -0
  206. package/blocklySkini/blockly/core/workspace.js +786 -0
  207. package/blocklySkini/blockly/core/workspace_audio.js +153 -0
  208. package/blocklySkini/blockly/core/workspace_comment.js +373 -0
  209. package/blocklySkini/blockly/core/workspace_comment_render_svg.js +461 -0
  210. package/blocklySkini/blockly/core/workspace_comment_svg.js +701 -0
  211. package/blocklySkini/blockly/core/workspace_drag_surface_svg.js +176 -0
  212. package/blocklySkini/blockly/core/workspace_dragger.js +85 -0
  213. package/blocklySkini/blockly/core/workspace_events.js +93 -0
  214. package/blocklySkini/blockly/core/workspace_svg.js +2661 -0
  215. package/blocklySkini/blockly/core/ws_comment_events.js +417 -0
  216. package/blocklySkini/blockly/core/xml.js +827 -0
  217. package/blocklySkini/blockly/core/zoom_controls.js +449 -0
  218. package/blocklySkini/blockly/core-browser.js +34 -0
  219. package/blocklySkini/blockly/core.d.ts +15 -0
  220. package/blocklySkini/blockly/core.js +38 -0
  221. package/blocklySkini/blockly/dart.d.ts +15 -0
  222. package/blocklySkini/blockly/dart.js +27 -0
  223. package/blocklySkini/blockly/dart_compressed.js +114 -0
  224. package/blocklySkini/blockly/dart_compressed.js.map +1 -0
  225. package/blocklySkini/blockly/generators/dart/colour.js +114 -0
  226. package/blocklySkini/blockly/generators/dart/lists.js +447 -0
  227. package/blocklySkini/blockly/generators/dart/logic.js +127 -0
  228. package/blocklySkini/blockly/generators/dart/loops.js +169 -0
  229. package/blocklySkini/blockly/generators/dart/math.js +485 -0
  230. package/blocklySkini/blockly/generators/dart/procedures.js +111 -0
  231. package/blocklySkini/blockly/generators/dart/text.js +339 -0
  232. package/blocklySkini/blockly/generators/dart/variables.js +32 -0
  233. package/blocklySkini/blockly/generators/dart/variables_dynamic.js +21 -0
  234. package/blocklySkini/blockly/generators/dart.js +290 -0
  235. package/blocklySkini/blockly/generators/javascript/colour.js +89 -0
  236. package/blocklySkini/blockly/generators/javascript/lists.js +388 -0
  237. package/blocklySkini/blockly/generators/javascript/logic.js +129 -0
  238. package/blocklySkini/blockly/generators/javascript/loops.js +184 -0
  239. package/blocklySkini/blockly/generators/javascript/math.js +409 -0
  240. package/blocklySkini/blockly/generators/javascript/procedures.js +113 -0
  241. package/blocklySkini/blockly/generators/javascript/text.js +367 -0
  242. package/blocklySkini/blockly/generators/javascript/variables.js +32 -0
  243. package/blocklySkini/blockly/generators/javascript/variables_dynamic.js +23 -0
  244. package/blocklySkini/blockly/generators/javascript.js +317 -0
  245. package/blocklySkini/blockly/generators/lua/colour.js +76 -0
  246. package/blocklySkini/blockly/generators/lua/lists.js +368 -0
  247. package/blocklySkini/blockly/generators/lua/logic.js +127 -0
  248. package/blocklySkini/blockly/generators/lua/loops.js +173 -0
  249. package/blocklySkini/blockly/generators/lua/math.js +423 -0
  250. package/blocklySkini/blockly/generators/lua/procedures.js +113 -0
  251. package/blocklySkini/blockly/generators/lua/text.js +353 -0
  252. package/blocklySkini/blockly/generators/lua/variables.js +32 -0
  253. package/blocklySkini/blockly/generators/lua/variables_dynamic.js +21 -0
  254. package/blocklySkini/blockly/generators/lua.js +198 -0
  255. package/blocklySkini/blockly/generators/php/colour.js +91 -0
  256. package/blocklySkini/blockly/generators/php/lists.js +498 -0
  257. package/blocklySkini/blockly/generators/php/logic.js +128 -0
  258. package/blocklySkini/blockly/generators/php/loops.js +170 -0
  259. package/blocklySkini/blockly/generators/php/math.js +370 -0
  260. package/blocklySkini/blockly/generators/php/procedures.js +132 -0
  261. package/blocklySkini/blockly/generators/php/text.js +271 -0
  262. package/blocklySkini/blockly/generators/php/variables.js +32 -0
  263. package/blocklySkini/blockly/generators/php/variables_dynamic.js +21 -0
  264. package/blocklySkini/blockly/generators/php.js +318 -0
  265. package/blocklySkini/blockly/generators/python/colour.js +72 -0
  266. package/blocklySkini/blockly/generators/python/lists.js +349 -0
  267. package/blocklySkini/blockly/generators/python/logic.js +127 -0
  268. package/blocklySkini/blockly/generators/python/loops.js +214 -0
  269. package/blocklySkini/blockly/generators/python/math.js +385 -0
  270. package/blocklySkini/blockly/generators/python/procedures.js +134 -0
  271. package/blocklySkini/blockly/generators/python/text.js +293 -0
  272. package/blocklySkini/blockly/generators/python/variables.js +32 -0
  273. package/blocklySkini/blockly/generators/python/variables_dynamic.js +21 -0
  274. package/blocklySkini/blockly/generators/python.js +322 -0
  275. package/blocklySkini/blockly/index.d.ts +22 -0
  276. package/blocklySkini/blockly/index.js +24 -0
  277. package/blocklySkini/blockly/javascript.d.ts +15 -0
  278. package/blocklySkini/blockly/javascript.js +27 -0
  279. package/blocklySkini/blockly/javascript_compressed.js +115 -0
  280. package/blocklySkini/blockly/javascript_compressed.js.map +1 -0
  281. package/blocklySkini/blockly/lua.d.ts +15 -0
  282. package/blocklySkini/blockly/lua.js +27 -0
  283. package/blocklySkini/blockly/lua_compressed.js +94 -0
  284. package/blocklySkini/blockly/lua_compressed.js.map +1 -0
  285. package/blocklySkini/blockly/media/1x1.gif +0 -0
  286. package/blocklySkini/blockly/media/click.mp3 +0 -0
  287. package/blocklySkini/blockly/media/click.ogg +0 -0
  288. package/blocklySkini/blockly/media/click.wav +0 -0
  289. package/blocklySkini/blockly/media/delete.mp3 +0 -0
  290. package/blocklySkini/blockly/media/delete.ogg +0 -0
  291. package/blocklySkini/blockly/media/delete.wav +0 -0
  292. package/blocklySkini/blockly/media/disconnect.mp3 +0 -0
  293. package/blocklySkini/blockly/media/disconnect.ogg +0 -0
  294. package/blocklySkini/blockly/media/disconnect.wav +0 -0
  295. package/blocklySkini/blockly/media/dropdown-arrow.svg +1 -0
  296. package/blocklySkini/blockly/media/handclosed.cur +0 -0
  297. package/blocklySkini/blockly/media/handdelete.cur +0 -0
  298. package/blocklySkini/blockly/media/handopen.cur +0 -0
  299. package/blocklySkini/blockly/media/pilcrow.png +0 -0
  300. package/blocklySkini/blockly/media/quote0.png +0 -0
  301. package/blocklySkini/blockly/media/quote1.png +0 -0
  302. package/blocklySkini/blockly/media/sprites.png +0 -0
  303. package/blocklySkini/blockly/media/sprites.svg +74 -0
  304. package/blocklySkini/blockly/msg/ab.d.ts +16 -0
  305. package/blocklySkini/blockly/msg/ab.js +447 -0
  306. package/blocklySkini/blockly/msg/ar.d.ts +16 -0
  307. package/blocklySkini/blockly/msg/ar.js +447 -0
  308. package/blocklySkini/blockly/msg/az.d.ts +16 -0
  309. package/blocklySkini/blockly/msg/az.js +447 -0
  310. package/blocklySkini/blockly/msg/ba.d.ts +16 -0
  311. package/blocklySkini/blockly/msg/ba.js +447 -0
  312. package/blocklySkini/blockly/msg/bcc.d.ts +16 -0
  313. package/blocklySkini/blockly/msg/bcc.js +447 -0
  314. package/blocklySkini/blockly/msg/be-tarask.d.ts +16 -0
  315. package/blocklySkini/blockly/msg/be-tarask.js +447 -0
  316. package/blocklySkini/blockly/msg/be.d.ts +16 -0
  317. package/blocklySkini/blockly/msg/be.js +447 -0
  318. package/blocklySkini/blockly/msg/bg.d.ts +16 -0
  319. package/blocklySkini/blockly/msg/bg.js +447 -0
  320. package/blocklySkini/blockly/msg/bn.d.ts +16 -0
  321. package/blocklySkini/blockly/msg/bn.js +447 -0
  322. package/blocklySkini/blockly/msg/br.d.ts +16 -0
  323. package/blocklySkini/blockly/msg/br.js +447 -0
  324. package/blocklySkini/blockly/msg/ca.d.ts +16 -0
  325. package/blocklySkini/blockly/msg/ca.js +447 -0
  326. package/blocklySkini/blockly/msg/constants.d.ts +16 -0
  327. package/blocklySkini/blockly/msg/cs.d.ts +16 -0
  328. package/blocklySkini/blockly/msg/cs.js +447 -0
  329. package/blocklySkini/blockly/msg/da.d.ts +16 -0
  330. package/blocklySkini/blockly/msg/da.js +447 -0
  331. package/blocklySkini/blockly/msg/de.d.ts +16 -0
  332. package/blocklySkini/blockly/msg/de.js +447 -0
  333. package/blocklySkini/blockly/msg/diq.d.ts +16 -0
  334. package/blocklySkini/blockly/msg/diq.js +447 -0
  335. package/blocklySkini/blockly/msg/dty.d.ts +16 -0
  336. package/blocklySkini/blockly/msg/dty.js +447 -0
  337. package/blocklySkini/blockly/msg/ee.d.ts +16 -0
  338. package/blocklySkini/blockly/msg/ee.js +447 -0
  339. package/blocklySkini/blockly/msg/el.d.ts +16 -0
  340. package/blocklySkini/blockly/msg/el.js +447 -0
  341. package/blocklySkini/blockly/msg/en-gb.d.ts +16 -0
  342. package/blocklySkini/blockly/msg/en-gb.js +447 -0
  343. package/blocklySkini/blockly/msg/en.d.ts +16 -0
  344. package/blocklySkini/blockly/msg/en.js +447 -0
  345. package/blocklySkini/blockly/msg/eo.d.ts +16 -0
  346. package/blocklySkini/blockly/msg/eo.js +447 -0
  347. package/blocklySkini/blockly/msg/es.d.ts +16 -0
  348. package/blocklySkini/blockly/msg/es.js +447 -0
  349. package/blocklySkini/blockly/msg/et.d.ts +16 -0
  350. package/blocklySkini/blockly/msg/et.js +447 -0
  351. package/blocklySkini/blockly/msg/eu.d.ts +16 -0
  352. package/blocklySkini/blockly/msg/eu.js +447 -0
  353. package/blocklySkini/blockly/msg/fa.d.ts +16 -0
  354. package/blocklySkini/blockly/msg/fa.js +447 -0
  355. package/blocklySkini/blockly/msg/fi.d.ts +16 -0
  356. package/blocklySkini/blockly/msg/fi.js +447 -0
  357. package/blocklySkini/blockly/msg/fr.d.ts +16 -0
  358. package/blocklySkini/blockly/msg/fr.js +447 -0
  359. package/blocklySkini/blockly/msg/gl.d.ts +16 -0
  360. package/blocklySkini/blockly/msg/gl.js +447 -0
  361. package/blocklySkini/blockly/msg/gor.d.ts +16 -0
  362. package/blocklySkini/blockly/msg/gor.js +447 -0
  363. package/blocklySkini/blockly/msg/ha.d.ts +16 -0
  364. package/blocklySkini/blockly/msg/ha.js +447 -0
  365. package/blocklySkini/blockly/msg/he.d.ts +16 -0
  366. package/blocklySkini/blockly/msg/he.js +447 -0
  367. package/blocklySkini/blockly/msg/hi.d.ts +16 -0
  368. package/blocklySkini/blockly/msg/hi.js +447 -0
  369. package/blocklySkini/blockly/msg/hrx.d.ts +16 -0
  370. package/blocklySkini/blockly/msg/hrx.js +447 -0
  371. package/blocklySkini/blockly/msg/hu.d.ts +16 -0
  372. package/blocklySkini/blockly/msg/hu.js +447 -0
  373. package/blocklySkini/blockly/msg/hy.d.ts +16 -0
  374. package/blocklySkini/blockly/msg/hy.js +447 -0
  375. package/blocklySkini/blockly/msg/ia.d.ts +16 -0
  376. package/blocklySkini/blockly/msg/ia.js +447 -0
  377. package/blocklySkini/blockly/msg/id.d.ts +16 -0
  378. package/blocklySkini/blockly/msg/id.js +447 -0
  379. package/blocklySkini/blockly/msg/ig.d.ts +16 -0
  380. package/blocklySkini/blockly/msg/ig.js +447 -0
  381. package/blocklySkini/blockly/msg/is.d.ts +16 -0
  382. package/blocklySkini/blockly/msg/is.js +447 -0
  383. package/blocklySkini/blockly/msg/it.d.ts +16 -0
  384. package/blocklySkini/blockly/msg/it.js +447 -0
  385. package/blocklySkini/blockly/msg/ja.d.ts +16 -0
  386. package/blocklySkini/blockly/msg/ja.js +447 -0
  387. package/blocklySkini/blockly/msg/kab.d.ts +16 -0
  388. package/blocklySkini/blockly/msg/kab.js +447 -0
  389. package/blocklySkini/blockly/msg/kn.d.ts +16 -0
  390. package/blocklySkini/blockly/msg/kn.js +447 -0
  391. package/blocklySkini/blockly/msg/ko.d.ts +16 -0
  392. package/blocklySkini/blockly/msg/ko.js +447 -0
  393. package/blocklySkini/blockly/msg/lb.d.ts +16 -0
  394. package/blocklySkini/blockly/msg/lb.js +447 -0
  395. package/blocklySkini/blockly/msg/lki.d.ts +16 -0
  396. package/blocklySkini/blockly/msg/lki.js +447 -0
  397. package/blocklySkini/blockly/msg/lo.d.ts +16 -0
  398. package/blocklySkini/blockly/msg/lo.js +447 -0
  399. package/blocklySkini/blockly/msg/lrc.d.ts +16 -0
  400. package/blocklySkini/blockly/msg/lrc.js +447 -0
  401. package/blocklySkini/blockly/msg/lt.d.ts +16 -0
  402. package/blocklySkini/blockly/msg/lt.js +447 -0
  403. package/blocklySkini/blockly/msg/lv.d.ts +16 -0
  404. package/blocklySkini/blockly/msg/lv.js +447 -0
  405. package/blocklySkini/blockly/msg/mk.d.ts +16 -0
  406. package/blocklySkini/blockly/msg/mk.js +447 -0
  407. package/blocklySkini/blockly/msg/mnw.d.ts +16 -0
  408. package/blocklySkini/blockly/msg/mnw.js +447 -0
  409. package/blocklySkini/blockly/msg/ms.d.ts +16 -0
  410. package/blocklySkini/blockly/msg/ms.js +447 -0
  411. package/blocklySkini/blockly/msg/msg.d.ts +444 -0
  412. package/blocklySkini/blockly/msg/nb.d.ts +16 -0
  413. package/blocklySkini/blockly/msg/nb.js +447 -0
  414. package/blocklySkini/blockly/msg/nl.d.ts +16 -0
  415. package/blocklySkini/blockly/msg/nl.js +447 -0
  416. package/blocklySkini/blockly/msg/oc.d.ts +16 -0
  417. package/blocklySkini/blockly/msg/oc.js +447 -0
  418. package/blocklySkini/blockly/msg/pl.d.ts +16 -0
  419. package/blocklySkini/blockly/msg/pl.js +447 -0
  420. package/blocklySkini/blockly/msg/pms.d.ts +16 -0
  421. package/blocklySkini/blockly/msg/pms.js +447 -0
  422. package/blocklySkini/blockly/msg/pt-br.d.ts +16 -0
  423. package/blocklySkini/blockly/msg/pt-br.js +447 -0
  424. package/blocklySkini/blockly/msg/pt.d.ts +16 -0
  425. package/blocklySkini/blockly/msg/pt.js +447 -0
  426. package/blocklySkini/blockly/msg/qqq.d.ts +16 -0
  427. package/blocklySkini/blockly/msg/ro.d.ts +16 -0
  428. package/blocklySkini/blockly/msg/ro.js +447 -0
  429. package/blocklySkini/blockly/msg/ru.d.ts +16 -0
  430. package/blocklySkini/blockly/msg/ru.js +447 -0
  431. package/blocklySkini/blockly/msg/sc.d.ts +16 -0
  432. package/blocklySkini/blockly/msg/sc.js +447 -0
  433. package/blocklySkini/blockly/msg/sd.d.ts +16 -0
  434. package/blocklySkini/blockly/msg/sd.js +447 -0
  435. package/blocklySkini/blockly/msg/shn.d.ts +16 -0
  436. package/blocklySkini/blockly/msg/shn.js +447 -0
  437. package/blocklySkini/blockly/msg/sk.d.ts +16 -0
  438. package/blocklySkini/blockly/msg/sk.js +447 -0
  439. package/blocklySkini/blockly/msg/skr-arab.d.ts +16 -0
  440. package/blocklySkini/blockly/msg/skr-arab.js +447 -0
  441. package/blocklySkini/blockly/msg/sl.d.ts +16 -0
  442. package/blocklySkini/blockly/msg/sl.js +447 -0
  443. package/blocklySkini/blockly/msg/sq.d.ts +16 -0
  444. package/blocklySkini/blockly/msg/sq.js +447 -0
  445. package/blocklySkini/blockly/msg/sr-latn.d.ts +16 -0
  446. package/blocklySkini/blockly/msg/sr-latn.js +447 -0
  447. package/blocklySkini/blockly/msg/sr.d.ts +16 -0
  448. package/blocklySkini/blockly/msg/sr.js +447 -0
  449. package/blocklySkini/blockly/msg/sv.d.ts +16 -0
  450. package/blocklySkini/blockly/msg/sv.js +447 -0
  451. package/blocklySkini/blockly/msg/synonyms.d.ts +16 -0
  452. package/blocklySkini/blockly/msg/ta.d.ts +16 -0
  453. package/blocklySkini/blockly/msg/ta.js +447 -0
  454. package/blocklySkini/blockly/msg/tcy.d.ts +16 -0
  455. package/blocklySkini/blockly/msg/tcy.js +447 -0
  456. package/blocklySkini/blockly/msg/te.d.ts +16 -0
  457. package/blocklySkini/blockly/msg/te.js +447 -0
  458. package/blocklySkini/blockly/msg/th.d.ts +16 -0
  459. package/blocklySkini/blockly/msg/th.js +447 -0
  460. package/blocklySkini/blockly/msg/tl.d.ts +16 -0
  461. package/blocklySkini/blockly/msg/tl.js +447 -0
  462. package/blocklySkini/blockly/msg/tlh.d.ts +16 -0
  463. package/blocklySkini/blockly/msg/tlh.js +447 -0
  464. package/blocklySkini/blockly/msg/tr.d.ts +16 -0
  465. package/blocklySkini/blockly/msg/tr.js +447 -0
  466. package/blocklySkini/blockly/msg/ug-arab.d.ts +16 -0
  467. package/blocklySkini/blockly/msg/ug-arab.js +447 -0
  468. package/blocklySkini/blockly/msg/uk.d.ts +16 -0
  469. package/blocklySkini/blockly/msg/uk.js +447 -0
  470. package/blocklySkini/blockly/msg/ur.d.ts +16 -0
  471. package/blocklySkini/blockly/msg/ur.js +447 -0
  472. package/blocklySkini/blockly/msg/vi.d.ts +16 -0
  473. package/blocklySkini/blockly/msg/vi.js +447 -0
  474. package/blocklySkini/blockly/msg/xmf.d.ts +16 -0
  475. package/blocklySkini/blockly/msg/xmf.js +447 -0
  476. package/blocklySkini/blockly/msg/yo.d.ts +16 -0
  477. package/blocklySkini/blockly/msg/yo.js +447 -0
  478. package/blocklySkini/blockly/msg/zh-hans.d.ts +16 -0
  479. package/blocklySkini/blockly/msg/zh-hans.js +447 -0
  480. package/blocklySkini/blockly/msg/zh-hant.d.ts +16 -0
  481. package/blocklySkini/blockly/msg/zh-hant.js +447 -0
  482. package/blocklySkini/blockly/node.js +35 -0
  483. package/blocklySkini/blockly/package.json +84 -0
  484. package/blocklySkini/blockly/php.d.ts +15 -0
  485. package/blocklySkini/blockly/php.js +27 -0
  486. package/blocklySkini/blockly/php_compressed.js +103 -0
  487. package/blocklySkini/blockly/php_compressed.js.map +1 -0
  488. package/blocklySkini/blockly/python.d.ts +15 -0
  489. package/blocklySkini/blockly/python.js +27 -0
  490. package/blocklySkini/blockly/python_compressed.js +98 -0
  491. package/blocklySkini/blockly/python_compressed.js.map +1 -0
  492. package/blocklySkini/blocklySkini.html +81 -0
  493. package/blocklySkini/orchestrations/.xml +1 -0
  494. package/blocklySkini/orchestrations/BluesSkini-1.xml +231 -0
  495. package/blocklySkini/orchestrations/BluesSkini-2.xml +741 -0
  496. package/blocklySkini/orchestrations/BluesSkini-3.xml +731 -0
  497. package/blocklySkini/orchestrations/BluesSkini-4.xml +695 -0
  498. package/blocklySkini/orchestrations/BluesSkini-5.xml +731 -0
  499. package/blocklySkini/orchestrations/BluesSkini.xml +704 -0
  500. package/blocklySkini/orchestrations/FunkBitwig-1.xml +778 -0
  501. package/blocklySkini/orchestrations/FunkBitwig-2.xml +471 -0
  502. package/blocklySkini/orchestrations/JouerLeBonInstrument1-1.xml +784 -0
  503. package/blocklySkini/orchestrations/MajeurMineur-1.xml +638 -0
  504. package/blocklySkini/orchestrations/Opus5-3 - Copie.xml +1041 -0
  505. package/blocklySkini/orchestrations/Opus5-3.xml +1128 -0
  506. package/blocklySkini/orchestrations/Quatuor1-1.xml +357 -0
  507. package/blocklySkini/orchestrations/TechnoBitwig-1.xml +221 -0
  508. package/blocklySkini/orchestrations/TestBlockly.xml +497 -0
  509. package/blocklySkini/orchestrations/TestBlockly1.xml +500 -0
  510. package/blocklySkini/orchestrations/TestBlockly2.xml +792 -0
  511. package/blocklySkini/orchestrations/TestBlockly3-1.xml +1182 -0
  512. package/blocklySkini/orchestrations/TestBlockly3.xml +1251 -0
  513. package/blocklySkini/orchestrations/TestFunction.xml +143 -0
  514. package/blocklySkini/orchestrations/TestIf.xml +80 -0
  515. package/blocklySkini/orchestrations/TestLoop.xml +127 -0
  516. package/blocklySkini/orchestrations/TestOrchestration2.xml +460 -0
  517. package/blocklySkini/orchestrations/TestPrint.xml +70 -0
  518. package/blocklySkini/orchestrations/TestSubMod.xml +81 -0
  519. package/blocklySkini/orchestrations/Testlogic.xml +113 -0
  520. package/blocklySkini/orchestrations/TrouveLaPercu-1.xml +813 -0
  521. package/blocklySkini/orchestrations/TrouveLaPercu-2.xml +813 -0
  522. package/blocklySkini/orchestrations/bar.xml +496 -0
  523. package/blocklySkini/orchestrations/bar2.xml +496 -0
  524. package/blocklySkini/orchestrations/foo.xml +500 -0
  525. package/blocklySkini/orchestrations/opus5Blockly - Copie.xml +496 -0
  526. package/blocklySkini/orchestrations/opus5Blockly-3.xml +868 -0
  527. package/blocklySkini/orchestrations/opus5Blockly.xml +496 -0
  528. package/blocklySkini/orchestrations/testOrchestration3.xml +483 -0
  529. package/blocklySkini/orchestrations/testOrchestration4.xml +487 -0
  530. package/blocklySkini/scripts/hiphop_blocks.js +6104 -0
  531. package/blocklySkini/scripts/main2.js +801 -0
  532. package/blocklySkini/styles/index.css +320 -0
  533. package/blocklySkini/styles/material.css +11552 -0
  534. package/package.json +4 -3
@@ -0,0 +1,2661 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2014 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ /**
8
+ * @fileoverview Object representing a workspace rendered as SVG.
9
+ * @author fraser@google.com (Neil Fraser)
10
+ */
11
+ 'use strict';
12
+
13
+ goog.provide('Blockly.WorkspaceSvg');
14
+
15
+ goog.require('Blockly.BlockSvg');
16
+ goog.require('Blockly.blockRendering');
17
+ goog.require('Blockly.ConnectionDB');
18
+ goog.require('Blockly.constants');
19
+ goog.require('Blockly.ContextMenuRegistry');
20
+ goog.require('Blockly.Events');
21
+ goog.require('Blockly.Events.BlockCreate');
22
+ goog.require('Blockly.Gesture');
23
+ goog.require('Blockly.Grid');
24
+ goog.require('Blockly.MarkerManager');
25
+ goog.require('Blockly.Msg');
26
+ goog.require('Blockly.navigation');
27
+ goog.require('Blockly.Options');
28
+ goog.require('Blockly.registry');
29
+ goog.require('Blockly.ThemeManager');
30
+ goog.require('Blockly.Themes.Classic');
31
+ goog.require('Blockly.TouchGesture');
32
+ goog.require('Blockly.utils');
33
+ goog.require('Blockly.utils.Coordinate');
34
+ goog.require('Blockly.utils.dom');
35
+ goog.require('Blockly.utils.Metrics');
36
+ goog.require('Blockly.utils.object');
37
+ goog.require('Blockly.utils.Rect');
38
+ goog.require('Blockly.utils.Svg');
39
+ goog.require('Blockly.utils.toolbox');
40
+ goog.require('Blockly.Workspace');
41
+ goog.require('Blockly.WorkspaceAudio');
42
+ goog.require('Blockly.WorkspaceDragSurfaceSvg');
43
+ goog.require('Blockly.Xml');
44
+
45
+ goog.requireType('Blockly.blockRendering.Renderer');
46
+ goog.requireType('Blockly.IASTNodeLocationSvg');
47
+ goog.requireType('Blockly.IBoundedElement');
48
+ goog.requireType('Blockly.IFlyout');
49
+
50
+
51
+ /**
52
+ * Class for a workspace. This is an onscreen area with optional trashcan,
53
+ * scrollbars, bubbles, and dragging.
54
+ * @param {!Blockly.Options} options Dictionary of options.
55
+ * @param {Blockly.BlockDragSurfaceSvg=} opt_blockDragSurface Drag surface for
56
+ * blocks.
57
+ * @param {Blockly.WorkspaceDragSurfaceSvg=} opt_wsDragSurface Drag surface for
58
+ * the workspace.
59
+ * @extends {Blockly.Workspace}
60
+ * @implements {Blockly.IASTNodeLocationSvg}
61
+ * @constructor
62
+ */
63
+ Blockly.WorkspaceSvg = function(options,
64
+ opt_blockDragSurface, opt_wsDragSurface) {
65
+ Blockly.WorkspaceSvg.superClass_.constructor.call(this, options);
66
+ /** @type {function():!Blockly.utils.Metrics} */
67
+ this.getMetrics =
68
+ options.getMetrics || Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_;
69
+ /** @type {function(!{x:number, y:number}):void} */
70
+ this.setMetrics =
71
+ options.setMetrics || Blockly.WorkspaceSvg.setTopLevelWorkspaceMetrics_;
72
+
73
+
74
+ this.connectionDBList = Blockly.ConnectionDB.init(this.connectionChecker);
75
+
76
+ if (opt_blockDragSurface) {
77
+ this.blockDragSurface_ = opt_blockDragSurface;
78
+ }
79
+
80
+ if (opt_wsDragSurface) {
81
+ this.workspaceDragSurface_ = opt_wsDragSurface;
82
+ }
83
+
84
+ this.useWorkspaceDragSurface_ =
85
+ !!this.workspaceDragSurface_ && Blockly.utils.is3dSupported();
86
+
87
+ /**
88
+ * List of currently highlighted blocks. Block highlighting is often used to
89
+ * visually mark blocks currently being executed.
90
+ * @type {!Array.<!Blockly.BlockSvg>}
91
+ * @private
92
+ */
93
+ this.highlightedBlocks_ = [];
94
+
95
+ /**
96
+ * Object in charge of loading, storing, and playing audio for a workspace.
97
+ * @type {!Blockly.WorkspaceAudio}
98
+ * @private
99
+ */
100
+ this.audioManager_ = new Blockly.WorkspaceAudio(
101
+ /** @type {Blockly.WorkspaceSvg} */ (options.parentWorkspace));
102
+
103
+ /**
104
+ * This workspace's grid object or null.
105
+ * @type {Blockly.Grid}
106
+ * @private
107
+ */
108
+ this.grid_ = this.options.gridPattern ?
109
+ new Blockly.Grid(this.options.gridPattern, options.gridOptions) : null;
110
+
111
+ /**
112
+ * Manager in charge of markers and cursors.
113
+ * @type {!Blockly.MarkerManager}
114
+ * @private
115
+ */
116
+ this.markerManager_ = new Blockly.MarkerManager(this);
117
+
118
+ /**
119
+ * Map from function names to callbacks, for deciding what to do when a custom
120
+ * toolbox category is opened.
121
+ * @type {!Object.<string, ?function(!Blockly.Workspace):!Array.<!Element>>}
122
+ * @private
123
+ */
124
+ this.toolboxCategoryCallbacks_ = {};
125
+
126
+ /**
127
+ * Map from function names to callbacks, for deciding what to do when a button
128
+ * is clicked.
129
+ * @type {!Object.<string, ?function(!Blockly.FlyoutButton)>}
130
+ * @private
131
+ */
132
+ this.flyoutButtonCallbacks_ = {};
133
+
134
+ if (Blockly.Variables && Blockly.Variables.flyoutCategory) {
135
+ this.registerToolboxCategoryCallback(Blockly.VARIABLE_CATEGORY_NAME,
136
+ Blockly.Variables.flyoutCategory);
137
+ }
138
+ if (Blockly.VariablesDynamic && Blockly.VariablesDynamic.flyoutCategory) {
139
+ this.registerToolboxCategoryCallback(Blockly.VARIABLE_DYNAMIC_CATEGORY_NAME,
140
+ Blockly.VariablesDynamic.flyoutCategory);
141
+ }
142
+ if (Blockly.Procedures && Blockly.Procedures.flyoutCategory) {
143
+ this.registerToolboxCategoryCallback(Blockly.PROCEDURE_CATEGORY_NAME,
144
+ Blockly.Procedures.flyoutCategory);
145
+ this.addChangeListener(Blockly.Procedures.mutatorOpenListener);
146
+ }
147
+
148
+ /**
149
+ * Object in charge of storing and updating the workspace theme.
150
+ * @type {!Blockly.ThemeManager}
151
+ * @protected
152
+ */
153
+ this.themeManager_ = this.options.parentWorkspace ?
154
+ this.options.parentWorkspace.getThemeManager() :
155
+ new Blockly.ThemeManager(this,
156
+ this.options.theme || Blockly.Themes.Classic);
157
+ this.themeManager_.subscribeWorkspace(this);
158
+
159
+ /**
160
+ * The block renderer used for rendering blocks on this workspace.
161
+ * @type {!Blockly.blockRendering.Renderer}
162
+ * @private
163
+ */
164
+ this.renderer_ = Blockly.blockRendering.init(this.options.renderer || 'geras',
165
+ this.getTheme(), this.options.rendererOverrides);
166
+
167
+ /**
168
+ * Cached parent SVG.
169
+ * @type {SVGElement}
170
+ * @private
171
+ */
172
+ this.cachedParentSvg_ = null;
173
+
174
+ /**
175
+ * True if keyboard accessibility mode is on, false otherwise.
176
+ * @type {boolean}
177
+ */
178
+ this.keyboardAccessibilityMode = false;
179
+
180
+ /**
181
+ * The list of top-level bounded elements on the workspace.
182
+ * @type {!Array.<!Blockly.IBoundedElement>}
183
+ * @private
184
+ */
185
+ this.topBoundedElements_ = [];
186
+ };
187
+ Blockly.utils.object.inherits(Blockly.WorkspaceSvg, Blockly.Workspace);
188
+
189
+ /**
190
+ * A wrapper function called when a resize event occurs.
191
+ * You can pass the result to `unbindEvent_`.
192
+ * @type {Array.<!Array>}
193
+ * @private
194
+ */
195
+ Blockly.WorkspaceSvg.prototype.resizeHandlerWrapper_ = null;
196
+
197
+ /**
198
+ * The render status of an SVG workspace.
199
+ * Returns `false` for headless workspaces and true for instances of
200
+ * `Blockly.WorkspaceSvg`.
201
+ * @type {boolean}
202
+ */
203
+ Blockly.WorkspaceSvg.prototype.rendered = true;
204
+
205
+ /**
206
+ * Whether the workspace is visible. False if the workspace has been hidden
207
+ * by calling `setVisible(false)`.
208
+ * @type {boolean}
209
+ * @private
210
+ */
211
+ Blockly.WorkspaceSvg.prototype.isVisible_ = true;
212
+
213
+ /**
214
+ * Is this workspace the surface for a flyout?
215
+ * @type {boolean}
216
+ */
217
+ Blockly.WorkspaceSvg.prototype.isFlyout = false;
218
+
219
+ /**
220
+ * Is this workspace the surface for a mutator?
221
+ * @type {boolean}
222
+ * @package
223
+ */
224
+ Blockly.WorkspaceSvg.prototype.isMutator = false;
225
+
226
+ /**
227
+ * Whether this workspace has resizes enabled.
228
+ * Disable during batch operations for a performance improvement.
229
+ * @type {boolean}
230
+ * @private
231
+ */
232
+ Blockly.WorkspaceSvg.prototype.resizesEnabled_ = true;
233
+
234
+ /**
235
+ * Current horizontal scrolling offset in pixel units, relative to the
236
+ * workspace origin.
237
+ *
238
+ * It is useful to think about a view, and a canvas moving beneath that
239
+ * view. As the canvas moves right, this value becomes more positive, and
240
+ * the view is now "seeing" the left side of the canvas. As the canvas moves
241
+ * left, this value becomes more negative, and the view is now "seeing" the
242
+ * right side of the canvas.
243
+ *
244
+ * The confusing thing about this value is that it does not, and must not
245
+ * include the absoluteLeft offset. This is because it is used to calculate
246
+ * the viewLeft value.
247
+ *
248
+ * The viewLeft is relative to the workspace origin (although in pixel
249
+ * units). The workspace origin is the top-left corner of the workspace (at
250
+ * least when it is enabled). It is shifted from the top-left of the blocklyDiv
251
+ * so as not to be beneath the toolbox.
252
+ *
253
+ * When the workspace is enabled the viewLeft and workspace origin are at
254
+ * the same X location. As the canvas slides towards the right beneath the view
255
+ * this value (scrollX) becomes more positive, and the viewLeft becomes more
256
+ * negative relative to the workspace origin (imagine the workspace origin
257
+ * as a dot on the canvas sliding to the right as the canvas moves).
258
+ *
259
+ * So if the scrollX were to include the absoluteLeft this would in a way
260
+ * "unshift" the workspace origin. This means that the viewLeft would be
261
+ * representing the left edge of the blocklyDiv, rather than the left edge
262
+ * of the workspace.
263
+ *
264
+ * @type {number}
265
+ */
266
+ Blockly.WorkspaceSvg.prototype.scrollX = 0;
267
+
268
+ /**
269
+ * Current vertical scrolling offset in pixel units, relative to the
270
+ * workspace origin.
271
+ *
272
+ * It is useful to think about a view, and a canvas moving beneath that
273
+ * view. As the canvas moves down, this value becomes more positive, and the
274
+ * view is now "seeing" the upper part of the canvas. As the canvas moves
275
+ * up, this value becomes more negative, and the view is "seeing" the lower
276
+ * part of the canvas.
277
+ *
278
+ * This confusing thing about this value is that it does not, and must not
279
+ * include the absoluteTop offset. This is because it is used to calculate
280
+ * the viewTop value.
281
+ *
282
+ * The viewTop is relative to the workspace origin (although in pixel
283
+ * units). The workspace origin is the top-left corner of the workspace (at
284
+ * least when it is enabled). It is shifted from the top-left of the
285
+ * blocklyDiv so as not to be beneath the toolbox.
286
+ *
287
+ * When the workspace is enabled the viewTop and workspace origin are at the
288
+ * same Y location. As the canvas slides towards the bottom this value
289
+ * (scrollY) becomes more positive, and the viewTop becomes more negative
290
+ * relative to the workspace origin (image in the workspace origin as a dot
291
+ * on the canvas sliding downwards as the canvas moves).
292
+ *
293
+ * So if the scrollY were to include the absoluteTop this would in a way
294
+ * "unshift" the workspace origin. This means that the viewTop would be
295
+ * representing the top edge of the blocklyDiv, rather than the top edge of
296
+ * the workspace.
297
+ *
298
+ * @type {number}
299
+ */
300
+ Blockly.WorkspaceSvg.prototype.scrollY = 0;
301
+
302
+ /**
303
+ * Horizontal scroll value when scrolling started in pixel units.
304
+ * @type {number}
305
+ */
306
+ Blockly.WorkspaceSvg.prototype.startScrollX = 0;
307
+
308
+ /**
309
+ * Vertical scroll value when scrolling started in pixel units.
310
+ * @type {number}
311
+ */
312
+ Blockly.WorkspaceSvg.prototype.startScrollY = 0;
313
+
314
+ /**
315
+ * Distance from mouse to object being dragged.
316
+ * @type {Blockly.utils.Coordinate}
317
+ * @private
318
+ */
319
+ Blockly.WorkspaceSvg.prototype.dragDeltaXY_ = null;
320
+
321
+ /**
322
+ * Current scale.
323
+ * @type {number}
324
+ */
325
+ Blockly.WorkspaceSvg.prototype.scale = 1;
326
+
327
+ // TODO(#4203) Enable viewport events after ui events refactor.
328
+ // /**
329
+ // * Cached scale value. Used to detect changes in viewport.
330
+ // * @type {number}
331
+ // * @private
332
+ // */
333
+ // Blockly.WorkspaceSvg.prototype.oldScale_ = 1;
334
+ //
335
+ // /**
336
+ // * Cached viewport top value. Used to detect changes in viewport.
337
+ // * @type {number}
338
+ // * @private
339
+ // */
340
+ // Blockly.WorkspaceSvg.prototype.oldTop_ = 0;
341
+ //
342
+ // /**
343
+ // * Cached viewport left value. Used to detect changes in viewport.
344
+ // * @type {number}
345
+ // * @private
346
+ // */
347
+ // Blockly.WorkspaceSvg.prototype.oldLeft_ = 0;
348
+
349
+ /**
350
+ * The workspace's trashcan (if any).
351
+ * @type {Blockly.Trashcan}
352
+ */
353
+ Blockly.WorkspaceSvg.prototype.trashcan = null;
354
+
355
+ /**
356
+ * This workspace's scrollbars, if they exist.
357
+ * @type {Blockly.ScrollbarPair}
358
+ */
359
+ Blockly.WorkspaceSvg.prototype.scrollbar = null;
360
+
361
+ /**
362
+ * Fixed flyout providing blocks which may be dragged into this workspace.
363
+ * @type {Blockly.IFlyout}
364
+ * @private
365
+ */
366
+ Blockly.WorkspaceSvg.prototype.flyout_ = null;
367
+
368
+ /**
369
+ * Category-based toolbox providing blocks which may be dragged into this
370
+ * workspace.
371
+ * @type {Blockly.IToolbox}
372
+ * @private
373
+ */
374
+ Blockly.WorkspaceSvg.prototype.toolbox_ = null;
375
+
376
+ /**
377
+ * The current gesture in progress on this workspace, if any.
378
+ * @type {Blockly.TouchGesture}
379
+ * @private
380
+ */
381
+ Blockly.WorkspaceSvg.prototype.currentGesture_ = null;
382
+
383
+ /**
384
+ * This workspace's surface for dragging blocks, if it exists.
385
+ * @type {Blockly.BlockDragSurfaceSvg}
386
+ * @private
387
+ */
388
+ Blockly.WorkspaceSvg.prototype.blockDragSurface_ = null;
389
+
390
+ /**
391
+ * This workspace's drag surface, if it exists.
392
+ * @type {Blockly.WorkspaceDragSurfaceSvg}
393
+ * @private
394
+ */
395
+ Blockly.WorkspaceSvg.prototype.workspaceDragSurface_ = null;
396
+
397
+ /**
398
+ * Whether to move workspace to the drag surface when it is dragged.
399
+ * True if it should move, false if it should be translated directly.
400
+ * @type {boolean}
401
+ * @private
402
+ */
403
+ Blockly.WorkspaceSvg.prototype.useWorkspaceDragSurface_ = false;
404
+
405
+ /**
406
+ * Whether the drag surface is actively in use. When true, calls to
407
+ * translate will translate the drag surface instead of the translating the
408
+ * workspace directly.
409
+ * This is set to true in setupDragSurface and to false in resetDragSurface.
410
+ * @type {boolean}
411
+ * @private
412
+ */
413
+ Blockly.WorkspaceSvg.prototype.isDragSurfaceActive_ = false;
414
+
415
+ /**
416
+ * The first parent div with 'injectionDiv' in the name, or null if not set.
417
+ * Access this with getInjectionDiv.
418
+ * @type {Element}
419
+ * @private
420
+ */
421
+ Blockly.WorkspaceSvg.prototype.injectionDiv_ = null;
422
+
423
+ /**
424
+ * Last known position of the page scroll.
425
+ * This is used to determine whether we have recalculated screen coordinate
426
+ * stuff since the page scrolled.
427
+ * @type {Blockly.utils.Coordinate}
428
+ * @private
429
+ */
430
+ Blockly.WorkspaceSvg.prototype.lastRecordedPageScroll_ = null;
431
+
432
+ /**
433
+ * Developers may define this function to add custom menu options to the
434
+ * workspace's context menu or edit the workspace-created set of menu options.
435
+ * @param {!Array.<!Object>} options List of menu options to add to.
436
+ * @param {!Event} e The right-click event that triggered the context menu.
437
+ */
438
+ Blockly.WorkspaceSvg.prototype.configureContextMenu;
439
+
440
+ /**
441
+ * In a flyout, the target workspace where blocks should be placed after a drag.
442
+ * Otherwise null.
443
+ * @type {Blockly.WorkspaceSvg}
444
+ * @package
445
+ */
446
+ Blockly.WorkspaceSvg.prototype.targetWorkspace = null;
447
+
448
+ /**
449
+ * Inverted screen CTM, for use in mouseToSvg.
450
+ * @type {SVGMatrix}
451
+ * @private
452
+ */
453
+ Blockly.WorkspaceSvg.prototype.inverseScreenCTM_ = null;
454
+
455
+ /**
456
+ * Inverted screen CTM is dirty, recalculate it.
457
+ * @type {boolean}
458
+ * @private
459
+ */
460
+ Blockly.WorkspaceSvg.prototype.inverseScreenCTMDirty_ = true;
461
+
462
+ /**
463
+ * Get the marker manager for this workspace.
464
+ * @return {Blockly.MarkerManager} The marker manager.
465
+ */
466
+ Blockly.WorkspaceSvg.prototype.getMarkerManager = function() {
467
+ return this.markerManager_;
468
+ };
469
+
470
+ /**
471
+ * Add the cursor svg to this workspaces svg group.
472
+ * @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
473
+ * workspace svg group.
474
+ * @package
475
+ */
476
+ Blockly.WorkspaceSvg.prototype.setCursorSvg = function(cursorSvg) {
477
+ this.markerManager_.setCursorSvg(cursorSvg);
478
+ };
479
+
480
+ /**
481
+ * Add the marker svg to this workspaces svg group.
482
+ * @param {SVGElement} markerSvg The svg root of the marker to be added to the
483
+ * workspace svg group.
484
+ * @package
485
+ */
486
+ Blockly.WorkspaceSvg.prototype.setMarkerSvg = function(markerSvg) {
487
+ this.markerManager_.setMarkerSvg(markerSvg);
488
+ };
489
+
490
+ /**
491
+ * Get the marker with the given id.
492
+ * @param {string} id The id of the marker.
493
+ * @return {Blockly.Marker} The marker with the given id or null if no marker
494
+ * with the given id exists.
495
+ * @package
496
+ */
497
+ Blockly.WorkspaceSvg.prototype.getMarker = function(id) {
498
+ if (this.markerManager_) {
499
+ return this.markerManager_.getMarker(id);
500
+ }
501
+ return null;
502
+ };
503
+
504
+ /**
505
+ * The cursor for this workspace.
506
+ * @return {Blockly.Cursor} The cursor for the workspace.
507
+ */
508
+ Blockly.WorkspaceSvg.prototype.getCursor = function() {
509
+ if (this.markerManager_) {
510
+ return this.markerManager_.getCursor();
511
+ }
512
+ return null;
513
+ };
514
+
515
+ /**
516
+ * Get the block renderer attached to this workspace.
517
+ * @return {!Blockly.blockRendering.Renderer} The renderer attached to this workspace.
518
+ */
519
+ Blockly.WorkspaceSvg.prototype.getRenderer = function() {
520
+ return this.renderer_;
521
+ };
522
+
523
+ /**
524
+ * Get the theme manager for this workspace.
525
+ * @return {!Blockly.ThemeManager} The theme manager for this workspace.
526
+ * @package
527
+ */
528
+ Blockly.WorkspaceSvg.prototype.getThemeManager = function() {
529
+ return this.themeManager_;
530
+ };
531
+
532
+ /**
533
+ * Get the workspace theme object.
534
+ * @return {!Blockly.Theme} The workspace theme object.
535
+ */
536
+ Blockly.WorkspaceSvg.prototype.getTheme = function() {
537
+ return this.themeManager_.getTheme();
538
+ };
539
+
540
+ /**
541
+ * Set the workspace theme object.
542
+ * If no theme is passed, default to the `Blockly.Themes.Classic` theme.
543
+ * @param {Blockly.Theme} theme The workspace theme object.
544
+ */
545
+ Blockly.WorkspaceSvg.prototype.setTheme = function(theme) {
546
+ if (!theme) {
547
+ theme = /** @type {!Blockly.Theme} */ (Blockly.Themes.Classic);
548
+ }
549
+ this.themeManager_.setTheme(theme);
550
+ };
551
+
552
+ /**
553
+ * Refresh all blocks on the workspace after a theme update.
554
+ * @package
555
+ */
556
+ Blockly.WorkspaceSvg.prototype.refreshTheme = function() {
557
+ if (this.svgGroup_) {
558
+ this.renderer_.refreshDom(this.svgGroup_, this.getTheme());
559
+ }
560
+
561
+ // Update all blocks in workspace that have a style name.
562
+ this.updateBlockStyles_(this.getAllBlocks(false).filter(
563
+ function(block) {
564
+ return block.getStyleName() !== undefined;
565
+ }
566
+ ));
567
+
568
+ // Update current toolbox selection.
569
+ this.refreshToolboxSelection();
570
+ if (this.toolbox_) {
571
+ this.toolbox_.refreshTheme();
572
+ }
573
+
574
+ // Re-render if workspace is visible
575
+ if (this.isVisible()) {
576
+ this.setVisible(true);
577
+ }
578
+
579
+ var event = new Blockly.Events.Ui(null, 'theme', null, null);
580
+ event.workspaceId = this.id;
581
+ Blockly.Events.fire(event);
582
+ };
583
+
584
+ /**
585
+ * Updates all the blocks with new style.
586
+ * @param {!Array.<!Blockly.Block>} blocks List of blocks to update the style
587
+ * on.
588
+ * @private
589
+ */
590
+ Blockly.WorkspaceSvg.prototype.updateBlockStyles_ = function(blocks) {
591
+ for (var i = 0, block; (block = blocks[i]); i++) {
592
+ var blockStyleName = block.getStyleName();
593
+ if (blockStyleName) {
594
+ block.setStyle(blockStyleName);
595
+ if (block.mutator) {
596
+ block.mutator.updateBlockStyle();
597
+ }
598
+ }
599
+ }
600
+ };
601
+
602
+ /**
603
+ * Getter for the inverted screen CTM.
604
+ * @return {SVGMatrix} The matrix to use in mouseToSvg
605
+ */
606
+ Blockly.WorkspaceSvg.prototype.getInverseScreenCTM = function() {
607
+
608
+ // Defer getting the screen CTM until we actually need it, this should
609
+ // avoid forced reflows from any calls to updateInverseScreenCTM.
610
+ if (this.inverseScreenCTMDirty_) {
611
+ var ctm = this.getParentSvg().getScreenCTM();
612
+ if (ctm) {
613
+ this.inverseScreenCTM_ = ctm.inverse();
614
+ this.inverseScreenCTMDirty_ = false;
615
+ }
616
+ }
617
+
618
+ return this.inverseScreenCTM_;
619
+ };
620
+
621
+ /**
622
+ * Mark the inverse screen CTM as dirty.
623
+ */
624
+ Blockly.WorkspaceSvg.prototype.updateInverseScreenCTM = function() {
625
+ this.inverseScreenCTMDirty_ = true;
626
+ };
627
+
628
+ /**
629
+ * Getter for isVisible
630
+ * @return {boolean} Whether the workspace is visible.
631
+ * False if the workspace has been hidden by calling `setVisible(false)`.
632
+ */
633
+ Blockly.WorkspaceSvg.prototype.isVisible = function() {
634
+ return this.isVisible_;
635
+ };
636
+
637
+ /**
638
+ * Return the absolute coordinates of the top-left corner of this element,
639
+ * scales that after canvas SVG element, if it's a descendant.
640
+ * The origin (0,0) is the top-left corner of the Blockly SVG.
641
+ * @param {!SVGElement} element SVG element to find the coordinates of.
642
+ * @return {!Blockly.utils.Coordinate} Object with .x and .y properties.
643
+ * @package
644
+ */
645
+ Blockly.WorkspaceSvg.prototype.getSvgXY = function(element) {
646
+ var x = 0;
647
+ var y = 0;
648
+ var scale = 1;
649
+ if (Blockly.utils.dom.containsNode(this.getCanvas(), element) ||
650
+ Blockly.utils.dom.containsNode(this.getBubbleCanvas(), element)) {
651
+ // Before the SVG canvas, scale the coordinates.
652
+ scale = this.scale;
653
+ }
654
+ do {
655
+ // Loop through this block and every parent.
656
+ var xy = Blockly.utils.getRelativeXY(element);
657
+ if (element == this.getCanvas() ||
658
+ element == this.getBubbleCanvas()) {
659
+ // After the SVG canvas, don't scale the coordinates.
660
+ scale = 1;
661
+ }
662
+ x += xy.x * scale;
663
+ y += xy.y * scale;
664
+ element = /** @type {!SVGElement} */ (element.parentNode);
665
+ } while (element && element != this.getParentSvg());
666
+ return new Blockly.utils.Coordinate(x, y);
667
+ };
668
+
669
+ /**
670
+ * Return the position of the workspace origin relative to the injection div
671
+ * origin in pixels.
672
+ * The workspace origin is where a block would render at position (0, 0).
673
+ * It is not the upper left corner of the workspace SVG.
674
+ * @return {!Blockly.utils.Coordinate} Offset in pixels.
675
+ * @package
676
+ */
677
+ Blockly.WorkspaceSvg.prototype.getOriginOffsetInPixels = function() {
678
+ return Blockly.utils.getInjectionDivXY_(this.getCanvas());
679
+ };
680
+
681
+ /**
682
+ * Return the injection div that is a parent of this workspace.
683
+ * Walks the DOM the first time it's called, then returns a cached value.
684
+ * Note: We assume this is only called after the workspace has been injected
685
+ * into the DOM.
686
+ * @return {!Element} The first parent div with 'injectionDiv' in the name.
687
+ * @package
688
+ */
689
+ Blockly.WorkspaceSvg.prototype.getInjectionDiv = function() {
690
+ // NB: it would be better to pass this in at createDom, but is more likely to
691
+ // break existing uses of Blockly.
692
+ if (!this.injectionDiv_) {
693
+ var element = this.svgGroup_;
694
+ while (element) {
695
+ var classes = element.getAttribute('class') || '';
696
+ if ((' ' + classes + ' ').indexOf(' injectionDiv ') != -1) {
697
+ this.injectionDiv_ = element;
698
+ break;
699
+ }
700
+ element = /** @type {!Element} */ (element.parentNode);
701
+ }
702
+ }
703
+ return /** @type {!Element} */ (this.injectionDiv_);
704
+ };
705
+
706
+ /**
707
+ * Get the svg block canvas for the workspace.
708
+ * @return {SVGElement} The svg group for the workspace.
709
+ * @package
710
+ */
711
+ Blockly.WorkspaceSvg.prototype.getBlockCanvas = function() {
712
+ return this.svgBlockCanvas_;
713
+ };
714
+
715
+ /**
716
+ * Save resize handler data so we can delete it later in dispose.
717
+ * @param {!Array.<!Array>} handler Data that can be passed to unbindEvent_.
718
+ */
719
+ Blockly.WorkspaceSvg.prototype.setResizeHandlerWrapper = function(handler) {
720
+ this.resizeHandlerWrapper_ = handler;
721
+ };
722
+
723
+ /**
724
+ * Create the workspace DOM elements.
725
+ * @param {string=} opt_backgroundClass Either 'blocklyMainBackground' or
726
+ * 'blocklyMutatorBackground'.
727
+ * @return {!Element} The workspace's SVG group.
728
+ */
729
+ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) {
730
+ /**
731
+ * <g class="blocklyWorkspace">
732
+ * <rect class="blocklyMainBackground" height="100%" width="100%"></rect>
733
+ * [Trashcan and/or flyout may go here]
734
+ * <g class="blocklyBlockCanvas"></g>
735
+ * <g class="blocklyBubbleCanvas"></g>
736
+ * </g>
737
+ * @type {SVGElement}
738
+ */
739
+ this.svgGroup_ = Blockly.utils.dom.createSvgElement(
740
+ Blockly.utils.Svg.G,
741
+ {'class': 'blocklyWorkspace'}, null);
742
+
743
+ // Note that a <g> alone does not receive mouse events--it must have a
744
+ // valid target inside it. If no background class is specified, as in the
745
+ // flyout, the workspace will not receive mouse events.
746
+ if (opt_backgroundClass) {
747
+ /** @type {SVGElement} */
748
+ this.svgBackground_ = Blockly.utils.dom.createSvgElement(
749
+ Blockly.utils.Svg.RECT,
750
+ {'height': '100%', 'width': '100%', 'class': opt_backgroundClass},
751
+ this.svgGroup_);
752
+
753
+ if (opt_backgroundClass == 'blocklyMainBackground' && this.grid_) {
754
+ this.svgBackground_.style.fill =
755
+ 'url(#' + this.grid_.getPatternId() + ')';
756
+ } else {
757
+ this.themeManager_.subscribe(this.svgBackground_,
758
+ 'workspaceBackgroundColour', 'fill');
759
+ }
760
+ }
761
+ /** @type {SVGElement} */
762
+ this.svgBlockCanvas_ = Blockly.utils.dom.createSvgElement(
763
+ Blockly.utils.Svg.G,
764
+ {'class': 'blocklyBlockCanvas'}, this.svgGroup_);
765
+ /** @type {SVGElement} */
766
+ this.svgBubbleCanvas_ = Blockly.utils.dom.createSvgElement(
767
+ Blockly.utils.Svg.G,
768
+ {'class': 'blocklyBubbleCanvas'}, this.svgGroup_);
769
+
770
+ if (!this.isFlyout) {
771
+ Blockly.bindEventWithChecks_(this.svgGroup_, 'mousedown', this,
772
+ this.onMouseDown_, false, true);
773
+ Blockly.bindEventWithChecks_(this.svgGroup_, 'wheel', this,
774
+ this.onMouseWheel_);
775
+ }
776
+
777
+ // Determine if there needs to be a category tree, or a simple list of
778
+ // blocks. This cannot be changed later, since the UI is very different.
779
+ if (this.options.hasCategories) {
780
+ if (!Blockly.Toolbox) {
781
+ throw Error('Missing require for Blockly.Toolbox');
782
+ }
783
+ var ToolboxClass = Blockly.registry.getClassFromOptions(
784
+ Blockly.registry.Type.TOOLBOX, this.options);
785
+ this.toolbox_ = new ToolboxClass(this);
786
+ }
787
+ if (this.grid_) {
788
+ this.grid_.update(this.scale);
789
+ }
790
+ this.recordDeleteAreas();
791
+
792
+ this.markerManager_.setCursor(new Blockly.Cursor());
793
+ this.markerManager_.registerMarker(Blockly.navigation.MARKER_NAME,
794
+ new Blockly.Marker());
795
+
796
+ this.renderer_.createDom(this.svgGroup_, this.getTheme());
797
+ return this.svgGroup_;
798
+ };
799
+
800
+ /**
801
+ * Dispose of this workspace.
802
+ * Unlink from all DOM elements to prevent memory leaks.
803
+ * @suppress {checkTypes}
804
+ */
805
+ Blockly.WorkspaceSvg.prototype.dispose = function() {
806
+ // Stop rerendering.
807
+ this.rendered = false;
808
+ if (this.currentGesture_) {
809
+ this.currentGesture_.cancel();
810
+ }
811
+ if (this.svgGroup_) {
812
+ Blockly.utils.dom.removeNode(this.svgGroup_);
813
+ this.svgGroup_ = null;
814
+ }
815
+ this.svgBlockCanvas_ = null;
816
+ this.svgBubbleCanvas_ = null;
817
+ if (this.toolbox_) {
818
+ this.toolbox_.dispose();
819
+ this.toolbox_ = null;
820
+ }
821
+ if (this.flyout_) {
822
+ this.flyout_.dispose();
823
+ this.flyout_ = null;
824
+ }
825
+ if (this.trashcan) {
826
+ this.trashcan.dispose();
827
+ this.trashcan = null;
828
+ }
829
+ if (this.scrollbar) {
830
+ this.scrollbar.dispose();
831
+ this.scrollbar = null;
832
+ }
833
+ if (this.zoomControls_) {
834
+ this.zoomControls_.dispose();
835
+ this.zoomControls_ = null;
836
+ }
837
+
838
+ if (this.audioManager_) {
839
+ this.audioManager_.dispose();
840
+ this.audioManager_ = null;
841
+ }
842
+
843
+ if (this.grid_) {
844
+ this.grid_.dispose();
845
+ this.grid_ = null;
846
+ }
847
+
848
+ this.renderer_.dispose();
849
+
850
+ if (this.markerManager_) {
851
+ this.markerManager_.dispose();
852
+ this.markerManager_ = null;
853
+ }
854
+
855
+ Blockly.WorkspaceSvg.superClass_.dispose.call(this);
856
+
857
+ // Dispose of theme manager after all blocks and mutators are disposed of.
858
+ if (this.themeManager_) {
859
+ this.themeManager_.unsubscribeWorkspace(this);
860
+ this.themeManager_.unsubscribe(this.svgBackground_);
861
+ if (!this.options.parentWorkspace) {
862
+ this.themeManager_.dispose();
863
+ this.themeManager_ = null;
864
+ }
865
+ }
866
+
867
+ this.connectionDBList = null;
868
+
869
+ this.toolboxCategoryCallbacks_ = null;
870
+ this.flyoutButtonCallbacks_ = null;
871
+
872
+ if (!this.options.parentWorkspace) {
873
+ // Top-most workspace. Dispose of the div that the
874
+ // SVG is injected into (i.e. injectionDiv).
875
+ var parentSvg = this.getParentSvg();
876
+ if (parentSvg && parentSvg.parentNode) {
877
+ Blockly.utils.dom.removeNode(parentSvg.parentNode);
878
+ }
879
+ }
880
+ if (this.resizeHandlerWrapper_) {
881
+ Blockly.unbindEvent_(this.resizeHandlerWrapper_);
882
+ this.resizeHandlerWrapper_ = null;
883
+ }
884
+ };
885
+
886
+ /**
887
+ * Obtain a newly created block.
888
+ *
889
+ * This block's svg must still be initialized
890
+ * ([initSvg]{@link Blockly.BlockSvg#initSvg}) and it must be rendered
891
+ * ([render]{@link Blockly.BlockSvg#render}) before the block will be visible.
892
+ * @param {!string} prototypeName Name of the language object containing
893
+ * type-specific functions for this block.
894
+ * @param {string=} opt_id Optional ID. Use this ID if provided, otherwise
895
+ * create a new ID.
896
+ * @return {!Blockly.BlockSvg} The created block.
897
+ * @override
898
+ */
899
+ Blockly.WorkspaceSvg.prototype.newBlock = function(prototypeName, opt_id) {
900
+ return new Blockly.BlockSvg(this, prototypeName, opt_id);
901
+ };
902
+
903
+ /**
904
+ * Add a trashcan.
905
+ * @package
906
+ */
907
+ Blockly.WorkspaceSvg.prototype.addTrashcan = function() {
908
+ if (!Blockly.Trashcan) {
909
+ throw Error('Missing require for Blockly.Trashcan');
910
+ }
911
+ /** @type {Blockly.Trashcan} */
912
+ this.trashcan = new Blockly.Trashcan(this);
913
+ var svgTrashcan = this.trashcan.createDom();
914
+ this.svgGroup_.insertBefore(svgTrashcan, this.svgBlockCanvas_);
915
+ };
916
+
917
+ /**
918
+ * Add zoom controls.
919
+ * @package
920
+ */
921
+ Blockly.WorkspaceSvg.prototype.addZoomControls = function() {
922
+ if (!Blockly.ZoomControls) {
923
+ throw Error('Missing require for Blockly.ZoomControls');
924
+ }
925
+ /** @type {Blockly.ZoomControls} */
926
+ this.zoomControls_ = new Blockly.ZoomControls(this);
927
+ var svgZoomControls = this.zoomControls_.createDom();
928
+ this.svgGroup_.appendChild(svgZoomControls);
929
+ };
930
+
931
+ /**
932
+ * Add a flyout element in an element with the given tag name.
933
+ * @param {string|
934
+ * !Blockly.utils.Svg<!SVGSVGElement>|
935
+ * !Blockly.utils.Svg<!SVGGElement>} tagName What type of tag the
936
+ * flyout belongs in.
937
+ * @return {!Element} The element containing the flyout DOM.
938
+ * @package
939
+ */
940
+ Blockly.WorkspaceSvg.prototype.addFlyout = function(tagName) {
941
+ var workspaceOptions = new Blockly.Options(
942
+ /** @type {!Blockly.BlocklyOptions} */
943
+ ({
944
+ 'parentWorkspace': this,
945
+ 'rtl': this.RTL,
946
+ 'oneBasedIndex': this.options.oneBasedIndex,
947
+ 'horizontalLayout': this.horizontalLayout,
948
+ 'renderer': this.options.renderer,
949
+ 'rendererOverrides': this.options.rendererOverrides
950
+ }));
951
+ workspaceOptions.toolboxPosition = this.options.toolboxPosition;
952
+ if (this.horizontalLayout) {
953
+ if (!Blockly.HorizontalFlyout) {
954
+ throw Error('Missing require for Blockly.HorizontalFlyout');
955
+ }
956
+ this.flyout_ = new Blockly.HorizontalFlyout(workspaceOptions);
957
+ } else {
958
+ if (!Blockly.VerticalFlyout) {
959
+ throw Error('Missing require for Blockly.VerticalFlyout');
960
+ }
961
+ this.flyout_ = new Blockly.VerticalFlyout(workspaceOptions);
962
+ }
963
+ this.flyout_.autoClose = false;
964
+ this.flyout_.getWorkspace().setVisible(true);
965
+
966
+ // Return the element so that callers can place it in their desired
967
+ // spot in the DOM. For example, mutator flyouts do not go in the same place
968
+ // as main workspace flyouts.
969
+ return this.flyout_.createDom(tagName);
970
+ };
971
+
972
+ /**
973
+ * Getter for the flyout associated with this workspace. This flyout may be
974
+ * owned by either the toolbox or the workspace, depending on toolbox
975
+ * configuration. It will be null if there is no flyout.
976
+ * @param {boolean=} opt_own Only return the workspace's own flyout if True.
977
+ * @return {Blockly.IFlyout} The flyout on this workspace.
978
+ * @package
979
+ */
980
+ Blockly.WorkspaceSvg.prototype.getFlyout = function(opt_own) {
981
+ if (this.flyout_ || opt_own) {
982
+ return this.flyout_;
983
+ }
984
+ if (this.toolbox_) {
985
+ return this.toolbox_.getFlyout();
986
+ }
987
+ return null;
988
+ };
989
+
990
+ /**
991
+ * Getter for the toolbox associated with this workspace, if one exists.
992
+ * @return {Blockly.IToolbox} The toolbox on this workspace.
993
+ * @package
994
+ */
995
+ Blockly.WorkspaceSvg.prototype.getToolbox = function() {
996
+ return this.toolbox_;
997
+ };
998
+
999
+ /**
1000
+ * Update items that use screen coordinate calculations
1001
+ * because something has changed (e.g. scroll position, window size).
1002
+ * @private
1003
+ */
1004
+ Blockly.WorkspaceSvg.prototype.updateScreenCalculations_ = function() {
1005
+ this.updateInverseScreenCTM();
1006
+ this.recordDeleteAreas();
1007
+ };
1008
+
1009
+ /**
1010
+ * If enabled, resize the parts of the workspace that change when the workspace
1011
+ * contents (e.g. block positions) change. This will also scroll the
1012
+ * workspace contents if needed.
1013
+ * @package
1014
+ */
1015
+ Blockly.WorkspaceSvg.prototype.resizeContents = function() {
1016
+ if (!this.resizesEnabled_ || !this.rendered) {
1017
+ return;
1018
+ }
1019
+ if (this.scrollbar) {
1020
+ this.scrollbar.resize();
1021
+ }
1022
+ this.updateInverseScreenCTM();
1023
+ };
1024
+
1025
+ /**
1026
+ * Resize and reposition all of the workspace chrome (toolbox,
1027
+ * trash, scrollbars etc.)
1028
+ * This should be called when something changes that
1029
+ * requires recalculating dimensions and positions of the
1030
+ * trash, zoom, toolbox, etc. (e.g. window resize).
1031
+ */
1032
+ Blockly.WorkspaceSvg.prototype.resize = function() {
1033
+ if (this.toolbox_) {
1034
+ this.toolbox_.position();
1035
+ }
1036
+ if (this.flyout_) {
1037
+ this.flyout_.position();
1038
+ }
1039
+ if (this.trashcan) {
1040
+ this.trashcan.position();
1041
+ }
1042
+ if (this.zoomControls_) {
1043
+ this.zoomControls_.position();
1044
+ }
1045
+ if (this.scrollbar) {
1046
+ this.scrollbar.resize();
1047
+ }
1048
+ this.updateScreenCalculations_();
1049
+ };
1050
+
1051
+ /**
1052
+ * Resizes and repositions workspace chrome if the page has a new
1053
+ * scroll position.
1054
+ * @package
1055
+ */
1056
+ Blockly.WorkspaceSvg.prototype.updateScreenCalculationsIfScrolled =
1057
+ function() {
1058
+ /* eslint-disable indent */
1059
+ var currScroll = Blockly.utils.getDocumentScroll();
1060
+ if (!Blockly.utils.Coordinate.equals(
1061
+ this.lastRecordedPageScroll_, currScroll)) {
1062
+ this.lastRecordedPageScroll_ = currScroll;
1063
+ this.updateScreenCalculations_();
1064
+ }
1065
+ }; /* eslint-enable indent */
1066
+
1067
+ /**
1068
+ * Get the SVG element that forms the drawing surface.
1069
+ * @return {!SVGGElement} SVG group element.
1070
+ */
1071
+ Blockly.WorkspaceSvg.prototype.getCanvas = function() {
1072
+ return /** @type {!SVGGElement} */ (this.svgBlockCanvas_);
1073
+ };
1074
+
1075
+ /**
1076
+ * Get the SVG element that forms the bubble surface.
1077
+ * @return {!SVGGElement} SVG group element.
1078
+ */
1079
+ Blockly.WorkspaceSvg.prototype.getBubbleCanvas = function() {
1080
+ return /** @type {!SVGGElement} */ (this.svgBubbleCanvas_);
1081
+ };
1082
+
1083
+ /**
1084
+ * Get the SVG element that contains this workspace.
1085
+ * Note: We assume this is only called after the workspace has been injected
1086
+ * into the DOM.
1087
+ * @return {!SVGElement} SVG element.
1088
+ */
1089
+ Blockly.WorkspaceSvg.prototype.getParentSvg = function() {
1090
+ if (!this.cachedParentSvg_) {
1091
+ var element = this.svgGroup_;
1092
+ while (element) {
1093
+ if (element.tagName == 'svg') {
1094
+ this.cachedParentSvg_ = element;
1095
+ break;
1096
+ }
1097
+ element = /** @type {!SVGElement} */ (element.parentNode);
1098
+ }
1099
+ }
1100
+ return /** @type {!SVGElement} */ (this.cachedParentSvg_);
1101
+ };
1102
+
1103
+ /**
1104
+ * Fires a viewport event if events are enabled and there is a change in
1105
+ * viewport values.
1106
+ * @package
1107
+ */
1108
+ Blockly.WorkspaceSvg.prototype.maybeFireViewportChangeEvent = function() {
1109
+ // TODO(#4203) Enable viewport events after ui events refactor.
1110
+ // if (!Blockly.Events.isEnabled()) {
1111
+ // return;
1112
+ // }
1113
+ // var scale = this.scale;
1114
+ // var top = -this.scrollY;
1115
+ // var left = -this.scrollX;
1116
+ // if (scale == this.oldScale_ && top == this.oldTop_ && left == this.oldLeft_) {
1117
+ // return;
1118
+ // }
1119
+ // this.oldScale_ = scale;
1120
+ // this.oldTop_ = top;
1121
+ // this.oldLeft_ = left;
1122
+ // var event = new Blockly.Events.Ui(null, 'viewport', null,
1123
+ // { scale: scale, top: top, left: left });
1124
+ // event.workspaceId = this.id;
1125
+ // Blockly.Events.fire(event);
1126
+ };
1127
+
1128
+ /**
1129
+ * Translate this workspace to new coordinates.
1130
+ * @param {number} x Horizontal translation, in pixel units relative to the
1131
+ * top left of the Blockly div.
1132
+ * @param {number} y Vertical translation, in pixel units relative to the
1133
+ * top left of the Blockly div.
1134
+ */
1135
+ Blockly.WorkspaceSvg.prototype.translate = function(x, y) {
1136
+ if (this.useWorkspaceDragSurface_ && this.isDragSurfaceActive_) {
1137
+ this.workspaceDragSurface_.translateSurface(x,y);
1138
+ } else {
1139
+ var translation = 'translate(' + x + ',' + y + ') ' +
1140
+ 'scale(' + this.scale + ')';
1141
+ this.svgBlockCanvas_.setAttribute('transform', translation);
1142
+ this.svgBubbleCanvas_.setAttribute('transform', translation);
1143
+ }
1144
+ // Now update the block drag surface if we're using one.
1145
+ if (this.blockDragSurface_) {
1146
+ this.blockDragSurface_.translateAndScaleGroup(x, y, this.scale);
1147
+ }
1148
+ // And update the grid if we're using one.
1149
+ if (this.grid_) {
1150
+ this.grid_.moveTo(x, y);
1151
+ }
1152
+
1153
+ this.maybeFireViewportChangeEvent();
1154
+ };
1155
+
1156
+ /**
1157
+ * Called at the end of a workspace drag to take the contents
1158
+ * out of the drag surface and put them back into the workspace SVG.
1159
+ * Does nothing if the workspace drag surface is not enabled.
1160
+ * @package
1161
+ */
1162
+ Blockly.WorkspaceSvg.prototype.resetDragSurface = function() {
1163
+ // Don't do anything if we aren't using a drag surface.
1164
+ if (!this.useWorkspaceDragSurface_) {
1165
+ return;
1166
+ }
1167
+
1168
+ this.isDragSurfaceActive_ = false;
1169
+
1170
+ var trans = this.workspaceDragSurface_.getSurfaceTranslation();
1171
+ this.workspaceDragSurface_.clearAndHide(this.svgGroup_);
1172
+ var translation = 'translate(' + trans.x + ',' + trans.y + ') ' +
1173
+ 'scale(' + this.scale + ')';
1174
+ this.svgBlockCanvas_.setAttribute('transform', translation);
1175
+ this.svgBubbleCanvas_.setAttribute('transform', translation);
1176
+ };
1177
+
1178
+ /**
1179
+ * Called at the beginning of a workspace drag to move contents of
1180
+ * the workspace to the drag surface.
1181
+ * Does nothing if the drag surface is not enabled.
1182
+ * @package
1183
+ */
1184
+ Blockly.WorkspaceSvg.prototype.setupDragSurface = function() {
1185
+ // Don't do anything if we aren't using a drag surface.
1186
+ if (!this.useWorkspaceDragSurface_) {
1187
+ return;
1188
+ }
1189
+
1190
+ // This can happen if the user starts a drag, mouses up outside of the
1191
+ // document where the mouseup listener is registered (e.g. outside of an
1192
+ // iframe) and then moves the mouse back in the workspace. On mobile and ff,
1193
+ // we get the mouseup outside the frame. On chrome and safari desktop we do
1194
+ // not.
1195
+ if (this.isDragSurfaceActive_) {
1196
+ return;
1197
+ }
1198
+
1199
+ this.isDragSurfaceActive_ = true;
1200
+
1201
+ // Figure out where we want to put the canvas back. The order
1202
+ // in the is important because things are layered.
1203
+ var previousElement =
1204
+ /** @type {Element} */ (this.svgBlockCanvas_.previousSibling);
1205
+ var width = parseInt(this.getParentSvg().getAttribute('width'), 10);
1206
+ var height = parseInt(this.getParentSvg().getAttribute('height'), 10);
1207
+ var coord = Blockly.utils.getRelativeXY(this.getCanvas());
1208
+ this.workspaceDragSurface_.setContentsAndShow(this.getCanvas(),
1209
+ this.getBubbleCanvas(), previousElement, width, height, this.scale);
1210
+ this.workspaceDragSurface_.translateSurface(coord.x, coord.y);
1211
+ };
1212
+
1213
+ /**
1214
+ * @return {Blockly.BlockDragSurfaceSvg} This workspace's block drag surface,
1215
+ * if one is in use.
1216
+ * @package
1217
+ */
1218
+ Blockly.WorkspaceSvg.prototype.getBlockDragSurface = function() {
1219
+ return this.blockDragSurface_;
1220
+ };
1221
+
1222
+ /**
1223
+ * Returns the horizontal offset of the workspace.
1224
+ * Intended for LTR/RTL compatibility in XML.
1225
+ * @return {number} Width.
1226
+ */
1227
+ Blockly.WorkspaceSvg.prototype.getWidth = function() {
1228
+ var metrics = this.getMetrics();
1229
+ return metrics ? metrics.viewWidth / this.scale : 0;
1230
+ };
1231
+
1232
+ /**
1233
+ * Toggles the visibility of the workspace.
1234
+ * Currently only intended for main workspace.
1235
+ * @param {boolean} isVisible True if workspace should be visible.
1236
+ */
1237
+ Blockly.WorkspaceSvg.prototype.setVisible = function(isVisible) {
1238
+ this.isVisible_ = isVisible;
1239
+ if (!this.svgGroup_) {
1240
+ return;
1241
+ }
1242
+
1243
+ // Tell the scrollbar whether its container is visible so it can
1244
+ // tell when to hide itself.
1245
+ if (this.scrollbar) {
1246
+ this.scrollbar.setContainerVisible(isVisible);
1247
+ }
1248
+
1249
+ // Tell the flyout whether its container is visible so it can
1250
+ // tell when to hide itself.
1251
+ if (this.getFlyout()) {
1252
+ this.getFlyout().setContainerVisible(isVisible);
1253
+ }
1254
+
1255
+ this.getParentSvg().style.display = isVisible ? 'block' : 'none';
1256
+ if (this.toolbox_) {
1257
+ // Currently does not support toolboxes in mutators.
1258
+ this.toolbox_.setVisible(isVisible);
1259
+ }
1260
+ if (isVisible) {
1261
+ var blocks = this.getAllBlocks(false);
1262
+ // Tell each block on the workspace to mark its fields as dirty.
1263
+ for (var i = blocks.length - 1; i >= 0; i--) {
1264
+ blocks[i].markDirty();
1265
+ }
1266
+
1267
+ this.render();
1268
+ if (this.toolbox_) {
1269
+ this.toolbox_.position();
1270
+ }
1271
+ } else {
1272
+ Blockly.hideChaff(true);
1273
+ }
1274
+ };
1275
+
1276
+ /**
1277
+ * Render all blocks in workspace.
1278
+ */
1279
+ Blockly.WorkspaceSvg.prototype.render = function() {
1280
+ // Generate list of all blocks.
1281
+ var blocks = this.getAllBlocks(false);
1282
+ // Render each block.
1283
+ for (var i = blocks.length - 1; i >= 0; i--) {
1284
+ blocks[i].render(false);
1285
+ }
1286
+
1287
+ if (this.currentGesture_) {
1288
+ var imList = this.currentGesture_.getInsertionMarkers();
1289
+ for (var i = 0; i < imList.length; i++) {
1290
+ imList[i].render(false);
1291
+ }
1292
+ }
1293
+
1294
+ this.markerManager_.updateMarkers();
1295
+ };
1296
+
1297
+ /**
1298
+ * Highlight or unhighlight a block in the workspace. Block highlighting is
1299
+ * often used to visually mark blocks currently being executed.
1300
+ * @param {?string} id ID of block to highlight/unhighlight,
1301
+ * or null for no block (used to unhighlight all blocks).
1302
+ * @param {boolean=} opt_state If undefined, highlight specified block and
1303
+ * automatically unhighlight all others. If true or false, manually
1304
+ * highlight/unhighlight the specified block.
1305
+ */
1306
+ Blockly.WorkspaceSvg.prototype.highlightBlock = function(id, opt_state) {
1307
+ if (opt_state === undefined) {
1308
+ // Unhighlight all blocks.
1309
+ for (var i = 0, block; (block = this.highlightedBlocks_[i]); i++) {
1310
+ block.setHighlighted(false);
1311
+ }
1312
+ this.highlightedBlocks_.length = 0;
1313
+ }
1314
+ // Highlight/unhighlight the specified block.
1315
+ var block = id ? this.getBlockById(id) : null;
1316
+ if (block) {
1317
+ var state = (opt_state === undefined) || opt_state;
1318
+ // Using Set here would be great, but at the cost of IE10 support.
1319
+ if (!state) {
1320
+ Blockly.utils.arrayRemove(this.highlightedBlocks_, block);
1321
+ } else if (this.highlightedBlocks_.indexOf(block) == -1) {
1322
+ this.highlightedBlocks_.push(block);
1323
+ }
1324
+ block.setHighlighted(state);
1325
+ }
1326
+ };
1327
+
1328
+ /**
1329
+ * Paste the provided block onto the workspace.
1330
+ * @param {!Element|!DocumentFragment} xmlBlock XML block element or an empty
1331
+ * DocumentFragment if the block was an insertion marker.
1332
+ */
1333
+ Blockly.WorkspaceSvg.prototype.paste = function(xmlBlock) {
1334
+ if (!this.rendered || !xmlBlock.tagName || xmlBlock.getElementsByTagName('block').length >=
1335
+ this.remainingCapacity()) {
1336
+ return;
1337
+ }
1338
+ // The check above for tagName rules out the possibility of this being a DocumentFragment.
1339
+ xmlBlock = /** @type {!Element} */ (xmlBlock);
1340
+ if (this.currentGesture_) {
1341
+ this.currentGesture_.cancel(); // Dragging while pasting? No.
1342
+ }
1343
+ if (xmlBlock.tagName.toLowerCase() == 'comment') {
1344
+ this.pasteWorkspaceComment_(xmlBlock);
1345
+ } else {
1346
+ this.pasteBlock_(xmlBlock);
1347
+ }
1348
+ };
1349
+
1350
+ /**
1351
+ * Paste the provided block onto the workspace.
1352
+ * @param {!Element} xmlBlock XML block element.
1353
+ * @private
1354
+ */
1355
+ Blockly.WorkspaceSvg.prototype.pasteBlock_ = function(xmlBlock) {
1356
+ Blockly.Events.disable();
1357
+ try {
1358
+ var block = Blockly.Xml.domToBlock(xmlBlock, this);
1359
+
1360
+ // Handle paste for keyboard navigation
1361
+ var markedNode = this.getMarker(Blockly.navigation.MARKER_NAME).getCurNode();
1362
+ if (this.keyboardAccessibilityMode && markedNode &&
1363
+ markedNode.isConnection()) {
1364
+ var markedLocation =
1365
+ /** @type {!Blockly.RenderedConnection} */ (markedNode.getLocation());
1366
+ Blockly.navigation.insertBlock(/** @type {!Blockly.BlockSvg} */ (block),
1367
+ markedLocation);
1368
+ return;
1369
+ }
1370
+
1371
+ // Move the duplicate to original position.
1372
+ var blockX = parseInt(xmlBlock.getAttribute('x'), 10);
1373
+ var blockY = parseInt(xmlBlock.getAttribute('y'), 10);
1374
+ if (!isNaN(blockX) && !isNaN(blockY)) {
1375
+ if (this.RTL) {
1376
+ blockX = -blockX;
1377
+ }
1378
+ // Offset block until not clobbering another block and not in connection
1379
+ // distance with neighbouring blocks.
1380
+ do {
1381
+ var collide = false;
1382
+ var allBlocks = this.getAllBlocks(false);
1383
+ for (var i = 0, otherBlock; (otherBlock = allBlocks[i]); i++) {
1384
+ var otherXY = otherBlock.getRelativeToSurfaceXY();
1385
+ if (Math.abs(blockX - otherXY.x) <= 1 &&
1386
+ Math.abs(blockY - otherXY.y) <= 1) {
1387
+ collide = true;
1388
+ break;
1389
+ }
1390
+ }
1391
+ if (!collide) {
1392
+ // Check for blocks in snap range to any of its connections.
1393
+ var connections = block.getConnections_(false);
1394
+ for (var i = 0, connection; (connection = connections[i]); i++) {
1395
+ var neighbour = connection.closest(Blockly.SNAP_RADIUS,
1396
+ new Blockly.utils.Coordinate(blockX, blockY));
1397
+ if (neighbour.connection) {
1398
+ collide = true;
1399
+ break;
1400
+ }
1401
+ }
1402
+ }
1403
+ if (collide) {
1404
+ if (this.RTL) {
1405
+ blockX -= Blockly.SNAP_RADIUS;
1406
+ } else {
1407
+ blockX += Blockly.SNAP_RADIUS;
1408
+ }
1409
+ blockY += Blockly.SNAP_RADIUS * 2;
1410
+ }
1411
+ } while (collide);
1412
+ block.moveBy(blockX, blockY);
1413
+ }
1414
+ } finally {
1415
+ Blockly.Events.enable();
1416
+ }
1417
+ if (Blockly.Events.isEnabled() && !block.isShadow()) {
1418
+ Blockly.Events.fire(new Blockly.Events.BlockCreate(block));
1419
+ }
1420
+ block.select();
1421
+ };
1422
+
1423
+ /**
1424
+ * Paste the provided comment onto the workspace.
1425
+ * @param {!Element} xmlComment XML workspace comment element.
1426
+ * @private
1427
+ * @suppress {checkTypes} Suppress checks while workspace comments are not
1428
+ * bundled in.
1429
+ */
1430
+ Blockly.WorkspaceSvg.prototype.pasteWorkspaceComment_ = function(xmlComment) {
1431
+ Blockly.Events.disable();
1432
+ try {
1433
+ var comment = Blockly.WorkspaceCommentSvg.fromXml(xmlComment, this);
1434
+ // Move the duplicate to original position.
1435
+ var commentX = parseInt(xmlComment.getAttribute('x'), 10);
1436
+ var commentY = parseInt(xmlComment.getAttribute('y'), 10);
1437
+ if (!isNaN(commentX) && !isNaN(commentY)) {
1438
+ if (this.RTL) {
1439
+ commentX = -commentX;
1440
+ }
1441
+ // Offset workspace comment.
1442
+ // TODO (#1719): Properly offset comment such that it's not interfering
1443
+ // with any blocks.
1444
+ commentX += 50;
1445
+ commentY += 50;
1446
+ comment.moveBy(commentX, commentY);
1447
+ }
1448
+ } finally {
1449
+ Blockly.Events.enable();
1450
+ }
1451
+ if (Blockly.Events.isEnabled()) {
1452
+ // TODO: Fire a Workspace Comment Create event.
1453
+ }
1454
+ comment.select();
1455
+ };
1456
+
1457
+ /**
1458
+ * Refresh the toolbox unless there's a drag in progress.
1459
+ * @package
1460
+ */
1461
+ Blockly.WorkspaceSvg.prototype.refreshToolboxSelection = function() {
1462
+ var ws = this.isFlyout ? this.targetWorkspace : this;
1463
+ if (ws && !ws.currentGesture_ && ws.toolbox_ && ws.toolbox_.getFlyout()) {
1464
+ ws.toolbox_.refreshSelection();
1465
+ }
1466
+ };
1467
+
1468
+ /**
1469
+ * Rename a variable by updating its name in the variable map. Update the
1470
+ * flyout to show the renamed variable immediately.
1471
+ * @param {string} id ID of the variable to rename.
1472
+ * @param {string} newName New variable name.
1473
+ */
1474
+ Blockly.WorkspaceSvg.prototype.renameVariableById = function(id, newName) {
1475
+ Blockly.WorkspaceSvg.superClass_.renameVariableById.call(this, id, newName);
1476
+ this.refreshToolboxSelection();
1477
+ };
1478
+
1479
+ /**
1480
+ * Delete a variable by the passed in ID. Update the flyout to show
1481
+ * immediately that the variable is deleted.
1482
+ * @param {string} id ID of variable to delete.
1483
+ */
1484
+ Blockly.WorkspaceSvg.prototype.deleteVariableById = function(id) {
1485
+ Blockly.WorkspaceSvg.superClass_.deleteVariableById.call(this, id);
1486
+ this.refreshToolboxSelection();
1487
+ };
1488
+
1489
+ /**
1490
+ * Create a new variable with the given name. Update the flyout to show the
1491
+ * new variable immediately.
1492
+ * @param {string} name The new variable's name.
1493
+ * @param {?string=} opt_type The type of the variable like 'int' or 'string'.
1494
+ * Does not need to be unique. Field_variable can filter variables based on
1495
+ * their type. This will default to '' which is a specific type.
1496
+ * @param {?string=} opt_id The unique ID of the variable. This will default to
1497
+ * a UUID.
1498
+ * @return {!Blockly.VariableModel} The newly created variable.
1499
+ */
1500
+ Blockly.WorkspaceSvg.prototype.createVariable = function(name,
1501
+ opt_type, opt_id) {
1502
+ var newVar = Blockly.WorkspaceSvg.superClass_.createVariable.call(
1503
+ this, name, opt_type, opt_id);
1504
+ this.refreshToolboxSelection();
1505
+ return newVar;
1506
+ };
1507
+
1508
+ /**
1509
+ * Make a list of all the delete areas for this workspace.
1510
+ */
1511
+ Blockly.WorkspaceSvg.prototype.recordDeleteAreas = function() {
1512
+ if (this.trashcan && this.svgGroup_.parentNode) {
1513
+ this.deleteAreaTrash_ = this.trashcan.getClientRect();
1514
+ } else {
1515
+ this.deleteAreaTrash_ = null;
1516
+ }
1517
+ if (this.flyout_) {
1518
+ this.deleteAreaToolbox_ = this.flyout_.getClientRect();
1519
+ } else if (this.toolbox_ && typeof this.toolbox_.getClientRect == 'function') {
1520
+ this.deleteAreaToolbox_ = this.toolbox_.getClientRect();
1521
+ } else {
1522
+ this.deleteAreaToolbox_ = null;
1523
+ }
1524
+ };
1525
+
1526
+ /**
1527
+ * Is the mouse event over a delete area (toolbox or non-closing flyout)?
1528
+ * @param {!Event} e Mouse move event.
1529
+ * @return {?number} Null if not over a delete area, or an enum representing
1530
+ * which delete area the event is over.
1531
+ */
1532
+ Blockly.WorkspaceSvg.prototype.isDeleteArea = function(e) {
1533
+ if (this.deleteAreaTrash_ &&
1534
+ this.deleteAreaTrash_.contains(e.clientX, e.clientY)) {
1535
+ return Blockly.DELETE_AREA_TRASH;
1536
+ }
1537
+ if (this.deleteAreaToolbox_ &&
1538
+ this.deleteAreaToolbox_.contains(e.clientX, e.clientY)) {
1539
+ return Blockly.DELETE_AREA_TOOLBOX;
1540
+ }
1541
+ return Blockly.DELETE_AREA_NONE;
1542
+ };
1543
+
1544
+ /**
1545
+ * Handle a mouse-down on SVG drawing surface.
1546
+ * @param {!Event} e Mouse down event.
1547
+ * @private
1548
+ */
1549
+ Blockly.WorkspaceSvg.prototype.onMouseDown_ = function(e) {
1550
+ var gesture = this.getGesture(e);
1551
+ if (gesture) {
1552
+ gesture.handleWsStart(e, this);
1553
+ }
1554
+ };
1555
+
1556
+ /**
1557
+ * Start tracking a drag of an object on this workspace.
1558
+ * @param {!Event} e Mouse down event.
1559
+ * @param {!Blockly.utils.Coordinate} xy Starting location of object.
1560
+ */
1561
+ Blockly.WorkspaceSvg.prototype.startDrag = function(e, xy) {
1562
+ // Record the starting offset between the bubble's location and the mouse.
1563
+ var point = Blockly.utils.mouseToSvg(e, this.getParentSvg(),
1564
+ this.getInverseScreenCTM());
1565
+ // Fix scale of mouse event.
1566
+ point.x /= this.scale;
1567
+ point.y /= this.scale;
1568
+ this.dragDeltaXY_ = Blockly.utils.Coordinate.difference(xy, point);
1569
+ };
1570
+
1571
+ /**
1572
+ * Track a drag of an object on this workspace.
1573
+ * @param {!Event} e Mouse move event.
1574
+ * @return {!Blockly.utils.Coordinate} New location of object.
1575
+ */
1576
+ Blockly.WorkspaceSvg.prototype.moveDrag = function(e) {
1577
+ var point = Blockly.utils.mouseToSvg(e, this.getParentSvg(),
1578
+ this.getInverseScreenCTM());
1579
+ // Fix scale of mouse event.
1580
+ point.x /= this.scale;
1581
+ point.y /= this.scale;
1582
+ return Blockly.utils.Coordinate.sum(
1583
+ /** @type {!Blockly.utils.Coordinate} */ (this.dragDeltaXY_), point);
1584
+ };
1585
+
1586
+ /**
1587
+ * Is the user currently dragging a block or scrolling the flyout/workspace?
1588
+ * @return {boolean} True if currently dragging or scrolling.
1589
+ */
1590
+ Blockly.WorkspaceSvg.prototype.isDragging = function() {
1591
+ return this.currentGesture_ != null && this.currentGesture_.isDragging();
1592
+ };
1593
+
1594
+ /**
1595
+ * Is this workspace draggable?
1596
+ * @return {boolean} True if this workspace may be dragged.
1597
+ */
1598
+ Blockly.WorkspaceSvg.prototype.isDraggable = function() {
1599
+ return this.options.moveOptions && this.options.moveOptions.drag;
1600
+ };
1601
+
1602
+ /**
1603
+ * Should the workspace have bounded content? Used to tell if the
1604
+ * workspace's content should be sized so that it can move (bounded) or not
1605
+ * (exact sizing).
1606
+ * @return {boolean} True if the workspace should be bounded, false otherwise.
1607
+ * @package
1608
+ */
1609
+ Blockly.WorkspaceSvg.prototype.isContentBounded = function() {
1610
+ return (this.options.moveOptions && this.options.moveOptions.scrollbars) ||
1611
+ (this.options.moveOptions && this.options.moveOptions.wheel) ||
1612
+ (this.options.moveOptions && this.options.moveOptions.drag) ||
1613
+ (this.options.zoomOptions && this.options.zoomOptions.controls) ||
1614
+ (this.options.zoomOptions && this.options.zoomOptions.wheel) ||
1615
+ (this.options.zoomOptions && this.options.zoomOptions.pinch);
1616
+ };
1617
+
1618
+ /**
1619
+ * Is this workspace movable?
1620
+ *
1621
+ * This means the user can reposition the X Y coordinates of the workspace
1622
+ * through input. This can be through scrollbars, scroll wheel, dragging, or
1623
+ * through zooming with the scroll wheel or pinch (since the zoom is centered on
1624
+ * the mouse position). This does not include zooming with the zoom controls
1625
+ * since the X Y coordinates are decided programmatically.
1626
+ * @return {boolean} True if the workspace is movable, false otherwise.
1627
+ */
1628
+ Blockly.WorkspaceSvg.prototype.isMovable = function() {
1629
+ return (this.options.moveOptions && this.options.moveOptions.scrollbars) ||
1630
+ (this.options.moveOptions && this.options.moveOptions.wheel) ||
1631
+ (this.options.moveOptions && this.options.moveOptions.drag) ||
1632
+ (this.options.zoomOptions && this.options.zoomOptions.wheel) ||
1633
+ (this.options.zoomOptions && this.options.zoomOptions.pinch);
1634
+ };
1635
+
1636
+ /**
1637
+ * Handle a mouse-wheel on SVG drawing surface.
1638
+ * @param {!Event} e Mouse wheel event.
1639
+ * @private
1640
+ */
1641
+ Blockly.WorkspaceSvg.prototype.onMouseWheel_ = function(e) {
1642
+ // Don't scroll or zoom anything if drag is in progress.
1643
+ if (Blockly.Gesture.inProgress()) {
1644
+ e.preventDefault();
1645
+ e.stopPropagation();
1646
+ return;
1647
+ }
1648
+ var canWheelZoom = this.options.zoomOptions && this.options.zoomOptions.wheel;
1649
+ var canWheelMove = this.options.moveOptions && this.options.moveOptions.wheel;
1650
+ if (!canWheelZoom && !canWheelMove) {
1651
+ return;
1652
+ }
1653
+
1654
+ var scrollDelta = Blockly.utils.getScrollDeltaPixels(e);
1655
+ if (canWheelZoom && (e.ctrlKey || !canWheelMove)) {
1656
+ // Zoom.
1657
+ // The vertical scroll distance that corresponds to a click of a zoom
1658
+ // button.
1659
+ var PIXELS_PER_ZOOM_STEP = 50;
1660
+ var delta = -scrollDelta.y / PIXELS_PER_ZOOM_STEP;
1661
+ var position = Blockly.utils.mouseToSvg(e, this.getParentSvg(),
1662
+ this.getInverseScreenCTM());
1663
+ this.zoom(position.x, position.y, delta);
1664
+ } else {
1665
+ // Scroll.
1666
+ var x = this.scrollX - scrollDelta.x;
1667
+ var y = this.scrollY - scrollDelta.y;
1668
+
1669
+ if (e.shiftKey && !scrollDelta.x) {
1670
+ // Scroll horizontally (based on vertical scroll delta).
1671
+ // This is needed as for some browser/system combinations which do not
1672
+ // set deltaX.
1673
+ x = this.scrollX - scrollDelta.y;
1674
+ y = this.scrollY; // Don't scroll vertically
1675
+ }
1676
+ this.scroll(x, y);
1677
+ }
1678
+ e.preventDefault();
1679
+ };
1680
+
1681
+ /**
1682
+ * Calculate the bounding box for the blocks on the workspace.
1683
+ * Coordinate system: workspace coordinates.
1684
+ *
1685
+ * @return {!Blockly.utils.Rect} Contains the position and size of the
1686
+ * bounding box containing the blocks on the workspace.
1687
+ */
1688
+ Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox = function() {
1689
+ var topElements = this.getTopBoundedElements();
1690
+ // There are no blocks, return empty rectangle.
1691
+ if (!topElements.length) {
1692
+ return new Blockly.utils.Rect(0, 0, 0, 0);
1693
+ }
1694
+
1695
+ // Initialize boundary using the first block.
1696
+ var boundary = topElements[0].getBoundingRectangle();
1697
+
1698
+ // Start at 1 since the 0th block was used for initialization.
1699
+ for (var i = 1; i < topElements.length; i++) {
1700
+ var blockBoundary = topElements[i].getBoundingRectangle();
1701
+ if (blockBoundary.top < boundary.top) {
1702
+ boundary.top = blockBoundary.top;
1703
+ }
1704
+ if (blockBoundary.bottom > boundary.bottom) {
1705
+ boundary.bottom = blockBoundary.bottom;
1706
+ }
1707
+ if (blockBoundary.left < boundary.left) {
1708
+ boundary.left = blockBoundary.left;
1709
+ }
1710
+ if (blockBoundary.right > boundary.right) {
1711
+ boundary.right = blockBoundary.right;
1712
+ }
1713
+ }
1714
+ return boundary;
1715
+ };
1716
+
1717
+ /**
1718
+ * Clean up the workspace by ordering all the blocks in a column.
1719
+ */
1720
+ Blockly.WorkspaceSvg.prototype.cleanUp = function() {
1721
+ this.setResizesEnabled(false);
1722
+ Blockly.Events.setGroup(true);
1723
+ var topBlocks = this.getTopBlocks(true);
1724
+ var cursorY = 0;
1725
+ for (var i = 0, block; (block = topBlocks[i]); i++) {
1726
+ if (!block.isMovable()) {
1727
+ continue;
1728
+ }
1729
+ var xy = block.getRelativeToSurfaceXY();
1730
+ block.moveBy(-xy.x, cursorY - xy.y);
1731
+ block.snapToGrid();
1732
+ cursorY = block.getRelativeToSurfaceXY().y +
1733
+ block.getHeightWidth().height +
1734
+ this.renderer_.getConstants().MIN_BLOCK_HEIGHT;
1735
+ }
1736
+ Blockly.Events.setGroup(false);
1737
+ this.setResizesEnabled(true);
1738
+ };
1739
+
1740
+ /**
1741
+ * Show the context menu for the workspace.
1742
+ * @param {!Event} e Mouse event.
1743
+ * @package
1744
+ */
1745
+ Blockly.WorkspaceSvg.prototype.showContextMenu = function(e) {
1746
+ if (this.options.readOnly || this.isFlyout) {
1747
+ return;
1748
+ }
1749
+ var menuOptions = Blockly.ContextMenuRegistry.registry.getContextMenuOptions(
1750
+ Blockly.ContextMenuRegistry.ScopeType.WORKSPACE, {workspace: this});
1751
+
1752
+ // Allow the developer to add or modify menuOptions.
1753
+ if (this.configureContextMenu) {
1754
+ this.configureContextMenu(menuOptions, e);
1755
+ }
1756
+
1757
+ Blockly.ContextMenu.show(e, menuOptions, this.RTL);
1758
+ };
1759
+
1760
+ /**
1761
+ * Modify the block tree on the existing toolbox.
1762
+ * @param {?Blockly.utils.toolbox.ToolboxDefinition} toolboxDef
1763
+ * DOM tree of toolbox contents, string of toolbox contents, or JSON
1764
+ * representing toolbox definition.
1765
+ */
1766
+ Blockly.WorkspaceSvg.prototype.updateToolbox = function(toolboxDef) {
1767
+ var parsedToolboxDef = Blockly.utils.toolbox.convertToolboxDefToJson(toolboxDef);
1768
+
1769
+ if (!parsedToolboxDef) {
1770
+ if (this.options.languageTree) {
1771
+ throw Error('Can\'t nullify an existing toolbox.');
1772
+ }
1773
+ return; // No change (null to null).
1774
+ }
1775
+ if (!this.options.languageTree) {
1776
+ throw Error('Existing toolbox is null. Can\'t create new toolbox.');
1777
+ }
1778
+
1779
+ if (Blockly.utils.toolbox.hasCategories(parsedToolboxDef)) {
1780
+ if (!this.toolbox_) {
1781
+ throw Error('Existing toolbox has no categories. Can\'t change mode.');
1782
+ }
1783
+ this.options.languageTree = parsedToolboxDef;
1784
+ this.toolbox_.render(parsedToolboxDef);
1785
+ } else {
1786
+ if (!this.flyout_) {
1787
+ throw Error('Existing toolbox has categories. Can\'t change mode.');
1788
+ }
1789
+ this.options.languageTree = parsedToolboxDef;
1790
+ this.flyout_.show(parsedToolboxDef);
1791
+ }
1792
+ };
1793
+
1794
+ /**
1795
+ * Mark this workspace as the currently focused main workspace.
1796
+ */
1797
+ Blockly.WorkspaceSvg.prototype.markFocused = function() {
1798
+ if (this.options.parentWorkspace) {
1799
+ this.options.parentWorkspace.markFocused();
1800
+ } else {
1801
+ Blockly.mainWorkspace = this;
1802
+ // We call e.preventDefault in many event handlers which means we
1803
+ // need to explicitly grab focus (e.g from a textarea) because
1804
+ // the browser will not do it for us. How to do this is browser dependent.
1805
+ this.setBrowserFocus();
1806
+ }
1807
+ };
1808
+
1809
+ /**
1810
+ * Set the workspace to have focus in the browser.
1811
+ * @private
1812
+ */
1813
+ Blockly.WorkspaceSvg.prototype.setBrowserFocus = function() {
1814
+ // Blur whatever was focused since explicitly grabbing focus below does not
1815
+ // work in Edge.
1816
+ if (document.activeElement) {
1817
+ document.activeElement.blur();
1818
+ }
1819
+ try {
1820
+ // Focus the workspace SVG - this is for Chrome and Firefox.
1821
+ this.getParentSvg().focus({preventScroll:true});
1822
+ } catch (e) {
1823
+ // IE and Edge do not support focus on SVG elements. When that fails
1824
+ // above, get the injectionDiv (the workspace's parent) and focus that
1825
+ // instead. This doesn't work in Chrome.
1826
+ try {
1827
+ // In IE11, use setActive (which is IE only) so the page doesn't scroll
1828
+ // to the workspace gaining focus.
1829
+ this.getParentSvg().parentNode.setActive();
1830
+ } catch (e) {
1831
+ // setActive support was discontinued in Edge so when that fails, call
1832
+ // focus instead.
1833
+ this.getParentSvg().parentNode.focus({preventScroll:true});
1834
+ }
1835
+ }
1836
+ };
1837
+
1838
+ /**
1839
+ * Zooms the workspace in or out relative to/centered on the given (x, y)
1840
+ * coordinate.
1841
+ * @param {number} x X coordinate of center, in pixel units relative to the
1842
+ * top-left corner of the parentSVG.
1843
+ * @param {number} y Y coordinate of center, in pixel units relative to the
1844
+ * top-left corner of the parentSVG.
1845
+ * @param {number} amount Amount of zooming. The formula for the new scale
1846
+ * is newScale = currentScale * (scaleSpeed^amount). scaleSpeed is set in
1847
+ * the workspace options. Negative amount values zoom out, and positive
1848
+ * amount values zoom in.
1849
+ */
1850
+ Blockly.WorkspaceSvg.prototype.zoom = function(x, y, amount) {
1851
+ // Scale factor.
1852
+ var speed = this.options.zoomOptions.scaleSpeed;
1853
+ var scaleChange = Math.pow(speed, amount);
1854
+ var newScale = this.scale * scaleChange;
1855
+ if (this.scale == newScale) {
1856
+ return; // No change in zoom.
1857
+ }
1858
+
1859
+ // Clamp scale within valid range.
1860
+ if (newScale > this.options.zoomOptions.maxScale) {
1861
+ scaleChange = this.options.zoomOptions.maxScale / this.scale;
1862
+ } else if (newScale < this.options.zoomOptions.minScale) {
1863
+ scaleChange = this.options.zoomOptions.minScale / this.scale;
1864
+ }
1865
+
1866
+ // Transform the x/y coordinates from the parentSVG's space into the
1867
+ // canvas' space, so that they are in workspace units relative to the top
1868
+ // left of the visible portion of the workspace.
1869
+ var matrix = this.getCanvas().getCTM();
1870
+ var center = this.getParentSvg().createSVGPoint();
1871
+ center.x = x;
1872
+ center.y = y;
1873
+ center = center.matrixTransform(matrix.inverse());
1874
+ x = center.x;
1875
+ y = center.y;
1876
+
1877
+ // Find the new scrollX/scrollY so that the center remains in the same
1878
+ // position (relative to the center) after we zoom.
1879
+ // newScale and matrix.a should be identical (within a rounding error).
1880
+ matrix = matrix.translate(x * (1 - scaleChange), y * (1 - scaleChange))
1881
+ .scale(scaleChange);
1882
+ // scrollX and scrollY are in pixels.
1883
+ // The scrollX and scrollY still need to have absoluteLeft and absoluteTop
1884
+ // subtracted from them, but we'll leave that for setScale so that they're
1885
+ // correctly updated for the new flyout size if we have a simple toolbox.
1886
+ this.scrollX = matrix.e;
1887
+ this.scrollY = matrix.f;
1888
+ this.setScale(newScale);
1889
+ };
1890
+
1891
+ /**
1892
+ * Zooming the blocks centered in the center of view with zooming in or out.
1893
+ * @param {number} type Type of zooming (-1 zooming out and 1 zooming in).
1894
+ */
1895
+ Blockly.WorkspaceSvg.prototype.zoomCenter = function(type) {
1896
+ var metrics = this.getMetrics();
1897
+ if (this.flyout_) {
1898
+ // If you want blocks in the center of the view (visible portion of the
1899
+ // workspace) to stay centered when the size of the view decreases (i.e.
1900
+ // when the size of the flyout increases) you need the center of the
1901
+ // *blockly div* to stay in the same pixel-position.
1902
+ // Note: This only works because of how scrollCenter positions blocks.
1903
+ var x = metrics.svgWidth ? metrics.svgWidth / 2 : 0;
1904
+ var y = metrics.svgHeight ? metrics.svgHeight / 2 : 0;
1905
+ } else {
1906
+ var x = (metrics.viewWidth / 2) + metrics.absoluteLeft;
1907
+ var y = (metrics.viewHeight / 2) + metrics.absoluteTop;
1908
+ }
1909
+ this.zoom(x, y, type);
1910
+ };
1911
+
1912
+ /**
1913
+ * Zoom the blocks to fit in the workspace if possible.
1914
+ */
1915
+ Blockly.WorkspaceSvg.prototype.zoomToFit = function() {
1916
+ if (!this.isMovable()) {
1917
+ console.warn('Tried to move a non-movable workspace. This could result' +
1918
+ ' in blocks becoming inaccessible.');
1919
+ return;
1920
+ }
1921
+
1922
+ var metrics = this.getMetrics();
1923
+ var workspaceWidth = metrics.viewWidth;
1924
+ var workspaceHeight = metrics.viewHeight;
1925
+ var blocksBox = this.getBlocksBoundingBox();
1926
+ var blocksWidth = blocksBox.right - blocksBox.left;
1927
+ var blocksHeight = blocksBox.bottom - blocksBox.top;
1928
+ if (!blocksWidth) {
1929
+ return; // Prevents zooming to infinity.
1930
+ }
1931
+ if (this.flyout_) {
1932
+ // We have to add the flyout size to both the workspace size and the
1933
+ // block size because the blocks we want to resize include the blocks in
1934
+ // the flyout, and the area we want to fit them includes the portion of
1935
+ // the workspace that is behind the flyout.
1936
+ if (this.horizontalLayout) {
1937
+ workspaceHeight += this.flyout_.getHeight();
1938
+ // Convert from pixels to workspace coordinates.
1939
+ blocksHeight += this.flyout_.getHeight() / this.scale;
1940
+ } else {
1941
+ workspaceWidth += this.flyout_.getWidth();
1942
+ // Convert from pixels to workspace coordinates.
1943
+ blocksWidth += this.flyout_.getWidth() / this.scale;
1944
+ }
1945
+ }
1946
+
1947
+ // Scale Units: (pixels / workspaceUnit)
1948
+ var ratioX = workspaceWidth / blocksWidth;
1949
+ var ratioY = workspaceHeight / blocksHeight;
1950
+ Blockly.Events.disable();
1951
+ try {
1952
+ this.setScale(Math.min(ratioX, ratioY));
1953
+ this.scrollCenter();
1954
+ } finally {
1955
+ Blockly.Events.enable();
1956
+ }
1957
+ this.maybeFireViewportChangeEvent();
1958
+ };
1959
+
1960
+ /**
1961
+ * Add a transition class to the block and bubble canvas, to animate any
1962
+ * transform changes.
1963
+ * @package
1964
+ */
1965
+ Blockly.WorkspaceSvg.prototype.beginCanvasTransition = function() {
1966
+ Blockly.utils.dom.addClass(
1967
+ /** @type {!SVGElement} */ (this.svgBlockCanvas_),
1968
+ 'blocklyCanvasTransitioning');
1969
+ Blockly.utils.dom.addClass(
1970
+ /** @type {!SVGElement} */ (this.svgBubbleCanvas_),
1971
+ 'blocklyCanvasTransitioning');
1972
+ };
1973
+
1974
+ /**
1975
+ * Remove transition class from the block and bubble canvas.
1976
+ * @package
1977
+ */
1978
+ Blockly.WorkspaceSvg.prototype.endCanvasTransition = function() {
1979
+ Blockly.utils.dom.removeClass(
1980
+ /** @type {!SVGElement} */ (this.svgBlockCanvas_),
1981
+ 'blocklyCanvasTransitioning');
1982
+ Blockly.utils.dom.removeClass(
1983
+ /** @type {!SVGElement} */ (this.svgBubbleCanvas_),
1984
+ 'blocklyCanvasTransitioning');
1985
+ };
1986
+
1987
+ /**
1988
+ * Center the workspace.
1989
+ */
1990
+ Blockly.WorkspaceSvg.prototype.scrollCenter = function() {
1991
+ if (!this.isMovable()) {
1992
+ console.warn('Tried to move a non-movable workspace. This could result' +
1993
+ ' in blocks becoming inaccessible.');
1994
+ return;
1995
+ }
1996
+
1997
+ var metrics = this.getMetrics();
1998
+ var x = (metrics.contentWidth - metrics.viewWidth) / 2;
1999
+ var y = (metrics.contentHeight - metrics.viewHeight) / 2;
2000
+
2001
+ // Convert from workspace directions to canvas directions.
2002
+ x = -x - metrics.contentLeft;
2003
+ y = -y - metrics.contentTop;
2004
+ this.scroll(x, y);
2005
+ };
2006
+
2007
+ /**
2008
+ * Scroll the workspace to center on the given block.
2009
+ * @param {?string} id ID of block center on.
2010
+ * @public
2011
+ */
2012
+ Blockly.WorkspaceSvg.prototype.centerOnBlock = function(id) {
2013
+ if (!this.isMovable()) {
2014
+ console.warn('Tried to move a non-movable workspace. This could result' +
2015
+ ' in blocks becoming inaccessible.');
2016
+ return;
2017
+ }
2018
+
2019
+ var block = id ? this.getBlockById(id) : null;
2020
+ if (!block) {
2021
+ return;
2022
+ }
2023
+
2024
+ // XY is in workspace coordinates.
2025
+ var xy = block.getRelativeToSurfaceXY();
2026
+ // Height/width is in workspace units.
2027
+ var heightWidth = block.getHeightWidth();
2028
+
2029
+ // Find the enter of the block in workspace units.
2030
+ var blockCenterY = xy.y + heightWidth.height / 2;
2031
+
2032
+ // In RTL the block's position is the top right of the block, not top left.
2033
+ var multiplier = this.RTL ? -1 : 1;
2034
+ var blockCenterX = xy.x + (multiplier * heightWidth.width / 2);
2035
+
2036
+ // Workspace scale, used to convert from workspace coordinates to pixels.
2037
+ var scale = this.scale;
2038
+
2039
+ // Center of block in pixels, relative to workspace origin (center 0,0).
2040
+ // Scrolling to here would put the block in the top-left corner of the
2041
+ // visible workspace.
2042
+ var pixelX = blockCenterX * scale;
2043
+ var pixelY = blockCenterY * scale;
2044
+
2045
+ var metrics = this.getMetrics();
2046
+
2047
+ // viewHeight and viewWidth are in pixels.
2048
+ var halfViewWidth = metrics.viewWidth / 2;
2049
+ var halfViewHeight = metrics.viewHeight / 2;
2050
+
2051
+ // Put the block in the center of the visible workspace instead.
2052
+ var scrollToCenterX = pixelX - halfViewWidth;
2053
+ var scrollToCenterY = pixelY - halfViewHeight;
2054
+
2055
+ // Convert from workspace directions to canvas directions.
2056
+ var x = -scrollToCenterX;
2057
+ var y = -scrollToCenterY;
2058
+
2059
+ this.scroll(x, y);
2060
+ };
2061
+
2062
+ /**
2063
+ * Set the workspace's zoom factor.
2064
+ * @param {number} newScale Zoom factor. Units: (pixels / workspaceUnit).
2065
+ */
2066
+ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) {
2067
+ if (this.options.zoomOptions.maxScale &&
2068
+ newScale > this.options.zoomOptions.maxScale) {
2069
+ newScale = this.options.zoomOptions.maxScale;
2070
+ } else if (this.options.zoomOptions.minScale &&
2071
+ newScale < this.options.zoomOptions.minScale) {
2072
+ newScale = this.options.zoomOptions.minScale;
2073
+ }
2074
+ this.scale = newScale;
2075
+
2076
+ Blockly.hideChaff(false);
2077
+ if (this.flyout_) {
2078
+ // No toolbox, resize flyout.
2079
+ this.flyout_.reflow();
2080
+ this.recordDeleteAreas();
2081
+ }
2082
+ if (this.grid_) {
2083
+ this.grid_.update(this.scale);
2084
+ }
2085
+
2086
+ // We call scroll instead of scrollbar.resize() so that we can center the
2087
+ // zoom correctly without scrollbars, but scroll does not resize the
2088
+ // scrollbars so we have to call resizeView/resizeContent as well.
2089
+ var metrics = this.getMetrics();
2090
+ // The scroll values and the view values are additive inverses of
2091
+ // each other, so when we subtract from one we have to add to the other.
2092
+ this.scrollX -= metrics.absoluteLeft;
2093
+ this.scrollY -= metrics.absoluteTop;
2094
+ metrics.viewLeft += metrics.absoluteLeft;
2095
+ metrics.viewTop += metrics.absoluteTop;
2096
+
2097
+ this.scroll(this.scrollX, this.scrollY);
2098
+ if (this.scrollbar) {
2099
+ if (this.flyout_) {
2100
+ this.scrollbar.hScroll.resizeViewHorizontal(metrics);
2101
+ this.scrollbar.vScroll.resizeViewVertical(metrics);
2102
+ } else {
2103
+ this.scrollbar.hScroll.resizeContentHorizontal(metrics);
2104
+ this.scrollbar.vScroll.resizeContentVertical(metrics);
2105
+ }
2106
+ }
2107
+ };
2108
+
2109
+
2110
+ /**
2111
+ * Get the workspace's zoom factor. If the workspace has a parent, we call into
2112
+ * the parent to get the workspace scale.
2113
+ * @return {number} The workspace zoom factor. Units: (pixels / workspaceUnit).
2114
+ */
2115
+ Blockly.WorkspaceSvg.prototype.getScale = function() {
2116
+ if (this.options.parentWorkspace) {
2117
+ return this.options.parentWorkspace.getScale();
2118
+ }
2119
+ return this.scale;
2120
+ };
2121
+
2122
+ /**
2123
+ * Scroll the workspace to a specified offset (in pixels), keeping in the
2124
+ * workspace bounds. See comment on workspaceSvg.scrollX for more detail on
2125
+ * the meaning of these values.
2126
+ * @param {number} x Target X to scroll to.
2127
+ * @param {number} y Target Y to scroll to.
2128
+ * @package
2129
+ */
2130
+ Blockly.WorkspaceSvg.prototype.scroll = function(x, y) {
2131
+ Blockly.hideChaff(/* opt_allowToolbox */ true);
2132
+
2133
+ // Keep scrolling within the bounds of the content.
2134
+ var metrics = this.getMetrics();
2135
+ // This is the offset of the top-left corner of the view from the
2136
+ // workspace origin when the view is "seeing" the bottom-right corner of
2137
+ // the content.
2138
+ var maxOffsetOfViewFromOriginX = metrics.contentWidth + metrics.contentLeft -
2139
+ metrics.viewWidth;
2140
+ var maxOffsetOfViewFromOriginY = metrics.contentHeight + metrics.contentTop -
2141
+ metrics.viewHeight;
2142
+ // Canvas coordinates (aka scroll coordinates) have inverse directionality
2143
+ // to workspace coordinates so we have to inverse them.
2144
+ x = Math.min(x, -metrics.contentLeft);
2145
+ y = Math.min(y, -metrics.contentTop);
2146
+ x = Math.max(x, -maxOffsetOfViewFromOriginX);
2147
+ y = Math.max(y, -maxOffsetOfViewFromOriginY);
2148
+
2149
+ this.scrollX = x;
2150
+ this.scrollY = y;
2151
+ if (this.scrollbar) {
2152
+ // The content position (displacement from the content's top-left to the
2153
+ // origin) plus the scroll position (displacement from the view's top-left
2154
+ // to the origin) gives us the distance from the view's top-left to the
2155
+ // content's top-left. Then we negate this so we get the displacement from
2156
+ // the content's top-left to the view's top-left, matching the
2157
+ // directionality of the scrollbars.
2158
+
2159
+ this.scrollbar.hScroll.setHandlePosition(-(x + metrics.contentLeft) *
2160
+ this.scrollbar.hScroll.ratio);
2161
+ this.scrollbar.vScroll.setHandlePosition(-(y + metrics.contentTop) *
2162
+ this.scrollbar.vScroll.ratio);
2163
+ }
2164
+ // We have to shift the translation so that when the canvas is at 0, 0 the
2165
+ // workspace origin is not underneath the toolbox.
2166
+ x += metrics.absoluteLeft;
2167
+ y += metrics.absoluteTop;
2168
+ this.translate(x, y);
2169
+ };
2170
+
2171
+ /**
2172
+ * Get the dimensions of the given workspace component, in pixels.
2173
+ * @param {Blockly.IToolbox|Blockly.IFlyout} elem The element to get the
2174
+ * dimensions of, or null. It should be a toolbox or flyout, and should
2175
+ * implement getWidth() and getHeight().
2176
+ * @return {!Blockly.utils.Size} An object containing width and height
2177
+ * attributes, which will both be zero if elem did not exist.
2178
+ * @private
2179
+ */
2180
+ Blockly.WorkspaceSvg.getDimensionsPx_ = function(elem) {
2181
+ var width = 0;
2182
+ var height = 0;
2183
+ if (elem) {
2184
+ width = elem.getWidth();
2185
+ height = elem.getHeight();
2186
+ }
2187
+ return new Blockly.utils.Size(width, height);
2188
+ };
2189
+
2190
+ /**
2191
+ * Get the content dimensions of the given workspace, taking into account
2192
+ * whether or not it is scrollable and what size the workspace div is on screen.
2193
+ * @param {!Blockly.WorkspaceSvg} ws The workspace to measure.
2194
+ * @param {!Object} svgSize An object containing height and width attributes in
2195
+ * CSS pixels. Together they specify the size of the visible workspace, not
2196
+ * including areas covered up by the toolbox.
2197
+ * @return {!Object} The dimensions of the contents of the given workspace, as
2198
+ * an object containing at least
2199
+ * - height and width in pixels
2200
+ * - left and top in pixels relative to the workspace origin.
2201
+ * @private
2202
+ */
2203
+ Blockly.WorkspaceSvg.getContentDimensions_ = function(ws, svgSize) {
2204
+ if (ws.isContentBounded()) {
2205
+ return Blockly.WorkspaceSvg.getContentDimensionsBounded_(ws, svgSize);
2206
+ } else {
2207
+ return Blockly.WorkspaceSvg.getContentDimensionsExact_(ws);
2208
+ }
2209
+ };
2210
+
2211
+ /**
2212
+ * Get the bounding box for all workspace contents, in pixels.
2213
+ * @param {!Blockly.WorkspaceSvg} ws The workspace to inspect.
2214
+ * @return {!Object} The dimensions of the contents of the given workspace, as
2215
+ * an object containing
2216
+ * - height and width in pixels
2217
+ * - left, right, top and bottom in pixels relative to the workspace origin.
2218
+ * @private
2219
+ */
2220
+ Blockly.WorkspaceSvg.getContentDimensionsExact_ = function(ws) {
2221
+ // Block bounding box is in workspace coordinates.
2222
+ var blockBox = ws.getBlocksBoundingBox();
2223
+ var scale = ws.scale;
2224
+
2225
+ // Convert to pixels.
2226
+ var top = blockBox.top * scale;
2227
+ var bottom = blockBox.bottom * scale;
2228
+ var left = blockBox.left * scale;
2229
+ var right = blockBox.right * scale;
2230
+
2231
+ return {
2232
+ top: top,
2233
+ bottom: bottom,
2234
+ left: left,
2235
+ right: right,
2236
+ width: right - left,
2237
+ height: bottom - top
2238
+ };
2239
+ };
2240
+
2241
+ /**
2242
+ * Calculate the size of a scrollable workspace, which should include room for a
2243
+ * half screen border around the workspace contents.
2244
+ * @param {!Blockly.WorkspaceSvg} ws The workspace to measure.
2245
+ * @param {!Object} svgSize An object containing height and width attributes in
2246
+ * CSS pixels. Together they specify the size of the visible workspace, not
2247
+ * including areas covered up by the toolbox.
2248
+ * @return {!Object} The dimensions of the contents of the given workspace, as
2249
+ * an object containing
2250
+ * - height and width in pixels
2251
+ * - left and top in pixels relative to the workspace origin.
2252
+ * @private
2253
+ */
2254
+ Blockly.WorkspaceSvg.getContentDimensionsBounded_ = function(ws, svgSize) {
2255
+ var content = Blockly.WorkspaceSvg.getContentDimensionsExact_(ws);
2256
+
2257
+ // View height and width are both in pixels, and are the same as the SVG size.
2258
+ var viewWidth = svgSize.width;
2259
+ var viewHeight = svgSize.height;
2260
+ var halfWidth = viewWidth / 2;
2261
+ var halfHeight = viewHeight / 2;
2262
+
2263
+ // Add a border around the content that is at least half a screen wide.
2264
+ // Ensure border is wide enough that blocks can scroll over entire screen.
2265
+ var left = Math.min(content.left - halfWidth, content.right - viewWidth);
2266
+ var right = Math.max(content.right + halfWidth, content.left + viewWidth);
2267
+
2268
+ var top = Math.min(content.top - halfHeight, content.bottom - viewHeight);
2269
+ var bottom = Math.max(content.bottom + halfHeight, content.top + viewHeight);
2270
+
2271
+ var dimensions = {
2272
+ left: left,
2273
+ top: top,
2274
+ height: bottom - top,
2275
+ width: right - left
2276
+ };
2277
+ return dimensions;
2278
+ };
2279
+
2280
+ /**
2281
+ * Return an object with all the metrics required to size scrollbars for a
2282
+ * top level workspace. The following properties are computed:
2283
+ * Coordinate system: pixel coordinates, -left, -up, +right, +down
2284
+ * .viewHeight: Height of the visible portion of the workspace.
2285
+ * .viewWidth: Width of the visible portion of the workspace.
2286
+ * .contentHeight: Height of the content.
2287
+ * .contentWidth: Width of the content.
2288
+ * .svgHeight: Height of the Blockly div (the view + the toolbox,
2289
+ * simple or otherwise),
2290
+ * .svgWidth: Width of the Blockly div (the view + the toolbox,
2291
+ * simple or otherwise),
2292
+ * .viewTop: Top-edge of the visible portion of the workspace, relative to
2293
+ * the workspace origin.
2294
+ * .viewLeft: Left-edge of the visible portion of the workspace, relative to
2295
+ * the workspace origin.
2296
+ * .contentTop: Top-edge of the content, relative to the workspace origin.
2297
+ * .contentLeft: Left-edge of the content relative to the workspace origin.
2298
+ * .absoluteTop: Top-edge of the visible portion of the workspace, relative
2299
+ * to the blocklyDiv.
2300
+ * .absoluteLeft: Left-edge of the visible portion of the workspace, relative
2301
+ * to the blocklyDiv.
2302
+ * .toolboxWidth: Width of the toolbox, if it exists. Otherwise zero.
2303
+ * .toolboxHeight: Height of the toolbox, if it exists. Otherwise zero.
2304
+ * .flyoutWidth: Width of the flyout if it is always open. Otherwise zero.
2305
+ * .flyoutHeight: Height of the flyout if it is always open. Otherwise zero.
2306
+ * .toolboxPosition: Top, bottom, left or right. Use TOOLBOX_AT constants to
2307
+ * compare.
2308
+ * @return {!Blockly.utils.Metrics} Contains size and position metrics of a top
2309
+ * level workspace.
2310
+ * @private
2311
+ * @this {Blockly.WorkspaceSvg}
2312
+ */
2313
+ Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_ = function() {
2314
+
2315
+ var toolboxDimensions =
2316
+ Blockly.WorkspaceSvg.getDimensionsPx_(this.toolbox_);
2317
+ var flyoutDimensions =
2318
+ Blockly.WorkspaceSvg.getDimensionsPx_(this.flyout_);
2319
+
2320
+ // Contains height and width in CSS pixels.
2321
+ // svgSize is equivalent to the size of the injectionDiv at this point.
2322
+ var svgSize = Blockly.svgSize(this.getParentSvg());
2323
+ var viewSize = {height: svgSize.height, width: svgSize.width};
2324
+ if (this.toolbox_) {
2325
+ if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP ||
2326
+ this.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) {
2327
+ viewSize.height -= toolboxDimensions.height;
2328
+ } else if (this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT ||
2329
+ this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) {
2330
+ viewSize.width -= toolboxDimensions.width;
2331
+ }
2332
+ } else if (this.flyout_) {
2333
+ if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP ||
2334
+ this.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) {
2335
+ viewSize.height -= flyoutDimensions.height;
2336
+ } else if (this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT ||
2337
+ this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) {
2338
+ viewSize.width -= flyoutDimensions.width;
2339
+ }
2340
+ }
2341
+
2342
+ // svgSize is now the space taken up by the Blockly workspace, not including
2343
+ // the toolbox.
2344
+ var contentDimensions =
2345
+ Blockly.WorkspaceSvg.getContentDimensions_(this, viewSize);
2346
+
2347
+ var absoluteLeft = 0;
2348
+ if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) {
2349
+ absoluteLeft = toolboxDimensions.width;
2350
+ } else if (this.flyout_ && this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) {
2351
+ absoluteLeft = flyoutDimensions.width;
2352
+ }
2353
+ var absoluteTop = 0;
2354
+ if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) {
2355
+ absoluteTop = toolboxDimensions.height;
2356
+ } else if (this.flyout_ && this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) {
2357
+ absoluteTop = flyoutDimensions.height;
2358
+ }
2359
+
2360
+ var metrics = {
2361
+ contentHeight: contentDimensions.height,
2362
+ contentWidth: contentDimensions.width,
2363
+ contentTop: contentDimensions.top,
2364
+ contentLeft: contentDimensions.left,
2365
+
2366
+ viewHeight: viewSize.height,
2367
+ viewWidth: viewSize.width,
2368
+ viewTop: -this.scrollY,
2369
+ viewLeft: -this.scrollX,
2370
+
2371
+ absoluteTop: absoluteTop,
2372
+ absoluteLeft: absoluteLeft,
2373
+
2374
+ svgHeight: svgSize.height,
2375
+ svgWidth: svgSize.width,
2376
+
2377
+ toolboxWidth: toolboxDimensions.width,
2378
+ toolboxHeight: toolboxDimensions.height,
2379
+ toolboxPosition: this.toolboxPosition,
2380
+
2381
+ flyoutWidth: flyoutDimensions.width,
2382
+ flyoutHeight: flyoutDimensions.height
2383
+ };
2384
+ return metrics;
2385
+ };
2386
+
2387
+ /**
2388
+ * Sets the X/Y translations of a top level workspace.
2389
+ * @param {!Object} xyRatio Contains an x and/or y property which is a float
2390
+ * between 0 and 1 specifying the degree of scrolling.
2391
+ * @private
2392
+ * @this {Blockly.WorkspaceSvg}
2393
+ */
2394
+ Blockly.WorkspaceSvg.setTopLevelWorkspaceMetrics_ = function(xyRatio) {
2395
+ var metrics = this.getMetrics();
2396
+ if (typeof xyRatio.x == 'number') {
2397
+ this.scrollX = -metrics.contentWidth * xyRatio.x - metrics.contentLeft;
2398
+ }
2399
+ if (typeof xyRatio.y == 'number') {
2400
+ this.scrollY = -metrics.contentHeight * xyRatio.y - metrics.contentTop;
2401
+ }
2402
+ // We have to shift the translation so that when the canvas is at 0, 0 the
2403
+ // workspace origin is not underneath the toolbox.
2404
+ var x = this.scrollX + metrics.absoluteLeft;
2405
+ var y = this.scrollY + metrics.absoluteTop;
2406
+ // We could call scroll here, but that has extra checks we don't need to do.
2407
+ this.translate(x, y);
2408
+ };
2409
+
2410
+ /**
2411
+ * Find the block on this workspace with the specified ID.
2412
+ * @param {string} id ID of block to find.
2413
+ * @return {Blockly.BlockSvg} The sought after block, or null if not found.
2414
+ * @override
2415
+ */
2416
+ Blockly.WorkspaceSvg.prototype.getBlockById = function(id) {
2417
+ return /** @type {Blockly.BlockSvg} */ (
2418
+ Blockly.WorkspaceSvg.superClass_.getBlockById.call(this, id));
2419
+ };
2420
+
2421
+ /**
2422
+ * Finds the top-level blocks and returns them. Blocks are optionally sorted
2423
+ * by position; top to bottom (with slight LTR or RTL bias).
2424
+ * @param {boolean} ordered Sort the list if true.
2425
+ * @return {!Array.<!Blockly.BlockSvg>} The top-level block objects.
2426
+ * @override
2427
+ */
2428
+ Blockly.WorkspaceSvg.prototype.getTopBlocks = function(ordered) {
2429
+ return Blockly.WorkspaceSvg.superClass_.getTopBlocks.call(this, ordered);
2430
+ };
2431
+
2432
+ /**
2433
+ * Adds a block to the list of top blocks.
2434
+ * @param {!Blockly.Block} block Block to add.
2435
+ */
2436
+ Blockly.WorkspaceSvg.prototype.addTopBlock = function(block) {
2437
+ this.addTopBoundedElement(/** @type {!Blockly.BlockSvg} */ (block));
2438
+ Blockly.WorkspaceSvg.superClass_.addTopBlock.call(this, block);
2439
+ };
2440
+
2441
+ /**
2442
+ * Removes a block from the list of top blocks.
2443
+ * @param {!Blockly.Block} block Block to remove.
2444
+ */
2445
+ Blockly.WorkspaceSvg.prototype.removeTopBlock = function(block) {
2446
+ this.removeTopBoundedElement(/** @type {!Blockly.BlockSvg} */ (block));
2447
+ Blockly.WorkspaceSvg.superClass_.removeTopBlock.call(this, block);
2448
+ };
2449
+
2450
+ /**
2451
+ * Adds a comment to the list of top comments.
2452
+ * @param {!Blockly.WorkspaceComment} comment comment to add.
2453
+ */
2454
+ Blockly.WorkspaceSvg.prototype.addTopComment = function(comment) {
2455
+ this.addTopBoundedElement(
2456
+ /** @type {!Blockly.WorkspaceCommentSvg} */ (comment));
2457
+ Blockly.WorkspaceSvg.superClass_.addTopComment.call(this, comment);
2458
+ };
2459
+
2460
+ /**
2461
+ * Removes a comment from the list of top comments.
2462
+ * @param {!Blockly.WorkspaceComment} comment comment to remove.
2463
+ */
2464
+ Blockly.WorkspaceSvg.prototype.removeTopComment = function(comment) {
2465
+ this.removeTopBoundedElement(
2466
+ /** @type {!Blockly.WorkspaceCommentSvg} */ (comment));
2467
+ Blockly.WorkspaceSvg.superClass_.removeTopComment.call(this, comment);
2468
+ };
2469
+
2470
+ /**
2471
+ * Adds a bounded element to the list of top bounded elements.
2472
+ * @param {!Blockly.IBoundedElement} element Bounded element to add.
2473
+ */
2474
+ Blockly.WorkspaceSvg.prototype.addTopBoundedElement = function(element) {
2475
+ this.topBoundedElements_.push(element);
2476
+ };
2477
+
2478
+ /**
2479
+ * Removes a bounded element from the list of top bounded elements.
2480
+ * @param {!Blockly.IBoundedElement} element Bounded element to remove.
2481
+ */
2482
+ Blockly.WorkspaceSvg.prototype.removeTopBoundedElement = function(element) {
2483
+ Blockly.utils.arrayRemove(this.topBoundedElements_, element);
2484
+ };
2485
+
2486
+ /**
2487
+ * Finds the top-level bounded elements and returns them.
2488
+ * @return {!Array.<!Blockly.IBoundedElement>} The top-level bounded elements.
2489
+ */
2490
+ Blockly.WorkspaceSvg.prototype.getTopBoundedElements = function() {
2491
+ return [].concat(this.topBoundedElements_);
2492
+ };
2493
+
2494
+ /**
2495
+ * Update whether this workspace has resizes enabled.
2496
+ * If enabled, workspace will resize when appropriate.
2497
+ * If disabled, workspace will not resize until re-enabled.
2498
+ * Use to avoid resizing during a batch operation, for performance.
2499
+ * @param {boolean} enabled Whether resizes should be enabled.
2500
+ */
2501
+ Blockly.WorkspaceSvg.prototype.setResizesEnabled = function(enabled) {
2502
+ var reenabled = (!this.resizesEnabled_ && enabled);
2503
+ this.resizesEnabled_ = enabled;
2504
+ if (reenabled) {
2505
+ // Newly enabled. Trigger a resize.
2506
+ this.resizeContents();
2507
+ }
2508
+ };
2509
+
2510
+ /**
2511
+ * Dispose of all blocks in workspace, with an optimization to prevent resizes.
2512
+ */
2513
+ Blockly.WorkspaceSvg.prototype.clear = function() {
2514
+ this.setResizesEnabled(false);
2515
+ Blockly.WorkspaceSvg.superClass_.clear.call(this);
2516
+ this.topBoundedElements_ = [];
2517
+ this.setResizesEnabled(true);
2518
+ };
2519
+
2520
+ /**
2521
+ * Register a callback function associated with a given key, for clicks on
2522
+ * buttons and labels in the flyout.
2523
+ * For instance, a button specified by the XML
2524
+ * <button text="create variable" callbackKey="CREATE_VARIABLE"></button>
2525
+ * should be matched by a call to
2526
+ * registerButtonCallback("CREATE_VARIABLE", yourCallbackFunction).
2527
+ * @param {string} key The name to use to look up this function.
2528
+ * @param {function(!Blockly.FlyoutButton)} func The function to call when the
2529
+ * given button is clicked.
2530
+ */
2531
+ Blockly.WorkspaceSvg.prototype.registerButtonCallback = function(key, func) {
2532
+ if (typeof func != 'function') {
2533
+ throw TypeError('Button callbacks must be functions.');
2534
+ }
2535
+ this.flyoutButtonCallbacks_[key] = func;
2536
+ };
2537
+
2538
+ /**
2539
+ * Get the callback function associated with a given key, for clicks on buttons
2540
+ * and labels in the flyout.
2541
+ * @param {string} key The name to use to look up the function.
2542
+ * @return {?function(!Blockly.FlyoutButton)} The function corresponding to the
2543
+ * given key for this workspace; null if no callback is registered.
2544
+ */
2545
+ Blockly.WorkspaceSvg.prototype.getButtonCallback = function(key) {
2546
+ var result = this.flyoutButtonCallbacks_[key];
2547
+ return result ? result : null;
2548
+ };
2549
+
2550
+ /**
2551
+ * Remove a callback for a click on a button in the flyout.
2552
+ * @param {string} key The name associated with the callback function.
2553
+ */
2554
+ Blockly.WorkspaceSvg.prototype.removeButtonCallback = function(key) {
2555
+ this.flyoutButtonCallbacks_[key] = null;
2556
+ };
2557
+
2558
+ /**
2559
+ * Register a callback function associated with a given key, for populating
2560
+ * custom toolbox categories in this workspace. See the variable and procedure
2561
+ * categories as an example.
2562
+ * @param {string} key The name to use to look up this function.
2563
+ * @param {function(!Blockly.Workspace):!Array.<!Element>} func The function to
2564
+ * call when the given toolbox category is opened.
2565
+ */
2566
+ Blockly.WorkspaceSvg.prototype.registerToolboxCategoryCallback = function(key,
2567
+ func) {
2568
+ if (typeof func != 'function') {
2569
+ throw TypeError('Toolbox category callbacks must be functions.');
2570
+ }
2571
+ this.toolboxCategoryCallbacks_[key] = func;
2572
+ };
2573
+
2574
+ /**
2575
+ * Get the callback function associated with a given key, for populating
2576
+ * custom toolbox categories in this workspace.
2577
+ * @param {string} key The name to use to look up the function.
2578
+ * @return {?function(!Blockly.Workspace):!Array.<!Element>} The function
2579
+ * corresponding to the given key for this workspace, or null if no function
2580
+ * is registered.
2581
+ */
2582
+ Blockly.WorkspaceSvg.prototype.getToolboxCategoryCallback = function(key) {
2583
+ return this.toolboxCategoryCallbacks_[key] || null;
2584
+ };
2585
+
2586
+ /**
2587
+ * Remove a callback for a click on a custom category's name in the toolbox.
2588
+ * @param {string} key The name associated with the callback function.
2589
+ */
2590
+ Blockly.WorkspaceSvg.prototype.removeToolboxCategoryCallback = function(key) {
2591
+ this.toolboxCategoryCallbacks_[key] = null;
2592
+ };
2593
+
2594
+ /**
2595
+ * Look up the gesture that is tracking this touch stream on this workspace.
2596
+ * May create a new gesture.
2597
+ * @param {!Event} e Mouse event or touch event.
2598
+ * @return {Blockly.TouchGesture} The gesture that is tracking this touch
2599
+ * stream, or null if no valid gesture exists.
2600
+ * @package
2601
+ */
2602
+ Blockly.WorkspaceSvg.prototype.getGesture = function(e) {
2603
+ var isStart = (e.type == 'mousedown' || e.type == 'touchstart' ||
2604
+ e.type == 'pointerdown');
2605
+
2606
+ var gesture = this.currentGesture_;
2607
+ if (gesture) {
2608
+ if (isStart && gesture.hasStarted()) {
2609
+ console.warn('Tried to start the same gesture twice.');
2610
+ // That's funny. We must have missed a mouse up.
2611
+ // Cancel it, rather than try to retrieve all of the state we need.
2612
+ gesture.cancel();
2613
+ return null;
2614
+ }
2615
+ return gesture;
2616
+ }
2617
+
2618
+ // No gesture existed on this workspace, but this looks like the start of a
2619
+ // new gesture.
2620
+ if (isStart) {
2621
+ this.currentGesture_ = new Blockly.TouchGesture(e, this);
2622
+ return this.currentGesture_;
2623
+ }
2624
+ // No gesture existed and this event couldn't be the start of a new gesture.
2625
+ return null;
2626
+ };
2627
+
2628
+ /**
2629
+ * Clear the reference to the current gesture.
2630
+ * @package
2631
+ */
2632
+ Blockly.WorkspaceSvg.prototype.clearGesture = function() {
2633
+ this.currentGesture_ = null;
2634
+ };
2635
+
2636
+ /**
2637
+ * Cancel the current gesture, if one exists.
2638
+ * @package
2639
+ */
2640
+ Blockly.WorkspaceSvg.prototype.cancelCurrentGesture = function() {
2641
+ if (this.currentGesture_) {
2642
+ this.currentGesture_.cancel();
2643
+ }
2644
+ };
2645
+
2646
+ /**
2647
+ * Get the audio manager for this workspace.
2648
+ * @return {!Blockly.WorkspaceAudio} The audio manager for this workspace.
2649
+ */
2650
+ Blockly.WorkspaceSvg.prototype.getAudioManager = function() {
2651
+ return this.audioManager_;
2652
+ };
2653
+
2654
+ /**
2655
+ * Get the grid object for this workspace, or null if there is none.
2656
+ * @return {Blockly.Grid} The grid object for this workspace.
2657
+ * @package
2658
+ */
2659
+ Blockly.WorkspaceSvg.prototype.getGrid = function() {
2660
+ return this.grid_;
2661
+ };