Skip to content

Commit da56a34

Browse files
committed
Added class Button to toolbox/items.ts.
Added support for making a category initially expanded. Cleaned up other classes in toolbox/items.ts. Modified getHardwareCategory in toolbox/hardware_category.ts so the Hardware or Robot category are initially expanded. Modified getToolboxJSON in toolbox/toolbox.ts so it prevent a problem with blockly choking on our Category class. Modified code that puts event handler blocks in the toolbox so that if an event handler is already on the workspace, a button for that event is put in the toolbox. If the user hits the button, an info message tells the user that the event handler is already on the workspace.
1 parent 93d41f0 commit da56a34

File tree

12 files changed

+145
-85
lines changed

12 files changed

+145
-85
lines changed

src/App.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import * as CustomBlocks from './blocks/setup_custom_blocks';
4646

4747
import { initialize as initializePythonBlocks } from './blocks/utils/python';
4848
import * as ChangeFramework from './blocks/utils/change_framework'
49+
import { registerToolboxButton } from './blocks/mrc_event_handler'
4950
import { mutatorOpenListener } from './blocks/mrc_param_container'
5051
import { TOOLBOX_UPDATE_EVENT } from './blocks/mrc_mechanism_component_holder';
5152
import { antdThemeFromString } from './reactComponents/ThemeModal';
@@ -432,6 +433,9 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
432433
ChangeFramework.setup(newWorkspace);
433434
newWorkspace.addChangeListener(mutatorOpenListener);
434435
newWorkspace.addChangeListener(handleBlocksChanged);
436+
437+
registerToolboxButton(newWorkspace, messageApi);
438+
435439
generatorContext.current = createGeneratorContext();
436440

437441
if (currentModule) {

src/blocks/mrc_event_handler.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import * as Blockly from 'blockly';
2424
import {Order} from 'blockly/python';
2525

26+
import type { MessageInstance } from 'antd/es/message/interface';
2627
import { Editor } from '../editor/editor';
2728
import { ExtendedPythonGenerator } from '../editor/extended_python_generator';
2829
import { createFieldFlydown } from '../fields/field_flydown';
@@ -34,6 +35,9 @@ import * as storageModuleContent from '../storage/module_content';
3435

3536
export const BLOCK_NAME = 'mrc_event_handler';
3637

38+
const BUTTON_CALLBACK_KEY = 'EVENT_HANDLER_ALREADY_ON_WORKSPACE';
39+
const BUTTON_STYLE = 'eventHandlerButtonStyle';
40+
3741
const FIELD_SENDER = 'SENDER';
3842
const FIELD_EVENT_NAME = 'EVENT_NAME';
3943

@@ -48,6 +52,7 @@ export interface Parameter {
4852
type?: string;
4953
}
5054

55+
const SENDER_VALUE_ROBOT = 'robot';
5156
const WARNING_ID_EVENT_CHANGED = 'event changed';
5257

5358
export type EventHandlerBlock = Blockly.Block & EventHandlerMixin & Blockly.BlockSvg;
@@ -405,9 +410,22 @@ function generateRegisterEventHandler(
405410

406411
export function addRobotEventHandlerBlocks(
407412
events: storageModuleContent.Event[],
413+
eventHandlerBlocks: EventHandlerBlock[],
408414
contents: toolboxItems.ContentsType[]) {
415+
// Collect the ids of events for which there is already an event handler.
416+
const eventIds: string[] = [];
417+
eventHandlerBlocks.forEach(eventHandlerBlock => {
418+
eventIds.push(eventHandlerBlock.getEventId());
419+
});
409420
events.forEach(event => {
410-
contents.push(createRobotEventHandlerBlock(event));
421+
if (eventIds.includes(event.eventId)) {
422+
// If there is already an event handler for this event, put a button in the toolbox.
423+
const text = '\u00A0\u00A0when\u00A0\u00A0' + SENDER_VALUE_ROBOT + '\u00A0\u00A0' + event.name + '\u00A0\u00A0';
424+
const button = new toolboxItems.Button(text, BUTTON_CALLBACK_KEY, BUTTON_STYLE);
425+
contents.push(button);
426+
} else {
427+
contents.push(createRobotEventHandlerBlock(event));
428+
}
411429
});
412430
}
413431

@@ -425,7 +443,7 @@ function createRobotEventHandlerBlock(
425443
});
426444
});
427445
const fields: {[key: string]: any} = {};
428-
fields[FIELD_SENDER] = 'robot';
446+
fields[FIELD_SENDER] = SENDER_VALUE_ROBOT;
429447
fields[FIELD_EVENT_NAME] = event.name;
430448
const inputs: {[key: string]: any} = {};
431449
return new toolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
@@ -434,9 +452,22 @@ function createRobotEventHandlerBlock(
434452
export function addMechanismEventHandlerBlocks(
435453
mechanismInRobot: storageModuleContent.MechanismInRobot,
436454
events: storageModuleContent.Event[],
455+
eventHandlerBlocks: EventHandlerBlock[],
437456
contents: toolboxItems.ContentsType[]) {
457+
// Collect the ids of events for which there is already an event handler.
458+
const eventIds: string[] = [];
459+
eventHandlerBlocks.forEach(eventHandlerBlock => {
460+
eventIds.push(eventHandlerBlock.getEventId());
461+
});
438462
events.forEach(event => {
439-
contents.push(createMechanismEventHandlerBlock(mechanismInRobot, event));
463+
if (eventIds.includes(event.eventId)) {
464+
// If there is already an event handler for this event, put a button in the toolbox.
465+
const text = 'when ' + mechanismInRobot.name + ' ' + event.name;
466+
const button = new toolboxItems.Button(text, BUTTON_CALLBACK_KEY, BUTTON_STYLE);
467+
contents.push(button);
468+
} else {
469+
contents.push(createMechanismEventHandlerBlock(mechanismInRobot, event));
470+
}
440471
});
441472
}
442473

@@ -502,3 +533,9 @@ export function renameMechanismName(workspace: Blockly.Workspace, mechanismId: s
502533
(block as EventHandlerBlock).renameMechanismName(mechanismId, newName);
503534
});
504535
}
536+
537+
export function registerToolboxButton(workspace: Blockly.WorkspaceSvg, messageApi: MessageInstance) {
538+
workspace.registerButtonCallback(BUTTON_CALLBACK_KEY, function (_button) {
539+
messageApi.info(Blockly.Msg.EVENT_HANDLER_ALREADY_ON_WORKSPACE);
540+
});
541+
}

src/blocks/tokens.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export function customTokens(t: (key: string) => string): typeof Blockly.Msg {
3535
PARAMETER: t('BLOCKLY.PARAMETER'),
3636
PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK:
3737
t('BLOCKLY.PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK'),
38+
EVENT_HANDLER_ALREADY_ON_WORKSPACE:
39+
t('BLOCKLY.EVENT_HANDLER_ALREADY_ON_WORKSPACE'),
3840
MECHANISMS: t('MECHANISMS'),
3941
OPMODES: t('OPMODES'),
4042
COMPONENTS: t('BLOCKLY.COMPONENTS'),

src/editor/editor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ export class Editor {
174174
private clearBlocklyWorkspace() {
175175
if (this.bindedOnChange) {
176176
this.blocklyWorkspace.removeChangeListener(this.bindedOnChange);
177+
this.bindedOnChange = null;
177178
}
178179
this.blocklyWorkspace.hideChaff();
179180
this.blocklyWorkspace.clear();

src/i18n/locales/en/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"WHEN": "when",
4646
"PARAMETER": "parameter",
4747
"PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK": "Parameters can only go in their method's block",
48+
"EVENT_HANDLER_ALREADY_ON_WORKSPACE": "This event handler is already on the workspace.",
4849
"COMPONENTS": "Components",
4950
"EVENTS": "Events",
5051
"EVALUATE_BUT_IGNORE_RESULT": "evaluate but ignore result",

src/i18n/locales/es/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"WHEN": "cuando",
4747
"PARAMETER": "parámetro",
4848
"PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK": "Los parámetros solo pueden ir en el bloque de su método",
49+
"EVENT_HANDLER_ALREADY_ON_WORKSPACE": "Este controlador de eventos ya está en el área de trabajo.",
4950
"COMPONENTS": "Componentes",
5051
"EVENTS": "Eventos",
5152
"EVALUATE_BUT_IGNORE_RESULT": "evaluar pero ignorar resultado",

src/i18n/locales/he/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"WHEN": "כאשר",
4646
"PARAMETER": "פרמטר",
4747
"PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK": "פרמטרים יכולים להיכנס רק בבלוק השיטה שלהם",
48+
"EVENT_HANDLER_ALREADY_ON_WORKSPACE": "מטפל אירועים זה כבר נמצא בסביבת העבודה.",
4849
"COMPONENTS": "רכיבים",
4950
"EVENTS": "אירועים",
5051
"EVALUATE_BUT_IGNORE_RESULT": "הערך אך התעלם מהתוצאה",

src/index.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ code {
6161
/* Ensure smooth scrolling for the entire toolbox content */
6262
.blocklyToolboxContents {
6363
scroll-behavior: smooth !important;
64-
}
64+
}
65+
66+
.eventHandlerButtonStyle {
67+
fill: #995ba5;
68+
}

src/toolbox/event_handlers_category.ts

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,8 @@ class EventHandlersCategory {
9696

9797
// Get the list of events from the robot.
9898
const eventsFromRobot = editor.getEventsFromRobot();
99-
// Remove events if there is already a corresponding handler in the workspace.
10099
const eventHandlerBlocks = editor.getRobotEventHandlersAlreadyInWorkspace();
101-
const eventIds: string[] = [];
102-
eventHandlerBlocks.forEach(eventHandlerBlock => {
103-
eventIds.push(eventHandlerBlock.getEventId());
104-
});
105-
const eventsToShow = eventsFromRobot.filter(event => {
106-
return !eventIds.includes(event.eventId);
107-
});
108-
addRobotEventHandlerBlocks(eventsToShow, contents);
100+
addRobotEventHandlerBlocks(eventsFromRobot, eventHandlerBlocks, contents);
109101

110102
const toolboxInfo = {
111103
contents: contents,
@@ -129,17 +121,10 @@ class EventHandlersCategory {
129121
const mechanism = editor.getMechanism(this.mechanismInRobot);
130122
if (mechanism) {
131123
const eventsFromMechanism = editor.getEventsFromMechanism(mechanism);
132-
// Remove events if there is already a corresponding handler in the workspace.
133124
const eventHandlerBlocks = editor.getMechanismEventHandlersAlreadyInWorkspace(
134125
this.mechanismInRobot);
135-
const eventIds: string[] = [];
136-
eventHandlerBlocks.forEach(eventHandlerBlock => {
137-
eventIds.push(eventHandlerBlock.getEventId());
138-
});
139-
const eventsToShow = eventsFromMechanism.filter(event => {
140-
return !eventIds.includes(event.eventId);
141-
});
142-
addMechanismEventHandlerBlocks(this.mechanismInRobot, eventsToShow, contents);
126+
addMechanismEventHandlerBlocks(
127+
this.mechanismInRobot, eventsFromMechanism, eventHandlerBlocks, contents);
143128
if (contents.length === 0) {
144129
const label : toolboxItems.Label = new toolboxItems.Label(Blockly.Msg['NO_MECHANISM_CONTENTS']);
145130
contents.push(label);

src/toolbox/hardware_category.ts

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,33 +31,29 @@ import {
3131
addInstanceMechanismBlocks } from '../blocks/mrc_call_python_function';
3232
import { Editor } from '../editor/editor';
3333

34-
export function getHardwareCategory(
35-
editor: Editor): toolboxItems.Category {
36-
34+
export function getHardwareCategory(editor: Editor): toolboxItems.Category {
3735
const moduleType = editor.getCurrentModuleType();
3836
switch (moduleType) {
3937
case storageModule.ModuleType.ROBOT:
40-
return {
41-
kind: 'category',
42-
name: Blockly.Msg['MRC_CATEGORY_HARDWARE'],
43-
contents: [
44-
getRobotMechanismsCategory(editor),
45-
getComponentsCategory(editor, moduleType),
46-
],
47-
};
38+
return new toolboxItems.Category(
39+
Blockly.Msg['MRC_CATEGORY_HARDWARE'],
40+
[
41+
getRobotMechanismsCategory(editor),
42+
getComponentsCategory(editor, moduleType),
43+
],
44+
toolboxItems.ExpandedState.EXPANDED);
4845
case storageModule.ModuleType.MECHANISM:
4946
return getComponentsCategory(editor, moduleType);
5047
case storageModule.ModuleType.OPMODE:
51-
return {
52-
kind: 'category',
53-
name: Blockly.Msg['MRC_CATEGORY_ROBOT'],
54-
contents: [
55-
getRobotMechanismsCategory(editor),
56-
getRobotComponentsCategory(editor),
57-
getRobotMethodsCategory(editor),
58-
getRobotEventHandlersCategory(editor),
59-
],
60-
};
48+
return new toolboxItems.Category(
49+
Blockly.Msg['MRC_CATEGORY_ROBOT'],
50+
[
51+
getRobotMechanismsCategory(editor),
52+
getRobotComponentsCategory(editor),
53+
getRobotMethodsCategory(editor),
54+
getRobotEventHandlersCategory(editor),
55+
],
56+
toolboxItems.ExpandedState.EXPANDED);
6157
}
6258
throw new Error('moduleType has unexpected value: ' + moduleType);
6359
}

0 commit comments

Comments
 (0)