Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import * as CustomBlocks from './blocks/setup_custom_blocks';
import { initialize as initializePythonBlocks } from './blocks/utils/python';
import * as ChangeFramework from './blocks/utils/change_framework'
import { mutatorOpenListener } from './blocks/mrc_param_container'
import { TOOLBOX_UPDATE_EVENT } from './blocks/mrc_mechanism_component_holder';

/** Storage key for shown toolbox categories. */
const SHOWN_TOOLBOX_CATEGORIES_KEY = 'shownPythonToolboxCategories';
Expand Down Expand Up @@ -253,6 +254,22 @@ const App: React.FC = (): React.JSX.Element => {
return tabs;
};

/** Handles toolbox update requests from blocks */
const handleToolboxUpdateRequest = React.useCallback(() => {
if (blocksEditor.current && currentModule) {
blocksEditor.current.updateToolbox(shownPythonToolboxCategories);
}
}, [currentModule, shownPythonToolboxCategories]);

// Add event listener for toolbox updates
React.useEffect(() => {
window.addEventListener(TOOLBOX_UPDATE_EVENT, handleToolboxUpdateRequest);

return () => {
window.removeEventListener(TOOLBOX_UPDATE_EVENT, handleToolboxUpdateRequest);
};
}, [handleToolboxUpdateRequest]);

// Initialize storage and blocks when app loads
React.useEffect(() => {
openStorage();
Expand All @@ -269,13 +286,6 @@ const App: React.FC = (): React.JSX.Element => {
}
}, [currentModule]);

// Update toolbox when shown categories change
React.useEffect(() => {
if (blocksEditor.current) {
blocksEditor.current.updateToolbox(shownPythonToolboxCategories);
}
}, [shownPythonToolboxCategories]);

// Initialize Blockly workspace and editor when component and storage are ready
React.useEffect(() => {
if (!blocklyComponent.current || !storage) {
Expand Down
18 changes: 18 additions & 0 deletions src/blocks/mrc_mechanism_component_holder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export const BLOCK_NAME = 'mrc_mechanism_component_holder';
export const MECHANISM = 'mechanism';
export const COMPONENT = 'component';

export const TOOLBOX_UPDATE_EVENT = 'toolbox-update-requested';

type MechanismComponentHolderExtraState = {
hideMechanisms?: boolean;
}
Expand Down Expand Up @@ -115,17 +117,33 @@ const MECHANISM_COMPONENT_HOLDER = {
let blockMoveEvent = blockEvent as Blockly.Events.BlockMove;
if (blockMoveEvent.reason?.includes('connect')) {
setName(block);
updateToolboxAfterDelay();
}
}
else {
if (blockEvent.type == Blockly.Events.BLOCK_CHANGE) {
setName(block);
updateToolboxAfterDelay();
}
}
},

}

let toolboxUpdateTimeout: NodeJS.Timeout | null = null;
export function updateToolboxAfterDelay(){
if (toolboxUpdateTimeout) {
clearTimeout(toolboxUpdateTimeout);
}
toolboxUpdateTimeout = setTimeout(() => {
const event = new CustomEvent(TOOLBOX_UPDATE_EVENT, {
detail: { timestamp: Date.now() }
});
window.dispatchEvent(event);
toolboxUpdateTimeout = null;
}, 100);
}

export const setup = function () {
Blockly.Blocks[BLOCK_NAME] = MECHANISM_COMPONENT_HOLDER;
}
Expand Down
34 changes: 25 additions & 9 deletions src/toolbox/blocks_components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,35 @@
*/

/**
* @author [email protected] (Alan Smith)
* @fileoverview Component blocks for the toolbox.
*/

import * as ToolboxItems from './items';
import * as ColorSensor from './hardware_components/color_sensor';
import * as SmartMotor from './hardware_components/smart_motor';
import * as TouchSensor from './hardware_components/touch_sensor';
import * as Servo from './hardware_components/servo';
import * as TouchSensor from './hardware_components/touch_sensor';

const ALL_COMPONENTS: Record<string, (componentName: string) => ToolboxItems.ContentsType[]> = {
[ColorSensor.TYPE_NAME]: ColorSensor.getBlocks,
[SmartMotor.TYPE_NAME]: SmartMotor.getBlocks,
[TouchSensor.TYPE_NAME]: TouchSensor.getBlocks,
[Servo.TYPE_NAME]: Servo.getBlocks,
};

export function getAllPossibleComponents(hideParams: boolean): ToolboxItems.ContentsType[] {
return [
SmartMotor.getDefinitionBlock(hideParams),
TouchSensor.getDefinitionBlock(hideParams),
ColorSensor.getDefinitionBlock(hideParams),
Servo.getDefinitionBlock(hideParams),
];
}

export function getAllPossibleComponents(hideParams : boolean): ToolboxItems.ContentsType[] {
return [
SmartMotor.getDefinitionBlock(hideParams),
TouchSensor.getDefinitionBlock(hideParams),
ColorSensor.getDefinitionBlock(hideParams),
Servo.getDefinitionBlock(hideParams),
];
export function getBlocks(componentType: string, componentName: string): ToolboxItems.ContentsType[] {
const getBlocksFunction = ALL_COMPONENTS[componentType];
if (getBlocksFunction) {
return getBlocksFunction(componentName);
}
return [];
}
51 changes: 37 additions & 14 deletions src/toolbox/hardware_category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ import * as Blockly from 'blockly/core';
import * as toolboxItems from './items';
import * as commonStorage from '../storage/common_storage';
import { getAllPossibleMechanisms } from './blocks_mechanisms';
import { getAllPossibleComponents } from './blocks_components';
import * as SmartMotor from './hardware_components/smart_motor';
import * as TouchSensor from './hardware_components/touch_sensor';
import { getAllPossibleComponents, getBlocks } from './blocks_components';
import * as MechanismComponentHolder from '../blocks/mrc_mechanism_component_holder';

export function getHardwareCategory(currentModule: commonStorage.Module) {
if (currentModule.moduleType === commonStorage.MODULE_TYPE_OPMODE) {
Expand Down Expand Up @@ -243,22 +242,46 @@ function getRobotMethodsBlocks(currentModule: commonStorage.Module) {

function getComponentsBlocks(currentModule: commonStorage.Module) {
const contents = [];

// Add the "+ Component" category
contents.push({
kind: 'category',
name: '+ Component',
contents: getAllPossibleComponents(true)
});
contents.push({
kind: 'category',
name: 'my_motor',
contents: SmartMotor.getBlocks('my_motor')
},
{
kind: 'category',
name: 'my_touch_sensor',
contents: TouchSensor.getBlocks('my_touch_sensor')
},
);

// Get components from the current workspace
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!!!

const workspace = Blockly.getMainWorkspace();
if (workspace) {
const holderBlocks = workspace.getBlocksByType(MechanismComponentHolder.BLOCK_NAME);

holderBlocks.forEach(holderBlock => {
// Get component blocks from the COMPONENTS input
const componentsInput = holderBlock.getInput('COMPONENTS');
if (componentsInput && componentsInput.connection) {
let componentBlock = componentsInput.connection.targetBlock();

// Walk through all connected component blocks
while (componentBlock) {
if (componentBlock.type === 'mrc_component') {
const componentName = componentBlock.getFieldValue('NAME');
const componentType = componentBlock.getFieldValue('TYPE');

if (componentName && componentType) {
// Get the blocks for this specific component
contents.push({
kind: 'category',
name: componentName,
contents: getBlocks(componentType, componentName),
});
}
}
// Move to the next block in the chain
componentBlock = componentBlock.getNextBlock();
}
}
});
}
return {
kind: 'category',
name: 'Components',
Expand Down