Merge pull request #4976 from google/rc_2021_7

Rc 2021 7
This commit is contained in:
Beka Westberg
2021-07-01 08:57:19 -07:00
committed by GitHub
276 changed files with 11586 additions and 8058 deletions
+2 -4
View File
@@ -72,8 +72,7 @@
"balanced": true
},
"exceptions": ["*"]
}],
"es5/no-es6-methods": ["warn"]
}]
},
"env": {
"browser": true
@@ -83,7 +82,6 @@
"goog": true
},
"extends": [
"eslint:recommended",
"plugin:es5/no-es2015"
"eslint:recommended"
]
}
+6
View File
@@ -10,3 +10,9 @@ updates:
target-branch: "develop"
schedule:
interval: "weekly"
ignore:
- dependency-name: "jsdom"
# For jsdom, ignore all updates for version 16.
# We should test that this does not cause issue
# google/blockly-samples#665 when version 17 is released.
versions: "16.x"
+6 -4
View File
@@ -7,12 +7,14 @@ on: [pull_request]
jobs:
build:
# TODO (#2114): re-enable osx build.
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
node-version: [10.x, 12.x, 14.x]
# TODO (#2114): re-enable osx build.
# os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest]
node-version: [10.x, 12.x, 14.x, 16.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
@@ -35,7 +37,7 @@ jobs:
run: source ./tests/scripts/setup_osx_env.sh
- name: Run
run: npm run test:run
run: npm run test
env:
CI: true
+1 -1
View File
@@ -41,7 +41,7 @@ Want to make Blockly better? We welcome contributions to Blockly in the form of
## Releases
The next major release will be **March 25th, 2021**.
The next major release will be **September 30th, 2021**.
We release by pushing the latest code to the master branch, followed by updating the npm package, our [docs](https://developers.google.com/blockly), and [demo pages](https://google.github.io/blockly-samples/). We typically release a new version of Blockly once a quarter (every 3 months). If there are breaking bugs, such as a crash when performing a standard action or a rendering issue that makes Blockly unusable, we will cherry-pick fixes to master between releases to fix them. The [releases page](https://github.com/google/blockly/releases) has a list of all releases.
-1
View File
@@ -11,7 +11,6 @@ deploy
/static/scripts/
/static/typings/
/static/build.py
/static/eslintrc.json
/static/gulpfile.js
/static/jsconfig.json
+328 -308
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+189 -183
View File
@@ -21,207 +21,213 @@ this.BLOCKLY_DIR = (function(root) {
this.BLOCKLY_BOOT = function(root) {
// Execute after Closure has loaded.
goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.Workspace', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es5'});
goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox'], {});
goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], [], {});
goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch'], {});
goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {});
goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation'], {});
goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry'], {});
goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants'], {});
goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], [], {});
goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes'], {});
goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.IASTNodeLocation', 'Blockly.IDeletable', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.Workspace', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.object'], {'lang': 'es5'});
goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']);
goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.IASTNodeLocationSvg', 'Blockly.IBoundedElement', 'Blockly.ICopyable', 'Blockly.IDraggable', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']);
goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], []);
goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.utils.global']);
goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.IBubble', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']);
goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], []);
goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation']);
goog.addDependency('../../core/connection_checker.js', ['Blockly.ConnectionChecker'], ['Blockly.Connection', 'Blockly.IConnectionChecker', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.registry']);
goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Blockly.RenderedConnection', 'Blockly.connectionTypes', 'Blockly.constants']);
goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], []);
goog.addDependency('../../core/constants.js', ['Blockly.constants'], ['Blockly.connectionTypes']);
goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'});
goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es5'});
goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es5'});
goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style'], {});
goog.addDependency('../../core/events/block_events.js', ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.registry', 'Blockly.utils'], {});
goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events'], {});
goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_click.js', ['Blockly.Events.Click'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_marker_move.js', ['Blockly.Events.MarkerMove'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_selected.js', ['Blockly.Events.Selected'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_theme_change.js', ['Blockly.Events.ThemeChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_toolbox_item_select.js', ['Blockly.Events.ToolboxItemSelect'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_trashcan_open.js', ['Blockly.Events.TrashcanOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/events_viewport.js', ['Blockly.Events.ViewportChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/ui_events.js', ['Blockly.Events.Ui', 'Blockly.Events.UiBase'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/events/variable_events.js', ['Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {});
goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.BlockSvg', 'Blockly.DragTarget', 'Blockly.IDeleteArea']);
goog.addDependency('../../core/drag_target.js', ['Blockly.DragTarget'], ['Blockly.IDragTarget']);
goog.addDependency('../../core/dropdowndiv.js', ['Blockly.DropDownDiv'], ['Blockly.utils.Rect', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.style']);
goog.addDependency('../../core/events/block_events.js', ['Blockly.Events.BlockBase', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Events.Change', 'Blockly.Events.Create', 'Blockly.Events.Delete', 'Blockly.Events.Move'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']);
goog.addDependency('../../core/events/events.js', ['Blockly.Events'], ['Blockly.registry', 'Blockly.utils']);
goog.addDependency('../../core/events/events_abstract.js', ['Blockly.Events.Abstract'], ['Blockly.Events']);
goog.addDependency('../../core/events/events_block_drag.js', ['Blockly.Events.BlockDrag'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_bubble_open.js', ['Blockly.Events.BubbleOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_click.js', ['Blockly.Events.Click'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_marker_move.js', ['Blockly.Events.MarkerMove'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_selected.js', ['Blockly.Events.Selected'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_theme_change.js', ['Blockly.Events.ThemeChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_toolbox_item_select.js', ['Blockly.Events.ToolboxItemSelect'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_trashcan_open.js', ['Blockly.Events.TrashcanOpen'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/events_viewport.js', ['Blockly.Events.ViewportChange'], ['Blockly.Events', 'Blockly.Events.UiBase', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/ui_events.js', ['Blockly.Events.Ui', 'Blockly.Events.UiBase'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/variable_events.js', ['Blockly.Events.VarBase', 'Blockly.Events.VarCreate', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object']);
goog.addDependency('../../core/events/workspace_events.js', ['Blockly.Events.FinishedLoading'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'});
goog.addDependency('../../core/events/ws_comment_events.js', ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils'], {});
goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Gesture', 'Blockly.Tooltip', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {'lang': 'es5'});
goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.IdGenerator', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object'], {});
goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.FieldTextInput', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es5'});
goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object'], {});
goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry'], {});
goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object'], {});
goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'});
goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {});
goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {});
goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.constants'], {});
goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {});
goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/events/ws_comment_events.js', ['Blockly.Events.CommentBase', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove'], ['Blockly.Events', 'Blockly.Events.Abstract', 'Blockly.Xml', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.object', 'Blockly.utils.xml']);
goog.addDependency('../../core/extensions.js', ['Blockly.Extensions'], ['Blockly.utils']);
goog.addDependency('../../core/field.js', ['Blockly.Field'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Gesture', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible', 'Blockly.IRegistrable', 'Blockly.MarkerManager', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {'lang': 'es5'});
goog.addDependency('../../core/field_angle.js', ['Blockly.FieldAngle'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/field_checkbox.js', ['Blockly.FieldCheckbox'], ['Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/field_colour.js', ['Blockly.FieldColour'], ['Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils.IdGenerator', 'Blockly.utils.KeyCodes', 'Blockly.utils.Size', 'Blockly.utils.aria', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/field_dropdown.js', ['Blockly.FieldDropdown'], ['Blockly.DropDownDiv', 'Blockly.Field', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.string', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/field_image.js', ['Blockly.FieldImage'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/field_label.js', ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/field_label_serializable.js', ['Blockly.FieldLabelSerializable'], ['Blockly.FieldLabel', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.object']);
goog.addDependency('../../core/field_multilineinput.js', ['Blockly.FieldMultilineInput'], ['Blockly.Css', 'Blockly.Field', 'Blockly.FieldTextInput', 'Blockly.WidgetDiv', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.KeyCodes', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es5'});
goog.addDependency('../../core/field_number.js', ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'Blockly.fieldRegistry', 'Blockly.utils.aria', 'Blockly.utils.object']);
goog.addDependency('../../core/field_registry.js', ['Blockly.fieldRegistry'], ['Blockly.registry']);
goog.addDependency('../../core/field_textinput.js', ['Blockly.FieldTextInput'], ['Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.browserEvents', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/field_variable.js', ['Blockly.FieldVariable'], ['Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.object']);
goog.addDependency('../../core/flyout_base.js', ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutMetricsManager', 'Blockly.Gesture', 'Blockly.IFlyout', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox', 'Blockly.utils.xml']);
goog.addDependency('../../core/flyout_button.js', ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.style'], {'lang': 'es5'});
goog.addDependency('../../core/flyout_horizontal.js', ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']);
goog.addDependency('../../core/flyout_vertical.js', ['Blockly.VerticalFlyout'], ['Blockly.Block', 'Blockly.DropDownDiv', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.WidgetDiv', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.object', 'Blockly.utils.toolbox']);
goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.Block', 'Blockly.constants', 'Blockly.utils.deprecation']);
goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate']);
goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es5'});
goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes'], {});
goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.Events', 'Blockly.blockAnimations', 'Blockly.connectionTypes', 'Blockly.constants'], {'lang': 'es5'});
goog.addDependency('../../core/interfaces/i_accessibility.js', ['Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible'], [], {});
goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], [], {});
goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], [], {});
goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], [], {});
goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], [], {});
goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], [], {});
goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], [], {});
goog.addDependency('../../core/interfaces/i_deletearea.js', ['Blockly.IDeleteArea'], [], {});
goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], [], {});
goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], [], {});
goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], [], {});
goog.addDependency('../../core/interfaces/i_plugin.js', ['Blockly.IPlugin'], [], {});
goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IPlugin'], {});
goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], [], {});
goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], [], {});
goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], [], {});
goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], [], {});
goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], [], {});
goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem', 'Blockly.ISelectableToolboxItem', 'Blockly.IToolboxItem'], [], {});
goog.addDependency('../../core/interfaces/i_workspace_plugin.js', ['Blockly.IWorkspacePlugin'], [], {});
goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes']);
goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.ComponentManager', 'Blockly.Events', 'Blockly.blockAnimations', 'Blockly.connectionTypes', 'Blockly.constants'], {'lang': 'es5'});
goog.addDependency('../../core/interfaces/i_accessibility.js', ['Blockly.IASTNodeLocation', 'Blockly.IASTNodeLocationSvg', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.IKeyboardAccessible'], []);
goog.addDependency('../../core/interfaces/i_autohideable.js', ['Blockly.IAutoHideable'], ['Blockly.IComponent']);
goog.addDependency('../../core/interfaces/i_block_dragger.js', ['Blockly.IBlockDragger'], []);
goog.addDependency('../../core/interfaces/i_bounded_element.js', ['Blockly.IBoundedElement'], []);
goog.addDependency('../../core/interfaces/i_bubble.js', ['Blockly.IBubble'], ['Blockly.IContextMenu', 'Blockly.IDraggable']);
goog.addDependency('../../core/interfaces/i_component.js', ['Blockly.IComponent'], []);
goog.addDependency('../../core/interfaces/i_connection_checker.js', ['Blockly.IConnectionChecker'], []);
goog.addDependency('../../core/interfaces/i_contextmenu.js', ['Blockly.IContextMenu'], []);
goog.addDependency('../../core/interfaces/i_copyable.js', ['Blockly.ICopyable'], []);
goog.addDependency('../../core/interfaces/i_deletable.js', ['Blockly.IDeletable'], []);
goog.addDependency('../../core/interfaces/i_delete_area.js', ['Blockly.IDeleteArea'], ['Blockly.IDragTarget']);
goog.addDependency('../../core/interfaces/i_drag_target.js', ['Blockly.IDragTarget'], ['Blockly.IComponent']);
goog.addDependency('../../core/interfaces/i_draggable.js', ['Blockly.IDraggable'], ['Blockly.IDeletable']);
goog.addDependency('../../core/interfaces/i_flyout.js', ['Blockly.IFlyout'], []);
goog.addDependency('../../core/interfaces/i_metrics_manager.js', ['Blockly.IMetricsManager'], []);
goog.addDependency('../../core/interfaces/i_movable.js', ['Blockly.IMovable'], []);
goog.addDependency('../../core/interfaces/i_positionable.js', ['Blockly.IPositionable'], ['Blockly.IComponent']);
goog.addDependency('../../core/interfaces/i_registrable.js', ['Blockly.IRegistrable'], []);
goog.addDependency('../../core/interfaces/i_registrable_field.js', ['Blockly.IRegistrableField'], []);
goog.addDependency('../../core/interfaces/i_selectable.js', ['Blockly.ISelectable'], []);
goog.addDependency('../../core/interfaces/i_styleable.js', ['Blockly.IStyleable'], []);
goog.addDependency('../../core/interfaces/i_toolbox.js', ['Blockly.IToolbox'], []);
goog.addDependency('../../core/interfaces/i_toolbox_item.js', ['Blockly.ICollapsibleToolboxItem', 'Blockly.ISelectableToolboxItem', 'Blockly.IToolboxItem'], []);
goog.addDependency('../../core/keyboard_nav/ast_node.js', ['Blockly.ASTNode'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Coordinate'], {'lang': 'es5'});
goog.addDependency('../../core/keyboard_nav/basic_cursor.js', ['Blockly.BasicCursor'], ['Blockly.ASTNode', 'Blockly.Cursor', 'Blockly.registry'], {'lang': 'es5'});
goog.addDependency('../../core/keyboard_nav/cursor.js', ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.Marker', 'Blockly.registry', 'Blockly.utils.object'], {'lang': 'es5'});
goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode'], {});
goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object'], {});
goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker'], {});
goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style'], {});
goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.IdGenerator', 'Blockly.utils.aria', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/keyboard_nav/marker.js', ['Blockly.Marker'], ['Blockly.ASTNode']);
goog.addDependency('../../core/keyboard_nav/tab_navigate_cursor.js', ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object']);
goog.addDependency('../../core/marker_manager.js', ['Blockly.MarkerManager'], ['Blockly.Cursor', 'Blockly.Marker']);
goog.addDependency('../../core/menu.js', ['Blockly.Menu'], ['Blockly.browserEvents', 'Blockly.utils.Coordinate', 'Blockly.utils.KeyCodes', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.style']);
goog.addDependency('../../core/menuitem.js', ['Blockly.MenuItem'], ['Blockly.utils.IdGenerator', 'Blockly.utils.aria', 'Blockly.utils.dom']);
goog.addDependency('../../core/metrics_manager.js', ['Blockly.FlyoutMetricsManager', 'Blockly.MetricsManager'], ['Blockly.IMetricsManager', 'Blockly.registry', 'Blockly.utils.Size', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global'], {});
goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.constants'], {});
goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.IdGenerator', 'Blockly.utils.Metrics', 'Blockly.utils.toolbox'], {});
goog.addDependency('../../core/plugin_manager.js', ['Blockly.PluginManager'], [], {});
goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/registry.js', ['Blockly.registry'], [], {});
goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry'], {});
goog.addDependency('../../core/msg.js', ['Blockly.Msg'], ['Blockly.utils.global']);
goog.addDependency('../../core/mutator.js', ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Options', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox', 'Blockly.utils.xml']);
goog.addDependency('../../core/names.js', ['Blockly.Names'], ['Blockly.Msg', 'Blockly.constants']);
goog.addDependency('../../core/options.js', ['Blockly.Options'], ['Blockly.Theme', 'Blockly.Themes.Classic', 'Blockly.registry', 'Blockly.utils.IdGenerator', 'Blockly.utils.Metrics', 'Blockly.utils.toolbox']);
goog.addDependency('../../core/positionable_helpers.js', ['Blockly.uiPosition'], ['Blockly.Scrollbar', 'Blockly.utils.Rect', 'Blockly.utils.toolbox']);
goog.addDependency('../../core/procedures.js', ['Blockly.Procedures'], ['Blockly.Blocks', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.Msg', 'Blockly.Names', 'Blockly.Workspace', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils.xml']);
goog.addDependency('../../core/registry.js', ['Blockly.registry'], []);
goog.addDependency('../../core/rendered_connection.js', ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/common/block_rendering.js', ['Blockly.blockRendering'], ['Blockly.registry']);
goog.addDependency('../../core/renderers/common/constants.js', ['Blockly.blockRendering.ConstantProvider'], ['Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent'], {'lang': 'es5'});
goog.addDependency('../../core/renderers/common/debugger.js', ['Blockly.blockRendering.Debug'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'});
goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {});
goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], [], {});
goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes'], {});
goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.IRegistrable', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.connectionTypes', 'Blockly.constants'], {});
goog.addDependency('../../core/renderers/common/drawer.js', ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']);
goog.addDependency('../../core/renderers/common/i_path_object.js', ['Blockly.blockRendering.IPathObject'], []);
goog.addDependency('../../core/renderers/common/info.js', ['Blockly.blockRendering.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes']);
goog.addDependency('../../core/renderers/common/marker_svg.js', ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode', 'Blockly.Events', 'Blockly.Events.MarkerMove', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/renderers/common/path_object.js', ['Blockly.blockRendering.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/renderers/common/renderer.js', ['Blockly.blockRendering.Renderer'], ['Blockly.IRegistrable', 'Blockly.InsertionMarkerManager', 'Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Debug', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo', 'Blockly.connectionTypes', 'Blockly.constants']);
goog.addDependency('../../core/renderers/geras/constants.js', ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {'lang': 'es5'});
goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.geras.Highlighter', 'Blockly.geras.RenderInfo', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {});
goog.addDependency('../../core/renderers/geras/drawer.js', ['Blockly.geras.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.geras.Highlighter', 'Blockly.geras.RenderInfo', 'Blockly.utils.object', 'Blockly.utils.svgPaths']);
goog.addDependency('../../core/renderers/geras/highlight_constants.js', ['Blockly.geras.HighlightConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.svgPaths'], {'lang': 'es5'});
goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths'], {});
goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras', 'Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/geras/measurables/inputs.js', ['Blockly.geras.InlineInput', 'Blockly.geras.StatementInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.PathObject', 'Blockly.geras.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types'], {});
goog.addDependency('../../core/renderers/measurables/connections.js', ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/measurables/inputs.js', ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.StatementInput'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/measurables/row_elements.js', ['Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.SquareCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/measurables/rows.js', ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.TopRow'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/measurables/types.js', ['Blockly.blockRendering.Types'], [], {});
goog.addDependency('../../core/renderers/minimalist/constants.js', ['Blockly.minimalist.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/minimalist/drawer.js', ['Blockly.minimalist.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimalist', 'Blockly.minimalist.RenderInfo'], ['Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/geras/highlighter.js', ['Blockly.geras.Highlighter'], ['Blockly.blockRendering.Types', 'Blockly.utils.svgPaths']);
goog.addDependency('../../core/renderers/geras/info.js', ['Blockly.geras', 'Blockly.geras.RenderInfo'], ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.geras.InlineInput', 'Blockly.geras.StatementInput', 'Blockly.inputTypes', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/geras/measurables/inputs.js', ['Blockly.geras.InlineInput', 'Blockly.geras.StatementInput'], ['Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.StatementInput', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/geras/path_object.js', ['Blockly.geras.PathObject'], ['Blockly.Theme', 'Blockly.blockRendering.PathObject', 'Blockly.geras.ConstantProvider', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/geras/renderer.js', ['Blockly.geras.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.geras.ConstantProvider', 'Blockly.geras.Drawer', 'Blockly.geras.HighlightConstantProvider', 'Blockly.geras.PathObject', 'Blockly.geras.RenderInfo', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/measurables/base.js', ['Blockly.blockRendering.Measurable'], ['Blockly.blockRendering.Types']);
goog.addDependency('../../core/renderers/measurables/connections.js', ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/measurables/inputs.js', ['Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.StatementInput'], ['Blockly.blockRendering.Connection', 'Blockly.blockRendering.Types', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/measurables/row_elements.js', ['Blockly.blockRendering.Field', 'Blockly.blockRendering.Hat', 'Blockly.blockRendering.Icon', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.JaggedEdge', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.SquareCorner'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/measurables/rows.js', ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.TopRow'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.InputConnection', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.Types', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/measurables/types.js', ['Blockly.blockRendering.Types'], []);
goog.addDependency('../../core/renderers/minimalist/constants.js', ['Blockly.minimalist.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/minimalist/drawer.js', ['Blockly.minimalist.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/minimalist/info.js', ['Blockly.minimalist', 'Blockly.minimalist.RenderInfo'], ['Blockly.utils.object']);
goog.addDependency('../../core/renderers/minimalist/renderer.js', ['Blockly.minimalist.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.minimalist.ConstantProvider', 'Blockly.minimalist.Drawer', 'Blockly.minimalist.RenderInfo', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/thrasos/info.js', ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/thrasos/renderer.js', ['Blockly.thrasos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.thrasos.RenderInfo', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/zelos/constants.js', ['Blockly.zelos.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.Svg', 'Blockly.utils.colour', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths'], {'lang': 'es5'});
goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.zelos.RenderInfo'], {});
goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.TopRow'], {});
goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/zelos/measurables/rows.js', ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.utils.object'], {});
goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider'], {});
goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo'], {});
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Themes.Dark', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer'], {});
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes'], {});
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {});
goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils', 'Blockly.utils.object'], {});
goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme'], {});
goog.addDependency('../../core/theme/dark.js', ['Blockly.Themes.Dark'], ['Blockly.Theme'], {});
goog.addDependency('../../core/theme/deuteranopia.js', ['Blockly.Themes.Deuteranopia'], ['Blockly.Theme'], {});
goog.addDependency('../../core/theme/highcontrast.js', ['Blockly.Themes.HighContrast'], ['Blockly.Theme'], {});
goog.addDependency('../../core/theme/modern.js', ['Blockly.Themes.Modern'], ['Blockly.Theme'], {});
goog.addDependency('../../core/theme/tritanopia.js', ['Blockly.Themes.Tritanopia'], ['Blockly.Theme'], {});
goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme'], {});
goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.Theme'], {});
goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {});
goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'});
goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.CollapsibleToolboxCategory', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], [], {});
goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.utils.string'], {});
goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string'], {});
goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object'], {});
goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IPositionable', 'Blockly.Scrollbar', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], [], {});
goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], [], {});
goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], [], {});
goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], [], {});
goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent'], {});
goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], [], {});
goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.IdGenerator'], [], {});
goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], [], {});
goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], [], {});
goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], [], {});
goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], [], {});
goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], [], {});
goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], [], {});
goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], [], {});
goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size'], {});
goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], [], {});
goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], [], {});
goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.constants'], {});
goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global'], {});
goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], [], {});
goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.object'], {});
goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils'], {});
goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.utils.dom'], {});
goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math'], {});
goog.addDependency('../../core/renderers/zelos/drawer.js', ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.Drawer', 'Blockly.utils.object', 'Blockly.utils.svgPaths', 'Blockly.zelos.RenderInfo']);
goog.addDependency('../../core/renderers/zelos/info.js', ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.FieldImage', 'Blockly.FieldLabel', 'Blockly.FieldTextInput', 'Blockly.blockRendering.InRowSpacer', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Types', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils.object', 'Blockly.zelos.BottomRow', 'Blockly.zelos.RightConnectionShape', 'Blockly.zelos.TopRow']);
goog.addDependency('../../core/renderers/zelos/marker_svg.js', ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/renderers/zelos/measurables/inputs.js', ['Blockly.zelos.StatementInput'], ['Blockly.blockRendering.StatementInput', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/zelos/measurables/row_elements.js', ['Blockly.zelos.RightConnectionShape'], ['Blockly.blockRendering.Measurable', 'Blockly.blockRendering.Types', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/zelos/measurables/rows.js', ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.utils.object']);
goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider']);
goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo']);
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Themes.Dark', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes']);
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object']);
goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils', 'Blockly.utils.object']);
goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme']);
goog.addDependency('../../core/theme/dark.js', ['Blockly.Themes.Dark'], ['Blockly.Theme']);
goog.addDependency('../../core/theme/deuteranopia.js', ['Blockly.Themes.Deuteranopia'], ['Blockly.Theme']);
goog.addDependency('../../core/theme/highcontrast.js', ['Blockly.Themes.HighContrast'], ['Blockly.Theme']);
goog.addDependency('../../core/theme/modern.js', ['Blockly.Themes.Modern'], ['Blockly.Theme']);
goog.addDependency('../../core/theme/tritanopia.js', ['Blockly.Themes.Tritanopia'], ['Blockly.Theme']);
goog.addDependency('../../core/theme/zelos.js', ['Blockly.Themes.Zelos'], ['Blockly.Theme']);
goog.addDependency('../../core/theme_manager.js', ['Blockly.ThemeManager'], ['Blockly.Theme']);
goog.addDependency('../../core/toolbox/category.js', ['Blockly.ToolboxCategory'], ['Blockly.ISelectableToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/toolbox/collapsible_category.js', ['Blockly.CollapsibleToolboxCategory'], ['Blockly.ICollapsibleToolboxItem', 'Blockly.ToolboxCategory', 'Blockly.ToolboxItem', 'Blockly.ToolboxSeparator', 'Blockly.registry', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox']);
goog.addDependency('../../core/toolbox/separator.js', ['Blockly.ToolboxSeparator'], ['Blockly.IToolboxItem', 'Blockly.ToolboxItem', 'Blockly.registry', 'Blockly.utils.dom'], {'lang': 'es5'});
goog.addDependency('../../core/toolbox/toolbox.js', ['Blockly.Toolbox'], ['Blockly.BlockSvg', 'Blockly.CollapsibleToolboxCategory', 'Blockly.ComponentManager', 'Blockly.Css', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.ToolboxItemSelect', 'Blockly.IAutoHideable', 'Blockly.IKeyboardAccessible', 'Blockly.IStyleable', 'Blockly.IToolbox', 'Blockly.Options', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/toolbox/toolbox_item.js', ['Blockly.ToolboxItem'], ['Blockly.IToolboxItem']);
goog.addDependency('../../core/tooltip.js', ['Blockly.Tooltip'], ['Blockly.browserEvents', 'Blockly.utils.string']);
goog.addDependency('../../core/touch.js', ['Blockly.Touch'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.string']);
goog.addDependency('../../core/touch_gesture.js', ['Blockly.TouchGesture'], ['Blockly.Gesture', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.object']);
goog.addDependency('../../core/trashcan.js', ['Blockly.Trashcan'], ['Blockly.ComponentManager', 'Blockly.DeleteArea', 'Blockly.Events', 'Blockly.Events.TrashcanOpen', 'Blockly.IAutoHideable', 'Blockly.IPositionable', 'Blockly.Options', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/utils.js', ['Blockly.utils'], ['Blockly.Msg', 'Blockly.constants', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.colour', 'Blockly.utils.global', 'Blockly.utils.string', 'Blockly.utils.style', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/utils/aria.js', ['Blockly.utils.aria'], []);
goog.addDependency('../../core/utils/colour.js', ['Blockly.utils.colour'], []);
goog.addDependency('../../core/utils/coordinate.js', ['Blockly.utils.Coordinate'], []);
goog.addDependency('../../core/utils/deprecation.js', ['Blockly.utils.deprecation'], []);
goog.addDependency('../../core/utils/dom.js', ['Blockly.utils.dom'], ['Blockly.utils.Svg', 'Blockly.utils.userAgent']);
goog.addDependency('../../core/utils/global.js', ['Blockly.utils.global'], []);
goog.addDependency('../../core/utils/idgenerator.js', ['Blockly.utils.IdGenerator'], []);
goog.addDependency('../../core/utils/keycodes.js', ['Blockly.utils.KeyCodes'], []);
goog.addDependency('../../core/utils/math.js', ['Blockly.utils.math'], []);
goog.addDependency('../../core/utils/metrics.js', ['Blockly.utils.Metrics'], []);
goog.addDependency('../../core/utils/object.js', ['Blockly.utils.object'], []);
goog.addDependency('../../core/utils/rect.js', ['Blockly.utils.Rect'], []);
goog.addDependency('../../core/utils/size.js', ['Blockly.utils.Size'], []);
goog.addDependency('../../core/utils/string.js', ['Blockly.utils.string'], []);
goog.addDependency('../../core/utils/style.js', ['Blockly.utils.style'], ['Blockly.utils.Coordinate', 'Blockly.utils.Size']);
goog.addDependency('../../core/utils/svg.js', ['Blockly.utils.Svg'], []);
goog.addDependency('../../core/utils/svg_paths.js', ['Blockly.utils.svgPaths'], []);
goog.addDependency('../../core/utils/toolbox.js', ['Blockly.utils.toolbox'], ['Blockly.Xml', 'Blockly.constants']);
goog.addDependency('../../core/utils/useragent.js', ['Blockly.utils.userAgent'], ['Blockly.utils.global']);
goog.addDependency('../../core/utils/xml.js', ['Blockly.utils.xml'], []);
goog.addDependency('../../core/variable_map.js', ['Blockly.VariableMap'], ['Blockly.Events', 'Blockly.Events.VarDelete', 'Blockly.Events.VarRename', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.object']);
goog.addDependency('../../core/variable_model.js', ['Blockly.VariableModel'], ['Blockly.Events', 'Blockly.Events.VarCreate', 'Blockly.utils']);
goog.addDependency('../../core/variables.js', ['Blockly.Variables'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Xml', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.xml']);
goog.addDependency('../../core/variables_dynamic.js', ['Blockly.VariablesDynamic'], ['Blockly.Blocks', 'Blockly.Msg', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.utils.xml']);
goog.addDependency('../../core/warning.js', ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/widgetdiv.js', ['Blockly.WidgetDiv'], ['Blockly.utils.dom']);
goog.addDependency('../../core/workspace.js', ['Blockly.Workspace'], ['Blockly.ConnectionChecker', 'Blockly.Events', 'Blockly.IASTNodeLocation', 'Blockly.Options', 'Blockly.VariableMap', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.math']);
goog.addDependency('../../core/workspace_audio.js', ['Blockly.WorkspaceAudio'], ['Blockly.constants', 'Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.userAgent'], {'lang': 'es5'});
goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object'], {});
goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {});
goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate'], {});
goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.PluginManager', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml'], {});
goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/workspace_comment.js', ['Blockly.WorkspaceComment'], ['Blockly.Events', 'Blockly.Events.CommentChange', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.xml']);
goog.addDependency('../../core/workspace_comment_render_svg.js', ['Blockly.WorkspaceCommentSvg.render'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/workspace_comment_svg.js', ['Blockly.WorkspaceCommentSvg'], ['Blockly.Css', 'Blockly.Events', 'Blockly.Events.CommentCreate', 'Blockly.Events.CommentDelete', 'Blockly.Events.CommentMove', 'Blockly.Events.Selected', 'Blockly.WorkspaceComment', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object']);
goog.addDependency('../../core/workspace_drag_surface_svg.js', ['Blockly.WorkspaceDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
goog.addDependency('../../core/workspace_dragger.js', ['Blockly.WorkspaceDragger'], ['Blockly.utils.Coordinate']);
goog.addDependency('../../core/workspace_svg.js', ['Blockly.WorkspaceSvg'], ['Blockly.BlockSvg', 'Blockly.ComponentManager', 'Blockly.ConnectionDB', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.ThemeChange', 'Blockly.Events.ViewportChange', 'Blockly.Gesture', 'Blockly.Grid', 'Blockly.IASTNodeLocationSvg', 'Blockly.MarkerManager', 'Blockly.MetricsManager', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ThemeManager', 'Blockly.Themes.Classic', 'Blockly.TouchGesture', 'Blockly.Workspace', 'Blockly.WorkspaceAudio', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.Xml', 'Blockly.blockRendering', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Rect', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.toolbox'], {'lang': 'es5'});
goog.addDependency('../../core/xml.js', ['Blockly.Xml'], ['Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.dom', 'Blockly.utils.xml']);
goog.addDependency('../../core/zoom_controls.js', ['Blockly.ZoomControls'], ['Blockly.ComponentManager', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.IPositionable', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.constants', 'Blockly.uiPosition', 'Blockly.utils', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es5'});
goog.addDependency("base.js", [], []);
// Load Blockly.
goog.require('Blockly.requires')
goog.require('Blockly.requires');
delete root.BLOCKLY_DIR;
delete root.BLOCKLY_BOOT;
-1
View File
@@ -15,7 +15,6 @@
*/
'use strict';
goog.provide('Blockly.Blocks.lists'); // Deprecated
goog.provide('Blockly.Constants.Lists');
goog.require('Blockly');
+2 -2
View File
@@ -473,9 +473,9 @@ Blockly.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN = {
},
/**
* Reconnects child blocks.
* @param {!Array.<?Blockly.RenderedConnection>} valueConnections List of
* @param {!Array<?Blockly.RenderedConnection>} valueConnections List of
* value connections for 'if' input.
* @param {!Array.<?Blockly.RenderedConnection>} statementConnections List of
* @param {!Array<?Blockly.RenderedConnection>} statementConnections List of
* statement connections for 'do' input.
* @param {?Blockly.RenderedConnection} elseStatementConnection Statement
* connection for else input.
+6 -6
View File
@@ -264,7 +264,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
},
/**
* Return all variables referenced by this block.
* @return {!Array.<string>} List of variable names.
* @return {!Array<string>} List of variable names.
* @this {Blockly.Block}
*/
getVars: function() {
@@ -272,7 +272,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
},
/**
* Return all variables referenced by this block.
* @return {!Array.<!Blockly.VariableModel>} List of variable models.
* @return {!Array<!Blockly.VariableModel>} List of variable models.
* @this {Blockly.Block}
*/
getVarModels: function() {
@@ -634,8 +634,8 @@ Blockly.Blocks['procedures_callnoreturn'] = {
},
/**
* Notification that the procedure's parameters have changed.
* @param {!Array.<string>} paramNames New param names, e.g. ['x', 'y', 'z'].
* @param {!Array.<string>} paramIds IDs of params (consistent for each
* @param {!Array<string>} paramNames New param names, e.g. ['x', 'y', 'z'].
* @param {!Array<string>} paramIds IDs of params (consistent for each
* parameter through the life of a mutator, regardless of param renaming),
* e.g. ['piua', 'f8b_', 'oi.o'].
* @private
@@ -809,7 +809,7 @@ Blockly.Blocks['procedures_callnoreturn'] = {
},
/**
* Return all variables referenced by this block.
* @return {!Array.<string>} List of variable names.
* @return {!Array<string>} List of variable names.
* @this {Blockly.Block}
*/
getVars: function() {
@@ -817,7 +817,7 @@ Blockly.Blocks['procedures_callnoreturn'] = {
},
/**
* Return all variables referenced by this block.
* @return {!Array.<!Blockly.VariableModel>} List of variable models.
* @return {!Array<!Blockly.VariableModel>} List of variable models.
* @this {Blockly.Block}
*/
getVarModels: function() {
+1 -1
View File
@@ -13,7 +13,7 @@
'use strict';Blockly.Blocks.colour={};Blockly.Constants={};Blockly.Constants.Colour={};Blockly.Constants.Colour.HUE=20;
Blockly.defineBlocksWithJsonArray([{type:"colour_picker",message0:"%1",args0:[{type:"field_colour",name:"COLOUR",colour:"#ff0000"}],output:"Colour",helpUrl:"%{BKY_COLOUR_PICKER_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_PICKER_TOOLTIP}",extensions:["parent_tooltip_when_inline"]},{type:"colour_random",message0:"%{BKY_COLOUR_RANDOM_TITLE}",output:"Colour",helpUrl:"%{BKY_COLOUR_RANDOM_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_RANDOM_TOOLTIP}"},{type:"colour_rgb",message0:"%{BKY_COLOUR_RGB_TITLE} %{BKY_COLOUR_RGB_RED} %1 %{BKY_COLOUR_RGB_GREEN} %2 %{BKY_COLOUR_RGB_BLUE} %3",
args0:[{type:"input_value",name:"RED",check:"Number",align:"RIGHT"},{type:"input_value",name:"GREEN",check:"Number",align:"RIGHT"},{type:"input_value",name:"BLUE",check:"Number",align:"RIGHT"}],output:"Colour",helpUrl:"%{BKY_COLOUR_RGB_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_RGB_TOOLTIP}"},{type:"colour_blend",message0:"%{BKY_COLOUR_BLEND_TITLE} %{BKY_COLOUR_BLEND_COLOUR1} %1 %{BKY_COLOUR_BLEND_COLOUR2} %2 %{BKY_COLOUR_BLEND_RATIO} %3",args0:[{type:"input_value",name:"COLOUR1",check:"Colour",
align:"RIGHT"},{type:"input_value",name:"COLOUR2",check:"Colour",align:"RIGHT"},{type:"input_value",name:"RATIO",check:"Number",align:"RIGHT"}],output:"Colour",helpUrl:"%{BKY_COLOUR_BLEND_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_BLEND_TOOLTIP}"}]);Blockly.Blocks.lists={};Blockly.Constants.Lists={};Blockly.Constants.Lists.HUE=260;
align:"RIGHT"},{type:"input_value",name:"COLOUR2",check:"Colour",align:"RIGHT"},{type:"input_value",name:"RATIO",check:"Number",align:"RIGHT"}],output:"Colour",helpUrl:"%{BKY_COLOUR_BLEND_HELPURL}",style:"colour_blocks",tooltip:"%{BKY_COLOUR_BLEND_TOOLTIP}"}]);Blockly.Constants.Lists={};Blockly.Constants.Lists.HUE=260;
Blockly.defineBlocksWithJsonArray([{type:"lists_create_empty",message0:"%{BKY_LISTS_CREATE_EMPTY_TITLE}",output:"Array",style:"list_blocks",tooltip:"%{BKY_LISTS_CREATE_EMPTY_TOOLTIP}",helpUrl:"%{BKY_LISTS_CREATE_EMPTY_HELPURL}"},{type:"lists_repeat",message0:"%{BKY_LISTS_REPEAT_TITLE}",args0:[{type:"input_value",name:"ITEM"},{type:"input_value",name:"NUM",check:"Number"}],output:"Array",style:"list_blocks",tooltip:"%{BKY_LISTS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_LISTS_REPEAT_HELPURL}"},{type:"lists_reverse",
message0:"%{BKY_LISTS_REVERSE_MESSAGE0}",args0:[{type:"input_value",name:"LIST",check:"Array"}],output:"Array",inputsInline:!0,style:"list_blocks",tooltip:"%{BKY_LISTS_REVERSE_TOOLTIP}",helpUrl:"%{BKY_LISTS_REVERSE_HELPURL}"},{type:"lists_isEmpty",message0:"%{BKY_LISTS_ISEMPTY_TITLE}",args0:[{type:"input_value",name:"VALUE",check:["String","Array"]}],output:"Boolean",style:"list_blocks",tooltip:"%{BKY_LISTS_ISEMPTY_TOOLTIP}",helpUrl:"%{BKY_LISTS_ISEMPTY_HELPURL}"},{type:"lists_length",message0:"%{BKY_LISTS_LENGTH_TITLE}",
args0:[{type:"input_value",name:"VALUE",check:["String","Array"]}],output:"Number",style:"list_blocks",tooltip:"%{BKY_LISTS_LENGTH_TOOLTIP}",helpUrl:"%{BKY_LISTS_LENGTH_HELPURL}"}]);
File diff suppressed because one or more lines are too long
-507
View File
@@ -1,507 +0,0 @@
#!/usr/bin/python2.7
#
# Deprecation warning: (July 2020)
# This build script has been deprecated, please use 'npm run build' instead.
# The script will be removed from Blockly core in Q4 of 2020.
#
# Compresses the core Blockly files into a single JavaScript file.
#
# Copyright 2012 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Usage: build.py <0 or more of core, generators, langfiles>
# build.py with no parameters builds all files.
# core builds blockly_compressed, blockly_uncompressed, and blocks_compressed.
# generators builds every <language>_compressed.js.
# langfiles builds every msg/js/<LANG>.js file.
# This script generates two versions of Blockly's core files:
# blockly_compressed.js
# blockly_uncompressed.js
# The compressed file is a concatenation of all of Blockly's core files which
# have been run through Google's Closure Compiler. This is done using the
# online API (which takes a few seconds and requires an Internet connection).
# The uncompressed file is a script that loads in each of Blockly's core files
# one by one. This takes much longer for a browser to load, but is useful
# when debugging code since line numbers are meaningful and variables haven't
# been renamed. The uncompressed file also allows for a faster development
# cycle since there is no need to rebuild or recompile, just reload.
#
# This script also generates:
# blocks_compressed.js: The compressed Blockly language blocks.
# javascript_compressed.js: The compressed JavaScript generator.
# python_compressed.js: The compressed Python generator.
# php_compressed.js: The compressed PHP generator.
# lua_compressed.js: The compressed Lua generator.
# dart_compressed.js: The compressed Dart generator.
# msg/js/<LANG>.js for every language <LANG> defined in msg/js/<LANG>.json.
import argparse
import codecs
import glob
import json
import os
import re
import subprocess
import sys
import threading
if sys.version_info[0] == 2:
import httplib
from urllib import urlencode
else:
import http.client as httplib
from urllib.parse import urlencode
from importlib import reload
# Read package.json and extract the current Blockly version.
blocklyVersion = json.loads(open('package.json', 'r').read())['version']
def import_path(fullpath):
"""Import a file with full path specification.
Allows one to import from any directory, something __import__ does not do.
Args:
fullpath: Path and filename of import.
Returns:
An imported module.
"""
path, filename = os.path.split(fullpath)
filename, ext = os.path.splitext(filename)
sys.path.append(path)
module = __import__(filename)
reload(module) # Might be out of date.
del sys.path[-1]
return module
HEADER = ("// Do not edit this file; automatically generated by build.py.\n"
"'use strict';\n")
class Gen_uncompressed(threading.Thread):
"""Generate a JavaScript file that loads Blockly's raw files.
Runs in a separate thread.
"""
def __init__(self, search_paths, target_filename):
threading.Thread.__init__(self)
self.search_paths = search_paths
self.target_filename = target_filename
def run(self):
f = open(self.target_filename, 'w')
f.write(HEADER)
f.write("""
this.IS_NODE_JS = !!(typeof module !== 'undefined' && module.exports);
this.BLOCKLY_DIR = (function(root) {
if (!root.IS_NODE_JS) {
// Find name of current directory.
var scripts = document.getElementsByTagName('script');
var re = new RegExp('(.+)[\/]blockly_(.*)uncompressed\.js$');
for (var i = 0, script; script = scripts[i]; i++) {
var match = re.exec(script.src);
if (match) {
return match[1];
}
}
alert('Could not detect Blockly\\'s directory name.');
}
return '';
})(this);
this.BLOCKLY_BOOT = function(root) {
// Execute after Closure has loaded.
""")
add_dependency = []
base_path = calcdeps.FindClosureBasePath(self.search_paths)
for dep in calcdeps.BuildDependenciesFromFiles(self.search_paths):
add_dependency.append(calcdeps.GetDepsLine(dep, base_path))
add_dependency.sort() # Deterministic build.
add_dependency = '\n'.join(add_dependency)
f.write(add_dependency + '\n')
f.write('\n')
f.write('// Load Blockly.\n')
f.write('goog.require(\'Blockly.requires\')\n')
f.write("""
delete root.BLOCKLY_DIR;
delete root.BLOCKLY_BOOT;
delete root.IS_NODE_JS;
};
if (this.IS_NODE_JS) {
this.BLOCKLY_BOOT(this);
module.exports = Blockly;
} else {
document.write('<script src="' + this.BLOCKLY_DIR +
'/closure/goog/base.js"></script>');
document.write('<script>this.BLOCKLY_BOOT(this);</script>');
}
""")
f.close()
print("SUCCESS: " + self.target_filename)
class Gen_compressed(threading.Thread):
"""Generate a JavaScript file that contains all of Blockly's core and all
required parts of Closure, compiled together.
Uses the Closure Compiler's online API.
Runs in a separate thread.
"""
def __init__(self, search_paths, bundles):
threading.Thread.__init__(self)
self.search_paths = search_paths
self.bundles = bundles
def run(self):
if (self.bundles.core):
self.gen_core()
self.gen_blocks()
if (self.bundles.generators):
self.gen_generator("javascript")
self.gen_generator("python")
self.gen_generator("php")
self.gen_generator("lua")
self.gen_generator("dart")
def gen_core(self):
target_filename = "blockly_compressed.js"
# Define the parameters for the POST request.
params = [
("compilation_level", "SIMPLE_OPTIMIZATIONS"),
("use_closure_library", "false"),
("output_format", "json"),
("output_info", "compiled_code"),
("output_info", "warnings"),
("output_info", "errors"),
("output_info", "statistics"),
("warning_level", "DEFAULT"),
]
# Read in all the source files.
filenames = calcdeps.CalculateDependencies(self.search_paths,
[os.path.join("core", "requires.js")])
filenames.sort() # Deterministic build.
for filename in filenames:
# Filter out the Closure files (the compiler will add them).
if filename.startswith("closure"):
continue
f = codecs.open(filename, encoding="utf-8")
code = "".join(f.readlines())
# Inject the Blockly version.
if filename == "core/blockly.js":
code = code.replace("Blockly.VERSION = 'uncompiled';",
"Blockly.VERSION = '%s';" % blocklyVersion)
# Strip out all requireType calls.
code = re.sub(r"goog.requireType(.*)", "", code)
params.append(("js_code", code.encode("utf-8")))
f.close()
self.do_compile(params, target_filename, filenames, "")
def gen_blocks(self):
target_filename = "blocks_compressed.js"
# Define the parameters for the POST request.
params = [
("compilation_level", "SIMPLE_OPTIMIZATIONS"),
("output_format", "json"),
("output_info", "compiled_code"),
("output_info", "warnings"),
("output_info", "errors"),
("output_info", "statistics"),
("warning_level", "DEFAULT"),
]
# Add Blockly, Blockly.Blocks, and all fields to be compatible with the compiler.
params.append(("js_code", """
goog.provide('Blockly');
goog.provide('Blockly.Blocks');
goog.provide('Blockly.Comment');
goog.provide('Blockly.FieldCheckbox');
goog.provide('Blockly.FieldColour');
goog.provide('Blockly.FieldDropdown');
goog.provide('Blockly.FieldImage');
goog.provide('Blockly.FieldLabel');
goog.provide('Blockly.FieldMultilineInput');
goog.provide('Blockly.FieldNumber');
goog.provide('Blockly.FieldTextInput');
goog.provide('Blockly.FieldVariable');
goog.provide('Blockly.Mutator');
goog.provide('Blockly.Warning');
"""))
# Read in all the source files.
filenames = glob.glob(os.path.join("blocks", "*.js"))
filenames.sort() # Deterministic build.
for filename in filenames:
f = codecs.open(filename, encoding="utf-8")
params.append(("js_code", "".join(f.readlines()).encode("utf-8")))
f.close()
# Remove Blockly, Blockly.Blocks and all fields to be compatible with Blockly.
remove = r"var Blockly=\{[^;]*\};\n?"
self.do_compile(params, target_filename, filenames, remove)
def gen_generator(self, language):
target_filename = language + "_compressed.js"
# Define the parameters for the POST request.
params = [
("compilation_level", "SIMPLE_OPTIMIZATIONS"),
("output_format", "json"),
("output_info", "compiled_code"),
("output_info", "warnings"),
("output_info", "errors"),
("output_info", "statistics"),
("warning_level", "DEFAULT"),
]
# Read in all the source files.
# Add Blockly.Generator and Blockly.utils.string to be compatible
# with the compiler.
params.append(("js_code", """
goog.provide('Blockly.Generator');
goog.provide('Blockly.utils.global');
goog.provide('Blockly.utils.string');
"""))
filenames = glob.glob(
os.path.join("generators", language, "*.js"))
filenames.sort() # Deterministic build.
filenames.insert(0, os.path.join("generators", language + ".js"))
for filename in filenames:
f = codecs.open(filename, encoding="utf-8")
params.append(("js_code", "".join(f.readlines()).encode("utf-8")))
f.close()
filenames.insert(0, "[goog.provide]")
# Remove Blockly.Generator and Blockly.utils.string to be compatible
# with Blockly.
remove = r"var Blockly=\{[^;]*\};\s*Blockly.utils.global={};\s*Blockly.utils.string={};\n?"
self.do_compile(params, target_filename, filenames, remove)
def do_compile(self, params, target_filename, filenames, remove):
# Send the request to Google.
headers = {"Content-type": "application/x-www-form-urlencoded"}
conn = httplib.HTTPSConnection("closure-compiler.appspot.com")
conn.request("POST", "/compile", urlencode(params), headers)
response = conn.getresponse()
# Decode is necessary for Python 3.4 compatibility
json_str = response.read().decode("utf-8")
conn.close()
# Parse the JSON response.
try:
json_data = json.loads(json_str)
except ValueError:
print("ERROR: Could not parse JSON for %s. Raw data:" % target_filename)
print(json_str)
return
def file_lookup(name):
if not name.startswith("Input_"):
return "???"
n = int(name[6:])
return filenames[n]
if "serverErrors" in json_data:
errors = json_data["serverErrors"]
for error in errors:
print("SERVER ERROR: %s" % target_filename)
print(error["error"])
elif "errors" in json_data:
errors = json_data["errors"]
for error in errors:
print("FATAL ERROR")
print(error["error"])
if error["file"]:
print("%s at line %d:" % (
file_lookup(error["file"]), error["lineno"]))
print(error["line"])
print((" " * error["charno"]) + "^")
sys.exit(1)
else:
if "warnings" in json_data:
warnings = json_data["warnings"]
for warning in warnings:
print("WARNING")
print(warning["warning"])
if warning["file"]:
print("%s at line %d:" % (
file_lookup(warning["file"]), warning["lineno"]))
print(warning["line"])
print((" " * warning["charno"]) + "^")
print()
if not "compiledCode" in json_data:
print("FATAL ERROR: Compiler did not return compiledCode.")
sys.exit(1)
code = HEADER + "\n" + json_data["compiledCode"]
# Remove Blockly definitions to be compatible with Blockly.
code = re.sub(remove, "", code)
code = self.trim_licence(code)
stats = json_data["statistics"]
original_b = stats["originalSize"]
compressed_b = stats["compressedSize"]
if original_b > 0 and compressed_b > 0:
f = open(target_filename, "w")
f.write(code)
f.close()
original_kb = int(original_b / 1024 + 0.5)
compressed_kb = int(compressed_b / 1024 + 0.5)
ratio = int(float(compressed_b) / float(original_b) * 100 + 0.5)
print("SUCCESS: " + target_filename)
print("Size changed from %d KB to %d KB (%d%%)." % (
original_kb, compressed_kb, ratio))
else:
print("UNKNOWN ERROR")
def trim_licence(self, code):
"""Strip out Google's and MIT's Apache licences.
JS Compiler preserves dozens of Apache licences in the Blockly code.
Remove these if they belong to Google or MIT.
MIT's permission to do this is logged in Blockly issue 2412.
Args:
code: Large blob of compiled source code.
Returns:
Code with Google's and MIT's Apache licences trimmed.
"""
apache2 = re.compile("""/\\*
(Copyright \\d+ (Google LLC|Massachusetts Institute of Technology))
( All rights reserved.
)? SPDX-License-Identifier: Apache-2.0
\\*/""")
return re.sub(apache2, "", code)
class Gen_langfiles(threading.Thread):
"""Generate JavaScript file for each natural language supported.
Runs in a separate thread.
"""
def __init__(self):
threading.Thread.__init__(self)
def run(self):
# The files msg/json/{en,qqq,synonyms}.json depend on msg/messages.js.
try:
subprocess.check_call([
"python",
os.path.join("scripts", "i18n", "js_to_json.py"),
"--input_file", "msg/messages.js",
"--output_dir", "msg/json/",
"--quiet"])
except (subprocess.CalledProcessError, OSError) as e:
# Documentation for subprocess.check_call says that CalledProcessError
# will be raised on failure, but I found that OSError is also possible.
print("Error running scripts/i18n/js_to_json.py: ", e)
sys.exit(1)
# Checking whether it is necessary to rebuild the js files would be a lot of
# work since we would have to compare each <lang>.json file with each
# <lang>.js file. Rebuilding is easy and cheap, so just go ahead and do it.
try:
# Use create_messages.py to create .js files from .json files.
cmd = [
"python",
os.path.join("scripts", "i18n", "create_messages.py"),
"--source_lang_file", os.path.join("msg", "json", "en.json"),
"--source_synonym_file", os.path.join("msg", "json", "synonyms.json"),
"--source_constants_file", os.path.join("msg", "json", "constants.json"),
"--key_file", os.path.join("msg", "json", "keys.json"),
"--output_dir", os.path.join("msg", "js"),
"--quiet"]
json_files = glob.glob(os.path.join("msg", "json", "*.json"))
json_files = [file for file in json_files if not
(file.endswith(("keys.json", "synonyms.json", "qqq.json", "constants.json")))]
cmd.extend(json_files)
subprocess.check_call(cmd)
except (subprocess.CalledProcessError, OSError) as e:
print("Error running scripts/i18n/create_messages.py: ", e)
sys.exit(1)
# Output list of .js files created.
for f in json_files:
# This assumes the path to the current directory does not contain "json".
f = f.replace("json", "js")
if os.path.isfile(f):
print("SUCCESS: " + f)
else:
print("FAILED to create " + f)
# Class to hold arguments if user passes in old argument style.
class Arguments:
def __init__(self):
self.core = False
self.generators = False
self.langfiles = False
# Gets the command line arguments.
def get_args():
parser = argparse.ArgumentParser(description="Decide which files to build.")
parser.add_argument('-core', action="store_true", default=False, help="Build core")
parser.add_argument('-generators', action="store_true", default=False, help="Build the generators")
parser.add_argument('-langfiles', action="store_true", default=False, help="Build all the language files")
# New argument style: ./build.py -core
# Old argument style: ./build.py core
# Changed as of July 2019.
try:
args = parser.parse_args()
if (not args.core) and (not args.generators) and (not args.langfiles):
# No arguments, use these defaults:
args.core = True
args.generators = True
args.langfiles = True
except SystemExit:
# Fall back to old argument style.
args = Arguments()
args.core = 'core' in sys.argv
args.generators = 'generators' in sys.argv
args.langfiles = 'langfiles' in sys.argv
if 'accessible' in sys.argv:
print("The Blockly accessibility demo has moved to https://github.com/google/blockly-experimental")
return args
if __name__ == "__main__":
args = get_args()
calcdeps = import_path(os.path.join("closure", "bin", "calcdeps.py"))
full_search_paths = calcdeps.ExpandDirectories(["core", "closure"])
full_search_paths = sorted(full_search_paths) # Deterministic build.
print("Deprecation Warning: (July 2020)\n This build script has been " +
"deprecated, please use 'npm run build' instead. \n The script will be " +
"removed from Blockly core in Q4 of 2020.\n")
# Uncompressed and compressed are run in parallel threads.
# Uncompressed is limited by processor speed.
if (args.core):
Gen_uncompressed(full_search_paths, 'blockly_uncompressed.js').start()
# Compressed is limited by network and server speed.
Gen_compressed(full_search_paths, args).start()
# This is run locally in a separate thread
if (args.langfiles):
Gen_langfiles().start()
+64 -54
View File
@@ -29,6 +29,8 @@ goog.require('Blockly.Events.BlockDelete');
goog.require('Blockly.Events.BlockMove');
goog.require('Blockly.Extensions');
goog.require('Blockly.fieldRegistry');
goog.require('Blockly.IASTNodeLocation');
goog.require('Blockly.IDeletable');
goog.require('Blockly.Input');
goog.require('Blockly.inputTypes');
goog.require('Blockly.Tooltip');
@@ -41,7 +43,6 @@ goog.require('Blockly.Workspace');
goog.requireType('Blockly.Comment');
goog.requireType('Blockly.Events.Abstract');
goog.requireType('Blockly.Field');
goog.requireType('Blockly.IASTNodeLocation');
goog.requireType('Blockly.Mutator');
goog.requireType('Blockly.utils.Size');
goog.requireType('Blockly.VariableModel');
@@ -57,6 +58,7 @@ goog.requireType('Blockly.VariableModel');
* create a new ID.
* @constructor
* @implements {Blockly.IASTNodeLocation}
* @implements {Blockly.IDeletable}
* @throws When the prototypeName is not valid or not allowed.
*/
Blockly.Block = function(workspace, prototypeName, opt_id) {
@@ -77,7 +79,7 @@ Blockly.Block = function(workspace, prototypeName, opt_id) {
this.nextConnection = null;
/** @type {Blockly.Connection} */
this.previousConnection = null;
/** @type {!Array.<!Blockly.Input>} */
/** @type {!Array<!Blockly.Input>} */
this.inputList = [];
/** @type {boolean|undefined} */
this.inputsInline = undefined;
@@ -98,7 +100,7 @@ Blockly.Block = function(workspace, prototypeName, opt_id) {
this.parentBlock_ = null;
/**
* @type {!Array.<!Blockly.Block>}
* @type {!Array<!Blockly.Block>}
* @protected
*/
this.childBlocks_ = [];
@@ -263,13 +265,13 @@ Blockly.Block = function(workspace, prototypeName, opt_id) {
Blockly.Block.CommentModel;
/**
* The language-neutral id given to the collapsed input.
* The language-neutral ID given to the collapsed input.
* @const {string}
*/
Blockly.Block.COLLAPSED_INPUT_NAME = Blockly.constants.COLLAPSED_INPUT_NAME;
/**
* The language-neutral id given to the collapsed field.
* The language-neutral ID given to the collapsed field.
* @const {string}
*/
Blockly.Block.COLLAPSED_FIELD_NAME = Blockly.constants.COLLAPSED_FIELD_NAME;
@@ -305,10 +307,10 @@ Blockly.Block.prototype.colour_ = '#000000';
/**
* Name of the block style.
* @type {?string}
* @type {string}
* @protected
*/
Blockly.Block.prototype.styleName_ = null;
Blockly.Block.prototype.styleName_ = '';
/**
* An optional method called during initialization.
@@ -349,7 +351,7 @@ Blockly.Block.prototype.suppressPrefixSuffix;
* An optional property for declaring developer variables. Return a list of
* variable names for use by generators. Developer variables are never shown to
* the user, but are declared as global variables in the generated code.
* @type {?function():!Array.<string>}
* @type {?function():!Array<string>}
*/
Blockly.Block.prototype.getDeveloperVariables;
@@ -498,7 +500,7 @@ Blockly.Block.prototype.unplugFromRow_ = function(opt_healStack) {
* Since only one block can be displaced and attached to the insertion marker
* this should only ever return one connection.
*
* @return {Blockly.Connection} The connection on the value input, or null.
* @return {?Blockly.Connection} The connection on the value input, or null.
* @private
*/
Blockly.Block.prototype.getOnlyValueConnection_ = function() {
@@ -509,7 +511,7 @@ Blockly.Block.prototype.getOnlyValueConnection_ = function() {
thisConnection.type == Blockly.connectionTypes.INPUT_VALUE &&
thisConnection.targetConnection) {
if (connection) {
return null; // More than one value input found.
return null; // More than one value input found.
}
connection = thisConnection;
}
@@ -549,7 +551,7 @@ Blockly.Block.prototype.unplugFromStack_ = function(opt_healStack) {
/**
* Returns all connections originating from this block.
* @param {boolean} _all If true, return all connections even hidden ones.
* @return {!Array.<!Blockly.Connection>} Array of connections.
* @return {!Array<!Blockly.Connection>} Array of connections.
* @package
*/
Blockly.Block.prototype.getConnections_ = function(_all) {
@@ -573,20 +575,21 @@ Blockly.Block.prototype.getConnections_ = function(_all) {
/**
* Walks down a stack of blocks and finds the last next connection on the stack.
* @return {Blockly.Connection} The last next connection on the stack, or null.
* @param {boolean} ignoreShadows If true,the last connection on a non-shadow
* block will be returned. If false, this will follow shadows to find the
* last connection.
* @return {?Blockly.Connection} The last next connection on the stack, or null.
* @package
*/
Blockly.Block.prototype.lastConnectionInStack = function() {
Blockly.Block.prototype.lastConnectionInStack = function(ignoreShadows) {
var nextConnection = this.nextConnection;
while (nextConnection) {
var nextBlock = nextConnection.targetBlock();
if (!nextBlock) {
// Found a next connection with nothing on the other side.
if (!nextBlock || (ignoreShadows && nextBlock.isShadow())) {
return nextConnection;
}
nextConnection = nextBlock.nextConnection;
}
// Ran out of next connections.
return null;
};
@@ -602,17 +605,17 @@ Blockly.Block.prototype.bumpNeighbours = function() {
* Return the parent block or null if this block is at the top level. The parent
* block is either the block connected to the previous connection (for a statement
* block) or the block connected to the output connection (for a value block).
* @return {Blockly.Block} The block that holds the current block.
* @return {?Blockly.Block} The block (if any) that holds the current block.
*/
Blockly.Block.prototype.getParent = function() {
// Look at the DOM to see if we are nested in another block.
return this.parentBlock_;
};
/**
* Return the input that connects to the specified block.
* @param {!Blockly.Block} block A block connected to an input on this block.
* @return {Blockly.Input} The input that connects to the specified block.
* @return {?Blockly.Input} The input (if any) that connects to the specified
* block.
*/
Blockly.Block.prototype.getInputWithBlock = function(block) {
for (var i = 0, input; (input = this.inputList[i]); i++) {
@@ -627,7 +630,7 @@ Blockly.Block.prototype.getInputWithBlock = function(block) {
* Return the parent block that surrounds the current block, or null if this
* block has no surrounding block. A parent block might just be the previous
* statement, whereas the surrounding block is an if statement, while loop, etc.
* @return {Blockly.Block} The block that surrounds the current block.
* @return {?Blockly.Block} The block (if any) that surrounds the current block.
*/
Blockly.Block.prototype.getSurroundParent = function() {
var block = this;
@@ -645,7 +648,7 @@ Blockly.Block.prototype.getSurroundParent = function() {
/**
* Return the next statement block directly connected to this block.
* @return {Blockly.Block} The next statement block or null.
* @return {?Blockly.Block} The next statement block or null.
*/
Blockly.Block.prototype.getNextBlock = function() {
return this.nextConnection && this.nextConnection.targetBlock();
@@ -653,7 +656,7 @@ Blockly.Block.prototype.getNextBlock = function() {
/**
* Returns the block connected to the previous connection.
* @return {Blockly.Block} The previous statement block or null.
* @return {?Blockly.Block} The previous statement block or null.
*/
Blockly.Block.prototype.getPreviousBlock = function() {
return this.previousConnection && this.previousConnection.targetBlock();
@@ -662,7 +665,7 @@ Blockly.Block.prototype.getPreviousBlock = function() {
/**
* Return the connection on the first statement input on this block, or null if
* there are none.
* @return {Blockly.Connection} The first statement connection or null.
* @return {?Blockly.Connection} The first statement connection or null.
* @package
*/
Blockly.Block.prototype.getFirstStatementConnection = function() {
@@ -711,7 +714,7 @@ Blockly.Block.prototype.getTopStackBlock = function() {
* Excludes any connection on an output tab or any preceding statement.
* Blocks are optionally sorted by position; top to bottom.
* @param {boolean} ordered Sort the list if true.
* @return {!Array.<!Blockly.Block>} Array of blocks.
* @return {!Array<!Blockly.Block>} Array of blocks.
*/
Blockly.Block.prototype.getChildren = function(ordered) {
if (!ordered) {
@@ -776,7 +779,7 @@ Blockly.Block.prototype.setParent = function(newParent) {
* Excludes any connection on an output tab or any preceding statements.
* Blocks are optionally sorted by position; top to bottom.
* @param {boolean} ordered Sort the list if true.
* @return {!Array.<!Blockly.Block>} Flattened array of blocks.
* @return {!Array<!Blockly.Block>} Flattened array of blocks.
*/
Blockly.Block.prototype.getDescendants = function(ordered) {
var blocks = [this];
@@ -905,7 +908,7 @@ Blockly.Block.prototype.isDisposed = function() {
* Used to match connections between a block and its insertion marker.
* @param {!Blockly.Block} otherBlock The other block to match against.
* @param {!Blockly.Connection} conn The other connection to match.
* @return {Blockly.Connection} The matching connection on this block, or null.
* @return {?Blockly.Connection} The matching connection on this block, or null.
* @package
*/
Blockly.Block.prototype.getMatchingConnection = function(otherBlock, conn) {
@@ -943,7 +946,7 @@ Blockly.Block.prototype.setTooltip = function(newTip) {
/**
* Returns the tooltip text for this block.
* @returns {!string} The tooltip text for this block.
* @return {!string} The tooltip text for this block.
*/
Blockly.Block.prototype.getTooltip = function() {
return Blockly.Tooltip.getTooltipOfObject(this);
@@ -959,7 +962,7 @@ Blockly.Block.prototype.getColour = function() {
/**
* Get the name of the block style.
* @return {?string} Name of the block style.
* @return {string} Name of the block style.
*/
Blockly.Block.prototype.getStyleName = function() {
return this.styleName_;
@@ -986,7 +989,7 @@ Blockly.Block.prototype.setColour = function(colour) {
/**
* Set the style and colour values of a block.
* @param {string} blockStyleName Name of the block style
* @param {string} blockStyleName Name of the block style.
*/
Blockly.Block.prototype.setStyle = function(blockStyleName) {
this.styleName_ = blockStyleName;
@@ -1018,12 +1021,18 @@ Blockly.Block.prototype.setOnChange = function(onchangeFn) {
/**
* Returns the named field from a block.
* @param {string} name The name of the field.
* @return {Blockly.Field} Named field, or null if field does not exist.
* @return {?Blockly.Field} Named field, or null if field does not exist.
*/
Blockly.Block.prototype.getField = function(name) {
if (typeof name !== 'string') {
throw TypeError('Blockly.Block.prototype.getField expects a string ' +
'with the field name but received ' +
(name === undefined ? 'nothing' : name + ' of type ' + typeof name) +
' instead');
}
for (var i = 0, input; (input = this.inputList[i]); i++) {
for (var j = 0, field; (field = input.fieldRow[j]); j++) {
if (field.name == name) {
if (field.name === name) {
return field;
}
}
@@ -1033,7 +1042,7 @@ Blockly.Block.prototype.getField = function(name) {
/**
* Return all variables referenced by this block.
* @return {!Array.<string>} List of variable names.
* @return {!Array<string>} List of variable names.
*/
Blockly.Block.prototype.getVars = function() {
var vars = [];
@@ -1049,7 +1058,7 @@ Blockly.Block.prototype.getVars = function() {
/**
* Return all variables referenced by this block.
* @return {!Array.<!Blockly.VariableModel>} List of variable models.
* @return {!Array<!Blockly.VariableModel>} List of variable models.
* @package
*/
Blockly.Block.prototype.getVarModels = function() {
@@ -1121,7 +1130,7 @@ Blockly.Block.prototype.getFieldValue = function(name) {
/**
* Sets the value of the given field for this block.
* @param {*} newValue The value to set.
* @param {!string} name The name of the field to set the value of.
* @param {string} name The name of the field to set the value of.
*/
Blockly.Block.prototype.setFieldValue = function(newValue, name) {
var field = this.getField(name);
@@ -1134,7 +1143,7 @@ Blockly.Block.prototype.setFieldValue = function(newValue, name) {
/**
* Set whether this block can chain onto the bottom of another block.
* @param {boolean} newBoolean True if there can be a previous statement.
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* @param {(string|Array<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) {
@@ -1166,7 +1175,7 @@ Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) {
/**
* Set whether another block can chain onto the bottom of this block.
* @param {boolean} newBoolean True if there can be a next statement.
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* @param {(string|Array<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) {
@@ -1194,7 +1203,7 @@ Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) {
/**
* Set whether this block returns a value.
* @param {boolean} newBoolean True if there is an output.
* @param {(string|Array.<string>|null)=} opt_check Returned type or list
* @param {(string|Array<string>|null)=} opt_check Returned type or list
* of returned types. Null or undefined if any type could be returned
* (e.g. variable get).
*/
@@ -1423,16 +1432,19 @@ Blockly.Block.prototype.toString = function(opt_maxLength, opt_emptyToken) {
// Run through our text array and simplify expression to remove parentheses
// around single field blocks.
for (var i = 2, l = text.length; i < l; i++) {
// E.g. ['repeat', '(', '10', ')', 'times', 'do', '?']
for (var i = 2; i < text.length; i++) {
if (text[i - 2] == '(' && text[i] == ')') {
text[i - 2] = text[i - 1];
text.splice(i - 1, 2);
l -= 2;
}
}
// Join the text array, removing spaces around added paranthesis.
text = text.join(' ').replace(/(\() | (\))/gmi, '$1$2').trim() || '???';
// Join the text array, removing spaces around added parentheses.
text = text.reduce(function(acc, value) {
return acc + ((acc.substr(-1) == '(' || value == ')') ? '' : ' ') + value;
}, '');
text = text.trim() || '???';
if (opt_maxLength) {
// TODO: Improve truncation so that text from this block is given priority.
// E.g. "1+2+3+4+5+6+7+8+9=0" should be "...6+7+8+9=0", not "1+2+3+4+5...".
@@ -1550,16 +1562,15 @@ Blockly.Block.prototype.jsonInit = function(json) {
json['extensions'] = [json['extensions']]; // Correct and continue.
}
// Add the mutator to the block
// Add the mutator to the block.
if (json['mutator'] !== undefined) {
Blockly.Extensions.apply(json['mutator'], this, true);
}
if (Array.isArray(json['extensions'])) {
var extensionNames = json['extensions'];
var extensionNames = json['extensions'];
if (Array.isArray(extensionNames)) {
for (var j = 0; j < extensionNames.length; ++j) {
var extensionName = extensionNames[j];
Blockly.Extensions.apply(extensionName, this, false);
Blockly.Extensions.apply(extensionNames[j], this, false);
}
}
};
@@ -1700,7 +1711,7 @@ Blockly.Block.prototype.validateTokens_ = function(tokens, argsCount) {
};
/**
* Inserts args in place of numerical tokens. String args are converted to json
* Inserts args in place of numerical tokens. String args are converted to JSON
* that defines a label field. If necessary an extra dummy input is added to
* the end of the elements.
* @param {!Array<!string|number>} tokens The tokens to interpolate
@@ -1742,9 +1753,9 @@ Blockly.Block.prototype.interpolateArguments_ =
};
/**
* Creates a field from the json definition of a field. If a field with the
* Creates a field from the JSON definition of a field. If a field with the
* given type cannot be found, this attempts to create a different field using
* the 'alt' property of the json definition (if it exists).
* the 'alt' property of the JSON definition (if it exists).
* @param {{alt:(string|undefined)}} element The element to try to turn into a
* field.
* @return {?Blockly.Field} The field defined by the JSON, or null if one
@@ -1764,7 +1775,7 @@ Blockly.Block.prototype.fieldFromJson_ = function(element) {
};
/**
* Creates an input from the json definition of an input. Sets the input's check
* Creates an input from the JSON definition of an input. Sets the input's check
* and alignment if they are provided.
* @param {!Object} element The JSON to turn into an input.
* @param {string} warningPrefix The prefix to add to warnings to help the
@@ -1949,15 +1960,14 @@ Blockly.Block.prototype.removeInput = function(name, opt_quiet) {
}
if (opt_quiet) {
return false;
} else {
throw Error('Input not found: ' + name);
}
throw Error('Input not found: ' + name);
};
/**
* Fetches the named input object.
* @param {string} name The name of the input.
* @return {Blockly.Input} The input object, or null if input does not exist.
* @return {?Blockly.Input} The input object, or null if input does not exist.
*/
Blockly.Block.prototype.getInput = function(name) {
for (var i = 0, input; (input = this.inputList[i]); i++) {
@@ -1972,7 +1982,7 @@ Blockly.Block.prototype.getInput = function(name) {
/**
* Fetches the block attached to the named input.
* @param {string} name The name of the input.
* @return {Blockly.Block} The attached value block, or null if the input is
* @return {?Blockly.Block} The attached value block, or null if the input is
* either disconnected or if the input does not exist.
*/
Blockly.Block.prototype.getInputTargetBlock = function(name) {
+65 -18
View File
@@ -39,7 +39,7 @@ Blockly.BlockDragSurfaceSvg = function(container) {
/**
* The SVG drag surface. Set once by Blockly.BlockDragSurfaceSvg.createDom.
* @type {SVGElement}
* @type {?SVGElement}
* @private
*/
Blockly.BlockDragSurfaceSvg.prototype.SVG_ = null;
@@ -47,14 +47,14 @@ Blockly.BlockDragSurfaceSvg.prototype.SVG_ = null;
/**
* This is where blocks live while they are being dragged if the drag surface
* is enabled.
* @type {SVGElement}
* @type {?SVGElement}
* @private
*/
Blockly.BlockDragSurfaceSvg.prototype.dragGroup_ = null;
/**
* Containing HTML element; parent of the workspace and the drag surface.
* @type {Element}
* @type {?Element}
* @private
*/
Blockly.BlockDragSurfaceSvg.prototype.container_ = null;
@@ -71,11 +71,21 @@ Blockly.BlockDragSurfaceSvg.prototype.scale_ = 1;
* Cached value for the translation of the drag surface.
* This translation is in pixel units, because the scale is applied to the
* drag group rather than the top-level SVG.
* @type {Blockly.utils.Coordinate}
* @type {?Blockly.utils.Coordinate}
* @private
*/
Blockly.BlockDragSurfaceSvg.prototype.surfaceXY_ = null;
/**
* Cached value for the translation of the child drag surface in pixel units.
* Since the child drag surface tracks the translation of the workspace this is
* ultimately the translation of the workspace.
* @type {!Blockly.utils.Coordinate}
* @private
*/
Blockly.BlockDragSurfaceSvg.prototype.childSurfaceXY_ =
new Blockly.utils.Coordinate(0, 0);
/**
* Create the drag surface and inject it into the container.
*/
@@ -90,9 +100,10 @@ Blockly.BlockDragSurfaceSvg.prototype.createDom = function() {
'xmlns:xlink': Blockly.utils.dom.XLINK_NS,
'version': '1.1',
'class': 'blocklyBlockDragSurface'
}, this.container_);
this.dragGroup_ = Blockly.utils.dom.createSvgElement(
Blockly.utils.Svg.G, {}, this.SVG_);
},
this.container_);
this.dragGroup_ =
Blockly.utils.dom.createSvgElement(Blockly.utils.Svg.G, {}, this.SVG_);
};
/**
@@ -114,18 +125,23 @@ Blockly.BlockDragSurfaceSvg.prototype.setBlocksAndShow = function(blocks) {
/**
* Translate and scale the entire drag surface group to the given position, to
* keep in sync with the workspace.
* @param {number} x X translation in workspace coordinates.
* @param {number} y Y translation in workspace coordinates.
* @param {number} x X translation in pixel coordinates.
* @param {number} y Y translation in pixel coordinates.
* @param {number} scale Scale of the group.
*/
Blockly.BlockDragSurfaceSvg.prototype.translateAndScaleGroup = function(x, y,
scale) {
Blockly.BlockDragSurfaceSvg.prototype.translateAndScaleGroup = function(
x, y, scale) {
this.scale_ = scale;
// This is a work-around to prevent a the blocks from rendering
// fuzzy while they are being dragged on the drag surface.
var fixedX = x.toFixed(0);
var fixedY = y.toFixed(0);
this.dragGroup_.setAttribute('transform',
this.childSurfaceXY_.x = parseInt(fixedX, 10);
this.childSurfaceXY_.y = parseInt(fixedY, 10);
this.dragGroup_.setAttribute(
'transform',
'translate(' + fixedX + ',' + fixedY + ') scale(' + scale + ')');
};
@@ -142,8 +158,20 @@ Blockly.BlockDragSurfaceSvg.prototype.translateSurfaceInternal_ = function() {
y = y.toFixed(0);
this.SVG_.style.display = 'block';
Blockly.utils.dom.setCssTransform(this.SVG_,
'translate3d(' + x + 'px, ' + y + 'px, 0px)');
Blockly.utils.dom.setCssTransform(
this.SVG_, 'translate3d(' + x + 'px, ' + y + 'px, 0px)');
};
/**
* Translates the entire surface by a relative offset.
* @param {number} deltaX Horizontal offset in pixel units.
* @param {number} deltaY Vertical offset in pixel units.
*/
Blockly.BlockDragSurfaceSvg.prototype.translateBy = function(deltaX, deltaY) {
var x = this.surfaceXY_.x + deltaX;
var y = this.surfaceXY_.y + deltaY;
this.surfaceXY_ = new Blockly.utils.Coordinate(x, y);
this.translateSurfaceInternal_();
};
/**
@@ -155,7 +183,8 @@ Blockly.BlockDragSurfaceSvg.prototype.translateSurfaceInternal_ = function() {
* @param {number} y Y translation for the entire surface.
*/
Blockly.BlockDragSurfaceSvg.prototype.translateSurface = function(x, y) {
this.surfaceXY_ = new Blockly.utils.Coordinate(x * this.scale_, y * this.scale_);
this.surfaceXY_ =
new Blockly.utils.Coordinate(x * this.scale_, y * this.scale_);
this.translateSurfaceInternal_();
};
@@ -172,22 +201,40 @@ Blockly.BlockDragSurfaceSvg.prototype.getSurfaceTranslation = function() {
/**
* Provide a reference to the drag group (primarily for
* BlockSvg.getRelativeToSurfaceXY).
* @return {SVGElement} Drag surface group element.
* @return {?SVGElement} Drag surface group element.
*/
Blockly.BlockDragSurfaceSvg.prototype.getGroup = function() {
return this.dragGroup_;
};
/**
* Returns the SVG drag surface.
* @returns {?SVGElement} The SVG drag surface.
*/
Blockly.BlockDragSurfaceSvg.prototype.getSvgRoot = function() {
return this.SVG_;
};
/**
* Get the current blocks on the drag surface, if any (primarily
* for BlockSvg.getRelativeToSurfaceXY).
* @return {Element} Drag surface block DOM element, or undefined if no blocks
* exist.
* @return {?Element} Drag surface block DOM element, or null if no blocks exist.
*/
Blockly.BlockDragSurfaceSvg.prototype.getCurrentBlock = function() {
return /** @type {Element} */ (this.dragGroup_.firstChild);
};
/**
* Gets the translation of the child block surface
* This surface is in charge of keeping track of how much the workspace has
* moved.
* @return {!Blockly.utils.Coordinate} The amount the workspace has been moved.
*/
Blockly.BlockDragSurfaceSvg.prototype.getWsTranslation = function() {
// Returning a copy so the coordinate can not be changed outside this class.
return this.childSurfaceXY_.clone();
};
/**
* Clear the group and hide the surface; move the blocks off onto the provided
* element.
+196 -110
View File
@@ -20,11 +20,14 @@ goog.require('Blockly.Events');
goog.require('Blockly.Events.BlockDrag');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BlockMove');
goog.require('Blockly.IBlockDragger');
goog.require('Blockly.InsertionMarkerManager');
goog.require('Blockly.registry');
goog.require('Blockly.utils.Coordinate');
goog.require('Blockly.utils.dom');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.IDragTarget');
goog.requireType('Blockly.WorkspaceSvg');
@@ -34,43 +37,42 @@ goog.requireType('Blockly.WorkspaceSvg');
* @param {!Blockly.BlockSvg} block The block to drag.
* @param {!Blockly.WorkspaceSvg} workspace The workspace to drag on.
* @constructor
* @implements {Blockly.IBlockDragger}
*/
Blockly.BlockDragger = function(block, workspace) {
/**
* The top block in the stack that is being dragged.
* @type {!Blockly.BlockSvg}
* @private
* @protected
*/
this.draggingBlock_ = block;
/**
* The workspace on which the block is being dragged.
* @type {!Blockly.WorkspaceSvg}
* @private
* @protected
*/
this.workspace_ = workspace;
/**
* Object that keeps track of connections on dragged blocks.
* @type {!Blockly.InsertionMarkerManager}
* @private
* @protected
*/
this.draggedConnectionManager_ = new Blockly.InsertionMarkerManager(
this.draggingBlock_);
this.draggedConnectionManager_ =
new Blockly.InsertionMarkerManager(this.draggingBlock_);
/**
* Which delete area the mouse pointer is over, if any.
* One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @type {?number}
* Which drag area the mouse pointer is over, if any.
* @type {?Blockly.IDragTarget}
* @private
*/
this.deleteArea_ = null;
this.dragTarget_ = null;
/**
* Whether the block would be deleted if dropped immediately.
* @type {boolean}
* @private
* @protected
*/
this.wouldDeleteBlock_ = false;
@@ -78,7 +80,7 @@ Blockly.BlockDragger = function(block, workspace) {
* The location of the top left corner of the dragging block at the beginning
* of the drag in workspace coordinates.
* @type {!Blockly.utils.Coordinate}
* @private
* @protected
*/
this.startXY_ = this.draggingBlock_.getRelativeToSurfaceXY();
@@ -86,8 +88,8 @@ Blockly.BlockDragger = function(block, workspace) {
* A list of all of the icons (comment, warning, and mutator) that are
* on this block and its descendants. Moving an icon moves the bubble that
* extends from it if that bubble is open.
* @type {Array.<!Object>}
* @private
* @type {Array<!Object>}
* @protected
*/
this.dragIconData_ = Blockly.BlockDragger.initIconData_(block);
};
@@ -109,7 +111,7 @@ Blockly.BlockDragger.prototype.dispose = function() {
* on this block and its descendants. Moving an icon moves the bubble that
* extends from it if that bubble is open.
* @param {!Blockly.BlockSvg} block The root block that is being dragged.
* @return {!Array.<!Object>} The list of all icons and their locations.
* @return {!Array<!Object>} The list of all icons and their locations.
* @private
*/
Blockly.BlockDragger.initIconData_ = function(block) {
@@ -120,7 +122,8 @@ Blockly.BlockDragger.initIconData_ = function(block) {
var icons = descendant.getIcons();
for (var j = 0; j < icons.length; j++) {
var data = {
// Blockly.utils.Coordinate with x and y properties (workspace coordinates).
// Blockly.utils.Coordinate with x and y properties (workspace
// coordinates).
location: icons[j].getIconLocation(),
// Blockly.Icon
icon: icons[j]
@@ -137,10 +140,10 @@ Blockly.BlockDragger.initIconData_ = function(block) {
* moved from the position at mouse down, in pixel units.
* @param {boolean} healStack Whether or not to heal the stack after
* disconnecting.
* @package
* @public
*/
Blockly.BlockDragger.prototype.startBlockDrag = function(currentDragDeltaXY,
healStack) {
Blockly.BlockDragger.prototype.startDrag = function(
currentDragDeltaXY, healStack) {
if (!Blockly.Events.getGroup()) {
Blockly.Events.setGroup(true);
}
@@ -160,34 +163,52 @@ Blockly.BlockDragger.prototype.startBlockDrag = function(currentDragDeltaXY,
this.workspace_.setResizesEnabled(false);
Blockly.blockAnimations.disconnectUiStop();
if (this.draggingBlock_.getParent() ||
(healStack && this.draggingBlock_.nextConnection &&
this.draggingBlock_.nextConnection.targetBlock())) {
this.draggingBlock_.unplug(healStack);
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
this.draggingBlock_.translate(newLoc.x, newLoc.y);
Blockly.blockAnimations.disconnectUiEffect(this.draggingBlock_);
this.draggedConnectionManager_.updateAvailableConnections();
if (this.shouldDisconnect_(healStack)) {
this.disconnectBlock_(healStack, currentDragDeltaXY);
}
this.draggingBlock_.setDragging(true);
// For future consideration: we may be able to put moveToDragSurface inside
// the block dragger, which would also let the block not track the block drag
// surface.
this.draggingBlock_.moveToDragSurface();
};
var toolbox = this.workspace_.getToolbox();
if (toolbox && typeof toolbox.addStyle == 'function') {
var style = this.draggingBlock_.isDeletable() ? 'blocklyToolboxDelete' :
'blocklyToolboxGrab';
toolbox.addStyle(style);
}
/**
* Whether or not we should disconnect the block when a drag is started.
* @param {boolean} healStack Whether or not to heal the stack after
* disconnecting.
* @return {boolean} True to disconnect the block, false otherwise.
* @protected
*/
Blockly.BlockDragger.prototype.shouldDisconnect_ = function(healStack) {
return !!(
this.draggingBlock_.getParent() ||
(healStack && this.draggingBlock_.nextConnection &&
this.draggingBlock_.nextConnection.targetBlock()));
};
/**
* Disconnects the block and moves it to a new location.
* @param {boolean} healStack Whether or not to heal the stack after
* disconnecting.
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at mouse down, in pixel units.
* @protected
*/
Blockly.BlockDragger.prototype.disconnectBlock_ = function(
healStack, currentDragDeltaXY) {
this.draggingBlock_.unplug(healStack);
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
this.draggingBlock_.translate(newLoc.x, newLoc.y);
Blockly.blockAnimations.disconnectUiEffect(this.draggingBlock_);
this.draggedConnectionManager_.updateAvailableConnections();
};
/**
* Fire a UI event at the start of a block drag.
* @private
* @protected
*/
Blockly.BlockDragger.prototype.fireDragStartEvent_ = function() {
var event = new (Blockly.Events.get(Blockly.Events.BLOCK_DRAG))(
@@ -201,19 +222,32 @@ Blockly.BlockDragger.prototype.fireDragStartEvent_ = function() {
* @param {!Event} e The most recent move event.
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at the start of the drag, in pixel units.
* @package
* @public
*/
Blockly.BlockDragger.prototype.dragBlock = function(e, currentDragDeltaXY) {
Blockly.BlockDragger.prototype.drag = function(e, currentDragDeltaXY) {
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
this.draggingBlock_.moveDuringDrag(newLoc);
this.dragIcons_(delta);
this.deleteArea_ = this.workspace_.isDeleteArea(e);
this.draggedConnectionManager_.update(delta, this.deleteArea_);
var oldDragTarget = this.dragTarget_;
this.dragTarget_ = this.workspace_.getDragTarget(e);
this.updateCursorDuringBlockDrag_();
this.draggedConnectionManager_.update(delta, this.dragTarget_);
var oldWouldDeleteBlock = this.wouldDeleteBlock_;
this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock();
if (oldWouldDeleteBlock != this.wouldDeleteBlock_) {
// Prevent unnecessary add/remove class calls.
this.updateCursorDuringBlockDrag_();
}
// Call drag enter/exit/over after wouldDeleteBlock is called in
// InsertionMarkerManager.update.
if (this.dragTarget_ !== oldDragTarget) {
oldDragTarget && oldDragTarget.onDragExit(this.draggingBlock_);
this.dragTarget_ && this.dragTarget_.onDragEnter(this.draggingBlock_);
}
this.dragTarget_ && this.dragTarget_.onDragOver(this.draggingBlock_);
};
/**
@@ -221,11 +255,11 @@ Blockly.BlockDragger.prototype.dragBlock = function(e, currentDragDeltaXY) {
* @param {!Event} e The mouseup/touchend event.
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at the start of the drag, in pixel units.
* @package
* @public
*/
Blockly.BlockDragger.prototype.endBlockDrag = function(e, currentDragDeltaXY) {
Blockly.BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) {
// Make sure internal state is fresh.
this.dragBlock(e, currentDragDeltaXY);
this.drag(e, currentDragDeltaXY);
this.dragIconData_ = [];
this.fireDragEndEvent_();
@@ -233,38 +267,99 @@ Blockly.BlockDragger.prototype.endBlockDrag = function(e, currentDragDeltaXY) {
Blockly.blockAnimations.disconnectUiStop();
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
var preventMove = !!this.dragTarget_ &&
this.dragTarget_.shouldPreventMove(this.draggingBlock_);
if (preventMove) {
var newLoc = this.startXY_;
} else {
var newValues = this.getNewLocationAfterDrag_(currentDragDeltaXY);
var delta = newValues.delta;
var newLoc = newValues.newLocation;
}
this.draggingBlock_.moveOffDragSurface(newLoc);
if (this.dragTarget_) {
this.dragTarget_.onDrop(this.draggingBlock_);
}
var deleted = this.maybeDeleteBlock_();
if (!deleted) {
// These are expensive and don't need to be done if we're deleting.
this.draggingBlock_.moveConnections(delta.x, delta.y);
this.draggingBlock_.setDragging(false);
this.fireMoveEvent_();
if (this.draggedConnectionManager_.wouldConnectBlock()) {
// Applying connections also rerenders the relevant blocks.
this.draggedConnectionManager_.applyConnections();
if (delta) { // !preventMove
this.updateBlockAfterMove_(delta);
} else {
this.draggingBlock_.render();
// Blocks dragged directly from a flyout may need to be bumped into
// bounds.
Blockly.bumpObjectIntoBounds_(
this.draggingBlock_.workspace,
this.workspace_.getMetricsManager().getScrollMetrics(true),
this.draggingBlock_);
}
this.draggingBlock_.scheduleSnapAndBump();
}
this.workspace_.setResizesEnabled(true);
var toolbox = this.workspace_.getToolbox();
if (toolbox && typeof toolbox.removeStyle == 'function') {
var style = this.draggingBlock_.isDeletable() ? 'blocklyToolboxDelete' :
'blocklyToolboxGrab';
toolbox.removeStyle(style);
}
Blockly.Events.setGroup(false);
};
/**
* Calculates the drag delta and new location values after a block is dragged.
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the start of the drag, in pixel units.
* @return {{delta: !Blockly.utils.Coordinate, newLocation:
* !Blockly.utils.Coordinate}} New location after drag. delta is in
* workspace units. newLocation is the new coordinate where the block should
* end up.
* @protected
*/
Blockly.BlockDragger.prototype.getNewLocationAfterDrag_ = function(
currentDragDeltaXY) {
var newValues = {};
newValues.delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
newValues.newLocation =
Blockly.utils.Coordinate.sum(this.startXY_, newValues.delta);
return newValues;
};
/**
* May delete the dragging block, if allowed. If `this.wouldDeleteBlock_` is not
* true, the block will not be deleted. This should be called at the end of a
* block drag.
* @return {boolean} True if the block was deleted.
* @protected
*/
Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() {
if (this.wouldDeleteBlock_) {
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBlock_.dispose(false, true);
Blockly.draggingConnections = [];
return true;
}
return false;
};
/**
* Updates the necessary information to place a block at a certain location.
* @param {!Blockly.utils.Coordinate} delta The change in location from where
* the block started the drag to where it ended the drag.
* @protected
*/
Blockly.BlockDragger.prototype.updateBlockAfterMove_ = function(delta) {
this.draggingBlock_.moveConnections(delta.x, delta.y);
this.fireMoveEvent_();
if (this.draggedConnectionManager_.wouldConnectBlock()) {
// Applying connections also rerenders the relevant blocks.
this.draggedConnectionManager_.applyConnections();
} else {
this.draggingBlock_.render();
}
this.draggingBlock_.scheduleSnapAndBump();
};
/**
* Fire a UI event at the end of a block drag.
* @private
* @protected
*/
Blockly.BlockDragger.prototype.fireDragEndEvent_ = function() {
var event = new (Blockly.Events.get(Blockly.Events.BLOCK_DRAG))(
@@ -272,61 +367,48 @@ Blockly.BlockDragger.prototype.fireDragEndEvent_ = function() {
Blockly.Events.fire(event);
};
/**
* Adds or removes the style of the cursor for the toolbox.
* This is what changes the cursor to display an x when a deletable block is
* held over the toolbox.
* @param {boolean} isEnd True if we are at the end of a drag, false otherwise.
* @protected
*/
Blockly.BlockDragger.prototype.updateToolboxStyle_ = function(isEnd) {
var toolbox = this.workspace_.getToolbox();
if (toolbox) {
var style = this.draggingBlock_.isDeletable() ? 'blocklyToolboxDelete' :
'blocklyToolboxGrab';
if (isEnd && typeof toolbox.removeStyle == 'function') {
toolbox.removeStyle(style);
} else if (!isEnd && typeof toolbox.addStyle == 'function') {
toolbox.addStyle(style);
}
}
};
/**
* Fire a move event at the end of a block drag.
* @private
* @protected
*/
Blockly.BlockDragger.prototype.fireMoveEvent_ = function() {
var event = new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(
this.draggingBlock_);
var event =
new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(this.draggingBlock_);
event.oldCoordinate = this.startXY_;
event.recordNew();
Blockly.Events.fire(event);
};
/**
* Shut the trash can and, if necessary, delete the dragging block.
* Should be called at the end of a block drag.
* @return {boolean} Whether the block was deleted.
* @private
*/
Blockly.BlockDragger.prototype.maybeDeleteBlock_ = function() {
var trashcan = this.workspace_.trashcan;
if (this.wouldDeleteBlock_) {
if (trashcan) {
setTimeout(trashcan.closeLid.bind(trashcan), 100);
}
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBlock_.dispose(false, true);
Blockly.draggingConnections = [];
} else if (trashcan) {
// Make sure the trash can lid is closed.
trashcan.closeLid();
}
return this.wouldDeleteBlock_;
};
/**
* Update the cursor (and possibly the trash can lid) to reflect whether the
* dragging block would be deleted if released immediately.
* @private
* @protected
*/
Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() {
this.wouldDeleteBlock_ = this.draggedConnectionManager_.wouldDeleteBlock();
var trashcan = this.workspace_.trashcan;
if (this.wouldDeleteBlock_) {
this.draggingBlock_.setDeleteStyle(true);
if (this.deleteArea_ == Blockly.DELETE_AREA_TRASH && trashcan) {
trashcan.setLidOpen(true);
}
} else {
this.draggingBlock_.setDeleteStyle(false);
if (trashcan) {
trashcan.setLidOpen(false);
}
}
this.draggingBlock_.setDeleteStyle(this.wouldDeleteBlock_);
};
/**
@@ -334,11 +416,11 @@ Blockly.BlockDragger.prototype.updateCursorDuringBlockDrag_ = function() {
* correction for mutator workspaces.
* This function does not consider differing origins. It simply scales the
* input's x and y values.
* @param {!Blockly.utils.Coordinate} pixelCoord A coordinate with x and y values
* in CSS pixel units.
* @return {!Blockly.utils.Coordinate} The input coordinate divided by the workspace
* scale.
* @private
* @param {!Blockly.utils.Coordinate} pixelCoord A coordinate with x and y
* values in CSS pixel units.
* @return {!Blockly.utils.Coordinate} The input coordinate divided by the
* workspace scale.
* @protected
*/
Blockly.BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
var result = new Blockly.utils.Coordinate(
@@ -359,7 +441,7 @@ Blockly.BlockDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) {
* Move all of the icons connected to this drag.
* @param {!Blockly.utils.Coordinate} dxy How far to move the icons from their
* original positions, in workspace units.
* @private
* @protected
*/
Blockly.BlockDragger.prototype.dragIcons_ = function(dxy) {
// Moving icons moves their associated bubbles.
@@ -372,9 +454,9 @@ Blockly.BlockDragger.prototype.dragIcons_ = function(dxy) {
/**
* Get a list of the insertion markers that currently exist. Drags have 0, 1,
* or 2 insertion markers.
* @return {!Array.<!Blockly.BlockSvg>} A possibly empty list of insertion
* @return {!Array<!Blockly.BlockSvg>} A possibly empty list of insertion
* marker blocks.
* @package
* @public
*/
Blockly.BlockDragger.prototype.getInsertionMarkers = function() {
// No insertion markers with the old style of dragged connection managers.
@@ -384,3 +466,7 @@ Blockly.BlockDragger.prototype.getInsertionMarkers = function() {
}
return [];
};
Blockly.registry.register(
Blockly.registry.Type.BLOCK_DRAGGER, Blockly.registry.DEFAULT,
Blockly.BlockDragger);
+39 -31
View File
@@ -27,6 +27,10 @@ goog.require('Blockly.Events');
goog.require('Blockly.Events.BlockMove');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.Selected');
goog.require('Blockly.IASTNodeLocationSvg');
goog.require('Blockly.IBoundedElement');
goog.require('Blockly.ICopyable');
goog.require('Blockly.IDraggable');
goog.require('Blockly.Msg');
goog.require('Blockly.RenderedConnection');
goog.require('Blockly.TabNavigateCursor');
@@ -39,6 +43,7 @@ goog.require('Blockly.utils.deprecation');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.Rect');
goog.require('Blockly.utils.Svg');
goog.require('Blockly.utils.userAgent');
goog.require('Blockly.Xml');
@@ -46,9 +51,6 @@ goog.requireType('Blockly.blockRendering.Debug');
goog.requireType('Blockly.Comment');
goog.requireType('Blockly.Connection');
goog.requireType('Blockly.Field');
goog.requireType('Blockly.IASTNodeLocationSvg');
goog.requireType('Blockly.IBoundedElement');
goog.requireType('Blockly.ICopyable');
goog.requireType('Blockly.Input');
goog.requireType('Blockly.Mutator');
goog.requireType('Blockly.Theme');
@@ -68,6 +70,7 @@ goog.requireType('Blockly.WorkspaceSvg');
* @implements {Blockly.IASTNodeLocationSvg}
* @implements {Blockly.IBoundedElement}
* @implements {Blockly.ICopyable}
* @implements {Blockly.IDraggable}
* @constructor
*/
Blockly.BlockSvg = function(workspace, prototypeName, opt_id) {
@@ -156,7 +159,7 @@ Blockly.BlockSvg.prototype.width = 0;
/**
* Map from IDs for warnings text to PIDs of functions to apply them.
* Used to be able to maintain multiple warnings.
* @type {Object.<string, number>}
* @type {Object<string, number>}
* @private
*/
Blockly.BlockSvg.prototype.warningTextDb_ = null;
@@ -199,7 +202,7 @@ Blockly.BlockSvg.prototype.compose;
/**
* An optional method for defining custom block context menu items.
* @type {?function(!Array.<!Object>)}
* @type {?function(!Array<!Object>)}
*/
Blockly.BlockSvg.prototype.customContextMenu;
@@ -339,33 +342,33 @@ Blockly.BlockSvg.prototype.unselect = function() {
/**
* Block's mutator icon (if any).
* @type {Blockly.Mutator}
* @type {?Blockly.Mutator}
*/
Blockly.BlockSvg.prototype.mutator = null;
/**
* Block's comment icon (if any).
* @type {Blockly.Comment}
* @type {?Blockly.Comment}
* @deprecated August 2019. Use getCommentIcon instead.
*/
Blockly.BlockSvg.prototype.comment = null;
/**
* Block's comment icon (if any).
* @type {Blockly.Comment}
* @type {?Blockly.Comment}
* @private
*/
Blockly.BlockSvg.prototype.commentIcon_ = null;
/**
* Block's warning icon (if any).
* @type {Blockly.Warning}
* @type {?Blockly.Warning}
*/
Blockly.BlockSvg.prototype.warning = null;
/**
* Returns a list of mutator, comment, and warning icons.
* @return {!Array} List of icons.
* @return {!Array<!Blockly.Icon>} List of icons.
*/
Blockly.BlockSvg.prototype.getIcons = function() {
var icons = [];
@@ -383,7 +386,7 @@ Blockly.BlockSvg.prototype.getIcons = function() {
/**
* Set parent of this block to be a new block or null.
* @param {Blockly.Block} newParent New parent block.
* @param {?Blockly.Block} newParent New parent block.
* @override
*/
Blockly.BlockSvg.prototype.setParent = function(newParent) {
@@ -747,7 +750,7 @@ Blockly.BlockSvg.prototype.showHelp = function() {
/**
* Generate the context menu for this block.
* @protected
* @return {Array.<!Object>} Context menu options
* @return {?Array<!Object>} Context menu options or null if no menu.
*/
Blockly.BlockSvg.prototype.generateContextMenu = function() {
if (this.workspace.options.readOnly || !this.contextMenu) {
@@ -1008,7 +1011,7 @@ Blockly.BlockSvg.prototype.updateDisabled = function() {
/**
* Get the comment icon attached to this block, or null if the block has no
* comment.
* @return {Blockly.Comment} The comment icon attached to this block, or null.
* @return {?Blockly.Comment} The comment icon attached to this block, or null.
*/
Blockly.BlockSvg.prototype.getCommentIcon = function() {
return this.commentIcon_;
@@ -1137,7 +1140,7 @@ Blockly.BlockSvg.prototype.setWarningText = function(text, opt_id) {
/**
* Give this block a mutator dialog.
* @param {Blockly.Mutator} mutator A mutator dialog instance or null to remove.
* @param {?Blockly.Mutator} mutator A mutator dialog instance or null to remove.
*/
Blockly.BlockSvg.prototype.setMutator = function(mutator) {
if (this.mutator && this.mutator !== mutator) {
@@ -1233,7 +1236,7 @@ Blockly.BlockSvg.prototype.setColour = function(colour) {
/**
* Set the style and colour values of a block.
* @param {string} blockStyleName Name of the block style
* @param {string} blockStyleName Name of the block style.
* @throws {Error} if the block style does not exist.
*/
Blockly.BlockSvg.prototype.setStyle = function(blockStyleName) {
@@ -1278,7 +1281,7 @@ Blockly.BlockSvg.prototype.bringToFront = function() {
/**
* Set whether this block can chain onto the bottom of another block.
* @param {boolean} newBoolean True if there can be a previous statement.
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* @param {(string|Array<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.BlockSvg.prototype.setPreviousStatement = function(newBoolean,
@@ -1295,7 +1298,7 @@ Blockly.BlockSvg.prototype.setPreviousStatement = function(newBoolean,
/**
* Set whether another block can chain onto the bottom of this block.
* @param {boolean} newBoolean True if there can be a next statement.
* @param {(string|Array.<string>|null)=} opt_check Statement type or
* @param {(string|Array<string>|null)=} opt_check Statement type or
* list of statement types. Null/undefined if any type could be connected.
*/
Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) {
@@ -1311,7 +1314,7 @@ Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) {
/**
* Set whether this block returns a value.
* @param {boolean} newBoolean True if there is an output.
* @param {(string|Array.<string>|null)=} opt_check Returned type or list
* @param {(string|Array<string>|null)=} opt_check Returned type or list
* of returned types. Null or undefined if any type could be returned
* (e.g. variable get).
*/
@@ -1380,7 +1383,8 @@ Blockly.BlockSvg.prototype.moveNumberedInputBefore = function(
* @param {string} name Language-neutral identifier which may used to find this
* input again. Should be unique to this block.
* @return {!Blockly.Input} The input object created.
* @private
* @protected
* @override
*/
Blockly.BlockSvg.prototype.appendInput_ = function(type, name) {
var input = Blockly.BlockSvg.superClass_.appendInput_.call(this, type, name);
@@ -1443,7 +1447,7 @@ Blockly.BlockSvg.prototype.setConnectionTracking = function(track) {
* @param {boolean} all If true, return all connections even hidden ones.
* Otherwise, for a non-rendered block return an empty list, and for a
* collapsed block don't return inputs connections.
* @return {!Array.<!Blockly.RenderedConnection>} Array of connections.
* @return {!Array<!Blockly.RenderedConnection>} Array of connections.
* @package
*/
Blockly.BlockSvg.prototype.getConnections_ = function(all) {
@@ -1471,14 +1475,18 @@ Blockly.BlockSvg.prototype.getConnections_ = function(all) {
/**
* Walks down a stack of blocks and finds the last next connection on the stack.
* @return {Blockly.RenderedConnection} The last next connection on the stack,
* @param {boolean} ignoreShadows If true,the last connection on a non-shadow
* block will be returned. If false, this will follow shadows to find the
* last connection.
* @return {?Blockly.RenderedConnection} The last next connection on the stack,
* or null.
* @package
* @override
*/
Blockly.BlockSvg.prototype.lastConnectionInStack = function() {
Blockly.BlockSvg.prototype.lastConnectionInStack = function(ignoreShadows) {
return /** @type {Blockly.RenderedConnection} */ (
Blockly.BlockSvg.superClass_.lastConnectionInStack.call(this));
Blockly.BlockSvg.superClass_
.lastConnectionInStack.call(this, ignoreShadows));
};
/**
@@ -1487,7 +1495,7 @@ Blockly.BlockSvg.prototype.lastConnectionInStack = function() {
* Used to match connections between a block and its insertion marker.
* @param {!Blockly.Block} otherBlock The other block to match against.
* @param {!Blockly.Connection} conn The other connection to match.
* @return {Blockly.RenderedConnection} The matching connection on this block,
* @return {?Blockly.RenderedConnection} The matching connection on this block,
* or null.
* @package
* @override
@@ -1601,7 +1609,7 @@ Blockly.BlockSvg.prototype.positionNearConnection = function(sourceConnection,
/**
* Return the parent block or null if this block is at the top level.
* @return {Blockly.BlockSvg} The block that holds the current block.
* @return {?Blockly.BlockSvg} The block (if any) that holds the current block.
* @override
*/
Blockly.BlockSvg.prototype.getParent = function() {
@@ -1707,9 +1715,9 @@ Blockly.BlockSvg.prototype.updateConnectionLocations_ = function() {
};
/**
* Add the cursor svg to this block's svg group.
* @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
* block svg group.
* Add the cursor SVG to this block's SVG group.
* @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the
* block SVG group.
* @package
*/
Blockly.BlockSvg.prototype.setCursorSvg = function(cursorSvg) {
@@ -1717,9 +1725,9 @@ Blockly.BlockSvg.prototype.setCursorSvg = function(cursorSvg) {
};
/**
* Add the marker svg to this block's svg group.
* @param {SVGElement} markerSvg The svg root of the marker to be added to the
* block svg group.
* Add the marker SVG to this block's SVG group.
* @param {SVGElement} markerSvg The SVG root of the marker to be added to the
* block SVG group.
* @package
*/
Blockly.BlockSvg.prototype.setMarkerSvg = function(markerSvg) {
+27 -27
View File
@@ -17,9 +17,10 @@
goog.provide('Blockly');
goog.require('Blockly.browserEvents');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.ComponentManager');
goog.require('Blockly.connectionTypes');
goog.require('Blockly.constants');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BlockCreate');
@@ -60,10 +61,11 @@ goog.requireType('Blockly.Workspace');
/**
* Blockly core version.
* This constant is overridden by the build script (build.py) to the value of the version
* in package.json. This is done during the gen_core build step.
* For local builds, you can pass --define='Blockly.VERSION=X.Y.Z' to the compiler
* to override this constant.
* This constant is overridden by the build script (npm run build) to the value
* of the version in package.json. This is done by the Closure Compiler in the
* buildCompressed gulp task.
* For local builds, you can pass --define='Blockly.VERSION=X.Y.Z' to the
* compiler to override this constant.
* @define {string}
*/
Blockly.VERSION = 'uncompiled';
@@ -83,7 +85,7 @@ Blockly.selected = null;
/**
* All of the connections on blocks that are currently being dragged.
* @type {!Array.<!Blockly.Connection>}
* @type {!Array<!Blockly.Connection>}
* @package
*/
Blockly.draggingConnections = [];
@@ -216,7 +218,12 @@ Blockly.deleteBlock = function(selected) {
if (!selected.workspace.isFlyout) {
Blockly.Events.setGroup(true);
Blockly.hideChaff();
selected.dispose(/* heal */ true, true);
if (selected.outputConnection) {
// Do not attempt to heal rows (https://github.com/google/blockly/issues/4832)
selected.dispose(false, true);
} else {
selected.dispose(/* heal */ true, true);
}
Blockly.Events.setGroup(false);
}
};
@@ -294,27 +301,20 @@ Blockly.onContextMenu_ = function(e) {
/**
* Close tooltips, context menus, dropdown selections, etc.
* @param {boolean=} opt_allowToolbox If true, don't close the toolbox.
* @param {boolean=} opt_onlyClosePopups Whether only popups should be closed.
*/
Blockly.hideChaff = function(opt_allowToolbox) {
Blockly.hideChaff = function(opt_onlyClosePopups) {
Blockly.Tooltip.hide();
Blockly.WidgetDiv.hide();
Blockly.DropDownDiv.hideWithoutAnimation();
if (!opt_allowToolbox) {
var workspace = Blockly.getMainWorkspace();
// For now the trashcan flyout always autocloses because it overlays the
// trashcan UI (no trashcan to click to close it).
if (workspace.trashcan &&
workspace.trashcan.flyout) {
workspace.trashcan.closeFlyout();
}
var toolbox = workspace.getToolbox();
if (toolbox &&
toolbox.getFlyout() &&
toolbox.getFlyout().autoClose) {
toolbox.clearSelection();
}
}
var onlyClosePopups = !!opt_onlyClosePopups;
var workspace = Blockly.getMainWorkspace();
var autoHideables = workspace.getComponentManager().getComponents(
Blockly.ComponentManager.Capability.AUTOHIDEABLE, true);
autoHideables.forEach(function(autoHideable) {
autoHideable.autoHide(onlyClosePopups);
});
};
/**
@@ -380,7 +380,7 @@ Blockly.jsonInitFactory_ = function(jsonDef) {
/**
* Define blocks from an array of JSON block definitions, as might be generated
* by the Blockly Developer Tools.
* @param {!Array.<!Object>} jsonArray An array of JSON block definitions.
* @param {!Array<!Object>} jsonArray An array of JSON block definitions.
*/
Blockly.defineBlocksWithJsonArray = function(jsonArray) {
for (var i = 0; i < jsonArray.length; i++) {
@@ -475,7 +475,7 @@ Blockly.checkBlockColourConstants = function() {
* Checks for a constant in the Blockly namespace, verifying it is undefined or
* has the old/original value. Prints a warning if this is not true.
* @param {string} msgName The Msg constant identifier.
* @param {Array.<string>} blocklyNamePath The name parts of the tested
* @param {!Array<string>} blocklyNamePath The name parts of the tested
* constant.
* @param {number|undefined} expectedValue The expected value of the constant.
* @private
+1 -1
View File
@@ -18,6 +18,6 @@ goog.provide('Blockly.Blocks');
/**
* A mapping of block type names to block prototype objects.
* @type {!Object.<string,Object>}
* @type {!Object<string,Object>}
*/
Blockly.Blocks = Object.create(null);
+4 -3
View File
@@ -13,13 +13,14 @@
goog.provide('Blockly.browserEvents');
goog.require('Blockly.Touch');
goog.require('Blockly.utils.global');
/**
* Blockly opaque event data used to unbind events when using
* `Blockly.browserEvents.bind` and
* `Blockly.browserEvents.conditionalBind`.
* @typedef {!Array.<!Array>}
* @typedef {!Array<!Array>}
*/
Blockly.browserEvents.Data;
@@ -30,7 +31,7 @@ Blockly.browserEvents.Data;
* mousedown or mousemove, which may be part of a drag or click).
* @param {!EventTarget} node Node upon which to listen.
* @param {string} name Event name to listen to (e.g. 'mousedown').
* @param {Object} thisObject The value of 'this' in the function.
* @param {?Object} thisObject The value of 'this' in the function.
* @param {!Function} func Function to call when event is triggered.
* @param {boolean=} opt_noCaptureIdentifier True if triggering on this event
* should not block execution of other event handlers on this touch or
@@ -105,7 +106,7 @@ Blockly.browserEvents.conditionalBind = function(
* mouseover for tooltips).
* @param {!EventTarget} node Node upon which to listen.
* @param {string} name Event name to listen to (e.g. 'mousedown').
* @param {Object} thisObject The value of 'this' in the function.
* @param {?Object} thisObject The value of 'this' in the function.
* @param {!Function} func Function to call when event is triggered.
* @return {!Blockly.browserEvents.Data} Opaque data that can be passed to
* unbindEvent_.
+2 -2
View File
@@ -13,6 +13,7 @@
goog.provide('Blockly.Bubble');
goog.require('Blockly.browserEvents');
goog.require('Blockly.IBubble');
goog.require('Blockly.Scrollbar');
goog.require('Blockly.Touch');
goog.require('Blockly.utils');
@@ -27,7 +28,6 @@ goog.require('Blockly.Workspace');
goog.requireType('Blockly.BlockDragSurfaceSvg');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.IBubble');
goog.requireType('Blockly.MetricsManager');
goog.requireType('Blockly.WorkspaceSvg');
@@ -37,7 +37,7 @@ goog.requireType('Blockly.WorkspaceSvg');
* @param {!Blockly.WorkspaceSvg} workspace The workspace on which to draw the
* bubble.
* @param {!Element} content SVG content for the bubble.
* @param {Element} shape SVG element to avoid eclipsing.
* @param {!Element} shape SVG element to avoid eclipsing.
* @param {!Blockly.utils.Coordinate} anchorXY Absolute position of bubble's
* anchor point.
* @param {?number} bubbleWidth Width of bubble, or null if not resizable.
+53 -57
View File
@@ -14,6 +14,7 @@ goog.provide('Blockly.BubbleDragger');
/** @suppress {extraRequire} */
goog.require('Blockly.Bubble');
goog.require('Blockly.ComponentManager');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.Events');
@@ -51,13 +52,11 @@ Blockly.BubbleDragger = function(bubble, workspace) {
this.workspace_ = workspace;
/**
* Which delete area the mouse pointer is over, if any.
* One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @type {?number}
* Which drag target the mouse pointer is over, if any.
* @type {?Blockly.IDragTarget}
* @private
*/
this.deleteArea_ = null;
this.dragTarget_ = null;
/**
* Whether the bubble would be deleted if dropped immediately.
@@ -113,13 +112,6 @@ Blockly.BubbleDragger.prototype.startBubbleDrag = function() {
}
this.draggingBubble_.setDragging && this.draggingBubble_.setDragging(true);
var toolbox = this.workspace_.getToolbox();
if (toolbox && typeof toolbox.addStyle == 'function') {
var style = this.draggingBubble_.isDeletable() ? 'blocklyToolboxDelete' :
'blocklyToolboxGrab';
toolbox.addStyle(style);
}
};
/**
@@ -133,36 +125,45 @@ Blockly.BubbleDragger.prototype.startBubbleDrag = function() {
Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) {
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
this.draggingBubble_.moveDuringDrag(this.dragSurface_, newLoc);
if (this.draggingBubble_.isDeletable()) {
this.deleteArea_ = this.workspace_.isDeleteArea(e);
var oldDragTarget = this.dragTarget_;
this.dragTarget_ = this.workspace_.getDragTarget(e);
var oldWouldDeleteBubble = this.wouldDeleteBubble_;
this.wouldDeleteBubble_ = this.shouldDelete_(this.dragTarget_);
if (oldWouldDeleteBubble != this.wouldDeleteBubble_) {
// Prevent unnecessary add/remove class calls.
this.updateCursorDuringBubbleDrag_();
}
// Call drag enter/exit/over after wouldDeleteBlock is called in shouldDelete_
if (this.dragTarget_ !== oldDragTarget) {
oldDragTarget && oldDragTarget.onDragExit(this.draggingBubble_);
this.dragTarget_ && this.dragTarget_.onDragEnter(this.draggingBubble_);
}
this.dragTarget_ && this.dragTarget_.onDragOver(this.draggingBubble_);
};
/**
* Shut the trash can and, if necessary, delete the dragging bubble.
* Should be called at the end of a bubble drag.
* @return {boolean} Whether the bubble was deleted.
* Whether ending the drag would delete the bubble.
* @param {?Blockly.IDragTarget} dragTarget The drag target that the bubblee is
* currently over.
* @return {boolean} Whether dropping the bubble immediately would delete the
* block.
* @private
*/
Blockly.BubbleDragger.prototype.maybeDeleteBubble_ = function() {
var trashcan = this.workspace_.trashcan;
if (this.wouldDeleteBubble_) {
if (trashcan) {
setTimeout(trashcan.closeLid.bind(trashcan), 100);
Blockly.BubbleDragger.prototype.shouldDelete_ = function(dragTarget) {
if (dragTarget) {
var componentManager = this.workspace_.getComponentManager();
var isDeleteArea = componentManager.hasCapability(dragTarget.id,
Blockly.ComponentManager.Capability.DELETE_AREA);
if (isDeleteArea) {
return (/** @type {!Blockly.IDeleteArea} */ (dragTarget))
.wouldDelete(this.draggingBubble_, false);
}
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBubble_.dispose(false, true);
} else if (trashcan) {
// Make sure the trash can lid is closed.
trashcan.closeLid();
}
return this.wouldDeleteBubble_;
return false;
};
/**
@@ -171,19 +172,7 @@ Blockly.BubbleDragger.prototype.maybeDeleteBubble_ = function() {
* @private
*/
Blockly.BubbleDragger.prototype.updateCursorDuringBubbleDrag_ = function() {
this.wouldDeleteBubble_ = this.deleteArea_ != Blockly.DELETE_AREA_NONE;
var trashcan = this.workspace_.trashcan;
if (this.wouldDeleteBubble_) {
this.draggingBubble_.setDeleteStyle(true);
if (this.deleteArea_ == Blockly.DELETE_AREA_TRASH && trashcan) {
trashcan.setLidOpen(true);
}
} else {
this.draggingBubble_.setDeleteStyle(false);
if (trashcan) {
trashcan.setLidOpen(false);
}
}
this.draggingBubble_.setDeleteStyle(this.wouldDeleteBubble_);
};
/**
@@ -198,30 +187,37 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function(
// Make sure internal state is fresh.
this.dragBubble(e, currentDragDeltaXY);
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
var preventMove = this.dragTarget_ &&
this.dragTarget_.shouldPreventMove(this.draggingBubble_);
if (preventMove) {
var newLoc = this.startXY_;
} else {
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY);
var newLoc = Blockly.utils.Coordinate.sum(this.startXY_, delta);
}
// Move the bubble to its final location.
this.draggingBubble_.moveTo(newLoc.x, newLoc.y);
var deleted = this.maybeDeleteBubble_();
if (!deleted) {
if (this.dragTarget_) {
this.dragTarget_.onDrop(this.draggingBubble_);
}
if (this.wouldDeleteBubble_) {
// Fire a move event, so we know where to go back to for an undo.
this.fireMoveEvent_();
this.draggingBubble_.dispose(false, true);
} else {
// Put everything back onto the bubble canvas.
if (this.dragSurface_) {
this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas());
}
this.draggingBubble_.setDragging && this.draggingBubble_.setDragging(false);
if (this.draggingBubble_.setDragging) {
this.draggingBubble_.setDragging(false);
}
this.fireMoveEvent_();
}
this.workspace_.setResizesEnabled(true);
var toolbox = this.workspace_.getToolbox();
if (toolbox && typeof toolbox.removeStyle == 'function') {
var style = this.draggingBubble_.isDeletable() ? 'blocklyToolboxDelete' :
'blocklyToolboxGrab';
toolbox.removeStyle(style);
}
Blockly.Events.setGroup(false);
};
+244
View File
@@ -0,0 +1,244 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Manager for all items registered with the workspace.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.ComponentManager');
goog.requireType('Blockly.IAutoHideable');
goog.requireType('Blockly.IComponent');
goog.requireType('Blockly.IDeleteArea');
goog.requireType('Blockly.IDragTarget');
goog.requireType('Blockly.IPositionable');
/**
* Manager for all items registered with the workspace.
* @constructor
*/
Blockly.ComponentManager = function() {
/**
* A map of the components registered with the workspace, mapped to id.
* @type {!Object<string, !Blockly.ComponentManager.ComponentDatum>}
* @private
*/
this.componentData_ = Object.create(null);
/**
* A map of capabilities to component IDs.
* @type {!Object<string, !Array<string>>}
* @private
*/
this.capabilityToComponentIds_ = Object.create(null);
};
/**
* An object storing component information.
* @typedef {{
* component: !Blockly.IComponent,
* capabilities: (
* !Array<string|!Blockly.ComponentManager.Capability<!Blockly.IComponent>>
* ),
* weight: number
* }}
*/
Blockly.ComponentManager.ComponentDatum;
/**
* Adds a component.
* @param {!Blockly.ComponentManager.ComponentDatum} componentInfo The data for
* the component to register.
* @param {boolean=} opt_allowOverrides True to prevent an error when overriding
* an already registered item.
*/
Blockly.ComponentManager.prototype.addComponent = function(
componentInfo, opt_allowOverrides) {
// Don't throw an error if opt_allowOverrides is true.
var id = componentInfo.component.id;
if (!opt_allowOverrides && this.componentData_[id]) {
throw Error(
'Plugin "' + id + '" with capabilities "' +
this.componentData_[id].capabilities + '" already added.');
}
this.componentData_[id] = componentInfo;
var stringCapabilities = [];
for (var i = 0; i < componentInfo.capabilities.length; i++) {
var capability = String(componentInfo.capabilities[i]).toLowerCase();
stringCapabilities.push(capability);
if (this.capabilityToComponentIds_[capability] === undefined) {
this.capabilityToComponentIds_[capability] = [id];
} else {
this.capabilityToComponentIds_[capability].push(id);
}
}
this.componentData_[id].capabilities = stringCapabilities;
};
/**
* Removes a component.
* @param {string} id The ID of the component to remove.
*/
Blockly.ComponentManager.prototype.removeComponent = function(id) {
var componentInfo = this.componentData_[id];
if (!componentInfo) {
return;
}
for (var i = 0; i < componentInfo.capabilities.length; i++) {
var capability = String(componentInfo.capabilities[i]).toLowerCase();
this.capabilityToComponentIds_[capability].splice(
this.capabilityToComponentIds_[capability].indexOf(id), 1);
}
delete this.componentData_[id];
};
/**
* Adds a capability to a existing registered component.
* @param {string} id The ID of the component to add the capability to.
* @param {string|!Blockly.ComponentManager.Capability<T>} capability The
* capability to add.
* @template T
*/
Blockly.ComponentManager.prototype.addCapability = function(id, capability) {
if (!this.getComponent(id)) {
throw Error('Cannot add capability, "' + capability + '". Plugin "' +
id + '" has not been added to the ComponentManager');
}
if (this.hasCapability(id, capability)) {
console.warn('Plugin "' + id + 'already has capability "' +
capability + '"');
return;
}
capability = String(capability).toLowerCase();
this.componentData_[id].capabilities.push(capability);
this.capabilityToComponentIds_[capability].push(id);
};
/**
* Removes a capability from an existing registered component.
* @param {string} id The ID of the component to remove the capability from.
* @param {string|!Blockly.ComponentManager.Capability<T>} capability The
* capability to remove.
* @template T
*/
Blockly.ComponentManager.prototype.removeCapability = function(id, capability) {
if (!this.getComponent(id)) {
throw Error('Cannot remove capability, "' + capability + '". Plugin "' +
id + '" has not been added to the ComponentManager');
}
if (!this.hasCapability(id, capability)) {
console.warn('Plugin "' + id + 'doesn\'t have capability "' +
capability + '" to remove');
return;
}
capability = String(capability).toLowerCase();
this.componentData_[id].capabilities.splice(
this.componentData_[id].capabilities.indexOf(capability), 1);
this.capabilityToComponentIds_[capability].splice(
this.capabilityToComponentIds_[capability].indexOf(id), 1);
};
/**
* Returns whether the component with this id has the specified capability.
* @param {string} id The ID of the component to check.
* @param {string|!Blockly.ComponentManager.Capability<T>} capability The
* capability to check for.
* @return {boolean} Whether the component has the capability.
* @template T
*/
Blockly.ComponentManager.prototype.hasCapability = function(id, capability) {
capability = String(capability).toLowerCase();
return this.componentData_[id].capabilities.indexOf(capability) !== -1;
};
/**
* Gets the component with the given ID.
* @param {string} id The ID of the component to get.
* @return {!Blockly.IComponent|undefined} The component with the given name
* or undefined if not found.
*/
Blockly.ComponentManager.prototype.getComponent = function(id) {
return this.componentData_[id] && this.componentData_[id].component;
};
/**
* Gets all the components with the specified capability.
* @param {string|!Blockly.ComponentManager.Capability<T>
* } capability The capability of the component.
* @param {boolean} sorted Whether to return list ordered by weights.
* @return {!Array<T>} The components that match the specified capability.
* @template T
*/
Blockly.ComponentManager.prototype.getComponents = function(capability, sorted) {
capability = String(capability).toLowerCase();
var componentIds = this.capabilityToComponentIds_[capability];
if (!componentIds) {
return [];
}
var components = [];
if (sorted) {
var componentDataList = [];
var componentData = this.componentData_;
componentIds.forEach(function(id) {
componentDataList.push(componentData[id]);
});
componentDataList.sort(function(a, b) {
return a.weight - b.weight;
});
componentDataList.forEach(function(ComponentDatum) {
components.push(ComponentDatum.component);
});
} else {
var componentData = this.componentData_;
componentIds.forEach(function(id) {
components.push(componentData[id].component);
});
}
return components;
};
/**
* A name with the capability of the element stored in the generic.
* @param {string} name The name of the component capability.
* @constructor
* @template T
*/
Blockly.ComponentManager.Capability = function(name) {
/**
* @type {string}
* @private
*/
this.name_ = name;
};
/**
* Returns the name of the capability.
* @return {string} The name.
* @override
*/
Blockly.ComponentManager.Capability.prototype.toString = function() {
return this.name_;
};
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IPositionable>} */
Blockly.ComponentManager.Capability.POSITIONABLE =
new Blockly.ComponentManager.Capability('positionable');
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IDragTarget>} */
Blockly.ComponentManager.Capability.DRAG_TARGET =
new Blockly.ComponentManager.Capability('drag_target');
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IDeleteArea>} */
Blockly.ComponentManager.Capability.DELETE_AREA =
new Blockly.ComponentManager.Capability('delete_area');
/** @type {!Blockly.ComponentManager.Capability<!Blockly.IAutoHideable>} */
Blockly.ComponentManager.Capability.AUTOHIDEABLE =
new Blockly.ComponentManager.Capability('autohideable');
+111 -124
View File
@@ -18,11 +18,11 @@ goog.require('Blockly.constants');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BlockMove');
goog.require('Blockly.IASTNodeLocationWithBlock');
goog.require('Blockly.utils.deprecation');
goog.require('Blockly.Xml');
goog.requireType('Blockly.Block');
goog.requireType('Blockly.IASTNodeLocationWithBlock');
goog.requireType('Blockly.IConnectionChecker');
goog.requireType('Blockly.Input');
@@ -104,106 +104,58 @@ Blockly.Connection.prototype.y = 0;
* @protected
*/
Blockly.Connection.prototype.connect_ = function(childConnection) {
var INPUT = Blockly.connectionTypes.INPUT_VALUE;
var parentConnection = this;
var parentBlock = parentConnection.getSourceBlock();
var childBlock = childConnection.getSourceBlock();
// Disconnect any existing parent on the child connection.
// Make sure the childConnection is available.
if (childConnection.isConnected()) {
childConnection.disconnect();
}
// Make sure the parentConnection is available.
var orphan;
if (parentConnection.isConnected()) {
// Other connection is already connected to something.
// Disconnect it and reattach it or bump it as needed.
var orphanBlock = parentConnection.targetBlock();
var shadowDom = parentConnection.getShadowDom();
// Temporarily set the shadow DOM to null so it does not respawn.
parentConnection.shadowDom_ = null;
// Displaced shadow blocks dissolve rather than reattaching or bumping.
if (orphanBlock.isShadow()) {
// Save the shadow block so that field values are preserved.
// This cast assumes that a block can not be both a shadow block and an insertion marker.
shadowDom = /** @type {!Element} */ (Blockly.Xml.blockToDom(orphanBlock));
orphanBlock.dispose(false);
orphanBlock = null;
} else if (parentConnection.type == Blockly.connectionTypes.INPUT_VALUE) {
// Value connections.
// If female block is already connected, disconnect and bump the male.
if (!orphanBlock.outputConnection) {
throw Error('Orphan block does not have an output connection.');
}
// Attempt to reattach the orphan at the end of the newly inserted
// block. Since this block may be a row, walk down to the end
// or to the first (and only) shadow block.
var connection = Blockly.Connection.lastConnectionInRow(
childBlock, orphanBlock);
if (connection) {
orphanBlock.outputConnection.connect(connection);
orphanBlock = null;
}
} else if (
parentConnection.type == Blockly.connectionTypes.NEXT_STATEMENT) {
// Statement connections.
// Statement blocks may be inserted into the middle of a stack.
// Split the stack.
if (!orphanBlock.previousConnection) {
throw Error('Orphan block does not have a previous connection.');
}
// Attempt to reattach the orphan at the bottom of the newly inserted
// block. Since this block may be a stack, walk down to the end.
var newBlock = childBlock;
while (newBlock.nextConnection) {
var nextBlock = newBlock.getNextBlock();
if (nextBlock && !nextBlock.isShadow()) {
newBlock = nextBlock;
} else {
var checker = orphanBlock.workspace.connectionChecker;
if (checker.canConnect(
orphanBlock.previousConnection, newBlock.nextConnection, false)) {
newBlock.nextConnection.connect(orphanBlock.previousConnection);
orphanBlock = null;
}
break;
}
}
}
if (orphanBlock) {
// Unable to reattach orphan.
var shadowDom = parentConnection.getShadowDom(true);
parentConnection.shadowDom_ = null; // Set to null so it doesn't respawn.
var target = parentConnection.targetBlock();
if (target.isShadow()) {
target.dispose(false);
} else {
parentConnection.disconnect();
if (Blockly.Events.recordUndo) {
// Bump it off to the side after a moment.
var group = Blockly.Events.getGroup();
setTimeout(function() {
// Verify orphan hasn't been deleted or reconnected.
if (orphanBlock.workspace && !orphanBlock.getParent()) {
Blockly.Events.setGroup(group);
if (orphanBlock.outputConnection) {
orphanBlock.outputConnection.onFailedConnect(parentConnection);
} else if (orphanBlock.previousConnection) {
orphanBlock.previousConnection.onFailedConnect(parentConnection);
}
Blockly.Events.setGroup(false);
}
}, Blockly.BUMP_DELAY);
}
orphan = target;
}
// Restore the shadow DOM.
parentConnection.shadowDom_ = shadowDom;
}
// Connect the new connection to the parent.
var event;
if (Blockly.Events.isEnabled()) {
event = new (Blockly.Events.get(Blockly.Events.BLOCK_MOVE))(childBlock);
}
// Establish the connections.
Blockly.Connection.connectReciprocally_(parentConnection, childConnection);
// Demote the inferior block so that one is a child of the superior one.
childBlock.setParent(parentBlock);
if (event) {
event.recordNew();
Blockly.Events.fire(event);
}
// Deal with the orphan if it exists.
if (orphan) {
var orphanConnection = parentConnection.type === INPUT ?
orphan.outputConnection : orphan.previousConnection;
var connection = Blockly.Connection.getConnectionForOrphanedConnection(
childBlock, /** @type {!Blockly.Connection} */ (orphanConnection));
if (connection) {
orphanConnection.connect(connection);
} else {
orphanConnection.onFailedConnect(parentConnection);
}
}
};
/**
* Dispose of this connection and deal with connected blocks.
* @package
@@ -318,7 +270,8 @@ Blockly.Connection.prototype.isConnectionAllowed = function(candidate) {
};
/**
* Behavior after a connection attempt fails.
* Called when an attempted connection fails. NOP by default (i.e. for headless
* workspaces).
* @param {!Blockly.Connection} _otherConnection Connection that this connection
* failed to connect to.
* @package
@@ -372,30 +325,31 @@ Blockly.Connection.connectReciprocally_ = function(first, second) {
};
/**
* Does the given block have one and only one connection point that will accept
* an orphaned block?
* Returns the single connection on the block that will accept the orphaned
* block, if one can be found. If the block has multiple compatible connections
* (even if they are filled) this returns null. If the block has no compatible
* connections, this returns null.
* @param {!Blockly.Block} block The superior block.
* @param {!Blockly.Block} orphanBlock The inferior block.
* @return {Blockly.Connection} The suitable connection point on 'block',
* @return {?Blockly.Connection} The suitable connection point on 'block',
* or null.
* @private
*/
Blockly.Connection.singleConnection_ = function(block, orphanBlock) {
var connection = null;
Blockly.Connection.getSingleConnection_ = function(block, orphanBlock) {
var foundConnection = null;
var output = orphanBlock.outputConnection;
for (var i = 0; i < block.inputList.length; i++) {
var thisConnection = block.inputList[i].connection;
var typeChecker = output.getConnectionChecker();
if (thisConnection &&
thisConnection.type == Blockly.connectionTypes.INPUT_VALUE &&
typeChecker.canConnect(output, thisConnection, false)) {
if (connection) {
var typeChecker = output.getConnectionChecker();
for (var i = 0, input; (input = block.inputList[i]); i++) {
var connection = input.connection;
if (connection && typeChecker.canConnect(output, connection, false)) {
if (foundConnection) {
return null; // More than one connection.
}
connection = thisConnection;
foundConnection = connection;
}
}
return connection;
return foundConnection;
};
/**
@@ -406,22 +360,49 @@ Blockly.Connection.singleConnection_ = function(block, orphanBlock) {
* Terminates early for shadow blocks.
* @param {!Blockly.Block} startBlock The block on which to start the search.
* @param {!Blockly.Block} orphanBlock The block that is looking for a home.
* @return {Blockly.Connection} The suitable connection point on the chain
* @return {?Blockly.Connection} The suitable connection point on the chain
* of blocks, or null.
* @package
* @private
*/
Blockly.Connection.lastConnectionInRow = function(startBlock, orphanBlock) {
var newBlock = startBlock;
var connection;
while ((connection = Blockly.Connection.singleConnection_(
/** @type {!Blockly.Block} */ (newBlock), orphanBlock))) {
newBlock = connection.targetBlock();
if (!newBlock || newBlock.isShadow()) {
return connection;
}
}
return null;
};
Blockly.Connection.getConnectionForOrphanedOutput_ =
function(startBlock, orphanBlock) {
var newBlock = startBlock;
var connection;
while ((connection = Blockly.Connection.getSingleConnection_(
/** @type {!Blockly.Block} */ (newBlock), orphanBlock))) {
newBlock = connection.targetBlock();
if (!newBlock || newBlock.isShadow()) {
return connection;
}
}
return null;
};
/**
* Returns the connection (starting at the startBlock) which will accept
* the given connection. This includes compatible connection types and
* connection checks.
* @param {!Blockly.Block} startBlock The block on which to start the search.
* @param {!Blockly.Connection} orphanConnection The connection that is looking
* for a home.
* @return {?Blockly.Connection} The suitable connection point on the chain of
* blocks, or null.
*/
Blockly.Connection.getConnectionForOrphanedConnection =
function(startBlock, orphanConnection) {
if (orphanConnection.type === Blockly.connectionTypes.OUTPUT_VALUE) {
return Blockly.Connection.getConnectionForOrphanedOutput_(
startBlock, orphanConnection.getSourceBlock());
}
// Otherwise we're dealing with a stack.
var connection = startBlock.lastConnectionInStack(true);
var checker = orphanConnection.getConnectionChecker();
if (connection &&
checker.canConnect(orphanConnection, connection, false)) {
return connection;
}
return null;
};
/**
* Disconnect this connection.
@@ -491,8 +472,7 @@ Blockly.Connection.prototype.respawnShadow_ = function() {
var parentBlock = this.getSourceBlock();
var shadow = this.getShadowDom();
if (parentBlock.workspace && shadow) {
var blockShadow =
Blockly.Xml.domToBlock(shadow, parentBlock.workspace);
var blockShadow = Blockly.Xml.domToBlock(shadow, parentBlock.workspace);
if (blockShadow.outputConnection) {
this.connect(blockShadow.outputConnection);
} else if (blockShadow.previousConnection) {
@@ -505,7 +485,7 @@ Blockly.Connection.prototype.respawnShadow_ = function() {
/**
* Returns the block that this connection connects to.
* @return {Blockly.Block} The connected block or null if none is connected.
* @return {?Blockly.Block} The connected block or null if none is connected.
*/
Blockly.Connection.prototype.targetBlock = function() {
if (this.isConnected()) {
@@ -567,7 +547,7 @@ Blockly.Connection.prototype.onCheckChanged_ = function() {
/**
* Change a connection's compatibility.
* @param {?(string|!Array.<string>)} check Compatible value type or list of
* @param {?(string|!Array<string>)} check Compatible value type or list of
* value types. Null if all types are compatible.
* @return {!Blockly.Connection} The connection being modified
* (to allow chaining).
@@ -588,7 +568,7 @@ Blockly.Connection.prototype.setCheck = function(check) {
/**
* Get a connection's compatibility.
* @return {Array} List of compatible value types.
* @return {?Array} List of compatible value types.
* Null if all types are compatible.
* @public
*/
@@ -598,7 +578,7 @@ Blockly.Connection.prototype.getCheck = function() {
/**
* Changes the connection's shadow block.
* @param {Element} shadow DOM representation of a block or null.
* @param {?Element} shadow DOM representation of a block or null.
*/
Blockly.Connection.prototype.setShadowDom = function(shadow) {
this.shadowDom_ = shadow;
@@ -614,10 +594,17 @@ Blockly.Connection.prototype.setShadowDom = function(shadow) {
/**
* Returns the xml representation of the connection's shadow block.
* @return {Element} Shadow DOM representation of a block or null.
* @param {boolean=} returnCurrent If true, and the shadow block is currently
* attached to this connection, this serializes the state of that block
* and returns it (so that field values are correct). Otherwise the saved
* shadowDom is just returned.
* @return {?Element} Shadow DOM representation of a block or null.
*/
Blockly.Connection.prototype.getShadowDom = function() {
return this.shadowDom_;
Blockly.Connection.prototype.getShadowDom = function(returnCurrent) {
return (returnCurrent && this.targetBlock().isShadow()) ?
/** @type {!Element} */ (Blockly.Xml.blockToDom(
/** @type {!Blockly.Block} */ (this.targetBlock()))) :
this.shadowDom_;
};
/**
@@ -629,7 +616,7 @@ Blockly.Connection.prototype.getShadowDom = function() {
* {@link Blockly.RenderedConnection} overrides this behavior with a list
* computed from the rendered positioning.
* @param {number} _maxLimit The maximum radius to another connection.
* @return {!Array.<!Blockly.Connection>} List of connections.
* @return {!Array<!Blockly.Connection>} List of connections.
* @package
*/
Blockly.Connection.prototype.neighbours = function(_maxLimit) {
@@ -638,17 +625,16 @@ Blockly.Connection.prototype.neighbours = function(_maxLimit) {
/**
* Get the parent input of a connection.
* @return {Blockly.Input} The input that the connection belongs to or null if
* @return {?Blockly.Input} The input that the connection belongs to or null if
* no parent exists.
* @package
*/
Blockly.Connection.prototype.getParentInput = function() {
var parentInput = null;
var block = this.sourceBlock_;
var inputs = block.inputList;
for (var idx = 0; idx < block.inputList.length; idx++) {
if (inputs[idx].connection === this) {
parentInput = inputs[idx];
var inputs = this.sourceBlock_.inputList;
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].connection === this) {
parentInput = inputs[i];
break;
}
}
@@ -661,11 +647,12 @@ Blockly.Connection.prototype.getParentInput = function() {
* @return {string} The description.
*/
Blockly.Connection.prototype.toString = function() {
var msg;
var block = this.sourceBlock_;
if (!block) {
return 'Orphan Connection';
} else if (block.outputConnection == this) {
}
var msg;
if (block.outputConnection == this) {
msg = 'Output Connection of ';
} else if (block.previousConnection == this) {
msg = 'Previous Connection of ';
+14 -14
View File
@@ -35,7 +35,7 @@ goog.requireType('Blockly.utils.Coordinate');
Blockly.ConnectionDB = function(checker) {
/**
* Array of connections sorted by y position in workspace units.
* @type {!Array.<!Blockly.RenderedConnection>}
* @type {!Array<!Blockly.RenderedConnection>}
* @private
*/
this.connections_ = [];
@@ -84,21 +84,21 @@ Blockly.ConnectionDB.prototype.findIndexOfConnection_ = function(conn, yPos) {
yPos = conn.y;
// Walk forward and back on the y axis looking for the connection.
var pointerMin = bestGuess;
var pointerMax = bestGuess;
while (pointerMin >= 0 && this.connections_[pointerMin].y == yPos) {
if (this.connections_[pointerMin] == conn) {
return pointerMin;
var pointer = bestGuess;
while (pointer >= 0 && this.connections_[pointer].y == yPos) {
if (this.connections_[pointer] == conn) {
return pointer;
}
pointerMin--;
pointer--;
}
while (pointerMax < this.connections_.length &&
this.connections_[pointerMax].y == yPos) {
if (this.connections_[pointerMax] == conn) {
return pointerMax;
pointer = bestGuess;
while (pointer < this.connections_.length &&
this.connections_[pointer].y == yPos) {
if (this.connections_[pointer] == conn) {
return pointer;
}
pointerMax++;
pointer++;
}
return -1;
};
@@ -150,7 +150,7 @@ Blockly.ConnectionDB.prototype.removeConnection = function(connection, yPos) {
* @param {!Blockly.RenderedConnection} connection The connection whose
* neighbours should be returned.
* @param {number} maxRadius The maximum radius to another connection.
* @return {!Array.<!Blockly.RenderedConnection>} List of connections.
* @return {!Array<!Blockly.RenderedConnection>} List of connections.
*/
Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) {
var db = this.connections_;
@@ -286,7 +286,7 @@ Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius,
* Initialize a set of connection DBs for a workspace.
* @param {!Blockly.IConnectionChecker} checker The workspace's
* connection checker, used to decide if connections are valid during a drag.
* @return {!Array.<!Blockly.ConnectionDB>} Array of databases.
* @return {!Array<!Blockly.ConnectionDB>} Array of databases.
*/
Blockly.ConnectionDB.init = function(checker) {
// Create four databases, one for each connection type.
+2 -22
View File
@@ -161,26 +161,6 @@ Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.NEXT_STATEMENT] =
Blockly.OPPOSITE_TYPE[Blockly.connectionTypes.PREVIOUS_STATEMENT] =
Blockly.connectionTypes.NEXT_STATEMENT;
/**
* ENUM representing that an event is not in any delete areas.
* Null for backwards compatibility reasons.
* @const
*/
Blockly.DELETE_AREA_NONE = null;
/**
* ENUM representing that an event is in the delete area of the trash can.
* @const
*/
Blockly.DELETE_AREA_TRASH = 1;
/**
* ENUM representing that an event is in the delete area of the toolbox or
* flyout.
* @const
*/
Blockly.DELETE_AREA_TOOLBOX = 2;
/**
* String for use in the "custom" attribute of a category in toolbox XML.
* This string indicates that the category should be dynamically populated with
@@ -221,13 +201,13 @@ Blockly.RENAME_VARIABLE_ID = 'RENAME_VARIABLE_ID';
Blockly.DELETE_VARIABLE_ID = 'DELETE_VARIABLE_ID';
/**
* The language-neutral id given to the collapsed input.
* The language-neutral ID given to the collapsed input.
* @const {string}
*/
Blockly.constants.COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT';
/**
* The language-neutral id given to the collapsed field.
* The language-neutral ID given to the collapsed field.
* @const {string}
*/
Blockly.constants.COLLAPSED_FIELD_NAME = '_TEMP_COLLAPSED_FIELD';
+2 -2
View File
@@ -54,7 +54,7 @@ Blockly.ContextMenu.menu_ = null;
/**
* Construct the menu based on the list of options and show the menu.
* @param {!Event} e Mouse event.
* @param {!Array.<!Object>} options Array of menu options.
* @param {!Array<!Object>} options Array of menu options.
* @param {boolean} rtl True if RTL, false if LTR.
*/
Blockly.ContextMenu.show = function(e, options, rtl) {
@@ -75,7 +75,7 @@ Blockly.ContextMenu.show = function(e, options, rtl) {
/**
* Create the context menu object and populate it with the given options.
* @param {!Array.<!Object>} options Array of menu options.
* @param {!Array<!Object>} options Array of menu options.
* @param {boolean} rtl True if RTL, false if LTR.
* @return {!Blockly.Menu} The menu that will be shown on right click.
* @private
+11 -11
View File
@@ -183,7 +183,7 @@ Blockly.ContextMenuItems.registerExpand = function() {
/**
* Adds a block and its children to a list of deletable blocks.
* @param {!Blockly.BlockSvg} block to delete.
* @param {!Array.<!Blockly.BlockSvg>} deleteList list of blocks that can be deleted. This will be
* @param {!Array<!Blockly.BlockSvg>} deleteList list of blocks that can be deleted. This will be
* modifed in place with the given block and its descendants.
* @private
*/
@@ -191,7 +191,7 @@ Blockly.ContextMenuItems.addDeletableBlocks_ = function(block, deleteList) {
if (block.isDeletable()) {
Array.prototype.push.apply(deleteList, block.getDescendants(false));
} else {
var children = /** @type !Array.<!Blockly.BlockSvg> */ (block.getChildren(false));
var children = /** @type !Array<!Blockly.BlockSvg> */ (block.getChildren(false));
for (var i = 0; i < children.length; i++) {
Blockly.ContextMenuItems.addDeletableBlocks_(children[i], deleteList);
}
@@ -201,7 +201,7 @@ Blockly.ContextMenuItems.addDeletableBlocks_ = function(block, deleteList) {
/**
* Constructs a list of blocks that can be deleted in the given workspace.
* @param {!Blockly.WorkspaceSvg} workspace to delete all blocks from.
* @return {!Array.<!Blockly.BlockSvg>} list of blocks to delete.
* @return {!Array<!Blockly.BlockSvg>} list of blocks to delete.
* @private
*/
Blockly.ContextMenuItems.getDeletableBlocks_ = function(workspace) {
@@ -214,8 +214,8 @@ Blockly.ContextMenuItems.getDeletableBlocks_ = function(workspace) {
};
/** Deletes the given blocks. Used to delete all blocks in the workspace.
* @param {!Array.<!Blockly.BlockSvg>} deleteList list of blocks to delete.
* @param {string} eventGroup event group id with which all delete events should be associated.
* @param {!Array<!Blockly.BlockSvg>} deleteList list of blocks to delete.
* @param {string} eventGroup event group ID with which all delete events should be associated.
* @private
*/
Blockly.ContextMenuItems.deleteNext_ = function(deleteList, eventGroup) {
@@ -397,14 +397,12 @@ Blockly.ContextMenuItems.registerCollapseExpandBlock = function() {
/** @type {!Blockly.ContextMenuRegistry.RegistryItem} */
var collapseExpandOption = {
displayText: function(/** @type {!Blockly.ContextMenuRegistry.Scope} */ scope) {
if (scope.block.isCollapsed()) {
return Blockly.Msg['EXPAND_BLOCK'];
}
return Blockly.Msg['COLLAPSE_BLOCK'];
return scope.block.isCollapsed() ?
Blockly.Msg['EXPAND_BLOCK'] : Blockly.Msg['COLLAPSE_BLOCK'];
},
preconditionFn: function(/** @type {!Blockly.ContextMenuRegistry.Scope} */ scope) {
var block = scope.block;
if (!block.isInFlyout && block.isMovable()) {
if (!block.isInFlyout && block.isMovable() && block.workspace.options.collapse) {
return 'enabled';
}
return 'hidden';
@@ -479,7 +477,9 @@ Blockly.ContextMenuItems.registerDelete = function() {
},
callback: function(/** @type {!Blockly.ContextMenuRegistry.Scope} */ scope) {
Blockly.Events.setGroup(true);
scope.block.dispose(true, true);
if (scope.block) {
Blockly.deleteBlock(scope.block);
}
Blockly.Events.setGroup(false);
},
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
+15 -19
View File
@@ -31,11 +31,11 @@ Blockly.ContextMenuRegistry = function() {
Blockly.ContextMenuRegistry.registry = this;
/**
* Registry of all registered RegistryItems, keyed by id.
* @type {!Object<string, Blockly.ContextMenuRegistry.RegistryItem>}
* Registry of all registered RegistryItems, keyed by ID.
* @type {!Object<string, !Blockly.ContextMenuRegistry.RegistryItem>}
* @private
*/
this.registry_ = {};
this.registry_ = Object.create(null);
};
/**
@@ -93,37 +93,33 @@ Blockly.ContextMenuRegistry.registry = null;
/**
* Registers a RegistryItem.
* @param {!Blockly.ContextMenuRegistry.RegistryItem} item Context menu item to register.
* @throws {Error} if an item with the given id already exists.
* @throws {Error} if an item with the given ID already exists.
*/
Blockly.ContextMenuRegistry.prototype.register = function(item) {
if (this.registry_[item.id]) {
throw Error('Menu item with id "' + item.id + '" is already registered.');
throw Error('Menu item with ID "' + item.id + '" is already registered.');
}
this.registry_[item.id] = item;
};
/**
* Unregisters a RegistryItem with the given id.
* @param {string} id The id of the RegistryItem to remove.
* @throws {Error} if an item with the given id does not exist.
* Unregisters a RegistryItem with the given ID.
* @param {string} id The ID of the RegistryItem to remove.
* @throws {Error} if an item with the given ID does not exist.
*/
Blockly.ContextMenuRegistry.prototype.unregister = function(id) {
if (this.registry_[id]) {
delete this.registry_[id];
} else {
throw new Error('Menu item with id "' + id + '" not found.');
if (!this.registry_[id]) {
throw new Error('Menu item with ID "' + id + '" not found.');
}
delete this.registry_[id];
};
/**
* @param {string} id The id of the RegistryItem to get.
* @returns {?Blockly.ContextMenuRegistry.RegistryItem} RegistryItem or null if not found
* @param {string} id The ID of the RegistryItem to get.
* @return {?Blockly.ContextMenuRegistry.RegistryItem} RegistryItem or null if not found
*/
Blockly.ContextMenuRegistry.prototype.getItem = function(id) {
if (this.registry_[id]) {
return this.registry_[id];
}
return null;
return this.registry_[id] || null;
};
/**
@@ -133,7 +129,7 @@ Blockly.ContextMenuRegistry.prototype.getItem = function(id) {
* shown (e.g. on a block or on a workspace)
* @param {!Blockly.ContextMenuRegistry.Scope} scope Current scope of context menu
* (i.e., the exact workspace or block being clicked on)
* @returns {!Array.<!Blockly.ContextMenuRegistry.ContextMenuOption>} the list of ContextMenuOptions
* @return {!Array<!Blockly.ContextMenuRegistry.ContextMenuOption>} the list of ContextMenuOptions
*/
Blockly.ContextMenuRegistry.prototype.getContextMenuOptions = function(scopeType, scope) {
var menuOptions = [];
+10 -10
View File
@@ -28,7 +28,7 @@ Blockly.Css.injected_ = false;
* Add some CSS to the blob that will be injected later. Allows optional
* components such as fields and the toolbox to store separate CSS.
* The provided array of CSS will be destroyed by this function.
* @param {!Array.<string>} cssArray Array of CSS strings.
* @param {!Array<string>} cssArray Array of CSS strings.
*/
Blockly.Css.register = function(cssArray) {
if (Blockly.Css.injected_) {
@@ -88,13 +88,13 @@ Blockly.Css.CONTENT = [
'.blocklyWidgetDiv {',
'display: none;',
'position: absolute;',
'z-index: 99999;', /* big value for bootstrap3 compatibility */
'z-index: 99999;', /* big value for bootstrap3 compatibility */
'}',
'.injectionDiv {',
'height: 100%;',
'position: relative;',
'overflow: hidden;', /* So blocks in drag surface disappear at edges */
'overflow: hidden;', /* So blocks in drag surface disappear at edges */
'touch-action: none;',
'}',
@@ -125,7 +125,7 @@ Blockly.Css.CONTENT = [
'right: 0;',
'bottom: 0;',
'overflow: visible !important;',
'z-index: 50;', /* Display below toolbox, but above everything else. */
'z-index: 50;', /* Display below toolbox, but above everything else. */
'}',
'.blocklyBlockCanvas.blocklyCanvasTransitioning,',
@@ -143,7 +143,7 @@ Blockly.Css.CONTENT = [
'opacity: .9;',
'padding: 2px;',
'position: absolute;',
'z-index: 100000;', /* big value for bootstrap3 compatibility */
'z-index: 100000;', /* big value for bootstrap3 compatibility */
'}',
'.blocklyDropDownDiv {',
@@ -165,7 +165,7 @@ Blockly.Css.CONTENT = [
'}',
'.blocklyDropDownContent {',
'max-height: 300px;', // @todo: spec for maximum height.
'max-height: 300px;', // @todo: spec for maximum height.
'overflow: auto;',
'overflow-x: hidden;',
'position: relative;',
@@ -498,11 +498,11 @@ Blockly.Css.CONTENT = [
'}',
'.blocklyDropDownDiv .blocklyMenu {',
'background: inherit;', /* Compatibility with gapi, reset from goog-menu */
'border: inherit;', /* Compatibility with gapi, reset from goog-menu */
'background: inherit;', /* Compatibility with gapi, reset from goog-menu */
'border: inherit;', /* Compatibility with gapi, reset from goog-menu */
'font: normal 13px "Helvetica Neue", Helvetica, sans-serif;',
'outline: none;',
'position: relative;', /* Compatibility with gapi, reset from goog-menu */
'position: relative;', /* Compatibility with gapi, reset from goog-menu */
'z-index: 20000;', /* Arbitrary, but some apps depend on it... */
'}',
@@ -541,7 +541,7 @@ Blockly.Css.CONTENT = [
'background: url(<<<PATH>>>/sprites.png) no-repeat -48px -16px;',
'float: left;',
'margin-left: -24px;',
'position: static;', /* Scroll with the menu. */
'position: static;', /* Scroll with the menu. */
'}',
'.blocklyMenuItemRtl .blocklyMenuItemCheckbox {',
+74
View File
@@ -0,0 +1,74 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The abstract class for a component that can delete a block or
* bubble that is dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.DeleteArea');
goog.require('Blockly.BlockSvg');
goog.require('Blockly.DragTarget');
goog.require('Blockly.IDeleteArea');
goog.requireType('Blockly.IDraggable');
/**
* Abstract class for a component that can delete a block or bubble that is
* dropped on top of it.
* @extends {Blockly.DragTarget}
* @implements {Blockly.IDeleteArea}
* @constructor
*/
Blockly.DeleteArea = function() {
Blockly.DeleteArea.superClass_.constructor.call(this);
/**
* Whether the last block or bubble dragged over this delete area would be
* deleted if dropped on this component.
* This property is not updated after the block or bubble is deleted.
* @type {boolean}
* @protected
*/
this.wouldDelete_ = false;
};
Blockly.utils.object.inherits(Blockly.DeleteArea, Blockly.DragTarget);
/**
* Returns whether the provided block or bubble would be deleted if dropped on
* this area.
* This method should check if the element is deletable and is always called
* before onDragEnter/onDragOver/onDragExit.
* @param {!Blockly.IDraggable} element The block or bubble currently being
* dragged.
* @param {boolean} couldConnect Whether the element could could connect to
* another.
* @return {boolean} Whether the element provided would be deleted if dropped on
* this area.
*/
Blockly.DeleteArea.prototype.wouldDelete = function(element, couldConnect) {
if (element instanceof Blockly.BlockSvg) {
var block = /** @type {Blockly.BlockSvg} */ (element);
var couldDeleteBlock = !block.getParent() && block.isDeletable();
this.updateWouldDelete_(couldDeleteBlock && !couldConnect);
} else {
this.updateWouldDelete_(element.isDeletable());
}
return this.wouldDelete_;
};
/**
* Updates the internal wouldDelete_ state.
* @param {boolean} wouldDelete The new value for the wouldDelete state.
* @protected
*/
Blockly.DeleteArea.prototype.updateWouldDelete_ = function(wouldDelete) {
this.wouldDelete_ = wouldDelete;
};
+88
View File
@@ -0,0 +1,88 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The abstract class for a component with custom behaviour when a
* block or bubble is dragged over or dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.DragTarget');
goog.require('Blockly.IDragTarget');
goog.requireType('Blockly.IDraggable');
goog.requireType('Blockly.utils.Rect');
/**
* Abstract class for a component with custom behaviour when a block or bubble
* is dragged over or dropped on top of it.
* @implements {Blockly.IDragTarget}
* @constructor
*/
Blockly.DragTarget = function() {};
/**
* Returns the bounding rectangle of the drag target area in pixel units
* relative to the Blockly injection div.
* @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
* target area should be ignored.
*/
Blockly.DragTarget.prototype.getClientRect;
/**
* Handles when a cursor with a block or bubble enters this drag target.
* @param {!Blockly.IDraggable} _dragElement The block or bubble currently being
* dragged.
*/
Blockly.DragTarget.prototype.onDragEnter = function(_dragElement) {
// no-op
};
/**
* Handles when a cursor with a block or bubble is dragged over this drag
* target.
* @param {!Blockly.IDraggable} _dragElement The block or bubble currently being
* dragged.
*/
Blockly.DragTarget.prototype.onDragOver = function(_dragElement) {
// no-op
};
/**
* Handles when a cursor with a block or bubble exits this drag target.
* @param {!Blockly.IDraggable} _dragElement The block or bubble currently being
* dragged.
*/
Blockly.DragTarget.prototype.onDragExit = function(_dragElement) {
// no-op
};
/**
* Handles when a block or bubble is dropped on this component.
* Should not handle delete here.
* @param {!Blockly.IDraggable} _dragElement The block or bubble currently being
* dragged.
*/
Blockly.DragTarget.prototype.onDrop = function(_dragElement) {
// no-op
};
/**
* Returns whether the provided block or bubble should not be moved after being
* dropped on this component. If true, the element will return to where it was
* when the drag started.
* @param {!Blockly.IDraggable} _dragElement The block or bubble currently being
* dragged.
* @return {boolean} Whether the block or bubble provided should be returned to
* drag start.
*/
Blockly.DragTarget.prototype.shouldPreventMove = function(_dragElement) {
return false;
};
+5 -5
View File
@@ -493,7 +493,7 @@ Blockly.DropDownDiv.getPositionBelowMetrics_ = function(
return {
initialX: xCoords.divX,
initialY : primaryY,
finalX: xCoords.divX, // X position remains constant during animation.
finalX: xCoords.divX, // X position remains constant during animation.
finalY: finalY,
arrowX: xCoords.arrowX,
arrowY: arrowY,
@@ -525,12 +525,12 @@ Blockly.DropDownDiv.getPositionAboveMetrics_ = function(
var arrowY = divSize.height - (Blockly.DropDownDiv.BORDER_SIZE * 2) -
(Blockly.DropDownDiv.ARROW_SIZE / 2);
var finalY = secondaryY - divSize.height - Blockly.DropDownDiv.PADDING_Y;
var initialY = secondaryY - divSize.height; // No padding on Y
var initialY = secondaryY - divSize.height; // No padding on Y.
return {
initialX: xCoords.divX,
initialY : initialY,
finalX: xCoords.divX, // X position remains constant during animation.
finalX: xCoords.divX, // X position remains constant during animation.
finalY: finalY,
arrowX: xCoords.arrowX,
arrowY: arrowY,
@@ -560,8 +560,8 @@ Blockly.DropDownDiv.getPositionTopOfPageMetrics_ = function(
return {
initialX: xCoords.divX,
initialY : 0,
finalX: xCoords.divX, // X position remains constant during animation.
finalY: 0, // Y position remains constant during animation.
finalX: xCoords.divX, // X position remains constant during animation.
finalY: 0, // Y position remains constant during animation.
arrowAtTop: null,
arrowX: null,
arrowY: null,
+16 -16
View File
@@ -20,9 +20,9 @@ goog.provide('Blockly.Events.Create'); // Deprecated.
goog.provide('Blockly.Events.Delete'); // Deprecated.
goog.provide('Blockly.Events.Move'); // Deprecated.
goog.require('Blockly.connectionTypes');
goog.require('Blockly.Events');
goog.require('Blockly.Events.Abstract');
goog.require('Blockly.connectionTypes');
goog.require('Blockly.registry');
goog.require('Blockly.utils.Coordinate');
goog.require('Blockly.utils.object');
@@ -44,7 +44,7 @@ Blockly.Events.BlockBase = function(opt_block) {
this.isBlank = typeof opt_block == 'undefined';
/**
* The block id for the block this event pertains to
* The block ID for the block this event pertains to
* @type {string}
*/
this.blockId = this.isBlank ? '' : opt_block.id;
@@ -88,7 +88,7 @@ Blockly.Events.BlockBase.prototype.fromJson = function(json) {
* @extends {Blockly.Events.BlockBase}
* @constructor
*/
Blockly.Events.Change = function(opt_block, opt_element, opt_name, opt_oldValue,
Blockly.Events.BlockChange = function(opt_block, opt_element, opt_name, opt_oldValue,
opt_newValue) {
Blockly.Events.Change.superClass_.constructor.call(this, opt_block);
if (!opt_block) {
@@ -99,7 +99,7 @@ Blockly.Events.Change = function(opt_block, opt_element, opt_name, opt_oldValue,
this.oldValue = typeof opt_oldValue == 'undefined' ? '' : opt_oldValue;
this.newValue = typeof opt_newValue == 'undefined' ? '' : opt_newValue;
};
Blockly.utils.object.inherits(Blockly.Events.Change, Blockly.Events.BlockBase);
Blockly.utils.object.inherits(Blockly.Events.BlockChange, Blockly.Events.BlockBase);
/**
* Class for a block change event.
@@ -112,20 +112,20 @@ Blockly.utils.object.inherits(Blockly.Events.Change, Blockly.Events.BlockBase);
* @extends {Blockly.Events.BlockBase}
* @constructor
*/
Blockly.Events.BlockChange = Blockly.Events.Change;
Blockly.Events.Change = Blockly.Events.BlockChange;
/**
* Type of this event.
* @type {string}
*/
Blockly.Events.Change.prototype.type = Blockly.Events.CHANGE;
Blockly.Events.BlockChange.prototype.type = Blockly.Events.CHANGE;
/**
* Encode the event as JSON.
* @return {!Object} JSON representation.
*/
Blockly.Events.Change.prototype.toJson = function() {
var json = Blockly.Events.Change.superClass_.toJson.call(this);
Blockly.Events.BlockChange.prototype.toJson = function() {
var json = Blockly.Events.BlockChange.superClass_.toJson.call(this);
json['element'] = this.element;
if (this.name) {
json['name'] = this.name;
@@ -139,8 +139,8 @@ Blockly.Events.Change.prototype.toJson = function() {
* Decode the JSON event.
* @param {!Object} json JSON representation.
*/
Blockly.Events.Change.prototype.fromJson = function(json) {
Blockly.Events.Change.superClass_.fromJson.call(this, json);
Blockly.Events.BlockChange.prototype.fromJson = function(json) {
Blockly.Events.BlockChange.superClass_.fromJson.call(this, json);
this.element = json['element'];
this.name = json['name'];
this.oldValue = json['oldValue'];
@@ -151,7 +151,7 @@ Blockly.Events.Change.prototype.fromJson = function(json) {
* Does this event record any change of state?
* @return {boolean} False if something changed.
*/
Blockly.Events.Change.prototype.isNull = function() {
Blockly.Events.BlockChange.prototype.isNull = function() {
return this.oldValue == this.newValue;
};
@@ -159,7 +159,7 @@ Blockly.Events.Change.prototype.isNull = function() {
* Run a change event.
* @param {boolean} forward True if run forward, false if run backward (undo).
*/
Blockly.Events.Change.prototype.run = function(forward) {
Blockly.Events.BlockChange.prototype.run = function(forward) {
var workspace = this.getEventWorkspace_();
var block = workspace.getBlockById(this.blockId);
if (!block) {
@@ -202,7 +202,7 @@ Blockly.Events.Change.prototype.run = function(forward) {
var dom = Blockly.Xml.textToDom(/** @type {string} */ (value) || '<mutation/>');
block.domToMutation(dom);
}
Blockly.Events.fire(new (Blockly.Events.get(Blockly.Events.CHANGE))(
Blockly.Events.fire(new Blockly.Events.BlockChange(
block, 'mutation', null, oldMutation, value));
break;
default:
@@ -332,7 +332,7 @@ Blockly.utils.object.inherits(Blockly.Events.Delete, Blockly.Events.BlockBase);
/**
* Class for a block deletion event.
* @param {Blockly.Block} block The deleted block. Null for a blank event.
* @param {?Blockly.Block} block The deleted block. Null for a blank event.
* @extends {Blockly.Events.BlockBase}
* @constructor
*/
@@ -420,7 +420,7 @@ Blockly.utils.object.inherits(Blockly.Events.Move, Blockly.Events.BlockBase);
/**
* Class for a block move event. Created before the move.
* @param {Blockly.Block} block The moved block. Null for a blank event.
* @param {?Blockly.Block} block The moved block. Null for a blank event.
* @extends {Blockly.Events.BlockBase}
* @constructor
*/
@@ -568,6 +568,6 @@ Blockly.registry.register(Blockly.registry.Type.EVENT, Blockly.Events.CREATE,
Blockly.registry.register(Blockly.registry.Type.EVENT, Blockly.Events.DELETE,
Blockly.Events.Delete);
Blockly.registry.register(Blockly.registry.Type.EVENT, Blockly.Events.CHANGE,
Blockly.Events.Change);
Blockly.Events.BlockChange);
Blockly.registry.register(Blockly.registry.Type.EVENT, Blockly.Events.MOVE,
Blockly.Events.Move);
+10 -4
View File
@@ -266,9 +266,9 @@ Blockly.Events.fireNow_ = function() {
/**
* Filter the queued events and merge duplicates.
* @param {!Array.<!Blockly.Events.Abstract>} queueIn Array of events.
* @param {!Array<!Blockly.Events.Abstract>} queueIn Array of events.
* @param {boolean} forward True if forward (redo), false if backward (undo).
* @return {!Array.<!Blockly.Events.Abstract>} Array of filtered events.
* @return {!Array<!Blockly.Events.Abstract>} Array of filtered events.
*/
Blockly.Events.filter = function(queueIn, forward) {
var queue = queueIn.slice(); // Shallow copy of queue.
@@ -281,7 +281,7 @@ Blockly.Events.filter = function(queueIn, forward) {
// Merge duplicates.
for (var i = 0, event; (event = queue[i]); i++) {
if (!event.isNull()) {
// Treat all ui events as the same type in hash table.
// Treat all UI events as the same type in hash table.
var eventType = event.isUiEvent ? Blockly.Events.UI : event.type;
var key = [eventType, event.blockId, event.workspaceId].join(' ');
@@ -305,6 +305,12 @@ Blockly.Events.filter = function(queueIn, forward) {
event.name == lastEvent.name) {
// Merge change events.
lastEvent.newValue = event.newValue;
} else if (event.type == Blockly.Events.VIEWPORT_CHANGE) {
// Merge viewport change events.
lastEvent.viewTop = event.viewTop;
lastEvent.viewLeft = event.viewLeft;
lastEvent.scale = event.scale;
lastEvent.oldScale = event.oldScale;
} else if (event.type == Blockly.Events.CLICK &&
lastEvent.type == Blockly.Events.BUBBLE_OPEN) {
// Drop click events caused by opening/closing bubbles.
@@ -390,7 +396,7 @@ Blockly.Events.setGroup = function(state) {
/**
* Compute a list of the IDs of the specified block and all its descendants.
* @param {!Blockly.Block} block The root block.
* @return {!Array.<string>} List of block IDs.
* @return {!Array<string>} List of block IDs.
* @package
*/
Blockly.Events.getDescendantIds = function(block) {
+1 -1
View File
@@ -52,7 +52,7 @@ Blockly.Events.Abstract = function() {
};
/**
* Whether or not the event is a ui event.
* Whether or not the event is a UI event.
* @type {boolean}
*/
Blockly.Events.Abstract.prototype.isUiEvent = false;
+2 -2
View File
@@ -26,7 +26,7 @@ goog.requireType('Blockly.Block');
* dragged. Undefined for a blank event.
* @param {boolean=} opt_isStart Whether this is the start of a block drag.
* Undefined for a blank event.
* @param {!Array.<!Blockly.Block>=} opt_blocks The blocks affected by this
* @param {!Array<!Blockly.Block>=} opt_blocks The blocks affected by this
* drag. Undefined for a blank event.
* @extends {Blockly.Events.UiBase}
* @constructor
@@ -44,7 +44,7 @@ Blockly.Events.BlockDrag = function(opt_block, opt_isStart, opt_blocks) {
/**
* The blocks affected by this drag event.
* @type {!Array.<!Blockly.Block>|undefined}
* @type {!Array<!Blockly.Block>|undefined}
*/
this.blocks = opt_blocks;
};
+2 -2
View File
@@ -20,9 +20,9 @@ goog.require('Blockly.utils.object');
/**
* Class for a selected event.
* @param {?string=} opt_oldElementId The id of the previously selected
* @param {?string=} opt_oldElementId The ID of the previously selected
* element. Null if no element last selected. Undefined for a blank event.
* @param {?string=} opt_newElementId The id of the selected element. Null if no
* @param {?string=} opt_newElementId The ID of the selected element. Null if no
* element currently selected (deselect). Undefined for a blank event.
* @param {string=} opt_workspaceId The workspace identifier for this event.
* Null if no element previously selected. Undefined for a blank event.
+9 -10
View File
@@ -28,7 +28,7 @@ goog.requireType('Blockly.Block');
* The set of all registered extensions, keyed by extension name/id.
* @private
*/
Blockly.Extensions.ALL_ = {};
Blockly.Extensions.ALL_ = Object.create(null);
/**
* Registers a new extension function. Extensions are functions that help
@@ -78,7 +78,7 @@ Blockly.Extensions.registerMixin = function(name, mixinObj) {
* @param {!Object} mixinObj The values to mix in.
* @param {(function())=} opt_helperFn An optional function to apply after
* mixing in the object.
* @param {!Array.<string>=} opt_blockList A list of blocks to appear in the
* @param {!Array<string>=} opt_blockList A list of blocks to appear in the
* flyout of the mutator dialog.
* @throws {Error} if the mutation is invalid or can't be applied to the block.
*/
@@ -157,7 +157,7 @@ Blockly.Extensions.apply = function(name, block, isMutator) {
Blockly.Extensions.checkBlockHasMutatorProperties_(errorPrefix, block);
} else {
if (!Blockly.Extensions.mutatorPropertiesMatch_(
/** @type {!Array.<Object>} */ (mutatorProperties), block)) {
/** @type {!Array<Object>} */ (mutatorProperties), block)) {
throw Error('Error when applying extension "' + name + '": ' +
'mutation properties changed when applying a non-mutator extension.');
}
@@ -227,10 +227,9 @@ Blockly.Extensions.checkMutatorDialog_ = function(object, errorPrefix) {
return true;
} else if (!hasCompose && !hasDecompose) {
return false;
} else {
throw Error(errorPrefix +
'Must have both or neither of "compose" and "decompose"');
}
throw Error(errorPrefix +
'Must have both or neither of "compose" and "decompose"');
};
/**
@@ -257,7 +256,7 @@ Blockly.Extensions.checkBlockHasMutatorProperties_ = function(errorPrefix,
/**
* Get a list of values of mutator properties on the given block.
* @param {!Blockly.Block} block The block to inspect.
* @return {!Array.<Object>} A list with all of the defined properties, which
* @return {!Array<Object>} A list with all of the defined properties, which
* should be functions, but may be anything other than undefined.
* @private
*/
@@ -284,7 +283,7 @@ Blockly.Extensions.getMutatorProperties_ = function(block) {
* Check that the current mutator properties match a list of old mutator
* properties. This should be called after applying a non-mutator extension,
* to verify that the extension didn't change properties it shouldn't.
* @param {!Array.<Object>} oldProperties The old values to compare to.
* @param {!Array<Object>} oldProperties The old values to compare to.
* @param {!Blockly.Block} block The block to inspect for new values.
* @return {boolean} True if the property lists match.
* @private
@@ -317,7 +316,7 @@ Blockly.Extensions.mutatorPropertiesMatch_ = function(oldProperties, block) {
* reported as warnings in the console, and are never fatal.
* @param {string} dropdownName The name of the field whose value is the key
* to the lookup table.
* @param {!Object.<string, string>} lookupTable The table of field values to
* @param {!Object<string, string>} lookupTable The table of field values to
* tooltip text.
* @return {!Function} The extension function.
*/
@@ -377,7 +376,7 @@ Blockly.Extensions.buildTooltipForDropdown = function(dropdownName,
* Emits console warnings when they are not.
* @param {!Blockly.Block} block The block containing the dropdown
* @param {string} dropdownName The name of the dropdown
* @param {!Object.<string, string>} lookupTable The string lookup table
* @param {!Object<string, string>} lookupTable The string lookup table
* @private
*/
Blockly.Extensions.checkDropdownOptionsInTable_ = function(block, dropdownName,
+13 -10
View File
@@ -15,11 +15,17 @@
goog.provide('Blockly.Field');
goog.require('Blockly.browserEvents');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BlockChange');
/** @suppress {extraRequire} */
goog.require('Blockly.Gesture');
goog.require('Blockly.IASTNodeLocationSvg');
goog.require('Blockly.IASTNodeLocationWithBlock');
goog.require('Blockly.IKeyboardAccessible');
goog.require('Blockly.IRegistrable');
goog.require('Blockly.MarkerManager');
goog.require('Blockly.Tooltip');
goog.require('Blockly.utils');
goog.require('Blockly.utils.dom');
@@ -28,15 +34,12 @@ goog.require('Blockly.utils.Size');
goog.require('Blockly.utils.style');
goog.require('Blockly.utils.Svg');
goog.require('Blockly.utils.userAgent');
goog.require('Blockly.WidgetDiv');
goog.requireType('Blockly.Block');
goog.requireType('Blockly.blockRendering.ConstantProvider');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.IASTNodeLocationSvg');
goog.requireType('Blockly.IASTNodeLocationWithBlock');
goog.requireType('Blockly.IKeyboardAccessible');
goog.requireType('Blockly.Input');
goog.requireType('Blockly.IRegistrable');
goog.requireType('Blockly.ShortcutRegistry');
goog.requireType('Blockly.utils.Coordinate');
goog.requireType('Blockly.WorkspaceSvg');
@@ -533,7 +536,7 @@ Blockly.Field.prototype.setValidator = function(handler) {
/**
* Gets the validation function for editable fields, or null if not set.
* @return {Function} Validation function, or null.
* @return {?Function} Validation function, or null.
*/
Blockly.Field.prototype.getValidator = function() {
return this.validator_;
@@ -946,7 +949,7 @@ Blockly.Field.prototype.setTooltip = function(newTip) {
/**
* Returns the tooltip text for this field.
* @returns {string} The tooltip text for this field.
* @return {string} The tooltip text for this field.
*/
Blockly.Field.prototype.getTooltip = function() {
var clickTarget = this.getClickTarget_();
@@ -1041,8 +1044,8 @@ Blockly.Field.prototype.onShortcut = function(_shortcut) {
};
/**
* Add the cursor svg to this fields svg group.
* @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
* Add the cursor SVG to this fields SVG group.
* @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the
* field group.
* @package
*/
@@ -1057,8 +1060,8 @@ Blockly.Field.prototype.setCursorSvg = function(cursorSvg) {
};
/**
* Add the marker svg to this fields svg group.
* @param {SVGElement} markerSvg The svg root of the marker to be added to the
* Add the marker SVG to this fields SVG group.
* @param {SVGElement} markerSvg The SVG root of the marker to be added to the
* field group.
* @package
*/
+18 -9
View File
@@ -18,10 +18,12 @@ goog.require('Blockly.DropDownDiv');
goog.require('Blockly.fieldRegistry');
goog.require('Blockly.FieldTextInput');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.KeyCodes');
goog.require('Blockly.utils.math');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.Svg');
goog.require('Blockly.utils.userAgent');
goog.require('Blockly.WidgetDiv');
/**
@@ -75,15 +77,22 @@ Blockly.FieldAngle = function(opt_value, opt_validator, opt_config) {
Blockly.FieldAngle.superClass_.constructor.call(
this, opt_value, opt_validator, opt_config);
/**
* The angle picker's SVG element.
* @type {?SVGElement}
* @private
*/
this.editor_ = null;
/**
* The angle picker's gauge path depending on the value.
* @type {SVGElement}
* @type {?SVGElement}
*/
this.gauge_ = null;
/**
* The angle picker's line drawn representing the value's angle.
* @type {SVGElement}
* @type {?SVGElement}
*/
this.line_ = null;
@@ -181,7 +190,8 @@ Blockly.FieldAngle.RADIUS = Blockly.FieldAngle.HALF - 1;
/**
* Configure the field based on the given map of options.
* @param {!Object} config A map of options to configure the field based on.
* @private
* @protected
* @override
*/
Blockly.FieldAngle.prototype.configure_ = function(config) {
Blockly.FieldAngle.superClass_.configure_.call(this, config);
@@ -246,7 +256,7 @@ Blockly.FieldAngle.prototype.initView = function() {
/**
* Updates the graph when the field rerenders.
* @private
* @protected
* @override
*/
Blockly.FieldAngle.prototype.render_ = function() {
@@ -268,8 +278,8 @@ Blockly.FieldAngle.prototype.showEditor_ = function(opt_e) {
Blockly.utils.userAgent.IPAD;
Blockly.FieldAngle.superClass_.showEditor_.call(this, opt_e, noFocus);
var editor = this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(editor);
this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);
Blockly.DropDownDiv.setColour(this.sourceBlock_.style.colourPrimary,
this.sourceBlock_.style.colourTertiary);
@@ -282,7 +292,6 @@ Blockly.FieldAngle.prototype.showEditor_ = function(opt_e) {
/**
* Create the angle dropdown editor.
* @return {!SVGElement} The newly created angle picker.
* @private
*/
Blockly.FieldAngle.prototype.dropdownCreate_ = function() {
@@ -340,11 +349,11 @@ Blockly.FieldAngle.prototype.dropdownCreate_ = function() {
circle, 'click', this, this.onMouseMove_, true, true);
this.moveSurfaceWrapper_ = Blockly.browserEvents.conditionalBind(
circle, 'mousemove', this, this.onMouseMove_, true, true);
return svg;
this.editor_ = svg;
};
/**
* Disposes of events and dom-references belonging to the angle editor.
* Disposes of events and DOM-references belonging to the angle editor.
* @private
*/
Blockly.FieldAngle.prototype.dropdownDispose_ = function() {
+2 -1
View File
@@ -88,7 +88,8 @@ Blockly.FieldCheckbox.prototype.CURSOR = 'default';
/**
* Configure the field based on the given map of options.
* @param {!Object} config A map of options to configure the field based on.
* @private
* @protected
* @override
*/
Blockly.FieldCheckbox.prototype.configure_ = function(config) {
Blockly.FieldCheckbox.superClass_.configure_.call(this, config);
+13 -13
View File
@@ -47,7 +47,7 @@ Blockly.FieldColour = function(opt_value, opt_validator, opt_config) {
/**
* The field's colour picker element.
* @type {Element}
* @type {?Element}
* @private
*/
this.picker_ = null;
@@ -130,14 +130,14 @@ Blockly.FieldColour.prototype.isDirty_ = false;
/**
* Array of colours used by this field. If null, use the global list.
* @type {Array.<string>}
* @type {Array<string>}
* @private
*/
Blockly.FieldColour.prototype.colours_ = null;
/**
* Array of colour tooltips used by this field. If null, use the global list.
* @type {Array.<string>}
* @type {Array<string>}
* @private
*/
Blockly.FieldColour.prototype.titles_ = null;
@@ -153,7 +153,8 @@ Blockly.FieldColour.prototype.columns_ = 0;
/**
* Configure the field based on the given map of options.
* @param {!Object} config A map of options to configure the field based on.
* @private
* @protected
* @override
*/
Blockly.FieldColour.prototype.configure_ = function(config) {
Blockly.FieldColour.superClass_.configure_.call(this, config);
@@ -242,7 +243,7 @@ Blockly.FieldColour.prototype.getText = function() {
* An array of colour strings for the palette.
* Copied from goog.ui.ColorPicker.SIMPLE_GRID_COLORS
* All colour pickers use this unless overridden with setColours.
* @type {!Array.<string>}
* @type {!Array<string>}
*/
Blockly.FieldColour.COLOURS = [
// grays
@@ -278,7 +279,7 @@ Blockly.FieldColour.prototype.DEFAULT_VALUE = Blockly.FieldColour.COLOURS[0];
* An array of tooltip strings for the palette. If not the same length as
* COLOURS, the colour's hex code will be used for any missing titles.
* All colour pickers use this unless overridden with setColours.
* @type {!Array.<string>}
* @type {!Array<string>}
*/
Blockly.FieldColour.TITLES = [];
@@ -290,9 +291,9 @@ Blockly.FieldColour.COLUMNS = 7;
/**
* Set a custom colour grid for this field.
* @param {Array.<string>} colours Array of colours for this block,
* @param {Array<string>} colours Array of colours for this block,
* or null to use default (Blockly.FieldColour.COLOURS).
* @param {Array.<string>=} opt_titles Optional array of colour tooltips,
* @param {Array<string>=} opt_titles Optional array of colour tooltips,
* or null to use default (Blockly.FieldColour.TITLES).
* @return {!Blockly.FieldColour} Returns itself (for method chaining).
*/
@@ -320,7 +321,7 @@ Blockly.FieldColour.prototype.setColumns = function(columns) {
* @protected
*/
Blockly.FieldColour.prototype.showEditor_ = function() {
this.picker_ = this.dropdownCreate_();
this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(this.picker_);
Blockly.DropDownDiv.showPositionedByField(
@@ -472,7 +473,7 @@ Blockly.FieldColour.prototype.onMouseLeave_ = function() {
/**
* Returns the currently highlighted item (if any).
* @return {HTMLElement} Highlighted item (null if none).
* @return {?HTMLElement} Highlighted item (null if none).
* @private
*/
Blockly.FieldColour.prototype.getHighlighted_ = function() {
@@ -511,7 +512,6 @@ Blockly.FieldColour.prototype.setHighlightedCell_ = function(cell, index) {
/**
* Create a colour picker dropdown editor.
* @return {!Element} The newly created colour picker.
* @private
*/
Blockly.FieldColour.prototype.dropdownCreate_ = function() {
@@ -567,11 +567,11 @@ Blockly.FieldColour.prototype.dropdownCreate_ = function() {
this.onKeyDownWrapper_ = Blockly.browserEvents.conditionalBind(
table, 'keydown', this, this.onKeyDown_);
return table;
this.picker_ = table;
};
/**
* Disposes of events and dom-references belonging to the colour editor.
* Disposes of events and DOM-references belonging to the colour editor.
* @private
*/
Blockly.FieldColour.prototype.dropdownDispose_ = function() {
+19 -20
View File
@@ -14,6 +14,7 @@
goog.provide('Blockly.FieldDropdown');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Field');
goog.require('Blockly.fieldRegistry');
goog.require('Blockly.Menu');
@@ -30,7 +31,7 @@ goog.require('Blockly.utils.userAgent');
/**
* Class for an editable dropdown field.
* @param {(!Array.<!Array>|!Function)} menuGenerator A non-empty array of
* @param {(!Array<!Array>|!Function)} menuGenerator A non-empty array of
* options for a dropdown list, or a function which generates these options.
* @param {Function=} opt_validator A function that is called to validate
* changes to the field's value. Takes in a language-neutral dropdown
@@ -51,15 +52,15 @@ Blockly.FieldDropdown = function(menuGenerator, opt_validator, opt_config) {
/**
* An array of options for a dropdown list,
* or a function which generates these options.
* @type {(!Array.<!Array>|
* !function(this:Blockly.FieldDropdown): !Array.<!Array>)}
* @type {(!Array<!Array>|
* !function(this:Blockly.FieldDropdown): !Array<!Array>)}
* @protected
*/
this.menuGenerator_ = menuGenerator;
/**
* A cache of the most recently generated options.
* @type {Array.<!Array.<string>>}
* @type {Array<!Array<string>>}
* @private
*/
this.generatedOptions_ = null;
@@ -94,35 +95,35 @@ Blockly.FieldDropdown = function(menuGenerator, opt_validator, opt_config) {
/**
* A reference to the currently selected menu item.
* @type {Blockly.MenuItem}
* @type {?Blockly.MenuItem}
* @private
*/
this.selectedMenuItem_ = null;
/**
* The dropdown menu.
* @type {Blockly.Menu}
* @type {?Blockly.Menu}
* @protected
*/
this.menu_ = null;
/**
* SVG image element if currently selected option is an image, or null.
* @type {SVGImageElement}
* @type {?SVGImageElement}
* @private
*/
this.imageElement_ = null;
/**
* Tspan based arrow element.
* @type {SVGTSpanElement}
* @type {?SVGTSpanElement}
* @private
*/
this.arrow_ = null;
/**
* SVG based arrow element.
* @type {SVGElement}
* @type {?SVGElement}
* @private
*/
this.svgArrow_ = null;
@@ -287,7 +288,7 @@ Blockly.FieldDropdown.prototype.createSVGArrow_ = function() {
* @protected
*/
Blockly.FieldDropdown.prototype.showEditor_ = function(opt_e) {
this.menu_ = this.dropdownCreate_();
this.dropdownCreate_();
if (opt_e && typeof opt_e.clientX === 'number') {
this.menu_.openingCoords =
new Blockly.utils.Coordinate(opt_e.clientX, opt_e.clientY);
@@ -326,18 +327,18 @@ Blockly.FieldDropdown.prototype.showEditor_ = function(opt_e) {
/**
* Create the dropdown editor.
* @return {!Blockly.Menu} The newly created dropdown menu.
* @private
*/
Blockly.FieldDropdown.prototype.dropdownCreate_ = function() {
var menu = new Blockly.Menu();
menu.setRole(Blockly.utils.aria.Role.LISTBOX);
this.menu_ = menu;
var options = this.getOptions(false);
this.selectedMenuItem_ = null;
for (var i = 0; i < options.length; i++) {
var content = options[i][0]; // Human-readable text or image.
var value = options[i][1]; // Language-neutral value.
var content = options[i][0]; // Human-readable text or image.
var value = options[i][1]; // Language-neutral value.
if (typeof content == 'object') {
// An image, not text.
var image = new Image(content['width'], content['height']);
@@ -356,12 +357,10 @@ Blockly.FieldDropdown.prototype.dropdownCreate_ = function() {
}
menuItem.onAction(this.handleMenuActionEvent_, this);
}
return menu;
};
/**
* Disposes of events and dom-references belonging to the dropdown editor.
* Disposes of events and DOM-references belonging to the dropdown editor.
* @private
*/
Blockly.FieldDropdown.prototype.dropdownDispose_ = function() {
@@ -448,11 +447,11 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() {
/**
* Use the calculated prefix and suffix lengths to trim all of the options in
* the given array.
* @param {!Array.<!Array>} options Array of option tuples:
* @param {!Array<!Array>} options Array of option tuples:
* (human-readable text or image, language-neutral name).
* @param {number} prefixLength The length of the common prefix.
* @param {number} suffixLength The length of the common suffix
* @return {!Array.<!Array>} A new array with all of the option text trimmed.
* @return {!Array<!Array>} A new array with all of the option text trimmed.
*/
Blockly.FieldDropdown.applyTrim_ = function(options,
prefixLength, suffixLength) {
@@ -479,7 +478,7 @@ Blockly.FieldDropdown.prototype.isOptionListDynamic = function() {
* Return a list of the options for this dropdown.
* @param {boolean=} opt_useCache For dynamic options, whether or not to use the
* cached options or to re-generate them.
* @return {!Array.<!Array>} A non-empty array of option tuples:
* @return {!Array<!Array>} A non-empty array of option tuples:
* (human-readable text or image, language-neutral name).
* @throws {TypeError} If generated options are incorrectly structured.
*/
@@ -491,7 +490,7 @@ Blockly.FieldDropdown.prototype.getOptions = function(opt_useCache) {
}
return this.generatedOptions_;
}
return /** @type {!Array.<!Array.<string>>} */ (this.menuGenerator_);
return /** @type {!Array<!Array<string>>} */ (this.menuGenerator_);
};
/**
+2 -1
View File
@@ -164,7 +164,8 @@ Blockly.FieldImage.prototype.isDirty_ = false;
/**
* Configure the field based on the given map of options.
* @param {!Object} config A map of options to configure the field based on.
* @private
* @protected
* @override
*/
Blockly.FieldImage.prototype.configure_ = function(config) {
Blockly.FieldImage.superClass_.configure_.call(this, config);
+2 -2
View File
@@ -109,8 +109,8 @@ Blockly.FieldLabel.prototype.doClassValidation_ = function(opt_newValue) {
};
/**
* Set the css class applied to the field's textElement_.
* @param {?string} cssClass The new css class name, or null to remove.
* Set the CSS class applied to the field's textElement_.
* @param {?string} cssClass The new CSS class name, or null to remove.
*/
Blockly.FieldLabel.prototype.setClass = function(cssClass) {
if (this.textElement_) {
+8 -4
View File
@@ -15,6 +15,8 @@
goog.provide('Blockly.FieldMultilineInput');
goog.require('Blockly.Css');
goog.require('Blockly.Field');
goog.require('Blockly.fieldRegistry');
goog.require('Blockly.FieldTextInput');
goog.require('Blockly.utils');
goog.require('Blockly.utils.aria');
@@ -23,6 +25,7 @@ goog.require('Blockly.utils.KeyCodes');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.Svg');
goog.require('Blockly.utils.userAgent');
goog.require('Blockly.WidgetDiv');
/**
@@ -59,7 +62,7 @@ Blockly.FieldMultilineInput = function(opt_value, opt_validator, opt_config) {
this.maxLines_ = Infinity;
/**
* Whether Y overflow is currently occuring.
* Whether Y overflow is currently occurring.
* @type {boolean}
* @protected
*/
@@ -97,8 +100,8 @@ Blockly.FieldMultilineInput.fromJson = function(options) {
* @package
*/
Blockly.FieldMultilineInput.prototype.toXml = function(fieldElement) {
// Replace '\n' characters with html-escaped equivalent '&#10'. This is
// needed so the plain-text representation of the xml produced by
// Replace '\n' characters with HTML-escaped equivalent '&#10'. This is
// needed so the plain-text representation of the XML produced by
// `Blockly.Xml.domToText` will appear on a single line (this is a limitation
// of the plain-text format).
fieldElement.textContent = this.getValue().replace(/\n/g, '&#10;');
@@ -132,7 +135,8 @@ Blockly.FieldMultilineInput.prototype.initView = function() {
* Get the text from this field as displayed on screen. May differ from getText
* due to ellipsis, and other formatting.
* @return {string} Currently displayed text.
* @private
* @protected
* @override
*/
Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() {
var textLines = this.getText();
+9 -11
View File
@@ -105,7 +105,8 @@ Blockly.FieldNumber.prototype.SERIALIZABLE = true;
/**
* Configure the field based on the given map of options.
* @param {!Object} config A map of options to configure the field based on.
* @private
* @protected
* @override
*/
Blockly.FieldNumber.prototype.configure_ = function(config) {
Blockly.FieldNumber.superClass_.configure_.call(this, config);
@@ -221,17 +222,14 @@ Blockly.FieldNumber.prototype.setPrecision = function(precision) {
* @private
*/
Blockly.FieldNumber.prototype.setPrecisionInternal_ = function(precision) {
if (precision == null) {
// Number(precision) would also be 0, but set explicitly to be clear.
this.precision_ = 0;
} else {
precision = Number(precision);
if (!isNaN(precision)) {
this.precision_ = precision;
}
this.precision_ = Number(precision) || 0;
var precisionString = String(this.precision_);
if (precisionString.indexOf('e') != -1) {
// String() is fast. But it turns .0000001 into '1e-7'.
// Use the much slower toLocaleString to access all the digits.
precisionString =
this.precision_.toLocaleString('en-US', {maximumFractionDigits: 20});
}
var precisionString = this.precision_.toLocaleString("en-US", {maximumFractionDigits: 20});
var decimalIndex = precisionString.indexOf('.');
if (decimalIndex == -1) {
// If the precision is 0 (float) allow any number of decimals,
+1 -1
View File
@@ -49,7 +49,7 @@ Blockly.fieldRegistry.unregister = function(type) {
* Blockly.fieldRegistry.register.
* @param {!Object} options A JSON object with a type and options specific
* to the field type.
* @return {Blockly.Field} The new field instance or null if a field wasn't
* @return {?Blockly.Field} The new field instance or null if a field wasn't
* found with the given type name
* @package
*/
+15 -13
View File
@@ -13,6 +13,7 @@
goog.provide('Blockly.FieldTextInput');
goog.require('Blockly.browserEvents');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BlockChange');
@@ -26,6 +27,7 @@ goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.KeyCodes');
goog.require('Blockly.utils.object');
goog.require('Blockly.utils.userAgent');
goog.require('Blockly.WidgetDiv');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.WorkspaceSvg');
@@ -387,7 +389,7 @@ Blockly.FieldTextInput.prototype.widgetCreate_ = function() {
/**
* Closes the editor, saves the results, and disposes of any events or
* dom-references belonging to the editor.
* DOM-references belonging to the editor.
* @protected
*/
Blockly.FieldTextInput.prototype.widgetDispose_ = function() {
@@ -454,7 +456,7 @@ Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) {
Blockly.WidgetDiv.hide();
Blockly.DropDownDiv.hideWithoutAnimation();
} else if (e.keyCode == Blockly.utils.KeyCodes.ESC) {
this.htmlInput_.value = this.htmlInput_.defaultValue;
this.setValue(this.htmlInput_.untypedDefaultValue_);
Blockly.WidgetDiv.hide();
Blockly.DropDownDiv.hideWithoutAnimation();
} else if (e.keyCode == Blockly.utils.KeyCodes.TAB) {
@@ -488,8 +490,8 @@ Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(_e) {
};
/**
* Set the html input value and the field's internal value. The difference
* between this and ``setValue`` is that this also updates the html input
* Set the HTML input value and the field's internal value. The difference
* between this and ``setValue`` is that this also updates the HTML input
* value whilst editing.
* @param {*} newValue New value.
* @protected
@@ -536,28 +538,28 @@ Blockly.FieldTextInput.prototype.isTabNavigable = function() {
/**
* Use the `getText_` developer hook to override the field's text representation.
* When we're currently editing, return the current html value instead.
* When we're currently editing, return the current HTML value instead.
* Otherwise, return null which tells the field to use the default behaviour
* (which is a string cast of the field's value).
* @return {?string} The html value if we're editing, otherwise null.
* @return {?string} The HTML value if we're editing, otherwise null.
* @protected
* @override
*/
Blockly.FieldTextInput.prototype.getText_ = function() {
if (this.isBeingEdited_ && this.htmlInput_) {
// We are currently editing, return the html input value instead.
// We are currently editing, return the HTML input value instead.
return this.htmlInput_.value;
}
return null;
};
/**
* Transform the provided value into a text to show in the html input.
* Override this method if the field's html input representation is different
* Transform the provided value into a text to show in the HTML input.
* Override this method if the field's HTML input representation is different
* than the field's value. This should be coupled with an override of
* `getValueFromEditorText_`.
* @param {*} value The value stored in this field.
* @return {string} The text to show on the html input.
* @return {string} The text to show on the HTML input.
* @protected
*/
Blockly.FieldTextInput.prototype.getEditorText_ = function(value) {
@@ -565,12 +567,12 @@ Blockly.FieldTextInput.prototype.getEditorText_ = function(value) {
};
/**
* Transform the text received from the html input into a value to store
* Transform the text received from the HTML input into a value to store
* in this field.
* Override this method if the field's html input representation is different
* Override this method if the field's HTML input representation is different
* than the field's value. This should be coupled with an override of
* `getEditorText_`.
* @param {string} text Text received from the html input.
* @param {string} text Text received from the HTML input.
* @return {*} The value to store.
* @protected
*/
+13 -13
View File
@@ -39,7 +39,7 @@ goog.requireType('Blockly.MenuItem');
* @param {Function=} opt_validator A function that is called to validate
* changes to the field's value. Takes in a variable ID & returns a
* validated variable ID, or null to abort the change.
* @param {Array.<string>=} opt_variableTypes A list of the types of variables
* @param {Array<string>=} opt_variableTypes A list of the types of variables
* to include in the dropdown.
* @param {string=} opt_defaultType The type of variable to create if this
* field's value is not explicitly set. Defaults to ''.
@@ -58,8 +58,8 @@ Blockly.FieldVariable = function(varName, opt_validator, opt_variableTypes,
/**
* An array of options for a dropdown list,
* or a function which generates these options.
* @type {(!Array.<!Array>|
* !function(this:Blockly.FieldDropdown): !Array.<!Array>)}
* @type {(!Array<!Array>|
* !function(this:Blockly.FieldDropdown): !Array<!Array>)}
* @protected
*/
this.menuGenerator_ = Blockly.FieldVariable.dropdownCreate;
@@ -129,7 +129,7 @@ Blockly.FieldVariable.prototype.configure_ = function(config) {
*/
Blockly.FieldVariable.prototype.initModel = function() {
if (this.variable_) {
return; // Initialization already happened.
return; // Initialization already happened.
}
var variable = Blockly.Variables.getOrCreateVariablePackage(
this.sourceBlock_.workspace, null,
@@ -225,7 +225,7 @@ Blockly.FieldVariable.prototype.getText = function() {
* Get the variable model for the selected variable.
* Not guaranteed to be in the variable map on the workspace (e.g. if accessed
* after the variable has been deleted).
* @return {Blockly.VariableModel} The selected variable, or null if none was
* @return {?Blockly.VariableModel} The selected variable, or null if none was
* selected.
* @package
*/
@@ -238,7 +238,7 @@ Blockly.FieldVariable.prototype.getVariable = function() {
* Returns null if the variable is not set, because validators should not
* run on the initial setValue call, because the field won't be attached to
* a block and workspace at that point.
* @return {Function} Validation function, or null.
* @return {?Function} Validation function, or null.
*/
Blockly.FieldVariable.prototype.getValidator = function() {
// Validators shouldn't operate on the initial setValue call.
@@ -251,9 +251,9 @@ Blockly.FieldVariable.prototype.getValidator = function() {
};
/**
* Ensure that the id belongs to a valid variable of an allowed type.
* @param {*=} opt_newValue The id of the new variable to set.
* @return {?string} The validated id, or null if invalid.
* Ensure that the ID belongs to a valid variable of an allowed type.
* @param {*=} opt_newValue The ID of the new variable to set.
* @return {?string} The validated ID, or null if invalid.
* @protected
*/
Blockly.FieldVariable.prototype.doClassValidation_ = function(opt_newValue) {
@@ -300,7 +300,7 @@ Blockly.FieldVariable.prototype.doValueUpdate_ = function(newId) {
Blockly.FieldVariable.prototype.typeIsAllowed_ = function(type) {
var typeList = this.getVariableTypes_();
if (!typeList) {
return true; // If it's null, all types are valid.
return true; // If it's null, all types are valid.
}
for (var i = 0; i < typeList.length; i++) {
if (type == typeList[i]) {
@@ -312,7 +312,7 @@ Blockly.FieldVariable.prototype.typeIsAllowed_ = function(type) {
/**
* Return a list of variable types to include in the dropdown.
* @return {!Array.<string>} Array of variable types.
* @return {!Array<string>} Array of variable types.
* @throws {Error} if variableTypes is an empty array.
* @private
*/
@@ -338,7 +338,7 @@ Blockly.FieldVariable.prototype.getVariableTypes_ = function() {
/**
* Parse the optional arguments representing the allowed variable types and the
* default variable type.
* @param {Array.<string>=} opt_variableTypes A list of the types of variables
* @param {Array<string>=} opt_variableTypes A list of the types of variables
* to include in the dropdown. If null or undefined, variables of all types
* will be displayed in the dropdown.
* @param {string=} opt_defaultType The type of the variable to create if this
@@ -388,7 +388,7 @@ Blockly.FieldVariable.prototype.refreshVariableName = function() {
/**
* Return a sorted list of variable names for variable dropdown menus.
* Include a special option at the end for creating a new variable name.
* @return {!Array.<!Array>} Array of variable names/id tuples.
* @return {!Array<!Array>} Array of variable names/id tuples.
* @this {Blockly.FieldVariable}
*/
Blockly.FieldVariable.dropdownCreate = function() {
+46 -20
View File
@@ -16,6 +16,8 @@ goog.require('Blockly.Block');
/** @suppress {extraRequire} */
goog.require('Blockly.blockRendering');
goog.require('Blockly.browserEvents');
goog.require('Blockly.ComponentManager');
goog.require('Blockly.DeleteArea');
goog.require('Blockly.Events');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BlockCreate');
@@ -24,6 +26,7 @@ goog.require('Blockly.Events.VarCreate');
goog.require('Blockly.FlyoutMetricsManager');
/** @suppress {extraRequire} */
goog.require('Blockly.Gesture');
goog.require('Blockly.IFlyout');
goog.require('Blockly.ScrollbarPair');
goog.require('Blockly.Tooltip');
/** @suppress {extraRequire} */
@@ -39,8 +42,6 @@ goog.require('Blockly.Xml');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.FlyoutButton');
goog.requireType('Blockly.IDeleteArea');
goog.requireType('Blockly.IFlyout');
goog.requireType('Blockly.Options');
goog.requireType('Blockly.utils.Rect');
@@ -51,10 +52,11 @@ goog.requireType('Blockly.utils.Rect');
* workspace.
* @constructor
* @abstract
* @implements {Blockly.IDeleteArea}
* @implements {Blockly.IFlyout}
* @extends {Blockly.DeleteArea}
*/
Blockly.Flyout = function(workspaceOptions) {
Blockly.Flyout.superClass_.constructor.call(this);
workspaceOptions.setMetrics = this.setMetrics_.bind(this);
/**
@@ -69,6 +71,13 @@ Blockly.Flyout = function(workspaceOptions) {
// Keep the workspace visibility consistent with the flyout's visibility.
this.workspace_.setVisible(this.isVisible_);
/**
* The unique id for this component that is used to register with the
* ComponentManager.
* @type {string}
*/
this.id = Blockly.utils.genUid();
/**
* Is RTL vs LTR.
* @type {boolean}
@@ -91,7 +100,7 @@ Blockly.Flyout = function(workspaceOptions) {
/**
* Opaque data that can be passed to Blockly.unbindEvent_.
* @type {!Array.<!Array>}
* @type {!Array<!Array>}
* @private
*/
this.eventWrappers_ = [];
@@ -99,28 +108,28 @@ Blockly.Flyout = function(workspaceOptions) {
/**
* List of background mats that lurk behind each block to catch clicks
* landing in the blocks' lakes and bays.
* @type {!Array.<!SVGElement>}
* @type {!Array<!SVGElement>}
* @private
*/
this.mats_ = [];
/**
* List of visible buttons.
* @type {!Array.<!Blockly.FlyoutButton>}
* @type {!Array<!Blockly.FlyoutButton>}
* @protected
*/
this.buttons_ = [];
/**
* List of event listeners.
* @type {!Array.<!Array>}
* @type {!Array<!Array>}
* @private
*/
this.listeners_ = [];
/**
* List of blocks that should always be disabled.
* @type {!Array.<!Blockly.Block>}
* @type {!Array<!Blockly.Block>}
* @private
*/
this.permanentlyDisabled_ = [];
@@ -140,6 +149,7 @@ Blockly.Flyout = function(workspaceOptions) {
*/
this.targetWorkspace = null;
};
Blockly.utils.object.inherits(Blockly.Flyout, Blockly.DeleteArea);
/**
* Does the flyout automatically close when a block is created?
@@ -196,7 +206,7 @@ Blockly.Flyout.prototype.GAP_Y = Blockly.Flyout.prototype.MARGIN * 3;
* @type {number}
* @const
*/
Blockly.Flyout.prototype.SCROLLBAR_PADDING = 2;
Blockly.Flyout.prototype.SCROLLBAR_MARGIN = 2.5;
/**
* Width of flyout.
@@ -232,8 +242,8 @@ Blockly.Flyout.prototype.dragAngleRange_ = 70;
/**
* Creates the flyout's DOM. Only needs to be called once. The flyout can
* either exist as its own svg element or be a g element nested inside a
* separate svg element.
* either exist as its own SVG element or be a g element nested inside a
* separate SVG element.
* @param {string|
* !Blockly.utils.Svg<!SVGSVGElement>|
* !Blockly.utils.Svg<!SVGGElement>} tagName The type of tag to
@@ -273,7 +283,7 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) {
this.workspace_.scrollbar = new Blockly.ScrollbarPair(
this.workspace_, this.horizontalLayout, !this.horizontalLayout,
'blocklyFlyoutScrollbar');
'blocklyFlyoutScrollbar', this.SCROLLBAR_MARGIN);
this.hide();
@@ -300,6 +310,15 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) {
this.workspace_.setVariableMap(this.targetWorkspace.getVariableMap());
this.workspace_.createPotentialVariableMap();
targetWorkspace.getComponentManager().addComponent({
component: this,
weight: 1,
capabilities: [
Blockly.ComponentManager.Capability.DELETE_AREA,
Blockly.ComponentManager.Capability.DRAG_TARGET
]
});
};
/**
@@ -309,6 +328,7 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) {
*/
Blockly.Flyout.prototype.dispose = function() {
this.hide();
this.workspace_.getComponentManager().removeComponent(this.id);
Blockly.browserEvents.unbind(this.eventWrappers_);
if (this.filterWrapper_) {
this.targetWorkspace.removeChangeListener(this.filterWrapper_);
@@ -380,6 +400,11 @@ Blockly.Flyout.prototype.setVisible = function(visible) {
this.isVisible_ = visible;
if (visibilityChanged) {
if (!this.autoClose) {
// Auto-close flyouts are ignored as drag targets, so only non auto-close
// flyouts need to have their drag target updated.
this.workspace_.recordDragTargets();
}
this.updateDisplay_();
}
};
@@ -498,7 +523,7 @@ Blockly.Flyout.prototype.show = function(flyoutDef) {
// Parse the Array, Node or NodeList into a a list of flyout items.
var parsedContent = Blockly.utils.toolbox.convertFlyoutDefToJsonArray(flyoutDef);
var flyoutInfo =
/** @type {{contents:!Array.<!Object>, gaps:!Array.<number>}} */ (
/** @type {{contents:!Array<!Object>, gaps:!Array<number>}} */ (
this.createFlyoutInfo_(parsedContent));
this.layout_(flyoutInfo.contents, flyoutInfo.gaps);
@@ -537,7 +562,7 @@ Blockly.Flyout.prototype.show = function(flyoutDef) {
* the flyout.
* @param {!Blockly.utils.toolbox.FlyoutItemInfoArray} parsedContent The array
* of objects to show in the flyout.
* @return {{contents:Array.<Object>, gaps:Array.<number>}} The list of contents
* @return {{contents:Array<Object>, gaps:Array<number>}} The list of contents
* and gaps needed to lay out the flyout.
* @private
*/
@@ -594,7 +619,7 @@ Blockly.Flyout.prototype.createFlyoutInfo_ = function(parsedContent) {
/**
* Gets the flyout definition for the dynamic category.
* @param {string} categoryName The name of the dynamic category.
* @return {!Array.<!Element>} The array of flyout items.
* @return {!Array<!Element>} The array of flyout items.
* @private
*/
Blockly.Flyout.prototype.getDynamicCategoryContents_ = function(categoryName) {
@@ -684,7 +709,7 @@ Blockly.Flyout.prototype.getBlockXml_ = function(blockInfo) {
* Add the necessary gap in the flyout for a separator.
* @param {!Blockly.utils.toolbox.SeparatorInfo} sepInfo The object holding
* information about a separator.
* @param {!Array.<number>} gaps The list gaps between items in the flyout.
* @param {!Array<number>} gaps The list gaps between items in the flyout.
* @param {number} defaultGap The default gap between the button and next element.
* @private
*/
@@ -1018,8 +1043,9 @@ Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) {
};
/**
* Return the deletion rectangle for this flyout in viewport coordinates.
* @return {Blockly.utils.Rect} Rectangle in which to delete.
* Returns the bounding rectangle of the drag target area in pixel units
* relative to viewport.
* @return {Blockly.utils.Rect} The component's bounding box.
*/
Blockly.Flyout.prototype.getClientRect;
@@ -1051,8 +1077,8 @@ Blockly.Flyout.prototype.setMetrics_;
/**
* Lay out the blocks in the flyout.
* @param {!Array.<!Object>} contents The blocks and buttons to lay out.
* @param {!Array.<number>} gaps The visible gaps between blocks.
* @param {!Array<!Object>} contents The blocks and buttons to lay out.
* @param {!Array<number>} gaps The visible gaps between blocks.
* @protected
*/
Blockly.Flyout.prototype.layout_;
+1
View File
@@ -17,6 +17,7 @@ goog.require('Blockly.Css');
goog.require('Blockly.utils');
goog.require('Blockly.utils.Coordinate');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.style');
goog.require('Blockly.utils.Svg');
goog.requireType('Blockly.utils.toolbox');
+11 -5
View File
@@ -16,6 +16,7 @@ goog.provide('Blockly.HorizontalFlyout');
goog.require('Blockly.Block');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Flyout');
goog.require('Blockly.registry');
goog.require('Blockly.Scrollbar');
@@ -230,8 +231,8 @@ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
/**
* Lay out the blocks in the flyout.
* @param {!Array.<!Object>} contents The blocks and buttons to lay out.
* @param {!Array.<number>} gaps The visible gaps between blocks.
* @param {!Array<!Object>} contents The blocks and buttons to lay out.
* @param {!Array<number>} gaps The visible gaps between blocks.
* @protected
*/
Blockly.HorizontalFlyout.prototype.layout_ = function(contents, gaps) {
@@ -303,11 +304,15 @@ Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function(
};
/**
* Return the deletion rectangle for this flyout in viewport coordinates.
* @return {Blockly.utils.Rect} Rectangle in which to delete.
* Returns the bounding rectangle of the drag target area in pixel units
* relative to viewport.
* @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
* target area should be ignored.
*/
Blockly.HorizontalFlyout.prototype.getClientRect = function() {
if (!this.svgGroup_) {
if (!this.svgGroup_ || this.autoClose || !this.isVisible()) {
// The bounding rectangle won't compute correctly if the flyout is closed
// and auto-close flyouts aren't valid drag targets (or delete areas).
return null;
}
@@ -362,6 +367,7 @@ Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() {
// Record the height for workspace metrics and .position.
this.height_ = flyoutHeight;
this.position();
this.targetWorkspace.recordDragTargets();
}
};
+11 -5
View File
@@ -16,6 +16,7 @@ goog.provide('Blockly.VerticalFlyout');
goog.require('Blockly.Block');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.DropDownDiv');
goog.require('Blockly.Flyout');
goog.require('Blockly.registry');
goog.require('Blockly.Scrollbar');
@@ -221,8 +222,8 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) {
/**
* Lay out the blocks in the flyout.
* @param {!Array.<!Object>} contents The blocks and buttons to lay out.
* @param {!Array.<number>} gaps The visible gaps between blocks.
* @param {!Array<!Object>} contents The blocks and buttons to lay out.
* @param {!Array<number>} gaps The visible gaps between blocks.
* @protected
*/
Blockly.VerticalFlyout.prototype.layout_ = function(contents, gaps) {
@@ -286,11 +287,15 @@ Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = function(
};
/**
* Return the deletion rectangle for this flyout in viewport coordinates.
* @return {Blockly.utils.Rect} Rectangle in which to delete.
* Returns the bounding rectangle of the drag target area in pixel units
* relative to viewport.
* @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
* target area should be ignored.
*/
Blockly.VerticalFlyout.prototype.getClientRect = function() {
if (!this.svgGroup_) {
if (!this.svgGroup_ || this.autoClose || !this.isVisible()) {
// The bounding rectangle won't compute correctly if the flyout is closed
// and auto-close flyouts aren't valid drag targets (or delete areas).
return null;
}
@@ -370,6 +375,7 @@ Blockly.VerticalFlyout.prototype.reflowInternal_ = function() {
// Record the width for workspace metrics and .position.
this.width_ = flyoutWidth;
this.position();
this.targetWorkspace.recordDragTargets();
}
};
+55 -22
View File
@@ -16,6 +16,7 @@ goog.provide('Blockly.Generator');
goog.require('Blockly.Block');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
goog.require('Blockly.utils.deprecation');
goog.requireType('Blockly.Names');
goog.requireType('Blockly.Workspace');
@@ -32,11 +33,6 @@ Blockly.Generator = function(name) {
new RegExp(this.FUNCTION_NAME_PLACEHOLDER_, 'g');
};
/**
* Category to separate generated function names from variables and procedures.
*/
Blockly.Generator.NAME_TYPE = 'generated_function';
/**
* Arbitrary code to inject into locations that risk causing infinite loops.
* Any instances of '%1' will be replaced by the block ID that failed.
@@ -77,7 +73,7 @@ Blockly.Generator.prototype.COMMENT_WRAP = 60;
/**
* List of outer-inner pairings that do NOT require parentheses.
* @type {!Array.<!Array.<number>>}
* @type {!Array<!Array<number>>}
*/
Blockly.Generator.prototype.ORDER_OVERRIDES = [];
@@ -92,7 +88,7 @@ Blockly.Generator.prototype.isInitialized = null;
/**
* Generate code for all blocks in the workspace to the specified language.
* @param {Blockly.Workspace} workspace Workspace to generate code from.
* @param {!Blockly.Workspace=} workspace Workspace to generate code from.
* @return {string} Generated code.
*/
Blockly.Generator.prototype.workspaceToCode = function(workspace) {
@@ -199,7 +195,7 @@ Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) {
var func = this[block.type];
if (typeof func != 'function') {
throw Error('Language "' + this.name_ + '" does not know how to generate ' +
' code for block type "' + block.type + '".');
'code for block type "' + block.type + '".');
}
// First argument to func.call is the value of 'this' in the generator.
// Prior to 24 September 2013 'this' was the only way to access the block.
@@ -223,9 +219,8 @@ Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) {
} else if (code === null) {
// Block has handled code generation itself.
return '';
} else {
throw SyntaxError('Invalid code generated: ' + code);
}
throw SyntaxError('Invalid code generated: ' + code);
};
/**
@@ -388,7 +383,7 @@ Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}';
/**
* A dictionary of definitions to be printed before the code.
* @type {Object}
* @type {!Object|undefined}
* @protected
*/
Blockly.Generator.prototype.definitions_;
@@ -396,38 +391,67 @@ Blockly.Generator.prototype.definitions_;
/**
* A dictionary mapping desired function names in definitions_ to actual
* function names (to avoid collisions with user functions).
* @type {Object}
* @type {!Object|undefined}
* @protected
*/
Blockly.Generator.prototype.functionNames_;
/**
* A database of variable names.
* @type {Blockly.Names}
* A database of variable and procedure names.
* @type {!Blockly.Names|undefined}
* @protected
*/
Blockly.Generator.prototype.variableDB_;
Blockly.Generator.prototype.nameDB_;
Object.defineProperty(Blockly.Generator.prototype, 'variableDB_', {
/**
* Getter.
* @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021).
* @this {Blockly.Generator}
* @return {!Blockly.Names|undefined} Name database.
*/
get: function() {
Blockly.utils.deprecation.warn(
'variableDB_', 'May 2021', 'May 2026', 'nameDB_');
return this.nameDB_;
},
/**
* Setter.
* @deprecated 'variableDB_' was renamed to 'nameDB_' (May 2021).
* @this {Blockly.Generator}
* @param {!Blockly.Names|undefined} nameDb New name database.
*/
set: function(nameDb) {
Blockly.utils.deprecation.warn(
'variableDB_', 'May 2021', 'May 2026', 'nameDB_');
this.nameDB_ = nameDb;
}
});
/**
* Define a function to be included in the generated code.
* Define a developer-defined function (not a user-defined procedure) to be
* included in the generated code. Used for creating private helper functions.
* The first time this is called with a given desiredName, the code is
* saved and an actual name is generated. Subsequent calls with the
* same desiredName have no effect but have the same return value.
*
* It is up to the caller to make sure the same desiredName is not
* used for different code values.
* used for different helper functions (e.g. use "colourRandom" and
* "listRandom", not "random"). There is no danger of colliding with reserved
* words, or user-defined variable or procedure names.
*
* The code gets output when Blockly.Generator.finish() is called.
*
* @param {string} desiredName The desired name of the function (e.g., isPrime).
* @param {!Array.<string>} code A list of statements. Use ' ' for indents.
* @param {string} desiredName The desired name of the function
* (e.g. mathIsPrime).
* @param {!Array<string>} code A list of statements. Use ' ' for indents.
* @return {string} The actual name of the new function. This may differ
* from desiredName if the former has already been taken by the user.
* @protected
*/
Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) {
if (!this.definitions_[desiredName]) {
var functionName = this.variableDB_.getDistinctName(desiredName,
var functionName = this.nameDB_.getDistinctName(desiredName,
Blockly.PROCEDURE_CATEGORY_NAME);
this.functionNames_[desiredName] = functionName;
var codeText = code.join('\n').replace(
@@ -455,6 +479,12 @@ Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) {
*/
Blockly.Generator.prototype.init = function(_workspace) {
// Optionally override
// Create a dictionary of definitions to be printed before the code.
this.definitions_ = Object.create(null);
// Create a dictionary mapping desired developer-defined function names in
// definitions_ to actual function names (to avoid collisions with
// user-defined procedures).
this.functionNames_ = Object.create(null);
};
/**
@@ -477,13 +507,16 @@ Blockly.Generator.prototype.scrub_ = function(_block, code, _opt_thisOnly) {
/**
* Hook for code to run at end of code generation.
* Subclasses may override this, e.g. to prepend the generated code with the
* variable definitions.
* Subclasses may override this, e.g. to prepend the generated code with import
* statements or variable definitions.
* @param {string} code Generated code.
* @return {string} Completed code.
*/
Blockly.Generator.prototype.finish = function(code) {
// Optionally override
// Clean up temporary data.
delete this.definitions_;
delete this.functionNames_;
return code;
};
+31 -8
View File
@@ -14,6 +14,7 @@
goog.provide('Blockly.Gesture');
goog.require('Blockly.blockAnimations');
/** @suppress {extraRequire} */
goog.require('Blockly.BlockDragger');
goog.require('Blockly.browserEvents');
goog.require('Blockly.BubbleDragger');
@@ -26,10 +27,12 @@ goog.require('Blockly.Tooltip');
goog.require('Blockly.Touch');
goog.require('Blockly.utils');
goog.require('Blockly.utils.Coordinate');
goog.require('Blockly.Workspace');
goog.require('Blockly.WorkspaceDragger');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.Field');
goog.requireType('Blockly.IBlockDragger');
goog.requireType('Blockly.IBubble');
goog.requireType('Blockly.IFlyout');
goog.requireType('Blockly.WorkspaceSvg');
@@ -180,7 +183,7 @@ Blockly.Gesture = function(e, creatorWorkspace) {
/**
* The object tracking a block drag, or null if none is in progress.
* @type {Blockly.BlockDragger}
* @type {?Blockly.IBlockDragger}
* @private
*/
this.blockDragger_ = null;
@@ -436,11 +439,14 @@ Blockly.Gesture.prototype.updateIsDragging_ = function() {
* @private
*/
Blockly.Gesture.prototype.startDraggingBlock_ = function() {
this.blockDragger_ = new Blockly.BlockDragger(
var BlockDraggerClass = Blockly.registry.getClassFromOptions(
Blockly.registry.Type.BLOCK_DRAGGER, this.creatorWorkspace_.options, true);
this.blockDragger_ = new BlockDraggerClass(
/** @type {!Blockly.BlockSvg} */ (this.targetBlock_),
/** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_));
this.blockDragger_.startBlockDrag(this.currentDragDeltaXY_, this.healStack_);
this.blockDragger_.dragBlock(this.mostRecentEvent_, this.currentDragDeltaXY_);
this.blockDragger_.startDrag(this.currentDragDeltaXY_, this.healStack_);
this.blockDragger_.drag(this.mostRecentEvent_, this.currentDragDeltaXY_);
};
/**
@@ -532,7 +538,7 @@ Blockly.Gesture.prototype.handleMove = function(e) {
if (this.isDraggingWorkspace_) {
this.workspaceDragger_.drag(this.currentDragDeltaXY_);
} else if (this.isDraggingBlock_) {
this.blockDragger_.dragBlock(
this.blockDragger_.drag(
this.mostRecentEvent_, this.currentDragDeltaXY_);
} else if (this.isDraggingBubble_) {
this.bubbleDragger_.dragBubble(
@@ -564,7 +570,7 @@ Blockly.Gesture.prototype.handleUp = function(e) {
if (this.isDraggingBubble_) {
this.bubbleDragger_.endBubbleDrag(e, this.currentDragDeltaXY_);
} else if (this.isDraggingBlock_) {
this.blockDragger_.endBlockDrag(e, this.currentDragDeltaXY_);
this.blockDragger_.endDrag(e, this.currentDragDeltaXY_);
} else if (this.isDraggingWorkspace_) {
this.workspaceDragger_.endDrag(this.currentDragDeltaXY_);
} else if (this.isBubbleClick_()) {
@@ -600,7 +606,7 @@ Blockly.Gesture.prototype.cancel = function() {
this.bubbleDragger_.endBubbleDrag(
this.mostRecentEvent_, this.currentDragDeltaXY_);
} else if (this.isDraggingBlock_) {
this.blockDragger_.endBlockDrag(
this.blockDragger_.endDrag(
this.mostRecentEvent_, this.currentDragDeltaXY_);
} else if (this.isDraggingWorkspace_) {
this.workspaceDragger_.endDrag(this.currentDragDeltaXY_);
@@ -952,7 +958,7 @@ Blockly.Gesture.prototype.hasStarted = function() {
/**
* Get a list of the insertion markers that currently exist. Block drags have
* 0, 1, or 2 insertion markers.
* @return {!Array.<!Blockly.BlockSvg>} A possibly empty list of insertion
* @return {!Array<!Blockly.BlockSvg>} A possibly empty list of insertion
* marker blocks.
* @package
*/
@@ -963,6 +969,23 @@ Blockly.Gesture.prototype.getInsertionMarkers = function() {
return [];
};
/**
* Gets the current dragger if an item is being dragged. Null if nothing is
* being dragged.
* @return {!Blockly.WorkspaceDragger|!Blockly.BubbleDragger|!Blockly.IBlockDragger|null}
* The dragger that is currently in use or null if no drag is in progress.
*/
Blockly.Gesture.prototype.getCurrentDragger = function() {
if (this.isDraggingBlock_) {
return this.blockDragger_;
} else if (this.isDraggingWorkspace_) {
return this.workspaceDragger_;
} else if (this.isDraggingBubble_) {
return this.bubbleDragger_;
}
return null;
};
/**
* Is a drag or other gesture currently in progress on any workspace?
* @return {boolean} True if gesture is occurring.
+1 -1
View File
@@ -108,7 +108,7 @@ Blockly.Grid.prototype.getSpacing = function() {
};
/**
* Get the id of the pattern element, which should be randomized to avoid
* Get the ID of the pattern element, which should be randomized to avoid
* conflicts with other Blockly instances on the page.
* @return {string} The pattern ID.
* @package
+3 -3
View File
@@ -56,14 +56,14 @@ Blockly.Icon.prototype.SIZE = 17;
/**
* Bubble UI (if visible).
* @type {Blockly.Bubble}
* @type {?Blockly.Bubble}
* @protected
*/
Blockly.Icon.prototype.bubble_ = null;
/**
* Absolute coordinate of icon's center.
* @type {Blockly.utils.Coordinate}
* @type {?Blockly.utils.Coordinate}
* @protected
*/
Blockly.Icon.prototype.iconXY_ = null;
@@ -177,7 +177,7 @@ Blockly.Icon.prototype.computeIconLocation = function() {
/**
* Returns the center of the block's icon relative to the surface.
* @return {Blockly.utils.Coordinate} Object with x and y properties in
* @return {?Blockly.utils.Coordinate} Object with x and y properties in
* workspace coordinates.
*/
Blockly.Icon.prototype.getIconLocation = function() {
+11 -9
View File
@@ -25,12 +25,15 @@ goog.require('Blockly.Tooltip');
goog.require('Blockly.utils');
goog.require('Blockly.utils.aria');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.math');
goog.require('Blockly.utils.Svg');
goog.require('Blockly.utils.userAgent');
goog.require('Blockly.Workspace');
goog.require('Blockly.WorkspaceDragSurfaceSvg');
goog.require('Blockly.WorkspaceSvg');
goog.require('Blockly.WidgetDiv');
goog.requireType('Blockly.Workspace');
goog.requireType('Blockly.BlockSvg');
/**
@@ -65,6 +68,7 @@ Blockly.inject = function(container, opt_options) {
// Create surfaces for dragging things. These are optimizations
// so that the browser does not repaint during the drag.
var blockDragSurface = new Blockly.BlockDragSurfaceSvg(subContainer);
var workspaceDragSurface = new Blockly.WorkspaceDragSurfaceSvg(subContainer);
var workspace = Blockly.createMainWorkspace_(svg, options, blockDragSurface,
@@ -163,7 +167,7 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
mainWorkspace.getTheme().getClassName());
if (!wsOptions.hasCategories && wsOptions.languageTree) {
// Add flyout as an <svg> that is a sibling of the workspace svg.
// Add flyout as an <svg> that is a sibling of the workspace SVG.
var flyout = mainWorkspace.addFlyout(Blockly.utils.Svg.SVG);
Blockly.utils.dom.insertAfter(flyout, svg);
}
@@ -231,8 +235,7 @@ Blockly.bumpTopObjectsIntoBounds_ = function(workspace) {
var scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true);
var topBlocks = workspace.getTopBoundedElements();
for (var i = 0, block; (block = topBlocks[i]); i++) {
Blockly.bumpObjectIntoBounds_(
workspace, scrollMetricsInWsCoords, block);
Blockly.bumpObjectIntoBounds_(workspace, scrollMetricsInWsCoords, block);
}
};
@@ -245,7 +248,7 @@ Blockly.bumpTopObjectsIntoBounds_ = function(workspace) {
Blockly.bumpIntoBoundsHandler_ = function(workspace) {
return function(e) {
var metricsManager = workspace.getMetricsManager();
if (!metricsManager.hasFixedEdges || workspace.isDragging()) {
if (!metricsManager.hasFixedEdges() || workspace.isDragging()) {
return;
}
@@ -288,7 +291,7 @@ Blockly.bumpIntoBoundsHandler_ = function(workspace) {
* in workspace coordinates.
* @param {!Blockly.IBoundedElement} object The object to bump.
* @return {boolean} True if block was bumped.
* @private
* @package
*/
Blockly.bumpObjectIntoBounds_ = function(workspace, scrollMetrics, object) {
// Compute new top/left position for object.
@@ -375,12 +378,11 @@ Blockly.init_ = function(mainWorkspace) {
}
}
var verticalSpacing = Blockly.Scrollbar.scrollbarThickness;
if (options.hasTrashcan) {
verticalSpacing = mainWorkspace.trashcan.init(verticalSpacing);
mainWorkspace.trashcan.init();
}
if (options.zoomOptions && options.zoomOptions.controls) {
mainWorkspace.zoomControls_.init(verticalSpacing);
mainWorkspace.zoomControls_.init();
}
if (options.moveOptions && options.moveOptions.scrollbars) {
+9 -10
View File
@@ -50,7 +50,7 @@ Blockly.Input = function(type, name, block, connection) {
this.sourceBlock_ = block;
/** @type {Blockly.Connection} */
this.connection = connection;
/** @type {!Array.<!Blockly.Field>} */
/** @type {!Array<!Blockly.Field>} */
this.fieldRow = [];
};
@@ -69,7 +69,7 @@ Blockly.Input.prototype.visible_ = true;
/**
* Get the source block for this input.
* @return {Blockly.Block} The source block, or null if there is none.
* @return {?Blockly.Block} The source block, or null if there is none.
*/
Blockly.Input.prototype.getSourceBlock = function() {
return this.sourceBlock_;
@@ -168,9 +168,8 @@ Blockly.Input.prototype.removeField = function(name, opt_quiet) {
}
if (opt_quiet) {
return false;
} else {
throw Error('Field "' + name + '" not found.');
}
throw Error('Field "' + name + '" not found.');
};
/**
@@ -185,7 +184,7 @@ Blockly.Input.prototype.isVisible = function() {
* Sets whether this input is visible or not.
* Should only be used to collapse/uncollapse a block.
* @param {boolean} visible True if visible.
* @return {!Array.<!Blockly.BlockSvg>} List of blocks to render.
* @return {!Array<!Blockly.BlockSvg>} List of blocks to render.
* @package
*/
Blockly.Input.prototype.setVisible = function(visible) {
@@ -230,7 +229,7 @@ Blockly.Input.prototype.markDirty = function() {
/**
* Change a connection's compatibility.
* @param {string|Array.<string>|null} check Compatible value type or
* @param {string|Array<string>|null} check Compatible value type or
* list of value types. Null if all types are compatible.
* @return {!Blockly.Input} The input being modified (to allow chaining).
*/
@@ -259,8 +258,8 @@ Blockly.Input.prototype.setAlign = function(align) {
/**
* Changes the connection's shadow block.
* @param {Element} shadow DOM representation of a block or null.
* @return {Blockly.Input} The input being modified (to allow chaining).
* @param {?Element} shadow DOM representation of a block or null.
* @return {!Blockly.Input} The input being modified (to allow chaining).
*/
Blockly.Input.prototype.setShadowDom = function(shadow) {
if (!this.connection) {
@@ -271,8 +270,8 @@ Blockly.Input.prototype.setShadowDom = function(shadow) {
};
/**
* Returns the xml representation of the connection's shadow block.
* @return {Element} Shadow DOM representation of a block or null.
* Returns the XML representation of the connection's shadow block.
* @return {?Element} Shadow DOM representation of a block or null.
*/
Blockly.Input.prototype.getShadowDom = function() {
if (!this.connection) {
+52 -25
View File
@@ -13,6 +13,7 @@
goog.provide('Blockly.InsertionMarkerManager');
goog.require('Blockly.blockAnimations');
goog.require('Blockly.ComponentManager');
goog.require('Blockly.connectionTypes');
/** @suppress {extraRequire} */
goog.require('Blockly.constants');
@@ -131,7 +132,7 @@ Blockly.InsertionMarkerManager = function(block) {
* other blocks. This includes all open connections on the top block, as well
* as the last connection on the block stack.
* Does not change during a drag.
* @type {!Array.<!Blockly.RenderedConnection>}
* @type {!Array<!Blockly.RenderedConnection>}
* @private
*/
this.availableConnections_ = this.initAvailableConnections_();
@@ -148,6 +149,17 @@ Blockly.InsertionMarkerManager.PREVIEW_TYPE = {
REPLACEMENT_FADE: 2,
};
/**
* An error message to throw if the block created by createMarkerBlock_ is
* missing any components.
* @type {string}
* @const
*/
Blockly.InsertionMarkerManager.DUPLICATE_BLOCK_ERROR = 'The insertion marker ' +
'manager tried to create a marker but the result is missing %1. If ' +
'you are using a mutator, make sure your domToMutation method is ' +
'properly defined.';
/**
* Sever all links from this object.
* @package
@@ -229,14 +241,15 @@ Blockly.InsertionMarkerManager.prototype.applyConnections = function() {
* Update connections based on the most recent move location.
* @param {!Blockly.utils.Coordinate} dxy Position relative to drag start,
* in workspace units.
* @param {?number} deleteArea One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @param {?Blockly.IDragTarget} dragTarget The drag target that the block is
* currently over.
* @package
*/
Blockly.InsertionMarkerManager.prototype.update = function(dxy, deleteArea) {
Blockly.InsertionMarkerManager.prototype.update = function(dxy, dragTarget) {
var candidate = this.getCandidate_(dxy);
this.wouldDeleteBlock_ = this.shouldDelete_(candidate, deleteArea);
this.wouldDeleteBlock_ = this.shouldDelete_(candidate, dragTarget);
var shouldUpdate = this.wouldDeleteBlock_ ||
this.shouldUpdatePreviews_(candidate, dxy);
@@ -279,9 +292,17 @@ Blockly.InsertionMarkerManager.prototype.createMarkerBlock_ = function(sourceBlo
continue; // Ignore the collapsed input.
}
var resultInput = result.inputList[i];
if (!resultInput) {
throw new Error(Blockly.InsertionMarkerManager.DUPLICATE_BLOCK_ERROR
.replace('%1', 'an input'));
}
for (var j = 0; j < sourceInput.fieldRow.length; j++) {
var sourceField = sourceInput.fieldRow[j];
var resultField = resultInput.fieldRow[j];
if (!resultField) {
throw new Error(Blockly.InsertionMarkerManager.DUPLICATE_BLOCK_ERROR
.replace('%1', 'a field'));
}
resultField.setValue(sourceField.getValue());
}
}
@@ -303,14 +324,14 @@ Blockly.InsertionMarkerManager.prototype.createMarkerBlock_ = function(sourceBlo
* only be called once, at the beginning of a drag.
* If the stack has more than one block, this function will populate
* lastOnStack_ and create the corresponding insertion marker.
* @return {!Array.<!Blockly.RenderedConnection>} A list of available
* @return {!Array<!Blockly.RenderedConnection>} A list of available
* connections.
* @private
*/
Blockly.InsertionMarkerManager.prototype.initAvailableConnections_ = function() {
var available = this.topBlock_.getConnections_(false);
// Also check the last connection on this stack
var lastOnStack = this.topBlock_.lastConnectionInStack();
var lastOnStack = this.topBlock_.lastConnectionInStack(true);
if (lastOnStack && lastOnStack != this.topBlock_.nextConnection) {
available.push(lastOnStack);
this.lastOnStack_ = lastOnStack;
@@ -365,7 +386,7 @@ Blockly.InsertionMarkerManager.prototype.shouldUpdatePreviews_ = function(
} else {
console.error('Only one of localConnection_ and closestConnection_ was set.');
}
} else { // No connection found.
} else { // No connection found.
// Only need to update if we were showing a preview before.
return !!(this.localConnection_ && this.closestConnection_);
}
@@ -426,23 +447,26 @@ Blockly.InsertionMarkerManager.prototype.getStartRadius_ = function() {
/**
* Whether ending the drag would delete the block.
* @param {!Object} candidate An object containing a local connection, a closest
* connection, and a radius.
* @param {?number} deleteArea One of {@link Blockly.DELETE_AREA_TRASH},
* {@link Blockly.DELETE_AREA_TOOLBOX}, or {@link Blockly.DELETE_AREA_NONE}.
* @return {boolean} True if dropping the block immediately would replace
* delete the block. False otherwise.
* connection, and a radius.
* @param {?Blockly.IDragTarget} dragTarget The drag target that the block is
* currently over.
* @return {boolean} Whether dropping the block immediately would delete the
* block.
* @private
*/
Blockly.InsertionMarkerManager.prototype.shouldDelete_ = function(candidate,
deleteArea) {
// Prefer connecting over dropping into the trash can, but prefer dragging to
// the toolbox over connecting to other blocks.
var wouldConnect = candidate && !!candidate.closest &&
deleteArea != Blockly.DELETE_AREA_TOOLBOX;
var wouldDelete = !!deleteArea && !this.topBlock_.getParent() &&
this.topBlock_.isDeletable();
return wouldDelete && !wouldConnect;
Blockly.InsertionMarkerManager.prototype.shouldDelete_ = function(
candidate, dragTarget) {
if (dragTarget) {
var componentManager = this.workspace_.getComponentManager();
var isDeleteArea = componentManager.hasCapability(dragTarget.id,
Blockly.ComponentManager.Capability.DELETE_AREA);
if (isDeleteArea) {
return (
/** @type {!Blockly.IDeleteArea} */ (dragTarget))
.wouldDelete(this.topBlock_, candidate && !!candidate.closest);
}
}
return false;
};
/**
@@ -650,7 +674,10 @@ Blockly.InsertionMarkerManager.prototype.hideInsertionMarker_ = function() {
}
this.markerConnection_ = null;
imBlock.getSvgRoot().setAttribute('visibility', 'hidden');
var svg = imBlock.getSvgRoot();
if (svg) {
svg.setAttribute('visibility', 'hidden');
}
};
/**
@@ -694,7 +721,7 @@ Blockly.InsertionMarkerManager.prototype.hideReplacementFade_ = function() {
/**
* Get a list of the insertion markers that currently exist. Drags have 0, 1,
* or 2 insertion markers.
* @return {!Array.<!Blockly.BlockSvg>} A possibly empty list of insertion
* @return {!Array<!Blockly.BlockSvg>} A possibly empty list of insertion
* marker blocks.
* @package
*/
+6 -6
View File
@@ -34,16 +34,16 @@ Blockly.IASTNodeLocation = function() {};
Blockly.IASTNodeLocationSvg = function() {};
/**
* Add the marker svg to this node's svg group.
* @param {SVGElement} markerSvg The svg root of the marker to be added to the
* svg group.
* Add the marker SVG to this node's SVG group.
* @param {SVGElement} markerSvg The SVG root of the marker to be added to the
* SVG group.
*/
Blockly.IASTNodeLocationSvg.prototype.setMarkerSvg;
/**
* Add the cursor svg to this node's svg group.
* @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
* svg group.
* Add the cursor SVG to this node's SVG group.
* @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the
* SVG group.
*/
Blockly.IASTNodeLocationSvg.prototype.setCursorSvg;
+32
View File
@@ -0,0 +1,32 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a component that is automatically hidden
* when Blockly.hideChaff is called.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IAutoHideable');
goog.require('Blockly.IComponent');
/**
* Interface for a component that can be automatically hidden.
* @extends {Blockly.IComponent}
* @interface
*/
Blockly.IAutoHideable = function() {};
/**
* Hides the component. Called in Blockly.hideChaff.
* @param {boolean} onlyClosePopups Whether only popups should be closed.
* Flyouts should not be closed if this is true.
*/
Blockly.IAutoHideable.prototype.autoHide;
+58
View File
@@ -0,0 +1,58 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a block dragger.
* @author aschmiedt@google.com (Abby Schmiedt)
*/
'use strict';
goog.provide('Blockly.IBlockDragger');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.utils.Coordinate');
/**
* A block dragger interface.
* @interface
*/
Blockly.IBlockDragger = function() {};
/**
* Start dragging a block. This includes moving it to the drag surface.
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at mouse down, in pixel units.
* @param {boolean} healStack Whether or not to heal the stack after
* disconnecting.
*/
Blockly.IBlockDragger.prototype.startDrag;
/**
* Execute a step of block dragging, based on the given event. Update the
* display accordingly.
* @param {!Event} e The most recent move event.
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at the start of the drag, in pixel units.
*/
Blockly.IBlockDragger.prototype.drag;
/**
* Finish a block drag and put the block back on the workspace.
* @param {!Event} e The mouseup/touchend event.
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at the start of the drag, in pixel units.
*/
Blockly.IBlockDragger.prototype.endDrag;
/**
* Get a list of the insertion markers that currently exist. Drags have 0, 1,
* or 2 insertion markers.
* @return {!Array.<!Blockly.BlockSvg>} A possibly empty list of insertion
* marker blocks.
*/
Blockly.IBlockDragger.prototype.getInsertionMarkers;
+4 -3
View File
@@ -13,16 +13,17 @@
goog.provide('Blockly.IBubble');
goog.require('Blockly.IContextMenu');
goog.require('Blockly.IDraggable');
goog.requireType('Blockly.BlockDragSurfaceSvg');
goog.requireType('Blockly.IContextMenu');
goog.requireType('Blockly.IDeletable');
goog.requireType('Blockly.utils.Coordinate');
/**
* A bubble interface.
* @interface
* @extends {Blockly.IDeletable}
* @extends {Blockly.IDraggable}
* @extends {Blockly.IContextMenu}
*/
Blockly.IBubble = function() {};
+30
View File
@@ -0,0 +1,30 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Interface for a workspace component that can be registered with
* the ComponentManager.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IComponent');
/**
* The interface for a workspace component that can be registered with the
* ComponentManager.
* @interface
*/
Blockly.IComponent = function() {};
/**
* The unique id for this component that is used to register with the
* ComponentManager.
* @type {string}
*/
Blockly.IComponent.id;
+42
View File
@@ -0,0 +1,42 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a component that can delete a block or bubble
* that is dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IDeleteArea');
goog.require('Blockly.IDragTarget');
goog.requireType('Blockly.IDraggable');
/**
* Interface for a component that can delete a block or bubble that is dropped
* on top of it.
* @extends {Blockly.IDragTarget}
* @interface
*/
Blockly.IDeleteArea = function() {};
/**
* Returns whether the provided block or bubble would be deleted if dropped on
* this area.
* This method should check if the element is deletable and is always called
* before onDragEnter/onDragOver/onDragExit.
* @param {!Blockly.IDraggable} element The block or bubble currently being
* dragged.
* @param {boolean} couldConnect Whether the element could could connect to
* another.
* @return {boolean} Whether the element provided would be deleted if dropped on
* this area.
*/
Blockly.IDeleteArea.prototype.wouldDelete;
-30
View File
@@ -1,30 +0,0 @@
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a component that can delete a block that is
* dropped on top of it.
* @author aschmiedt@google.com (Abby Schmiedt)
*/
'use strict';
goog.provide('Blockly.IDeleteArea');
goog.requireType('Blockly.utils.Rect');
/**
* Interface for a component that can delete a block that is dropped on top of it.
* @interface
*/
Blockly.IDeleteArea = function() {};
/**
* Return the deletion rectangle.
* @return {Blockly.utils.Rect} Rectangle in which to delete.
*/
Blockly.IDeleteArea.prototype.getClientRect;
+78
View File
@@ -0,0 +1,78 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for a component that has a handler for when a
* block is dropped on top of it.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IDragTarget');
goog.require('Blockly.IComponent');
goog.requireType('Blockly.IDraggable');
goog.requireType('Blockly.utils.Rect');
/**
* Interface for a component with custom behaviour when a block or bubble is
* dragged over or dropped on top of it.
* @extends {Blockly.IComponent}
* @interface
*/
Blockly.IDragTarget = function() {};
/**
* Returns the bounding rectangle of the drag target area in pixel units
* relative to viewport.
* @return {?Blockly.utils.Rect} The component's bounding box. Null if drag
* target area should be ignored.
*/
Blockly.IDragTarget.prototype.getClientRect;
/**
* Handles when a cursor with a block or bubble enters this drag target.
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
* dragged.
*/
Blockly.IDragTarget.prototype.onDragEnter;
/**
* Handles when a cursor with a block or bubble is dragged over this drag
* target.
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
* dragged.
*/
Blockly.IDragTarget.prototype.onDragOver;
/**
* Handles when a cursor with a block or bubble exits this drag target.
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
* dragged.
*/
Blockly.IDragTarget.prototype.onDragExit;
/**
* Handles when a block or bubble is dropped on this component.
* Should not handle delete here.
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
* dragged.
*/
Blockly.IDragTarget.prototype.onDrop;
/**
* Returns whether the provided block or bubble should not be moved after being
* dropped on this component. If true, the element will return to where it was
* when the drag started.
* @param {!Blockly.IDraggable} dragElement The block or bubble currently being
* dragged.
* @return {boolean} Whether the block or bubble provided should be returned to
* drag start.
*/
Blockly.IDragTarget.prototype.shouldPreventMove;
+24
View File
@@ -0,0 +1,24 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview The interface for an object that is draggable.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IDraggable');
goog.require('Blockly.IDeletable');
/**
* The interface for an object that can be dragged.
* @extends {Blockly.IDeletable}
* @interface
*/
Blockly.IDraggable = function() {};
+3 -3
View File
@@ -69,17 +69,17 @@ Blockly.IMetricsManager.prototype.getFlyoutMetrics;
Blockly.IMetricsManager.prototype.getToolboxMetrics;
/**
* Gets the width and height of the workspace's parent svg element in pixel
* Gets the width and height of the workspace's parent SVG element in pixel
* coordinates. This area includes the toolbox and the visible workspace area.
* @return {!Blockly.utils.Size} The width and height of the workspace's parent
* svg element.
* SVG element.
* @public
*/
Blockly.IMetricsManager.prototype.getSvgMetrics;
/**
* Gets the absolute left and absolute top in pixel coordinates.
* This is where the visible workspace starts in relation to the svg container.
* This is where the visible workspace starts in relation to the SVG container.
* @return {!Blockly.MetricsManager.AbsoluteMetrics} The absolute metrics for
* the workspace.
* @public
-22
View File
@@ -1,22 +0,0 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Interface for a plugin.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IPlugin');
/**
* The interface for a workspace plugin.
* @interface
*/
Blockly.IPlugin = function() {};
+8 -4
View File
@@ -5,7 +5,7 @@
*/
/**
* @fileoverview The interface for a positionable ui element.
* @fileoverview The interface for a positionable UI element.
* @author kozbial@google.com (Monica Kozbial)
*/
@@ -13,12 +13,15 @@
goog.provide('Blockly.IPositionable');
goog.require('Blockly.IPlugin');
goog.require('Blockly.IComponent');
goog.requireType('Blockly.MetricsManager');
goog.requireType('Blockly.utils.Rect');
/**
* Interface for a component that is positioned on top of the workspace.
* @extends {Blockly.IPlugin}
* @extends {Blockly.IComponent}
* @interface
*/
Blockly.IPositionable = function() {};
@@ -34,6 +37,7 @@ Blockly.IPositionable.prototype.position;
/**
* Returns the bounding rectangle of the UI element in pixel units relative to
* the Blockly injection div.
* @return {!Blockly.utils.Rect} The plugins bounding box.
* @return {?Blockly.utils.Rect} The UI elementss bounding box. Null if
* bounding box should be ignored by other UI elements.
*/
Blockly.IPositionable.prototype.getBoundingRectangle;
+6 -6
View File
@@ -26,7 +26,7 @@ Blockly.IToolboxItem = function() {};
/**
* Initializes the toolbox item.
* This includes creating the dom and updating the state of any items based
* This includes creating the DOM and updating the state of any items based
* on the info object.
* @return {void}
* @public
@@ -42,7 +42,7 @@ Blockly.IToolboxItem.prototype.getDiv;
/**
* Gets a unique identifier for this toolbox item.
* @return {string} The id for the toolbox item.
* @return {string} The ID for the toolbox item.
* @public
*/
Blockly.IToolboxItem.prototype.getId;
@@ -114,10 +114,10 @@ Blockly.ISelectableToolboxItem.prototype.getContents;
Blockly.ISelectableToolboxItem.prototype.setSelected;
/**
* Gets the html element that is clickable.
* The parent toolbox element receives clicks. The parent toolbox will add an id to this element so
* it can pass the onClick event to the correct toolboxItem.
* @return {!Element} The html element that receives clicks.
* Gets the HTML element that is clickable.
* The parent toolbox element receives clicks. The parent toolbox will add an ID
* to this element so it can pass the onClick event to the correct toolboxItem.
* @return {!Element} The HTML element that receives clicks.
* @public
*/
Blockly.ISelectableToolboxItem.prototype.getClickTarget;
-20
View File
@@ -1,20 +0,0 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Interface for plugins that can be registered on the workspace.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.IWorkspacePlugin');
/**
* Base interface for a plugin that can be registered on the workspace.
* @interface
*/
Blockly.IWorkspacePlugin = function() {};
+19 -19
View File
@@ -27,14 +27,14 @@ goog.requireType('Blockly.WorkspaceSvg');
Blockly.MarkerManager = function(workspace){
/**
* The cursor.
* @type {Blockly.Cursor}
* @type {?Blockly.Cursor}
* @private
*/
this.cursor_ = null;
/**
* The cursor's svg element.
* @type {SVGElement}
* The cursor's SVG element.
* @type {?SVGElement}
* @private
*/
this.cursorSvg_ = null;
@@ -44,7 +44,7 @@ Blockly.MarkerManager = function(workspace){
* @type {!Object<string, !Blockly.Marker>}
* @private
*/
this.markers_ = {};
this.markers_ = Object.create(null);
/**
* The workspace this marker manager is associated with.
@@ -78,7 +78,7 @@ Blockly.MarkerManager.prototype.registerMarker = function(id, marker) {
/**
* Unregister the marker by removing it from the map of markers.
* @param {string} id The id of the marker to unregister.
* @param {string} id The ID of the marker to unregister.
*/
Blockly.MarkerManager.prototype.unregisterMarker = function(id) {
var marker = this.markers_[id];
@@ -86,27 +86,27 @@ Blockly.MarkerManager.prototype.unregisterMarker = function(id) {
marker.dispose();
delete this.markers_[id];
} else {
throw Error('Marker with id ' + id + ' does not exist. Can only unregister' +
'markers that exist.');
throw Error('Marker with ID ' + id + ' does not exist. ' +
'Can only unregister markers that exist.');
}
};
/**
* Get the cursor for the workspace.
* @return {Blockly.Cursor} The cursor for this workspace.
* @return {?Blockly.Cursor} The cursor for this workspace.
*/
Blockly.MarkerManager.prototype.getCursor = function() {
return this.cursor_;
};
/**
* Get a single marker that corresponds to the given id.
* Get a single marker that corresponds to the given ID.
* @param {string} id A unique identifier for the marker.
* @return {Blockly.Marker} The marker that corresponds to the given id, or null
* if none exists.
* @return {?Blockly.Marker} The marker that corresponds to the given ID,
* or null if none exists.
*/
Blockly.MarkerManager.prototype.getMarker = function(id) {
return this.markers_[id];
return this.markers_[id] || null;
};
/**
@@ -127,9 +127,9 @@ Blockly.MarkerManager.prototype.setCursor = function(cursor) {
};
/**
* Add the cursor svg to this workspace svg group.
* @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
* workspace svg group.
* Add the cursor SVG to this workspace SVG group.
* @param {?SVGElement} cursorSvg The SVG root of the cursor to be added to the
* workspace SVG group.
* @package
*/
Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) {
@@ -143,9 +143,9 @@ Blockly.MarkerManager.prototype.setCursorSvg = function(cursorSvg) {
};
/**
* Add the marker svg to this workspaces svg group.
* @param {SVGElement} markerSvg The svg root of the marker to be added to the
* workspace svg group.
* Add the marker SVG to this workspaces SVG group.
* @param {?SVGElement} markerSvg The SVG root of the marker to be added to the
* workspace SVG group.
* @package
*/
Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) {
@@ -164,7 +164,7 @@ Blockly.MarkerManager.prototype.setMarkerSvg = function(markerSvg) {
};
/**
* Redraw the attached cursor svg if needed.
* Redraw the attached cursor SVG if needed.
* @package
*/
Blockly.MarkerManager.prototype.updateMarkers = function() {
+7 -7
View File
@@ -32,7 +32,7 @@ Blockly.Menu = function() {
* Array of menu items.
* (Nulls are never in the array, but typing the array as nullable prevents
* the compiler from objecting to .indexOf(null))
* @type {!Array.<Blockly.MenuItem>}
* @type {!Array<Blockly.MenuItem>}
* @private
*/
this.menuItems_ = [];
@@ -49,7 +49,7 @@ Blockly.Menu = function() {
/**
* This is the element that we will listen to the real focus events on.
* A value of null means no menu item is highlighted.
* @type {Blockly.MenuItem}
* @type {?Blockly.MenuItem}
* @private
*/
this.highlightedItem_ = null;
@@ -91,7 +91,7 @@ Blockly.Menu = function() {
/**
* The menu's root DOM element.
* @type {Element}
* @type {?Element}
* @private
*/
this.element_ = null;
@@ -149,7 +149,7 @@ Blockly.Menu.prototype.render = function(container) {
/**
* Gets the menu's element.
* @return {Element} The DOM element.
* @return {?Element} The DOM element.
* @package
*/
Blockly.Menu.prototype.getElement = function() {
@@ -255,7 +255,7 @@ Blockly.Menu.prototype.getMenuItem_ = function(elem) {
/**
* Highlights the given menu item, or clears highlighting if null.
* @param {Blockly.MenuItem} item Item to highlight, or null.
* @param {?Blockly.MenuItem} item Item to highlight, or null.
* @package
*/
Blockly.Menu.prototype.setHighlighted = function(item) {
@@ -382,7 +382,7 @@ Blockly.Menu.prototype.handleClick_ = function(e) {
/**
* Handles mouse enter events. Focus the element.
* @param {Event} _e Mouse event to handle.
* @param {!Event} _e Mouse event to handle.
* @private
*/
Blockly.Menu.prototype.handleMouseEnter_ = function(_e) {
@@ -391,7 +391,7 @@ Blockly.Menu.prototype.handleMouseEnter_ = function(_e) {
/**
* Handles mouse leave events. Blur and clear highlight.
* @param {Event} _e Mouse event to handle.
* @param {!Event} _e Mouse event to handle.
* @private
*/
Blockly.Menu.prototype.handleMouseLeave_ = function(_e) {
+2 -2
View File
@@ -91,7 +91,7 @@ Blockly.MenuItem = function(content, opt_value) {
/**
* Bound function to call when this menu item is clicked.
* @type {Function}
* @type {?Function}
* @private
*/
this.actionHandler_ = null;
@@ -153,7 +153,7 @@ Blockly.MenuItem.prototype.dispose = function() {
/**
* Gets the menu item's element.
* @return {Element} The DOM element.
* @return {?Element} The DOM element.
* @package
*/
Blockly.MenuItem.prototype.getElement = function() {
+10 -49
View File
@@ -52,7 +52,7 @@ Blockly.MetricsManager = function(workspace) {
Blockly.MetricsManager.ToolboxMetrics;
/**
* Describes where the viewport starts in relation to the workspace svg.
* Describes where the viewport starts in relation to the workspace SVG.
* @typedef {{
* left: number,
* top: number
@@ -84,7 +84,7 @@ Blockly.MetricsManager.ContainerRegion;
Blockly.MetricsManager.FixedEdges;
/**
* Common metrics used for ui elements.
* Common metrics used for UI elements.
* @typedef {{
* viewMetrics: !Blockly.MetricsManager.ContainerRegion,
* absoluteMetrics: !Blockly.MetricsManager.AbsoluteMetrics,
@@ -151,10 +151,10 @@ Blockly.MetricsManager.prototype.getToolboxMetrics = function() {
};
/**
* Gets the width and height of the workspace's parent svg element in pixel
* Gets the width and height of the workspace's parent SVG element in pixel
* coordinates. This area includes the toolbox and the visible workspace area.
* @return {!Blockly.utils.Size} The width and height of the workspace's parent
* svg element.
* SVG element.
* @public
*/
Blockly.MetricsManager.prototype.getSvgMetrics = function() {
@@ -163,7 +163,7 @@ Blockly.MetricsManager.prototype.getSvgMetrics = function() {
/**
* Gets the absolute left and absolute top in pixel coordinates.
* This is where the visible workspace starts in relation to the svg container.
* This is where the visible workspace starts in relation to the SVG container.
* @return {!Blockly.MetricsManager.AbsoluteMetrics} The absolute metrics for
* the workspace.
* @public
@@ -356,7 +356,7 @@ Blockly.MetricsManager.prototype.getPaddedContent_ = function(
* content metrics if they have been previously computed. Passing in null
* may cause the content metrics to be computed again, if it is needed.
* @return {!Blockly.MetricsManager.ContainerRegion} The metrics for the scroll
* container
* container.
*/
Blockly.MetricsManager.prototype.getScrollMetrics = function(
opt_getWorkspaceCoordinates, opt_viewMetrics, opt_contentMetrics) {
@@ -365,7 +365,7 @@ Blockly.MetricsManager.prototype.getScrollMetrics = function(
var contentMetrics = opt_contentMetrics || this.getContentMetrics();
var fixedEdges = this.getComputedFixedEdges_(viewMetrics);
// Add padding around content
// Add padding around content.
var paddedContent = this.getPaddedContent_(viewMetrics, contentMetrics);
// Use combination of fixed bounds and padded content to make scroll area.
@@ -387,8 +387,8 @@ Blockly.MetricsManager.prototype.getScrollMetrics = function(
};
/**
* Returns common metrics used by ui elements.
* @return {!Blockly.MetricsManager.UiMetrics} The ui metrics.
* Returns common metrics used by UI elements.
* @return {!Blockly.MetricsManager.UiMetrics} The UI metrics.
*/
Blockly.MetricsManager.prototype.getUiMetrics = function() {
return {
@@ -502,7 +502,7 @@ Blockly.utils.object.inherits(
/**
* Gets the bounding box of the blocks on the flyout's workspace.
* This is in workspace coordinates.
* @returns {!SVGRect|{height: number, y: number, width: number, x: number}} The
* @return {!SVGRect|{height: number, y: number, width: number, x: number}} The
* bounding box of the blocks on the workspace.
* @private
*/
@@ -556,42 +556,3 @@ Blockly.FlyoutMetricsManager.prototype.getScrollMetrics = function(
left: 0,
};
};
/**
* @override
*/
Blockly.FlyoutMetricsManager.prototype.getViewMetrics = function(
opt_getWorkspaceCoordinates) {
var svgMetrics = this.getSvgMetrics();
var scale = opt_getWorkspaceCoordinates ? this.workspace_.scale : 1;
if (this.flyout_.horizontalLayout) {
var viewWidth = svgMetrics.width - 2 * this.flyout_.SCROLLBAR_PADDING;
var viewHeight = svgMetrics.height - this.flyout_.SCROLLBAR_PADDING;
} else {
var viewWidth = svgMetrics.width - this.flyout_.SCROLLBAR_PADDING;
var viewHeight = svgMetrics.height - 2 * this.flyout_.SCROLLBAR_PADDING;
}
return {
height: viewHeight / scale,
width: viewWidth / scale,
top: -this.workspace_.scrollY / scale,
left: -this.workspace_.scrollX / scale,
};
};
/**
* @override
*/
Blockly.FlyoutMetricsManager.prototype.getAbsoluteMetrics = function() {
var scrollbarPadding = this.flyout_.SCROLLBAR_PADDING;
if (this.flyout_.horizontalLayout) {
// The viewWidth is svgWidth - 2 * scrollbarPadding. We want to put half
// of that padding to the left of the blocks.
return {top: 0, left: scrollbarPadding};
} else {
// The viewHeight is svgHeight - 2 * scrollbarPadding. We want to put half
// of that padding to the top of the blocks.
return {top: scrollbarPadding, left: 0};
}
};
+19 -13
View File
@@ -20,6 +20,7 @@ goog.require('Blockly.Events.BlockChange');
/** @suppress {extraRequire} */
goog.require('Blockly.Events.BubbleOpen');
goog.require('Blockly.Icon');
goog.require('Blockly.Options');
goog.require('Blockly.utils');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.object');
@@ -39,7 +40,7 @@ goog.requireType('Blockly.Workspace');
/**
* Class for a mutator dialog.
* @param {!Array.<string>} quarkNames List of names of sub-blocks for flyout.
* @param {!Array<string>} quarkNames List of names of sub-blocks for flyout.
* @extends {Blockly.Icon}
* @constructor
*/
@@ -49,6 +50,13 @@ Blockly.Mutator = function(quarkNames) {
};
Blockly.utils.object.inherits(Blockly.Mutator, Blockly.Icon);
/**
* Workspace in the mutator's bubble.
* @type {?Blockly.WorkspaceSvg}
* @private
*/
Blockly.Mutator.prototype.workspace_ = null;
/**
* Width of workspace.
* @private
@@ -63,7 +71,7 @@ Blockly.Mutator.prototype.workspaceHeight_ = 0;
/**
* Set the block this mutator is associated with.
* @param {Blockly.BlockSvg} block The block associated with this mutator.
* @param {!Blockly.BlockSvg} block The block associated with this mutator.
* @package
*/
Blockly.Mutator.prototype.setBlock = function(block) {
@@ -72,8 +80,8 @@ Blockly.Mutator.prototype.setBlock = function(block) {
/**
* Returns the workspace inside this mutator icon's bubble.
* @return {Blockly.WorkspaceSvg} The workspace inside this mutator icon's
* bubble.
* @return {?Blockly.WorkspaceSvg} The workspace inside this mutator icon's
* bubble or null if the mutator isn't open.
* @package
*/
Blockly.Mutator.prototype.getWorkspace = function() {
@@ -127,7 +135,7 @@ Blockly.Mutator.prototype.drawIcon_ = function(group) {
* Clicking on the icon toggles if the mutator bubble is visible.
* Disable if block is uneditable.
* @param {!Event} e Mouse click event.
* @private
* @protected
* @override
*/
Blockly.Mutator.prototype.iconClick_ = function(e) {
@@ -188,9 +196,9 @@ Blockly.Mutator.prototype.createEditor_ = function() {
this.workspace_.addChangeListener(Blockly.Events.disableOrphans);
// Mutator flyouts go inside the mutator workspace's <g> rather than in
// a top level svg. Instead of handling scale themselves, mutators
// a top level SVG. Instead of handling scale themselves, mutators
// inherit scale from the parent workspace.
// To fix this, scale needs to be applied at a different level in the dom.
// To fix this, scale needs to be applied at a different level in the DOM.
var flyoutSvg = hasFlyout ?
this.workspace_.addFlyout(Blockly.utils.Svg.G) : null;
var background = this.workspace_.createDom('blocklyMutatorBackground');
@@ -279,7 +287,7 @@ Blockly.Mutator.prototype.resizeBubble_ = function() {
*/
Blockly.Mutator.prototype.onBubbleMove_ = function() {
if (this.workspace_) {
this.workspace_.recordDeleteAreas();
this.workspace_.recordDragTargets();
}
};
@@ -465,16 +473,14 @@ Blockly.Mutator.prototype.updateBlockStyle = function() {
if (ws && ws.getAllBlocks(false)) {
var workspaceBlocks = ws.getAllBlocks(false);
for (var i = 0; i < workspaceBlocks.length; i++) {
var block = workspaceBlocks[i];
for (var i = 0, block; (block = workspaceBlocks[i]); i++) {
block.setStyle(block.getStyleName());
}
var flyout = ws.getFlyout();
if (flyout) {
var flyoutBlocks = flyout.workspace_.getAllBlocks(false);
for (var i = 0; i < flyoutBlocks.length; i++) {
var block = flyoutBlocks[i];
for (var i = 0, block; (block = flyoutBlocks[i]); i++) {
block.setStyle(block.getStyleName());
}
}
@@ -510,7 +516,7 @@ Blockly.Mutator.reconnect = function(connectionChild, block, inputName) {
* Get the parent workspace of a workspace that is inside a mutator, taking into
* account whether it is a flyout.
* @param {Blockly.Workspace} workspace The workspace that is inside a mutator.
* @return {Blockly.Workspace} The mutator's parent workspace or null.
* @return {?Blockly.Workspace} The mutator's parent workspace or null.
* @public
*/
Blockly.Mutator.findParentWs = function(workspace) {
+74 -32
View File
@@ -5,7 +5,7 @@
*/
/**
* @fileoverview Utility functions for handling variables and procedure names.
* @fileoverview Utility functions for handling variable and procedure names.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
@@ -20,11 +20,11 @@ goog.requireType('Blockly.VariableMap');
/**
* Class for a database of entity names (variables, functions, etc).
* Class for a database of entity names (variables, procedures, etc).
* @param {string} reservedWords A comma-separated string of words that are
* illegal for use as names in a language (e.g. 'new,if,this,...').
* @param {string=} opt_variablePrefix Some languages need a '$' or a namespace
* before all variable names.
* before all variable names (but not procedure names).
* @constructor
*/
Blockly.Names = function(reservedWords, opt_variablePrefix) {
@@ -52,9 +52,9 @@ Blockly.Names.DEVELOPER_VARIABLE_TYPE = 'DEVELOPER_VARIABLE';
* When JavaScript (or most other languages) is generated, variable 'foo' and
* procedure 'foo' would collide. However, Blockly has no such problems since
* variable get 'foo' and procedure call 'foo' are unambiguous.
* Therefore, Blockly keeps a separate type name to disambiguate.
* getName('foo', 'variable') -> 'foo'
* getName('foo', 'procedure') -> 'foo2'
* Therefore, Blockly keeps a separate realm name to disambiguate.
* getName('foo', 'VARIABLE') -> 'foo'
* getName('foo', 'PROCEDURE') -> 'foo2'
*/
/**
@@ -76,7 +76,7 @@ Blockly.Names.prototype.setVariableMap = function(map) {
/**
* Get the name for a user-defined variable, based on its ID.
* This should only be used for variables of type
* This should only be used for variables of realm
* Blockly.VARIABLE_CATEGORY_NAME.
* @param {string} id The ID to look up in the variable map.
* @return {?string} The name of the referenced variable, or null if there was
@@ -85,60 +85,101 @@ Blockly.Names.prototype.setVariableMap = function(map) {
*/
Blockly.Names.prototype.getNameForUserVariable_ = function(id) {
if (!this.variableMap_) {
console.log('Deprecated call to Blockly.Names.prototype.getName without ' +
console.warn('Deprecated call to Blockly.Names.prototype.getName without ' +
'defining a variable map. To fix, add the following code in your ' +
'generator\'s init() function:\n' +
'Blockly.YourGeneratorName.variableDB_.setVariableMap(' +
'Blockly.YourGeneratorName.nameDB_.setVariableMap(' +
'workspace.getVariableMap());');
return null;
}
var variable = this.variableMap_.getVariableById(id);
if (variable) {
return variable.name;
} else {
return null;
}
return null;
};
/**
* Generate names for user variables, but only ones that are being used.
* @param {!Blockly.Workspace} workspace Workspace to generate variables from.
*/
Blockly.Names.prototype.populateVariables = function(workspace) {
var variables = Blockly.Variables.allUsedVarModels(workspace);
for (var i = 0; i < variables.length; i++) {
this.getName(variables[i].getId(), Blockly.VARIABLE_CATEGORY_NAME);
}
};
/**
* Generate names for procedures.
* @param {!Blockly.Workspace} workspace Workspace to generate procedures from.
*/
Blockly.Names.prototype.populateProcedures = function(workspace) {
var procedures = Blockly.Procedures.allProcedures(workspace);
// Flatten the return vs no-return procedure lists.
procedures = procedures[0].concat(procedures[1]);
for (var i = 0; i < procedures.length; i++) {
this.getName(procedures[i][0], Blockly.PROCEDURE_CATEGORY_NAME);
}
};
/**
* Convert a Blockly entity name to a legal exportable entity name.
* @param {string} name The Blockly entity name (no constraints).
* @param {string} type The type of entity in Blockly
* ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...).
* @param {string} nameOrId The Blockly entity name (no constraints) or
* variable ID.
* @param {string} realm The realm of entity in Blockly
* ('VARIABLE', 'PROCEDURE', 'DEVELOPER_VARIABLE', etc...).
* @return {string} An entity name that is legal in the exported language.
*/
Blockly.Names.prototype.getName = function(name, type) {
if (type == Blockly.VARIABLE_CATEGORY_NAME) {
var varName = this.getNameForUserVariable_(name);
Blockly.Names.prototype.getName = function(nameOrId, realm) {
var name = nameOrId;
if (realm == Blockly.VARIABLE_CATEGORY_NAME) {
var varName = this.getNameForUserVariable_(nameOrId);
if (varName) {
// Successful ID lookup.
name = varName;
}
}
var normalized = name.toLowerCase() + '_' + type;
var normalizedName = name.toLowerCase();
var isVarType = type == Blockly.VARIABLE_CATEGORY_NAME ||
type == Blockly.Names.DEVELOPER_VARIABLE_TYPE;
var isVar = realm == Blockly.VARIABLE_CATEGORY_NAME ||
realm == Blockly.Names.DEVELOPER_VARIABLE_TYPE;
var prefix = isVarType ? this.variablePrefix_ : '';
if (normalized in this.db_) {
return prefix + this.db_[normalized];
var prefix = isVar ? this.variablePrefix_ : '';
if (!(realm in this.db_)) {
this.db_[realm] = Object.create(null);
}
var safeName = this.getDistinctName(name, type);
this.db_[normalized] = safeName.substr(prefix.length);
var realmDb = this.db_[realm];
if (normalizedName in realmDb) {
return prefix + realmDb[normalizedName];
}
var safeName = this.getDistinctName(name, realm);
realmDb[normalizedName] = safeName.substr(prefix.length);
return safeName;
};
/**
* Return a list of all known user-created names in a specified realm.
* @param {string} realm The realm of entity in Blockly
* ('VARIABLE', 'PROCEDURE', 'DEVELOPER_VARIABLE', etc...).
* @return {!Array<string>} A list of Blockly entity names (no constraints).
*/
Blockly.Names.prototype.getUserNames = function(realm) {
var realmDb = this.db_[realm] || {};
return Object.keys(realmDb);
};
/**
* Convert a Blockly entity name to a legal exportable entity name.
* Ensure that this is a new name not overlapping any previously defined name.
* Also check against list of reserved words for the current language and
* ensure name doesn't collide.
* @param {string} name The Blockly entity name (no constraints).
* @param {string} type The type of entity in Blockly
* ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...).
* @param {string} realm The realm of entity in Blockly
* ('VARIABLE', 'PROCEDURE', 'DEVELOPER_VARIABLE', etc...).
* @return {string} An entity name that is legal in the exported language.
*/
Blockly.Names.prototype.getDistinctName = function(name, type) {
Blockly.Names.prototype.getDistinctName = function(name, realm) {
var safeName = this.safeName_(name);
var i = '';
while (this.dbReverse_[safeName + i] ||
@@ -148,16 +189,16 @@ Blockly.Names.prototype.getDistinctName = function(name, type) {
}
safeName += i;
this.dbReverse_[safeName] = true;
var isVarType = type == Blockly.VARIABLE_CATEGORY_NAME ||
type == Blockly.Names.DEVELOPER_VARIABLE_TYPE;
var prefix = isVarType ? this.variablePrefix_ : '';
var isVar = realm == Blockly.VARIABLE_CATEGORY_NAME ||
realm == Blockly.Names.DEVELOPER_VARIABLE_TYPE;
var prefix = isVar ? this.variablePrefix_ : '';
return prefix + safeName;
};
/**
* Given a proposed entity name, generate a name that conforms to the
* [_A-Za-z][_A-Za-z0-9]* format that most languages consider legal for
* variables.
* variable and function names.
* @param {string} name Potentially illegal entity name.
* @return {string} Safe entity name.
* @private
@@ -186,5 +227,6 @@ Blockly.Names.prototype.safeName_ = function(name) {
* @return {boolean} True if names are the same.
*/
Blockly.Names.equals = function(name1, name2) {
// name1.localeCompare(name2) is slower.
return name1.toLowerCase() == name2.toLowerCase();
};
+3 -3
View File
@@ -123,7 +123,7 @@ Blockly.Options = function(options) {
this.readOnly = readOnly;
/** @type {number} */
this.maxBlocks = options['maxBlocks'] || Infinity;
/** @type {?Object.<string, number>} */
/** @type {?Object<string, number>} */
this.maxInstances = options['maxInstances'];
/** @type {string} */
this.pathToMedia = pathToMedia;
@@ -175,7 +175,7 @@ Blockly.Options = function(options) {
/**
* Map of plugin type to name of registered plugin or plugin class.
* @type {!Object.<string, (function(new:?, ...?)|string)>}
* @type {!Object<string, (function(new:?, ...?)|string)>}
*/
this.plugins = plugins;
};
@@ -275,7 +275,7 @@ Blockly.Options.parseMoveOptions_ = function(options, hasCategories) {
} else {
moveOptions.scrollbars = !!move['scrollbars'] || !!options['scrollbars'];
}
if (!moveOptions.scrollbars || move['wheel'] === undefined) {
// Defaults to true if single-direction scroll is enabled.
moveOptions.wheel = typeof moveOptions.scrollbars == 'object';
-137
View File
@@ -1,137 +0,0 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Manager for all items registered with the workspace.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.PluginManager');
/**
* Manager for all items registered with the workspace.
* @constructor
*/
Blockly.PluginManager = function() {
/**
* A map of the plugins registered with the workspace, mapped to id.
* @type {!Object<string, !Blockly.PluginManager.PluginDatum>}
* @private
*/
this.pluginData_ = {};
/**
* A map of types to plugin ids.
* @type {!Object<string, Array<string>>}
* @private
*/
this.typeToPluginIds_ = {};
};
/**
* An object storing plugin information.
* @typedef {{
* id: string,
* plugin: !Blockly.IPlugin,
* types: !Array<string|!Blockly.PluginManager.Type<Blockly.IPlugin>>,
* weight: number
* }}
*/
Blockly.PluginManager.PluginDatum;
/**
* Adds a plugin.
* @param {!Blockly.PluginManager.PluginDatum} pluginDataObject The plugin.
* @template T
*/
Blockly.PluginManager.prototype.addPlugin = function(pluginDataObject) {
this.pluginData_[pluginDataObject.id] = pluginDataObject;
for (var i = 0, type; (type = pluginDataObject.types[i]); i++) {
var typeKey = String(type).toLowerCase();
if (this.typeToPluginIds_[typeKey] === undefined) {
this.typeToPluginIds_[typeKey] = [pluginDataObject.id];
} else {
this.typeToPluginIds_[typeKey].push(pluginDataObject.id);
}
}
};
/**
* Gets the plugin with the given id and the given type.
* @param {string} id The id of the plugin to get.
* @return {!Blockly.IPlugin|undefined} The plugin with the given name
* or undefined if not found.
*/
Blockly.PluginManager.prototype.getPlugin = function(id) {
return this.pluginData_[id] && this.pluginData_[id].plugin;
};
/**
* Gets all the plugins of the specified type.
* @param {!Blockly.PluginManager.Type<T>} type The type of the plugin.
* @param {boolean} sorted Whether to return list ordered by weights.
* @return {!Array<T>} The plugins that match the
* specified type.
* @template T
*/
Blockly.PluginManager.prototype.getPlugins = function(type, sorted) {
var typeKey = String(type).toLowerCase();
var pluginIds = this.typeToPluginIds_[typeKey];
if (!pluginIds) {
return [];
}
var plugins = [];
if (sorted) {
var pluginDataList = [];
var pluginData = this.pluginData_;
pluginIds.forEach(function(id) {
pluginDataList.push(pluginData[id]);
});
pluginDataList.sort(function(a, b) {
return a.weight - b.weight;
});
pluginDataList.forEach(function(pluginDatum) {
plugins.push(pluginDatum.plugin);
});
} else {
var pluginData = this.pluginData_;
pluginIds.forEach(function(id) {
plugins.push(pluginData[id].plugin);
});
}
return plugins;
};
/**
* A name with the type of the element stored in the generic.
* @param {string} name The name of the plugin type.
* @constructor
* @template T
*/
Blockly.PluginManager.Type = function(name) {
/**
* @type {string}
* @private
*/
this.name_ = name;
};
/**
* Returns the name of the type.
* @return {string} The name.
* @override
*/
Blockly.PluginManager.Type.prototype.toString = function() {
return this.name_;
};
/** @type {!Blockly.PluginManager.Type<!Blockly.IPositionable>} */
Blockly.PluginManager.Type.POSITIONABLE =
new Blockly.PluginManager.Type('positionable');
+180
View File
@@ -0,0 +1,180 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview Utility functions for positioning UI elements.
* @author kozbial@google.com (Monica Kozbial)
*/
'use strict';
goog.provide('Blockly.uiPosition');
goog.require('Blockly.Scrollbar');
goog.require('Blockly.utils.Rect');
goog.require('Blockly.utils.toolbox');
goog.requireType('Blockly.MetricsManager');
goog.requireType('Blockly.WorkspaceSvg');
/**
* Enum for vertical positioning.
* @enum {number}
* @package
*/
Blockly.uiPosition.verticalPosition = {
TOP: 0,
BOTTOM: 1
};
/**
* Enum for horizontal positioning.
* @enum {number}
* @package
*/
Blockly.uiPosition.horizontalPosition = {
LEFT: 0,
RIGHT: 1
};
/**
* An object defining a horizontal and vertical positioning.
* @typedef {{
* horizontal: !Blockly.uiPosition.horizontalPosition,
* vertical: !Blockly.uiPosition.verticalPosition
* }}
* @package
*/
Blockly.uiPosition.Position;
/**
* Enum for bump rules to use for dealing with collisions.
* @enum {number}
* @package
*/
Blockly.uiPosition.bumpDirection = {
UP: 0,
DOWN: 1
};
/**
* Returns a rectangle representing reasonable position for where to place a UI
* element of the specified size given the restraints and locations of the
* scrollbars. This method does not take into account any already placed UI
* elements.
* @param {!Blockly.uiPosition.Position} position The starting
* horizontal and vertical position.
* @param {!Blockly.utils.Size} size the size of the UI element to get a start
* position for.
* @param {number} horizontalPadding The horizontal padding to use.
* @param {number} verticalPadding The vertical padding to use.
* @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace UI metrics.
* @param {!Blockly.WorkspaceSvg} workspace The workspace.
* @return {!Blockly.utils.Rect} The suggested start position.
* @package
*/
Blockly.uiPosition.getStartPositionRect = function(
position, size, horizontalPadding,
verticalPadding, metrics, workspace) {
// Horizontal positioning.
var left = 0;
var hasVerticalScrollbar =
workspace.scrollbar && workspace.scrollbar.canScrollVertically();
if (position.horizontal ===
Blockly.uiPosition.horizontalPosition.LEFT) {
left = metrics.absoluteMetrics.left + horizontalPadding;
if (hasVerticalScrollbar && workspace.RTL) {
left += Blockly.Scrollbar.scrollbarThickness;
}
} else { // position.horizontal == horizontalPosition.RIGHT
left = metrics.absoluteMetrics.left + metrics.viewMetrics.width -
size.width - horizontalPadding;
if (hasVerticalScrollbar && !workspace.RTL) {
left -= Blockly.Scrollbar.scrollbarThickness;
}
}
// Vertical positioning.
var top = 0;
if (position.vertical ===
Blockly.uiPosition.verticalPosition.TOP) {
top = metrics.absoluteMetrics.top + verticalPadding;
} else { // position.vertical == verticalPosition.BOTTOM
top = metrics.absoluteMetrics.top + metrics.viewMetrics.height -
size.height - verticalPadding;
if (workspace.scrollbar && workspace.scrollbar.canScrollHorizontally()) {
// The scrollbars are always positioned on the bottom if they exist.
top -= Blockly.Scrollbar.scrollbarThickness;
}
}
return new Blockly.utils.Rect(
top, top + size.height, left, left + size.width);
};
/**
* Returns a corner position that is on the opposite side of the workspace from
* the toolbox.
* If in horizontal orientation, defaults to the bottom corner. If in vertical
* orientation, defaults to the right corner.
* @param {!Blockly.WorkspaceSvg} workspace The workspace.
* @param {!Blockly.MetricsManager.UiMetrics} metrics The workspace metrics.
* @return {!Blockly.uiPosition.Position} The suggested corner position.
* @package
*/
Blockly.uiPosition.getCornerOppositeToolbox = function(workspace, metrics) {
var leftCorner =
metrics.toolboxMetrics.position !== Blockly.utils.toolbox.Position.LEFT &&
(!workspace.horizontalLayout || workspace.RTL);
var topCorner =
metrics.toolboxMetrics.position === Blockly.utils.toolbox.Position.BOTTOM;
var horizontalPosition = leftCorner ?
Blockly.uiPosition.horizontalPosition.LEFT :
Blockly.uiPosition.horizontalPosition.RIGHT;
var verticalPosition = topCorner ?
Blockly.uiPosition.verticalPosition.TOP :
Blockly.uiPosition.verticalPosition.BOTTOM;
return {
horizontal: horizontalPosition,
vertical: verticalPosition
};
};
/**
* Returns a position Rect based on a starting position that is bumped
* so that it doesn't intersect with any of the provided savedPositions. This
* method does not check that the bumped position is still within bounds.
* @param {!Blockly.utils.Rect} startRect The starting position to use.
* @param {number} margin The margin to use between elements when bumping.
* @param {!Blockly.uiPosition.bumpDirection} bumpDirection The direction
* to bump if there is a collision with an existing UI element.
* @param {!Array<!Blockly.utils.Rect>} savedPositions List of rectangles that
* represent the positions of UI elements already placed.
* @return {!Blockly.utils.Rect} The suggested position rectangle.
* @package
*/
Blockly.uiPosition.bumpPositionRect = function(
startRect, margin, bumpDirection, savedPositions) {
var top = startRect.top;
var left = startRect.left;
var width = startRect.right - startRect.left;
var height = startRect.bottom - startRect.top;
// Check for collision and bump if needed.
var boundingRect = startRect;
for (var i = 0, otherEl; (otherEl = savedPositions[i]); i++) {
if (boundingRect.intersects(otherEl)) {
if (bumpDirection === Blockly.uiPosition.bumpDirection.UP) {
top = otherEl.top - height - margin;
} else { // bumpDirection == bumpDirection.DOWN
top = otherEl.bottom + margin;
}
// Recheck other savedPositions
boundingRect = new Blockly.utils.Rect(
top, top + height, left, left + width);
i = -1;
}
}
return boundingRect;
};
+10 -8
View File
@@ -60,7 +60,7 @@ Blockly.Procedures.ProcedureBlock;
/**
* Find all user-created procedure definitions in a workspace.
* @param {!Blockly.Workspace} root Root workspace.
* @return {!Array.<!Array.<!Array>>} Pair of arrays, the
* @return {!Array<!Array<!Array>>} Pair of arrays, the
* first contains procedures without return variables, the second with.
* Each procedure is defined by a three-element list of name, parameter
* list, and return value boolean.
@@ -87,7 +87,7 @@ Blockly.Procedures.allProcedures = function(root) {
* @private
*/
Blockly.Procedures.procTupleComparator_ = function(ta, tb) {
return ta[0].toLowerCase().localeCompare(tb[0].toLowerCase());
return ta[0].localeCompare(tb[0], undefined, {sensitivity: 'base'});
};
/**
@@ -188,7 +188,7 @@ Blockly.Procedures.rename = function(name) {
/**
* Construct the blocks required by the flyout for the procedure category.
* @param {!Blockly.Workspace} workspace The workspace containing procedures.
* @return {!Array.<!Element>} Array of XML block elements.
* @return {!Array<!Element>} Array of XML block elements.
*/
Blockly.Procedures.flyoutCategory = function(workspace) {
var xmlList = [];
@@ -337,7 +337,7 @@ Blockly.Procedures.mutatorChangeListener_ = function(e) {
* Find all the callers of a named procedure.
* @param {string} name Name of procedure.
* @param {!Blockly.Workspace} workspace The workspace to find callers in.
* @return {!Array.<!Blockly.Block>} Array of caller blocks.
* @return {!Array<!Blockly.Block>} Array of caller blocks.
*/
Blockly.Procedures.getCallers = function(name, workspace) {
var callers = [];
@@ -391,18 +391,20 @@ Blockly.Procedures.mutateCallers = function(defBlock) {
* Find the definition block for the named procedure.
* @param {string} name Name of procedure.
* @param {!Blockly.Workspace} workspace The workspace to search.
* @return {Blockly.Block} The procedure definition block, or null not found.
* @return {?Blockly.Block} The procedure definition block, or null not found.
*/
Blockly.Procedures.getDefinition = function(name, workspace) {
// Assume that a procedure definition is a top block.
var blocks = workspace.getTopBlocks(false);
// Do not assume procedure is a top block. Some languages allow nested
// procedures. Also do not assume it is one of the built-in blocks. Only
// rely on getProcedureDef.
var blocks = workspace.getAllBlocks(false);
for (var i = 0; i < blocks.length; i++) {
if (blocks[i].getProcedureDef) {
var procedureBlock = /** @type {!Blockly.Procedures.ProcedureBlock} */ (
blocks[i]);
var tuple = procedureBlock.getProcedureDef();
if (tuple && Blockly.Names.equals(tuple[0], name)) {
return blocks[i];
return blocks[i]; // Can't use procedureBlock var due to type check.
}
}
}
+8 -3
View File
@@ -17,6 +17,7 @@ goog.requireType('Blockly.blockRendering.Renderer');
goog.requireType('Blockly.Cursor');
goog.requireType('Blockly.Events.Abstract');
goog.requireType('Blockly.Field');
goog.requireType('Blockly.IBlockDragger');
goog.requireType('Blockly.IConnectionChecker');
goog.requireType('Blockly.IFlyout');
goog.requireType('Blockly.IMetricsManager');
@@ -33,7 +34,7 @@ goog.requireType('Blockly.ToolboxItem');
*
* @type {Object<string, Object<string, function(new:?)>>}
*/
Blockly.registry.typeMap_ = {};
Blockly.registry.typeMap_ = Object.create(null);
/**
* The string used to register the default class for a type of plugin.
@@ -101,6 +102,10 @@ Blockly.registry.Type.FLYOUTS_HORIZONTAL_TOOLBOX =
Blockly.registry.Type.METRICS_MANAGER =
new Blockly.registry.Type('metricsManager');
/** @type {!Blockly.registry.Type<Blockly.IBlockDragger>} */
Blockly.registry.Type.BLOCK_DRAGGER =
new Blockly.registry.Type('blockDragger');
/**
* Registers a class based on a type and name.
* @param {string|!Blockly.registry.Type<T>} type The type of the plugin.
@@ -137,7 +142,7 @@ Blockly.registry.register = function(
var typeRegistry = Blockly.registry.typeMap_[type];
// If the type registry has not been created, create it.
if (!typeRegistry) {
typeRegistry = Blockly.registry.typeMap_[type] = {};
typeRegistry = Blockly.registry.typeMap_[type] = Object.create(null);
}
// Validate that the given class has all the required properties.
@@ -260,7 +265,7 @@ Blockly.registry.getClass = function(type, name, opt_throwIfMissing) {
* @param {string} name The plugin's name. (Ex. logic_category)
* @param {boolean=} opt_throwIfMissing Whether or not to throw an error if we
* are unable to find the object.
* @returns {T} The object with the given name and type or null if none exists.
* @return {?T} The object with the given name and type or null if none exists.
* @template T
*/
Blockly.registry.getObject = function(type, name, opt_throwIfMissing) {
+23 -9
View File
@@ -119,7 +119,7 @@ Blockly.RenderedConnection.prototype.getSourceBlock = function() {
/**
* Returns the block that this connection connects to.
* @return {Blockly.BlockSvg} The connected block or null if none is connected.
* @return {?Blockly.BlockSvg} The connected block or null if none is connected.
* @override
*/
Blockly.RenderedConnection.prototype.targetBlock = function() {
@@ -386,7 +386,7 @@ Blockly.RenderedConnection.prototype.stopTrackingAll = function() {
/**
* Start tracking this connection, as well as all down-stream connections on
* any block attached to this connection. This happens when a block is expanded.
* @return {!Array.<!Blockly.Block>} List of blocks to render.
* @return {!Array<!Blockly.Block>} List of blocks to render.
*/
Blockly.RenderedConnection.prototype.startTrackingAll = function() {
this.setTracking(true);
@@ -449,21 +449,34 @@ Blockly.RenderedConnection.prototype.isConnectionAllowed = function(candidate,
/**
* Behavior after a connection attempt fails.
* Bumps this connection away from the other connection. Called when an
* attempted connection fails.
* @param {!Blockly.Connection} otherConnection Connection that this connection
* failed to connect to.
* @package
*/
Blockly.RenderedConnection.prototype.onFailedConnect = function(
otherConnection) {
this.bumpAwayFrom(otherConnection);
};
Blockly.RenderedConnection.prototype.onFailedConnect =
function(otherConnection) {
var block = this.getSourceBlock();
if (Blockly.Events.recordUndo) {
var group = Blockly.Events.getGroup();
setTimeout(function() {
if (!block.isDisposed() && !block.getParent()) {
Blockly.Events.setGroup(group);
this.bumpAwayFrom(otherConnection);
Blockly.Events.setGroup(false);
}
}.bind(this), Blockly.BUMP_DELAY);
}
};
/**
* Disconnect two blocks that are connected by this connection.
* @param {!Blockly.Block} parentBlock The superior block.
* @param {!Blockly.Block} childBlock The inferior block.
* @private
* @protected
* @override
*/
Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock,
childBlock) {
@@ -484,7 +497,8 @@ Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock,
/**
* Respawn the shadow block if there was one connected to the this connection.
* Render/rerender blocks as needed.
* @private
* @protected
* @override
*/
Blockly.RenderedConnection.prototype.respawnShadow_ = function() {
Blockly.RenderedConnection.superClass_.respawnShadow_.call(this);
@@ -507,7 +521,7 @@ Blockly.RenderedConnection.prototype.respawnShadow_ = function() {
* Type checking does not apply, since this function is used for bumping.
* @param {number} maxLimit The maximum radius to another connection, in
* workspace units.
* @return {!Array.<!Blockly.Connection>} List of connections.
* @return {!Array<!Blockly.Connection>} List of connections.
* @package
*/
Blockly.RenderedConnection.prototype.neighbours = function(maxLimit) {
+6 -6
View File
@@ -261,14 +261,14 @@ Blockly.blockRendering.ConstantProvider = function() {
* to be the height of the text based on the font used.
* @type {number}
*/
this.FIELD_TEXT_HEIGHT = -1; // Dynamically set
this.FIELD_TEXT_HEIGHT = -1; // Dynamically set.
/**
* Text baseline. This constant is dynamically set in ``setFontConstants_``
* to be the baseline of the text based on the font used.
* @type {number}
*/
this.FIELD_TEXT_BASELINE = -1; // Dynamically set
this.FIELD_TEXT_BASELINE = -1; // Dynamically set.
/**
* A field's border rect corner radius.
@@ -587,10 +587,10 @@ Blockly.blockRendering.ConstantProvider.prototype.setTheme = function(
/**
* The block styles map.
* @type {Object.<string, Blockly.Theme.BlockStyle>}
* @type {Object<string, !Blockly.Theme.BlockStyle>}
* @package
*/
this.blockStyles = {};
this.blockStyles = Object.create(null);
var blockStyles = theme.blockStyles;
for (var key in blockStyles) {
@@ -855,7 +855,7 @@ Blockly.blockRendering.ConstantProvider.prototype.makePuzzleTab = function() {
var halfHeight = height / 2;
var control1Y = halfHeight + overlap;
var control2Y = halfHeight + 0.5;
var control3Y = overlap; // 2.5
var control3Y = overlap; // 2.5
var endPoint1 = Blockly.utils.svgPaths.point(-width, forward * halfHeight);
var endPoint2 = Blockly.utils.svgPaths.point(width, forward * halfHeight);
@@ -1181,7 +1181,7 @@ Blockly.blockRendering.ConstantProvider.prototype.injectCSS_ = function(
/**
* Get any renderer specific CSS to inject when the renderer is initialized.
* @param {string} selector CSS selector to use.
* @return {!Array.<string>} Array of CSS strings.
* @return {!Array<string>} Array of CSS strings.
* @protected
*/
Blockly.blockRendering.ConstantProvider.prototype.getCSS_ = function(selector) {
+3 -3
View File
@@ -38,7 +38,7 @@ goog.requireType('Blockly.RenderedConnection');
Blockly.blockRendering.Debug = function(constants) {
/**
* An array of SVG elements that have been created by this object.
* @type {Array.<!SVGElement>}
* @type {Array<!SVGElement>}
* @private
*/
this.debugElements_ = [];
@@ -62,7 +62,7 @@ Blockly.blockRendering.Debug = function(constants) {
/**
* Configuration object containing booleans to enable and disable debug
* rendering of specific rendering components.
* @type {!Object.<string, boolean>}
* @type {!Object<string, boolean>}
*/
Blockly.blockRendering.Debug.config = {
rowSpacers: true,
@@ -420,7 +420,7 @@ Blockly.blockRendering.Debug.prototype.drawDebug = function(block, info) {
/**
* Show a debug filter to highlight that a block has been rendered.
* @param {!SVGElement} svgPath The block's svg path.
* @param {!SVGElement} svgPath The block's SVG path.
* @package
*/
Blockly.blockRendering.Debug.prototype.drawRender = function(svgPath) {
+2 -2
View File
@@ -227,7 +227,7 @@ Blockly.blockRendering.Drawer.prototype.drawRightSideRow_ = function(row) {
/**
* Add steps for the bottom edge of a block, possibly including a notch
* for the next connection
* for the next connection.
* @protected
*/
Blockly.blockRendering.Drawer.prototype.drawBottom_ = function() {
@@ -449,7 +449,7 @@ Blockly.blockRendering.Drawer.prototype.positionNextConnection_ = function() {
if (bottomRow.connection) {
var connInfo = bottomRow.connection;
var x = connInfo.xPos; // Already contains info about startX
var x = connInfo.xPos; // Already contains info about startX.
var connX = (this.info_.RTL ? -x : x);
connInfo.connectionModel.setOffsetInBlock(connX, bottomRow.baseline);
}
+8 -8
View File
@@ -47,14 +47,14 @@ Blockly.blockRendering.IPathObject.prototype.constants;
Blockly.blockRendering.IPathObject.prototype.style;
/**
* Holds the cursors svg element when the cursor is attached to the block.
* Holds the cursors SVG element when the cursor is attached to the block.
* This is null if there is no cursor on the block.
* @type {SVGElement}
*/
Blockly.blockRendering.IPathObject.prototype.cursorSvg;
/**
* Holds the markers svg element when the marker is attached to the block.
* Holds the markers SVG element when the marker is attached to the block.
* This is null if there is no marker on the block.
* @type {SVGElement}
*/
@@ -89,17 +89,17 @@ Blockly.blockRendering.IPathObject.prototype.setStyle;
Blockly.blockRendering.IPathObject.prototype.flipRTL;
/**
* Add the cursor svg to this block's svg group.
* @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
* block svg group.
* Add the cursor SVG to this block's SVG group.
* @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the
* block SVG group.
* @package
*/
Blockly.blockRendering.IPathObject.prototype.setCursorSvg;
/**
* Add the marker svg to this block's svg group.
* @param {SVGElement} markerSvg The svg root of the marker to be added to the
* block svg group.
* Add the marker SVG to this block's SVG group.
* @param {SVGElement} markerSvg The SVG root of the marker to be added to the
* block SVG group.
* @package
*/
Blockly.blockRendering.IPathObject.prototype.setMarkerSvg;
+19 -30
View File
@@ -14,10 +14,12 @@ goog.provide('Blockly.blockRendering.RenderInfo');
goog.require('Blockly.blockRendering.BottomRow');
goog.require('Blockly.blockRendering.ExternalValueInput');
goog.require('Blockly.blockRendering.Field');
goog.require('Blockly.blockRendering.Hat');
goog.require('Blockly.blockRendering.InlineInput');
goog.require('Blockly.blockRendering.InputRow');
goog.require('Blockly.blockRendering.InRowSpacer');
goog.require('Blockly.blockRendering.JaggedEdge');
goog.require('Blockly.blockRendering.Measurable');
goog.require('Blockly.blockRendering.NextConnection');
goog.require('Blockly.blockRendering.OutputConnection');
@@ -133,19 +135,19 @@ Blockly.blockRendering.RenderInfo = function(renderer, block) {
/**
* An array of Row objects containing sizing information.
* @type {!Array.<!Blockly.blockRendering.Row>}
* @type {!Array<!Blockly.blockRendering.Row>}
*/
this.rows = [];
/**
* An array of input rows on the block.
* @type {!Array.<!Blockly.blockRendering.InputRow>}
* @type {!Array<!Blockly.blockRendering.InputRow>}
*/
this.inputRows = [];
/**
* An array of measurable objects containing hidden icons.
* @type {!Array.<!Blockly.blockRendering.Icon>}
* @type {!Array<!Blockly.blockRendering.Icon>}
*/
this.hiddenIcons = [];
@@ -208,14 +210,12 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() {
// Icons always go on the first row, before anything else.
var icons = this.block_.getIcons();
if (icons.length) {
for (var i = 0, icon; (icon = icons[i]); i++) {
var iconInfo = new Blockly.blockRendering.Icon(this.constants_, icon);
if (this.isCollapsed && icon.collapseHidden) {
this.hiddenIcons.push(iconInfo);
} else {
activeRow.elements.push(iconInfo);
}
for (var i = 0, icon; (icon = icons[i]); i++) {
var iconInfo = new Blockly.blockRendering.Icon(this.constants_, icon);
if (this.isCollapsed && icon.collapseHidden) {
this.hiddenIcons.push(iconInfo);
} else {
activeRow.elements.push(iconInfo);
}
}
@@ -262,17 +262,12 @@ Blockly.blockRendering.RenderInfo.prototype.createRows_ = function() {
Blockly.blockRendering.RenderInfo.prototype.populateTopRow_ = function() {
var hasPrevious = !!this.block_.previousConnection;
var hasHat = (this.block_.hat ?
this.block_.hat === 'cap' : this.constants_.ADD_START_HATS) &&
!this.outputConnection && !hasPrevious;
var leftSquareCorner = this.topRow.hasLeftSquareCorner(this.block_);
this.block_.hat === 'cap' : this.constants_.ADD_START_HATS) &&
!this.outputConnection && !hasPrevious;
if (leftSquareCorner) {
this.topRow.elements.push(
new Blockly.blockRendering.SquareCorner(this.constants_));
} else {
this.topRow.elements.push(
new Blockly.blockRendering.RoundCorner(this.constants_));
}
var cornerClass = this.topRow.hasLeftSquareCorner(this.block_) ?
Blockly.blockRendering.SquareCorner : Blockly.blockRendering.RoundCorner;
this.topRow.elements.push(new cornerClass(this.constants_));
if (hasHat) {
var hat = new Blockly.blockRendering.Hat(this.constants_);
@@ -299,15 +294,9 @@ Blockly.blockRendering.RenderInfo.prototype.populateTopRow_ = function() {
this.topRow.minHeight = this.constants_.TOP_ROW_MIN_HEIGHT;
}
var rightSquareCorner = this.topRow.hasRightSquareCorner(this.block_);
if (rightSquareCorner) {
this.topRow.elements.push(
new Blockly.blockRendering.SquareCorner(this.constants_, 'right'));
} else {
this.topRow.elements.push(
new Blockly.blockRendering.RoundCorner(this.constants_, 'right'));
}
cornerClass = this.topRow.hasRightSquareCorner(this.block_) ?
Blockly.blockRendering.SquareCorner : Blockly.blockRendering.RoundCorner;
this.topRow.elements.push(new cornerClass(this.constants_, 'right'));
};
/**
+6 -6
View File
@@ -97,9 +97,9 @@ Blockly.blockRendering.PathObject.prototype.flipRTL = function() {
};
/**
* Add the cursor svg to this block's svg group.
* @param {SVGElement} cursorSvg The svg root of the cursor to be added to the
* block svg group.
* Add the cursor SVG to this block's SVG group.
* @param {SVGElement} cursorSvg The SVG root of the cursor to be added to the
* block SVG group.
* @package
*/
Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) {
@@ -113,9 +113,9 @@ Blockly.blockRendering.PathObject.prototype.setCursorSvg = function(cursorSvg) {
};
/**
* Add the marker svg to this block's svg group.
* @param {SVGElement} markerSvg The svg root of the marker to be added to the
* block svg group.
* Add the marker SVG to this block's SVG group.
* @param {SVGElement} markerSvg The SVG root of the marker to be added to the
* block SVG group.
* @package
*/
Blockly.blockRendering.PathObject.prototype.setMarkerSvg = function(markerSvg) {
+5 -23
View File
@@ -246,29 +246,11 @@ Blockly.blockRendering.Renderer.prototype.shouldHighlightConnection =
*/
Blockly.blockRendering.Renderer.prototype.orphanCanConnectAtEnd =
function(topBlock, orphanBlock, localType) {
var orphanConnection = null;
var lastConnection = null;
if (localType ==
Blockly.connectionTypes
.OUTPUT_VALUE) { // We are replacing an output.
orphanConnection = orphanBlock.outputConnection;
// TODO: I don't think this function necessarily has the correct logic,
// but for now it is being kept for behavioral backwards-compat.
lastConnection = Blockly.Connection
.lastConnectionInRow(
/** @type {!Blockly.Block} **/ (topBlock), orphanBlock);
} else { // We are replacing a previous.
orphanConnection = orphanBlock.previousConnection;
// TODO: This lives on the block while lastConnectionInRow lives on
// on the connection. Something is fishy.
lastConnection = topBlock.lastConnectionInStack();
}
if (!lastConnection) {
return false;
}
return orphanConnection.getConnectionChecker().canConnect(
lastConnection, orphanConnection, false);
var orphanConnection = localType === Blockly.connectionTypes.OUTPUT_VALUE ?
orphanBlock.outputConnection : orphanBlock.previousConnection;
return !!Blockly.Connection.getConnectionForOrphanedConnection(
/** @type {!Blockly.Block} **/ (topBlock),
/** @type {!Blockly.Connection} **/ (orphanConnection));
};
/**
+3 -2
View File
@@ -120,7 +120,8 @@ Blockly.geras.Drawer.prototype.drawBottom_ = function() {
/**
* Add steps for the left side of the block, which may include an output
* connection
* @private
* @protected
* @override
*/
Blockly.geras.Drawer.prototype.drawLeft_ = function() {
this.highlighter_.drawLeft();
@@ -196,7 +197,7 @@ Blockly.geras.Drawer.prototype.positionNextConnection_ = function() {
if (bottomRow.connection) {
var connInfo = bottomRow.connection;
var x = connInfo.xPos; // Already contains info about startX
var x = connInfo.xPos; // Already contains info about startX.
var connX = (this.info_.RTL ? -x : x) +
(this.constants_.DARK_PATH_OFFSET / 2);
connInfo.connectionModel.setOffsetInBlock(
+1 -1
View File
@@ -47,7 +47,7 @@ Blockly.blockRendering.Row = function(constants) {
/**
* An array of elements contained in this row.
* @package
* @type {!Array.<!Blockly.blockRendering.Measurable>}
* @type {!Array<!Blockly.blockRendering.Measurable>}
*/
this.elements = [];
+15 -15
View File
@@ -214,23 +214,23 @@ Blockly.zelos.ConstantProvider = function() {
* @package
*/
this.SHAPE_IN_SHAPE_PADDING = {
1: { // Outer shape: hexagon.
0: 5 * this.GRID_UNIT, // Field in hexagon.
1: 2 * this.GRID_UNIT, // Hexagon in hexagon.
2: 5 * this.GRID_UNIT, // Round in hexagon.
3: 5 * this.GRID_UNIT // Square in hexagon.
1: { // Outer shape: hexagon.
0: 5 * this.GRID_UNIT, // Field in hexagon.
1: 2 * this.GRID_UNIT, // Hexagon in hexagon.
2: 5 * this.GRID_UNIT, // Round in hexagon.
3: 5 * this.GRID_UNIT // Square in hexagon.
},
2: { // Outer shape: round.
0: 3 * this.GRID_UNIT, // Field in round.
1: 3 * this.GRID_UNIT, // Hexagon in round.
2: 1 * this.GRID_UNIT, // Round in round.
3: 2 * this.GRID_UNIT // Square in round.
2: { // Outer shape: round.
0: 3 * this.GRID_UNIT, // Field in round.
1: 3 * this.GRID_UNIT, // Hexagon in round.
2: 1 * this.GRID_UNIT, // Round in round.
3: 2 * this.GRID_UNIT // Square in round.
},
3: { // Outer shape: square.
0: 2 * this.GRID_UNIT, // Field in square.
1: 2 * this.GRID_UNIT, // Hexagon in square.
2: 2 * this.GRID_UNIT, // Round in square.
3: 2 * this.GRID_UNIT // Square in square.
3: { // Outer shape: square.
0: 2 * this.GRID_UNIT, // Field in square.
1: 2 * this.GRID_UNIT, // Hexagon in square.
2: 2 * this.GRID_UNIT, // Round in square.
3: 2 * this.GRID_UNIT // Square in square.
}
};
+9 -13
View File
@@ -45,24 +45,24 @@ Blockly.zelos.PathObject = function(root, style, constants) {
/**
* The selected path of the block.
* @type {SVGElement}
* @type {?SVGElement}
* @private
*/
this.svgPathSelected_ = null;
/**
* The outline paths on the block.
* @type {!Object.<string,!SVGElement>}
* @type {!Object<string, !SVGElement>}
* @private
*/
this.outlines_ = {};
this.outlines_ = Object.create(null);
/**
* A set used to determine which outlines were used during a draw pass. The
* set is initialized with a reference to all the outlines in
* `this.outlines_`. Every time we use an outline during the draw pass, the
* reference is removed from this set.
* @type {Object.<string, number>}
* @type {Object<string, number>}
* @private
*/
this.remainingOutlines_ = null;
@@ -98,8 +98,7 @@ Blockly.zelos.PathObject.prototype.applyColour = function(block) {
}
// Apply colour to outlines.
for (var i = 0, keys = Object.keys(this.outlines_),
key; (key = keys[i]); i++) {
for (var key in this.outlines_) {
this.outlines_[key].setAttribute('fill', this.style.colourTertiary);
}
};
@@ -110,8 +109,7 @@ Blockly.zelos.PathObject.prototype.applyColour = function(block) {
Blockly.zelos.PathObject.prototype.flipRTL = function() {
Blockly.zelos.PathObject.superClass_.flipRTL.call(this);
// Mirror each input outline path.
for (var i = 0, keys = Object.keys(this.outlines_),
key; (key = keys[i]); i++) {
for (var key in this.outlines_) {
this.outlines_[key].setAttribute('transform', 'scale(-1 1)');
}
};
@@ -175,9 +173,8 @@ Blockly.zelos.PathObject.prototype.updateShapeForInputHighlight = function(
* @package
*/
Blockly.zelos.PathObject.prototype.beginDrawing = function() {
this.remainingOutlines_ = {};
for (var i = 0, keys = Object.keys(this.outlines_),
key; (key = keys[i]); i++) {
this.remainingOutlines_ = Object.create(null);
for (var key in this.outlines_) {
// The value set here isn't used anywhere, we are just using the
// object as a Set data structure.
this.remainingOutlines_[key] = 1;
@@ -192,8 +189,7 @@ Blockly.zelos.PathObject.prototype.endDrawing = function() {
// Go through all remaining outlines that were not used this draw pass, and
// remove them.
if (this.remainingOutlines_) {
for (var i = 0, keys = Object.keys(this.remainingOutlines_),
key; (key = keys[i]); i++) {
for (var key in this.remainingOutlines_) {
this.removeOutlinePath_(key);
}
}

Some files were not shown because too many files have changed in this diff Show More