From 10b3a9aa9ab46677e1e9234c48589675bc0c5613 Mon Sep 17 00:00:00 2001 From: alschmiedt Date: Wed, 4 Dec 2019 14:50:58 -0800 Subject: [PATCH] Refactor marker and cursor (#3484) * Refactor marker and cursor --- blockly_uncompressed.js | 16 +- core/blockly.js | 6 - core/css.js | 2 +- core/flyout_base.js | 4 +- core/keyboard_nav/cursor.js | 139 +++----- core/keyboard_nav/marker.js | 124 +++++++ core/keyboard_nav/marker_cursor.js | 76 ---- .../common/{cursor_svg.js => marker_svg.js} | 326 +++++++++--------- core/renderers/common/renderer.js | 19 +- .../zelos/{cursor_svg.js => marker_svg.js} | 70 ++-- core/renderers/zelos/renderer.js | 15 +- core/workspace.js | 11 +- core/workspace_svg.js | 12 +- 13 files changed, 399 insertions(+), 421 deletions(-) create mode 100644 core/keyboard_nav/marker.js delete mode 100644 core/keyboard_nav/marker_cursor.js rename core/renderers/common/{cursor_svg.js => marker_svg.js} (59%) rename core/renderers/zelos/{cursor_svg.js => marker_svg.js} (59%) diff --git a/blockly_uncompressed.js b/blockly_uncompressed.js index 3c9d17842..aa1c60289 100644 --- a/blockly_uncompressed.js +++ b/blockly_uncompressed.js @@ -61,7 +61,7 @@ goog.addDependency("../../core/field_number.js", ['Blockly.FieldNumber'], ['Bloc goog.addDependency("../../core/field_registry.js", ['Blockly.fieldRegistry'], []); goog.addDependency("../../core/field_textinput.js", ['Blockly.FieldTextInput'], ['Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Field', 'Blockly.fieldRegistry', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.aria', 'Blockly.utils.Coordinate', 'Blockly.utils.dom', 'Blockly.utils.KeyCodes', 'Blockly.utils.object', 'Blockly.utils.Size', 'Blockly.utils.userAgent']); goog.addDependency("../../core/field_variable.js", ['Blockly.FieldVariable'], ['Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.FieldDropdown', 'Blockly.fieldRegistry', 'Blockly.Msg', 'Blockly.utils', 'Blockly.utils.object', 'Blockly.utils.Size', 'Blockly.VariableModel', 'Blockly.Variables', 'Blockly.Xml']); -goog.addDependency("../../core/flyout_base.js", ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.blockRendering', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutCursor', 'Blockly.Gesture', 'Blockly.MarkerCursor', 'Blockly.Scrollbar', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.dom', 'Blockly.WorkspaceSvg', 'Blockly.Xml']); +goog.addDependency("../../core/flyout_base.js", ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.blockRendering', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.VarCreate', 'Blockly.FlyoutCursor', 'Blockly.Gesture', 'Blockly.Marker', 'Blockly.Scrollbar', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.dom', 'Blockly.WorkspaceSvg', 'Blockly.Xml']); goog.addDependency("../../core/flyout_button.js", ['Blockly.FlyoutButton'], ['Blockly.Css', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']); goog.addDependency("../../core/flyout_dragger.js", ['Blockly.FlyoutDragger'], ['Blockly.utils.object', 'Blockly.WorkspaceDragger']); goog.addDependency("../../core/flyout_horizontal.js", ['Blockly.HorizontalFlyout'], ['Blockly.Block', 'Blockly.Flyout', 'Blockly.Scrollbar', 'Blockly.utils', 'Blockly.utils.object', 'Blockly.utils.Rect', 'Blockly.WidgetDiv']); @@ -76,10 +76,10 @@ goog.addDependency("../../core/insertion_marker_manager.js", ['Blockly.Insertion goog.addDependency("../../core/keyboard_nav/action.js", ['Blockly.Action'], []); goog.addDependency("../../core/keyboard_nav/ast_node.js", ['Blockly.ASTNode'], ['Blockly.utils.Coordinate']); goog.addDependency("../../core/keyboard_nav/basic_cursor.js", ['Blockly.BasicCursor'], ['Blockly.ASTNode']); -goog.addDependency("../../core/keyboard_nav/cursor.js", ['Blockly.Cursor'], ['Blockly.ASTNode', 'Blockly.navigation']); +goog.addDependency("../../core/keyboard_nav/cursor.js", ['Blockly.Cursor'], ['Blockly.Action', 'Blockly.ASTNode', 'Blockly.Marker', 'Blockly.navigation', 'Blockly.utils.object']); goog.addDependency("../../core/keyboard_nav/flyout_cursor.js", ['Blockly.FlyoutCursor'], ['Blockly.Cursor', 'Blockly.navigation', 'Blockly.utils.object']); goog.addDependency("../../core/keyboard_nav/key_map.js", ['Blockly.user.keyMap'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object']); -goog.addDependency("../../core/keyboard_nav/marker_cursor.js", ['Blockly.MarkerCursor'], ['Blockly.Cursor', 'Blockly.utils.object']); +goog.addDependency("../../core/keyboard_nav/marker.js", ['Blockly.Marker'], ['Blockly.ASTNode', 'Blockly.navigation']); goog.addDependency("../../core/keyboard_nav/navigation.js", ['Blockly.navigation'], ['Blockly.Action', 'Blockly.ASTNode', 'Blockly.utils.Coordinate', 'Blockly.user.keyMap']); goog.addDependency("../../core/keyboard_nav/tab_navigate_cursor.js", ['Blockly.TabNavigateCursor'], ['Blockly.ASTNode', 'Blockly.BasicCursor', 'Blockly.utils.object']); goog.addDependency("../../core/msg.js", ['Blockly.Msg'], ['Blockly.utils.global']); @@ -90,13 +90,13 @@ goog.addDependency("../../core/procedures.js", ['Blockly.Procedures'], ['Blockly goog.addDependency("../../core/rendered_connection.js", ['Blockly.RenderedConnection'], ['Blockly.Connection', 'Blockly.Events', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.dom', 'Blockly.utils.object']); goog.addDependency("../../core/renderers/common/block_rendering.js", ['Blockly.blockRendering'], ['Blockly.utils.object']); goog.addDependency("../../core/renderers/common/constants.js", ['Blockly.blockRendering.ConstantProvider'], ['Blockly.utils.dom', 'Blockly.utils.svgPaths', 'Blockly.utils.userAgent']); -goog.addDependency("../../core/renderers/common/cursor_svg.js", ['Blockly.blockRendering.CursorSvg'], ['Blockly.ASTNode']); goog.addDependency("../../core/renderers/common/debugger.js", ['Blockly.blockRendering.Debug'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types']); goog.addDependency("../../core/renderers/common/drawer.js", ['Blockly.blockRendering.Drawer'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.TopRow', '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.InlineInput', 'Blockly.blockRendering.InRowSpacer', '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.StatementInput', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types']); +goog.addDependency("../../core/renderers/common/marker_svg.js", ['Blockly.blockRendering.MarkerSvg'], ['Blockly.ASTNode']); goog.addDependency("../../core/renderers/common/path_object.js", ['Blockly.blockRendering.PathObject'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.IPathObject', 'Blockly.Theme', 'Blockly.utils.dom']); -goog.addDependency("../../core/renderers/common/renderer.js", ['Blockly.blockRendering.Renderer'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.CursorSvg', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo']); +goog.addDependency("../../core/renderers/common/renderer.js", ['Blockly.blockRendering.Renderer'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.MarkerSvg', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.IPathObject', 'Blockly.blockRendering.PathObject', 'Blockly.blockRendering.RenderInfo']); goog.addDependency("../../core/renderers/geras/constants.js", ['Blockly.geras.ConstantProvider'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.utils.object']); goog.addDependency("../../core/renderers/geras/drawer.js", ['Blockly.geras.Drawer'], ['Blockly.blockRendering.ConstantProvider', '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']); @@ -118,12 +118,12 @@ goog.addDependency("../../core/renderers/minimalist/renderer.js", ['Blockly.mini goog.addDependency("../../core/renderers/thrasos/info.js", ['Blockly.thrasos', 'Blockly.thrasos.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', '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.utils.dom', 'Blockly.utils.object', 'Blockly.utils.svgPaths']); -goog.addDependency("../../core/renderers/zelos/cursor_svg.js", ['Blockly.zelos.CursorSvg'], ['Blockly.blockRendering.CursorSvg']); goog.addDependency("../../core/renderers/zelos/drawer.js", ['Blockly.zelos.Drawer'], ['Blockly.blockRendering.ConstantProvider', 'Blockly.blockRendering.Drawer', 'Blockly.blockRendering.Types', 'Blockly.utils.object', 'Blockly.zelos.RenderInfo']); goog.addDependency("../../core/renderers/zelos/info.js", ['Blockly.zelos', 'Blockly.zelos.RenderInfo'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.ExternalValueInput', 'Blockly.blockRendering.InlineInput', 'Blockly.blockRendering.InputRow', 'Blockly.blockRendering.Measurable', 'Blockly.blockRendering.NextConnection', 'Blockly.blockRendering.OutputConnection', 'Blockly.blockRendering.PreviousConnection', 'Blockly.blockRendering.RenderInfo', 'Blockly.blockRendering.RoundCorner', 'Blockly.blockRendering.Row', 'Blockly.blockRendering.SquareCorner', 'Blockly.blockRendering.SpacerRow', 'Blockly.blockRendering.StatementInput', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.Types', 'Blockly.utils.object', 'Blockly.zelos.AfterStatementSpacerRow', 'Blockly.zelos.BeforeStatementSpacerRow', 'Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow']); +goog.addDependency("../../core/renderers/zelos/marker_svg.js", ['Blockly.zelos.MarkerSvg'], ['Blockly.blockRendering.MarkerSvg']); goog.addDependency("../../core/renderers/zelos/measurables/rows.js", ['Blockly.zelos.BottomRow', 'Blockly.zelos.TopRow', 'Blockly.zelos.AfterStatementSpacerRow', 'Blockly.zelos.BeforeStatementSpacerRow'], ['Blockly.blockRendering.BottomRow', 'Blockly.blockRendering.TopRow', 'Blockly.blockRendering.SpacerRow', 'Blockly.utils.object']); goog.addDependency("../../core/renderers/zelos/path_object.js", ['Blockly.zelos.PathObject'], ['Blockly.blockRendering.PathObject', 'Blockly.zelos.ConstantProvider', 'Blockly.utils.dom', 'Blockly.utils.object']); -goog.addDependency("../../core/renderers/zelos/renderer.js", ['Blockly.zelos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo', 'Blockly.zelos.CursorSvg']); +goog.addDependency("../../core/renderers/zelos/renderer.js", ['Blockly.zelos.Renderer'], ['Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo', 'Blockly.zelos.MarkerSvg']); goog.addDependency("../../core/requires.js", ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.HorizontalFlyout', 'Blockly.VerticalFlyout', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.ZoomControls', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldLabelSerializable', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldVariable', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer', 'Blockly.Themes.Classic', 'Blockly.Themes.Dark', 'Blockly.Themes.Deuteranopia', 'Blockly.Themes.HighContrast', 'Blockly.Themes.Tritanopia']); goog.addDependency("../../core/scrollbar.js", ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Touch', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.dom']); goog.addDependency("../../core/theme.js", ['Blockly.Theme'], ['Blockly.utils', 'Blockly.utils.colour']); @@ -165,7 +165,7 @@ goog.addDependency("../../core/variables.js", ['Blockly.Variables'], ['Blockly.B goog.addDependency("../../core/variables_dynamic.js", ['Blockly.VariablesDynamic'], ['Blockly.Variables', 'Blockly.Blocks', 'Blockly.Msg', 'Blockly.utils.xml', 'Blockly.VariableModel']); goog.addDependency("../../core/warning.js", ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Events', 'Blockly.Events.Ui', 'Blockly.Icon', 'Blockly.utils.dom', 'Blockly.utils.object']); goog.addDependency("../../core/widgetdiv.js", ['Blockly.WidgetDiv'], ['Blockly.utils.style']); -goog.addDependency("../../core/workspace.js", ['Blockly.Workspace'], ['Blockly.Cursor', 'Blockly.MarkerCursor', 'Blockly.Events', 'Blockly.utils', 'Blockly.utils.math', 'Blockly.VariableMap']); +goog.addDependency("../../core/workspace.js", ['Blockly.Workspace'], ['Blockly.Cursor', 'Blockly.Marker', 'Blockly.Events', 'Blockly.utils', 'Blockly.utils.math', 'Blockly.VariableMap']); goog.addDependency("../../core/workspace_audio.js", ['Blockly.WorkspaceAudio'], ['Blockly.utils', 'Blockly.utils.global', 'Blockly.utils.userAgent']); 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.dom']); diff --git a/core/blockly.js b/core/blockly.js index 5f707a500..63c9578fa 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -66,12 +66,6 @@ Blockly.mainWorkspace = null; */ Blockly.selected = null; -/** - * Current cursor. - * @type {Blockly.Cursor} - */ -Blockly.cursor = null; - /** * All of the connections on blocks that are currently being dragged. * @type {!Array.} diff --git a/core/css.js b/core/css.js index 14eb3bb78..3e6314f65 100644 --- a/core/css.js +++ b/core/css.js @@ -485,7 +485,7 @@ Blockly.Css.CONTENT = [ 'padding-right: 28px;', '}', - '.blocklyVerticalCursor {', + '.blocklyVerticalMarker {', 'stroke-width: 3px;', 'fill: rgba(255,255,255,.5);', '}', diff --git a/core/flyout_base.js b/core/flyout_base.js index 85b69cd77..310cb6c33 100644 --- a/core/flyout_base.js +++ b/core/flyout_base.js @@ -30,7 +30,7 @@ goog.require('Blockly.Events.BlockCreate'); goog.require('Blockly.Events.VarCreate'); goog.require('Blockly.FlyoutCursor'); goog.require('Blockly.Gesture'); -goog.require('Blockly.MarkerCursor'); +goog.require('Blockly.Marker'); goog.require('Blockly.Scrollbar'); goog.require('Blockly.Tooltip'); goog.require('Blockly.Touch'); @@ -58,7 +58,7 @@ Blockly.Flyout = function(workspaceOptions) { this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions); this.workspace_.isFlyout = true; this.workspace_.setCursor(new Blockly.FlyoutCursor()); - this.workspace_.setMarker(new Blockly.MarkerCursor()); + this.workspace_.setMarker(new Blockly.Marker()); /** * Is RTL vs LTR. diff --git a/core/keyboard_nav/cursor.js b/core/keyboard_nav/cursor.js index a129c958e..7342e2491 100644 --- a/core/keyboard_nav/cursor.js +++ b/core/keyboard_nav/cursor.js @@ -24,118 +24,28 @@ goog.provide('Blockly.Cursor'); +goog.require('Blockly.Action'); goog.require('Blockly.ASTNode'); +goog.require('Blockly.Marker'); goog.require('Blockly.navigation'); +goog.require('Blockly.utils.object'); + /** * Class for a cursor. * A cursor controls how a user navigates the Blockly AST. * @constructor + * @extends {Blockly.Marker} */ Blockly.Cursor = function() { - /** - * The current location of the cursor. - * @type {Blockly.ASTNode} - * @private - */ - this.curNode_ = null; + Blockly.Cursor.superClass_.constructor.call(this); /** - * The object in charge of drawing the visual representation of the current node. - * @type {Blockly.blockRendering.CursorSvg} - * @private + * @override */ - this.drawer_ = null; -}; - -/** - * Sets the object in charge of drawing the cursor. - * @param {Blockly.blockRendering.CursorSvg} drawer The object in charge of drawing the cursor. - */ -Blockly.Cursor.prototype.setDrawer = function(drawer) { - this.drawer_ = drawer; -}; - -/** - * Get the current drawer for the cursor. - * @return {Blockly.blockRendering.CursorSvg} The object in charge of drawing the cursor. - */ -Blockly.Cursor.prototype.getDrawer = function() { - return this.drawer_; -}; - -/** - * Gets the current location of the cursor. - * @return {Blockly.ASTNode} The current field, connection, or block the cursor - * is on. - */ -Blockly.Cursor.prototype.getCurNode = function() { - return this.curNode_; -}; - -/** - * Set the location of the cursor and call the update method. - * Setting isStack to true will only work if the newLocation is the top most - * output or previous connection on a stack. - * @param {Blockly.ASTNode} newNode The new location of the cursor. - */ -Blockly.Cursor.prototype.setCurNode = function(newNode) { - var oldNode = this.curNode_; - this.curNode_ = newNode; - if (this.drawer_) { - this.drawer_.draw(oldNode, this.curNode_); - } -}; - -/** - * Redraw the current cursor. - * @package - */ -Blockly.Cursor.prototype.draw = function() { - if (this.drawer_) { - this.drawer_.draw(this.curNode_, this.curNode_); - } -}; - -/** - * Hide the cursor SVG. - */ -Blockly.Cursor.prototype.hide = function() { - if (this.drawer_) { - this.drawer_.hide(); - } -}; - -/** - * Handles the given action. - * This is only triggered when keyboard navigation is enabled. - * @param {!Blockly.Action} action The action to be handled. - * @return {boolean} True if the action has been handled, false otherwise. - */ -Blockly.Cursor.prototype.onBlocklyAction = function(action) { - // If we are on a field give it the option to handle the action - if (this.getCurNode() && - this.getCurNode().getType() === Blockly.ASTNode.types.FIELD && - this.getCurNode().getLocation().onBlocklyAction(action)) { - return true; - } - switch (action.name) { - case Blockly.navigation.actionNames.PREVIOUS: - this.prev(); - return true; - case Blockly.navigation.actionNames.OUT: - this.out(); - return true; - case Blockly.navigation.actionNames.NEXT: - this.next(); - return true; - case Blockly.navigation.actionNames.IN: - this.in(); - return true; - default: - return false; - } + this.type = 'cursor'; }; +Blockly.utils.object.inherits(Blockly.Cursor, Blockly.Marker); /** * Find the next connection, field, or block. @@ -234,3 +144,34 @@ Blockly.Cursor.prototype.out = function() { } return newNode; }; + +/** + * Handles the given action. + * This is only triggered when keyboard navigation is enabled. + * @param {!Blockly.Action} action The action to be handled. + * @return {boolean} True if the action has been handled, false otherwise. + */ +Blockly.Cursor.prototype.onBlocklyAction = function(action) { + // If we are on a field give it the option to handle the action + if (this.getCurNode() && + this.getCurNode().getType() === Blockly.ASTNode.types.FIELD && + this.getCurNode().getLocation().onBlocklyAction(action)) { + return true; + } + switch (action.name) { + case Blockly.navigation.actionNames.PREVIOUS: + this.prev(); + return true; + case Blockly.navigation.actionNames.OUT: + this.out(); + return true; + case Blockly.navigation.actionNames.NEXT: + this.next(); + return true; + case Blockly.navigation.actionNames.IN: + this.in(); + return true; + default: + return false; + } +}; diff --git a/core/keyboard_nav/marker.js b/core/keyboard_nav/marker.js new file mode 100644 index 000000000..16ae24061 --- /dev/null +++ b/core/keyboard_nav/marker.js @@ -0,0 +1,124 @@ +/** + * @license + * Copyright 2019 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. + */ + +/** + * @fileoverview The class representing a marker. + * Used primarily for keyboard navigation to show a marked location. + * @author aschmiedt@google.com (Abby Schmiedt) + */ +'use strict'; + +goog.provide('Blockly.Marker'); + +goog.require('Blockly.ASTNode'); +goog.require('Blockly.navigation'); + + +/** + * Class for a marker. + * This is used in keyboard navigation to save a location in the Blockly AST. + * @constructor + */ +Blockly.Marker = function() { + + /** + * The colour of the marker. + * @type {?string} + */ + this.colour = null; + + /** + * The current location of the marker. + * @type {Blockly.ASTNode} + * @private + */ + this.curNode_ = null; + + /** + * The object in charge of drawing the visual representation of the current node. + * @type {Blockly.blockRendering.MarkerSvg} + * @private + */ + this.drawer_ = null; + + /** + * The type of the marker. + * @type {string} + */ + this.type = 'marker'; +}; + +/** + * Sets the object in charge of drawing the marker. + * @param {Blockly.blockRendering.MarkerSvg} drawer The object in charge of + * drawing the marker. + */ +Blockly.Marker.prototype.setDrawer = function(drawer) { + this.drawer_ = drawer; +}; + +/** + * Get the current drawer for the marker. + * @return {Blockly.blockRendering.MarkerSvg} The object in charge of drawing + * the marker. + */ +Blockly.Marker.prototype.getDrawer = function() { + return this.drawer_; +}; + +/** + * Gets the current location of the marker. + * @return {Blockly.ASTNode} The current field, connection, or block the marker + * is on. + */ +Blockly.Marker.prototype.getCurNode = function() { + return this.curNode_; +}; + +/** + * Set the location of the marker and call the update method. + * Setting isStack to true will only work if the newLocation is the top most + * output or previous connection on a stack. + * @param {Blockly.ASTNode} newNode The new location of the marker. + */ +Blockly.Marker.prototype.setCurNode = function(newNode) { + var oldNode = this.curNode_; + this.curNode_ = newNode; + if (this.drawer_) { + this.drawer_.draw(oldNode, this.curNode_); + } +}; + +/** + * Redraw the current marker. + * @package + */ +Blockly.Marker.prototype.draw = function() { + if (this.drawer_) { + this.drawer_.draw(this.curNode_, this.curNode_); + } +}; + +/** + * Hide the marker SVG. + */ +Blockly.Marker.prototype.hide = function() { + if (this.drawer_) { + this.drawer_.hide(); + } +}; + diff --git a/core/keyboard_nav/marker_cursor.js b/core/keyboard_nav/marker_cursor.js deleted file mode 100644 index 0150ca66f..000000000 --- a/core/keyboard_nav/marker_cursor.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @license - * Copyright 2019 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. - */ - -/** - * @fileoverview The class representing a cursor used for marking a location. - * Used primarily for keyboard navigation. - * @author aschmiedt@google.com (Abby Schmiedt) - */ -'use strict'; - -goog.provide('Blockly.MarkerCursor'); - -goog.require('Blockly.Cursor'); -goog.require('Blockly.utils.object'); - - -/** - * Class for a marker. - * This is used in keyboard navigation to save a location in the Blockly AST. - * @constructor - * @extends {Blockly.Cursor} - */ -Blockly.MarkerCursor = function() { - Blockly.MarkerCursor.superClass_.constructor.call(this); -}; -Blockly.utils.object.inherits(Blockly.MarkerCursor, Blockly.Cursor); - -/** - * This is a no-op since markers do not move. - * @return {null} Always null. - * @override - */ -Blockly.MarkerCursor.prototype.next = function() { - return null; -}; - -/** - * This is a no-op since markers do not move. - * @return {null} Always null. - * @override - */ -Blockly.MarkerCursor.prototype.in = function() { - return null; -}; - -/** - * This is a no-op since markers do not move. - * @return {null} Always null. - * @override - */ -Blockly.MarkerCursor.prototype.prev = function() { - return null; -}; - -/** - * This is a no-op since markers do not move. - * @return {null} Always null. - * @override - */ -Blockly.MarkerCursor.prototype.out = function() { - return null; -}; diff --git a/core/renderers/common/cursor_svg.js b/core/renderers/common/marker_svg.js similarity index 59% rename from core/renderers/common/cursor_svg.js rename to core/renderers/common/marker_svg.js index 0bb0edc87..37dc877be 100644 --- a/core/renderers/common/cursor_svg.js +++ b/core/renderers/common/marker_svg.js @@ -16,46 +16,42 @@ */ /** - * @fileoverview Methods for graphically rendering a cursor as SVG. + * @fileoverview Methods for graphically rendering a marker as SVG. * @author samelh@microsoft.com (Sam El-Husseini) */ 'use strict'; -goog.provide('Blockly.blockRendering.CursorSvg'); +goog.provide('Blockly.blockRendering.MarkerSvg'); goog.require('Blockly.ASTNode'); /** - * Class for a cursor. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor belongs to. + * Class for a marker. + * @param {!Blockly.WorkspaceSvg} workspace The workspace the marker belongs to. * @param {!Blockly.blockRendering.ConstantProvider} constants The constants for * the renderer. - * @param {boolean=} opt_marker True if the cursor is a marker. A marker is used - * to save a location and is an immovable cursor. False or undefined if the - * cursor is not a marker. + * @param {!Blockly.Marker} marker The marker to draw. * @constructor */ -Blockly.blockRendering.CursorSvg = function(workspace, constants, opt_marker) { +Blockly.blockRendering.MarkerSvg = function(workspace, constants, marker) { /** - * The workspace the cursor belongs to. + * The workspace the marker belongs to. * @type {!Blockly.WorkspaceSvg} * @private */ this.workspace_ = workspace; /** - * True if the cursor should be drawn as a marker, false otherwise. - * A marker is drawn as a solid blue line, while the cursor is drawns as a - * flashing red one. - * @type {boolean} + * The marker to draw. + * @type {!Blockly.Marker} * @private */ - this.isMarker_ = !!opt_marker; + this.marker_ = marker; /** - * The workspace, field, or block that the cursor SVG element should be + * The workspace, field, or block that the marker SVG element should be * attached to. * @type {Blockly.WorkspaceSvg|Blockly.Field|Blockly.BlockSvg} * @private @@ -63,66 +59,74 @@ Blockly.blockRendering.CursorSvg = function(workspace, constants, opt_marker) { this.parent_ = null; /** - * The constants necessary to draw the cursor. + * The constants necessary to draw the marker. * @type {Blockly.blockRendering.ConstantProvider} * @protected */ this.constants_ = constants; /** - * The current SVG element for the cursor. + * The current SVG element for the marker. * @type {Element} */ - this.currentCursorSvg = null; + this.currentMarkerSvg = null; + + var defaultColour = this.isCursor() ? this.constants_.CURSOR_COLOUR : + this.constants_.MARKER_COLOUR; + + /** + * The colour of the marker. + * @type {string} + */ + this.colour_ = marker.colour || defaultColour; }; /** * The name of the CSS class for a cursor. * @const {string} */ -Blockly.blockRendering.CursorSvg.CURSOR_CLASS = 'blocklyCursor'; +Blockly.blockRendering.MarkerSvg.CURSOR_CLASS = 'blocklyCursor'; /** * The name of the CSS class for a marker. * @const {string} */ -Blockly.blockRendering.CursorSvg.MARKER_CLASS = 'blocklyMarker'; +Blockly.blockRendering.MarkerSvg.MARKER_CLASS = 'blocklyMarker'; /** - * What we multiply the height by to get the height of the cursor. + * What we multiply the height by to get the height of the marker. * Only used for the block and block connections. * @type {number} * @const */ -Blockly.blockRendering.CursorSvg.HEIGHT_MULTIPLIER = 3 / 4; +Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER = 3 / 4; /** * Return the root node of the SVG or null if none exists. * @return {SVGElement} The root SVG node. */ -Blockly.blockRendering.CursorSvg.prototype.getSvgRoot = function() { +Blockly.blockRendering.MarkerSvg.prototype.getSvgRoot = function() { return this.svgGroup_; }; /** - * True if the cursor should be drawn as a marker, false otherwise. - * A marker is drawn as a solid blue line, while the cursor is drawns as a - * flashing red one. - * @return {boolean} The root SVG node. + * True if the marker should be drawn as a cursor, false otherwise. + * A cursor is drawn as a flashing line. A marker is drawn as a solid line. + * @return {boolean} True if the marker is a cursor, false otherwise. */ -Blockly.blockRendering.CursorSvg.prototype.isMarker = function() { - return this.isMarker_; +Blockly.blockRendering.MarkerSvg.prototype.isCursor = function() { + return this.marker_.type == 'cursor'; }; /** - * Create the DOM element for the cursor. - * @return {!SVGElement} The cursor controls SVG group. + * Create the DOM element for the marker. + * @return {!SVGElement} The marker controls SVG group. * @package */ -Blockly.blockRendering.CursorSvg.prototype.createDom = function() { - var className = this.isMarker() ? - Blockly.blockRendering.CursorSvg.MARKER_CLASS : - Blockly.blockRendering.CursorSvg.CURSOR_CLASS; +Blockly.blockRendering.MarkerSvg.prototype.createDom = function() { + var className = this.isCursor() ? + Blockly.blockRendering.MarkerSvg.CURSOR_CLASS : + Blockly.blockRendering.MarkerSvg.MARKER_CLASS; this.svgGroup_ = Blockly.utils.dom.createSvgElement('g', { @@ -134,14 +138,14 @@ Blockly.blockRendering.CursorSvg.prototype.createDom = function() { }; /** - * Attaches the SVG root of the cursor to the SVG group of the parent. + * Attaches the SVG root of the marker to the SVG group of the parent. * @param {!Blockly.WorkspaceSvg|!Blockly.Field|!Blockly.BlockSvg} newParent - * The workspace, field, or block that the cursor SVG element should be + * The workspace, field, or block that the marker SVG element should be * attached to. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.setParent_ = function(newParent) { - if (this.isMarker_) { +Blockly.blockRendering.MarkerSvg.prototype.setParent_ = function(newParent) { + if (!this.isCursor()) { if (this.parent_) { this.parent_.setMarkerSvg(null); } @@ -160,26 +164,26 @@ Blockly.blockRendering.CursorSvg.prototype.setParent_ = function(newParent) { **************************/ /** - * Show the cursor as a combination of the previous connection and block, + * Show the marker as a combination of the previous connection and block, * the output connection and block, or just the block. - * @param {Blockly.BlockSvg} block The block the cursor is currently on. + * @param {Blockly.BlockSvg} block The block the marker is currently on. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showWithBlockPrevOutput_ = function(block) { +Blockly.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_ = function(block) { if (!block) { return; } var width = block.width; var height = block.height; - var cursorHeight = height * Blockly.blockRendering.CursorSvg.HEIGHT_MULTIPLIER; - var cursorOffset = this.constants_.CURSOR_BLOCK_PADDING; + var markerHeight = height * Blockly.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER; + var markerOffset = this.constants_.CURSOR_BLOCK_PADDING; if (block.previousConnection) { - this.positionPrevious_(width, cursorOffset, cursorHeight); + this.positionPrevious_(width, markerOffset, markerHeight); } else if (block.outputConnection) { this.positionOutput_(width, height); } else { - this.positionBlock_(width, cursorOffset, cursorHeight); + this.positionBlock_(width, markerOffset, markerHeight); } this.setParent_(block); @@ -189,10 +193,10 @@ Blockly.blockRendering.CursorSvg.prototype.showWithBlockPrevOutput_ = function(b /** * Show the visual representation of a workspace coordinate. * This is a horizontal line. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the cursor for. + * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showWithCoordinates_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showWithCoordinates_ = function(curNode) { var wsCoordinate = curNode.getWsCoordinate(); var x = wsCoordinate.x; var y = wsCoordinate.y; @@ -209,10 +213,10 @@ Blockly.blockRendering.CursorSvg.prototype.showWithCoordinates_ = function(curNo /** * Show the visual representation of a field. * This is a box around the field. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the cursor for. + * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showWithField_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showWithField_ = function(curNode) { var field = /** @type {Blockly.Field} */ (curNode.getLocation()); var width = field.getSize().width; var height = field.getSize().height; @@ -225,10 +229,10 @@ Blockly.blockRendering.CursorSvg.prototype.showWithField_ = function(curNode) { /** * Show the visual representation of an input. * This is a puzzle piece. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the cursor for. + * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showWithInput_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showWithInput_ = function(curNode) { var connection = /** @type {Blockly.Connection} */ (curNode.getLocation()); var sourceBlock = /** @type {!Blockly.BlockSvg} */ (connection.getSourceBlock()); @@ -242,10 +246,10 @@ Blockly.blockRendering.CursorSvg.prototype.showWithInput_ = function(curNode) { /** * Show the visual representation of a next connection. * This is a horizontal line. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the cursor for. + * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showWithNext_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showWithNext_ = function(curNode) { var connection = curNode.getLocation(); var targetBlock = /** @type {Blockly.BlockSvg} */ (connection.getSourceBlock()); var x = 0; @@ -262,10 +266,10 @@ Blockly.blockRendering.CursorSvg.prototype.showWithNext_ = function(curNode) { /** * Show the visual representation of a stack. * This is a box with extra padding around the entire stack of blocks. - * @param {!Blockly.ASTNode} curNode The node that we want to draw the cursor for. + * @param {!Blockly.ASTNode} curNode The node that we want to draw the marker for. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showWithStack_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showWithStack_ = function(curNode) { var block = /** @type {Blockly.BlockSvg} */ (curNode.getLocation()); // Gets the height and width of entire stack. @@ -291,12 +295,12 @@ Blockly.blockRendering.CursorSvg.prototype.showWithStack_ = function(curNode) { }; /** - * Show the current cursor. + * Show the current marker. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showCurrent_ = function() { +Blockly.blockRendering.MarkerSvg.prototype.showCurrent_ = function() { this.hide(); - this.currentCursorSvg.style.display = ''; + this.currentMarkerSvg.style.display = ''; }; /************************** @@ -304,107 +308,107 @@ Blockly.blockRendering.CursorSvg.prototype.showCurrent_ = function() { **************************/ /** - * Position the cursor for a block. + * Position the marker for a block. * Displays an outline of the top half of a rectangle around a block. * @param {number} width The width of the block. - * @param {number} cursorOffset The extra padding for around the block. - * @param {number} cursorHeight The height of the cursor. + * @param {number} markerOffset The extra padding for around the block. + * @param {number} markerHeight The height of the marker. * @private */ -Blockly.blockRendering.CursorSvg.prototype.positionBlock_ = function( - width, cursorOffset, cursorHeight) { - var cursorPath = Blockly.utils.svgPaths.moveBy(-cursorOffset, cursorHeight) + - Blockly.utils.svgPaths.lineOnAxis('V', -cursorOffset) + - Blockly.utils.svgPaths.lineOnAxis('H', width + cursorOffset * 2) + - Blockly.utils.svgPaths.lineOnAxis('V', cursorHeight); - this.cursorBlock_.setAttribute('d', cursorPath); +Blockly.blockRendering.MarkerSvg.prototype.positionBlock_ = function( + width, markerOffset, markerHeight) { + var markerPath = Blockly.utils.svgPaths.moveBy(-markerOffset, markerHeight) + + Blockly.utils.svgPaths.lineOnAxis('V', -markerOffset) + + Blockly.utils.svgPaths.lineOnAxis('H', width + markerOffset * 2) + + Blockly.utils.svgPaths.lineOnAxis('V', markerHeight); + this.markerBlock_.setAttribute('d', markerPath); if (this.workspace_.RTL) { - this.flipRtl_(this.cursorBlock_); + this.flipRtl_(this.markerBlock_); } - this.currentCursorSvg = this.cursorBlock_; + this.currentMarkerSvg = this.markerBlock_; }; /** - * Position the cursor for an input connection. + * Position the marker for an input connection. * Displays a filled in puzzle piece. - * @param {!Blockly.Connection} connection The connection to position cursor around. + * @param {!Blockly.Connection} connection The connection to position marker around. * @private */ -Blockly.blockRendering.CursorSvg.prototype.positionInput_ = function(connection) { +Blockly.blockRendering.MarkerSvg.prototype.positionInput_ = function(connection) { var x = connection.getOffsetInBlock().x; var y = connection.getOffsetInBlock().y; var path = Blockly.utils.svgPaths.moveTo(0, 0) + this.constants_.PUZZLE_TAB.pathDown; - this.cursorInput_.setAttribute('d', path); - this.cursorInput_.setAttribute('transform', + this.markerInput_.setAttribute('d', path); + this.markerInput_.setAttribute('transform', 'translate(' + x + ',' + y + ')' + (this.workspace_.RTL ? ' scale(-1 1)' : '')); - this.currentCursorSvg = this.cursorInput_; + this.currentMarkerSvg = this.markerInput_; }; /** - * Move and show the cursor at the specified coordinate in workspace units. + * Move and show the marker at the specified coordinate in workspace units. * Displays a horizontal line. * @param {number} x The new x, in workspace units. * @param {number} y The new y, in workspace units. * @param {number} width The new width, in workspace units. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.positionLine_ = function(x, y, width) { - this.cursorSvgLine_.setAttribute('x', x); - this.cursorSvgLine_.setAttribute('y', y); - this.cursorSvgLine_.setAttribute('width', width); - this.currentCursorSvg = this.cursorSvgLine_; +Blockly.blockRendering.MarkerSvg.prototype.positionLine_ = function(x, y, width) { + this.markerSvgLine_.setAttribute('x', x); + this.markerSvgLine_.setAttribute('y', y); + this.markerSvgLine_.setAttribute('width', width); + this.currentMarkerSvg = this.markerSvgLine_; }; /** - * Position the cursor for an output connection. + * Position the marker for an output connection. * Displays a puzzle outline and the top and bottom path. * @param {number} width The width of the block. * @param {number} height The height of the block. * @private */ -Blockly.blockRendering.CursorSvg.prototype.positionOutput_ = function(width, height) { - var cursorPath = Blockly.utils.svgPaths.moveBy(width, 0) + +Blockly.blockRendering.MarkerSvg.prototype.positionOutput_ = function(width, height) { + var markerPath = Blockly.utils.svgPaths.moveBy(width, 0) + Blockly.utils.svgPaths.lineOnAxis('h', -(width - this.constants_.PUZZLE_TAB.width)) + Blockly.utils.svgPaths.lineOnAxis('v', this.constants_.TAB_OFFSET_FROM_TOP) + this.constants_.PUZZLE_TAB.pathDown + Blockly.utils.svgPaths.lineOnAxis('V', height) + Blockly.utils.svgPaths.lineOnAxis('H', width); - this.cursorBlock_.setAttribute('d', cursorPath); + this.markerBlock_.setAttribute('d', markerPath); if (this.workspace_.RTL) { - this.flipRtl_(this.cursorBlock_); + this.flipRtl_(this.markerBlock_); } - this.currentCursorSvg = this.cursorBlock_; + this.currentMarkerSvg = this.markerBlock_; }; /** - * Position the cursor for a previous connection. + * Position the marker for a previous connection. * Displays a half rectangle with a notch in the top to represent the previous * connection. * @param {number} width The width of the block. - * @param {number} cursorOffset The offset of the cursor from around the block. - * @param {number} cursorHeight The height of the cursor. + * @param {number} markerOffset The offset of the marker from around the block. + * @param {number} markerHeight The height of the marker. * @private */ -Blockly.blockRendering.CursorSvg.prototype.positionPrevious_ = function( - width, cursorOffset, cursorHeight) { - var cursorPath = Blockly.utils.svgPaths.moveBy(-cursorOffset, cursorHeight) + - Blockly.utils.svgPaths.lineOnAxis('V', -cursorOffset) + +Blockly.blockRendering.MarkerSvg.prototype.positionPrevious_ = function( + width, markerOffset, markerHeight) { + var markerPath = Blockly.utils.svgPaths.moveBy(-markerOffset, markerHeight) + + Blockly.utils.svgPaths.lineOnAxis('V', -markerOffset) + Blockly.utils.svgPaths.lineOnAxis('H', this.constants_.NOTCH_OFFSET_LEFT) + this.constants_.NOTCH.pathLeft + - Blockly.utils.svgPaths.lineOnAxis('H', width + cursorOffset * 2) + - Blockly.utils.svgPaths.lineOnAxis('V', cursorHeight); - this.cursorBlock_.setAttribute('d', cursorPath); + Blockly.utils.svgPaths.lineOnAxis('H', width + markerOffset * 2) + + Blockly.utils.svgPaths.lineOnAxis('V', markerHeight); + this.markerBlock_.setAttribute('d', markerPath); if (this.workspace_.RTL) { - this.flipRtl_(this.cursorBlock_); + this.flipRtl_(this.markerBlock_); } - this.currentCursorSvg = this.cursorBlock_; + this.currentMarkerSvg = this.markerBlock_; }; /** - * Move and show the cursor at the specified coordinate in workspace units. + * Move and show the marker at the specified coordinate in workspace units. * Displays a filled in rectangle. * @param {number} x The new x, in workspace units. * @param {number} y The new y, in workspace units. @@ -412,41 +416,41 @@ Blockly.blockRendering.CursorSvg.prototype.positionPrevious_ = function( * @param {number} height The new height, in workspace units. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.positionRect_ = function(x, y, width, height) { - this.cursorSvgRect_.setAttribute('x', x); - this.cursorSvgRect_.setAttribute('y', y); - this.cursorSvgRect_.setAttribute('width', width); - this.cursorSvgRect_.setAttribute('height', height); - this.currentCursorSvg = this.cursorSvgRect_; +Blockly.blockRendering.MarkerSvg.prototype.positionRect_ = function(x, y, width, height) { + this.markerSvgRect_.setAttribute('x', x); + this.markerSvgRect_.setAttribute('y', y); + this.markerSvgRect_.setAttribute('width', width); + this.markerSvgRect_.setAttribute('height', height); + this.currentMarkerSvg = this.markerSvgRect_; }; /** * Flip the SVG paths in RTL. - * @param {!SVGElement} cursor The cursor that we want to flip. + * @param {!SVGElement} markerSvg The marker that we want to flip. * @private */ -Blockly.blockRendering.CursorSvg.prototype.flipRtl_ = function(cursor) { - cursor.setAttribute('transform', 'scale(-1 1)'); +Blockly.blockRendering.MarkerSvg.prototype.flipRtl_ = function(markerSvg) { + markerSvg.setAttribute('transform', 'scale(-1 1)'); }; /** - * Hide the cursor. + * Hide the marker. * @package */ -Blockly.blockRendering.CursorSvg.prototype.hide = function() { - this.cursorSvgLine_.style.display = 'none'; - this.cursorSvgRect_.style.display = 'none'; - this.cursorInput_.style.display = 'none'; - this.cursorBlock_.style.display = 'none'; +Blockly.blockRendering.MarkerSvg.prototype.hide = function() { + this.markerSvgLine_.style.display = 'none'; + this.markerSvgRect_.style.display = 'none'; + this.markerInput_.style.display = 'none'; + this.markerBlock_.style.display = 'none'; }; /** - * Update the cursor. - * @param {Blockly.ASTNode} oldNode The previous node the cursor was on or null. - * @param {Blockly.ASTNode} curNode The node that we want to draw the cursor for. + * Update the marker. + * @param {Blockly.ASTNode} oldNode The previous node the marker was on or null. + * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. * @package */ -Blockly.blockRendering.CursorSvg.prototype.draw = function(oldNode, curNode) { +Blockly.blockRendering.MarkerSvg.prototype.draw = function(oldNode, curNode) { if (!curNode) { this.hide(); return; @@ -454,10 +458,10 @@ Blockly.blockRendering.CursorSvg.prototype.draw = function(oldNode, curNode) { this.showAtLocation_(curNode); - this.fireCursorEvent_(oldNode, curNode); + this.firemarkerEvent_(oldNode, curNode); - // Ensures the cursor will be visible immediately after the move. - var animate = this.currentCursorSvg.childNodes[0]; + // Ensures the marker will be visible immediately after the move. + var animate = this.currentMarkerSvg.childNodes[0]; if (animate !== undefined) { animate.beginElement && animate.beginElement(); } @@ -465,11 +469,11 @@ Blockly.blockRendering.CursorSvg.prototype.draw = function(oldNode, curNode) { /** - * Update the cursor's visible state based on the type of curNode.. - * @param {Blockly.ASTNode} curNode The node that we want to draw the cursor for. + * Update the marker's visible state based on the type of curNode.. + * @param {Blockly.ASTNode} curNode The node that we want to draw the marker for. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.showAtLocation_ = function(curNode) { +Blockly.blockRendering.MarkerSvg.prototype.showAtLocation_ = function(curNode) { if (curNode.getType() == Blockly.ASTNode.types.BLOCK) { var block = /** @type {Blockly.BlockSvg} */ (curNode.getLocation()); this.showWithBlockPrevOutput_(block); @@ -493,14 +497,14 @@ Blockly.blockRendering.CursorSvg.prototype.showAtLocation_ = function(curNode) { }; /** - * Fire event for the cursor or marker. - * @param {Blockly.ASTNode} oldNode The old node the cursor used to be on. - * @param {!Blockly.ASTNode} curNode The new node the cursor is currently on. + * Fire event for the marker or marker. + * @param {Blockly.ASTNode} oldNode The old node the marker used to be on. + * @param {!Blockly.ASTNode} curNode The new node the marker is currently on. * @private */ -Blockly.blockRendering.CursorSvg.prototype.fireCursorEvent_ = function(oldNode, curNode) { +Blockly.blockRendering.MarkerSvg.prototype.firemarkerEvent_ = function(oldNode, curNode) { var curBlock = curNode.getSourceBlock(); - var eventType = this.isMarker_ ? 'markedNode' : 'cursorMove'; + var eventType = this.isCursor() ? 'cursorMove' : 'markerMove'; var event = new Blockly.Events.Ui(curBlock, eventType, oldNode, curNode); if (curNode.getType() == Blockly.ASTNode.types.WORKSPACE) { event.workspaceId = curNode.getLocation().id; @@ -509,27 +513,27 @@ Blockly.blockRendering.CursorSvg.prototype.fireCursorEvent_ = function(oldNode, }; /** - * Get the properties to make a cursor blink. - * @return {!Object} The object holding attributes to make the cursor blink. + * Get the properties to make a marker blink. + * @return {!Object} The object holding attributes to make the marker blink. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.getBlinkProperties_ = function() { +Blockly.blockRendering.MarkerSvg.prototype.getBlinkProperties_ = function() { return { 'attributeType': 'XML', 'attributeName': 'fill', 'dur': '1s', - 'values': this.constants_.CURSOR_COLOUR + ';transparent;transparent;', + 'values': this.colour_ + ';transparent;transparent;', 'repeatCount': 'indefinite' }; }; /** - * Create the cursor SVG. + * Create the marker SVG. * @return {Element} The SVG node created. * @protected */ -Blockly.blockRendering.CursorSvg.prototype.createDomInternal_ = function() { +Blockly.blockRendering.MarkerSvg.prototype.createDomInternal_ = function() { /* This markup will be generated and added to the .svgGroup_: @@ -539,75 +543,73 @@ Blockly.blockRendering.CursorSvg.prototype.createDomInternal_ = function() { */ - var colour = this.isMarker_ ? this.constants_.MARKER_COLOUR : - this.constants_.CURSOR_COLOUR; - this.cursorSvg_ = Blockly.utils.dom.createSvgElement('g', + this.markerSvg_ = Blockly.utils.dom.createSvgElement('g', { 'width': this.constants_.CURSOR_WS_WIDTH, 'height': this.constants_.WS_CURSOR_HEIGHT }, this.svgGroup_); // A horizontal line used to represent a workspace coordinate or next connection. - this.cursorSvgLine_ = Blockly.utils.dom.createSvgElement('rect', + this.markerSvgLine_ = Blockly.utils.dom.createSvgElement('rect', { - 'fill': colour, + 'fill': this.colour_, 'width': this.constants_.CURSOR_WS_WIDTH, 'height': this.constants_.WS_CURSOR_HEIGHT, 'style': 'display: none' }, - this.cursorSvg_); + this.markerSvg_); // A filled in rectangle used to represent a stack. - this.cursorSvgRect_ = Blockly.utils.dom.createSvgElement('rect', + this.markerSvgRect_ = Blockly.utils.dom.createSvgElement('rect', { - 'class': 'blocklyVerticalCursor', + 'class': 'blocklyVerticalMarker', 'rx': 10, 'ry': 10, 'style': 'display: none', - 'stroke': colour + 'stroke': this.colour_ }, - this.cursorSvg_); + this.markerSvg_); // A filled in puzzle piece used to represent an input value. - this.cursorInput_ = Blockly.utils.dom.createSvgElement('path', + this.markerInput_ = Blockly.utils.dom.createSvgElement('path', { 'transform': '', 'style': 'display: none', - 'fill': colour + 'fill': this.colour_ }, - this.cursorSvg_); + this.markerSvg_); // A path used to represent a previous connection and a block, an output // connection and a block, or a block. - this.cursorBlock_ = Blockly.utils.dom.createSvgElement('path', + this.markerBlock_ = Blockly.utils.dom.createSvgElement('path', { 'transform': '', 'style': 'display: none', 'fill': 'none', - 'stroke': colour, + 'stroke': this.colour_, 'stroke-width': this.constants_.CURSOR_STROKE_WIDTH }, - this.cursorSvg_); + this.markerSvg_); - // Markers and stack cursors don't blink. - if (!this.isMarker_) { + // Markers and stack markers don't blink. + if (this.isCursor()) { var blinkProperties = this.getBlinkProperties_(); Blockly.utils.dom.createSvgElement('animate', this.getBlinkProperties_(), - this.cursorSvgLine_); + this.markerSvgLine_); Blockly.utils.dom.createSvgElement('animate', blinkProperties, - this.cursorInput_); + this.markerInput_); blinkProperties['attributeName'] = 'stroke'; Blockly.utils.dom.createSvgElement('animate', blinkProperties, - this.cursorBlock_); + this.markerBlock_); } - return this.cursorSvg_; + return this.markerSvg_; }; /** - * Dispose of this cursor. + * Dispose of this marker. * @package */ -Blockly.blockRendering.CursorSvg.prototype.dispose = function() { +Blockly.blockRendering.MarkerSvg.prototype.dispose = function() { if (this.svgGroup_) { Blockly.utils.dom.removeNode(this.svgGroup_); } diff --git a/core/renderers/common/renderer.js b/core/renderers/common/renderer.js index 03160d592..51992224e 100644 --- a/core/renderers/common/renderer.js +++ b/core/renderers/common/renderer.js @@ -24,7 +24,7 @@ goog.provide('Blockly.blockRendering.Renderer'); goog.require('Blockly.blockRendering.ConstantProvider'); -goog.require('Blockly.blockRendering.CursorSvg'); +goog.require('Blockly.blockRendering.MarkerSvg'); goog.require('Blockly.blockRendering.Drawer'); goog.require('Blockly.blockRendering.IPathObject'); goog.require('Blockly.blockRendering.PathObject'); @@ -111,17 +111,16 @@ Blockly.blockRendering.Renderer.prototype.makeDebugger_ = function() { }; /** - * Create a new instance of the renderer's cursor drawer. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor belongs to. - * @param {boolean=} opt_marker True if the cursor is a marker. A marker is used - * to save a location and is an immovable cursor. False or undefined if the - * cursor is not a marker. - * @return {!Blockly.blockRendering.CursorSvg} The cursor drawer. + * Create a new instance of the renderer's marker drawer. + * @param {!Blockly.WorkspaceSvg} workspace The workspace the marker belongs to. + * @param {!Blockly.Marker} marker The marker. + * @return {!Blockly.blockRendering.MarkerSvg} The object in charge of drawing + * the marker. * @package */ -Blockly.blockRendering.Renderer.prototype.makeCursorDrawer = function( - workspace, opt_marker) { - return new Blockly.blockRendering.CursorSvg(workspace, this.getConstants(), opt_marker); +Blockly.blockRendering.Renderer.prototype.makeMarkerDrawer = function( + workspace, marker) { + return new Blockly.blockRendering.MarkerSvg(workspace, this.getConstants(), marker); }; /** diff --git a/core/renderers/zelos/cursor_svg.js b/core/renderers/zelos/marker_svg.js similarity index 59% rename from core/renderers/zelos/cursor_svg.js rename to core/renderers/zelos/marker_svg.js index dd578bcd6..7d262043f 100644 --- a/core/renderers/zelos/cursor_svg.js +++ b/core/renderers/zelos/marker_svg.js @@ -16,38 +16,36 @@ */ /** - * @fileoverview Methods for graphically rendering a cursor as SVG. + * @fileoverview Methods for graphically rendering a marker as SVG. * @author samelh@microsoft.com (Sam El-Husseini) */ 'use strict'; -goog.provide('Blockly.zelos.CursorSvg'); +goog.provide('Blockly.zelos.MarkerSvg'); -goog.require('Blockly.blockRendering.CursorSvg'); +goog.require('Blockly.blockRendering.MarkerSvg'); /** - * Class for a cursor. - * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor belongs to. + * Class to draw a marker. + * @param {!Blockly.WorkspaceSvg} workspace The workspace the marker belongs to. * @param {!Blockly.blockRendering.ConstantProvider} constants The constants for * the renderer. - * @param {boolean=} opt_marker True if the cursor is a marker. A marker is used - * to save a location and is an immovable cursor. False or undefined if the - * cursor is not a marker. + * @param {!Blockly.Marker} marker The marker to draw. * @constructor - * @extends {Blockly.blockRendering.CursorSvg} + * @extends {Blockly.blockRendering.MarkerSvg} */ -Blockly.zelos.CursorSvg = function(workspace, constants, opt_marker) { - Blockly.zelos.CursorSvg.superClass_.constructor.call( - this, workspace, constants, opt_marker); +Blockly.zelos.MarkerSvg = function(workspace, constants, marker) { + Blockly.zelos.MarkerSvg.superClass_.constructor.call( + this, workspace, constants, marker); }; -Blockly.utils.object.inherits(Blockly.zelos.CursorSvg, - Blockly.blockRendering.CursorSvg); +Blockly.utils.object.inherits(Blockly.zelos.MarkerSvg, + Blockly.blockRendering.MarkerSvg); /** * @override */ -Blockly.zelos.CursorSvg.prototype.showWithInput_ = function(curNode) { +Blockly.zelos.MarkerSvg.prototype.showWithInput_ = function(curNode) { var block = /** @type {!Blockly.BlockSvg} */ (curNode.getSourceBlock()); var connection = curNode.getLocation(); var offsetInBlock = connection.getOffsetInBlock(); @@ -61,9 +59,9 @@ Blockly.zelos.CursorSvg.prototype.showWithInput_ = function(curNode) { /** * Draw a rectangle around the block. - * @param {!Blockly.ASTNode} curNode The current node of the cursor. + * @param {!Blockly.ASTNode} curNode The current node of the marker. */ -Blockly.zelos.CursorSvg.prototype.showWithBlock_ = function(curNode) { +Blockly.zelos.MarkerSvg.prototype.showWithBlock_ = function(curNode) { var block = /** @type {!Blockly.BlockSvg} */ (curNode.getLocation()); // Gets the height and width of entire stack. @@ -81,16 +79,16 @@ Blockly.zelos.CursorSvg.prototype.showWithBlock_ = function(curNode) { * @param {number} y The y position of the circle. * @private */ -Blockly.zelos.CursorSvg.prototype.positionCircle_ = function(x, y) { - this.cursorCircle_.setAttribute('cx', x); - this.cursorCircle_.setAttribute('cy', y); - this.currentCursorSvg = this.cursorCircle_; +Blockly.zelos.MarkerSvg.prototype.positionCircle_ = function(x, y) { + this.markerCircle_.setAttribute('cx', x); + this.markerCircle_.setAttribute('cy', y); + this.currentMarkerSvg = this.markerCircle_; }; /** * @override */ -Blockly.zelos.CursorSvg.prototype.showAtLocation_ = function(curNode) { +Blockly.zelos.MarkerSvg.prototype.showAtLocation_ = function(curNode) { var handled = false; if (curNode.getType() == Blockly.ASTNode.types.OUTPUT) { // Inputs and outputs are drawn the same. @@ -102,22 +100,22 @@ Blockly.zelos.CursorSvg.prototype.showAtLocation_ = function(curNode) { } if (!handled) { - Blockly.zelos.CursorSvg.superClass_.showAtLocation_.call(this, curNode); + Blockly.zelos.MarkerSvg.superClass_.showAtLocation_.call(this, curNode); } }; /** * @override */ -Blockly.zelos.CursorSvg.prototype.hide = function() { - Blockly.zelos.CursorSvg.superClass_.hide.call(this); - this.cursorCircle_.style.display = 'none'; +Blockly.zelos.MarkerSvg.prototype.hide = function() { + Blockly.zelos.MarkerSvg.superClass_.hide.call(this); + this.markerCircle_.style.display = 'none'; }; /** * @override */ -Blockly.zelos.CursorSvg.prototype.createDomInternal_ = function() { +Blockly.zelos.MarkerSvg.prototype.createDomInternal_ = function() { /* This markup will be generated and added to the .svgGroup_: @@ -127,26 +125,24 @@ Blockly.zelos.CursorSvg.prototype.createDomInternal_ = function() { */ - Blockly.zelos.CursorSvg.superClass_.createDomInternal_.call(this); - var colour = this.isMarker() ? this.constants_.MARKER_COLOUR : - this.constants_.CURSOR_COLOUR; + Blockly.zelos.MarkerSvg.superClass_.createDomInternal_.call(this); - this.cursorCircle_ = Blockly.utils.dom.createSvgElement('circle', { + this.markerCircle_ = Blockly.utils.dom.createSvgElement('circle', { 'r': this.constants_.CURSOR_RADIUS, 'style': 'display: none', - 'fill': colour, - 'stroke': colour, + 'fill': this.colour_, + 'stroke': this.colour_, 'stroke-width': this.constants_.CURSOR_STROKE_WIDTH }, - this.cursorSvg_); + this.markerSvg_); // Markers and stack cursors don't blink. - if (!this.isMarker()) { + if (this.isCursor()) { var blinkProperties = this.getBlinkProperties_(); Blockly.utils.dom.createSvgElement('animate', blinkProperties, - this.cursorCircle_); + this.markerCircle_); } - return this.cursorSvg_; + return this.markerSvg_; }; diff --git a/core/renderers/zelos/renderer.js b/core/renderers/zelos/renderer.js index 3b08aa886..e620fb82a 100644 --- a/core/renderers/zelos/renderer.js +++ b/core/renderers/zelos/renderer.js @@ -30,7 +30,7 @@ goog.require('Blockly.zelos.ConstantProvider'); goog.require('Blockly.zelos.Drawer'); goog.require('Blockly.zelos.PathObject'); goog.require('Blockly.zelos.RenderInfo'); -goog.require('Blockly.zelos.CursorSvg'); +goog.require('Blockly.zelos.MarkerSvg'); /** @@ -84,16 +84,15 @@ Blockly.zelos.Renderer.prototype.makeDrawer_ = function(block, info) { /** * Create a new instance of the renderer's cursor drawer. * @param {!Blockly.WorkspaceSvg} workspace The workspace the cursor belongs to. - * @param {boolean=} opt_marker True if the cursor is a marker. A marker is used - * to save a location and is an immovable cursor. False or undefined if the - * cursor is not a marker. - * @return {!Blockly.blockRendering.CursorSvg} The cursor drawer. + * @param {!Blockly.Marker} marker The marker. + * @return {!Blockly.blockRendering.MarkerSvg} The object in charge of drawing + * the marker. * @package * @override */ -Blockly.zelos.Renderer.prototype.makeCursorDrawer = function( - workspace, opt_marker) { - return new Blockly.zelos.CursorSvg(workspace, this.getConstants(), opt_marker); +Blockly.zelos.Renderer.prototype.makeMarkerDrawer = function( + workspace, marker) { + return new Blockly.zelos.MarkerSvg(workspace, this.getConstants(), marker); }; /** diff --git a/core/workspace.js b/core/workspace.js index aec9a54bc..87cd0b2f9 100644 --- a/core/workspace.js +++ b/core/workspace.js @@ -24,7 +24,7 @@ goog.provide('Blockly.Workspace'); goog.require('Blockly.Cursor'); -goog.require('Blockly.MarkerCursor'); +goog.require('Blockly.Marker'); goog.require('Blockly.Events'); goog.require('Blockly.utils'); goog.require('Blockly.utils.math'); @@ -121,10 +121,10 @@ Blockly.Workspace = function(opt_options) { /** * The marker used to mark a location for keyboard navigation. - * @type {!Blockly.MarkerCursor} + * @type {!Blockly.Marker} * @protected */ - this.marker_ = new Blockly.MarkerCursor(); + this.marker_ = new Blockly.Marker(); /** * True if keyboard accessibility mode is on, false otherwise. @@ -171,7 +171,7 @@ Blockly.Workspace.prototype.setCursor = function(cursor) { /** * Sets the marker for keyboard navigation. - * @param {!Blockly.MarkerCursor} marker The marker used to mark a location for + * @param {!Blockly.Marker} marker The marker used to mark a location for * keyboard navigation. */ Blockly.Workspace.prototype.setMarker = function(marker) { @@ -188,7 +188,8 @@ Blockly.Workspace.prototype.getCursor = function() { /** * Get the marker used to mark a location for keyboard navigation. - * @return {Blockly.MarkerCursor} the marker for this workspace. + * @return {Blockly.Marker} The marker used to mark a location for keyboard + * navigation. */ Blockly.Workspace.prototype.getMarker = function() { return this.marker_; diff --git a/core/workspace_svg.js b/core/workspace_svg.js index d1b3aa772..b904e5e6a 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -511,7 +511,6 @@ Blockly.WorkspaceSvg.prototype.updateBlockStyles_ = function(blocks) { /** * Sets the cursor for use with keyboard navigation. - * * @param {!Blockly.Cursor} cursor The cursor used to move around this workspace. * @override */ @@ -520,14 +519,13 @@ Blockly.WorkspaceSvg.prototype.setCursor = function(cursor) { this.cursor_.getDrawer().dispose(); } this.cursor_ = cursor; - this.cursor_.setDrawer(this.getRenderer().makeCursorDrawer(this, false)); + this.cursor_.setDrawer(this.getRenderer().makeMarkerDrawer(this, this.cursor_)); this.setCursorSvg(this.cursor_.getDrawer().createDom()); }; /** * Sets the marker for use with keyboard navigation. - * @param {!Blockly.MarkerCursor} marker The immovable cursor used to mark a - * location on the workspace. + * @param {!Blockly.Marker} marker Used to save a location in the Blockly AST. * @override */ Blockly.WorkspaceSvg.prototype.setMarker = function(marker) { @@ -535,7 +533,7 @@ Blockly.WorkspaceSvg.prototype.setMarker = function(marker) { this.marker_.getDrawer().dispose(); } this.marker_ = marker; - this.marker_.setDrawer(this.getRenderer().makeCursorDrawer(this, true)); + this.marker_.setDrawer(this.getRenderer().makeMarkerDrawer(this, this.marker_)); this.setMarkerSvg(this.marker_.getDrawer().createDom()); }; @@ -753,11 +751,11 @@ Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) { } this.recordDeleteAreas(); - this.cursor_.setDrawer(this.getRenderer().makeCursorDrawer(this, false)); + this.cursor_.setDrawer(this.getRenderer().makeMarkerDrawer(this, this.cursor_)); var svgCursor = this.cursor_.getDrawer().createDom(); this.svgGroup_.appendChild(svgCursor); - this.marker_.setDrawer(this.getRenderer().makeCursorDrawer(this, true)); + this.marker_.setDrawer(this.getRenderer().makeMarkerDrawer(this, this.marker_)); var svgMarker = this.marker_.getDrawer().createDom(); this.svgGroup_.appendChild(svgMarker);