From 7a07b4b2ba60f653bff1c8f28c1b797271e3916b Mon Sep 17 00:00:00 2001 From: Aaron Dodson Date: Fri, 28 Mar 2025 13:54:33 -0700 Subject: [PATCH] refactor!: Remove old cursor and tab support. (#8803) --- core/block_svg.ts | 32 ---- core/blockly.ts | 4 - core/field.ts | 9 - core/field_input.ts | 14 -- core/keyboard_nav/basic_cursor.ts | 222 ----------------------- core/keyboard_nav/tab_navigate_cursor.ts | 45 ----- 6 files changed, 326 deletions(-) delete mode 100644 core/keyboard_nav/basic_cursor.ts delete mode 100644 core/keyboard_nav/tab_navigate_cursor.ts diff --git a/core/block_svg.ts b/core/block_svg.ts index a33a21a85..1b76ed3f1 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -34,7 +34,6 @@ import {BlockDragStrategy} from './dragging/block_drag_strategy.js'; import type {BlockMove} from './events/events_block_move.js'; import {EventType} from './events/type.js'; import * as eventUtils from './events/utils.js'; -import type {Field} from './field.js'; import {FieldLabel} from './field_label.js'; import {IconType} from './icons/icon_types.js'; import {MutatorIcon} from './icons/mutator_icon.js'; @@ -46,8 +45,6 @@ import type {ICopyable} from './interfaces/i_copyable.js'; import type {IDragStrategy, IDraggable} from './interfaces/i_draggable.js'; import {IIcon} from './interfaces/i_icon.js'; import * as internalConstants from './internal_constants.js'; -import {ASTNode} from './keyboard_nav/ast_node.js'; -import {TabNavigateCursor} from './keyboard_nav/tab_navigate_cursor.js'; import {MarkerManager} from './marker_manager.js'; import {Msg} from './msg.js'; import * as renderManagement from './render_management.js'; @@ -550,35 +547,6 @@ export class BlockSvg input.appendField(new FieldLabel(text), collapsedFieldName); } - /** - * Open the next (or previous) FieldTextInput. - * - * @param start Current field. - * @param forward If true go forward, otherwise backward. - */ - tab(start: Field, forward: boolean) { - const tabCursor = new TabNavigateCursor(); - tabCursor.setCurNode(ASTNode.createFieldNode(start)!); - const currentNode = tabCursor.getCurNode(); - - if (forward) { - tabCursor.next(); - } else { - tabCursor.prev(); - } - - const nextNode = tabCursor.getCurNode(); - if (nextNode && nextNode !== currentNode) { - const nextField = nextNode.getLocation() as Field; - nextField.showEditor(); - - // Also move the cursor if we're in keyboard nav mode. - if (this.workspace.keyboardAccessibilityMode) { - this.workspace.getCursor()!.setCurNode(nextNode); - } - } - } - /** * Handle a pointerdown on an SVG block. * diff --git a/core/blockly.ts b/core/blockly.ts index cf77bca3f..4c50c5ed5 100644 --- a/core/blockly.ts +++ b/core/blockly.ts @@ -169,10 +169,8 @@ import {IVariableMap} from './interfaces/i_variable_map.js'; import {IVariableModel, IVariableState} from './interfaces/i_variable_model.js'; import * as internalConstants from './internal_constants.js'; import {ASTNode} from './keyboard_nav/ast_node.js'; -import {BasicCursor} from './keyboard_nav/basic_cursor.js'; import {Cursor} from './keyboard_nav/cursor.js'; import {Marker} from './keyboard_nav/marker.js'; -import {TabNavigateCursor} from './keyboard_nav/tab_navigate_cursor.js'; import type {LayerManager} from './layer_manager.js'; import * as layers from './layers.js'; import {MarkerManager} from './marker_manager.js'; @@ -432,7 +430,6 @@ Names.prototype.populateProcedures = function ( // Re-export submodules that no longer declareLegacyNamespace. export { ASTNode, - BasicCursor, Block, BlockSvg, BlocklyOptions, @@ -589,7 +586,6 @@ export { ScrollbarPair, SeparatorFlyoutInflater, ShortcutRegistry, - TabNavigateCursor, Theme, ThemeManager, Toolbox, diff --git a/core/field.ts b/core/field.ts index deae29af9..9dbd5a5cf 100644 --- a/core/field.ts +++ b/core/field.ts @@ -1331,15 +1331,6 @@ export abstract class Field return false; } - /** - * Returns whether or not the field is tab navigable. - * - * @returns True if the field is tab navigable. - */ - isTabNavigable(): boolean { - return false; - } - /** * Handles the given keyboard shortcut. * diff --git a/core/field_input.ts b/core/field_input.ts index 98de56f7d..ed97544dc 100644 --- a/core/field_input.ts +++ b/core/field_input.ts @@ -562,11 +562,6 @@ export abstract class FieldInput extends Field< ); WidgetDiv.hideIfOwner(this); dropDownDiv.hideWithoutAnimation(); - } else if (e.key === 'Tab') { - WidgetDiv.hideIfOwner(this); - dropDownDiv.hideWithoutAnimation(); - (this.sourceBlock_ as BlockSvg).tab(this, !e.shiftKey); - e.preventDefault(); } } @@ -674,15 +669,6 @@ export abstract class FieldInput extends Field< return true; } - /** - * Returns whether or not the field is tab navigable. - * - * @returns True if the field is tab navigable. - */ - override isTabNavigable(): boolean { - return true; - } - /** * Use the `getText_` developer hook to override the field's text * representation. When we're currently editing, return the current HTML value diff --git a/core/keyboard_nav/basic_cursor.ts b/core/keyboard_nav/basic_cursor.ts deleted file mode 100644 index 752614152..000000000 --- a/core/keyboard_nav/basic_cursor.ts +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * The class representing a basic cursor. - * Used to demo switching between different cursors. - * - * @class - */ -// Former goog.module ID: Blockly.BasicCursor - -import * as registry from '../registry.js'; -import {ASTNode} from './ast_node.js'; -import {Cursor} from './cursor.js'; - -/** - * Class for a basic cursor. - * This will allow the user to get to all nodes in the AST by hitting next or - * previous. - */ -export class BasicCursor extends Cursor { - /** Name used for registering a basic cursor. */ - static readonly registrationName = 'basicCursor'; - - constructor() { - super(); - } - - /** - * Find the next node in the pre order traversal. - * - * @returns The next node, or null if the current node is not set or there is - * no next value. - */ - override next(): ASTNode | null { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - const newNode = this.getNextNode_(curNode, this.validNode_); - - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - /** - * For a basic cursor we only have the ability to go next and previous, so - * in will also allow the user to get to the next node in the pre order - * traversal. - * - * @returns The next node, or null if the current node is not set or there is - * no next value. - */ - override in(): ASTNode | null { - return this.next(); - } - - /** - * Find the previous node in the pre order traversal. - * - * @returns The previous node, or null if the current node is not set or there - * is no previous value. - */ - override prev(): ASTNode | null { - const curNode = this.getCurNode(); - if (!curNode) { - return null; - } - const newNode = this.getPreviousNode_(curNode, this.validNode_); - - if (newNode) { - this.setCurNode(newNode); - } - return newNode; - } - - /** - * For a basic cursor we only have the ability to go next and previous, so - * out will allow the user to get to the previous node in the pre order - * traversal. - * - * @returns The previous node, or null if the current node is not set or there - * is no previous value. - */ - override out(): ASTNode | null { - return this.prev(); - } - - /** - * Uses pre order traversal to navigate the Blockly AST. This will allow - * a user to easily navigate the entire Blockly AST without having to go in - * and out levels on the tree. - * - * @param node The current position in the AST. - * @param isValid A function true/false depending on whether the given node - * should be traversed. - * @returns The next node in the traversal. - */ - protected getNextNode_( - node: ASTNode | null, - isValid: (p1: ASTNode | null) => boolean, - ): ASTNode | null { - if (!node) { - return null; - } - const newNode = node.in() || node.next(); - if (isValid(newNode)) { - return newNode; - } else if (newNode) { - return this.getNextNode_(newNode, isValid); - } - const siblingOrParent = this.findSiblingOrParent(node.out()); - if (isValid(siblingOrParent)) { - return siblingOrParent; - } else if (siblingOrParent) { - return this.getNextNode_(siblingOrParent, isValid); - } - return null; - } - - /** - * Reverses the pre order traversal in order to find the previous node. This - * will allow a user to easily navigate the entire Blockly AST without having - * to go in and out levels on the tree. - * - * @param node The current position in the AST. - * @param isValid A function true/false depending on whether the given node - * should be traversed. - * @returns The previous node in the traversal or null if no previous node - * exists. - */ - protected getPreviousNode_( - node: ASTNode | null, - isValid: (p1: ASTNode | null) => boolean, - ): ASTNode | null { - if (!node) { - return null; - } - let newNode: ASTNode | null = node.prev(); - - if (newNode) { - newNode = this.getRightMostChild(newNode); - } else { - newNode = node.out(); - } - if (isValid(newNode)) { - return newNode; - } else if (newNode) { - return this.getPreviousNode_(newNode, isValid); - } - return null; - } - - /** - * Decides what nodes to traverse and which ones to skip. Currently, it - * skips output, stack and workspace nodes. - * - * @param node The AST node to check whether it is valid. - * @returns True if the node should be visited, false otherwise. - */ - protected validNode_(node: ASTNode | null): boolean { - let isValid = false; - const type = node && node.getType(); - if ( - type === ASTNode.types.OUTPUT || - type === ASTNode.types.INPUT || - type === ASTNode.types.FIELD || - type === ASTNode.types.NEXT || - type === ASTNode.types.PREVIOUS || - type === ASTNode.types.WORKSPACE - ) { - isValid = true; - } - return isValid; - } - - /** - * From the given node find either the next valid sibling or parent. - * - * @param node The current position in the AST. - * @returns The parent AST node or null if there are no valid parents. - */ - private findSiblingOrParent(node: ASTNode | null): ASTNode | null { - if (!node) { - return null; - } - const nextNode = node.next(); - if (nextNode) { - return nextNode; - } - return this.findSiblingOrParent(node.out()); - } - - /** - * Get the right most child of a node. - * - * @param node The node to find the right most child of. - * @returns The right most child of the given node, or the node if no child - * exists. - */ - private getRightMostChild(node: ASTNode | null): ASTNode | null { - if (!node!.in()) { - return node; - } - let newNode = node!.in(); - while (newNode && newNode.next()) { - newNode = newNode.next(); - } - return this.getRightMostChild(newNode); - } -} - -registry.register( - registry.Type.CURSOR, - BasicCursor.registrationName, - BasicCursor, -); diff --git a/core/keyboard_nav/tab_navigate_cursor.ts b/core/keyboard_nav/tab_navigate_cursor.ts deleted file mode 100644 index 0392887a1..000000000 --- a/core/keyboard_nav/tab_navigate_cursor.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * The class representing a cursor that is used to navigate - * between tab navigable fields. - * - * @class - */ -// Former goog.module ID: Blockly.TabNavigateCursor - -import type {Field} from '../field.js'; -import {ASTNode} from './ast_node.js'; -import {BasicCursor} from './basic_cursor.js'; - -/** - * A cursor for navigating between tab navigable fields. - */ -export class TabNavigateCursor extends BasicCursor { - /** - * Skip all nodes except for tab navigable fields. - * - * @param node The AST node to check whether it is valid. - * @returns True if the node should be visited, false otherwise. - */ - override validNode_(node: ASTNode | null): boolean { - let isValid = false; - const type = node && node.getType(); - if (node) { - const location = node.getLocation() as Field; - if ( - type === ASTNode.types.FIELD && - location && - location.isTabNavigable() && - location.isClickable() - ) { - isValid = true; - } - } - return isValid; - } -}