Skip to content

Commit 159e1bb

Browse files
authored
Make components real (#133)
* removed duplicate effect * Make components in mechanism "real" * Make toolbox update when mechanism_component holder changes
1 parent c4e2c3a commit 159e1bb

File tree

4 files changed

+97
-30
lines changed

4 files changed

+97
-30
lines changed

src/App.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import * as CustomBlocks from './blocks/setup_custom_blocks';
4242
import { initialize as initializePythonBlocks } from './blocks/utils/python';
4343
import * as ChangeFramework from './blocks/utils/change_framework'
4444
import { mutatorOpenListener } from './blocks/mrc_param_container'
45+
import { TOOLBOX_UPDATE_EVENT } from './blocks/mrc_mechanism_component_holder';
4546

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

257+
/** Handles toolbox update requests from blocks */
258+
const handleToolboxUpdateRequest = React.useCallback(() => {
259+
if (blocksEditor.current && currentModule) {
260+
blocksEditor.current.updateToolbox(shownPythonToolboxCategories);
261+
}
262+
}, [currentModule, shownPythonToolboxCategories]);
263+
264+
// Add event listener for toolbox updates
265+
React.useEffect(() => {
266+
window.addEventListener(TOOLBOX_UPDATE_EVENT, handleToolboxUpdateRequest);
267+
268+
return () => {
269+
window.removeEventListener(TOOLBOX_UPDATE_EVENT, handleToolboxUpdateRequest);
270+
};
271+
}, [handleToolboxUpdateRequest]);
272+
256273
// Initialize storage and blocks when app loads
257274
React.useEffect(() => {
258275
openStorage();
@@ -269,13 +286,6 @@ const App: React.FC = (): React.JSX.Element => {
269286
}
270287
}, [currentModule]);
271288

272-
// Update toolbox when shown categories change
273-
React.useEffect(() => {
274-
if (blocksEditor.current) {
275-
blocksEditor.current.updateToolbox(shownPythonToolboxCategories);
276-
}
277-
}, [shownPythonToolboxCategories]);
278-
279289
// Initialize Blockly workspace and editor when component and storage are ready
280290
React.useEffect(() => {
281291
if (!blocklyComponent.current || !storage) {

src/blocks/mrc_mechanism_component_holder.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export const BLOCK_NAME = 'mrc_mechanism_component_holder';
3737
export const MECHANISM = 'mechanism';
3838
export const COMPONENT = 'component';
3939

40+
export const TOOLBOX_UPDATE_EVENT = 'toolbox-update-requested';
41+
4042
type MechanismComponentHolderExtraState = {
4143
hideMechanisms?: boolean;
4244
}
@@ -115,17 +117,33 @@ const MECHANISM_COMPONENT_HOLDER = {
115117
let blockMoveEvent = blockEvent as Blockly.Events.BlockMove;
116118
if (blockMoveEvent.reason?.includes('connect')) {
117119
setName(block);
120+
updateToolboxAfterDelay();
118121
}
119122
}
120123
else {
121124
if (blockEvent.type == Blockly.Events.BLOCK_CHANGE) {
122125
setName(block);
126+
updateToolboxAfterDelay();
123127
}
124128
}
125129
},
126130

127131
}
128132

133+
let toolboxUpdateTimeout: NodeJS.Timeout | null = null;
134+
export function updateToolboxAfterDelay(){
135+
if (toolboxUpdateTimeout) {
136+
clearTimeout(toolboxUpdateTimeout);
137+
}
138+
toolboxUpdateTimeout = setTimeout(() => {
139+
const event = new CustomEvent(TOOLBOX_UPDATE_EVENT, {
140+
detail: { timestamp: Date.now() }
141+
});
142+
window.dispatchEvent(event);
143+
toolboxUpdateTimeout = null;
144+
}, 100);
145+
}
146+
129147
export const setup = function () {
130148
Blockly.Blocks[BLOCK_NAME] = MECHANISM_COMPONENT_HOLDER;
131149
}

src/toolbox/blocks_components.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,35 @@
1616
*/
1717

1818
/**
19-
* @author [email protected] (Alan Smith)
19+
* @fileoverview Component blocks for the toolbox.
2020
*/
21+
2122
import * as ToolboxItems from './items';
2223
import * as ColorSensor from './hardware_components/color_sensor';
2324
import * as SmartMotor from './hardware_components/smart_motor';
24-
import * as TouchSensor from './hardware_components/touch_sensor';
2525
import * as Servo from './hardware_components/servo';
26+
import * as TouchSensor from './hardware_components/touch_sensor';
27+
28+
const ALL_COMPONENTS: Record<string, (componentName: string) => ToolboxItems.ContentsType[]> = {
29+
[ColorSensor.TYPE_NAME]: ColorSensor.getBlocks,
30+
[SmartMotor.TYPE_NAME]: SmartMotor.getBlocks,
31+
[TouchSensor.TYPE_NAME]: TouchSensor.getBlocks,
32+
[Servo.TYPE_NAME]: Servo.getBlocks,
33+
};
34+
35+
export function getAllPossibleComponents(hideParams: boolean): ToolboxItems.ContentsType[] {
36+
return [
37+
SmartMotor.getDefinitionBlock(hideParams),
38+
TouchSensor.getDefinitionBlock(hideParams),
39+
ColorSensor.getDefinitionBlock(hideParams),
40+
Servo.getDefinitionBlock(hideParams),
41+
];
42+
}
2643

27-
export function getAllPossibleComponents(hideParams : boolean): ToolboxItems.ContentsType[] {
28-
return [
29-
SmartMotor.getDefinitionBlock(hideParams),
30-
TouchSensor.getDefinitionBlock(hideParams),
31-
ColorSensor.getDefinitionBlock(hideParams),
32-
Servo.getDefinitionBlock(hideParams),
33-
];
44+
export function getBlocks(componentType: string, componentName: string): ToolboxItems.ContentsType[] {
45+
const getBlocksFunction = ALL_COMPONENTS[componentType];
46+
if (getBlocksFunction) {
47+
return getBlocksFunction(componentName);
48+
}
49+
return [];
3450
}

src/toolbox/hardware_category.ts

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ import * as Blockly from 'blockly/core';
2929
import * as toolboxItems from './items';
3030
import * as commonStorage from '../storage/common_storage';
3131
import { getAllPossibleMechanisms } from './blocks_mechanisms';
32-
import { getAllPossibleComponents } from './blocks_components';
33-
import * as SmartMotor from './hardware_components/smart_motor';
34-
import * as TouchSensor from './hardware_components/touch_sensor';
32+
import { getAllPossibleComponents, getBlocks } from './blocks_components';
33+
import * as MechanismComponentHolder from '../blocks/mrc_mechanism_component_holder';
3534

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

244243
function getComponentsBlocks(currentModule: commonStorage.Module) {
245244
const contents = [];
245+
246+
// Add the "+ Component" category
246247
contents.push({
247248
kind: 'category',
248249
name: '+ Component',
249250
contents: getAllPossibleComponents(true)
250251
});
251-
contents.push({
252-
kind: 'category',
253-
name: 'my_motor',
254-
contents: SmartMotor.getBlocks('my_motor')
255-
},
256-
{
257-
kind: 'category',
258-
name: 'my_touch_sensor',
259-
contents: TouchSensor.getBlocks('my_touch_sensor')
260-
},
261-
);
252+
253+
// Get components from the current workspace
254+
const workspace = Blockly.getMainWorkspace();
255+
if (workspace) {
256+
const holderBlocks = workspace.getBlocksByType(MechanismComponentHolder.BLOCK_NAME);
257+
258+
holderBlocks.forEach(holderBlock => {
259+
// Get component blocks from the COMPONENTS input
260+
const componentsInput = holderBlock.getInput('COMPONENTS');
261+
if (componentsInput && componentsInput.connection) {
262+
let componentBlock = componentsInput.connection.targetBlock();
263+
264+
// Walk through all connected component blocks
265+
while (componentBlock) {
266+
if (componentBlock.type === 'mrc_component') {
267+
const componentName = componentBlock.getFieldValue('NAME');
268+
const componentType = componentBlock.getFieldValue('TYPE');
269+
270+
if (componentName && componentType) {
271+
// Get the blocks for this specific component
272+
contents.push({
273+
kind: 'category',
274+
name: componentName,
275+
contents: getBlocks(componentType, componentName),
276+
});
277+
}
278+
}
279+
// Move to the next block in the chain
280+
componentBlock = componentBlock.getNextBlock();
281+
}
282+
}
283+
});
284+
}
262285
return {
263286
kind: 'category',
264287
name: 'Components',

0 commit comments

Comments
 (0)