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
25 changes: 25 additions & 0 deletions server_python_scripts/blocks_base_classes/mechanism.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
# This is the class all mechanisms derive from

from typing import Callable

class Mechanism:
def __init__(self):
self.hardware = []
# In self.event_handlers, the keys are the event names, the values are a list of handlers.
self.event_handlers = {}

def register_event_handler(self, event_name: str, event_handler: Callable) -> None:
if event_name in self.event_handlers:
self.event_handlers[event_name].append(event_handler)
else:
self.event_handlers[event_name] = [event_handler]

def unregister_event_handler(self, event_name: str, event_handler: Callable) -> None:
if event_name in self.event_handlers:
if event_handler in self.event_handlers[event_name]:
self.event_handlers[event_name].remove(event_handler)
if not self.event_handlers[event_name]:
del self.event_handlers[event_name]

def fire_event(self, event_name: str, *args) -> None:
if event_name in self.event_handlers:
for event_handler in self.event_handlers[event_name]:
event_handler(*args)

def start(self) -> None:
for hardware in self.hardware:
hardware.start()

def update(self) -> None:
for hardware in self.hardware:
hardware.update()

def stop(self) -> None:
for hardware in self.hardware:
hardware.stop()
8 changes: 6 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
generatorContext.current.setModule(currentModule);
}
if (blocksEditor.current) {
blocksEditor.current.loadModuleBlocks(currentModule);
blocksEditor.current.loadModuleBlocks(currentModule, project);
}
}, [currentModule]);

Expand All @@ -436,11 +436,15 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
generatorContext.current.setModule(currentModule);
}

if (blocksEditor.current) {
blocksEditor.current.abandon();
}
blocksEditor.current = new editor.Editor(newWorkspace, generatorContext.current, storage);
blocksEditor.current.makeCurrent();

// Set the current module in the editor after creating it
if (currentModule) {
blocksEditor.current.loadModuleBlocks(currentModule);
blocksEditor.current.loadModuleBlocks(currentModule, project);
}

blocksEditor.current.updateToolbox(shownPythonToolboxCategories);
Expand Down
15 changes: 10 additions & 5 deletions src/blocks/mrc_call_python_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,8 @@ const CALL_PYTHON_FUNCTION = {
}
return components;
},
onLoad: function(this: CallPythonFunctionBlock): void {
// onLoad is called for each CallPythonFunctionBlock when the blocks are loaded in the blockly workspace.
mrcOnLoad: function(this: CallPythonFunctionBlock): void {
// mrcOnLoad is called for each CallPythonFunctionBlock when the blocks are loaded in the blockly workspace.
const warnings: string[] = [];

// If this block is calling a component method, check that the component
Expand All @@ -476,8 +476,13 @@ const CALL_PYTHON_FUNCTION = {
// visible warning on it.
if (this.mrcFunctionKind === FunctionKind.INSTANCE_COMPONENT) {
let foundComponent = false;
const components = this.getComponentsFromRobot();
for (const component of components) {
const componentsInScope: commonStorage.Component[] = [];
componentsInScope.push(...this.getComponentsFromRobot());
const editor = Editor.getEditorForBlocklyWorkspace(this.workspace);
if (editor && editor.getCurrentModuleType() === commonStorage.MODULE_TYPE_MECHANISM) {
componentsInScope.push(...editor.getComponentsFromWorkspace());
}
for (const component of componentsInScope) {
if (component.blockId === this.mrcOtherBlockId) {
foundComponent = true;

Expand All @@ -495,7 +500,7 @@ const CALL_PYTHON_FUNCTION = {
}
if (indexOfComponentName != -1) {
const componentNameChoices : string[] = [];
components.forEach(component => componentNameChoices.push(component.name));
componentsInScope.forEach(component => componentNameChoices.push(component.name));
titleInput.removeField(FIELD_COMPONENT_NAME);
titleInput.insertFieldAt(indexOfComponentName,
createFieldDropdown(componentNameChoices), FIELD_COMPONENT_NAME);
Expand Down
11 changes: 7 additions & 4 deletions src/blocks/mrc_class_method_def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ const CLASS_METHOD_DEF = {
this.updateBlock_();
},
/**
* Returns the state of this block as a JSON serializable object.
*/
* Returns the state of this block as a JSON serializable object.
*/
saveExtraState: function (
this: ClassMethodDefBlock): ClassMethodDefExtraState {
const extraState: ClassMethodDefExtraState = {
Expand Down Expand Up @@ -424,8 +424,11 @@ export const pythonFromBlock = function (

let params = block.mrcParameters;
let paramString = "self";
if (block.mrcPythonMethodName == '__init__') {
paramString += generator.getListOfPorts(false);
if (generator.getModuleType() == commonStorage.MODULE_TYPE_MECHANISM && block.mrcPythonMethodName == '__init__') {
const ports: string[] = generator.getComponentPortParameters();
if (ports.length) {
paramString += ', ' + ports.join(', ');
}
}

if (params.length != 0) {
Expand Down
27 changes: 14 additions & 13 deletions src/blocks/mrc_component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,13 @@ const COMPONENT = {
getComponent: function (this: ComponentBlock): commonStorage.Component | null {
const componentName = this.getFieldValue(FIELD_NAME);
const componentType = this.getFieldValue(FIELD_TYPE);
const ports: {[port: string]: string} = {};
this.getComponentPorts(ports);
return {
blockId: this.id,
name: componentName,
className: componentType,
ports: ports,
};
},
getNewPort: function (this: ComponentBlock, i: number): string {
Expand All @@ -153,14 +156,12 @@ const COMPONENT = {
}
return this.getFieldValue(FIELD_NAME) + extension + '_port';
},
getHardwarePorts: function (this: ComponentBlock, ports: {[key: string]: string}): void {
// Collect the hardware ports for this component block that are needed to generate
// the define_hardware method. (The key is the port, the value is the type.)
if (this.hideParams) {
for (let i = 0; i < this.mrcArgs.length; i++) {
const newPort = this.getNewPort(i);
ports[newPort] = this.mrcArgs[i].type;
}
getComponentPorts: function (this: ComponentBlock, ports: {[key: string]: string}): void {
// Collect the ports for this component block.
for (let i = 0; i < this.mrcArgs.length; i++) {
const newPort = this.getNewPort(i);
// The key is the port, the value is the type.
ports[newPort] = this.mrcArgs[i].type;
}
},
}
Expand Down Expand Up @@ -197,7 +198,7 @@ export const pythonFromBlock = function (
return code;
}

export function getAllPossibleComponents(hideParams: boolean): toolboxItems.ContentsType[] {
export function getAllPossibleComponents(moduleType: string): toolboxItems.ContentsType[] {
const contents: toolboxItems.ContentsType[] = [];
// Iterate through all the components subclasses and add definition blocks.
const componentTypes = getSubclassNames('component.Component');
Expand All @@ -215,7 +216,7 @@ export function getAllPossibleComponents(hideParams: boolean): toolboxItems.Cont

classData.staticMethods.forEach(staticFunctionData => {
if (staticFunctionData.returnType === componentType) {
contents.push(createComponentBlock(componentName, classData, staticFunctionData, hideParams));
contents.push(createComponentBlock(componentName, classData, staticFunctionData, moduleType));
}
});
});
Expand All @@ -224,12 +225,12 @@ export function getAllPossibleComponents(hideParams: boolean): toolboxItems.Cont
}

function createComponentBlock(
componentName: string, classData: ClassData, staticFunctionData: FunctionData, hideParams: boolean): toolboxItems.Block {
componentName: string, classData: ClassData, staticFunctionData: FunctionData, moduleType: string): toolboxItems.Block {
const extraState: ComponentExtraState = {
importModule: classData.moduleName,
staticFunctionName: staticFunctionData.functionName,
params: [],
hideParams: hideParams,
hideParams: (moduleType == commonStorage.MODULE_TYPE_MECHANISM),
};
const fields: {[key: string]: any} = {};
fields[FIELD_NAME] = componentName;
Expand All @@ -241,7 +242,7 @@ function createComponentBlock(
'name': argData.name,
'type': argData.type,
});
if (!hideParams) {
if (moduleType == commonStorage.MODULE_TYPE_ROBOT) {
if (argData.type === 'int') {
const portType = getPortTypeForArgument(argData.name);
if (portType) {
Expand Down
16 changes: 8 additions & 8 deletions src/blocks/mrc_event_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export type EventHandlerBlock = Blockly.Block & EventHandlerMixin & Blockly.Bloc

interface EventHandlerMixin extends EventHandlerMixinType {
mrcPathOfSender: string;
mrcTypeOfSender: SenderType;
mrcSenderType: SenderType;
mrcParameters: Parameter[];
mrcOtherBlockId: string,
}
Expand All @@ -63,7 +63,7 @@ type EventHandlerMixinType = typeof EVENT_HANDLER;
/** Extra state for serialising event handler blocks. */
export interface EventHandlerExtraState {
pathOfSender: string;
typeOfSender: SenderType;
senderType: SenderType;
/** The parameters of the event handler. */
params: Parameter[];
/** The id of the mrc_event block that defines the event. */
Expand Down Expand Up @@ -95,7 +95,7 @@ const EVENT_HANDLER = {
saveExtraState(this: EventHandlerBlock): EventHandlerExtraState {
const extraState: EventHandlerExtraState = {
pathOfSender: this.mrcPathOfSender,
typeOfSender: this.mrcTypeOfSender,
senderType: this.mrcSenderType,
params: [],
otherBlockId: this.mrcOtherBlockId,
};
Expand All @@ -115,7 +115,7 @@ const EVENT_HANDLER = {
*/
loadExtraState(this: EventHandlerBlock, extraState: EventHandlerExtraState): void {
this.mrcPathOfSender = extraState.pathOfSender;
this.mrcTypeOfSender = extraState.typeOfSender;
this.mrcSenderType = extraState.senderType;
this.mrcParameters = [];
this.mrcOtherBlockId = extraState.otherBlockId;

Expand Down Expand Up @@ -158,16 +158,16 @@ const EVENT_HANDLER = {
input.removeField(fieldName);
});
},
onLoad: function(this: EventHandlerBlock): void {
// onLoad is called for each EventHandlerBlock when the blocks are loaded in the blockly workspace.
mrcOnLoad: function(this: EventHandlerBlock): void {
// mrcOnLoad is called for each EventHandlerBlock when the blocks are loaded in the blockly workspace.
const warnings: string[] = [];

// If this block is an event handler for a robot event, check that the robot event
// still exists and hasn't been changed.
// If the robot event doesn't exist, put a visible warning on this block.
// If the robot event has changed, update the block if possible or put a
// visible warning on it.
if (this.mrcTypeOfSender === SenderType.ROBOT) {
if (this.mrcSenderType === SenderType.ROBOT) {
let foundRobotEvent = false;
const editor = Editor.getEditorForBlocklyWorkspace(this.workspace);
if (editor) {
Expand Down Expand Up @@ -301,7 +301,7 @@ function createRobotEventHandlerBlock(
const extraState: EventHandlerExtraState = {
// TODO(lizlooney): ask Alan what pathOfSender is for.
pathOfSender: '',
typeOfSender: SenderType.ROBOT,
senderType: SenderType.ROBOT,
params: [],
otherBlockId: event.blockId,
};
Expand Down
Loading