diff --git a/src/App.tsx b/src/App.tsx index 157d75bc..a6396579 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -31,7 +31,6 @@ import ToolboxSettingsModal from './reactComponents/ToolboxSettings'; import * as Tabs from './reactComponents/Tabs'; import { TabType } from './types/TabType'; -import * as editor from './editor/editor'; import { extendedPythonGenerator } from './editor/extended_python_generator'; import * as commonStorage from './storage/common_storage'; @@ -42,7 +41,6 @@ import * as clientSideStorage from './storage/client_side_storage'; import * as CustomBlocks from './blocks/setup_custom_blocks'; import { initialize as initializePythonBlocks } from './blocks/utils/python'; -import { TOOLBOX_UPDATE_EVENT } from './blocks/mrc_mechanism_component_holder'; import { antdThemeFromString } from './reactComponents/ThemeModal'; import { useTranslation } from 'react-i18next'; import { UserSettingsProvider } from './reactComponents/UserSettingsProvider'; @@ -261,24 +259,6 @@ const AppContent: React.FC = ({ project, setProject }): React.J handleToolboxSettingsOk(updatedShownCategories); }; - /** Handles toolbox update requests from blocks */ - const handleToolboxUpdateRequest = React.useCallback((e: Event) => { - const workspaceId = (e as CustomEvent).detail.workspaceId; - const correspondingEditor = editor.Editor.getEditorForBlocklyWorkspaceId(workspaceId); - if (correspondingEditor) { - correspondingEditor.updateToolbox(shownPythonToolboxCategories); - } - }, [shownPythonToolboxCategories, i18n.language]); - - // Add event listener for toolbox updates - React.useEffect(() => { - window.addEventListener(TOOLBOX_UPDATE_EVENT, handleToolboxUpdateRequest); - - return () => { - window.removeEventListener(TOOLBOX_UPDATE_EVENT, handleToolboxUpdateRequest); - }; - }, [handleToolboxUpdateRequest]); - // Initialize blocks when app loads React.useEffect(() => { initializeBlocks(); diff --git a/src/blocks/mrc_component.ts b/src/blocks/mrc_component.ts index e9a0f75b..0b8f2f96 100644 --- a/src/blocks/mrc_component.ts +++ b/src/blocks/mrc_component.ts @@ -172,6 +172,10 @@ const COMPONENT = { if (oldName && oldName !== name && oldName !== legalName) { // Rename any callers. renameMethodCallers(this.workspace, this.mrcComponentId, legalName); + const editor = Editor.getEditorForBlocklyWorkspace(this.workspace); + if (editor) { + editor.updateToolboxAfterDelay(); + } } return legalName; }, @@ -212,7 +216,7 @@ const COMPONENT = { /** * mrcOnMove is called when a ComponentBlock is moved. */ - mrcOnMove: function(this: ComponentBlock, reason: string[]): void { + mrcOnMove: function(this: ComponentBlock, editor: Editor, reason: string[]): void { this.checkBlockIsInHolder(); if (reason.includes('connect')) { const rootBlock: Blockly.Block | null = this.getRootBlock(); @@ -220,7 +224,7 @@ const COMPONENT = { (rootBlock as MechanismComponentHolderBlock).setNameOfChildBlock(this); } } - mrcDescendantsMayHaveChanged(this.workspace); + mrcDescendantsMayHaveChanged(this.workspace, editor); }, checkBlockIsInHolder: function(this: ComponentBlock): void { const rootBlock: Blockly.Block | null = this.getRootBlock(); diff --git a/src/blocks/mrc_event.ts b/src/blocks/mrc_event.ts index 070d7761..565f75fb 100644 --- a/src/blocks/mrc_event.ts +++ b/src/blocks/mrc_event.ts @@ -211,7 +211,7 @@ const EVENT = { /** * mrcOnMove is called when an EventBlock is moved. */ - mrcOnMove: function(this: EventBlock, reason: string[]): void { + mrcOnMove: function(this: EventBlock, editor: Editor, reason: string[]): void { this.checkBlockIsInHolder(); if (reason.includes('connect')) { const rootBlock: Blockly.Block | null = this.getRootBlock(); @@ -219,7 +219,7 @@ const EVENT = { (rootBlock as MechanismComponentHolderBlock).setNameOfChildBlock(this); } } - mrcDescendantsMayHaveChanged(this.workspace); + mrcDescendantsMayHaveChanged(this.workspace, editor); }, /** * mrcOnMutatorOpen is called when the mutator on an EventBlock is opened. diff --git a/src/blocks/mrc_get_parameter.ts b/src/blocks/mrc_get_parameter.ts index 10f1709f..e5e64053 100644 --- a/src/blocks/mrc_get_parameter.ts +++ b/src/blocks/mrc_get_parameter.ts @@ -23,6 +23,7 @@ import * as Blockly from 'blockly'; import {Order} from 'blockly/python'; +import { Editor } from '../editor/editor'; import {ExtendedPythonGenerator} from '../editor/extended_python_generator'; import {createFieldNonEditableText} from '../fields/FieldNonEditableText'; import {MRC_STYLE_VARIABLES} from '../themes/styles'; @@ -82,7 +83,7 @@ const GET_PARAMETER_BLOCK = { /** * mrcOnMove is called when an EventBlock is moved. */ - mrcOnMove: function(this: GetParameterBlock, _reason: string[]): void { + mrcOnMove: function(this: GetParameterBlock, _editor: Editor, _reason: string[]): void { this.checkBlockPlacement(); }, mrcOnAncestorMove: function(this: GetParameterBlock): void { diff --git a/src/blocks/mrc_jump_to_step.ts b/src/blocks/mrc_jump_to_step.ts index fbd470dd..b0e63d7b 100644 --- a/src/blocks/mrc_jump_to_step.ts +++ b/src/blocks/mrc_jump_to_step.ts @@ -21,6 +21,7 @@ */ import * as Blockly from 'blockly'; +import { Editor } from '../editor/editor'; import { ExtendedPythonGenerator } from '../editor/extended_python_generator'; import { createFieldNonEditableText } from '../fields/FieldNonEditableText'; import { MRC_STYLE_VARIABLES } from '../themes/styles'; @@ -62,7 +63,7 @@ const JUMP_TO_STEP_BLOCK = { /** * mrcOnMove is called when a JumpToStepBlock is moved. */ - mrcOnMove: function (this: JumpToStepBlock, _reason: string[]): void { + mrcOnMove: function (this: JumpToStepBlock, _editor: Editor, _reason: string[]): void { this.checkBlockPlacement(); }, mrcOnAncestorMove: function (this: JumpToStepBlock): void { diff --git a/src/blocks/mrc_mechanism.ts b/src/blocks/mrc_mechanism.ts index fe42fe38..d0225e57 100644 --- a/src/blocks/mrc_mechanism.ts +++ b/src/blocks/mrc_mechanism.ts @@ -212,7 +212,7 @@ const MECHANISM = { /** * mrcOnMove is called when a MechanismBlock is moved. */ - mrcOnMove: function(this: MechanismBlock, reason: string[]): void { + mrcOnMove: function(this: MechanismBlock, editor: Editor, reason: string[]): void { this.checkBlockIsInHolder(); if (reason.includes('connect')) { const rootBlock: Blockly.Block | null = this.getRootBlock(); @@ -220,7 +220,7 @@ const MECHANISM = { (rootBlock as MechanismComponentHolderBlock).setNameOfChildBlock(this); } } - mrcDescendantsMayHaveChanged(this.workspace); + mrcDescendantsMayHaveChanged(this.workspace, editor); }, checkBlockIsInHolder: function(this: MechanismBlock): void { const rootBlock: Blockly.Block | null = this.getRootBlock(); diff --git a/src/blocks/mrc_mechanism_component_holder.ts b/src/blocks/mrc_mechanism_component_holder.ts index e6e25a9b..8db2a310 100644 --- a/src/blocks/mrc_mechanism_component_holder.ts +++ b/src/blocks/mrc_mechanism_component_holder.ts @@ -46,8 +46,6 @@ const INPUT_COMPONENTS = 'COMPONENTS'; const INPUT_PRIVATE_COMPONENTS = 'PRIVATE_COMPONENTS'; const INPUT_EVENTS = 'EVENTS'; -export const TOOLBOX_UPDATE_EVENT = 'toolbox-update-requested'; - type MechanismComponentHolderExtraState = { hideMechanisms?: boolean; hidePrivateComponents?: boolean; @@ -62,7 +60,6 @@ interface MechanismComponentHolderMixin extends MechanismComponentHolderMixinTyp mrcComponentBlockIds: string, mrcPrivateComponentBlockIds: string, mrcEventBlockIds: string, - mrcToolboxUpdateTimeout: NodeJS.Timeout | null; } type MechanismComponentHolderMixinType = typeof MECHANISM_COMPONENT_HOLDER; @@ -78,7 +75,6 @@ const MECHANISM_COMPONENT_HOLDER = { this.mrcComponentBlockIds = ''; this.mrcPrivateComponentBlockIds = ''; this.mrcEventBlockIds = ''; - this.mrcToolboxUpdateTimeout = null; }, ...NONCOPYABLE_BLOCK, saveExtraState: function (this: MechanismComponentHolderBlock): MechanismComponentHolderExtraState { @@ -135,21 +131,21 @@ const MECHANISM_COMPONENT_HOLDER = { * mrcOnLoad is called for each MechanismComponentHolderBlock when the blocks are loaded in the blockly * workspace. */ - mrcOnLoad: function(this: MechanismComponentHolderBlock, _editor: Editor): void { - this.collectDescendants(false); + mrcOnLoad: function(this: MechanismComponentHolderBlock, editor: Editor): void { + this.collectDescendants(editor, false); }, /** * mrcOnDescendantDisconnect is called for each MechanismComponentHolderBlock when any descendant is * disconnected. */ - mrcOnDescendantDisconnect: function(this: MechanismComponentHolderBlock): void { - this.collectDescendants(true); + mrcOnDescendantDisconnect: function(this: MechanismComponentHolderBlock, editor: Editor): void { + this.collectDescendants(editor, true); }, - mrcDescendantsMayHaveChanged: function (this: MechanismComponentHolderBlock): void { - this.collectDescendants(true); + mrcDescendantsMayHaveChanged: function (this: MechanismComponentHolderBlock, editor: Editor): void { + this.collectDescendants(editor, true); }, collectDescendants: function ( - this: MechanismComponentHolderBlock, updateToolboxIfDescendantsChanged: boolean): void { + this: MechanismComponentHolderBlock, editor: Editor, updateToolboxIfDescendantsChanged: boolean): void { let mechanismBlockIds = ''; let componentBlockIds = ''; let privateComponentBlockIds = ''; @@ -209,7 +205,7 @@ const MECHANISM_COMPONENT_HOLDER = { componentBlockIds !== this.mrcComponentBlockIds || privateComponentBlockIds !== this.mrcPrivateComponentBlockIds || eventBlockIds !== this.mrcEventBlockIds) { - this.updateToolboxAfterDelay(); + editor.updateToolboxAfterDelay(); } } @@ -218,21 +214,6 @@ const MECHANISM_COMPONENT_HOLDER = { this.mrcPrivateComponentBlockIds = privateComponentBlockIds; this.mrcEventBlockIds = eventBlockIds; }, - updateToolboxAfterDelay: function (this: MechanismComponentHolderBlock): void { - if (this.mrcToolboxUpdateTimeout) { - clearTimeout(this.mrcToolboxUpdateTimeout); - } - this.mrcToolboxUpdateTimeout = setTimeout(() => { - const event = new CustomEvent(TOOLBOX_UPDATE_EVENT, { - detail: { - timestamp: Date.now(), - workspaceId: this.workspace.id, - } - }); - window.dispatchEvent(event); - this.mrcToolboxUpdateTimeout = null; - }, 100); - }, /** * setNameOfChildBlock is called from mrc_mechanism, mrc_component, and mrc_event blocks when they * connect to this mrc_mechanism_component_holder block. @@ -515,10 +496,10 @@ export function getEvents( }); } -export function mrcDescendantsMayHaveChanged(workspace: Blockly.Workspace): void { +export function mrcDescendantsMayHaveChanged(workspace: Blockly.Workspace, editor: Editor): void { // Get the holder block and call its mrcDescendantsMayHaveChanged method. workspace.getBlocksByType(BLOCK_NAME).forEach(block => { - (block as MechanismComponentHolderBlock).mrcDescendantsMayHaveChanged(); + (block as MechanismComponentHolderBlock).mrcDescendantsMayHaveChanged(editor); }); } diff --git a/src/editor/editor.ts b/src/editor/editor.ts index 8262b867..c6817f1c 100644 --- a/src/editor/editor.ts +++ b/src/editor/editor.ts @@ -67,6 +67,7 @@ export class Editor { private bindedOnChange: any = null; private shownPythonToolboxCategories: Set | null = null; private toolbox: Blockly.utils.toolbox.ToolboxInfo = EMPTY_TOOLBOX; + private toolboxUpdateTimeout: NodeJS.Timeout | null = null; constructor( blocklyWorkspace: Blockly.WorkspaceSvg, @@ -163,7 +164,7 @@ export class Editor { if (rootBlock) { // Call MRC_ON_DESCENDANT_DISCONNECT on the root block of the block that was disconnected. if (MRC_ON_DESCENDANT_DISCONNECT in rootBlock && typeof rootBlock[MRC_ON_DESCENDANT_DISCONNECT] === 'function') { - rootBlock[MRC_ON_DESCENDANT_DISCONNECT](); + rootBlock[MRC_ON_DESCENDANT_DISCONNECT](this); } } } @@ -175,7 +176,7 @@ export class Editor { } // Call MRC_ON_MOVE on the block that was moved. if (MRC_ON_MOVE in block && typeof block[MRC_ON_MOVE] === 'function') { - block[MRC_ON_MOVE](reason); + block[MRC_ON_MOVE](this, reason); } // Call MRC_ON_ANCESTOR_MOVE on all descendents of the block that was moved. block.getDescendants(false).forEach(descendant => { @@ -279,6 +280,16 @@ export class Editor { Blockly.serialization.workspaces.load(moduleContent.getBlocks(), this.blocklyWorkspace); } + public updateToolboxAfterDelay(): void { + if (this.toolboxUpdateTimeout) { + clearTimeout(this.toolboxUpdateTimeout); + } + this.toolboxUpdateTimeout = setTimeout(() => { + this.updateToolboxImpl(); + this.toolboxUpdateTimeout = null; + }, 100); + } + public updateToolbox(shownPythonToolboxCategories: Set): void { this.shownPythonToolboxCategories = shownPythonToolboxCategories; this.updateToolboxImpl();