mirror of
https://github.com/google/blockly.git
synced 2026-01-07 17:10:11 +01:00
release: Merge branch 'develop' into rc/v11.2.0
This commit is contained in:
@@ -101,6 +101,8 @@ function buildTSOverride({files, tsconfig}) {
|
||||
'@typescript-eslint/no-empty-function': ['off'],
|
||||
// Temporarily disable. 3 problems.
|
||||
'@typescript-eslint/no-empty-interface': ['off'],
|
||||
// We use this pattern extensively for block (e.g. controls_if) interfaces.
|
||||
'@typescript-eslint/no-empty-object-type': ['off'],
|
||||
|
||||
// TsDoc rules (using JsDoc plugin)
|
||||
// Disable built-in jsdoc verifier.
|
||||
|
||||
2
.github/workflows/appengine_deploy.yml
vendored
2
.github/workflows/appengine_deploy.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
path: _deploy/
|
||||
|
||||
- name: Deploy to App Engine
|
||||
uses: google-github-actions/deploy-appengine@v2.1.0
|
||||
uses: google-github-actions/deploy-appengine@v2.1.3
|
||||
# For parameters see:
|
||||
# https://github.com/google-github-actions/deploy-appengine#inputs
|
||||
with:
|
||||
|
||||
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
# TODO (#2114): re-enable osx build.
|
||||
# os: [ubuntu-latest, macos-latest]
|
||||
os: [ubuntu-latest]
|
||||
node-version: [18.x, 20.x]
|
||||
node-version: [18.x, 20.x, 22.x]
|
||||
# See supported Node.js release schedule at
|
||||
# https://nodejs.org/en/about/releases/
|
||||
|
||||
@@ -37,8 +37,8 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Npm Install
|
||||
run: npm install
|
||||
- name: Npm Clean Install
|
||||
run: npm ci
|
||||
|
||||
- name: Linux Test Setup
|
||||
if: runner.os == 'Linux'
|
||||
|
||||
@@ -10,4 +10,6 @@ module.exports = {
|
||||
bracketSpacing: false,
|
||||
// Put HTML tag closing brackets on same line as last attribute.
|
||||
bracketSameLine: true,
|
||||
// Organise imports using a plugin.
|
||||
'plugins': ['prettier-plugin-organize-imports'],
|
||||
};
|
||||
|
||||
@@ -6,6 +6,6 @@ var msg = 'Compiled Blockly files should be loaded from https://unpkg.com/blockl
|
||||
console.log(msg);
|
||||
try {
|
||||
alert(msg);
|
||||
} catch (_e) {
|
||||
} catch {
|
||||
// Can't alert? Probably node.js.
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks
|
||||
|
||||
import type {BlockDefinition} from '../core/blocks.js';
|
||||
import * as lists from './lists.js';
|
||||
import * as logic from './logic.js';
|
||||
import * as loops from './loops.js';
|
||||
@@ -14,7 +15,6 @@ import * as procedures from './procedures.js';
|
||||
import * as texts from './text.js';
|
||||
import * as variables from './variables.js';
|
||||
import * as variablesDynamic from './variables_dynamic.js';
|
||||
import type {BlockDefinition} from '../core/blocks.js';
|
||||
|
||||
export {
|
||||
lists,
|
||||
|
||||
@@ -6,22 +6,22 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.lists
|
||||
|
||||
import * as fieldRegistry from '../core/field_registry.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import {Align} from '../core/inputs/align.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {Connection} from '../core/connection.js';
|
||||
import type {BlockSvg} from '../core/block_svg.js';
|
||||
import type {FieldDropdown} from '../core/field_dropdown.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import {MutatorIcon} from '../core/icons/mutator_icon.js';
|
||||
import type {Workspace} from '../core/workspace.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import type {Connection} from '../core/connection.js';
|
||||
import '../core/field_dropdown.js';
|
||||
import type {FieldDropdown} from '../core/field_dropdown.js';
|
||||
import * as fieldRegistry from '../core/field_registry.js';
|
||||
import {MutatorIcon} from '../core/icons/mutator_icon.js';
|
||||
import {Align} from '../core/inputs/align.js';
|
||||
import {ValueInput} from '../core/inputs/value_input.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {Workspace} from '../core/workspace.js';
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
|
||||
@@ -6,22 +6,22 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.logic
|
||||
|
||||
import * as Events from '../core/events/events.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {BlockSvg} from '../core/block_svg.js';
|
||||
import type {Connection} from '../core/connection.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import type {Workspace} from '../core/workspace.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import type {Connection} from '../core/connection.js';
|
||||
import * as Events from '../core/events/events.js';
|
||||
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import '../core/field_dropdown.js';
|
||||
import '../core/field_label.js';
|
||||
import '../core/icons/mutator_icon.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {Workspace} from '../core/workspace.js';
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
|
||||
@@ -6,27 +6,27 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.loops
|
||||
|
||||
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import type {
|
||||
ContextMenuOption,
|
||||
LegacyContextMenuOption,
|
||||
} from '../core/contextmenu_registry.js';
|
||||
import * as Events from '../core/events/events.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import * as eventUtils from '../core/events/utils.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import '../core/field_dropdown.js';
|
||||
import '../core/field_label.js';
|
||||
import '../core/field_number.js';
|
||||
import '../core/field_variable.js';
|
||||
import '../core/icons/warning_icon.js';
|
||||
import {FieldVariable} from '../core/field_variable.js';
|
||||
import '../core/icons/warning_icon.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.math
|
||||
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import type {FieldDropdown} from '../core/field_dropdown.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import '../core/field_dropdown.js';
|
||||
import type {FieldDropdown} from '../core/field_dropdown.js';
|
||||
import '../core/field_label.js';
|
||||
import '../core/field_number.js';
|
||||
import '../core/field_variable.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
|
||||
@@ -6,40 +6,40 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.procedures
|
||||
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import * as Events from '../core/events/events.js';
|
||||
import * as Procedures from '../core/procedures.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import * as Xml from '../core/xml.js';
|
||||
import * as fieldRegistry from '../core/field_registry.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import {Align} from '../core/inputs/align.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {BlockSvg} from '../core/block_svg.js';
|
||||
import type {BlockCreate} from '../core/events/events_block_create.js';
|
||||
import type {BlockChange} from '../core/events/events_block_change.js';
|
||||
import type {BlockDefinition} from '../core/blocks.js';
|
||||
import * as common from '../core/common.js';
|
||||
import {defineBlocks} from '../core/common.js';
|
||||
import {config} from '../core/config.js';
|
||||
import type {Connection} from '../core/connection.js';
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import type {
|
||||
ContextMenuOption,
|
||||
LegacyContextMenuOption,
|
||||
} from '../core/contextmenu_registry.js';
|
||||
import * as Events from '../core/events/events.js';
|
||||
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import type {BlockChange} from '../core/events/events_block_change.js';
|
||||
import type {BlockCreate} from '../core/events/events_block_create.js';
|
||||
import * as eventUtils from '../core/events/utils.js';
|
||||
import {FieldCheckbox} from '../core/field_checkbox.js';
|
||||
import {FieldLabel} from '../core/field_label.js';
|
||||
import * as fieldRegistry from '../core/field_registry.js';
|
||||
import {FieldTextInput} from '../core/field_textinput.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import '../core/icons/comment_icon.js';
|
||||
import {MutatorIcon as Mutator} from '../core/icons/mutator_icon.js';
|
||||
import '../core/icons/warning_icon.js';
|
||||
import {Align} from '../core/inputs/align.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import {Names} from '../core/names.js';
|
||||
import * as Procedures from '../core/procedures.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {VariableModel} from '../core/variable_model.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import type {Workspace} from '../core/workspace.js';
|
||||
import type {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
import {config} from '../core/config.js';
|
||||
import {defineBlocks} from '../core/common.js';
|
||||
import '../core/icons/comment_icon.js';
|
||||
import '../core/icons/warning_icon.js';
|
||||
import * as common from '../core/common.js';
|
||||
import * as Xml from '../core/xml.js';
|
||||
|
||||
/** A dictionary of the block definitions provided by this module. */
|
||||
export const blocks: {[key: string]: BlockDefinition} = {};
|
||||
@@ -1206,7 +1206,7 @@ blocks['procedures_callreturn'] = {
|
||||
this.appendDummyInput('TOPROW').appendField('', 'NAME');
|
||||
this.setOutput(true);
|
||||
this.setStyle('procedure_blocks');
|
||||
// Tooltip is set in domToMutation.
|
||||
// Tooltip is set in renameProcedure.
|
||||
this.setHelpUrl(Msg['PROCEDURES_CALLRETURN_HELPURL']);
|
||||
this.arguments_ = [];
|
||||
this.argumentVarModels_ = [];
|
||||
|
||||
@@ -6,25 +6,25 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.texts
|
||||
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import * as fieldRegistry from '../core/field_registry.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import {Align} from '../core/inputs/align.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {BlockSvg} from '../core/block_svg.js';
|
||||
import {Connection} from '../core/connection.js';
|
||||
import {FieldImage} from '../core/field_image.js';
|
||||
import {FieldDropdown} from '../core/field_dropdown.js';
|
||||
import {FieldTextInput} from '../core/field_textinput.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import {MutatorIcon} from '../core/icons/mutator_icon.js';
|
||||
import type {Workspace} from '../core/workspace.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import {Connection} from '../core/connection.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import {FieldDropdown} from '../core/field_dropdown.js';
|
||||
import {FieldImage} from '../core/field_image.js';
|
||||
import * as fieldRegistry from '../core/field_registry.js';
|
||||
import {FieldTextInput} from '../core/field_textinput.js';
|
||||
import '../core/field_variable.js';
|
||||
import {MutatorIcon} from '../core/icons/mutator_icon.js';
|
||||
import {Align} from '../core/inputs/align.js';
|
||||
import {ValueInput} from '../core/inputs/value_input.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {Workspace} from '../core/workspace.js';
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
@@ -438,6 +438,11 @@ const PROMPT_COMMON = {
|
||||
domToMutation: function (this: PromptCommonBlock, xmlElement: Element) {
|
||||
this.updateType_(xmlElement.getAttribute('type')!);
|
||||
},
|
||||
|
||||
// These blocks do not need JSO serialization hooks (saveExtraState
|
||||
// and loadExtraState) because the state of this object is already
|
||||
// encoded in the dropdown values.
|
||||
// XML hooks are kept for backwards compatibility.
|
||||
};
|
||||
|
||||
blocks['text_prompt_ext'] = {
|
||||
@@ -468,16 +473,11 @@ blocks['text_prompt_ext'] = {
|
||||
: Msg['TEXT_PROMPT_TOOLTIP_NUMBER'];
|
||||
});
|
||||
},
|
||||
|
||||
// This block does not need JSO serialization hooks (saveExtraState and
|
||||
// loadExtraState) because the state of this object is already encoded in the
|
||||
// dropdown values.
|
||||
// XML hooks are kept for backwards compatibility.
|
||||
};
|
||||
|
||||
type PromptBlock = Block & PromptCommonMixin & QuoteImageMixin;
|
||||
|
||||
const TEXT_PROMPT_BLOCK = {
|
||||
blocks['text_prompt'] = {
|
||||
...PROMPT_COMMON,
|
||||
/**
|
||||
* Block for prompt function (internal message).
|
||||
@@ -520,8 +520,6 @@ const TEXT_PROMPT_BLOCK = {
|
||||
},
|
||||
};
|
||||
|
||||
blocks['text_prompt'] = TEXT_PROMPT_BLOCK;
|
||||
|
||||
blocks['text_count'] = {
|
||||
/**
|
||||
* Block for counting how many times one string appears within another string.
|
||||
@@ -666,7 +664,7 @@ const QUOTE_IMAGE_MIXIN = {
|
||||
* closing double quote. The selected quote will be adapted for RTL blocks.
|
||||
*
|
||||
* @param open If the image should be open quote (“ in LTR).
|
||||
* Otherwise, a closing quote is used (” in LTR).
|
||||
* Otherwise, a closing quote is used (” in LTR).
|
||||
* @returns The new field.
|
||||
*/
|
||||
newQuote_: function (this: QuoteImageBlock, open: boolean): FieldImage {
|
||||
|
||||
@@ -6,22 +6,22 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.variables
|
||||
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {
|
||||
ContextMenuOption,
|
||||
LegacyContextMenuOption,
|
||||
} from '../core/contextmenu_registry.js';
|
||||
import {FieldVariable} from '../core/field_variable.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import type {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import type {
|
||||
ContextMenuOption,
|
||||
LegacyContextMenuOption,
|
||||
} from '../core/contextmenu_registry.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import '../core/field_label.js';
|
||||
import {FieldVariable} from '../core/field_variable.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import type {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
|
||||
// Former goog.module ID: Blockly.libraryBlocks.variablesDynamic
|
||||
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {
|
||||
ContextMenuOption,
|
||||
LegacyContextMenuOption,
|
||||
} from '../core/contextmenu_registry.js';
|
||||
import {FieldVariable} from '../core/field_variable.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import type {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
import {
|
||||
createBlockDefinitionsFromJsonArray,
|
||||
defineBlocks,
|
||||
} from '../core/common.js';
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import type {
|
||||
ContextMenuOption,
|
||||
LegacyContextMenuOption,
|
||||
} from '../core/contextmenu_registry.js';
|
||||
import {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import '../core/field_label.js';
|
||||
import {FieldVariable} from '../core/field_variable.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import type {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
|
||||
108
core/block.ts
108
core/block.ts
@@ -23,35 +23,36 @@ import * as common from './common.js';
|
||||
import {Connection} from './connection.js';
|
||||
import {ConnectionType} from './connection_type.js';
|
||||
import * as constants from './constants.js';
|
||||
import {DuplicateIconType} from './icons/exceptions.js';
|
||||
import type {Abstract} from './events/events_abstract.js';
|
||||
import type {BlockChange} from './events/events_block_change.js';
|
||||
import type {BlockMove} from './events/events_block_move.js';
|
||||
import * as deprecation from './utils/deprecation.js';
|
||||
import {EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import * as Extensions from './extensions.js';
|
||||
import type {Field} from './field.js';
|
||||
import * as fieldRegistry from './field_registry.js';
|
||||
import {Input} from './inputs/input.js';
|
||||
import {Align} from './inputs/align.js';
|
||||
import type {IASTNodeLocation} from './interfaces/i_ast_node_location.js';
|
||||
import {type IIcon} from './interfaces/i_icon.js';
|
||||
import {isCommentIcon} from './interfaces/i_comment_icon.js';
|
||||
import {DuplicateIconType} from './icons/exceptions.js';
|
||||
import {IconType} from './icons/icon_types.js';
|
||||
import type {MutatorIcon} from './icons/mutator_icon.js';
|
||||
import {Align} from './inputs/align.js';
|
||||
import {DummyInput} from './inputs/dummy_input.js';
|
||||
import {EndRowInput} from './inputs/end_row_input.js';
|
||||
import {Input} from './inputs/input.js';
|
||||
import {StatementInput} from './inputs/statement_input.js';
|
||||
import {ValueInput} from './inputs/value_input.js';
|
||||
import type {IASTNodeLocation} from './interfaces/i_ast_node_location.js';
|
||||
import {isCommentIcon} from './interfaces/i_comment_icon.js';
|
||||
import {type IIcon} from './interfaces/i_icon.js';
|
||||
import * as registry from './registry.js';
|
||||
import * as Tooltip from './tooltip.js';
|
||||
import * as arrayUtils from './utils/array.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import * as deprecation from './utils/deprecation.js';
|
||||
import * as idGenerator from './utils/idgenerator.js';
|
||||
import * as parsing from './utils/parsing.js';
|
||||
import * as registry from './registry.js';
|
||||
import {Size} from './utils/size.js';
|
||||
import type {VariableModel} from './variable_model.js';
|
||||
import type {Workspace} from './workspace.js';
|
||||
import {DummyInput} from './inputs/dummy_input.js';
|
||||
import {EndRowInput} from './inputs/end_row_input.js';
|
||||
import {ValueInput} from './inputs/value_input.js';
|
||||
import {StatementInput} from './inputs/statement_input.js';
|
||||
import {IconType} from './icons/icon_types.js';
|
||||
|
||||
/**
|
||||
* Class for one block.
|
||||
@@ -143,24 +144,31 @@ export class Block implements IASTNodeLocation {
|
||||
suppressPrefixSuffix: boolean | null = false;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* An optional method for declaring developer variables, to be used
|
||||
* by generators. Developer variables are never shown to the user,
|
||||
* but are declared as global variables in the generated code.
|
||||
*
|
||||
* @returns a list of developer variable names.
|
||||
*/
|
||||
getDeveloperVariables?: () => string[];
|
||||
|
||||
/**
|
||||
* An optional function that reconfigures the block based on the contents of
|
||||
* the mutator dialog.
|
||||
* An optional method that reconfigures the block based on the
|
||||
* contents of the mutator dialog.
|
||||
*
|
||||
* @param rootBlock The root block in the mutator flyout.
|
||||
*/
|
||||
compose?: (p1: Block) => void;
|
||||
compose?: (rootBlock: Block) => void;
|
||||
|
||||
/**
|
||||
* An optional function that populates the mutator's dialog with
|
||||
* this block's components.
|
||||
* An optional function that populates the mutator flyout with
|
||||
* blocks representing this block's configuration.
|
||||
*
|
||||
* @param workspace The mutator flyout's workspace.
|
||||
* @returns The root block created in the flyout's workspace.
|
||||
*/
|
||||
decompose?: (p1: Workspace) => Block;
|
||||
decompose?: (workspace: Workspace) => Block;
|
||||
|
||||
id: string;
|
||||
outputConnection: Connection | null = null;
|
||||
nextConnection: Connection | null = null;
|
||||
@@ -216,7 +224,7 @@ export class Block implements IASTNodeLocation {
|
||||
/**
|
||||
* String for block help, or function that returns a URL. Null for no help.
|
||||
*/
|
||||
helpUrl: string | Function | null = null;
|
||||
helpUrl: string | (() => string) | null = null;
|
||||
|
||||
/** A bound callback function to use when the parent workspace changes. */
|
||||
private onchangeWrapper_: ((p1: Abstract) => void) | null = null;
|
||||
@@ -297,7 +305,7 @@ export class Block implements IASTNodeLocation {
|
||||
|
||||
// Fire a create event.
|
||||
if (eventUtils.isEnabled()) {
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(this));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(this));
|
||||
}
|
||||
} finally {
|
||||
eventUtils.setGroup(existingGroup);
|
||||
@@ -332,7 +340,7 @@ export class Block implements IASTNodeLocation {
|
||||
this.unplug(healStack);
|
||||
if (eventUtils.isEnabled()) {
|
||||
// Constructing the delete event is costly. Only perform if necessary.
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_DELETE))(this));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.BLOCK_DELETE))(this));
|
||||
}
|
||||
this.workspace.removeTopBlock(this);
|
||||
this.disposeInternal();
|
||||
@@ -716,7 +724,7 @@ export class Block implements IASTNodeLocation {
|
||||
}
|
||||
|
||||
// Check that block is connected to new parent if new parent is not null and
|
||||
// that block is not connected to superior one if new parent is null.
|
||||
// that block is not connected to superior one if new parent is null.
|
||||
const targetBlock =
|
||||
(this.previousConnection && this.previousConnection.targetBlock()) ||
|
||||
(this.outputConnection && this.outputConnection.targetBlock());
|
||||
@@ -734,14 +742,13 @@ export class Block implements IASTNodeLocation {
|
||||
}
|
||||
|
||||
// This block hasn't actually moved on-screen, so there's no need to
|
||||
// update
|
||||
// its connection locations.
|
||||
// update its connection locations.
|
||||
if (this.parentBlock_) {
|
||||
// Remove this block from the old parent's child list.
|
||||
arrayUtils.removeElem(this.parentBlock_.childBlocks_, this);
|
||||
} else {
|
||||
// New parent must be non-null so remove this block from the workspace's
|
||||
// list of top-most blocks.
|
||||
// New parent must be non-null so remove this block from the
|
||||
// workspace's list of top-most blocks.
|
||||
this.workspace.removeTopBlock(this);
|
||||
}
|
||||
|
||||
@@ -991,7 +998,7 @@ export class Block implements IASTNodeLocation {
|
||||
* @param url URL string for block help, or function that returns a URL. Null
|
||||
* for no help.
|
||||
*/
|
||||
setHelpUrl(url: string | Function) {
|
||||
setHelpUrl(url: string | (() => string)) {
|
||||
this.helpUrl = url;
|
||||
}
|
||||
|
||||
@@ -1323,7 +1330,7 @@ export class Block implements IASTNodeLocation {
|
||||
setInputsInline(newBoolean: boolean) {
|
||||
if (this.inputsInline !== newBoolean) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this,
|
||||
'inline',
|
||||
null,
|
||||
@@ -1460,13 +1467,32 @@ export class Block implements IASTNodeLocation {
|
||||
* update whether the block is currently disabled for this reason.
|
||||
*/
|
||||
setDisabledReason(disabled: boolean, reason: string): void {
|
||||
// Workspaces that were serialized before the reason for being disabled
|
||||
// could be specified may have blocks that are disabled without a known
|
||||
// reason. On being loaded, these blocks will default to having the manually
|
||||
// disabled reason. However, if the user isn't allowed to manually disable
|
||||
// or enable blocks, then this manually disabled reason cannot be removed.
|
||||
// For backward compatibility with these legacy workspaces, when removing
|
||||
// any disabled reason and the workspace does not allow manually disabling
|
||||
// but the block is manually disabled, then remove the manually disabled
|
||||
// reason in addition to the more specific reason. For example, when an
|
||||
// orphaned block is no longer orphaned, the block should be enabled again.
|
||||
if (
|
||||
!disabled &&
|
||||
!this.workspace.options.disable &&
|
||||
this.hasDisabledReason(constants.MANUALLY_DISABLED) &&
|
||||
reason != constants.MANUALLY_DISABLED
|
||||
) {
|
||||
this.setDisabledReason(false, constants.MANUALLY_DISABLED);
|
||||
}
|
||||
|
||||
if (this.disabledReasons.has(reason) !== disabled) {
|
||||
if (disabled) {
|
||||
this.disabledReasons.add(reason);
|
||||
} else {
|
||||
this.disabledReasons.delete(reason);
|
||||
}
|
||||
const blockChangeEvent = new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
const blockChangeEvent = new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this,
|
||||
'disabled',
|
||||
/* name= */ null,
|
||||
@@ -1534,7 +1560,7 @@ export class Block implements IASTNodeLocation {
|
||||
setCollapsed(collapsed: boolean) {
|
||||
if (this.collapsed_ !== collapsed) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this,
|
||||
'collapsed',
|
||||
null,
|
||||
@@ -1839,7 +1865,7 @@ export class Block implements IASTNodeLocation {
|
||||
const rawValue = json['colour'];
|
||||
try {
|
||||
this.setColour(rawValue);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
console.warn(warningPrefix + 'Illegal colour value: ', rawValue);
|
||||
}
|
||||
}
|
||||
@@ -1856,7 +1882,7 @@ export class Block implements IASTNodeLocation {
|
||||
const blockStyleName = json['style'];
|
||||
try {
|
||||
this.setStyle(blockStyleName);
|
||||
} catch (styleError) {
|
||||
} catch {
|
||||
console.warn(warningPrefix + 'Style does not exist: ', blockStyleName);
|
||||
}
|
||||
}
|
||||
@@ -2333,7 +2359,7 @@ export class Block implements IASTNodeLocation {
|
||||
}
|
||||
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this,
|
||||
'comment',
|
||||
null,
|
||||
@@ -2433,10 +2459,8 @@ export class Block implements IASTNodeLocation {
|
||||
if (this.parentBlock_) {
|
||||
throw Error('Block has parent');
|
||||
}
|
||||
const event = new (eventUtils.get(eventUtils.BLOCK_MOVE))(
|
||||
this,
|
||||
) as BlockMove;
|
||||
reason && event.setReason(reason);
|
||||
const event = new (eventUtils.get(EventType.BLOCK_MOVE))(this) as BlockMove;
|
||||
if (reason) event.setReason(reason);
|
||||
this.xy_.translate(dx, dy);
|
||||
event.recordNew();
|
||||
eventUtils.fire(event);
|
||||
|
||||
@@ -16,7 +16,9 @@ import './events/events_selected.js';
|
||||
|
||||
import {Block} from './block.js';
|
||||
import * as blockAnimations from './block_animations.js';
|
||||
import {IDeletable} from './blockly.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import {BlockCopyData, BlockPaster} from './clipboard/block_paster.js';
|
||||
import * as common from './common.js';
|
||||
import {config} from './config.js';
|
||||
import type {Connection} from './connection.js';
|
||||
@@ -28,11 +30,15 @@ import {
|
||||
ContextMenuRegistry,
|
||||
LegacyContextMenuOption,
|
||||
} from './contextmenu_registry.js';
|
||||
import {BlockDragStrategy} from './dragging/block_drag_strategy.js';
|
||||
import type {BlockMove} from './events/events_block_move.js';
|
||||
import * as deprecation from './utils/deprecation.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';
|
||||
import {WarningIcon} from './icons/warning_icon.js';
|
||||
import type {Input} from './inputs/input.js';
|
||||
import type {IASTNodeLocationSvg} from './interfaces/i_ast_node_location_svg.js';
|
||||
import type {IBoundedElement} from './interfaces/i_bounded_element.js';
|
||||
@@ -44,26 +50,21 @@ 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 {MutatorIcon} from './icons/mutator_icon.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
import {RenderedConnection} from './rendered_connection.js';
|
||||
import type {IPathObject} from './renderers/common/i_path_object.js';
|
||||
import * as blocks from './serialization/blocks.js';
|
||||
import type {BlockStyle} from './theme.js';
|
||||
import * as Tooltip from './tooltip.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import * as deprecation from './utils/deprecation.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import {Rect} from './utils/rect.js';
|
||||
import {Svg} from './utils/svg.js';
|
||||
import * as svgMath from './utils/svg_math.js';
|
||||
import {WarningIcon} from './icons/warning_icon.js';
|
||||
import {FlyoutItemInfo} from './utils/toolbox.js';
|
||||
import type {Workspace} from './workspace.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
import {IconType} from './icons/icon_types.js';
|
||||
import {BlockCopyData, BlockPaster} from './clipboard/block_paster.js';
|
||||
import {BlockDragStrategy} from './dragging/block_drag_strategy.js';
|
||||
import {IDeletable} from './blockly.js';
|
||||
import {FlyoutItemInfo} from './utils/toolbox.js';
|
||||
|
||||
/**
|
||||
* Class for a block's SVG representation.
|
||||
@@ -92,7 +93,25 @@ export class BlockSvg
|
||||
static readonly COLLAPSED_WARNING_ID = 'TEMP_COLLAPSED_WARNING_';
|
||||
override decompose?: (p1: Workspace) => BlockSvg;
|
||||
// override compose?: ((p1: BlockSvg) => void)|null;
|
||||
saveConnections?: (p1: BlockSvg) => void;
|
||||
|
||||
/**
|
||||
* An optional method which saves a record of blocks connected to
|
||||
* this block so they can be later restored after this block is
|
||||
* recoomposed (reconfigured). Typically records the connected
|
||||
* blocks on properties on blocks in the mutator flyout, so that
|
||||
* rearranging those component blocks will automatically rearrange
|
||||
* the corresponding connected blocks on this block after this block
|
||||
* is recomposed.
|
||||
*
|
||||
* To keep the saved connection information up-to-date, MutatorIcon
|
||||
* arranges for an event listener to call this method any time the
|
||||
* mutator flyout is open and a change occurs on this block's
|
||||
* workspace.
|
||||
*
|
||||
* @param rootBlock The root block in the mutator flyout.
|
||||
*/
|
||||
saveConnections?: (rootBlock: BlockSvg) => void;
|
||||
|
||||
customContextMenu?: (
|
||||
p1: Array<ContextMenuOption | LegacyContextMenuOption>,
|
||||
) => void;
|
||||
@@ -109,6 +128,14 @@ export class BlockSvg
|
||||
*/
|
||||
width = 0;
|
||||
|
||||
/**
|
||||
* Width of this block, not including any connected value blocks.
|
||||
* Width is in workspace units.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
childlessWidth = 0;
|
||||
|
||||
/**
|
||||
* Map from IDs for warnings text to PIDs of functions to apply them.
|
||||
* Used to be able to maintain multiple warnings.
|
||||
@@ -252,7 +279,7 @@ export class BlockSvg
|
||||
this.addSelect();
|
||||
}
|
||||
|
||||
/** Unselects this block. Unhighlights the blockv visually. */
|
||||
/** Unselects this block. Unhighlights the block visually. */
|
||||
unselect() {
|
||||
if (this.isShadow()) {
|
||||
this.getParent()?.unselect();
|
||||
@@ -351,8 +378,8 @@ export class BlockSvg
|
||||
const eventsEnabled = eventUtils.isEnabled();
|
||||
let event: BlockMove | null = null;
|
||||
if (eventsEnabled) {
|
||||
event = new (eventUtils.get(eventUtils.BLOCK_MOVE)!)(this) as BlockMove;
|
||||
reason && event.setReason(reason);
|
||||
event = new (eventUtils.get(EventType.BLOCK_MOVE)!)(this) as BlockMove;
|
||||
if (reason) event.setReason(reason);
|
||||
}
|
||||
|
||||
const delta = new Coordinate(dx, dy);
|
||||
@@ -436,8 +463,28 @@ export class BlockSvg
|
||||
* @returns Object with coordinates of the bounding box.
|
||||
*/
|
||||
getBoundingRectangle(): Rect {
|
||||
return this.getBoundingRectangleWithDimensions(this.getHeightWidth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the coordinates of a bounding box describing the dimensions of this
|
||||
* block alone.
|
||||
* Coordinate system: workspace coordinates.
|
||||
*
|
||||
* @returns Object with coordinates of the bounding box.
|
||||
*/
|
||||
getBoundingRectangleWithoutChildren(): Rect {
|
||||
return this.getBoundingRectangleWithDimensions({
|
||||
height: this.height,
|
||||
width: this.childlessWidth,
|
||||
});
|
||||
}
|
||||
|
||||
private getBoundingRectangleWithDimensions(blockBounds: {
|
||||
height: number;
|
||||
width: number;
|
||||
}) {
|
||||
const blockXY = this.getRelativeToSurfaceXY();
|
||||
const blockBounds = this.getHeightWidth();
|
||||
let left;
|
||||
let right;
|
||||
if (this.RTL) {
|
||||
@@ -750,6 +797,25 @@ export class BlockSvg
|
||||
blockAnimations.disposeUiEffect(this);
|
||||
}
|
||||
|
||||
// Selecting a shadow block highlights an ancestor block, but that highlight
|
||||
// should be removed if the shadow block will be deleted. So, before
|
||||
// deleting blocks and severing the connections between them, check whether
|
||||
// doing so would delete a selected block and make sure that any associated
|
||||
// parent is updated.
|
||||
const selection = common.getSelected();
|
||||
if (selection instanceof Block) {
|
||||
let selectionAncestor: Block | null = selection;
|
||||
while (selectionAncestor !== null) {
|
||||
if (selectionAncestor === this) {
|
||||
// The block to be deleted contains the selected block, so remove any
|
||||
// selection highlight associated with the selected block before
|
||||
// deleting them.
|
||||
selection.unselect();
|
||||
}
|
||||
selectionAncestor = selectionAncestor.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
super.dispose(!!healStack);
|
||||
dom.removeNode(this.svgGroup_);
|
||||
}
|
||||
@@ -1125,10 +1191,11 @@ export class BlockSvg
|
||||
* <g> tags do not respect z-index so SVG renders them in the
|
||||
* order that they are in the DOM. By placing this block first within the
|
||||
* block group's <g>, it will render on top of any other blocks.
|
||||
* Use sparingly, this method is expensive because it reorders the DOM
|
||||
* nodes.
|
||||
*
|
||||
* @param blockOnly: True to only move this block to the front without
|
||||
* @param blockOnly True to only move this block to the front without
|
||||
* adjusting its parents.
|
||||
* @internal
|
||||
*/
|
||||
bringToFront(blockOnly = false) {
|
||||
/* eslint-disable-next-line @typescript-eslint/no-this-alias */
|
||||
|
||||
329
core/blockly.ts
329
core/blockly.ts
@@ -22,8 +22,10 @@ import {BlocklyOptions} from './blockly_options.js';
|
||||
import {Blocks} from './blocks.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as bubbles from './bubbles.js';
|
||||
import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js';
|
||||
import * as bumpObjects from './bump_objects.js';
|
||||
import * as clipboard from './clipboard.js';
|
||||
import * as comments from './comments.js';
|
||||
import * as common from './common.js';
|
||||
import {ComponentManager} from './component_manager.js';
|
||||
import {config} from './config.js';
|
||||
@@ -31,15 +33,15 @@ import {Connection} from './connection.js';
|
||||
import {ConnectionChecker} from './connection_checker.js';
|
||||
import {ConnectionDB} from './connection_db.js';
|
||||
import {ConnectionType} from './connection_type.js';
|
||||
import * as constants from './constants.js';
|
||||
import * as ContextMenu from './contextmenu.js';
|
||||
import * as ContextMenuItems from './contextmenu_items.js';
|
||||
import {ContextMenuRegistry} from './contextmenu_registry.js';
|
||||
import * as comments from './comments.js';
|
||||
import * as Css from './css.js';
|
||||
import {DeleteArea} from './delete_area.js';
|
||||
import * as dialog from './dialog.js';
|
||||
import * as dragging from './dragging.js';
|
||||
import {DragTarget} from './drag_target.js';
|
||||
import * as dragging from './dragging.js';
|
||||
import * as dropDownDiv from './dropdowndiv.js';
|
||||
import * as Events from './events/events.js';
|
||||
import * as Extensions from './extensions.js';
|
||||
@@ -104,8 +106,8 @@ import {Gesture} from './gesture.js';
|
||||
import {Grid} from './grid.js';
|
||||
import * as icons from './icons.js';
|
||||
import {inject} from './inject.js';
|
||||
import {Input} from './inputs/input.js';
|
||||
import * as inputs from './inputs.js';
|
||||
import {Input} from './inputs/input.js';
|
||||
import {InsertionMarkerManager} from './insertion_marker_manager.js';
|
||||
import {InsertionMarkerPreviewer} from './insertion_marker_previewer.js';
|
||||
import {IASTNodeLocation} from './interfaces/i_ast_node_location.js';
|
||||
@@ -119,16 +121,16 @@ import {IComponent} from './interfaces/i_component.js';
|
||||
import {IConnectionChecker} from './interfaces/i_connection_checker.js';
|
||||
import {IConnectionPreviewer} from './interfaces/i_connection_previewer.js';
|
||||
import {IContextMenu} from './interfaces/i_contextmenu.js';
|
||||
import {ICopyable, isCopyable, ICopyData} from './interfaces/i_copyable.js';
|
||||
import {ICopyData, ICopyable, isCopyable} from './interfaces/i_copyable.js';
|
||||
import {IDeletable, isDeletable} from './interfaces/i_deletable.js';
|
||||
import {IDeleteArea} from './interfaces/i_delete_area.js';
|
||||
import {IDragTarget} from './interfaces/i_drag_target.js';
|
||||
import {IDragger} from './interfaces/i_dragger.js';
|
||||
import {
|
||||
IDragStrategy,
|
||||
IDraggable,
|
||||
isDraggable,
|
||||
IDragStrategy,
|
||||
} from './interfaces/i_draggable.js';
|
||||
import {IDragger} from './interfaces/i_dragger.js';
|
||||
import {IFlyout} from './interfaces/i_flyout.js';
|
||||
import {IHasBubble, hasBubble} from './interfaces/i_has_bubble.js';
|
||||
import {IIcon, isIcon} from './interfaces/i_icon.js';
|
||||
@@ -159,22 +161,21 @@ 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 {MarkerManager} from './marker_manager.js';
|
||||
import type {LayerManager} from './layer_manager.js';
|
||||
import * as layers from './layers.js';
|
||||
import {MarkerManager} from './marker_manager.js';
|
||||
import {Menu} from './menu.js';
|
||||
import {MenuItem} from './menuitem.js';
|
||||
import {MetricsManager} from './metrics_manager.js';
|
||||
import {Msg, setLocale} from './msg.js';
|
||||
import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js';
|
||||
import {Names} from './names.js';
|
||||
import {Options} from './options.js';
|
||||
import * as uiPosition from './positionable_helpers.js';
|
||||
import * as Procedures from './procedures.js';
|
||||
import * as registry from './registry.js';
|
||||
import {RenderedConnection} from './rendered_connection.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
import {RenderedConnection} from './rendered_connection.js';
|
||||
import * as blockRendering from './renderers/common/block_rendering.js';
|
||||
import * as constants from './constants.js';
|
||||
import * as geras from './renderers/geras/geras.js';
|
||||
import * as thrasos from './renderers/thrasos/thrasos.js';
|
||||
import * as zelos from './renderers/zelos/zelos.js';
|
||||
@@ -417,171 +418,187 @@ Names.prototype.populateProcedures = function (
|
||||
// clang-format on
|
||||
|
||||
// Re-export submodules that no longer declareLegacyNamespace.
|
||||
export {browserEvents};
|
||||
export {ContextMenu};
|
||||
export {ContextMenuItems};
|
||||
export {Css};
|
||||
export {Events};
|
||||
export {Extensions};
|
||||
export {Procedures};
|
||||
export {Procedures as procedures};
|
||||
export {ShortcutItems};
|
||||
export {Themes};
|
||||
export {Tooltip};
|
||||
export {Touch};
|
||||
export {Variables};
|
||||
export {VariablesDynamic};
|
||||
export {WidgetDiv};
|
||||
export {Xml};
|
||||
export {blockAnimations};
|
||||
export {blockRendering};
|
||||
export {bumpObjects};
|
||||
export {clipboard};
|
||||
export {common};
|
||||
export {constants};
|
||||
export {dialog};
|
||||
export {fieldRegistry};
|
||||
export {geras};
|
||||
export {registry};
|
||||
export {thrasos};
|
||||
export {uiPosition};
|
||||
export {utils};
|
||||
export {zelos};
|
||||
export {ASTNode};
|
||||
export {BasicCursor};
|
||||
export {Block};
|
||||
export {BlocklyOptions};
|
||||
export {BlockSvg};
|
||||
export {Blocks};
|
||||
export {bubbles};
|
||||
export {CollapsibleToolboxCategory};
|
||||
export {ComponentManager};
|
||||
export {Connection};
|
||||
export {ConnectionType};
|
||||
export {ConnectionChecker};
|
||||
export {ConnectionDB};
|
||||
export {ContextMenuRegistry};
|
||||
export {comments};
|
||||
export {Cursor};
|
||||
export {DeleteArea};
|
||||
export {dragging};
|
||||
export {DragTarget};
|
||||
export const DropDownDiv = dropDownDiv;
|
||||
export {Field, FieldConfig, FieldValidator, UnattachedFieldError};
|
||||
export {
|
||||
ASTNode,
|
||||
BasicCursor,
|
||||
Block,
|
||||
BlockSvg,
|
||||
BlocklyOptions,
|
||||
Blocks,
|
||||
CollapsibleToolboxCategory,
|
||||
ComponentManager,
|
||||
Connection,
|
||||
ConnectionChecker,
|
||||
ConnectionDB,
|
||||
ConnectionType,
|
||||
ContextMenu,
|
||||
ContextMenuItems,
|
||||
ContextMenuRegistry,
|
||||
Css,
|
||||
Cursor,
|
||||
DeleteArea,
|
||||
DragTarget,
|
||||
Events,
|
||||
Extensions,
|
||||
Procedures,
|
||||
ShortcutItems,
|
||||
Themes,
|
||||
Tooltip,
|
||||
Touch,
|
||||
Variables,
|
||||
VariablesDynamic,
|
||||
WidgetDiv,
|
||||
Xml,
|
||||
blockAnimations,
|
||||
blockRendering,
|
||||
browserEvents,
|
||||
bubbles,
|
||||
bumpObjects,
|
||||
clipboard,
|
||||
comments,
|
||||
common,
|
||||
constants,
|
||||
dialog,
|
||||
dragging,
|
||||
fieldRegistry,
|
||||
geras,
|
||||
Procedures as procedures,
|
||||
registry,
|
||||
thrasos,
|
||||
uiPosition,
|
||||
utils,
|
||||
zelos,
|
||||
};
|
||||
export const DropDownDiv = dropDownDiv;
|
||||
export {
|
||||
CodeGenerator,
|
||||
Field,
|
||||
FieldCheckbox,
|
||||
FieldCheckboxConfig,
|
||||
FieldCheckboxFromJsonConfig,
|
||||
FieldCheckboxValidator,
|
||||
};
|
||||
export {
|
||||
FieldConfig,
|
||||
FieldDropdown,
|
||||
FieldDropdownConfig,
|
||||
FieldDropdownFromJsonConfig,
|
||||
FieldDropdownValidator,
|
||||
MenuGenerator,
|
||||
MenuGeneratorFunction,
|
||||
MenuOption,
|
||||
};
|
||||
export {FieldImage, FieldImageConfig, FieldImageFromJsonConfig};
|
||||
export {FieldLabel, FieldLabelConfig, FieldLabelFromJsonConfig};
|
||||
export {FieldLabelSerializable};
|
||||
export {
|
||||
FieldImage,
|
||||
FieldImageConfig,
|
||||
FieldImageFromJsonConfig,
|
||||
FieldLabel,
|
||||
FieldLabelConfig,
|
||||
FieldLabelFromJsonConfig,
|
||||
FieldLabelSerializable,
|
||||
FieldNumber,
|
||||
FieldNumberConfig,
|
||||
FieldNumberFromJsonConfig,
|
||||
FieldNumberValidator,
|
||||
};
|
||||
export {
|
||||
FieldTextInput,
|
||||
FieldTextInputConfig,
|
||||
FieldTextInputFromJsonConfig,
|
||||
FieldTextInputValidator,
|
||||
};
|
||||
export {
|
||||
FieldValidator,
|
||||
FieldVariable,
|
||||
FieldVariableConfig,
|
||||
FieldVariableFromJsonConfig,
|
||||
FieldVariableValidator,
|
||||
Flyout,
|
||||
FlyoutButton,
|
||||
FlyoutMetricsManager,
|
||||
CodeGenerator as Generator,
|
||||
Gesture,
|
||||
Grid,
|
||||
HorizontalFlyout,
|
||||
IASTNodeLocation,
|
||||
IASTNodeLocationSvg,
|
||||
IASTNodeLocationWithBlock,
|
||||
IAutoHideable,
|
||||
IBoundedElement,
|
||||
IBubble,
|
||||
ICollapsibleToolboxItem,
|
||||
IComponent,
|
||||
IConnectionChecker,
|
||||
IConnectionPreviewer,
|
||||
IContextMenu,
|
||||
ICopyData,
|
||||
ICopyable,
|
||||
IDeletable,
|
||||
IDeleteArea,
|
||||
IDragStrategy,
|
||||
IDragTarget,
|
||||
IDraggable,
|
||||
IDragger,
|
||||
IFlyout,
|
||||
IHasBubble,
|
||||
IIcon,
|
||||
IKeyboardAccessible,
|
||||
IMetricsManager,
|
||||
IMovable,
|
||||
IObservable,
|
||||
IPaster,
|
||||
IPositionable,
|
||||
IRegistrable,
|
||||
IRenderedElement,
|
||||
ISelectable,
|
||||
ISelectableToolboxItem,
|
||||
ISerializable,
|
||||
IStyleable,
|
||||
IToolbox,
|
||||
IToolboxItem,
|
||||
IVariableBackedParameterModel,
|
||||
Input,
|
||||
InsertionMarkerManager,
|
||||
InsertionMarkerPreviewer,
|
||||
LayerManager,
|
||||
Marker,
|
||||
MarkerManager,
|
||||
Menu,
|
||||
MenuGenerator,
|
||||
MenuGeneratorFunction,
|
||||
MenuItem,
|
||||
MenuOption,
|
||||
MetricsManager,
|
||||
Msg,
|
||||
Names,
|
||||
Options,
|
||||
RenderedConnection,
|
||||
Scrollbar,
|
||||
ScrollbarPair,
|
||||
ShortcutRegistry,
|
||||
TabNavigateCursor,
|
||||
Theme,
|
||||
ThemeManager,
|
||||
Toolbox,
|
||||
ToolboxCategory,
|
||||
ToolboxItem,
|
||||
ToolboxSeparator,
|
||||
Trashcan,
|
||||
UnattachedFieldError,
|
||||
VariableMap,
|
||||
VariableModel,
|
||||
VerticalFlyout,
|
||||
Workspace,
|
||||
WorkspaceAudio,
|
||||
WorkspaceDragger,
|
||||
WorkspaceSvg,
|
||||
ZoomControls,
|
||||
config,
|
||||
hasBubble,
|
||||
icons,
|
||||
inject,
|
||||
inputs,
|
||||
isCopyable,
|
||||
isDeletable,
|
||||
isDraggable,
|
||||
isIcon,
|
||||
isObservable,
|
||||
isPaster,
|
||||
isRenderedElement,
|
||||
isSelectable,
|
||||
isSerializable,
|
||||
isVariableBackedParameterModel,
|
||||
layers,
|
||||
renderManagement,
|
||||
serialization,
|
||||
setLocale,
|
||||
};
|
||||
export {Flyout};
|
||||
export {FlyoutButton};
|
||||
export {FlyoutMetricsManager};
|
||||
export {CodeGenerator};
|
||||
export {CodeGenerator as Generator}; // Deprecated name, October 2022.
|
||||
export {Gesture};
|
||||
export {Grid};
|
||||
export {HorizontalFlyout};
|
||||
export {IASTNodeLocation};
|
||||
export {IASTNodeLocationSvg};
|
||||
export {IASTNodeLocationWithBlock};
|
||||
export {IAutoHideable};
|
||||
export {IBoundedElement};
|
||||
export {IBubble};
|
||||
export {ICollapsibleToolboxItem};
|
||||
export {IComponent};
|
||||
export {IConnectionChecker};
|
||||
export {IConnectionPreviewer};
|
||||
export {IContextMenu};
|
||||
export {icons};
|
||||
export {ICopyable, isCopyable, ICopyData};
|
||||
export {IDeletable, isDeletable};
|
||||
export {IDeleteArea};
|
||||
export {IDragTarget};
|
||||
export {IDragger};
|
||||
export {IDraggable, isDraggable, IDragStrategy};
|
||||
export {IFlyout};
|
||||
export {IHasBubble, hasBubble};
|
||||
export {IIcon, isIcon};
|
||||
export {IKeyboardAccessible};
|
||||
export {IMetricsManager};
|
||||
export {IMovable};
|
||||
export {Input};
|
||||
export {inputs};
|
||||
export {InsertionMarkerManager};
|
||||
export {InsertionMarkerPreviewer};
|
||||
export {IObservable, isObservable};
|
||||
export {IPaster, isPaster};
|
||||
export {IPositionable};
|
||||
export {IRegistrable};
|
||||
export {IRenderedElement, isRenderedElement};
|
||||
export {ISelectable, isSelectable};
|
||||
export {ISelectableToolboxItem};
|
||||
export {ISerializable, isSerializable};
|
||||
export {IStyleable};
|
||||
export {IToolbox};
|
||||
export {IToolboxItem};
|
||||
export {IVariableBackedParameterModel, isVariableBackedParameterModel};
|
||||
export {Marker};
|
||||
export {MarkerManager};
|
||||
export {LayerManager};
|
||||
export {Menu};
|
||||
export {MenuItem};
|
||||
export {MetricsManager};
|
||||
export {Msg, setLocale};
|
||||
export {Names};
|
||||
export {Options};
|
||||
export {RenderedConnection};
|
||||
export {renderManagement};
|
||||
export {Scrollbar};
|
||||
export {ScrollbarPair};
|
||||
export {ShortcutRegistry};
|
||||
export {TabNavigateCursor};
|
||||
export {Theme};
|
||||
export {ThemeManager};
|
||||
export {Toolbox};
|
||||
export {ToolboxCategory};
|
||||
export {ToolboxItem};
|
||||
export {ToolboxSeparator};
|
||||
export {Trashcan};
|
||||
export {VariableMap};
|
||||
export {VariableModel};
|
||||
export {VerticalFlyout};
|
||||
export {Workspace};
|
||||
export {WorkspaceAudio};
|
||||
export {WorkspaceDragger};
|
||||
export {WorkspaceSvg};
|
||||
export {ZoomControls};
|
||||
export {config};
|
||||
export {inject};
|
||||
export {serialization};
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
// Former goog.module ID: Blockly.BlocklyOptions
|
||||
|
||||
import type {Theme, ITheme} from './theme.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import type {ITheme, Theme} from './theme.js';
|
||||
import type {ToolboxDefinition} from './utils/toolbox.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
|
||||
/**
|
||||
* Blockly options.
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
// Former goog.module ID: Blockly.browserEvents
|
||||
|
||||
// Theoretically we could figure out a way to type the event params correctly,
|
||||
// but it's not high priority.
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
|
||||
|
||||
import * as Touch from './touch.js';
|
||||
import * as userAgent from './utils/useragent.js';
|
||||
|
||||
@@ -47,7 +51,7 @@ const PAGE_MODE_MULTIPLIER = 125;
|
||||
export function conditionalBind(
|
||||
node: EventTarget,
|
||||
name: string,
|
||||
thisObject: Object | null,
|
||||
thisObject: object | null,
|
||||
func: Function,
|
||||
opt_noCaptureIdentifier?: boolean,
|
||||
): Data {
|
||||
@@ -96,7 +100,7 @@ export function conditionalBind(
|
||||
export function bind(
|
||||
node: EventTarget,
|
||||
name: string,
|
||||
thisObject: Object | null,
|
||||
thisObject: object | null,
|
||||
func: Function,
|
||||
): Data {
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
|
||||
import {Bubble} from './bubbles/bubble.js';
|
||||
import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js';
|
||||
import {TextBubble} from './bubbles/text_bubble.js';
|
||||
import {TextInputBubble} from './bubbles/textinput_bubble.js';
|
||||
import {MiniWorkspaceBubble} from './bubbles/mini_workspace_bubble.js';
|
||||
|
||||
export {Bubble, TextBubble, TextInputBubble, MiniWorkspaceBubble};
|
||||
export {Bubble, MiniWorkspaceBubble, TextBubble, TextInputBubble};
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {ISelectable} from '../blockly.js';
|
||||
import * as browserEvents from '../browser_events.js';
|
||||
import * as common from '../common.js';
|
||||
import {BubbleDragStrategy} from '../dragging/bubble_drag_strategy.js';
|
||||
import {IBubble} from '../interfaces/i_bubble.js';
|
||||
import {ContainerRegion} from '../metrics_manager.js';
|
||||
import {Scrollbar} from '../scrollbar.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import * as idGenerator from '../utils/idgenerator.js';
|
||||
import * as math from '../utils/math.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import * as common from '../common.js';
|
||||
import {ISelectable} from '../blockly.js';
|
||||
import * as idGenerator from '../utils/idgenerator.js';
|
||||
|
||||
/**
|
||||
* The abstract pop-up bubble class. This creates a UI that looks like a speech
|
||||
@@ -212,9 +212,10 @@ export abstract class Bubble implements IBubble, ISelectable {
|
||||
this.background.setAttribute('fill', colour);
|
||||
}
|
||||
|
||||
/** Passes the pointer event off to the gesture system. */
|
||||
/** Brings the bubble to the front and passes the pointer event off to the gesture system. */
|
||||
private onMouseDown(e: PointerEvent) {
|
||||
this.workspace.getGesture(e)?.handleBubbleStart(e, this);
|
||||
this.bringToFront();
|
||||
common.setSelected(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {Abstract as AbstractEvent} from '../events/events_abstract.js';
|
||||
import type {BlocklyOptions} from '../blockly_options.js';
|
||||
import {Bubble} from './bubble.js';
|
||||
import {Abstract as AbstractEvent} from '../events/events_abstract.js';
|
||||
import {Options} from '../options.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Options} from '../options.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import type {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import type {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {Bubble} from './bubble.js';
|
||||
|
||||
/**
|
||||
* A bubble that contains a mini-workspace which can hold arbitrary blocks.
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {Bubble} from './bubble.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {Bubble} from './bubble.js';
|
||||
|
||||
/**
|
||||
* A bubble that displays non-editable text. Used by the warning icon.
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {Bubble} from './bubble.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as Css from '../css.js';
|
||||
import * as touch from '../touch.js';
|
||||
import {browserEvents} from '../utils.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import * as touch from '../touch.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {browserEvents} from '../utils.js';
|
||||
import {Bubble} from './bubble.js';
|
||||
|
||||
/**
|
||||
* A bubble that displays editable text. It can also be resized by the user.
|
||||
|
||||
@@ -12,7 +12,9 @@ import type {BlockCreate} from './events/events_block_create.js';
|
||||
import type {BlockMove} from './events/events_block_move.js';
|
||||
import type {CommentCreate} from './events/events_comment_create.js';
|
||||
import type {CommentMove} from './events/events_comment_move.js';
|
||||
import type {ViewportChange} from './events/events_viewport.js';
|
||||
import type {CommentResize} from './events/events_comment_resize.js';
|
||||
import {isViewportChange} from './events/predicates.js';
|
||||
import {BUMP_EVENTS, EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import type {IBoundedElement} from './interfaces/i_bounded_element.js';
|
||||
import type {ContainerRegion} from './metrics_manager.js';
|
||||
@@ -98,7 +100,7 @@ export function bumpIntoBoundsHandler(
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventUtils.BUMP_EVENTS.includes(e.type ?? '')) {
|
||||
if (BUMP_EVENTS.includes(e.type ?? '')) {
|
||||
const scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true);
|
||||
|
||||
// Triggered by move/create event
|
||||
@@ -126,13 +128,8 @@ export function bumpIntoBoundsHandler(
|
||||
);
|
||||
}
|
||||
eventUtils.setGroup(existingGroup);
|
||||
} else if (e.type === eventUtils.VIEWPORT_CHANGE) {
|
||||
const viewportEvent = e as ViewportChange;
|
||||
if (
|
||||
viewportEvent.scale &&
|
||||
viewportEvent.oldScale &&
|
||||
viewportEvent.scale > viewportEvent.oldScale
|
||||
) {
|
||||
} else if (isViewportChange(e)) {
|
||||
if (e.scale && e.oldScale && e.scale > e.oldScale) {
|
||||
bumpTopObjectsIntoBounds(workspace);
|
||||
}
|
||||
}
|
||||
@@ -154,17 +151,18 @@ function extractObjectFromEvent(
|
||||
): IBoundedElement | null {
|
||||
let object = null;
|
||||
switch (e.type) {
|
||||
case eventUtils.BLOCK_CREATE:
|
||||
case eventUtils.BLOCK_MOVE:
|
||||
case EventType.BLOCK_CREATE:
|
||||
case EventType.BLOCK_MOVE:
|
||||
object = workspace.getBlockById((e as BlockCreate | BlockMove).blockId!);
|
||||
if (object) {
|
||||
object = object.getRootBlock();
|
||||
}
|
||||
break;
|
||||
case eventUtils.COMMENT_CREATE:
|
||||
case eventUtils.COMMENT_MOVE:
|
||||
case EventType.COMMENT_CREATE:
|
||||
case EventType.COMMENT_MOVE:
|
||||
case EventType.COMMENT_RESIZE:
|
||||
object = workspace.getCommentById(
|
||||
(e as CommentCreate | CommentMove).commentId!,
|
||||
(e as CommentCreate | CommentMove | CommentResize).commentId!,
|
||||
) as RenderedWorkspaceComment;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
// Former goog.module ID: Blockly.clipboard
|
||||
|
||||
import type {ICopyData, ICopyable} from './interfaces/i_copyable.js';
|
||||
import {BlockPaster} from './clipboard/block_paster.js';
|
||||
import * as globalRegistry from './registry.js';
|
||||
import {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as registry from './clipboard/registry.js';
|
||||
import type {ICopyData, ICopyable} from './interfaces/i_copyable.js';
|
||||
import * as globalRegistry from './registry.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import {WorkspaceSvg} from './workspace_svg.js';
|
||||
|
||||
/** Metadata about the object that is currently on the clipboard. */
|
||||
let stashedCopyData: ICopyData | null = null;
|
||||
|
||||
@@ -5,15 +5,16 @@
|
||||
*/
|
||||
|
||||
import {BlockSvg} from '../block_svg.js';
|
||||
import * as registry from './registry.js';
|
||||
import * as common from '../common.js';
|
||||
import {config} from '../config.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {ICopyData} from '../interfaces/i_copyable.js';
|
||||
import {IPaster} from '../interfaces/i_paster.js';
|
||||
import {State, append} from '../serialization/blocks.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {config} from '../config.js';
|
||||
import * as common from '../common.js';
|
||||
import * as registry from './registry.js';
|
||||
|
||||
export class BlockPaster implements IPaster<BlockCopyData, BlockSvg> {
|
||||
static TYPE = 'block';
|
||||
@@ -52,7 +53,7 @@ export class BlockPaster implements IPaster<BlockCopyData, BlockSvg> {
|
||||
if (!block) return block;
|
||||
|
||||
if (eventUtils.isEnabled() && !block.isShadow()) {
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(block));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(block));
|
||||
}
|
||||
common.setSelected(block);
|
||||
return block;
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {IPaster} from '../interfaces/i_paster.js';
|
||||
import {RenderedWorkspaceComment} from '../comments/rendered_workspace_comment.js';
|
||||
import * as common from '../common.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {ICopyData} from '../interfaces/i_copyable.js';
|
||||
import {IPaster} from '../interfaces/i_paster.js';
|
||||
import * as commentSerialiation from '../serialization/workspace_comments.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import * as registry from './registry.js';
|
||||
import * as commentSerialiation from '../serialization/workspace_comments.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import * as common from '../common.js';
|
||||
import {RenderedWorkspaceComment} from '../comments/rendered_workspace_comment.js';
|
||||
|
||||
export class WorkspaceCommentPaster
|
||||
implements IPaster<WorkspaceCommentCopyData, RenderedWorkspaceComment>
|
||||
@@ -46,7 +47,7 @@ export class WorkspaceCommentPaster
|
||||
if (!comment) return null;
|
||||
|
||||
if (eventUtils.isEnabled()) {
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_CREATE))(comment));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.COMMENT_CREATE))(comment));
|
||||
}
|
||||
common.setSelected(comment);
|
||||
return comment;
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
*/
|
||||
|
||||
export {CommentView} from './comments/comment_view.js';
|
||||
export {WorkspaceComment} from './comments/workspace_comment.js';
|
||||
export {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js';
|
||||
export {WorkspaceComment} from './comments/workspace_comment.js';
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {IRenderedElement} from '../interfaces/i_rendered_element.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import * as layers from '../layers.js';
|
||||
import * as css from '../css.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import * as browserEvents from '../browser_events.js';
|
||||
import * as css from '../css.js';
|
||||
import {IRenderedElement} from '../interfaces/i_rendered_element.js';
|
||||
import * as layers from '../layers.js';
|
||||
import * as touch from '../touch.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
|
||||
export class CommentView implements IRenderedElement {
|
||||
/** The root group element of the comment view. */
|
||||
@@ -99,9 +99,12 @@ export class CommentView implements IRenderedElement {
|
||||
/** Whether this comment view has been disposed or not. */
|
||||
private disposed = false;
|
||||
|
||||
/** Size of this comment when the resize drag was initiated. */
|
||||
private preResizeSize?: Size;
|
||||
|
||||
constructor(private readonly workspace: WorkspaceSvg) {
|
||||
this.svgRoot = dom.createSvgElement(Svg.G, {
|
||||
'class': 'blocklyComment blocklyEditable',
|
||||
'class': 'blocklyComment blocklyEditable blocklyDraggable',
|
||||
});
|
||||
|
||||
this.highlightRect = this.createHighlightRect(this.svgRoot);
|
||||
@@ -125,7 +128,7 @@ export class CommentView implements IRenderedElement {
|
||||
workspace.getLayerManager()?.append(this, layers.BLOCK);
|
||||
|
||||
// Set size to the default size.
|
||||
this.setSize(this.size);
|
||||
this.setSizeWithoutFiringEvents(this.size);
|
||||
|
||||
// Set default transform (including inverted scale for RTL).
|
||||
this.moveTo(new Coordinate(0, 0));
|
||||
@@ -298,7 +301,7 @@ export class CommentView implements IRenderedElement {
|
||||
* Sets the size of the comment in workspace units, and updates the view
|
||||
* elements to reflect the new size.
|
||||
*/
|
||||
setSize(size: Size) {
|
||||
setSizeWithoutFiringEvents(size: Size) {
|
||||
const topBarSize = this.topBarBackground.getBBox();
|
||||
const deleteSize = this.deleteIcon.getBBox();
|
||||
const foldoutSize = this.foldoutIcon.getBBox();
|
||||
@@ -309,7 +312,6 @@ export class CommentView implements IRenderedElement {
|
||||
size,
|
||||
this.calcMinSize(topBarSize, foldoutSize, deleteSize),
|
||||
);
|
||||
const oldSize = this.size;
|
||||
this.size = size;
|
||||
|
||||
this.svgRoot.setAttribute('height', `${size.height}`);
|
||||
@@ -328,7 +330,15 @@ export class CommentView implements IRenderedElement {
|
||||
resizeSize,
|
||||
);
|
||||
this.updateResizeHandlePosition(size, resizeSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the comment in workspace units, updates the view
|
||||
* elements to reflect the new size, and triggers size change listeners.
|
||||
*/
|
||||
setSize(size: Size) {
|
||||
const oldSize = this.preResizeSize || this.size;
|
||||
this.setSizeWithoutFiringEvents(size);
|
||||
this.onSizeChange(oldSize, this.size);
|
||||
}
|
||||
|
||||
@@ -472,7 +482,7 @@ export class CommentView implements IRenderedElement {
|
||||
|
||||
/**
|
||||
* Triggers listeners when the size of the comment changes, either
|
||||
* progrmatically or manually by the user.
|
||||
* programmatically or manually by the user.
|
||||
*/
|
||||
private onSizeChange(oldSize: Size, newSize: Size) {
|
||||
// Loop through listeners backwards in case they remove themselves.
|
||||
@@ -512,6 +522,8 @@ export class CommentView implements IRenderedElement {
|
||||
return;
|
||||
}
|
||||
|
||||
this.preResizeSize = this.getSize();
|
||||
|
||||
// TODO(#7926): Move this into a utils file.
|
||||
this.workspace.startDrag(
|
||||
e,
|
||||
@@ -550,13 +562,18 @@ export class CommentView implements IRenderedElement {
|
||||
browserEvents.unbind(this.resizePointerMoveListener);
|
||||
this.resizePointerMoveListener = null;
|
||||
}
|
||||
// When ending a resize drag, notify size change listeners to fire an event.
|
||||
this.setSize(this.size);
|
||||
this.preResizeSize = undefined;
|
||||
}
|
||||
|
||||
/** Resizes the comment in response to a drag on the resize handle. */
|
||||
private onResizePointerMove(e: PointerEvent) {
|
||||
// TODO(#7926): Move this into a utils file.
|
||||
const delta = this.workspace.moveDrag(e);
|
||||
this.setSize(new Size(this.workspace.RTL ? -delta.x : delta.x, delta.y));
|
||||
const size = this.workspace.moveDrag(e);
|
||||
this.setSizeWithoutFiringEvents(
|
||||
new Size(this.workspace.RTL ? -size.x : size.x, size.y),
|
||||
);
|
||||
}
|
||||
|
||||
/** Returns true if the comment is currently collapsed. */
|
||||
@@ -573,7 +590,7 @@ export class CommentView implements IRenderedElement {
|
||||
dom.removeClass(this.svgRoot, 'blocklyCollapsed');
|
||||
}
|
||||
// Repositions resize handle and such.
|
||||
this.setSize(this.size);
|
||||
this.setSizeWithoutFiringEvents(this.size);
|
||||
this.onCollapse();
|
||||
}
|
||||
|
||||
@@ -682,7 +699,7 @@ export class CommentView implements IRenderedElement {
|
||||
|
||||
/**
|
||||
* Triggers listeners when the text of the comment changes, either
|
||||
* progrmatically or manually by the user.
|
||||
* programmatically or manually by the user.
|
||||
*/
|
||||
private onTextChange() {
|
||||
const oldText = this.text;
|
||||
@@ -810,7 +827,6 @@ css.register(`
|
||||
}
|
||||
|
||||
.blocklyCommentTopbarBackground {
|
||||
cursor: grab;
|
||||
fill: var(--commentBorderColour);
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
@@ -4,30 +4,31 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {WorkspaceComment} from './workspace_comment.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {CommentView} from './comment_view.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {IBoundedElement} from '../interfaces/i_bounded_element.js';
|
||||
import {IRenderedElement} from '../interfaces/i_rendered_element.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {IDraggable} from '../interfaces/i_draggable.js';
|
||||
import {CommentDragStrategy} from '../dragging/comment_drag_strategy.js';
|
||||
import * as browserEvents from '../browser_events.js';
|
||||
import * as common from '../common.js';
|
||||
import {ISelectable} from '../interfaces/i_selectable.js';
|
||||
import {IDeletable} from '../interfaces/i_deletable.js';
|
||||
import {ICopyable} from '../interfaces/i_copyable.js';
|
||||
import * as commentSerialization from '../serialization/workspace_comments.js';
|
||||
import {
|
||||
WorkspaceCommentPaster,
|
||||
WorkspaceCommentCopyData,
|
||||
WorkspaceCommentPaster,
|
||||
} from '../clipboard/workspace_comment_paster.js';
|
||||
import {IContextMenu} from '../interfaces/i_contextmenu.js';
|
||||
import * as common from '../common.js';
|
||||
import * as contextMenu from '../contextmenu.js';
|
||||
import {ContextMenuRegistry} from '../contextmenu_registry.js';
|
||||
import {CommentDragStrategy} from '../dragging/comment_drag_strategy.js';
|
||||
import {IBoundedElement} from '../interfaces/i_bounded_element.js';
|
||||
import {IContextMenu} from '../interfaces/i_contextmenu.js';
|
||||
import {ICopyable} from '../interfaces/i_copyable.js';
|
||||
import {IDeletable} from '../interfaces/i_deletable.js';
|
||||
import {IDraggable} from '../interfaces/i_draggable.js';
|
||||
import {IRenderedElement} from '../interfaces/i_rendered_element.js';
|
||||
import {ISelectable} from '../interfaces/i_selectable.js';
|
||||
import * as layers from '../layers.js';
|
||||
import * as commentSerialization from '../serialization/workspace_comments.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {CommentView} from './comment_view.js';
|
||||
import {WorkspaceComment} from './workspace_comment.js';
|
||||
|
||||
export class RenderedWorkspaceComment
|
||||
extends WorkspaceComment
|
||||
@@ -57,6 +58,7 @@ export class RenderedWorkspaceComment
|
||||
// Set the size to the default size as defined in the superclass.
|
||||
this.view.setSize(this.getSize());
|
||||
this.view.setEditable(this.isEditable());
|
||||
this.view.getSvgRoot().setAttribute('data-id', this.id);
|
||||
|
||||
this.addModelUpdateBindings();
|
||||
|
||||
@@ -207,6 +209,7 @@ export class RenderedWorkspaceComment
|
||||
const gesture = this.workspace.getGesture(e);
|
||||
if (gesture) {
|
||||
gesture.handleCommentStart(e, this);
|
||||
this.workspace.getLayerManager()?.append(this, layers.BLOCK);
|
||||
common.setSelected(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {Workspace} from '../workspace.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {CommentMove} from '../events/events_comment_move.js';
|
||||
import {CommentResize} from '../events/events_comment_resize.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as idGenerator from '../utils/idgenerator.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {CommentMove} from '../events/events_comment_move.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
|
||||
export class WorkspaceComment {
|
||||
/** The unique identifier for this comment. */
|
||||
@@ -62,13 +64,13 @@ export class WorkspaceComment {
|
||||
|
||||
private fireCreateEvent() {
|
||||
if (eventUtils.isEnabled()) {
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_CREATE))(this));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.COMMENT_CREATE))(this));
|
||||
}
|
||||
}
|
||||
|
||||
private fireDeleteEvent() {
|
||||
if (eventUtils.isEnabled()) {
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_DELETE))(this));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.COMMENT_DELETE))(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +78,7 @@ export class WorkspaceComment {
|
||||
private fireChangeEvent(oldText: string, newText: string) {
|
||||
if (eventUtils.isEnabled()) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.COMMENT_CHANGE))(this, oldText, newText),
|
||||
new (eventUtils.get(EventType.COMMENT_CHANGE))(this, oldText, newText),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -85,7 +87,7 @@ export class WorkspaceComment {
|
||||
private fireCollapseEvent(newCollapsed: boolean) {
|
||||
if (eventUtils.isEnabled()) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.COMMENT_COLLAPSE))(this, newCollapsed),
|
||||
new (eventUtils.get(EventType.COMMENT_COLLAPSE))(this, newCollapsed),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +106,14 @@ export class WorkspaceComment {
|
||||
|
||||
/** Sets the comment's size in workspace units. */
|
||||
setSize(size: Size) {
|
||||
const event = new (eventUtils.get(EventType.COMMENT_RESIZE))(
|
||||
this,
|
||||
) as CommentResize;
|
||||
|
||||
this.size = size;
|
||||
|
||||
event.recordCurrentSizeAsNewSize();
|
||||
eventUtils.fire(event);
|
||||
}
|
||||
|
||||
/** Returns the comment's size in workspace units. */
|
||||
@@ -175,7 +184,11 @@ export class WorkspaceComment {
|
||||
* workspace is read-only.
|
||||
*/
|
||||
isDeletable(): boolean {
|
||||
return this.isOwnDeletable() && !this.workspace.options.readOnly;
|
||||
return (
|
||||
this.isOwnDeletable() &&
|
||||
!this.isDeadOrDying() &&
|
||||
!this.workspace.options.readOnly
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +201,7 @@ export class WorkspaceComment {
|
||||
|
||||
/** Moves the comment to the given location in workspace coordinates. */
|
||||
moveTo(location: Coordinate, reason?: string[] | undefined) {
|
||||
const event = new (eventUtils.get(eventUtils.COMMENT_MOVE))(
|
||||
const event = new (eventUtils.get(EventType.COMMENT_MOVE))(
|
||||
this,
|
||||
) as CommentMove;
|
||||
if (reason) event.setReason(reason);
|
||||
@@ -196,7 +209,7 @@ export class WorkspaceComment {
|
||||
this.location = location;
|
||||
|
||||
event.recordNew();
|
||||
if (eventUtils.isEnabled()) eventUtils.fire(event);
|
||||
eventUtils.fire(event);
|
||||
}
|
||||
|
||||
/** Returns the position of the comment in workspace coordinates. */
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
// Former goog.module ID: Blockly.common
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
import type {Block} from './block.js';
|
||||
import {ISelectable} from './blockly.js';
|
||||
import {BlockDefinition, Blocks} from './blocks.js';
|
||||
import type {Connection} from './connection.js';
|
||||
import {EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import type {Workspace} from './workspace.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
|
||||
/** Database of all workspaces. */
|
||||
const WorkspaceDB_ = Object.create(null);
|
||||
@@ -108,7 +108,7 @@ export function getSelected(): ISelectable | null {
|
||||
export function setSelected(newSelection: ISelectable | null) {
|
||||
if (selected === newSelection) return;
|
||||
|
||||
const event = new (eventUtils.get(eventUtils.SELECTED))(
|
||||
const event = new (eventUtils.get(EventType.SELECTED))(
|
||||
selected?.id ?? null,
|
||||
newSelection?.id ?? null,
|
||||
newSelection?.workspace.id ?? selected?.workspace.id ?? '',
|
||||
|
||||
@@ -224,6 +224,16 @@ export class ComponentManager {
|
||||
}
|
||||
|
||||
export namespace ComponentManager {
|
||||
export enum ComponentWeight {
|
||||
// The toolbox weight is lower (higher precedence) than the flyout, so that
|
||||
// if both are under the pointer, the toolbox takes precedence even though
|
||||
// the flyout's drag target area is large enough to include the toolbox.
|
||||
TOOLBOX_WEIGHT = 0,
|
||||
FLYOUT_WEIGHT = 1,
|
||||
TRASHCAN_WEIGHT = 2,
|
||||
ZOOM_CONTROLS_WEIGHT = 3,
|
||||
}
|
||||
|
||||
/** An object storing component information. */
|
||||
export interface ComponentDatum {
|
||||
component: IComponent;
|
||||
@@ -232,4 +242,6 @@ export namespace ComponentManager {
|
||||
}
|
||||
}
|
||||
|
||||
export type ComponentWeight = ComponentManager.ComponentWeight;
|
||||
export const ComponentWeight = ComponentManager.ComponentWeight;
|
||||
export type ComponentDatum = ComponentManager.ComponentDatum;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
import type {Block} from './block.js';
|
||||
import {ConnectionType} from './connection_type.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 {Input} from './inputs/input.js';
|
||||
import type {IASTNodeLocationWithBlock} from './interfaces/i_ast_node_location_with_block.js';
|
||||
@@ -114,7 +115,7 @@ export class Connection implements IASTNodeLocationWithBlock {
|
||||
// Connect the new connection to the parent.
|
||||
let event;
|
||||
if (eventUtils.isEnabled()) {
|
||||
event = new (eventUtils.get(eventUtils.BLOCK_MOVE))(
|
||||
event = new (eventUtils.get(EventType.BLOCK_MOVE))(
|
||||
childBlock,
|
||||
) as BlockMove;
|
||||
event.setReason(['connect']);
|
||||
@@ -281,7 +282,7 @@ export class Connection implements IASTNodeLocationWithBlock {
|
||||
|
||||
let event;
|
||||
if (eventUtils.isEnabled()) {
|
||||
event = new (eventUtils.get(eventUtils.BLOCK_MOVE))(
|
||||
event = new (eventUtils.get(EventType.BLOCK_MOVE))(
|
||||
childConnection.getSourceBlock(),
|
||||
) as BlockMove;
|
||||
event.setReason(['disconnect']);
|
||||
|
||||
@@ -9,23 +9,24 @@
|
||||
import type {Block} from './block.js';
|
||||
import type {BlockSvg} from './block_svg.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as common from './common.js';
|
||||
import {config} from './config.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import type {
|
||||
ContextMenuOption,
|
||||
LegacyContextMenuOption,
|
||||
} from './contextmenu_registry.js';
|
||||
import {EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import {Menu} from './menu.js';
|
||||
import {MenuItem} from './menuitem.js';
|
||||
import * as aria from './utils/aria.js';
|
||||
import {Rect} from './utils/rect.js';
|
||||
import * as serializationBlocks from './serialization/blocks.js';
|
||||
import * as aria from './utils/aria.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import {Rect} from './utils/rect.js';
|
||||
import * as svgMath from './utils/svg_math.js';
|
||||
import * as WidgetDiv from './widgetdiv.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as Xml from './xml.js';
|
||||
import * as common from './common.js';
|
||||
|
||||
/**
|
||||
* Which block is the context menu attached to?
|
||||
@@ -260,7 +261,7 @@ export function callbackFactory(
|
||||
eventUtils.enable();
|
||||
}
|
||||
if (eventUtils.isEnabled() && !newBlock.isShadow()) {
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(newBlock));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(newBlock));
|
||||
}
|
||||
common.setSelected(newBlock);
|
||||
return newBlock;
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
import type {BlockSvg} from './block_svg.js';
|
||||
import * as clipboard from './clipboard.js';
|
||||
import {RenderedWorkspaceComment} from './comments/rendered_workspace_comment.js';
|
||||
import * as common from './common.js';
|
||||
import {MANUALLY_DISABLED} from './constants.js';
|
||||
import {
|
||||
ContextMenuRegistry,
|
||||
RegistryItem,
|
||||
Scope,
|
||||
} from './contextmenu_registry.js';
|
||||
import {MANUALLY_DISABLED} from './constants.js';
|
||||
import * as dialog from './dialog.js';
|
||||
import * as Events from './events/events.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
@@ -23,7 +24,6 @@ import {Msg} from './msg.js';
|
||||
import {StatementInput} from './renderers/zelos/zelos.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as common from './common.js';
|
||||
|
||||
/**
|
||||
* Option to undo previous action.
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
import {BlockSvg} from './block_svg.js';
|
||||
import {DragTarget} from './drag_target.js';
|
||||
import {isDeletable} from './interfaces/i_deletable.js';
|
||||
import type {IDeleteArea} from './interfaces/i_delete_area.js';
|
||||
import type {IDraggable} from './interfaces/i_draggable.js';
|
||||
import {isDeletable} from './interfaces/i_deletable.js';
|
||||
|
||||
/**
|
||||
* Abstract class for a component that can delete a block or bubble that is
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {Dragger} from './dragging/dragger.js';
|
||||
import {BlockDragStrategy} from './dragging/block_drag_strategy.js';
|
||||
import {BubbleDragStrategy} from './dragging/bubble_drag_strategy.js';
|
||||
import {CommentDragStrategy} from './dragging/comment_drag_strategy.js';
|
||||
import {Dragger} from './dragging/dragger.js';
|
||||
|
||||
export {Dragger, BlockDragStrategy, BubbleDragStrategy, CommentDragStrategy};
|
||||
export {BlockDragStrategy, BubbleDragStrategy, CommentDragStrategy, Dragger};
|
||||
|
||||
@@ -4,24 +4,25 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {IDragStrategy} from '../interfaces/i_draggable.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {BlockSvg} from '../block_svg.js';
|
||||
import {RenderedConnection} from '../rendered_connection.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import * as blockAnimation from '../block_animations.js';
|
||||
import {ConnectionType} from '../connection_type.js';
|
||||
import * as bumpObjects from '../bump_objects.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {IConnectionPreviewer} from '../interfaces/i_connection_previewer.js';
|
||||
import {Connection} from '../connection.js';
|
||||
import type {Block} from '../block.js';
|
||||
import * as blockAnimation from '../block_animations.js';
|
||||
import {BlockSvg} from '../block_svg.js';
|
||||
import * as bumpObjects from '../bump_objects.js';
|
||||
import {config} from '../config.js';
|
||||
import {Connection} from '../connection.js';
|
||||
import {ConnectionType} from '../connection_type.js';
|
||||
import type {BlockMove} from '../events/events_block_move.js';
|
||||
import {finishQueuedRenders} from '../render_management.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {IConnectionPreviewer} from '../interfaces/i_connection_previewer.js';
|
||||
import {IDragStrategy} from '../interfaces/i_draggable.js';
|
||||
import * as layers from '../layers.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {finishQueuedRenders} from '../render_management.js';
|
||||
import {RenderedConnection} from '../rendered_connection.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
|
||||
/** Represents a nearby valid connection. */
|
||||
interface ConnectionCandidate {
|
||||
@@ -61,6 +62,9 @@ export class BlockDragStrategy implements IDragStrategy {
|
||||
*/
|
||||
private dragOffset = new Coordinate(0, 0);
|
||||
|
||||
/** Was there already an event group in progress when the drag started? */
|
||||
private inGroup: boolean = false;
|
||||
|
||||
constructor(private block: BlockSvg) {
|
||||
this.workspace = block.workspace;
|
||||
}
|
||||
@@ -92,7 +96,8 @@ export class BlockDragStrategy implements IDragStrategy {
|
||||
}
|
||||
|
||||
this.dragging = true;
|
||||
if (!eventUtils.getGroup()) {
|
||||
this.inGroup = !!eventUtils.getGroup();
|
||||
if (!this.inGroup) {
|
||||
eventUtils.setGroup(true);
|
||||
}
|
||||
this.fireDragStartEvent();
|
||||
@@ -173,7 +178,7 @@ export class BlockDragStrategy implements IDragStrategy {
|
||||
|
||||
/** Fire a UI event at the start of a block drag. */
|
||||
private fireDragStartEvent() {
|
||||
const event = new (eventUtils.get(eventUtils.BLOCK_DRAG))(
|
||||
const event = new (eventUtils.get(EventType.BLOCK_DRAG))(
|
||||
this.block,
|
||||
true,
|
||||
this.block.getDescendants(false),
|
||||
@@ -183,7 +188,7 @@ export class BlockDragStrategy implements IDragStrategy {
|
||||
|
||||
/** Fire a UI event at the end of a block drag. */
|
||||
private fireDragEndEvent() {
|
||||
const event = new (eventUtils.get(eventUtils.BLOCK_DRAG))(
|
||||
const event = new (eventUtils.get(EventType.BLOCK_DRAG))(
|
||||
this.block,
|
||||
false,
|
||||
this.block.getDescendants(false),
|
||||
@@ -194,7 +199,7 @@ export class BlockDragStrategy implements IDragStrategy {
|
||||
/** Fire a move event at the end of a block drag. */
|
||||
private fireMoveEvent() {
|
||||
if (this.block.isDeadOrDying()) return;
|
||||
const event = new (eventUtils.get(eventUtils.BLOCK_MOVE))(
|
||||
const event = new (eventUtils.get(EventType.BLOCK_MOVE))(
|
||||
this.block,
|
||||
) as BlockMove;
|
||||
event.setReason(['drag']);
|
||||
@@ -389,7 +394,9 @@ export class BlockDragStrategy implements IDragStrategy {
|
||||
this.connectionPreviewer!.dispose();
|
||||
this.workspace.setResizesEnabled(true);
|
||||
|
||||
eventUtils.setGroup(false);
|
||||
if (!this.inGroup) {
|
||||
eventUtils.setGroup(false);
|
||||
}
|
||||
}
|
||||
|
||||
/** Connects the given candidate connections. */
|
||||
|
||||
@@ -4,15 +4,18 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {IDragStrategy} from '../interfaces/i_draggable.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {IBubble, WorkspaceSvg} from '../blockly.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {IDragStrategy} from '../interfaces/i_draggable.js';
|
||||
import * as layers from '../layers.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
|
||||
export class BubbleDragStrategy implements IDragStrategy {
|
||||
private startLoc: Coordinate | null = null;
|
||||
|
||||
/** Was there already an event group in progress when the drag started? */
|
||||
private inGroup: boolean = false;
|
||||
|
||||
constructor(
|
||||
private bubble: IBubble,
|
||||
private workspace: WorkspaceSvg,
|
||||
@@ -23,13 +26,16 @@ export class BubbleDragStrategy implements IDragStrategy {
|
||||
}
|
||||
|
||||
startDrag(): void {
|
||||
if (!eventUtils.getGroup()) {
|
||||
this.inGroup = !!eventUtils.getGroup();
|
||||
if (!this.inGroup) {
|
||||
eventUtils.setGroup(true);
|
||||
}
|
||||
this.startLoc = this.bubble.getRelativeToSurfaceXY();
|
||||
this.workspace.setResizesEnabled(false);
|
||||
this.workspace.getLayerManager()?.moveToDragLayer(this.bubble);
|
||||
this.bubble.setDragging && this.bubble.setDragging(true);
|
||||
if (this.bubble.setDragging) {
|
||||
this.bubble.setDragging(true);
|
||||
}
|
||||
}
|
||||
|
||||
drag(newLoc: Coordinate): void {
|
||||
@@ -38,7 +44,9 @@ export class BubbleDragStrategy implements IDragStrategy {
|
||||
|
||||
endDrag(): void {
|
||||
this.workspace.setResizesEnabled(true);
|
||||
eventUtils.setGroup(false);
|
||||
if (!this.inGroup) {
|
||||
eventUtils.setGroup(false);
|
||||
}
|
||||
|
||||
this.workspace
|
||||
.getLayerManager()
|
||||
|
||||
@@ -4,31 +4,41 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {IDragStrategy} from '../interfaces/i_draggable.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import * as layers from '../layers.js';
|
||||
import {RenderedWorkspaceComment} from '../comments.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {CommentMove} from '../events/events_comment_move.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {IDragStrategy} from '../interfaces/i_draggable.js';
|
||||
import * as layers from '../layers.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
|
||||
export class CommentDragStrategy implements IDragStrategy {
|
||||
private startLoc: Coordinate | null = null;
|
||||
|
||||
private workspace: WorkspaceSvg;
|
||||
|
||||
/** Was there already an event group in progress when the drag started? */
|
||||
private inGroup: boolean = false;
|
||||
|
||||
constructor(private comment: RenderedWorkspaceComment) {
|
||||
this.workspace = comment.workspace;
|
||||
}
|
||||
|
||||
isMovable(): boolean {
|
||||
return this.comment.isOwnMovable() && !this.workspace.options.readOnly;
|
||||
return (
|
||||
this.comment.isOwnMovable() &&
|
||||
!this.comment.isDeadOrDying() &&
|
||||
!this.workspace.options.readOnly
|
||||
);
|
||||
}
|
||||
|
||||
startDrag(): void {
|
||||
if (!eventUtils.getGroup()) {
|
||||
this.inGroup = !!eventUtils.getGroup();
|
||||
if (!this.inGroup) {
|
||||
eventUtils.setGroup(true);
|
||||
}
|
||||
this.fireDragStartEvent();
|
||||
this.startLoc = this.comment.getRelativeToSurfaceXY();
|
||||
this.workspace.setResizesEnabled(false);
|
||||
this.workspace.getLayerManager()?.moveToDragLayer(this.comment);
|
||||
@@ -40,6 +50,7 @@ export class CommentDragStrategy implements IDragStrategy {
|
||||
}
|
||||
|
||||
endDrag(): void {
|
||||
this.fireDragEndEvent();
|
||||
this.fireMoveEvent();
|
||||
|
||||
this.workspace
|
||||
@@ -50,12 +61,33 @@ export class CommentDragStrategy implements IDragStrategy {
|
||||
this.comment.snapToGrid();
|
||||
|
||||
this.workspace.setResizesEnabled(true);
|
||||
eventUtils.setGroup(false);
|
||||
if (!this.inGroup) {
|
||||
eventUtils.setGroup(false);
|
||||
}
|
||||
}
|
||||
|
||||
/** Fire a UI event at the start of a comment drag. */
|
||||
private fireDragStartEvent() {
|
||||
const event = new (eventUtils.get(EventType.COMMENT_DRAG))(
|
||||
this.comment,
|
||||
true,
|
||||
);
|
||||
eventUtils.fire(event);
|
||||
}
|
||||
|
||||
/** Fire a UI event at the end of a comment drag. */
|
||||
private fireDragEndEvent() {
|
||||
const event = new (eventUtils.get(EventType.COMMENT_DRAG))(
|
||||
this.comment,
|
||||
false,
|
||||
);
|
||||
eventUtils.fire(event);
|
||||
}
|
||||
|
||||
/** Fire a move event at the end of a comment drag. */
|
||||
private fireMoveEvent() {
|
||||
if (this.comment.isDeadOrDying()) return;
|
||||
const event = new (eventUtils.get(eventUtils.COMMENT_MOVE))(
|
||||
const event = new (eventUtils.get(EventType.COMMENT_MOVE))(
|
||||
this.comment,
|
||||
) as CommentMove;
|
||||
event.setReason(['drag']);
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {IDragTarget} from '../interfaces/i_drag_target.js';
|
||||
import {IDeletable, isDeletable} from '../interfaces/i_deletable.js';
|
||||
import {IDragger} from '../interfaces/i_dragger.js';
|
||||
import {IDraggable} from '../interfaces/i_draggable.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {ComponentManager} from '../component_manager.js';
|
||||
import {IDeleteArea} from '../interfaces/i_delete_area.js';
|
||||
import * as registry from '../registry.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import * as blockAnimations from '../block_animations.js';
|
||||
import {BlockSvg} from '../block_svg.js';
|
||||
import {ComponentManager} from '../component_manager.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {IDeletable, isDeletable} from '../interfaces/i_deletable.js';
|
||||
import {IDeleteArea} from '../interfaces/i_delete_area.js';
|
||||
import {IDragTarget} from '../interfaces/i_drag_target.js';
|
||||
import {IDraggable} from '../interfaces/i_draggable.js';
|
||||
import {IDragger} from '../interfaces/i_dragger.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import {WorkspaceSvg} from '../workspace_svg.js';
|
||||
|
||||
export class Dragger implements IDragger {
|
||||
protected startLoc: Coordinate;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
import type {BlockSvg} from './block_svg.js';
|
||||
import * as common from './common.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import type {Field} from './field.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import * as math from './utils/math.js';
|
||||
import {Rect} from './utils/rect.js';
|
||||
import type {Size} from './utils/size.js';
|
||||
@@ -53,7 +53,7 @@ export const ANIMATION_TIME = 0.25;
|
||||
let animateOutTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
/** Callback for when the drop-down is hidden. */
|
||||
let onHide: Function | null = null;
|
||||
let onHide: (() => void) | null = null;
|
||||
|
||||
/** A class name representing the current owner's workspace renderer. */
|
||||
let renderedClassName = '';
|
||||
@@ -202,7 +202,7 @@ export function setColour(backgroundColour: string, borderColour: string) {
|
||||
export function showPositionedByBlock<T>(
|
||||
field: Field<T>,
|
||||
block: BlockSvg,
|
||||
opt_onHide?: Function,
|
||||
opt_onHide?: () => void,
|
||||
opt_secondaryYOffset?: number,
|
||||
): boolean {
|
||||
return showPositionedByRect(
|
||||
@@ -226,7 +226,7 @@ export function showPositionedByBlock<T>(
|
||||
*/
|
||||
export function showPositionedByField<T>(
|
||||
field: Field<T>,
|
||||
opt_onHide?: Function,
|
||||
opt_onHide?: () => void,
|
||||
opt_secondaryYOffset?: number,
|
||||
): boolean {
|
||||
positionToField = true;
|
||||
@@ -278,7 +278,7 @@ function getScaledBboxOfField(field: Field): Rect {
|
||||
function showPositionedByRect(
|
||||
bBox: Rect,
|
||||
field: Field,
|
||||
opt_onHide?: Function,
|
||||
opt_onHide?: () => void,
|
||||
opt_secondaryYOffset?: number,
|
||||
): boolean {
|
||||
// If we can fit it, render below the block.
|
||||
@@ -334,7 +334,7 @@ export function show<T>(
|
||||
primaryY: number,
|
||||
secondaryX: number,
|
||||
secondaryY: number,
|
||||
opt_onHide?: Function,
|
||||
opt_onHide?: () => void,
|
||||
): boolean {
|
||||
owner = newOwner as Field;
|
||||
onHide = opt_onHide || null;
|
||||
|
||||
@@ -6,146 +6,103 @@
|
||||
|
||||
// Former goog.module ID: Blockly.Events
|
||||
|
||||
import {Abstract, AbstractEventJson} from './events_abstract.js';
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import {BlockChange, BlockChangeJson} from './events_block_change.js';
|
||||
import {BlockCreate, BlockCreateJson} from './events_block_create.js';
|
||||
import {BlockDelete, BlockDeleteJson} from './events_block_delete.js';
|
||||
import {BlockDrag, BlockDragJson} from './events_block_drag.js';
|
||||
import {
|
||||
import {EventType} from './type.js';
|
||||
|
||||
// Events.
|
||||
export {Abstract, AbstractEventJson} from './events_abstract.js';
|
||||
export {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
export {BlockChange, BlockChangeJson} from './events_block_change.js';
|
||||
export {BlockCreate, BlockCreateJson} from './events_block_create.js';
|
||||
export {BlockDelete, BlockDeleteJson} from './events_block_delete.js';
|
||||
export {BlockDrag, BlockDragJson} from './events_block_drag.js';
|
||||
export {
|
||||
BlockFieldIntermediateChange,
|
||||
BlockFieldIntermediateChangeJson,
|
||||
} from './events_block_field_intermediate_change.js';
|
||||
import {BlockMove, BlockMoveJson} from './events_block_move.js';
|
||||
import {BubbleOpen, BubbleOpenJson, BubbleType} from './events_bubble_open.js';
|
||||
import {Click, ClickJson, ClickTarget} from './events_click.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import {CommentChange, CommentChangeJson} from './events_comment_change.js';
|
||||
import {CommentCreate, CommentCreateJson} from './events_comment_create.js';
|
||||
import {CommentDelete} from './events_comment_delete.js';
|
||||
import {CommentMove, CommentMoveJson} from './events_comment_move.js';
|
||||
import {
|
||||
export {BlockMove, BlockMoveJson} from './events_block_move.js';
|
||||
export {BubbleOpen, BubbleOpenJson, BubbleType} from './events_bubble_open.js';
|
||||
export {Click, ClickJson, ClickTarget} from './events_click.js';
|
||||
export {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
export {CommentChange, CommentChangeJson} from './events_comment_change.js';
|
||||
export {
|
||||
CommentCollapse,
|
||||
CommentCollapseJson,
|
||||
} from './events_comment_collapse.js';
|
||||
import {MarkerMove, MarkerMoveJson} from './events_marker_move.js';
|
||||
import {Selected, SelectedJson} from './events_selected.js';
|
||||
import {ThemeChange, ThemeChangeJson} from './events_theme_change.js';
|
||||
import {
|
||||
export {CommentCreate, CommentCreateJson} from './events_comment_create.js';
|
||||
export {CommentDelete} from './events_comment_delete.js';
|
||||
export {CommentDrag, CommentDragJson} from './events_comment_drag.js';
|
||||
export {CommentMove, CommentMoveJson} from './events_comment_move.js';
|
||||
export {CommentResize, CommentResizeJson} from './events_comment_resize.js';
|
||||
export {MarkerMove, MarkerMoveJson} from './events_marker_move.js';
|
||||
export {Selected, SelectedJson} from './events_selected.js';
|
||||
export {ThemeChange, ThemeChangeJson} from './events_theme_change.js';
|
||||
export {
|
||||
ToolboxItemSelect,
|
||||
ToolboxItemSelectJson,
|
||||
} from './events_toolbox_item_select.js';
|
||||
import {TrashcanOpen, TrashcanOpenJson} from './events_trashcan_open.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
import {VarCreate, VarCreateJson} from './events_var_create.js';
|
||||
import {VarDelete, VarDeleteJson} from './events_var_delete.js';
|
||||
import {VarRename, VarRenameJson} from './events_var_rename.js';
|
||||
import {ViewportChange, ViewportChangeJson} from './events_viewport.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {FinishedLoading} from './workspace_events.js';
|
||||
export {TrashcanOpen, TrashcanOpenJson} from './events_trashcan_open.js';
|
||||
export {UiBase} from './events_ui_base.js';
|
||||
export {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
export {VarCreate, VarCreateJson} from './events_var_create.js';
|
||||
export {VarDelete, VarDeleteJson} from './events_var_delete.js';
|
||||
export {VarRename, VarRenameJson} from './events_var_rename.js';
|
||||
export {ViewportChange, ViewportChangeJson} from './events_viewport.js';
|
||||
export {FinishedLoading} from './workspace_events.js';
|
||||
|
||||
// Events.
|
||||
export {Abstract};
|
||||
export {AbstractEventJson};
|
||||
export {BubbleOpen};
|
||||
export {BubbleOpenJson};
|
||||
export {BubbleType};
|
||||
export {BlockBase};
|
||||
export {BlockBaseJson};
|
||||
export {BlockChange};
|
||||
export {BlockChangeJson};
|
||||
export {BlockCreate};
|
||||
export {BlockCreateJson};
|
||||
export {BlockDelete};
|
||||
export {BlockDeleteJson};
|
||||
export {BlockDrag};
|
||||
export {BlockDragJson};
|
||||
export {BlockFieldIntermediateChange};
|
||||
export {BlockFieldIntermediateChangeJson};
|
||||
export {BlockMove};
|
||||
export {BlockMoveJson};
|
||||
export {Click};
|
||||
export {ClickJson};
|
||||
export {ClickTarget};
|
||||
export {CommentBase};
|
||||
export {CommentBaseJson};
|
||||
export {CommentChange};
|
||||
export {CommentChangeJson};
|
||||
export {CommentCreate};
|
||||
export {CommentCreateJson};
|
||||
export {CommentDelete};
|
||||
export {CommentMove};
|
||||
export {CommentMoveJson};
|
||||
export {CommentCollapse};
|
||||
export {CommentCollapseJson};
|
||||
export {FinishedLoading};
|
||||
export {MarkerMove};
|
||||
export {MarkerMoveJson};
|
||||
export {Selected};
|
||||
export {SelectedJson};
|
||||
export {ThemeChange};
|
||||
export {ThemeChangeJson};
|
||||
export {ToolboxItemSelect};
|
||||
export {ToolboxItemSelectJson};
|
||||
export {TrashcanOpen};
|
||||
export {TrashcanOpenJson};
|
||||
export {UiBase};
|
||||
export {VarBase};
|
||||
export {VarBaseJson};
|
||||
export {VarCreate};
|
||||
export {VarCreateJson};
|
||||
export {VarDelete};
|
||||
export {VarDeleteJson};
|
||||
export {VarRename};
|
||||
export {VarRenameJson};
|
||||
export {ViewportChange};
|
||||
export {ViewportChangeJson};
|
||||
export type {BumpEvent} from './utils.js';
|
||||
|
||||
// Event types.
|
||||
export const BLOCK_CHANGE = eventUtils.BLOCK_CHANGE;
|
||||
export const BLOCK_CREATE = eventUtils.BLOCK_CREATE;
|
||||
export const BLOCK_DELETE = eventUtils.BLOCK_DELETE;
|
||||
export const BLOCK_DRAG = eventUtils.BLOCK_DRAG;
|
||||
export const BLOCK_MOVE = eventUtils.BLOCK_MOVE;
|
||||
export const BLOCK_CHANGE = EventType.BLOCK_CHANGE;
|
||||
export const BLOCK_CREATE = EventType.BLOCK_CREATE;
|
||||
export const BLOCK_DELETE = EventType.BLOCK_DELETE;
|
||||
export const BLOCK_DRAG = EventType.BLOCK_DRAG;
|
||||
export const BLOCK_MOVE = EventType.BLOCK_MOVE;
|
||||
export const BLOCK_FIELD_INTERMEDIATE_CHANGE =
|
||||
eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE;
|
||||
export const BUBBLE_OPEN = eventUtils.BUBBLE_OPEN;
|
||||
export type BumpEvent = eventUtils.BumpEvent;
|
||||
export const BUMP_EVENTS = eventUtils.BUMP_EVENTS;
|
||||
export const CHANGE = eventUtils.CHANGE;
|
||||
export const CLICK = eventUtils.CLICK;
|
||||
export const COMMENT_CHANGE = eventUtils.COMMENT_CHANGE;
|
||||
export const COMMENT_CREATE = eventUtils.COMMENT_CREATE;
|
||||
export const COMMENT_DELETE = eventUtils.COMMENT_DELETE;
|
||||
export const COMMENT_MOVE = eventUtils.COMMENT_MOVE;
|
||||
export const CREATE = eventUtils.CREATE;
|
||||
export const DELETE = eventUtils.DELETE;
|
||||
export const FINISHED_LOADING = eventUtils.FINISHED_LOADING;
|
||||
export const MARKER_MOVE = eventUtils.MARKER_MOVE;
|
||||
export const MOVE = eventUtils.MOVE;
|
||||
export const SELECTED = eventUtils.SELECTED;
|
||||
export const THEME_CHANGE = eventUtils.THEME_CHANGE;
|
||||
export const TOOLBOX_ITEM_SELECT = eventUtils.TOOLBOX_ITEM_SELECT;
|
||||
export const TRASHCAN_OPEN = eventUtils.TRASHCAN_OPEN;
|
||||
export const UI = eventUtils.UI;
|
||||
export const VAR_CREATE = eventUtils.VAR_CREATE;
|
||||
export const VAR_DELETE = eventUtils.VAR_DELETE;
|
||||
export const VAR_RENAME = eventUtils.VAR_RENAME;
|
||||
export const VIEWPORT_CHANGE = eventUtils.VIEWPORT_CHANGE;
|
||||
EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE;
|
||||
export const BUBBLE_OPEN = EventType.BUBBLE_OPEN;
|
||||
/** @deprecated Use BLOCK_CHANGE instead */
|
||||
export const CHANGE = EventType.BLOCK_CHANGE;
|
||||
export const CLICK = EventType.CLICK;
|
||||
export const COMMENT_CHANGE = EventType.COMMENT_CHANGE;
|
||||
export const COMMENT_CREATE = EventType.COMMENT_CREATE;
|
||||
export const COMMENT_DELETE = EventType.COMMENT_DELETE;
|
||||
export const COMMENT_MOVE = EventType.COMMENT_MOVE;
|
||||
export const COMMENT_RESIZE = EventType.COMMENT_RESIZE;
|
||||
export const COMMENT_DRAG = EventType.COMMENT_DRAG;
|
||||
/** @deprecated Use BLOCK_CREATE instead */
|
||||
export const CREATE = EventType.BLOCK_CREATE;
|
||||
/** @deprecated Use BLOCK_DELETE instead */
|
||||
export const DELETE = EventType.BLOCK_DELETE;
|
||||
export const FINISHED_LOADING = EventType.FINISHED_LOADING;
|
||||
export const MARKER_MOVE = EventType.MARKER_MOVE;
|
||||
/** @deprecated Use BLOCK_MOVE instead */
|
||||
export const MOVE = EventType.BLOCK_MOVE;
|
||||
export const SELECTED = EventType.SELECTED;
|
||||
export const THEME_CHANGE = EventType.THEME_CHANGE;
|
||||
export const TOOLBOX_ITEM_SELECT = EventType.TOOLBOX_ITEM_SELECT;
|
||||
export const TRASHCAN_OPEN = EventType.TRASHCAN_OPEN;
|
||||
export const UI = EventType.UI;
|
||||
export const VAR_CREATE = EventType.VAR_CREATE;
|
||||
export const VAR_DELETE = EventType.VAR_DELETE;
|
||||
export const VAR_RENAME = EventType.VAR_RENAME;
|
||||
export const VIEWPORT_CHANGE = EventType.VIEWPORT_CHANGE;
|
||||
|
||||
export {BUMP_EVENTS} from './type.js';
|
||||
|
||||
// Event utils.
|
||||
export const clearPendingUndo = eventUtils.clearPendingUndo;
|
||||
export const disable = eventUtils.disable;
|
||||
export const enable = eventUtils.enable;
|
||||
export const filter = eventUtils.filter;
|
||||
export const fire = eventUtils.fire;
|
||||
export const fromJson = eventUtils.fromJson;
|
||||
export const getDescendantIds = eventUtils.getDescendantIds;
|
||||
export const get = eventUtils.get;
|
||||
export const getGroup = eventUtils.getGroup;
|
||||
export const getRecordUndo = eventUtils.getRecordUndo;
|
||||
export const isEnabled = eventUtils.isEnabled;
|
||||
export const setGroup = eventUtils.setGroup;
|
||||
export const setRecordUndo = eventUtils.setRecordUndo;
|
||||
export const disableOrphans = eventUtils.disableOrphans;
|
||||
export {
|
||||
clearPendingUndo,
|
||||
disable,
|
||||
disableOrphans,
|
||||
enable,
|
||||
filter,
|
||||
fire,
|
||||
fromJson,
|
||||
get,
|
||||
getDescendantIds,
|
||||
getGroup,
|
||||
getRecordUndo,
|
||||
isEnabled,
|
||||
setGroup,
|
||||
setRecordUndo,
|
||||
} from './utils.js';
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
|
||||
import * as common from '../common.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
|
||||
import * as eventUtils from './utils.js';
|
||||
import {getGroup, getRecordUndo} from './utils.js';
|
||||
|
||||
/**
|
||||
* Abstract class for an event.
|
||||
@@ -48,8 +47,8 @@ export abstract class Abstract {
|
||||
type = '';
|
||||
|
||||
constructor() {
|
||||
this.group = eventUtils.getGroup();
|
||||
this.recordUndo = eventUtils.getRecordUndo();
|
||||
this.group = getGroup();
|
||||
this.recordUndo = getRecordUndo();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +107,6 @@ export abstract class Abstract {
|
||||
*
|
||||
* @returns The workspace the event belongs to.
|
||||
* @throws {Error} if workspace is null.
|
||||
* @internal
|
||||
*/
|
||||
getEventWorkspace_(): Workspace {
|
||||
let workspace;
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
import type {Block} from '../block.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
|
||||
import {
|
||||
Abstract as AbstractEvent,
|
||||
AbstractEventJson,
|
||||
|
||||
@@ -13,15 +13,15 @@
|
||||
|
||||
import type {Block} from '../block.js';
|
||||
import type {BlockSvg} from '../block_svg.js';
|
||||
import {MANUALLY_DISABLED} from '../constants.js';
|
||||
import {IconType} from '../icons/icon_types.js';
|
||||
import {hasBubble} from '../interfaces/i_has_bubble.js';
|
||||
import {MANUALLY_DISABLED} from '../constants.js';
|
||||
import * as registry from '../registry.js';
|
||||
import * as utilsXml from '../utils/xml.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
import * as Xml from '../xml.js';
|
||||
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import {EventType} from './type.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
|
||||
/**
|
||||
@@ -29,7 +29,7 @@ import * as eventUtils from './utils.js';
|
||||
* field values, comments, etc).
|
||||
*/
|
||||
export class BlockChange extends BlockBase {
|
||||
override type = eventUtils.BLOCK_CHANGE;
|
||||
override type = EventType.BLOCK_CHANGE;
|
||||
/**
|
||||
* The element that changed; one of 'field', 'comment', 'collapsed',
|
||||
* 'disabled', 'inline', or 'mutation'
|
||||
@@ -256,4 +256,4 @@ export interface BlockChangeJson extends BlockBaseJson {
|
||||
disabledReason?: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.CHANGE, BlockChange);
|
||||
registry.register(registry.Type.EVENT, EventType.BLOCK_CHANGE, BlockChange);
|
||||
|
||||
@@ -15,18 +15,18 @@ import type {Block} from '../block.js';
|
||||
import * as registry from '../registry.js';
|
||||
import * as blocks from '../serialization/blocks.js';
|
||||
import * as utilsXml from '../utils/xml.js';
|
||||
import * as Xml from '../xml.js';
|
||||
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
import * as Xml from '../xml.js';
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import {EventType} from './type.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners when a block (or connected stack of blocks) is
|
||||
* created.
|
||||
*/
|
||||
export class BlockCreate extends BlockBase {
|
||||
override type = eventUtils.BLOCK_CREATE;
|
||||
override type = EventType.BLOCK_CREATE;
|
||||
|
||||
/** The XML representation of the created block(s). */
|
||||
xml?: Element | DocumentFragment;
|
||||
@@ -182,4 +182,4 @@ export interface BlockCreateJson extends BlockBaseJson {
|
||||
recordUndo?: boolean;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.CREATE, BlockCreate);
|
||||
registry.register(registry.Type.EVENT, EventType.BLOCK_CREATE, BlockCreate);
|
||||
|
||||
@@ -15,11 +15,11 @@ import type {Block} from '../block.js';
|
||||
import * as registry from '../registry.js';
|
||||
import * as blocks from '../serialization/blocks.js';
|
||||
import * as utilsXml from '../utils/xml.js';
|
||||
import * as Xml from '../xml.js';
|
||||
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
import * as Xml from '../xml.js';
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import {EventType} from './type.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners when a block (or connected stack of blocks) is
|
||||
@@ -38,7 +38,7 @@ export class BlockDelete extends BlockBase {
|
||||
/** True if the deleted block was a shadow block, false otherwise. */
|
||||
wasShadow?: boolean;
|
||||
|
||||
override type = eventUtils.BLOCK_DELETE;
|
||||
override type = EventType.BLOCK_DELETE;
|
||||
|
||||
/** @param opt_block The deleted block. Undefined for a blank event. */
|
||||
constructor(opt_block?: Block) {
|
||||
@@ -179,4 +179,4 @@ export interface BlockDeleteJson extends BlockBaseJson {
|
||||
recordUndo?: boolean;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.DELETE, BlockDelete);
|
||||
registry.register(registry.Type.EVENT, EventType.BLOCK_DELETE, BlockDelete);
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
|
||||
import type {Block} from '../block.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners when a block is being manually dragged/dropped.
|
||||
@@ -34,7 +34,7 @@ export class BlockDrag extends UiBase {
|
||||
*/
|
||||
blocks?: Block[];
|
||||
|
||||
override type = eventUtils.BLOCK_DRAG;
|
||||
override type = EventType.BLOCK_DRAG;
|
||||
|
||||
/**
|
||||
* @param opt_block The top block in the stack that is being dragged.
|
||||
@@ -113,4 +113,4 @@ export interface BlockDragJson extends AbstractEventJson {
|
||||
blocks?: Block[];
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.BLOCK_DRAG, BlockDrag);
|
||||
registry.register(registry.Type.EVENT, EventType.BLOCK_DRAG, BlockDrag);
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
import type {Block} from '../block.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners when the value of a block's field has changed but the
|
||||
@@ -25,7 +24,7 @@ import * as eventUtils from './utils.js';
|
||||
* event.
|
||||
*/
|
||||
export class BlockFieldIntermediateChange extends BlockBase {
|
||||
override type = eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE;
|
||||
override type = EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE;
|
||||
|
||||
// Intermediate events do not undo or redo. They may be fired frequently while
|
||||
// the field editor widget is open. A separate BLOCK_CHANGE event is fired
|
||||
@@ -162,6 +161,6 @@ export interface BlockFieldIntermediateChangeJson extends BlockBaseJson {
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE,
|
||||
EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE,
|
||||
BlockFieldIntermediateChange,
|
||||
);
|
||||
|
||||
@@ -15,10 +15,9 @@ import type {Block} from '../block.js';
|
||||
import {ConnectionType} from '../connection_type.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {BlockBase, BlockBaseJson} from './events_block_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
interface BlockLocation {
|
||||
parentId?: string;
|
||||
@@ -31,7 +30,7 @@ interface BlockLocation {
|
||||
* connection to another, or from one location on the workspace to another.
|
||||
*/
|
||||
export class BlockMove extends BlockBase {
|
||||
override type = eventUtils.BLOCK_MOVE;
|
||||
override type = EventType.BLOCK_MOVE;
|
||||
|
||||
/** The ID of the old parent block. Undefined if it was a top-level block. */
|
||||
oldParentId?: string;
|
||||
@@ -304,4 +303,4 @@ export interface BlockMoveJson extends BlockBaseJson {
|
||||
recordUndo?: boolean;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.MOVE, BlockMove);
|
||||
registry.register(registry.Type.EVENT, EventType.BLOCK_MOVE, BlockMove);
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
|
||||
// Former goog.module ID: Blockly.Events.BubbleOpen
|
||||
|
||||
import type {AbstractEventJson} from './events_abstract.js';
|
||||
import type {BlockSvg} from '../block_svg.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import type {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Class for a bubble open event.
|
||||
@@ -31,7 +32,7 @@ export class BubbleOpen extends UiBase {
|
||||
/** The type of bubble; one of 'mutator', 'comment', or 'warning'. */
|
||||
bubbleType?: BubbleType;
|
||||
|
||||
override type = eventUtils.BUBBLE_OPEN;
|
||||
override type = EventType.BUBBLE_OPEN;
|
||||
|
||||
/**
|
||||
* @param opt_block The associated block. Undefined for a blank event.
|
||||
@@ -117,4 +118,4 @@ export interface BubbleOpenJson extends AbstractEventJson {
|
||||
blockId: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.BUBBLE_OPEN, BubbleOpen);
|
||||
registry.register(registry.Type.EVENT, EventType.BUBBLE_OPEN, BubbleOpen);
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
|
||||
// Former goog.module ID: Blockly.Events.Click
|
||||
|
||||
import type {Block} from '../block.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that some blockly element was clicked.
|
||||
@@ -31,7 +31,7 @@ export class Click extends UiBase {
|
||||
* or 'zoom_controls'.
|
||||
*/
|
||||
targetType?: ClickTarget;
|
||||
override type = eventUtils.CLICK;
|
||||
override type = EventType.CLICK;
|
||||
|
||||
/**
|
||||
* @param opt_block The affected block. Null for click events that do not have
|
||||
@@ -107,4 +107,4 @@ export interface ClickJson extends AbstractEventJson {
|
||||
blockId?: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.CLICK, Click);
|
||||
registry.register(registry.Type.EVENT, EventType.CLICK, Click);
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
import * as comments from '../serialization/workspace_comments.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {
|
||||
Abstract as AbstractEvent,
|
||||
AbstractEventJson,
|
||||
} from './events_abstract.js';
|
||||
import type {CommentCreate} from './events_comment_create.js';
|
||||
import type {CommentDelete} from './events_comment_delete.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {getGroup, getRecordUndo} from './utils.js';
|
||||
|
||||
/**
|
||||
* Abstract class for a comment event.
|
||||
@@ -44,8 +44,8 @@ export class CommentBase extends AbstractEvent {
|
||||
|
||||
this.commentId = opt_comment.id;
|
||||
this.workspaceId = opt_comment.workspace.id;
|
||||
this.group = eventUtils.getGroup();
|
||||
this.recordUndo = eventUtils.getRecordUndo();
|
||||
this.group = getGroup();
|
||||
this.recordUndo = getRecordUndo();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,18 +11,17 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.Events.CommentChange
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import * as registry from '../registry.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that the contents of a workspace comment has changed.
|
||||
*/
|
||||
export class CommentChange extends CommentBase {
|
||||
override type = eventUtils.COMMENT_CHANGE;
|
||||
override type = EventType.COMMENT_CHANGE;
|
||||
|
||||
// TODO(#6774): We should remove underscores.
|
||||
/** The previous contents of the comment. */
|
||||
@@ -154,8 +153,4 @@ export interface CommentChangeJson extends CommentBaseJson {
|
||||
newContents: string;
|
||||
}
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.COMMENT_CHANGE,
|
||||
CommentChange,
|
||||
);
|
||||
registry.register(registry.Type.EVENT, EventType.COMMENT_CHANGE, CommentChange);
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import * as registry from '../registry.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
export class CommentCollapse extends CommentBase {
|
||||
override type = eventUtils.COMMENT_COLLAPSE;
|
||||
override type = EventType.COMMENT_COLLAPSE;
|
||||
|
||||
constructor(
|
||||
comment?: WorkspaceComment,
|
||||
@@ -98,6 +98,6 @@ export interface CommentCollapseJson extends CommentBaseJson {
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.COMMENT_COLLAPSE,
|
||||
EventType.COMMENT_COLLAPSE,
|
||||
CommentCollapse,
|
||||
);
|
||||
|
||||
@@ -11,20 +11,20 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.Events.CommentCreate
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
import * as registry from '../registry.js';
|
||||
import * as comments from '../serialization/workspace_comments.js';
|
||||
import * as utilsXml from '../utils/xml.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import * as Xml from '../xml.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a workspace comment was created.
|
||||
*/
|
||||
export class CommentCreate extends CommentBase {
|
||||
override type = eventUtils.COMMENT_CREATE;
|
||||
override type = EventType.COMMENT_CREATE;
|
||||
|
||||
/** The XML representation of the created workspace comment. */
|
||||
xml?: Element | DocumentFragment;
|
||||
@@ -111,8 +111,4 @@ export interface CommentCreateJson extends CommentBaseJson {
|
||||
json: object;
|
||||
}
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.COMMENT_CREATE,
|
||||
CommentCreate,
|
||||
);
|
||||
registry.register(registry.Type.EVENT, EventType.COMMENT_CREATE, CommentCreate);
|
||||
|
||||
@@ -11,20 +11,20 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.Events.CommentDelete
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
import * as registry from '../registry.js';
|
||||
import * as comments from '../serialization/workspace_comments.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import * as utilsXml from '../utils/xml.js';
|
||||
import * as Xml from '../xml.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import * as Xml from '../xml.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a workspace comment has been deleted.
|
||||
*/
|
||||
export class CommentDelete extends CommentBase {
|
||||
override type = eventUtils.COMMENT_DELETE;
|
||||
override type = EventType.COMMENT_DELETE;
|
||||
|
||||
/** The XML representation of the deleted workspace comment. */
|
||||
xml?: Element;
|
||||
@@ -110,8 +110,4 @@ export interface CommentDeleteJson extends CommentBaseJson {
|
||||
json: object;
|
||||
}
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.COMMENT_DELETE,
|
||||
CommentDelete,
|
||||
);
|
||||
registry.register(registry.Type.EVENT, EventType.COMMENT_DELETE, CommentDelete);
|
||||
|
||||
99
core/events/events_comment_drag.ts
Normal file
99
core/events/events_comment_drag.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Events fired when a workspace comment is dragged.
|
||||
*/
|
||||
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners when a comment is being manually dragged/dropped.
|
||||
*/
|
||||
export class CommentDrag extends UiBase {
|
||||
/** The ID of the top-level comment being dragged. */
|
||||
commentId?: string;
|
||||
|
||||
/** True if this is the start of a drag, false if this is the end of one. */
|
||||
isStart?: boolean;
|
||||
|
||||
override type = EventType.COMMENT_DRAG;
|
||||
|
||||
/**
|
||||
* @param opt_comment The comment that is being dragged.
|
||||
* Undefined for a blank event.
|
||||
* @param opt_isStart Whether this is the start of a comment drag.
|
||||
* Undefined for a blank event.
|
||||
*/
|
||||
constructor(opt_comment?: WorkspaceComment, opt_isStart?: boolean) {
|
||||
const workspaceId = opt_comment ? opt_comment.workspace.id : undefined;
|
||||
super(workspaceId);
|
||||
if (!opt_comment) return;
|
||||
|
||||
this.commentId = opt_comment.id;
|
||||
this.isStart = opt_isStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the event as JSON.
|
||||
*
|
||||
* @returns JSON representation.
|
||||
*/
|
||||
override toJson(): CommentDragJson {
|
||||
const json = super.toJson() as CommentDragJson;
|
||||
if (this.isStart === undefined) {
|
||||
throw new Error(
|
||||
'Whether this event is the start of a drag is undefined. ' +
|
||||
'Either pass the value to the constructor, or call fromJson',
|
||||
);
|
||||
}
|
||||
if (this.commentId === undefined) {
|
||||
throw new Error(
|
||||
'The comment ID is undefined. Either pass a comment to ' +
|
||||
'the constructor, or call fromJson',
|
||||
);
|
||||
}
|
||||
json['isStart'] = this.isStart;
|
||||
json['commentId'] = this.commentId;
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the JSON event.
|
||||
*
|
||||
* @param event The event to append new properties to. Should be a subclass
|
||||
* of CommentDrag, but we can't specify that due to the fact that parameters
|
||||
* to static methods in subclasses must be supertypes of parameters to
|
||||
* static methods in superclasses.
|
||||
* @internal
|
||||
*/
|
||||
static fromJson(
|
||||
json: CommentDragJson,
|
||||
workspace: Workspace,
|
||||
event?: any,
|
||||
): CommentDrag {
|
||||
const newEvent = super.fromJson(
|
||||
json,
|
||||
workspace,
|
||||
event ?? new CommentDrag(),
|
||||
) as CommentDrag;
|
||||
newEvent.isStart = json['isStart'];
|
||||
newEvent.commentId = json['commentId'];
|
||||
return newEvent;
|
||||
}
|
||||
}
|
||||
|
||||
export interface CommentDragJson extends AbstractEventJson {
|
||||
isStart: boolean;
|
||||
commentId: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, EventType.COMMENT_DRAG, CommentDrag);
|
||||
@@ -11,19 +11,18 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.Events.CommentMove
|
||||
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a workspace comment has moved.
|
||||
*/
|
||||
export class CommentMove extends CommentBase {
|
||||
override type = eventUtils.COMMENT_MOVE;
|
||||
override type = EventType.COMMENT_MOVE;
|
||||
|
||||
/** The comment that is being moved. */
|
||||
comment_?: WorkspaceComment;
|
||||
@@ -204,4 +203,4 @@ export interface CommentMoveJson extends CommentBaseJson {
|
||||
newCoordinate: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.COMMENT_MOVE, CommentMove);
|
||||
registry.register(registry.Type.EVENT, EventType.COMMENT_MOVE, CommentMove);
|
||||
|
||||
169
core/events/events_comment_resize.ts
Normal file
169
core/events/events_comment_resize.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class for comment resize event.
|
||||
*/
|
||||
|
||||
import type {WorkspaceComment} from '../comments/workspace_comment.js';
|
||||
import * as registry from '../registry.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {CommentBase, CommentBaseJson} from './events_comment_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a workspace comment has resized.
|
||||
*/
|
||||
export class CommentResize extends CommentBase {
|
||||
override type = EventType.COMMENT_RESIZE;
|
||||
|
||||
/** The size of the comment before the resize. */
|
||||
oldSize?: Size;
|
||||
|
||||
/** The size of the comment after the resize. */
|
||||
newSize?: Size;
|
||||
|
||||
/**
|
||||
* @param opt_comment The comment that is being resized. Undefined for a blank
|
||||
* event.
|
||||
*/
|
||||
constructor(opt_comment?: WorkspaceComment) {
|
||||
super(opt_comment);
|
||||
|
||||
if (!opt_comment) {
|
||||
return; // Blank event to be populated by fromJson.
|
||||
}
|
||||
|
||||
this.oldSize = opt_comment.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the comment's new size. Called after the resize. Can only be
|
||||
* called once.
|
||||
*/
|
||||
recordCurrentSizeAsNewSize() {
|
||||
if (this.newSize) {
|
||||
throw Error(
|
||||
'Tried to record the new size of a comment on the ' +
|
||||
'same event twice.',
|
||||
);
|
||||
}
|
||||
const workspace = this.getEventWorkspace_();
|
||||
if (!this.commentId) {
|
||||
throw new Error(
|
||||
'The comment ID is undefined. Either pass a comment to ' +
|
||||
'the constructor, or call fromJson',
|
||||
);
|
||||
}
|
||||
const comment = workspace.getCommentById(this.commentId);
|
||||
if (!comment) {
|
||||
throw new Error(
|
||||
'The comment associated with the comment resize event ' +
|
||||
'could not be found',
|
||||
);
|
||||
}
|
||||
this.newSize = comment.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the event as JSON.
|
||||
*
|
||||
* @returns JSON representation.
|
||||
*/
|
||||
override toJson(): CommentResizeJson {
|
||||
const json = super.toJson() as CommentResizeJson;
|
||||
if (!this.oldSize) {
|
||||
throw new Error(
|
||||
'The old comment size is undefined. Either pass a comment to ' +
|
||||
'the constructor, or call fromJson',
|
||||
);
|
||||
}
|
||||
if (!this.newSize) {
|
||||
throw new Error(
|
||||
'The new comment size is undefined. Either call ' +
|
||||
'recordCurrentSizeAsNewSize, or call fromJson',
|
||||
);
|
||||
}
|
||||
json['oldWidth'] = Math.round(this.oldSize.width);
|
||||
json['oldHeight'] = Math.round(this.oldSize.height);
|
||||
json['newWidth'] = Math.round(this.newSize.width);
|
||||
json['newHeight'] = Math.round(this.newSize.height);
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the JSON event.
|
||||
*
|
||||
* @param event The event to append new properties to. Should be a subclass
|
||||
* of CommentResize, but we can't specify that due to the fact that
|
||||
* parameters to static methods in subclasses must be supertypes of
|
||||
* parameters to static methods in superclasses.
|
||||
* @internal
|
||||
*/
|
||||
static fromJson(
|
||||
json: CommentResizeJson,
|
||||
workspace: Workspace,
|
||||
event?: any,
|
||||
): CommentResize {
|
||||
const newEvent = super.fromJson(
|
||||
json,
|
||||
workspace,
|
||||
event ?? new CommentResize(),
|
||||
) as CommentResize;
|
||||
newEvent.oldSize = new Size(json['oldWidth'], json['oldHeight']);
|
||||
newEvent.newSize = new Size(json['newWidth'], json['newHeight']);
|
||||
return newEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this event record any change of state?
|
||||
*
|
||||
* @returns False if something changed.
|
||||
*/
|
||||
override isNull(): boolean {
|
||||
return Size.equals(this.oldSize, this.newSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a resize event.
|
||||
*
|
||||
* @param forward True if run forward, false if run backward (undo).
|
||||
*/
|
||||
override run(forward: boolean) {
|
||||
const workspace = this.getEventWorkspace_();
|
||||
if (!this.commentId) {
|
||||
throw new Error(
|
||||
'The comment ID is undefined. Either pass a comment to ' +
|
||||
'the constructor, or call fromJson',
|
||||
);
|
||||
}
|
||||
const comment = workspace.getCommentById(this.commentId);
|
||||
if (!comment) {
|
||||
console.warn("Can't resize non-existent comment: " + this.commentId);
|
||||
return;
|
||||
}
|
||||
|
||||
const size = forward ? this.newSize : this.oldSize;
|
||||
if (!size) {
|
||||
throw new Error(
|
||||
'Either oldSize or newSize is undefined. ' +
|
||||
'Either pass a comment to the constructor and call ' +
|
||||
'recordCurrentSizeAsNewSize, or call fromJson',
|
||||
);
|
||||
}
|
||||
comment.setSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
export interface CommentResizeJson extends CommentBaseJson {
|
||||
oldWidth: number;
|
||||
oldHeight: number;
|
||||
newWidth: number;
|
||||
newHeight: number;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, EventType.COMMENT_RESIZE, CommentResize);
|
||||
@@ -16,9 +16,8 @@ import {ASTNode} from '../keyboard_nav/ast_node.js';
|
||||
import * as registry from '../registry.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a marker (used for keyboard navigation) has
|
||||
@@ -41,7 +40,7 @@ export class MarkerMove extends UiBase {
|
||||
*/
|
||||
isCursor?: boolean;
|
||||
|
||||
override type = eventUtils.MARKER_MOVE;
|
||||
override type = EventType.MARKER_MOVE;
|
||||
|
||||
/**
|
||||
* @param opt_block The affected block. Null if current node is of type
|
||||
@@ -131,4 +130,4 @@ export interface MarkerMoveJson extends AbstractEventJson {
|
||||
newNode: ASTNode;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.MARKER_MOVE, MarkerMove);
|
||||
registry.register(registry.Type.EVENT, EventType.MARKER_MOVE, MarkerMove);
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
// Former goog.module ID: Blockly.Events.Selected
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Class for a selected event.
|
||||
@@ -32,7 +31,7 @@ export class Selected extends UiBase {
|
||||
*/
|
||||
newElementId?: string;
|
||||
|
||||
override type = eventUtils.SELECTED;
|
||||
override type = EventType.SELECTED;
|
||||
|
||||
/**
|
||||
* @param opt_oldElementId The ID of the previously selected element. Null if
|
||||
@@ -95,4 +94,4 @@ export interface SelectedJson extends AbstractEventJson {
|
||||
newElementId?: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.SELECTED, Selected);
|
||||
registry.register(registry.Type.EVENT, EventType.SELECTED, Selected);
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
// Former goog.module ID: Blockly.Events.ThemeChange
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that the workspace theme has changed.
|
||||
@@ -24,7 +24,7 @@ export class ThemeChange extends UiBase {
|
||||
/** The name of the new theme that has been set. */
|
||||
themeName?: string;
|
||||
|
||||
override type = eventUtils.THEME_CHANGE;
|
||||
override type = EventType.THEME_CHANGE;
|
||||
|
||||
/**
|
||||
* @param opt_themeName The theme name. Undefined for a blank event.
|
||||
@@ -81,4 +81,4 @@ export interface ThemeChangeJson extends AbstractEventJson {
|
||||
themeName: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.THEME_CHANGE, ThemeChange);
|
||||
registry.register(registry.Type.EVENT, EventType.THEME_CHANGE, ThemeChange);
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
// Former goog.module ID: Blockly.Events.ToolboxItemSelect
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a toolbox item has been selected.
|
||||
@@ -27,7 +27,7 @@ export class ToolboxItemSelect extends UiBase {
|
||||
/** The newly selected toolbox item. */
|
||||
newItem?: string;
|
||||
|
||||
override type = eventUtils.TOOLBOX_ITEM_SELECT;
|
||||
override type = EventType.TOOLBOX_ITEM_SELECT;
|
||||
|
||||
/**
|
||||
* @param opt_oldItem The previously selected toolbox item.
|
||||
@@ -91,6 +91,6 @@ export interface ToolboxItemSelectJson extends AbstractEventJson {
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.TOOLBOX_ITEM_SELECT,
|
||||
EventType.TOOLBOX_ITEM_SELECT,
|
||||
ToolboxItemSelect,
|
||||
);
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
// Former goog.module ID: Blockly.Events.TrashcanOpen
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners when the trashcan is opening or closing.
|
||||
@@ -27,7 +26,7 @@ export class TrashcanOpen extends UiBase {
|
||||
* False if it is currently closing (previously open).
|
||||
*/
|
||||
isOpen?: boolean;
|
||||
override type = eventUtils.TRASHCAN_OPEN;
|
||||
override type = EventType.TRASHCAN_OPEN;
|
||||
|
||||
/**
|
||||
* @param opt_isOpen Whether the trashcan flyout is opening (false if
|
||||
@@ -85,4 +84,4 @@ export interface TrashcanOpenJson extends AbstractEventJson {
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.TRASHCAN_OPEN, TrashcanOpen);
|
||||
registry.register(registry.Type.EVENT, EventType.TRASHCAN_OPEN, TrashcanOpen);
|
||||
|
||||
@@ -12,12 +12,11 @@
|
||||
// Former goog.module ID: Blockly.Events.VarBase
|
||||
|
||||
import type {VariableModel} from '../variable_model.js';
|
||||
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {
|
||||
Abstract as AbstractEvent,
|
||||
AbstractEventJson,
|
||||
} from './events_abstract.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
|
||||
/**
|
||||
* Abstract class for a variable event.
|
||||
|
||||
@@ -13,16 +13,15 @@
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {VariableModel} from '../variable_model.js';
|
||||
|
||||
import {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a variable model has been created.
|
||||
*/
|
||||
export class VarCreate extends VarBase {
|
||||
override type = eventUtils.VAR_CREATE;
|
||||
override type = EventType.VAR_CREATE;
|
||||
|
||||
/** The type of the variable that was created. */
|
||||
varType?: string;
|
||||
@@ -123,4 +122,4 @@ export interface VarCreateJson extends VarBaseJson {
|
||||
varName: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.VAR_CREATE, VarCreate);
|
||||
registry.register(registry.Type.EVENT, EventType.VAR_CREATE, VarCreate);
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {VariableModel} from '../variable_model.js';
|
||||
|
||||
import {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a variable model has been deleted.
|
||||
@@ -19,7 +18,7 @@ import type {Workspace} from '../workspace.js';
|
||||
* @class
|
||||
*/
|
||||
export class VarDelete extends VarBase {
|
||||
override type = eventUtils.VAR_DELETE;
|
||||
override type = EventType.VAR_DELETE;
|
||||
/** The type of the variable that was deleted. */
|
||||
varType?: string;
|
||||
/** The name of the variable that was deleted. */
|
||||
@@ -118,4 +117,4 @@ export interface VarDeleteJson extends VarBaseJson {
|
||||
varName: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.VAR_DELETE, VarDelete);
|
||||
registry.register(registry.Type.EVENT, EventType.VAR_DELETE, VarDelete);
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {VariableModel} from '../variable_model.js';
|
||||
|
||||
import {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {VarBase, VarBaseJson} from './events_var_base.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that a variable model was renamed.
|
||||
@@ -19,7 +18,7 @@ import type {Workspace} from '../workspace.js';
|
||||
* @class
|
||||
*/
|
||||
export class VarRename extends VarBase {
|
||||
override type = eventUtils.VAR_RENAME;
|
||||
override type = EventType.VAR_RENAME;
|
||||
|
||||
/** The previous name of the variable. */
|
||||
oldName?: string;
|
||||
@@ -127,4 +126,4 @@ export interface VarRenameJson extends VarBaseJson {
|
||||
newName: string;
|
||||
}
|
||||
|
||||
registry.register(registry.Type.EVENT, eventUtils.VAR_RENAME, VarRename);
|
||||
registry.register(registry.Type.EVENT, EventType.VAR_RENAME, VarRename);
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
// Former goog.module ID: Blockly.Events.ViewportChange
|
||||
|
||||
import * as registry from '../registry.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {AbstractEventJson} from './events_abstract.js';
|
||||
import {UiBase} from './events_ui_base.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners that the workspace surface's position or scale has
|
||||
@@ -42,7 +42,7 @@ export class ViewportChange extends UiBase {
|
||||
/** The previous scale of the workspace. */
|
||||
oldScale?: number;
|
||||
|
||||
override type = eventUtils.VIEWPORT_CHANGE;
|
||||
override type = EventType.VIEWPORT_CHANGE;
|
||||
|
||||
/**
|
||||
* @param opt_top Top-edge of the visible portion of the workspace, relative
|
||||
@@ -144,6 +144,6 @@ export interface ViewportChangeJson extends AbstractEventJson {
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.VIEWPORT_CHANGE,
|
||||
EventType.VIEWPORT_CHANGE,
|
||||
ViewportChange,
|
||||
);
|
||||
|
||||
172
core/events/predicates.ts
Normal file
172
core/events/predicates.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Predicates for testing Abstract event subclasses based on
|
||||
* their .type properties. These are useful because there are places
|
||||
* where it is not possible to use instanceof <ClassConstructor> tests
|
||||
* for type narrowing due to load ordering issues that would be caused
|
||||
* by the need to import (rather than just import type) the class
|
||||
* constructors in question.
|
||||
*/
|
||||
|
||||
import type {Abstract} from './events_abstract.js';
|
||||
import type {BlockChange} from './events_block_change.js';
|
||||
import type {BlockCreate} from './events_block_create.js';
|
||||
import type {BlockDelete} from './events_block_delete.js';
|
||||
import type {BlockDrag} from './events_block_drag.js';
|
||||
import type {BlockFieldIntermediateChange} from './events_block_field_intermediate_change.js';
|
||||
import type {BlockMove} from './events_block_move.js';
|
||||
import type {BubbleOpen} from './events_bubble_open.js';
|
||||
import type {Click} from './events_click.js';
|
||||
import type {CommentChange} from './events_comment_change.js';
|
||||
import type {CommentCollapse} from './events_comment_collapse.js';
|
||||
import type {CommentCreate} from './events_comment_create.js';
|
||||
import type {CommentDelete} from './events_comment_delete.js';
|
||||
import type {CommentDrag} from './events_comment_drag.js';
|
||||
import type {CommentMove} from './events_comment_move.js';
|
||||
import type {CommentResize} from './events_comment_resize.js';
|
||||
import type {MarkerMove} from './events_marker_move.js';
|
||||
import type {Selected} from './events_selected.js';
|
||||
import type {ThemeChange} from './events_theme_change.js';
|
||||
import type {ToolboxItemSelect} from './events_toolbox_item_select.js';
|
||||
import type {TrashcanOpen} from './events_trashcan_open.js';
|
||||
import type {VarCreate} from './events_var_create.js';
|
||||
import type {VarDelete} from './events_var_delete.js';
|
||||
import type {VarRename} from './events_var_rename.js';
|
||||
import type {ViewportChange} from './events_viewport.js';
|
||||
import type {FinishedLoading} from './workspace_events.js';
|
||||
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/** @returns true iff event.type is EventType.BLOCK_CREATE */
|
||||
export function isBlockCreate(event: Abstract): event is BlockCreate {
|
||||
return event.type === EventType.BLOCK_CREATE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.BLOCK_DELETE */
|
||||
export function isBlockDelete(event: Abstract): event is BlockDelete {
|
||||
return event.type === EventType.BLOCK_DELETE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.BLOCK_CHANGE */
|
||||
export function isBlockChange(event: Abstract): event is BlockChange {
|
||||
return event.type === EventType.BLOCK_CHANGE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE */
|
||||
export function isBlockFieldIntermediateChange(
|
||||
event: Abstract,
|
||||
): event is BlockFieldIntermediateChange {
|
||||
return event.type === EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.BLOCK_MOVE */
|
||||
export function isBlockMove(event: Abstract): event is BlockMove {
|
||||
return event.type === EventType.BLOCK_MOVE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.VAR_CREATE */
|
||||
export function isVarCreate(event: Abstract): event is VarCreate {
|
||||
return event.type === EventType.VAR_CREATE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.VAR_DELETE */
|
||||
export function isVarDelete(event: Abstract): event is VarDelete {
|
||||
return event.type === EventType.VAR_DELETE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.VAR_RENAME */
|
||||
export function isVarRename(event: Abstract): event is VarRename {
|
||||
return event.type === EventType.VAR_RENAME;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.BLOCK_DRAG */
|
||||
export function isBlockDrag(event: Abstract): event is BlockDrag {
|
||||
return event.type === EventType.BLOCK_DRAG;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.SELECTED */
|
||||
export function isSelected(event: Abstract): event is Selected {
|
||||
return event.type === EventType.SELECTED;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.CLICK */
|
||||
export function isClick(event: Abstract): event is Click {
|
||||
return event.type === EventType.CLICK;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.MARKER_MOVE */
|
||||
export function isMarkerMove(event: Abstract): event is MarkerMove {
|
||||
return event.type === EventType.MARKER_MOVE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.BUBBLE_OPEN */
|
||||
export function isBubbleOpen(event: Abstract): event is BubbleOpen {
|
||||
return event.type === EventType.BUBBLE_OPEN;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.TRASHCAN_OPEN */
|
||||
export function isTrashcanOpen(event: Abstract): event is TrashcanOpen {
|
||||
return event.type === EventType.TRASHCAN_OPEN;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.TOOLBOX_ITEM_SELECT */
|
||||
export function isToolboxItemSelect(
|
||||
event: Abstract,
|
||||
): event is ToolboxItemSelect {
|
||||
return event.type === EventType.TOOLBOX_ITEM_SELECT;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.THEME_CHANGE */
|
||||
export function isThemeChange(event: Abstract): event is ThemeChange {
|
||||
return event.type === EventType.THEME_CHANGE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.VIEWPORT_CHANGE */
|
||||
export function isViewportChange(event: Abstract): event is ViewportChange {
|
||||
return event.type === EventType.VIEWPORT_CHANGE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.COMMENT_CREATE */
|
||||
export function isCommentCreate(event: Abstract): event is CommentCreate {
|
||||
return event.type === EventType.COMMENT_CREATE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.COMMENT_DELETE */
|
||||
export function isCommentDelete(event: Abstract): event is CommentDelete {
|
||||
return event.type === EventType.COMMENT_DELETE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.COMMENT_CHANGE */
|
||||
export function isCommentChange(event: Abstract): event is CommentChange {
|
||||
return event.type === EventType.COMMENT_CHANGE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.COMMENT_MOVE */
|
||||
export function isCommentMove(event: Abstract): event is CommentMove {
|
||||
return event.type === EventType.COMMENT_MOVE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.COMMENT_RESIZE */
|
||||
export function isCommentResize(event: Abstract): event is CommentResize {
|
||||
return event.type === EventType.COMMENT_RESIZE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.COMMENT_DRAG */
|
||||
export function isCommentDrag(event: Abstract): event is CommentDrag {
|
||||
return event.type === EventType.COMMENT_DRAG;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.COMMENT_COLLAPSE */
|
||||
export function isCommentCollapse(event: Abstract): event is CommentCollapse {
|
||||
return event.type === EventType.COMMENT_COLLAPSE;
|
||||
}
|
||||
|
||||
/** @returns true iff event.type is EventType.FINISHED_LOADING */
|
||||
export function isFinishedLoading(event: Abstract): event is FinishedLoading {
|
||||
return event.type === EventType.FINISHED_LOADING;
|
||||
}
|
||||
85
core/events/type.ts
Normal file
85
core/events/type.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enum of values for the .type property for event classes (concrete subclasses
|
||||
* of Abstract).
|
||||
*/
|
||||
export enum EventType {
|
||||
/** Type of event that creates a block. */
|
||||
BLOCK_CREATE = 'create',
|
||||
/** Type of event that deletes a block. */
|
||||
BLOCK_DELETE = 'delete',
|
||||
/** Type of event that changes a block. */
|
||||
BLOCK_CHANGE = 'change',
|
||||
/**
|
||||
* Type of event representing an in-progress change to a field of a
|
||||
* block, which is expected to be followed by a block change event.
|
||||
*/
|
||||
BLOCK_FIELD_INTERMEDIATE_CHANGE = 'block_field_intermediate_change',
|
||||
/** Type of event that moves a block. */
|
||||
BLOCK_MOVE = 'move',
|
||||
/** Type of event that creates a variable. */
|
||||
VAR_CREATE = 'var_create',
|
||||
/** Type of event that deletes a variable. */
|
||||
VAR_DELETE = 'var_delete',
|
||||
/** Type of event that renames a variable. */
|
||||
VAR_RENAME = 'var_rename',
|
||||
/**
|
||||
* Type of generic event that records a UI change.
|
||||
*
|
||||
* @deprecated Was only ever intended for internal use.
|
||||
*/
|
||||
UI = 'ui',
|
||||
/** Type of event that drags a block. */
|
||||
BLOCK_DRAG = 'drag',
|
||||
/** Type of event that records a change in selected element. */
|
||||
SELECTED = 'selected',
|
||||
/** Type of event that records a click. */
|
||||
CLICK = 'click',
|
||||
/** Type of event that records a marker move. */
|
||||
MARKER_MOVE = 'marker_move',
|
||||
/** Type of event that records a bubble open. */
|
||||
BUBBLE_OPEN = 'bubble_open',
|
||||
/** Type of event that records a trashcan open. */
|
||||
TRASHCAN_OPEN = 'trashcan_open',
|
||||
/** Type of event that records a toolbox item select. */
|
||||
TOOLBOX_ITEM_SELECT = 'toolbox_item_select',
|
||||
/** Type of event that records a theme change. */
|
||||
THEME_CHANGE = 'theme_change',
|
||||
/** Type of event that records a viewport change. */
|
||||
VIEWPORT_CHANGE = 'viewport_change',
|
||||
/** Type of event that creates a comment. */
|
||||
COMMENT_CREATE = 'comment_create',
|
||||
/** Type of event that deletes a comment. */
|
||||
COMMENT_DELETE = 'comment_delete',
|
||||
/** Type of event that changes a comment. */
|
||||
COMMENT_CHANGE = 'comment_change',
|
||||
/** Type of event that moves a comment. */
|
||||
COMMENT_MOVE = 'comment_move',
|
||||
/** Type of event that resizes a comment. */
|
||||
COMMENT_RESIZE = 'comment_resize',
|
||||
/** Type of event that drags a comment. */
|
||||
COMMENT_DRAG = 'comment_drag',
|
||||
/** Type of event that collapses a comment. */
|
||||
COMMENT_COLLAPSE = 'comment_collapse',
|
||||
/** Type of event that records a workspace load. */
|
||||
FINISHED_LOADING = 'finished_loading',
|
||||
}
|
||||
|
||||
/**
|
||||
* List of events that cause objects to be bumped back into the visible
|
||||
* portion of the workspace.
|
||||
*
|
||||
* Not to be confused with bumping so that disconnected connections do not
|
||||
* appear connected.
|
||||
*/
|
||||
export const BUMP_EVENTS: string[] = [
|
||||
EventType.BLOCK_CREATE,
|
||||
EventType.BLOCK_MOVE,
|
||||
EventType.COMMENT_CREATE,
|
||||
EventType.COMMENT_MOVE,
|
||||
];
|
||||
@@ -9,17 +9,24 @@
|
||||
import type {Block} from '../block.js';
|
||||
import * as common from '../common.js';
|
||||
import * as registry from '../registry.js';
|
||||
import * as deprecation from '../utils/deprecation.js';
|
||||
import * as idGenerator from '../utils/idgenerator.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import type {WorkspaceSvg} from '../workspace_svg.js';
|
||||
|
||||
import type {Abstract} from './events_abstract.js';
|
||||
import type {BlockChange} from './events_block_change.js';
|
||||
import type {BlockCreate} from './events_block_create.js';
|
||||
import type {BlockMove} from './events_block_move.js';
|
||||
import type {CommentCreate} from './events_comment_create.js';
|
||||
import type {CommentMove} from './events_comment_move.js';
|
||||
import type {ViewportChange} from './events_viewport.js';
|
||||
import type {CommentResize} from './events_comment_resize.js';
|
||||
import {
|
||||
isBlockChange,
|
||||
isBlockCreate,
|
||||
isBlockMove,
|
||||
isBubbleOpen,
|
||||
isClick,
|
||||
isViewportChange,
|
||||
} from './predicates.js';
|
||||
|
||||
/** Group ID for new events. Grouped events are indivisible. */
|
||||
let group = '';
|
||||
@@ -48,146 +55,6 @@ export function getRecordUndo(): boolean {
|
||||
/** Allow change events to be created and fired. */
|
||||
let disabled = 0;
|
||||
|
||||
/**
|
||||
* Name of event that creates a block. Will be deprecated for BLOCK_CREATE.
|
||||
*/
|
||||
export const CREATE = 'create';
|
||||
|
||||
/**
|
||||
* Name of event that creates a block.
|
||||
*/
|
||||
export const BLOCK_CREATE = CREATE;
|
||||
|
||||
/**
|
||||
* Name of event that deletes a block. Will be deprecated for BLOCK_DELETE.
|
||||
*/
|
||||
export const DELETE = 'delete';
|
||||
|
||||
/**
|
||||
* Name of event that deletes a block.
|
||||
*/
|
||||
export const BLOCK_DELETE = DELETE;
|
||||
|
||||
/**
|
||||
* Name of event that changes a block. Will be deprecated for BLOCK_CHANGE.
|
||||
*/
|
||||
export const CHANGE = 'change';
|
||||
|
||||
/**
|
||||
* Name of event that changes a block.
|
||||
*/
|
||||
export const BLOCK_CHANGE = CHANGE;
|
||||
|
||||
/**
|
||||
* Name of event representing an in-progress change to a field of a block, which
|
||||
* is expected to be followed by a block change event.
|
||||
*/
|
||||
export const BLOCK_FIELD_INTERMEDIATE_CHANGE =
|
||||
'block_field_intermediate_change';
|
||||
|
||||
/**
|
||||
* Name of event that moves a block. Will be deprecated for BLOCK_MOVE.
|
||||
*/
|
||||
export const MOVE = 'move';
|
||||
|
||||
/**
|
||||
* Name of event that moves a block.
|
||||
*/
|
||||
export const BLOCK_MOVE = MOVE;
|
||||
|
||||
/**
|
||||
* Name of event that creates a variable.
|
||||
*/
|
||||
export const VAR_CREATE = 'var_create';
|
||||
|
||||
/**
|
||||
* Name of event that deletes a variable.
|
||||
*/
|
||||
export const VAR_DELETE = 'var_delete';
|
||||
|
||||
/**
|
||||
* Name of event that renames a variable.
|
||||
*/
|
||||
export const VAR_RENAME = 'var_rename';
|
||||
|
||||
/**
|
||||
* Name of generic event that records a UI change.
|
||||
*/
|
||||
export const UI = 'ui';
|
||||
|
||||
/**
|
||||
* Name of event that record a block drags a block.
|
||||
*/
|
||||
export const BLOCK_DRAG = 'drag';
|
||||
|
||||
/**
|
||||
* Name of event that records a change in selected element.
|
||||
*/
|
||||
export const SELECTED = 'selected';
|
||||
|
||||
/**
|
||||
* Name of event that records a click.
|
||||
*/
|
||||
export const CLICK = 'click';
|
||||
|
||||
/**
|
||||
* Name of event that records a marker move.
|
||||
*/
|
||||
export const MARKER_MOVE = 'marker_move';
|
||||
|
||||
/**
|
||||
* Name of event that records a bubble open.
|
||||
*/
|
||||
export const BUBBLE_OPEN = 'bubble_open';
|
||||
|
||||
/**
|
||||
* Name of event that records a trashcan open.
|
||||
*/
|
||||
export const TRASHCAN_OPEN = 'trashcan_open';
|
||||
|
||||
/**
|
||||
* Name of event that records a toolbox item select.
|
||||
*/
|
||||
export const TOOLBOX_ITEM_SELECT = 'toolbox_item_select';
|
||||
|
||||
/**
|
||||
* Name of event that records a theme change.
|
||||
*/
|
||||
export const THEME_CHANGE = 'theme_change';
|
||||
|
||||
/**
|
||||
* Name of event that records a viewport change.
|
||||
*/
|
||||
export const VIEWPORT_CHANGE = 'viewport_change';
|
||||
|
||||
/**
|
||||
* Name of event that creates a comment.
|
||||
*/
|
||||
export const COMMENT_CREATE = 'comment_create';
|
||||
|
||||
/**
|
||||
* Name of event that deletes a comment.
|
||||
*/
|
||||
export const COMMENT_DELETE = 'comment_delete';
|
||||
|
||||
/**
|
||||
* Name of event that changes a comment.
|
||||
*/
|
||||
export const COMMENT_CHANGE = 'comment_change';
|
||||
|
||||
/**
|
||||
* Name of event that moves a comment.
|
||||
*/
|
||||
export const COMMENT_MOVE = 'comment_move';
|
||||
|
||||
/** Type of event that moves a comment. */
|
||||
export const COMMENT_COLLAPSE = 'comment_collapse';
|
||||
|
||||
/**
|
||||
* Name of event that records a workspace load.
|
||||
*/
|
||||
export const FINISHED_LOADING = 'finished_loading';
|
||||
|
||||
/**
|
||||
* The language-neutral ID for when the reason why a block is disabled is
|
||||
* because the block is not descended from a root block.
|
||||
@@ -201,29 +68,31 @@ const ORPHANED_BLOCK_DISABLED_REASON = 'ORPHANED_BLOCK';
|
||||
* Not to be confused with bumping so that disconnected connections do not
|
||||
* appear connected.
|
||||
*/
|
||||
export type BumpEvent = BlockCreate | BlockMove | CommentCreate | CommentMove;
|
||||
|
||||
/**
|
||||
* List of events that cause objects to be bumped back into the visible
|
||||
* portion of the workspace.
|
||||
*
|
||||
* Not to be confused with bumping so that disconnected connections do not
|
||||
* appear connected.
|
||||
*/
|
||||
export const BUMP_EVENTS: string[] = [
|
||||
BLOCK_CREATE,
|
||||
BLOCK_MOVE,
|
||||
COMMENT_CREATE,
|
||||
COMMENT_MOVE,
|
||||
];
|
||||
export type BumpEvent =
|
||||
| BlockCreate
|
||||
| BlockMove
|
||||
| CommentCreate
|
||||
| CommentMove
|
||||
| CommentResize;
|
||||
|
||||
/** List of events queued for firing. */
|
||||
const FIRE_QUEUE: Abstract[] = [];
|
||||
|
||||
/**
|
||||
* Create a custom event and fire it.
|
||||
* Enqueue an event to be dispatched to change listeners.
|
||||
*
|
||||
* @param event Custom data for event.
|
||||
* Notes:
|
||||
*
|
||||
* - Events are enqueued until a timeout, generally after rendering is
|
||||
* complete or at the end of the current microtask, if not running
|
||||
* in a browser.
|
||||
* - Queued events are subject to destructive modification by being
|
||||
* combined with later-enqueued events, but only until they are
|
||||
* fired.
|
||||
* - Events are dispatched via the fireChangeListener method on the
|
||||
* affected workspace.
|
||||
*
|
||||
* @param event Any Blockly event.
|
||||
*/
|
||||
export function fire(event: Abstract) {
|
||||
TEST_ONLY.fireInternal(event);
|
||||
@@ -244,166 +113,187 @@ function fireInternal(event: Abstract) {
|
||||
requestAnimationFrame(() => {
|
||||
setTimeout(fireNow, 0);
|
||||
});
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// Otherwise we just want to delay so events can be coallesced.
|
||||
// requestAnimationFrame will error triggering this.
|
||||
setTimeout(fireNow, 0);
|
||||
}
|
||||
}
|
||||
FIRE_QUEUE.push(event);
|
||||
enqueueEvent(event);
|
||||
}
|
||||
|
||||
/** Fire all queued events. */
|
||||
/** Dispatch all queued events. */
|
||||
function fireNow() {
|
||||
const queue = filter(FIRE_QUEUE, true);
|
||||
FIRE_QUEUE.length = 0;
|
||||
for (let i = 0, event; (event = queue[i]); i++) {
|
||||
if (!event.workspaceId) {
|
||||
continue;
|
||||
}
|
||||
const eventWorkspace = common.getWorkspaceById(event.workspaceId);
|
||||
if (eventWorkspace) {
|
||||
eventWorkspace.fireChangeListener(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Post-filter the undo stack to squash and remove any events that result in
|
||||
// a null event
|
||||
|
||||
// 1. Determine which workspaces will need to have their undo stacks validated
|
||||
const workspaceIds = new Set(queue.map((e) => e.workspaceId));
|
||||
for (const workspaceId of workspaceIds) {
|
||||
// Only process valid workspaces
|
||||
if (!workspaceId) {
|
||||
continue;
|
||||
}
|
||||
const eventWorkspace = common.getWorkspaceById(workspaceId);
|
||||
if (!eventWorkspace) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the last contiguous group of events on the stack
|
||||
const undoStack = eventWorkspace.getUndoStack();
|
||||
let i;
|
||||
let group: string | undefined = undefined;
|
||||
for (i = undoStack.length; i > 0; i--) {
|
||||
const event = undoStack[i - 1];
|
||||
if (event.group === '') {
|
||||
break;
|
||||
} else if (group === undefined) {
|
||||
group = event.group;
|
||||
} else if (event.group !== group) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!group || i == undoStack.length - 1) {
|
||||
// Need a group of two or more events on the stack. Nothing to do here.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract the event group, filter, and add back to the undo stack
|
||||
let events = undoStack.splice(i, undoStack.length - i);
|
||||
events = filter(events, true);
|
||||
undoStack.push(...events);
|
||||
for (const event of queue) {
|
||||
if (!event.workspaceId) continue;
|
||||
common.getWorkspaceById(event.workspaceId)?.fireChangeListener(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the queued events and merge duplicates.
|
||||
* Enqueue an event on FIRE_QUEUE.
|
||||
*
|
||||
* @param queueIn Array of events.
|
||||
* Normally this is equivalent to FIRE_QUEUE.push(event), but if the
|
||||
* enqueued event is a BlockChange event and the most recent event(s)
|
||||
* on the queue are BlockMove events that (re)connect other blocks to
|
||||
* the changed block (and belong to the same event group) then the
|
||||
* enqueued event will be enqueued before those events rather than
|
||||
* after.
|
||||
*
|
||||
* This is a workaround for a problem caused by the fact that
|
||||
* MutatorIcon.prototype.recomposeSourceBlock can only fire a
|
||||
* BlockChange event after the mutating block's compose method
|
||||
* returns, meaning that if the compose method reconnects child blocks
|
||||
* the corresponding BlockMove events are emitted _before_ the
|
||||
* BlockChange event, causing issues with undo, mirroring, etc.; see
|
||||
* https://github.com/google/blockly/issues/8225#issuecomment-2195751783
|
||||
* (and following) for details.
|
||||
*/
|
||||
function enqueueEvent(event: Abstract) {
|
||||
if (isBlockChange(event) && event.element === 'mutation') {
|
||||
let i;
|
||||
for (i = FIRE_QUEUE.length; i > 0; i--) {
|
||||
const otherEvent = FIRE_QUEUE[i - 1];
|
||||
if (
|
||||
otherEvent.group !== event.group ||
|
||||
otherEvent.workspaceId !== event.workspaceId ||
|
||||
!isBlockMove(otherEvent) ||
|
||||
otherEvent.newParentId !== event.blockId
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
FIRE_QUEUE.splice(i, 0, event);
|
||||
return;
|
||||
}
|
||||
|
||||
FIRE_QUEUE.push(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the queued events by merging duplicates, removing null
|
||||
* events and reording BlockChange events.
|
||||
*
|
||||
* History of this function:
|
||||
*
|
||||
* This function was originally added in commit cf257ea5 with the
|
||||
* intention of dramatically reduing the total number of dispatched
|
||||
* events. Initialy it affected only BlockMove events but others were
|
||||
* added over time.
|
||||
*
|
||||
* Code was added to reorder BlockChange events added in commit
|
||||
* 5578458, for uncertain reasons but most probably as part of an
|
||||
* only-partially-successful attemp to fix problems with event
|
||||
* ordering during block mutations. This code should probably have
|
||||
* been added to the top of the function, before merging and
|
||||
* null-removal, but was added at the bottom for now-forgotten
|
||||
* reasons. See these bug investigations for a fuller discussion of
|
||||
* the underlying issue and some of the failures that arose because of
|
||||
* this incomplete/incorrect fix:
|
||||
*
|
||||
* https://github.com/google/blockly/issues/8225#issuecomment-2195751783
|
||||
* https://github.com/google/blockly/issues/2037#issuecomment-2209696351
|
||||
*
|
||||
* Later, in PR #1205 the original O(n^2) implementation was replaced
|
||||
* by a linear-time implementation, though additonal fixes were made
|
||||
* subsequently.
|
||||
*
|
||||
* In August 2024 a number of significant simplifications were made:
|
||||
*
|
||||
* This function was previously called from Workspace.prototype.undo,
|
||||
* but the mutation of events by this function was the cause of issue
|
||||
* #7026 (note that events would combine differently in reverse order
|
||||
* vs. forward order). The originally-chosen fix for this was the
|
||||
* addition (in PR #7069) of code to fireNow to post-filter the
|
||||
* .undoStack_ and .redoStack_ of any workspace that had just been
|
||||
* involved in dispatching events; this apparently resolved the issue
|
||||
* but added considerable additional complexity and made it difficult
|
||||
* to reason about how events are processed for undo/redo, so both the
|
||||
* call from undo and the post-processing code was removed, and
|
||||
* forward=true was made the default while calling the function with
|
||||
* forward=false was deprecated.
|
||||
*
|
||||
* At the same time, the buggy code to reorder BlockChange events was
|
||||
* replaced by a less-buggy version of the same functionality in a new
|
||||
* function, enqueueEvent, called from fireInternal, thus assuring
|
||||
* that events will be in the correct order at the time filter is
|
||||
* called.
|
||||
*
|
||||
* Additionally, the event merging code was modified so that only
|
||||
* immediately adjacent events would be merged. This simplified the
|
||||
* implementation while ensuring that the merging of events cannot
|
||||
* cause them to be reordered.
|
||||
*
|
||||
* @param queue Array of events.
|
||||
* @param forward True if forward (redo), false if backward (undo).
|
||||
* This parameter is deprecated: true is now the default and
|
||||
* calling filter with it set to false will in future not be
|
||||
* supported.
|
||||
* @returns Array of filtered events.
|
||||
*/
|
||||
export function filter(queueIn: Abstract[], forward: boolean): Abstract[] {
|
||||
let queue = queueIn.slice();
|
||||
// Shallow copy of queue.
|
||||
export function filter(queue: Abstract[], forward = true): Abstract[] {
|
||||
if (!forward) {
|
||||
// Undo is merged in reverse order.
|
||||
queue.reverse();
|
||||
deprecation.warn('filter(queue, /*forward=*/false)', 'v11.2', 'v12');
|
||||
// Undo was merged in reverse order.
|
||||
queue = queue.slice().reverse(); // Copy before reversing in place.
|
||||
}
|
||||
const mergedQueue = [];
|
||||
const hash = Object.create(null);
|
||||
const mergedQueue: Abstract[] = [];
|
||||
// Merge duplicates.
|
||||
for (let i = 0, event; (event = queue[i]); i++) {
|
||||
if (!event.isNull()) {
|
||||
// Treat all UI events as the same type in hash table.
|
||||
const eventType = event.isUiEvent ? UI : event.type;
|
||||
// TODO(#5927): Check whether `blockId` exists before accessing it.
|
||||
const blockId = (event as AnyDuringMigration).blockId;
|
||||
const key = [eventType, blockId, event.workspaceId].join(' ');
|
||||
|
||||
const lastEntry = hash[key];
|
||||
const lastEvent = lastEntry ? lastEntry.event : null;
|
||||
if (!lastEntry) {
|
||||
// Each item in the hash table has the event and the index of that event
|
||||
// in the input array. This lets us make sure we only merge adjacent
|
||||
// move events.
|
||||
hash[key] = {event, index: i};
|
||||
mergedQueue.push(event);
|
||||
} else if (event.type === MOVE && lastEntry.index === i - 1) {
|
||||
const moveEvent = event as BlockMove;
|
||||
// Merge move events.
|
||||
lastEvent.newParentId = moveEvent.newParentId;
|
||||
lastEvent.newInputName = moveEvent.newInputName;
|
||||
lastEvent.newCoordinate = moveEvent.newCoordinate;
|
||||
if (moveEvent.reason) {
|
||||
if (lastEvent.reason) {
|
||||
// Concatenate reasons without duplicates.
|
||||
const reasonSet = new Set(
|
||||
moveEvent.reason.concat(lastEvent.reason),
|
||||
);
|
||||
lastEvent.reason = Array.from(reasonSet);
|
||||
} else {
|
||||
lastEvent.reason = moveEvent.reason;
|
||||
}
|
||||
}
|
||||
lastEntry.index = i;
|
||||
} else if (
|
||||
event.type === CHANGE &&
|
||||
(event as BlockChange).element === lastEvent.element &&
|
||||
(event as BlockChange).name === lastEvent.name
|
||||
) {
|
||||
const changeEvent = event as BlockChange;
|
||||
// Merge change events.
|
||||
lastEvent.newValue = changeEvent.newValue;
|
||||
} else if (event.type === VIEWPORT_CHANGE) {
|
||||
const viewportEvent = event as ViewportChange;
|
||||
// Merge viewport change events.
|
||||
lastEvent.viewTop = viewportEvent.viewTop;
|
||||
lastEvent.viewLeft = viewportEvent.viewLeft;
|
||||
lastEvent.scale = viewportEvent.scale;
|
||||
lastEvent.oldScale = viewportEvent.oldScale;
|
||||
} else if (event.type === CLICK && lastEvent.type === BUBBLE_OPEN) {
|
||||
// Drop click events caused by opening/closing bubbles.
|
||||
} else {
|
||||
// Collision: newer events should merge into this event to maintain
|
||||
// order.
|
||||
hash[key] = {event, index: i};
|
||||
mergedQueue.push(event);
|
||||
for (const event of queue) {
|
||||
const lastEvent = mergedQueue[mergedQueue.length - 1];
|
||||
if (event.isNull()) continue;
|
||||
if (
|
||||
!lastEvent ||
|
||||
lastEvent.workspaceId !== event.workspaceId ||
|
||||
lastEvent.group !== event.group
|
||||
) {
|
||||
mergedQueue.push(event);
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
isBlockMove(event) &&
|
||||
isBlockMove(lastEvent) &&
|
||||
event.blockId === lastEvent.blockId
|
||||
) {
|
||||
// Merge move events.
|
||||
lastEvent.newParentId = event.newParentId;
|
||||
lastEvent.newInputName = event.newInputName;
|
||||
lastEvent.newCoordinate = event.newCoordinate;
|
||||
// Concatenate reasons without duplicates.
|
||||
if (lastEvent.reason || event.reason) {
|
||||
lastEvent.reason = Array.from(
|
||||
new Set((lastEvent.reason ?? []).concat(event.reason ?? [])),
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
isBlockChange(event) &&
|
||||
isBlockChange(lastEvent) &&
|
||||
event.blockId === lastEvent.blockId &&
|
||||
event.element === lastEvent.element &&
|
||||
event.name === lastEvent.name
|
||||
) {
|
||||
// Merge change events.
|
||||
lastEvent.newValue = event.newValue;
|
||||
} else if (isViewportChange(event) && isViewportChange(lastEvent)) {
|
||||
// Merge viewport change events.
|
||||
lastEvent.viewTop = event.viewTop;
|
||||
lastEvent.viewLeft = event.viewLeft;
|
||||
lastEvent.scale = event.scale;
|
||||
lastEvent.oldScale = event.oldScale;
|
||||
} else if (isClick(event) && isBubbleOpen(lastEvent)) {
|
||||
// Drop click events caused by opening/closing bubbles.
|
||||
} else {
|
||||
mergedQueue.push(event);
|
||||
}
|
||||
}
|
||||
// Filter out any events that have become null due to merging.
|
||||
queue = mergedQueue.filter(function (e) {
|
||||
return !e.isNull();
|
||||
});
|
||||
queue = mergedQueue.filter((e) => !e.isNull());
|
||||
if (!forward) {
|
||||
// Restore undo order.
|
||||
queue.reverse();
|
||||
}
|
||||
// Move mutation events to the top of the queue.
|
||||
// Intentionally skip first event.
|
||||
for (let i = 1, event; (event = queue[i]); i++) {
|
||||
// AnyDuringMigration because: Property 'element' does not exist on type
|
||||
// 'Abstract'.
|
||||
if (
|
||||
event.type === CHANGE &&
|
||||
(event as AnyDuringMigration).element === 'mutation'
|
||||
) {
|
||||
queue.unshift(queue.splice(i, 1)[0]);
|
||||
}
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
@@ -528,7 +418,7 @@ export function get(
|
||||
* @param event Custom data for event.
|
||||
*/
|
||||
export function disableOrphans(event: Abstract) {
|
||||
if (event.type === MOVE || event.type === CREATE) {
|
||||
if (isBlockMove(event) || isBlockCreate(event)) {
|
||||
const blockEvent = event as BlockMove | BlockCreate;
|
||||
if (!blockEvent.workspaceId) {
|
||||
return;
|
||||
@@ -572,6 +462,7 @@ export function disableOrphans(event: Abstract) {
|
||||
|
||||
export const TEST_ONLY = {
|
||||
FIRE_QUEUE,
|
||||
enqueueEvent,
|
||||
fireNow,
|
||||
fireInternal,
|
||||
setGroupInternal,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import * as registry from '../registry.js';
|
||||
import type {Workspace} from '../workspace.js';
|
||||
import {Abstract as AbstractEvent} from './events_abstract.js';
|
||||
import * as eventUtils from './utils.js';
|
||||
import {EventType} from './type.js';
|
||||
|
||||
/**
|
||||
* Notifies listeners when the workspace has finished deserializing from
|
||||
@@ -23,7 +23,7 @@ import * as eventUtils from './utils.js';
|
||||
export class FinishedLoading extends AbstractEvent {
|
||||
override isBlank = true;
|
||||
override recordUndo = false;
|
||||
override type = eventUtils.FINISHED_LOADING;
|
||||
override type = EventType.FINISHED_LOADING;
|
||||
|
||||
/**
|
||||
* @param opt_workspace The workspace that has finished loading. Undefined
|
||||
@@ -41,6 +41,6 @@ export class FinishedLoading extends AbstractEvent {
|
||||
|
||||
registry.register(
|
||||
registry.Type.EVENT,
|
||||
eventUtils.FINISHED_LOADING,
|
||||
EventType.FINISHED_LOADING,
|
||||
FinishedLoading,
|
||||
);
|
||||
|
||||
@@ -27,7 +27,10 @@ export const TEST_ONLY = {allExtensions};
|
||||
* @throws {Error} if the extension name is empty, the extension is already
|
||||
* registered, or extensionFn is not a function.
|
||||
*/
|
||||
export function register(name: string, initFn: Function) {
|
||||
export function register<T extends Block>(
|
||||
name: string,
|
||||
initFn: (this: T) => void,
|
||||
) {
|
||||
if (typeof name !== 'string' || name.trim() === '') {
|
||||
throw Error('Error: Invalid extension name "' + name + '"');
|
||||
}
|
||||
|
||||
@@ -20,12 +20,14 @@ import type {Block} from './block.js';
|
||||
import type {BlockSvg} from './block_svg.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as dropDownDiv from './dropdowndiv.js';
|
||||
import {EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import type {Input} from './inputs/input.js';
|
||||
import type {IASTNodeLocationSvg} from './interfaces/i_ast_node_location_svg.js';
|
||||
import type {IASTNodeLocationWithBlock} from './interfaces/i_ast_node_location_with_block.js';
|
||||
import type {IKeyboardAccessible} from './interfaces/i_keyboard_accessible.js';
|
||||
import type {IRegistrable} from './interfaces/i_registrable.js';
|
||||
import {ISerializable} from './interfaces/i_serializable.js';
|
||||
import {MarkerManager} from './marker_manager.js';
|
||||
import type {ConstantProvider} from './renderers/common/constants.js';
|
||||
import type {KeyboardShortcut} from './shortcut_registry.js';
|
||||
@@ -41,7 +43,6 @@ import * as userAgent from './utils/useragent.js';
|
||||
import * as utilsXml from './utils/xml.js';
|
||||
import * as WidgetDiv from './widgetdiv.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import {ISerializable} from './interfaces/i_serializable.js';
|
||||
|
||||
/**
|
||||
* A function that is called to validate changes to the field's value before
|
||||
@@ -1080,7 +1081,7 @@ export abstract class Field<T = any>
|
||||
setValue(newValue: AnyDuringMigration, fireChangeEvent = true) {
|
||||
const doLogging = false;
|
||||
if (newValue === null) {
|
||||
doLogging && console.log('null, return');
|
||||
if (doLogging) console.log('null, return');
|
||||
// Not a valid value to check.
|
||||
return;
|
||||
}
|
||||
@@ -1092,7 +1093,7 @@ export abstract class Field<T = any>
|
||||
fireChangeEvent,
|
||||
);
|
||||
if (classValue instanceof Error) {
|
||||
doLogging && console.log('invalid class validation, return');
|
||||
if (doLogging) console.log('invalid class validation, return');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1103,19 +1104,19 @@ export abstract class Field<T = any>
|
||||
fireChangeEvent,
|
||||
);
|
||||
if (localValue instanceof Error) {
|
||||
doLogging && console.log('invalid local validation, return');
|
||||
if (doLogging) console.log('invalid local validation, return');
|
||||
return;
|
||||
}
|
||||
|
||||
const source = this.sourceBlock_;
|
||||
if (source && source.disposed) {
|
||||
doLogging && console.log('source disposed, return');
|
||||
if (doLogging) console.log('source disposed, return');
|
||||
return;
|
||||
}
|
||||
|
||||
const oldValue = this.getValue();
|
||||
if (oldValue === localValue) {
|
||||
doLogging && console.log('same, doValueUpdate_, return');
|
||||
if (doLogging) console.log('same, doValueUpdate_, return');
|
||||
this.doValueUpdate_(localValue);
|
||||
return;
|
||||
}
|
||||
@@ -1123,7 +1124,7 @@ export abstract class Field<T = any>
|
||||
this.doValueUpdate_(localValue);
|
||||
if (fireChangeEvent && source && eventUtils.isEnabled()) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
source,
|
||||
'field',
|
||||
this.name || null,
|
||||
@@ -1135,7 +1136,7 @@ export abstract class Field<T = any>
|
||||
if (this.isDirty_) {
|
||||
this.forceRerender();
|
||||
}
|
||||
doLogging && console.log(this.value_);
|
||||
if (doLogging) console.log(this.value_);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
// Unused import preserved for side-effects. Remove if unneeded.
|
||||
import './events/events_block_change.js';
|
||||
|
||||
import * as dom from './utils/dom.js';
|
||||
import {Field, FieldConfig, FieldValidator} from './field.js';
|
||||
import * as fieldRegistry from './field_registry.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
|
||||
type BoolString = 'TRUE' | 'FALSE';
|
||||
type CheckboxBool = BoolString | boolean;
|
||||
|
||||
@@ -24,12 +24,12 @@ import {
|
||||
import * as fieldRegistry from './field_registry.js';
|
||||
import {Menu} from './menu.js';
|
||||
import {MenuItem} from './menuitem.js';
|
||||
import * as style from './utils/style.js';
|
||||
import * as aria from './utils/aria.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import * as parsing from './utils/parsing.js';
|
||||
import * as utilsString from './utils/string.js';
|
||||
import * as style from './utils/style.js';
|
||||
import {Svg} from './utils/svg.js';
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
import './events/events_block_change.js';
|
||||
|
||||
import {BlockSvg} from './block_svg.js';
|
||||
import * as bumpObjects from './bump_objects.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as bumpObjects from './bump_objects.js';
|
||||
import * as dialog from './dialog.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import * as dropDownDiv from './dropdowndiv.js';
|
||||
import {EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import {
|
||||
Field,
|
||||
@@ -30,10 +30,11 @@ import {
|
||||
import {Msg} from './msg.js';
|
||||
import * as aria from './utils/aria.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import {Size} from './utils/size.js';
|
||||
import * as userAgent from './utils/useragent.js';
|
||||
import * as WidgetDiv from './widgetdiv.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import {Size} from './utils/size.js';
|
||||
|
||||
/**
|
||||
* Supported types for FieldInput subclasses.
|
||||
@@ -187,7 +188,7 @@ export abstract class FieldInput<T extends InputTypes> extends Field<
|
||||
fireChangeEvent
|
||||
) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this.sourceBlock_,
|
||||
'field',
|
||||
this.name || null,
|
||||
@@ -475,7 +476,7 @@ export abstract class FieldInput<T extends InputTypes> extends Field<
|
||||
// multiple times while the editor was open, but this will fire an event
|
||||
// containing the value when the editor was opened as well as the new one.
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this.sourceBlock_,
|
||||
'field',
|
||||
this.name || null,
|
||||
@@ -592,7 +593,7 @@ export abstract class FieldInput<T extends InputTypes> extends Field<
|
||||
// Fire a special event indicating that the value changed but the change
|
||||
// isn't complete yet and normal field change listeners can wait.
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_FIELD_INTERMEDIATE_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_FIELD_INTERMEDIATE_CHANGE))(
|
||||
this.sourceBlock_,
|
||||
this.name || null,
|
||||
oldValue,
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.FieldLabel
|
||||
|
||||
import * as dom from './utils/dom.js';
|
||||
import {Field, FieldConfig} from './field.js';
|
||||
import * as fieldRegistry from './field_registry.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import * as parsing from './utils/parsing.js';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
// Former goog.module ID: Blockly.FieldNumber
|
||||
|
||||
import {Field} from './field.js';
|
||||
import * as fieldRegistry from './field_registry.js';
|
||||
import {
|
||||
FieldInput,
|
||||
FieldInputConfig,
|
||||
FieldInputValidator,
|
||||
} from './field_input.js';
|
||||
import * as fieldRegistry from './field_registry.js';
|
||||
import * as aria from './utils/aria.js';
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,19 +11,22 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.Flyout
|
||||
|
||||
import type {Abstract as AbstractEvent} from './events/events_abstract.js';
|
||||
import type {Block} from './block.js';
|
||||
import {BlockSvg} from './block_svg.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as common from './common.js';
|
||||
import {ComponentManager} from './component_manager.js';
|
||||
import {MANUALLY_DISABLED} from './constants.js';
|
||||
import {DeleteArea} from './delete_area.js';
|
||||
import type {Abstract as AbstractEvent} from './events/events_abstract.js';
|
||||
import {EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import {FlyoutButton} from './flyout_button.js';
|
||||
import {FlyoutMetricsManager} from './flyout_metrics_manager.js';
|
||||
import {IAutoHideable} from './interfaces/i_autohideable.js';
|
||||
import type {IFlyout} from './interfaces/i_flyout.js';
|
||||
import {MANUALLY_DISABLED} from './constants.js';
|
||||
import type {Options} from './options.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
import {ScrollbarPair} from './scrollbar_pair.js';
|
||||
import * as blocks from './serialization/blocks.js';
|
||||
import * as Tooltip from './tooltip.js';
|
||||
@@ -32,12 +35,10 @@ import * as dom from './utils/dom.js';
|
||||
import * as idGenerator from './utils/idgenerator.js';
|
||||
import {Svg} from './utils/svg.js';
|
||||
import * as toolbox from './utils/toolbox.js';
|
||||
import * as utilsXml from './utils/xml.js';
|
||||
import * as Variables from './variables.js';
|
||||
import {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as utilsXml from './utils/xml.js';
|
||||
import * as Xml from './xml.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
import {IAutoHideable} from './interfaces/i_autohideable.js';
|
||||
|
||||
enum FlyoutItemType {
|
||||
BLOCK = 'block',
|
||||
@@ -427,7 +428,7 @@ export abstract class Flyout
|
||||
|
||||
targetWorkspace.getComponentManager().addComponent({
|
||||
component: this,
|
||||
weight: 1,
|
||||
weight: ComponentManager.ComponentWeight.FLYOUT_WEIGHT,
|
||||
capabilities: [
|
||||
ComponentManager.Capability.AUTOHIDEABLE,
|
||||
ComponentManager.Capability.DELETE_AREA,
|
||||
@@ -1070,7 +1071,7 @@ export abstract class Flyout
|
||||
* @param block The flyout block to copy.
|
||||
* @returns Function to call when block is clicked.
|
||||
*/
|
||||
private blockMouseDown(block: BlockSvg): Function {
|
||||
private blockMouseDown(block: BlockSvg) {
|
||||
return (e: PointerEvent) => {
|
||||
const gesture = this.targetWorkspace.getGesture(e);
|
||||
if (gesture) {
|
||||
@@ -1138,13 +1139,13 @@ export abstract class Flyout
|
||||
for (let i = 0; i < newVariables.length; i++) {
|
||||
const thisVariable = newVariables[i];
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.VAR_CREATE))(thisVariable),
|
||||
new (eventUtils.get(EventType.VAR_CREATE))(thisVariable),
|
||||
);
|
||||
}
|
||||
|
||||
// Block events come after var events, in case they refer to newly created
|
||||
// variables.
|
||||
eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CREATE))(newBlock));
|
||||
eventUtils.fire(new (eventUtils.get(EventType.BLOCK_CREATE))(newBlock));
|
||||
}
|
||||
if (this.autoClose) {
|
||||
this.hide();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.FlyoutButton
|
||||
|
||||
import type {IASTNodeLocationSvg} from './blockly.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import * as Css from './css.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
@@ -20,7 +21,6 @@ import * as style from './utils/style.js';
|
||||
import {Svg} from './utils/svg.js';
|
||||
import type * as toolbox from './utils/toolbox.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import type {IASTNodeLocationSvg} from './blockly.js';
|
||||
|
||||
/**
|
||||
* Class for a button or label in the flyout.
|
||||
|
||||
@@ -44,7 +44,7 @@ export class FlyoutMetricsManager extends MetricsManager {
|
||||
let blockBoundingBox;
|
||||
try {
|
||||
blockBoundingBox = this.workspace_.getCanvas().getBBox();
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// Firefox has trouble with hidden elements (Bug 528969).
|
||||
// 2021 Update: It looks like this was fixed around Firefox 77 released in
|
||||
// 2020.
|
||||
|
||||
@@ -295,8 +295,8 @@ export class CodeGenerator {
|
||||
* @param name The name of the input.
|
||||
* @param outerOrder The maximum binding strength (minimum order value) of any
|
||||
* operators adjacent to "block".
|
||||
* @returns Generated code or '' if no blocks are connected or the specified
|
||||
* input does not exist.
|
||||
* @returns Generated code or '' if no blocks are connected.
|
||||
* @throws ReferenceError if the specified input does not exist.
|
||||
*/
|
||||
valueToCode(block: Block, name: string, outerOrder: number): string {
|
||||
if (isNaN(outerOrder)) {
|
||||
@@ -381,6 +381,7 @@ export class CodeGenerator {
|
||||
* @param block The block containing the input.
|
||||
* @param name The name of the input.
|
||||
* @returns Generated code or '' if no blocks are connected.
|
||||
* @throws ReferenceError if the specified input does not exist.
|
||||
*/
|
||||
statementToCode(block: Block, name: string): string {
|
||||
const targetBlock = block.getInputTargetBlock(name);
|
||||
|
||||
@@ -18,23 +18,24 @@ import './events/events_click.js';
|
||||
import * as blockAnimations from './block_animations.js';
|
||||
import type {BlockSvg} from './block_svg.js';
|
||||
import * as browserEvents from './browser_events.js';
|
||||
import {RenderedWorkspaceComment} from './comments.js';
|
||||
import * as common from './common.js';
|
||||
import {config} from './config.js';
|
||||
import * as dropDownDiv from './dropdowndiv.js';
|
||||
import {EventType} from './events/type.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import type {Field} from './field.js';
|
||||
import type {IBubble} from './interfaces/i_bubble.js';
|
||||
import {IDraggable, isDraggable} from './interfaces/i_draggable.js';
|
||||
import {IDragger} from './interfaces/i_dragger.js';
|
||||
import type {IFlyout} from './interfaces/i_flyout.js';
|
||||
import type {IIcon} from './interfaces/i_icon.js';
|
||||
import * as registry from './registry.js';
|
||||
import * as Tooltip from './tooltip.js';
|
||||
import * as Touch from './touch.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import {WorkspaceDragger} from './workspace_dragger.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import type {IIcon} from './interfaces/i_icon.js';
|
||||
import {IDragger} from './interfaces/i_dragger.js';
|
||||
import * as registry from './registry.js';
|
||||
import {IDraggable, isDraggable} from './interfaces/i_draggable.js';
|
||||
import {RenderedWorkspaceComment} from './comments.js';
|
||||
|
||||
/**
|
||||
* Note: In this file "start" refers to pointerdown
|
||||
@@ -599,13 +600,20 @@ export class Gesture {
|
||||
*/
|
||||
handleTouchMove(e: PointerEvent) {
|
||||
const pointerId = Touch.getTouchIdentifierFromEvent(e);
|
||||
// Update the cache
|
||||
this.cachedPoints.set(pointerId, this.getTouchPoint(e));
|
||||
|
||||
if (this.isPinchZoomEnabled && this.cachedPoints.size === 2) {
|
||||
this.handlePinch(e);
|
||||
} else {
|
||||
this.handleMove(e);
|
||||
// Handle the move directly instead of calling handleMove
|
||||
this.updateFromEvent(e);
|
||||
if (this.workspaceDragger) {
|
||||
this.workspaceDragger.drag(this.currentDragDeltaXY);
|
||||
} else if (this.dragger) {
|
||||
this.dragger.onDrag(this.mostRecentEvent, this.currentDragDeltaXY);
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,7 +777,7 @@ export class Gesture {
|
||||
*/
|
||||
private fireWorkspaceClick(ws: WorkspaceSvg) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.CLICK))(null, ws.id, 'workspace'),
|
||||
new (eventUtils.get(EventType.CLICK))(null, ws.id, 'workspace'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -902,7 +910,7 @@ export class Gesture {
|
||||
);
|
||||
}
|
||||
// Clicks events are on the start block, even if it was a shadow.
|
||||
const event = new (eventUtils.get(eventUtils.CLICK))(
|
||||
const event = new (eventUtils.get(EventType.CLICK))(
|
||||
this.startBlock,
|
||||
this.startWorkspace_.id,
|
||||
'block',
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.Grid
|
||||
|
||||
import * as dom from './utils/dom.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import {Svg} from './utils/svg.js';
|
||||
import {GridOptions} from './options.js';
|
||||
import {Coordinate} from './utils/coordinate.js';
|
||||
import * as dom from './utils/dom.js';
|
||||
import {Svg} from './utils/svg.js';
|
||||
|
||||
/**
|
||||
* Class for a workspace's grid.
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {Icon} from './icons/icon.js';
|
||||
import {CommentIcon, CommentState} from './icons/comment_icon.js';
|
||||
import {MutatorIcon} from './icons/mutator_icon.js';
|
||||
import {WarningIcon} from './icons/warning_icon.js';
|
||||
import {IconType} from './icons/icon_types.js';
|
||||
import * as exceptions from './icons/exceptions.js';
|
||||
import {Icon} from './icons/icon.js';
|
||||
import {IconType} from './icons/icon_types.js';
|
||||
import {MutatorIcon} from './icons/mutator_icon.js';
|
||||
import * as registry from './icons/registry.js';
|
||||
import {WarningIcon} from './icons/warning_icon.js';
|
||||
|
||||
export {
|
||||
Icon,
|
||||
CommentIcon,
|
||||
CommentState,
|
||||
MutatorIcon,
|
||||
WarningIcon,
|
||||
IconType,
|
||||
exceptions,
|
||||
Icon,
|
||||
IconType,
|
||||
MutatorIcon,
|
||||
registry,
|
||||
WarningIcon,
|
||||
};
|
||||
|
||||
@@ -8,21 +8,22 @@
|
||||
|
||||
import type {Block} from '../block.js';
|
||||
import type {BlockSvg} from '../block_svg.js';
|
||||
import {IconType} from './icon_types.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {Icon} from './icon.js';
|
||||
import type {IHasBubble} from '../interfaces/i_has_bubble.js';
|
||||
import type {ISerializable} from '../interfaces/i_serializable.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import * as registry from './registry.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import {TextBubble} from '../bubbles/text_bubble.js';
|
||||
import {TextInputBubble} from '../bubbles/textinput_bubble.js';
|
||||
import type {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import type {IHasBubble} from '../interfaces/i_has_bubble.js';
|
||||
import type {ISerializable} from '../interfaces/i_serializable.js';
|
||||
import * as renderManagement from '../render_management.js';
|
||||
import {Coordinate} from '../utils.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import type {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {Icon} from './icon.js';
|
||||
import {IconType} from './icon_types.js';
|
||||
import * as registry from './registry.js';
|
||||
|
||||
/** The size of the comment icon in workspace-scale units. */
|
||||
const SIZE = 17;
|
||||
@@ -159,7 +160,7 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable {
|
||||
setText(text: string) {
|
||||
const oldText = this.text;
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this.sourceBlock,
|
||||
'comment',
|
||||
null,
|
||||
@@ -238,7 +239,7 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable {
|
||||
if (this.text === newText) return;
|
||||
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this.sourceBlock,
|
||||
'comment',
|
||||
null,
|
||||
@@ -288,7 +289,7 @@ export class CommentIcon extends Icon implements IHasBubble, ISerializable {
|
||||
}
|
||||
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BUBBLE_OPEN))(
|
||||
new (eventUtils.get(EventType.BUBBLE_OPEN))(
|
||||
this.sourceBlock,
|
||||
visible,
|
||||
'comment',
|
||||
|
||||
@@ -9,12 +9,12 @@ import type {BlockSvg} from '../block_svg.js';
|
||||
import * as browserEvents from '../browser_events.js';
|
||||
import {hasBubble} from '../interfaces/i_has_bubble.js';
|
||||
import type {IIcon} from '../interfaces/i_icon.js';
|
||||
import * as tooltip from '../tooltip.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import type {IconType} from './icon_types.js';
|
||||
import * as tooltip from '../tooltip.js';
|
||||
|
||||
/**
|
||||
* The abstract icon class. Icons are visual elements that live in the top-start
|
||||
|
||||
@@ -6,22 +6,24 @@
|
||||
|
||||
// Former goog.module ID: Blockly.Mutator
|
||||
|
||||
import type {BlockSvg} from '../block_svg.js';
|
||||
import type {BlocklyOptions} from '../blockly_options.js';
|
||||
import {MiniWorkspaceBubble} from '../bubbles/mini_workspace_bubble.js';
|
||||
import type {Abstract} from '../events/events_abstract.js';
|
||||
import {BlockChange} from '../events/events_block_change.js';
|
||||
import type {BlocklyOptions} from '../blockly_options.js';
|
||||
import type {BlockSvg} from '../block_svg.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {isBlockChange, isBlockCreate} from '../events/predicates.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import type {IHasBubble} from '../interfaces/i_has_bubble.js';
|
||||
import {Icon} from './icon.js';
|
||||
import {MiniWorkspaceBubble} from '../bubbles/mini_workspace_bubble.js';
|
||||
import * as renderManagement from '../render_management.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils/size.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import type {WorkspaceSvg} from '../workspace_svg.js';
|
||||
import {Icon} from './icon.js';
|
||||
import {IconType} from './icon_types.js';
|
||||
import * as renderManagement from '../render_management.js';
|
||||
|
||||
/** The size of the mutator icon in workspace-scale units. */
|
||||
const SIZE = 17;
|
||||
@@ -193,7 +195,7 @@ export class MutatorIcon extends Icon implements IHasBubble {
|
||||
}
|
||||
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BUBBLE_OPEN))(
|
||||
new (eventUtils.get(EventType.BUBBLE_OPEN))(
|
||||
this.sourceBlock,
|
||||
visible,
|
||||
'mutator',
|
||||
@@ -307,9 +309,8 @@ export class MutatorIcon extends Icon implements IHasBubble {
|
||||
static isIgnorableMutatorEvent(e: Abstract) {
|
||||
return (
|
||||
e.isUiEvent ||
|
||||
e.type === eventUtils.CREATE ||
|
||||
(e.type === eventUtils.CHANGE &&
|
||||
(e as BlockChange).element === 'disabled')
|
||||
isBlockCreate(e) ||
|
||||
(isBlockChange(e) && e.element === 'disabled')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -331,7 +332,7 @@ export class MutatorIcon extends Icon implements IHasBubble {
|
||||
|
||||
if (oldExtraState !== newExtraState) {
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
|
||||
new (eventUtils.get(EventType.BLOCK_CHANGE))(
|
||||
this.sourceBlock,
|
||||
'mutation',
|
||||
null,
|
||||
|
||||
@@ -7,17 +7,18 @@
|
||||
// Former goog.module ID: Blockly.Warning
|
||||
|
||||
import type {BlockSvg} from '../block_svg.js';
|
||||
import {TextBubble} from '../bubbles/text_bubble.js';
|
||||
import {EventType} from '../events/type.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import type {IHasBubble} from '../interfaces/i_has_bubble.js';
|
||||
import * as renderManagement from '../render_management.js';
|
||||
import {Size} from '../utils.js';
|
||||
import {Coordinate} from '../utils/coordinate.js';
|
||||
import * as dom from '../utils/dom.js';
|
||||
import * as eventUtils from '../events/utils.js';
|
||||
import {Icon} from './icon.js';
|
||||
import type {IHasBubble} from '../interfaces/i_has_bubble.js';
|
||||
import {Rect} from '../utils/rect.js';
|
||||
import {Size} from '../utils.js';
|
||||
import {Svg} from '../utils/svg.js';
|
||||
import {TextBubble} from '../bubbles/text_bubble.js';
|
||||
import {Icon} from './icon.js';
|
||||
import {IconType} from './icon_types.js';
|
||||
import * as renderManagement from '../render_management.js';
|
||||
|
||||
/** The size of the warning icon in workspace-scale units. */
|
||||
const SIZE = 17;
|
||||
@@ -188,7 +189,7 @@ export class WarningIcon extends Icon implements IHasBubble {
|
||||
}
|
||||
|
||||
eventUtils.fire(
|
||||
new (eventUtils.get(eventUtils.BUBBLE_OPEN))(
|
||||
new (eventUtils.get(EventType.BUBBLE_OPEN))(
|
||||
this.sourceBlock,
|
||||
visible,
|
||||
'warning',
|
||||
|
||||
@@ -77,6 +77,8 @@ export function inject(
|
||||
common.setMainWorkspace(workspace);
|
||||
});
|
||||
|
||||
browserEvents.conditionalBind(subContainer, 'keydown', null, onKeyDown);
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
@@ -320,8 +322,6 @@ let documentEventsBound = false;
|
||||
* Most of these events should be bound to the SVG's surface.
|
||||
* However, 'mouseup' has to be on the whole document so that a block dragged
|
||||
* out of bounds and released will know that it has been released.
|
||||
* Also, 'keydown' has to be on the whole document since the browser doesn't
|
||||
* understand a concept of focus on the SVG image.
|
||||
*/
|
||||
function bindDocumentEvents() {
|
||||
if (!documentEventsBound) {
|
||||
@@ -333,7 +333,6 @@ function bindDocumentEvents() {
|
||||
}
|
||||
}
|
||||
});
|
||||
browserEvents.conditionalBind(document, 'keydown', null, onKeyDown);
|
||||
// longStop needs to run to stop the context menu from showing up. It
|
||||
// should run regardless of what other touch event handlers have run.
|
||||
browserEvents.bind(document, 'touchend', null, Touch.longStop);
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
*/
|
||||
|
||||
import {Align} from './inputs/align.js';
|
||||
import {Input} from './inputs/input.js';
|
||||
import {DummyInput} from './inputs/dummy_input.js';
|
||||
import {EndRowInput} from './inputs/end_row_input.js';
|
||||
import {Input} from './inputs/input.js';
|
||||
import {inputTypes} from './inputs/input_types.js';
|
||||
import {StatementInput} from './inputs/statement_input.js';
|
||||
import {ValueInput} from './inputs/value_input.js';
|
||||
import {inputTypes} from './inputs/input_types.js';
|
||||
|
||||
export {
|
||||
Align,
|
||||
Input,
|
||||
DummyInput,
|
||||
EndRowInput,
|
||||
Input,
|
||||
inputTypes,
|
||||
StatementInput,
|
||||
ValueInput,
|
||||
inputTypes,
|
||||
};
|
||||
|
||||
@@ -21,8 +21,8 @@ import type {ConnectionType} from '../connection_type.js';
|
||||
import type {Field} from '../field.js';
|
||||
import * as fieldRegistry from '../field_registry.js';
|
||||
import type {RenderedConnection} from '../rendered_connection.js';
|
||||
import {inputTypes} from './input_types.js';
|
||||
import {Align} from './align.js';
|
||||
import {inputTypes} from './input_types.js';
|
||||
|
||||
/** Class for an input with optional fields. */
|
||||
export class Input {
|
||||
|
||||
@@ -11,20 +11,20 @@
|
||||
*/
|
||||
// Former goog.module ID: Blockly.InsertionMarkerManager
|
||||
|
||||
import {finishQueuedRenders} from './render_management.js';
|
||||
import * as blockAnimations from './block_animations.js';
|
||||
import type {BlockSvg} from './block_svg.js';
|
||||
import * as common from './common.js';
|
||||
import {ComponentManager} from './component_manager.js';
|
||||
import {config} from './config.js';
|
||||
import * as blocks from './serialization/blocks.js';
|
||||
import * as eventUtils from './events/utils.js';
|
||||
import type {IDeleteArea} from './interfaces/i_delete_area.js';
|
||||
import type {IDragTarget} from './interfaces/i_drag_target.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
import {finishQueuedRenders} from './render_management.js';
|
||||
import type {RenderedConnection} from './rendered_connection.js';
|
||||
import * as blocks from './serialization/blocks.js';
|
||||
import type {Coordinate} from './utils/coordinate.js';
|
||||
import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
import * as renderManagement from './render_management.js';
|
||||
|
||||
/** Represents a nearby valid connection. */
|
||||
interface CandidateConnection {
|
||||
@@ -529,7 +529,7 @@ export class InsertionMarkerManager {
|
||||
local.getSourceBlock(),
|
||||
local,
|
||||
);
|
||||
} catch (e) {
|
||||
} catch {
|
||||
// It's possible that the number of connections on the local block has
|
||||
// changed since the insertion marker was originally created. Let's
|
||||
// recreate the insertion marker and try again. In theory we could
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user