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.
- package/blocklySkini/archive/blocklyControleur.js +87 -0
- package/blocklySkini/archive/blocklySkini.js +84 -0
- package/blocklySkini/archive/blocklyhop.js +75 -0
- package/blocklySkini/archive/clientControleurBlocly.js +170 -0
- package/blocklySkini/archive/index.html +76 -0
- package/blocklySkini/archive/testHHsuspend.txt +89 -0
- package/blocklySkini/archive/testHHtrap.txt +262 -0
- package/blocklySkini/archive/testOrchestration.txt +177 -0
- package/blocklySkini/archive/testOrchestration.xml +447 -0
- package/blocklySkini/archive/testOrchestration2.xml +456 -0
- package/blocklySkini/blockly/README.md +77 -0
- package/blocklySkini/blockly/blockly.d.ts +21480 -0
- package/blocklySkini/blockly/blockly.js +25 -0
- package/blocklySkini/blockly/blockly.min.js +2188 -0
- package/blocklySkini/blockly/blockly_compressed.js +1455 -0
- package/blocklySkini/blockly/blockly_compressed.js.map +1 -0
- package/blocklySkini/blockly/blocks/colour.js +122 -0
- package/blocklySkini/blockly/blocks/lists.js +862 -0
- package/blocklySkini/blockly/blocks/logic.js +635 -0
- package/blocklySkini/blockly/blocks/loops.js +357 -0
- package/blocklySkini/blockly/blocks/math.js +566 -0
- package/blocklySkini/blockly/blocks/procedures.js +1072 -0
- package/blocklySkini/blockly/blocks/text.js +923 -0
- package/blocklySkini/blockly/blocks/variables.js +163 -0
- package/blocklySkini/blockly/blocks/variables_dynamic.js +180 -0
- package/blocklySkini/blockly/blocks.d.ts +15 -0
- package/blocklySkini/blockly/blocks.js +27 -0
- package/blocklySkini/blockly/blocks_compressed.js +182 -0
- package/blocklySkini/blockly/blocks_compressed.js.map +1 -0
- package/blocklySkini/blockly/browser.js +36 -0
- package/blocklySkini/blockly/core/block.js +2010 -0
- package/blocklySkini/blockly/core/block_animations.js +203 -0
- package/blocklySkini/blockly/core/block_drag_surface.js +212 -0
- package/blocklySkini/blockly/core/block_dragger.js +378 -0
- package/blocklySkini/blockly/core/block_events.js +548 -0
- package/blocklySkini/blockly/core/block_svg.js +1763 -0
- package/blocklySkini/blockly/core/blockly.js +674 -0
- package/blocklySkini/blockly/core/blocks.js +23 -0
- package/blocklySkini/blockly/core/bubble.js +880 -0
- package/blocklySkini/blockly/core/bubble_dragger.js +274 -0
- package/blocklySkini/blockly/core/comment.js +439 -0
- package/blocklySkini/blockly/core/components/component.js +554 -0
- package/blocklySkini/blockly/core/components/tree/basenode.js +895 -0
- package/blocklySkini/blockly/core/components/tree/treecontrol.js +332 -0
- package/blocklySkini/blockly/core/components/tree/treenode.js +172 -0
- package/blocklySkini/blockly/core/connection.js +682 -0
- package/blocklySkini/blockly/core/connection_checker.js +285 -0
- package/blocklySkini/blockly/core/connection_db.js +295 -0
- package/blocklySkini/blockly/core/constants.js +277 -0
- package/blocklySkini/blockly/core/contextmenu.js +307 -0
- package/blocklySkini/blockly/core/contextmenu_items.js +534 -0
- package/blocklySkini/blockly/core/contextmenu_registry.js +165 -0
- package/blocklySkini/blockly/core/css.js +549 -0
- package/blocklySkini/blockly/core/dropdowndiv.js +776 -0
- package/blocklySkini/blockly/core/events.js +387 -0
- package/blocklySkini/blockly/core/events_abstract.js +106 -0
- package/blocklySkini/blockly/core/extensions.js +450 -0
- package/blocklySkini/blockly/core/field.js +1162 -0
- package/blocklySkini/blockly/core/field_angle.js +562 -0
- package/blocklySkini/blockly/core/field_checkbox.js +220 -0
- package/blocklySkini/blockly/core/field_colour.js +664 -0
- package/blocklySkini/blockly/core/field_dropdown.js +760 -0
- package/blocklySkini/blockly/core/field_image.js +286 -0
- package/blocklySkini/blockly/core/field_label.js +130 -0
- package/blocklySkini/blockly/core/field_label_serializable.js +69 -0
- package/blocklySkini/blockly/core/field_multilineinput.js +299 -0
- package/blocklySkini/blockly/core/field_number.js +317 -0
- package/blocklySkini/blockly/core/field_registry.js +66 -0
- package/blocklySkini/blockly/core/field_textinput.js +616 -0
- package/blocklySkini/blockly/core/field_variable.js +463 -0
- package/blocklySkini/blockly/core/flyout_base.js +1071 -0
- package/blocklySkini/blockly/core/flyout_button.js +325 -0
- package/blocklySkini/blockly/core/flyout_dragger.js +76 -0
- package/blocklySkini/blockly/core/flyout_horizontal.js +388 -0
- package/blocklySkini/blockly/core/flyout_vertical.js +397 -0
- package/blocklySkini/blockly/core/generator.js +482 -0
- package/blocklySkini/blockly/core/gesture.js +993 -0
- package/blocklySkini/blockly/core/grid.js +222 -0
- package/blocklySkini/blockly/core/icon.js +206 -0
- package/blocklySkini/blockly/core/inject.js +487 -0
- package/blocklySkini/blockly/core/input.js +296 -0
- package/blocklySkini/blockly/core/insertion_marker_manager.js +700 -0
- package/blocklySkini/blockly/core/interfaces/i_accessibility.js +72 -0
- package/blocklySkini/blockly/core/interfaces/i_bounded_element.js +31 -0
- package/blocklySkini/blockly/core/interfaces/i_bubble.js +83 -0
- package/blocklySkini/blockly/core/interfaces/i_connection_checker.js +94 -0
- package/blocklySkini/blockly/core/interfaces/i_contextmenu.js +26 -0
- package/blocklySkini/blockly/core/interfaces/i_copyable.js +40 -0
- package/blocklySkini/blockly/core/interfaces/i_deletable.js +27 -0
- package/blocklySkini/blockly/core/interfaces/i_deletearea.js +28 -0
- package/blocklySkini/blockly/core/interfaces/i_flyout.js +178 -0
- package/blocklySkini/blockly/core/interfaces/i_movable.js +27 -0
- package/blocklySkini/blockly/core/interfaces/i_registrable.js +22 -0
- package/blocklySkini/blockly/core/interfaces/i_registrable_field.js +31 -0
- package/blocklySkini/blockly/core/interfaces/i_selectable.js +43 -0
- package/blocklySkini/blockly/core/interfaces/i_styleable.js +33 -0
- package/blocklySkini/blockly/core/interfaces/i_toolbox.js +131 -0
- package/blocklySkini/blockly/core/interfaces/i_toolbox_item.js +148 -0
- package/blocklySkini/blockly/core/keyboard_nav/action.js +26 -0
- package/blocklySkini/blockly/core/keyboard_nav/ast_node.js +684 -0
- package/blocklySkini/blockly/core/keyboard_nav/basic_cursor.js +208 -0
- package/blocklySkini/blockly/core/keyboard_nav/cursor.js +170 -0
- package/blocklySkini/blockly/core/keyboard_nav/flyout_cursor.js +106 -0
- package/blocklySkini/blockly/core/keyboard_nav/key_map.js +190 -0
- package/blocklySkini/blockly/core/keyboard_nav/marker.js +120 -0
- package/blocklySkini/blockly/core/keyboard_nav/navigation.js +1084 -0
- package/blocklySkini/blockly/core/keyboard_nav/tab_navigate_cursor.js +48 -0
- package/blocklySkini/blockly/core/marker_manager.js +183 -0
- package/blocklySkini/blockly/core/menu.js +465 -0
- package/blocklySkini/blockly/core/menuitem.js +280 -0
- package/blocklySkini/blockly/core/msg.js +31 -0
- package/blocklySkini/blockly/core/mutator.js +555 -0
- package/blocklySkini/blockly/core/names.js +186 -0
- package/blocklySkini/blockly/core/options.js +365 -0
- package/blocklySkini/blockly/core/procedures.js +404 -0
- package/blocklySkini/blockly/core/registry.js +265 -0
- package/blocklySkini/blockly/core/rendered_connection.js +565 -0
- package/blocklySkini/blockly/core/renderers/common/block_rendering.js +81 -0
- package/blocklySkini/blockly/core/renderers/common/constants.js +1256 -0
- package/blocklySkini/blockly/core/renderers/common/debugger.js +431 -0
- package/blocklySkini/blockly/core/renderers/common/drawer.js +468 -0
- package/blocklySkini/blockly/core/renderers/common/i_path_object.js +151 -0
- package/blocklySkini/blockly/core/renderers/common/info.js +775 -0
- package/blocklySkini/blockly/core/renderers/common/marker_svg.js +687 -0
- package/blocklySkini/blockly/core/renderers/common/path_object.js +279 -0
- package/blocklySkini/blockly/core/renderers/common/renderer.js +301 -0
- package/blocklySkini/blockly/core/renderers/geras/constants.js +64 -0
- package/blocklySkini/blockly/core/renderers/geras/drawer.js +205 -0
- package/blocklySkini/blockly/core/renderers/geras/highlight_constants.js +311 -0
- package/blocklySkini/blockly/core/renderers/geras/highlighter.js +256 -0
- package/blocklySkini/blockly/core/renderers/geras/info.js +483 -0
- package/blocklySkini/blockly/core/renderers/geras/measurables/inputs.js +67 -0
- package/blocklySkini/blockly/core/renderers/geras/path_object.js +177 -0
- package/blocklySkini/blockly/core/renderers/geras/renderer.js +138 -0
- package/blocklySkini/blockly/core/renderers/measurables/base.js +44 -0
- package/blocklySkini/blockly/core/renderers/measurables/connections.js +114 -0
- package/blocklySkini/blockly/core/renderers/measurables/inputs.js +160 -0
- package/blocklySkini/blockly/core/renderers/measurables/row_elements.js +185 -0
- package/blocklySkini/blockly/core/renderers/measurables/rows.js +532 -0
- package/blocklySkini/blockly/core/renderers/measurables/types.js +349 -0
- package/blocklySkini/blockly/core/renderers/minimalist/constants.js +29 -0
- package/blocklySkini/blockly/core/renderers/minimalist/drawer.js +32 -0
- package/blocklySkini/blockly/core/renderers/minimalist/info.js +45 -0
- package/blocklySkini/blockly/core/renderers/minimalist/renderer.js +70 -0
- package/blocklySkini/blockly/core/renderers/thrasos/info.js +338 -0
- package/blocklySkini/blockly/core/renderers/thrasos/renderer.js +45 -0
- package/blocklySkini/blockly/core/renderers/zelos/constants.js +1002 -0
- package/blocklySkini/blockly/core/renderers/zelos/drawer.js +233 -0
- package/blocklySkini/blockly/core/renderers/zelos/info.js +587 -0
- package/blocklySkini/blockly/core/renderers/zelos/marker_svg.js +148 -0
- package/blocklySkini/blockly/core/renderers/zelos/measurables/inputs.js +47 -0
- package/blocklySkini/blockly/core/renderers/zelos/measurables/row_elements.js +37 -0
- package/blocklySkini/blockly/core/renderers/zelos/measurables/rows.js +108 -0
- package/blocklySkini/blockly/core/renderers/zelos/path_object.js +244 -0
- package/blocklySkini/blockly/core/renderers/zelos/renderer.js +130 -0
- package/blocklySkini/blockly/core/requires.js +84 -0
- package/blocklySkini/blockly/core/scrollbar.js +880 -0
- package/blocklySkini/blockly/core/theme/classic.js +87 -0
- package/blocklySkini/blockly/core/theme/dark.js +33 -0
- package/blocklySkini/blockly/core/theme/deuteranopia.js +104 -0
- package/blocklySkini/blockly/core/theme/highcontrast.js +119 -0
- package/blocklySkini/blockly/core/theme/modern.js +108 -0
- package/blocklySkini/blockly/core/theme/tritanopia.js +103 -0
- package/blocklySkini/blockly/core/theme/zelos.js +106 -0
- package/blocklySkini/blockly/core/theme.js +236 -0
- package/blocklySkini/blockly/core/theme_manager.js +197 -0
- package/blocklySkini/blockly/core/toolbox/category.js +690 -0
- package/blocklySkini/blockly/core/toolbox/collapsible_category.js +294 -0
- package/blocklySkini/blockly/core/toolbox/separator.js +123 -0
- package/blocklySkini/blockly/core/toolbox/toolbox.js +984 -0
- package/blocklySkini/blockly/core/toolbox/toolbox_item.js +145 -0
- package/blocklySkini/blockly/core/toolbox.js +943 -0
- package/blocklySkini/blockly/core/tooltip.js +387 -0
- package/blocklySkini/blockly/core/touch.js +255 -0
- package/blocklySkini/blockly/core/touch_gesture.js +325 -0
- package/blocklySkini/blockly/core/trashcan.js +661 -0
- package/blocklySkini/blockly/core/ui_events.js +85 -0
- package/blocklySkini/blockly/core/utils/aria.js +167 -0
- package/blocklySkini/blockly/core/utils/colour.js +208 -0
- package/blocklySkini/blockly/core/utils/coordinate.js +125 -0
- package/blocklySkini/blockly/core/utils/deprecation.js +34 -0
- package/blocklySkini/blockly/core/utils/dom.js +391 -0
- package/blocklySkini/blockly/core/utils/global.js +37 -0
- package/blocklySkini/blockly/core/utils/idgenerator.js +33 -0
- package/blocklySkini/blockly/core/utils/keycodes.js +164 -0
- package/blocklySkini/blockly/core/utils/math.js +56 -0
- package/blocklySkini/blockly/core/utils/metrics.js +124 -0
- package/blocklySkini/blockly/core/utils/object.js +73 -0
- package/blocklySkini/blockly/core/utils/rect.js +54 -0
- package/blocklySkini/blockly/core/utils/size.js +58 -0
- package/blocklySkini/blockly/core/utils/string.js +284 -0
- package/blocklySkini/blockly/core/utils/style.js +281 -0
- package/blocklySkini/blockly/core/utils/svg.js +181 -0
- package/blocklySkini/blockly/core/utils/svg_paths.js +142 -0
- package/blocklySkini/blockly/core/utils/toolbox.js +401 -0
- package/blocklySkini/blockly/core/utils/useragent.js +110 -0
- package/blocklySkini/blockly/core/utils/xml.js +79 -0
- package/blocklySkini/blockly/core/utils.js +652 -0
- package/blocklySkini/blockly/core/variable_events.js +248 -0
- package/blocklySkini/blockly/core/variable_map.js +414 -0
- package/blocklySkini/blockly/core/variable_model.js +95 -0
- package/blocklySkini/blockly/core/variables.js +571 -0
- package/blocklySkini/blockly/core/variables_dynamic.js +100 -0
- package/blocklySkini/blockly/core/warning.js +200 -0
- package/blocklySkini/blockly/core/widgetdiv.js +241 -0
- package/blocklySkini/blockly/core/workspace.js +786 -0
- package/blocklySkini/blockly/core/workspace_audio.js +153 -0
- package/blocklySkini/blockly/core/workspace_comment.js +373 -0
- package/blocklySkini/blockly/core/workspace_comment_render_svg.js +461 -0
- package/blocklySkini/blockly/core/workspace_comment_svg.js +701 -0
- package/blocklySkini/blockly/core/workspace_drag_surface_svg.js +176 -0
- package/blocklySkini/blockly/core/workspace_dragger.js +85 -0
- package/blocklySkini/blockly/core/workspace_events.js +93 -0
- package/blocklySkini/blockly/core/workspace_svg.js +2661 -0
- package/blocklySkini/blockly/core/ws_comment_events.js +417 -0
- package/blocklySkini/blockly/core/xml.js +827 -0
- package/blocklySkini/blockly/core/zoom_controls.js +449 -0
- package/blocklySkini/blockly/core-browser.js +34 -0
- package/blocklySkini/blockly/core.d.ts +15 -0
- package/blocklySkini/blockly/core.js +38 -0
- package/blocklySkini/blockly/dart.d.ts +15 -0
- package/blocklySkini/blockly/dart.js +27 -0
- package/blocklySkini/blockly/dart_compressed.js +114 -0
- package/blocklySkini/blockly/dart_compressed.js.map +1 -0
- package/blocklySkini/blockly/generators/dart/colour.js +114 -0
- package/blocklySkini/blockly/generators/dart/lists.js +447 -0
- package/blocklySkini/blockly/generators/dart/logic.js +127 -0
- package/blocklySkini/blockly/generators/dart/loops.js +169 -0
- package/blocklySkini/blockly/generators/dart/math.js +485 -0
- package/blocklySkini/blockly/generators/dart/procedures.js +111 -0
- package/blocklySkini/blockly/generators/dart/text.js +339 -0
- package/blocklySkini/blockly/generators/dart/variables.js +32 -0
- package/blocklySkini/blockly/generators/dart/variables_dynamic.js +21 -0
- package/blocklySkini/blockly/generators/dart.js +290 -0
- package/blocklySkini/blockly/generators/javascript/colour.js +89 -0
- package/blocklySkini/blockly/generators/javascript/lists.js +388 -0
- package/blocklySkini/blockly/generators/javascript/logic.js +129 -0
- package/blocklySkini/blockly/generators/javascript/loops.js +184 -0
- package/blocklySkini/blockly/generators/javascript/math.js +409 -0
- package/blocklySkini/blockly/generators/javascript/procedures.js +113 -0
- package/blocklySkini/blockly/generators/javascript/text.js +367 -0
- package/blocklySkini/blockly/generators/javascript/variables.js +32 -0
- package/blocklySkini/blockly/generators/javascript/variables_dynamic.js +23 -0
- package/blocklySkini/blockly/generators/javascript.js +317 -0
- package/blocklySkini/blockly/generators/lua/colour.js +76 -0
- package/blocklySkini/blockly/generators/lua/lists.js +368 -0
- package/blocklySkini/blockly/generators/lua/logic.js +127 -0
- package/blocklySkini/blockly/generators/lua/loops.js +173 -0
- package/blocklySkini/blockly/generators/lua/math.js +423 -0
- package/blocklySkini/blockly/generators/lua/procedures.js +113 -0
- package/blocklySkini/blockly/generators/lua/text.js +353 -0
- package/blocklySkini/blockly/generators/lua/variables.js +32 -0
- package/blocklySkini/blockly/generators/lua/variables_dynamic.js +21 -0
- package/blocklySkini/blockly/generators/lua.js +198 -0
- package/blocklySkini/blockly/generators/php/colour.js +91 -0
- package/blocklySkini/blockly/generators/php/lists.js +498 -0
- package/blocklySkini/blockly/generators/php/logic.js +128 -0
- package/blocklySkini/blockly/generators/php/loops.js +170 -0
- package/blocklySkini/blockly/generators/php/math.js +370 -0
- package/blocklySkini/blockly/generators/php/procedures.js +132 -0
- package/blocklySkini/blockly/generators/php/text.js +271 -0
- package/blocklySkini/blockly/generators/php/variables.js +32 -0
- package/blocklySkini/blockly/generators/php/variables_dynamic.js +21 -0
- package/blocklySkini/blockly/generators/php.js +318 -0
- package/blocklySkini/blockly/generators/python/colour.js +72 -0
- package/blocklySkini/blockly/generators/python/lists.js +349 -0
- package/blocklySkini/blockly/generators/python/logic.js +127 -0
- package/blocklySkini/blockly/generators/python/loops.js +214 -0
- package/blocklySkini/blockly/generators/python/math.js +385 -0
- package/blocklySkini/blockly/generators/python/procedures.js +134 -0
- package/blocklySkini/blockly/generators/python/text.js +293 -0
- package/blocklySkini/blockly/generators/python/variables.js +32 -0
- package/blocklySkini/blockly/generators/python/variables_dynamic.js +21 -0
- package/blocklySkini/blockly/generators/python.js +322 -0
- package/blocklySkini/blockly/index.d.ts +22 -0
- package/blocklySkini/blockly/index.js +24 -0
- package/blocklySkini/blockly/javascript.d.ts +15 -0
- package/blocklySkini/blockly/javascript.js +27 -0
- package/blocklySkini/blockly/javascript_compressed.js +115 -0
- package/blocklySkini/blockly/javascript_compressed.js.map +1 -0
- package/blocklySkini/blockly/lua.d.ts +15 -0
- package/blocklySkini/blockly/lua.js +27 -0
- package/blocklySkini/blockly/lua_compressed.js +94 -0
- package/blocklySkini/blockly/lua_compressed.js.map +1 -0
- package/blocklySkini/blockly/media/1x1.gif +0 -0
- package/blocklySkini/blockly/media/click.mp3 +0 -0
- package/blocklySkini/blockly/media/click.ogg +0 -0
- package/blocklySkini/blockly/media/click.wav +0 -0
- package/blocklySkini/blockly/media/delete.mp3 +0 -0
- package/blocklySkini/blockly/media/delete.ogg +0 -0
- package/blocklySkini/blockly/media/delete.wav +0 -0
- package/blocklySkini/blockly/media/disconnect.mp3 +0 -0
- package/blocklySkini/blockly/media/disconnect.ogg +0 -0
- package/blocklySkini/blockly/media/disconnect.wav +0 -0
- package/blocklySkini/blockly/media/dropdown-arrow.svg +1 -0
- package/blocklySkini/blockly/media/handclosed.cur +0 -0
- package/blocklySkini/blockly/media/handdelete.cur +0 -0
- package/blocklySkini/blockly/media/handopen.cur +0 -0
- package/blocklySkini/blockly/media/pilcrow.png +0 -0
- package/blocklySkini/blockly/media/quote0.png +0 -0
- package/blocklySkini/blockly/media/quote1.png +0 -0
- package/blocklySkini/blockly/media/sprites.png +0 -0
- package/blocklySkini/blockly/media/sprites.svg +74 -0
- package/blocklySkini/blockly/msg/ab.d.ts +16 -0
- package/blocklySkini/blockly/msg/ab.js +447 -0
- package/blocklySkini/blockly/msg/ar.d.ts +16 -0
- package/blocklySkini/blockly/msg/ar.js +447 -0
- package/blocklySkini/blockly/msg/az.d.ts +16 -0
- package/blocklySkini/blockly/msg/az.js +447 -0
- package/blocklySkini/blockly/msg/ba.d.ts +16 -0
- package/blocklySkini/blockly/msg/ba.js +447 -0
- package/blocklySkini/blockly/msg/bcc.d.ts +16 -0
- package/blocklySkini/blockly/msg/bcc.js +447 -0
- package/blocklySkini/blockly/msg/be-tarask.d.ts +16 -0
- package/blocklySkini/blockly/msg/be-tarask.js +447 -0
- package/blocklySkini/blockly/msg/be.d.ts +16 -0
- package/blocklySkini/blockly/msg/be.js +447 -0
- package/blocklySkini/blockly/msg/bg.d.ts +16 -0
- package/blocklySkini/blockly/msg/bg.js +447 -0
- package/blocklySkini/blockly/msg/bn.d.ts +16 -0
- package/blocklySkini/blockly/msg/bn.js +447 -0
- package/blocklySkini/blockly/msg/br.d.ts +16 -0
- package/blocklySkini/blockly/msg/br.js +447 -0
- package/blocklySkini/blockly/msg/ca.d.ts +16 -0
- package/blocklySkini/blockly/msg/ca.js +447 -0
- package/blocklySkini/blockly/msg/constants.d.ts +16 -0
- package/blocklySkini/blockly/msg/cs.d.ts +16 -0
- package/blocklySkini/blockly/msg/cs.js +447 -0
- package/blocklySkini/blockly/msg/da.d.ts +16 -0
- package/blocklySkini/blockly/msg/da.js +447 -0
- package/blocklySkini/blockly/msg/de.d.ts +16 -0
- package/blocklySkini/blockly/msg/de.js +447 -0
- package/blocklySkini/blockly/msg/diq.d.ts +16 -0
- package/blocklySkini/blockly/msg/diq.js +447 -0
- package/blocklySkini/blockly/msg/dty.d.ts +16 -0
- package/blocklySkini/blockly/msg/dty.js +447 -0
- package/blocklySkini/blockly/msg/ee.d.ts +16 -0
- package/blocklySkini/blockly/msg/ee.js +447 -0
- package/blocklySkini/blockly/msg/el.d.ts +16 -0
- package/blocklySkini/blockly/msg/el.js +447 -0
- package/blocklySkini/blockly/msg/en-gb.d.ts +16 -0
- package/blocklySkini/blockly/msg/en-gb.js +447 -0
- package/blocklySkini/blockly/msg/en.d.ts +16 -0
- package/blocklySkini/blockly/msg/en.js +447 -0
- package/blocklySkini/blockly/msg/eo.d.ts +16 -0
- package/blocklySkini/blockly/msg/eo.js +447 -0
- package/blocklySkini/blockly/msg/es.d.ts +16 -0
- package/blocklySkini/blockly/msg/es.js +447 -0
- package/blocklySkini/blockly/msg/et.d.ts +16 -0
- package/blocklySkini/blockly/msg/et.js +447 -0
- package/blocklySkini/blockly/msg/eu.d.ts +16 -0
- package/blocklySkini/blockly/msg/eu.js +447 -0
- package/blocklySkini/blockly/msg/fa.d.ts +16 -0
- package/blocklySkini/blockly/msg/fa.js +447 -0
- package/blocklySkini/blockly/msg/fi.d.ts +16 -0
- package/blocklySkini/blockly/msg/fi.js +447 -0
- package/blocklySkini/blockly/msg/fr.d.ts +16 -0
- package/blocklySkini/blockly/msg/fr.js +447 -0
- package/blocklySkini/blockly/msg/gl.d.ts +16 -0
- package/blocklySkini/blockly/msg/gl.js +447 -0
- package/blocklySkini/blockly/msg/gor.d.ts +16 -0
- package/blocklySkini/blockly/msg/gor.js +447 -0
- package/blocklySkini/blockly/msg/ha.d.ts +16 -0
- package/blocklySkini/blockly/msg/ha.js +447 -0
- package/blocklySkini/blockly/msg/he.d.ts +16 -0
- package/blocklySkini/blockly/msg/he.js +447 -0
- package/blocklySkini/blockly/msg/hi.d.ts +16 -0
- package/blocklySkini/blockly/msg/hi.js +447 -0
- package/blocklySkini/blockly/msg/hrx.d.ts +16 -0
- package/blocklySkini/blockly/msg/hrx.js +447 -0
- package/blocklySkini/blockly/msg/hu.d.ts +16 -0
- package/blocklySkini/blockly/msg/hu.js +447 -0
- package/blocklySkini/blockly/msg/hy.d.ts +16 -0
- package/blocklySkini/blockly/msg/hy.js +447 -0
- package/blocklySkini/blockly/msg/ia.d.ts +16 -0
- package/blocklySkini/blockly/msg/ia.js +447 -0
- package/blocklySkini/blockly/msg/id.d.ts +16 -0
- package/blocklySkini/blockly/msg/id.js +447 -0
- package/blocklySkini/blockly/msg/ig.d.ts +16 -0
- package/blocklySkini/blockly/msg/ig.js +447 -0
- package/blocklySkini/blockly/msg/is.d.ts +16 -0
- package/blocklySkini/blockly/msg/is.js +447 -0
- package/blocklySkini/blockly/msg/it.d.ts +16 -0
- package/blocklySkini/blockly/msg/it.js +447 -0
- package/blocklySkini/blockly/msg/ja.d.ts +16 -0
- package/blocklySkini/blockly/msg/ja.js +447 -0
- package/blocklySkini/blockly/msg/kab.d.ts +16 -0
- package/blocklySkini/blockly/msg/kab.js +447 -0
- package/blocklySkini/blockly/msg/kn.d.ts +16 -0
- package/blocklySkini/blockly/msg/kn.js +447 -0
- package/blocklySkini/blockly/msg/ko.d.ts +16 -0
- package/blocklySkini/blockly/msg/ko.js +447 -0
- package/blocklySkini/blockly/msg/lb.d.ts +16 -0
- package/blocklySkini/blockly/msg/lb.js +447 -0
- package/blocklySkini/blockly/msg/lki.d.ts +16 -0
- package/blocklySkini/blockly/msg/lki.js +447 -0
- package/blocklySkini/blockly/msg/lo.d.ts +16 -0
- package/blocklySkini/blockly/msg/lo.js +447 -0
- package/blocklySkini/blockly/msg/lrc.d.ts +16 -0
- package/blocklySkini/blockly/msg/lrc.js +447 -0
- package/blocklySkini/blockly/msg/lt.d.ts +16 -0
- package/blocklySkini/blockly/msg/lt.js +447 -0
- package/blocklySkini/blockly/msg/lv.d.ts +16 -0
- package/blocklySkini/blockly/msg/lv.js +447 -0
- package/blocklySkini/blockly/msg/mk.d.ts +16 -0
- package/blocklySkini/blockly/msg/mk.js +447 -0
- package/blocklySkini/blockly/msg/mnw.d.ts +16 -0
- package/blocklySkini/blockly/msg/mnw.js +447 -0
- package/blocklySkini/blockly/msg/ms.d.ts +16 -0
- package/blocklySkini/blockly/msg/ms.js +447 -0
- package/blocklySkini/blockly/msg/msg.d.ts +444 -0
- package/blocklySkini/blockly/msg/nb.d.ts +16 -0
- package/blocklySkini/blockly/msg/nb.js +447 -0
- package/blocklySkini/blockly/msg/nl.d.ts +16 -0
- package/blocklySkini/blockly/msg/nl.js +447 -0
- package/blocklySkini/blockly/msg/oc.d.ts +16 -0
- package/blocklySkini/blockly/msg/oc.js +447 -0
- package/blocklySkini/blockly/msg/pl.d.ts +16 -0
- package/blocklySkini/blockly/msg/pl.js +447 -0
- package/blocklySkini/blockly/msg/pms.d.ts +16 -0
- package/blocklySkini/blockly/msg/pms.js +447 -0
- package/blocklySkini/blockly/msg/pt-br.d.ts +16 -0
- package/blocklySkini/blockly/msg/pt-br.js +447 -0
- package/blocklySkini/blockly/msg/pt.d.ts +16 -0
- package/blocklySkini/blockly/msg/pt.js +447 -0
- package/blocklySkini/blockly/msg/qqq.d.ts +16 -0
- package/blocklySkini/blockly/msg/ro.d.ts +16 -0
- package/blocklySkini/blockly/msg/ro.js +447 -0
- package/blocklySkini/blockly/msg/ru.d.ts +16 -0
- package/blocklySkini/blockly/msg/ru.js +447 -0
- package/blocklySkini/blockly/msg/sc.d.ts +16 -0
- package/blocklySkini/blockly/msg/sc.js +447 -0
- package/blocklySkini/blockly/msg/sd.d.ts +16 -0
- package/blocklySkini/blockly/msg/sd.js +447 -0
- package/blocklySkini/blockly/msg/shn.d.ts +16 -0
- package/blocklySkini/blockly/msg/shn.js +447 -0
- package/blocklySkini/blockly/msg/sk.d.ts +16 -0
- package/blocklySkini/blockly/msg/sk.js +447 -0
- package/blocklySkini/blockly/msg/skr-arab.d.ts +16 -0
- package/blocklySkini/blockly/msg/skr-arab.js +447 -0
- package/blocklySkini/blockly/msg/sl.d.ts +16 -0
- package/blocklySkini/blockly/msg/sl.js +447 -0
- package/blocklySkini/blockly/msg/sq.d.ts +16 -0
- package/blocklySkini/blockly/msg/sq.js +447 -0
- package/blocklySkini/blockly/msg/sr-latn.d.ts +16 -0
- package/blocklySkini/blockly/msg/sr-latn.js +447 -0
- package/blocklySkini/blockly/msg/sr.d.ts +16 -0
- package/blocklySkini/blockly/msg/sr.js +447 -0
- package/blocklySkini/blockly/msg/sv.d.ts +16 -0
- package/blocklySkini/blockly/msg/sv.js +447 -0
- package/blocklySkini/blockly/msg/synonyms.d.ts +16 -0
- package/blocklySkini/blockly/msg/ta.d.ts +16 -0
- package/blocklySkini/blockly/msg/ta.js +447 -0
- package/blocklySkini/blockly/msg/tcy.d.ts +16 -0
- package/blocklySkini/blockly/msg/tcy.js +447 -0
- package/blocklySkini/blockly/msg/te.d.ts +16 -0
- package/blocklySkini/blockly/msg/te.js +447 -0
- package/blocklySkini/blockly/msg/th.d.ts +16 -0
- package/blocklySkini/blockly/msg/th.js +447 -0
- package/blocklySkini/blockly/msg/tl.d.ts +16 -0
- package/blocklySkini/blockly/msg/tl.js +447 -0
- package/blocklySkini/blockly/msg/tlh.d.ts +16 -0
- package/blocklySkini/blockly/msg/tlh.js +447 -0
- package/blocklySkini/blockly/msg/tr.d.ts +16 -0
- package/blocklySkini/blockly/msg/tr.js +447 -0
- package/blocklySkini/blockly/msg/ug-arab.d.ts +16 -0
- package/blocklySkini/blockly/msg/ug-arab.js +447 -0
- package/blocklySkini/blockly/msg/uk.d.ts +16 -0
- package/blocklySkini/blockly/msg/uk.js +447 -0
- package/blocklySkini/blockly/msg/ur.d.ts +16 -0
- package/blocklySkini/blockly/msg/ur.js +447 -0
- package/blocklySkini/blockly/msg/vi.d.ts +16 -0
- package/blocklySkini/blockly/msg/vi.js +447 -0
- package/blocklySkini/blockly/msg/xmf.d.ts +16 -0
- package/blocklySkini/blockly/msg/xmf.js +447 -0
- package/blocklySkini/blockly/msg/yo.d.ts +16 -0
- package/blocklySkini/blockly/msg/yo.js +447 -0
- package/blocklySkini/blockly/msg/zh-hans.d.ts +16 -0
- package/blocklySkini/blockly/msg/zh-hans.js +447 -0
- package/blocklySkini/blockly/msg/zh-hant.d.ts +16 -0
- package/blocklySkini/blockly/msg/zh-hant.js +447 -0
- package/blocklySkini/blockly/node.js +35 -0
- package/blocklySkini/blockly/package.json +84 -0
- package/blocklySkini/blockly/php.d.ts +15 -0
- package/blocklySkini/blockly/php.js +27 -0
- package/blocklySkini/blockly/php_compressed.js +103 -0
- package/blocklySkini/blockly/php_compressed.js.map +1 -0
- package/blocklySkini/blockly/python.d.ts +15 -0
- package/blocklySkini/blockly/python.js +27 -0
- package/blocklySkini/blockly/python_compressed.js +98 -0
- package/blocklySkini/blockly/python_compressed.js.map +1 -0
- package/blocklySkini/blocklySkini.html +81 -0
- package/blocklySkini/orchestrations/.xml +1 -0
- package/blocklySkini/orchestrations/BluesSkini-1.xml +231 -0
- package/blocklySkini/orchestrations/BluesSkini-2.xml +741 -0
- package/blocklySkini/orchestrations/BluesSkini-3.xml +731 -0
- package/blocklySkini/orchestrations/BluesSkini-4.xml +695 -0
- package/blocklySkini/orchestrations/BluesSkini-5.xml +731 -0
- package/blocklySkini/orchestrations/BluesSkini.xml +704 -0
- package/blocklySkini/orchestrations/FunkBitwig-1.xml +778 -0
- package/blocklySkini/orchestrations/FunkBitwig-2.xml +471 -0
- package/blocklySkini/orchestrations/JouerLeBonInstrument1-1.xml +784 -0
- package/blocklySkini/orchestrations/MajeurMineur-1.xml +638 -0
- package/blocklySkini/orchestrations/Opus5-3 - Copie.xml +1041 -0
- package/blocklySkini/orchestrations/Opus5-3.xml +1128 -0
- package/blocklySkini/orchestrations/Quatuor1-1.xml +357 -0
- package/blocklySkini/orchestrations/TechnoBitwig-1.xml +221 -0
- package/blocklySkini/orchestrations/TestBlockly.xml +497 -0
- package/blocklySkini/orchestrations/TestBlockly1.xml +500 -0
- package/blocklySkini/orchestrations/TestBlockly2.xml +792 -0
- package/blocklySkini/orchestrations/TestBlockly3-1.xml +1182 -0
- package/blocklySkini/orchestrations/TestBlockly3.xml +1251 -0
- package/blocklySkini/orchestrations/TestFunction.xml +143 -0
- package/blocklySkini/orchestrations/TestIf.xml +80 -0
- package/blocklySkini/orchestrations/TestLoop.xml +127 -0
- package/blocklySkini/orchestrations/TestOrchestration2.xml +460 -0
- package/blocklySkini/orchestrations/TestPrint.xml +70 -0
- package/blocklySkini/orchestrations/TestSubMod.xml +81 -0
- package/blocklySkini/orchestrations/Testlogic.xml +113 -0
- package/blocklySkini/orchestrations/TrouveLaPercu-1.xml +813 -0
- package/blocklySkini/orchestrations/TrouveLaPercu-2.xml +813 -0
- package/blocklySkini/orchestrations/bar.xml +496 -0
- package/blocklySkini/orchestrations/bar2.xml +496 -0
- package/blocklySkini/orchestrations/foo.xml +500 -0
- package/blocklySkini/orchestrations/opus5Blockly - Copie.xml +496 -0
- package/blocklySkini/orchestrations/opus5Blockly-3.xml +868 -0
- package/blocklySkini/orchestrations/opus5Blockly.xml +496 -0
- package/blocklySkini/orchestrations/testOrchestration3.xml +483 -0
- package/blocklySkini/orchestrations/testOrchestration4.xml +487 -0
- package/blocklySkini/scripts/hiphop_blocks.js +6104 -0
- package/blocklySkini/scripts/main2.js +801 -0
- package/blocklySkini/styles/index.css +320 -0
- package/blocklySkini/styles/material.css +11552 -0
- 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
|
+
};
|