mirror of
https://github.com/google/blockly.git
synced 2026-05-12 23:20:10 +02:00
b0475b0c68
* fix: Remove spurious blank lines Remove extraneous blank lines introduced by deletion of 'use strict'; pragmas. Also fix the location of the goog.declareModuleId call in core/utils/array.ts. * fix: Add missing double-blank-line before body of modules Our convention is to have two blank lines between the imports (or module ID, if there are no imports) and the beginning of the body of the module. Enforce this. * fix: one addition format error for PR #6243
135 lines
3.1 KiB
TypeScript
135 lines
3.1 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2019 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview The class representing a cursor.
|
|
* Used primarily for keyboard navigation.
|
|
*/
|
|
|
|
/**
|
|
* The class representing a cursor.
|
|
* Used primarily for keyboard navigation.
|
|
* @class
|
|
*/
|
|
import * as goog from '../../closure/goog/goog.js';
|
|
goog.declareModuleId('Blockly.Cursor');
|
|
|
|
import * as registry from '../registry.js';
|
|
|
|
import {ASTNode} from './ast_node.js';
|
|
import {Marker} from './marker.js';
|
|
|
|
|
|
/**
|
|
* Class for a cursor.
|
|
* A cursor controls how a user navigates the Blockly AST.
|
|
* @alias Blockly.Cursor
|
|
*/
|
|
export class Cursor extends Marker {
|
|
override type = 'cursor';
|
|
|
|
/** @alias Blockly.Cursor */
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
/**
|
|
* Find the next connection, field, or block.
|
|
* @return The next element, or null if the current node is not set or there
|
|
* is no next value.
|
|
*/
|
|
next(): ASTNode|null {
|
|
const curNode = this.getCurNode();
|
|
if (!curNode) {
|
|
return null;
|
|
}
|
|
|
|
let newNode = curNode.next();
|
|
while (newNode && newNode.next() &&
|
|
(newNode.getType() === ASTNode.types.NEXT ||
|
|
newNode.getType() === ASTNode.types.BLOCK)) {
|
|
newNode = newNode.next();
|
|
}
|
|
|
|
if (newNode) {
|
|
this.setCurNode(newNode);
|
|
}
|
|
return newNode;
|
|
}
|
|
|
|
/**
|
|
* Find the in connection or field.
|
|
* @return The in element, or null if the current node is not set or there is
|
|
* no in value.
|
|
*/
|
|
in(): ASTNode|null {
|
|
let curNode: ASTNode|null = this.getCurNode();
|
|
if (!curNode) {
|
|
return null;
|
|
}
|
|
// If we are on a previous or output connection, go to the block level
|
|
// before performing next operation.
|
|
if (curNode.getType() === ASTNode.types.PREVIOUS ||
|
|
curNode.getType() === ASTNode.types.OUTPUT) {
|
|
curNode = curNode.next();
|
|
}
|
|
const newNode = curNode?.in() ?? null;
|
|
|
|
if (newNode) {
|
|
this.setCurNode(newNode);
|
|
}
|
|
return newNode;
|
|
}
|
|
|
|
/**
|
|
* Find the previous connection, field, or block.
|
|
* @return The previous element, or null if the current node is not set or
|
|
* there is no previous value.
|
|
*/
|
|
prev(): ASTNode|null {
|
|
const curNode = this.getCurNode();
|
|
if (!curNode) {
|
|
return null;
|
|
}
|
|
let newNode = curNode.prev();
|
|
|
|
while (newNode && newNode.prev() &&
|
|
(newNode.getType() === ASTNode.types.NEXT ||
|
|
newNode.getType() === ASTNode.types.BLOCK)) {
|
|
newNode = newNode.prev();
|
|
}
|
|
|
|
if (newNode) {
|
|
this.setCurNode(newNode);
|
|
}
|
|
return newNode;
|
|
}
|
|
|
|
/**
|
|
* Find the out connection, field, or block.
|
|
* @return The out element, or null if the current node is not set or there is
|
|
* no out value.
|
|
*/
|
|
out(): ASTNode|null {
|
|
const curNode = this.getCurNode();
|
|
if (!curNode) {
|
|
return null;
|
|
}
|
|
let newNode = curNode.out();
|
|
|
|
if (newNode && newNode.getType() === ASTNode.types.BLOCK) {
|
|
newNode = newNode.prev() || newNode;
|
|
}
|
|
|
|
if (newNode) {
|
|
this.setCurNode(newNode);
|
|
}
|
|
return newNode;
|
|
}
|
|
}
|
|
|
|
registry.register(registry.Type.CURSOR, registry.DEFAULT, Cursor);
|