Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,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 { registerToolboxButton } from './blocks/mrc_event_handler'
import { mutatorOpenListener } from './blocks/mrc_param_container'
import { TOOLBOX_UPDATE_EVENT } from './blocks/mrc_mechanism_component_holder';
import { antdThemeFromString } from './reactComponents/ThemeModal';
Expand Down Expand Up @@ -432,6 +433,9 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
ChangeFramework.setup(newWorkspace);
newWorkspace.addChangeListener(mutatorOpenListener);
newWorkspace.addChangeListener(handleBlocksChanged);

registerToolboxButton(newWorkspace, messageApi);

generatorContext.current = createGeneratorContext();

if (currentModule) {
Expand Down
43 changes: 40 additions & 3 deletions src/blocks/mrc_event_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import * as Blockly from 'blockly';
import {Order} from 'blockly/python';

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

export const BLOCK_NAME = 'mrc_event_handler';

const BUTTON_CALLBACK_KEY = 'EVENT_HANDLER_ALREADY_ON_WORKSPACE';
const BUTTON_STYLE = 'eventHandlerButtonStyle';

const FIELD_SENDER = 'SENDER';
const FIELD_EVENT_NAME = 'EVENT_NAME';

Expand All @@ -48,6 +52,7 @@ export interface Parameter {
type?: string;
}

const SENDER_VALUE_ROBOT = 'robot';
const WARNING_ID_EVENT_CHANGED = 'event changed';

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

export function addRobotEventHandlerBlocks(
events: storageModuleContent.Event[],
eventHandlerBlocks: EventHandlerBlock[],
contents: toolboxItems.ContentsType[]) {
// Collect the ids of events for which there is already an event handler.
const eventIds: string[] = [];
eventHandlerBlocks.forEach(eventHandlerBlock => {
eventIds.push(eventHandlerBlock.getEventId());
});
events.forEach(event => {
contents.push(createRobotEventHandlerBlock(event));
if (eventIds.includes(event.eventId)) {
// If there is already an event handler for this event, put a button in the toolbox.
const text = '\u00A0\u00A0when\u00A0\u00A0' + SENDER_VALUE_ROBOT + '\u00A0\u00A0' + event.name + '\u00A0\u00A0';
const button = new toolboxItems.Button(text, BUTTON_CALLBACK_KEY, BUTTON_STYLE);
contents.push(button);
} else {
contents.push(createRobotEventHandlerBlock(event));
}
});
}

Expand All @@ -425,7 +443,7 @@ function createRobotEventHandlerBlock(
});
});
const fields: {[key: string]: any} = {};
fields[FIELD_SENDER] = 'robot';
fields[FIELD_SENDER] = SENDER_VALUE_ROBOT;
fields[FIELD_EVENT_NAME] = event.name;
const inputs: {[key: string]: any} = {};
return new toolboxItems.Block(BLOCK_NAME, extraState, fields, Object.keys(inputs).length ? inputs : null);
Expand All @@ -434,9 +452,22 @@ function createRobotEventHandlerBlock(
export function addMechanismEventHandlerBlocks(
mechanismInRobot: storageModuleContent.MechanismInRobot,
events: storageModuleContent.Event[],
eventHandlerBlocks: EventHandlerBlock[],
contents: toolboxItems.ContentsType[]) {
// Collect the ids of events for which there is already an event handler.
const eventIds: string[] = [];
eventHandlerBlocks.forEach(eventHandlerBlock => {
eventIds.push(eventHandlerBlock.getEventId());
});
events.forEach(event => {
contents.push(createMechanismEventHandlerBlock(mechanismInRobot, event));
if (eventIds.includes(event.eventId)) {
// If there is already an event handler for this event, put a button in the toolbox.
const text = 'when ' + mechanismInRobot.name + ' ' + event.name;
const button = new toolboxItems.Button(text, BUTTON_CALLBACK_KEY, BUTTON_STYLE);
contents.push(button);
} else {
contents.push(createMechanismEventHandlerBlock(mechanismInRobot, event));
}
});
}

Expand Down Expand Up @@ -502,3 +533,9 @@ export function renameMechanismName(workspace: Blockly.Workspace, mechanismId: s
(block as EventHandlerBlock).renameMechanismName(mechanismId, newName);
});
}

export function registerToolboxButton(workspace: Blockly.WorkspaceSvg, messageApi: MessageInstance) {
workspace.registerButtonCallback(BUTTON_CALLBACK_KEY, function (_button) {
messageApi.info(Blockly.Msg.EVENT_HANDLER_ALREADY_ON_WORKSPACE);
});
}
2 changes: 2 additions & 0 deletions src/blocks/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export function customTokens(t: (key: string) => string): typeof Blockly.Msg {
PARAMETER: t('BLOCKLY.PARAMETER'),
PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK:
t('BLOCKLY.PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK'),
EVENT_HANDLER_ALREADY_ON_WORKSPACE:
t('BLOCKLY.EVENT_HANDLER_ALREADY_ON_WORKSPACE'),
MECHANISMS: t('MECHANISMS'),
OPMODES: t('OPMODES'),
COMPONENTS: t('BLOCKLY.COMPONENTS'),
Expand Down
1 change: 1 addition & 0 deletions src/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export class Editor {
private clearBlocklyWorkspace() {
if (this.bindedOnChange) {
this.blocklyWorkspace.removeChangeListener(this.bindedOnChange);
this.bindedOnChange = null;
}
this.blocklyWorkspace.hideChaff();
this.blocklyWorkspace.clear();
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"WHEN": "when",
"PARAMETER": "parameter",
"PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK": "Parameters can only go in their method's block",
"EVENT_HANDLER_ALREADY_ON_WORKSPACE": "This event handler is already on the workspace.",
"COMPONENTS": "Components",
"EVENTS": "Events",
"EVALUATE_BUT_IGNORE_RESULT": "evaluate but ignore result",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"WHEN": "cuando",
"PARAMETER": "parámetro",
"PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK": "Los parámetros solo pueden ir en el bloque de su método",
"EVENT_HANDLER_ALREADY_ON_WORKSPACE": "Este controlador de eventos ya está en el área de trabajo.",
"COMPONENTS": "Componentes",
"EVENTS": "Eventos",
"EVALUATE_BUT_IGNORE_RESULT": "evaluar pero ignorar resultado",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/he/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"WHEN": "כאשר",
"PARAMETER": "פרמטר",
"PARAMETERS_CAN_ONLY_GO_IN_THEIR_METHODS_BLOCK": "פרמטרים יכולים להיכנס רק בבלוק השיטה שלהם",
"EVENT_HANDLER_ALREADY_ON_WORKSPACE": "מטפל אירועים זה כבר נמצא בסביבת העבודה.",
"COMPONENTS": "רכיבים",
"EVENTS": "אירועים",
"EVALUATE_BUT_IGNORE_RESULT": "הערך אך התעלם מהתוצאה",
Expand Down
6 changes: 5 additions & 1 deletion src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,8 @@ code {
/* Ensure smooth scrolling for the entire toolbox content */
.blocklyToolboxContents {
scroll-behavior: smooth !important;
}
}

.eventHandlerButtonStyle {
fill: #995ba5;
}
21 changes: 3 additions & 18 deletions src/toolbox/event_handlers_category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,8 @@ class EventHandlersCategory {

// Get the list of events from the robot.
const eventsFromRobot = editor.getEventsFromRobot();
// Remove events if there is already a corresponding handler in the workspace.
const eventHandlerBlocks = editor.getRobotEventHandlersAlreadyInWorkspace();
const eventIds: string[] = [];
eventHandlerBlocks.forEach(eventHandlerBlock => {
eventIds.push(eventHandlerBlock.getEventId());
});
const eventsToShow = eventsFromRobot.filter(event => {
return !eventIds.includes(event.eventId);
});
addRobotEventHandlerBlocks(eventsToShow, contents);
addRobotEventHandlerBlocks(eventsFromRobot, eventHandlerBlocks, contents);

const toolboxInfo = {
contents: contents,
Expand All @@ -129,17 +121,10 @@ class EventHandlersCategory {
const mechanism = editor.getMechanism(this.mechanismInRobot);
if (mechanism) {
const eventsFromMechanism = editor.getEventsFromMechanism(mechanism);
// Remove events if there is already a corresponding handler in the workspace.
const eventHandlerBlocks = editor.getMechanismEventHandlersAlreadyInWorkspace(
this.mechanismInRobot);
const eventIds: string[] = [];
eventHandlerBlocks.forEach(eventHandlerBlock => {
eventIds.push(eventHandlerBlock.getEventId());
});
const eventsToShow = eventsFromMechanism.filter(event => {
return !eventIds.includes(event.eventId);
});
addMechanismEventHandlerBlocks(this.mechanismInRobot, eventsToShow, contents);
addMechanismEventHandlerBlocks(
this.mechanismInRobot, eventsFromMechanism, eventHandlerBlocks, contents);
if (contents.length === 0) {
const label : toolboxItems.Label = new toolboxItems.Label(Blockly.Msg['NO_MECHANISM_CONTENTS']);
contents.push(label);
Expand Down
38 changes: 17 additions & 21 deletions src/toolbox/hardware_category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,29 @@ import {
addInstanceMechanismBlocks } from '../blocks/mrc_call_python_function';
import { Editor } from '../editor/editor';

export function getHardwareCategory(
editor: Editor): toolboxItems.Category {

export function getHardwareCategory(editor: Editor): toolboxItems.Category {
const moduleType = editor.getCurrentModuleType();
switch (moduleType) {
case storageModule.ModuleType.ROBOT:
return {
kind: 'category',
name: Blockly.Msg['MRC_CATEGORY_HARDWARE'],
contents: [
getRobotMechanismsCategory(editor),
getComponentsCategory(editor, moduleType),
],
};
return new toolboxItems.Category(
Blockly.Msg['MRC_CATEGORY_HARDWARE'],
[
getRobotMechanismsCategory(editor),
getComponentsCategory(editor, moduleType),
],
toolboxItems.ExpandedState.EXPANDED);
case storageModule.ModuleType.MECHANISM:
return getComponentsCategory(editor, moduleType);
case storageModule.ModuleType.OPMODE:
return {
kind: 'category',
name: Blockly.Msg['MRC_CATEGORY_ROBOT'],
contents: [
getRobotMechanismsCategory(editor),
getRobotComponentsCategory(editor),
getRobotMethodsCategory(editor),
getRobotEventHandlersCategory(editor),
],
};
return new toolboxItems.Category(
Blockly.Msg['MRC_CATEGORY_ROBOT'],
[
getRobotMechanismsCategory(editor),
getRobotComponentsCategory(editor),
getRobotMethodsCategory(editor),
getRobotEventHandlersCategory(editor),
],
toolboxItems.ExpandedState.EXPANDED);
}
throw new Error('moduleType has unexpected value: ' + moduleType);
}
Expand Down
71 changes: 51 additions & 20 deletions src/toolbox/items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,39 @@ export class Item {
}
}

// TODO(lizlooney): Use new toolboxItems.Sep() to create separators in other files.

export class Sep extends Item {
constructor() {
super('sep');
}
}

// TODO(lizlooney): Use new toolboxItems.Label() to create labels in other files.

export class Label extends Item {
text: string;

constructor(text: string) {
constructor(text: string, webClass?: string) {
super('label');
this.text = text;
if (webClass) {
(this as any)['web-class'] = webClass;
}
}
}

export class Button extends Item {
text: string;
callbackkey: string;

constructor(text: string, callbackkey: string, webClass?: string) {
super('button');
this.text = text;
this.callbackkey = callbackkey;
if (webClass) {
(this as any)['web-class'] = webClass;
}
}
}

Expand Down Expand Up @@ -68,23 +89,34 @@ export class Block extends Item {
}
}

export type ContentsType = Sep | Label | Block | Category;
export type ContentsType = Sep | Label | Button | Block | Category;

export enum ExpandedState {
COLLAPSED,
EXPANDED,
}

// TODO(lizlooney): Use new toolboxItems.Category() to create categories in other files.

export class Category extends Item {
/** The category name. */
name: string;
expanded?: boolean;
categorystyle?: string;
custom?: string;

/** The blocks for this category. */
contents?: ContentsType[] = [];

constructor(name: string, contents: ContentsType[], categorystyle?: string, custom?: string) {
constructor(name: string, contents: ContentsType[], expandedState?: ExpandedState, categorystyle?: string, custom?: string) {
super('category');
this.name = name;
if (contents) {
this.contents = contents;
}
if (expandedState === ExpandedState.EXPANDED) {
this.expanded = true;
}
if (categorystyle) {
this.categorystyle = categorystyle;
}
Expand All @@ -97,30 +129,29 @@ export class Category extends Item {
export class PythonModuleCategory extends Category {
moduleName: string;

constructor(moduleName: string, name: string, contents: ContentsType[], categorystyle?: string, custom?: string) {
super(name, contents);
if (categorystyle) {
this.categorystyle = categorystyle;
}
if (custom) {
this.custom = custom;
}
constructor(
moduleName: string,
name: string,
contents: ContentsType[],
expandedState?: ExpandedState,
categorystyle?: string,
custom?: string) {
super(name, contents, expandedState, categorystyle, custom);
this.moduleName = moduleName;
}
}

export class PythonClassCategory extends Category {
className: string;

constructor(className: string, name: string, contents: ContentsType[]);
constructor(className: string, name: string, contents: ContentsType[], categorystyle?: string, custom?: string) {
super(name, contents);
if (categorystyle) {
this.categorystyle = categorystyle;
}
if (custom) {
this.custom = custom;
}
constructor(
className: string,
name: string,
contents: ContentsType[],
expandedState?: ExpandedState,
categorystyle?: string,
custom?: string) {
super(name, contents, expandedState, categorystyle, custom);
this.className = className;
}
}
Loading