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
70 changes: 46 additions & 24 deletions src/blocks/mrc_event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import * as Blockly from 'blockly';
import { MRC_STYLE_EVENTS } from '../themes/styles'
import { ExtendedPythonGenerator } from '../editor/extended_python_generator';
import { MUTATOR_BLOCK_NAME, PARAM_CONTAINER_BLOCK_NAME, MethodMutatorArgBlock } from './mrc_param_container'
import * as ChangeFramework from './utils/change_framework';
import { BLOCK_NAME as MRC_MECHANISM_COMPONENT_HOLDER } from './mrc_mechanism_component_holder';
import * as toolboxItems from '../toolbox/items';
import * as storageModuleContent from '../storage/module_content';
Expand All @@ -33,13 +32,17 @@ import { renameMethodCallers, mutateMethodCallers } from './mrc_call_python_func
export const BLOCK_NAME = 'mrc_event';
export const OUTPUT_NAME = 'mrc_event';

const INPUT_TITLE = 'TITLE';
const FIELD_EVENT_NAME = 'NAME';
const FIELD_PARAM_PREFIX = 'PARAM_';

type Parameter = {
name: string,
type?: string,
};

const WARNING_ID_NOT_IN_HOLDER = 'not in holder';

type EventExtraState = {
eventId?: string,
params?: Parameter[],
Expand All @@ -50,6 +53,14 @@ export type EventBlock = Blockly.Block & EventMixin & Blockly.BlockSvg;
interface EventMixin extends EventMixinType {
mrcEventId: string,
mrcParameters: Parameter[],

/**
* mrcHasWarning is set to true if we set the warning text on the block. It is checked to avoid
* adding a warning if there already is one. Otherwise, if we get two move events (one for drag
* and one for snap), and we call setWarningText for both events, we get a detached warning
* balloon. See https://github.com/wpilibsuite/systemcore-blocks-interface/issues/248.
*/
mrcHasWarning: boolean,
}
type EventMixinType = typeof EVENT;

Expand All @@ -59,12 +70,11 @@ const EVENT = {
*/
init: function (this: EventBlock): void {
this.setStyle(MRC_STYLE_EVENTS);
this.appendDummyInput("TITLE")
this.appendDummyInput(INPUT_TITLE)
.appendField(new Blockly.FieldTextInput('my_event'), FIELD_EVENT_NAME);
this.setPreviousStatement(true, OUTPUT_NAME);
this.setNextStatement(true, OUTPUT_NAME);
this.setMutator(new Blockly.icons.MutatorIcon([MUTATOR_BLOCK_NAME], this));
ChangeFramework.registerCallback(BLOCK_NAME, [Blockly.Events.BLOCK_MOVE], this.onBlockChanged);
},

/**
Expand All @@ -91,6 +101,7 @@ const EVENT = {
loadExtraState: function (this: EventBlock, extraState: EventExtraState): void {
this.mrcEventId = extraState.eventId ? extraState.eventId : this.id;
this.mrcParameters = [];
this.mrcHasWarning = false;

if (extraState.params) {
extraState.params.forEach((arg) => {
Expand All @@ -108,7 +119,7 @@ const EVENT = {
*/
updateBlock_: function (this: EventBlock): void {
const name = this.getFieldValue(FIELD_EVENT_NAME);
const input = this.getInput('TITLE');
const input = this.getInput(INPUT_TITLE);
if (!input) {
return;
}
Expand Down Expand Up @@ -136,8 +147,7 @@ const EVENT = {
paramBlock.originalName = param.name;
}
this.mrcParameters.push(param);
paramBlock =
paramBlock.nextConnection && paramBlock.nextConnection.targetBlock();
paramBlock = paramBlock.nextConnection && paramBlock.nextConnection.targetBlock();
}
this.mrcUpdateParams();
mutateMethodCallers(this.workspace, this.mrcEventId, this.getEvent());
Expand All @@ -152,7 +162,7 @@ const EVENT = {
let connection = topBlock!.getInput('STACK')!.connection;

for (let i = 0; i < this.mrcParameters.length; i++) {
let itemBlock = workspace.newBlock(MUTATOR_BLOCK_NAME);
const itemBlock = workspace.newBlock(MUTATOR_BLOCK_NAME);
(itemBlock as Blockly.BlockSvg).initSvg();
itemBlock.setFieldValue(this.mrcParameters[i].name, 'NAME');
(itemBlock as MethodMutatorArgBlock).originalName = this.mrcParameters[i].name;
Expand All @@ -164,11 +174,11 @@ const EVENT = {
},
mrcUpdateParams: function (this: EventBlock) {
if (this.mrcParameters.length > 0) {
let input = this.getInput('TITLE');
const input = this.getInput(INPUT_TITLE);
if (input) {
this.removeParameterFields(input);
this.mrcParameters.forEach((param) => {
const paramName = 'PARAM_' + param.name;
const paramName = FIELD_PARAM_PREFIX + param.name;
const field = new Blockly.FieldTextInput(param.name);
field.EDITABLE = false;
input.appendField(field, paramName);
Expand All @@ -178,7 +188,7 @@ const EVENT = {
},
removeParameterFields: function (input: Blockly.Input) {
const fieldsToRemove = input.fieldRow
.filter(field => field.name?.startsWith('PARAM_'))
.filter(field => field.name?.startsWith(FIELD_PARAM_PREFIX))
.map(field => field.name!);

fieldsToRemove.forEach(fieldName => {
Expand All @@ -197,21 +207,33 @@ const EVENT = {
}
return legalName;
},
onBlockChanged(block: Blockly.BlockSvg, blockEvent: Blockly.Events.BlockBase): void {
const blockBlock = block as Blockly.Block;

if (blockEvent.type === Blockly.Events.BLOCK_MOVE) {
const parent = ChangeFramework.getParentOfType(block, MRC_MECHANISM_COMPONENT_HOLDER);

if (parent) {
// If it is, we allow it to stay.
blockBlock.setWarningText(null);
return;
/**
* mrcOnLoad is called for each EventBlock when the blocks are loaded in the blockly workspace.
*/
mrcOnLoad: function(this: EventBlock): void {
this.checkParentIsHolder();
},
/**
* mrcOnLoad is called when an EventBlock is moved.
*/
mrcOnMove: function(this: EventBlock): void {
this.checkParentIsHolder();
},
checkParentIsHolder: function(this: EventBlock): void {
const parentBlock = this.getParent();
if (parentBlock && parentBlock.type === MRC_MECHANISM_COMPONENT_HOLDER) {
// If the parent block is the mechanism_component_holder, the event block is allowed to stay.
// Remove any previous warning.
this.setWarningText(null, WARNING_ID_NOT_IN_HOLDER);
this.mrcHasWarning = false;
} else {
// Otherwise, add a warning to the block.
this.unplug(true);
if (!this.mrcHasWarning) {
this.setWarningText(Blockly.Msg.WARNING_EVENT_NOT_IN_HOLDER, WARNING_ID_NOT_IN_HOLDER);
this.getIcon(Blockly.icons.IconType.WARNING)!.setBubbleVisible(true);
this.mrcHasWarning = true;
}
// If we end up here it shouldn't be allowed
block.unplug(true);
blockBlock.setWarningText('Events can only go in the events section of the robot or mechanism');
blockBlock.getIcon(Blockly.icons.IconType.WARNING)!.setBubbleVisible(true);
}
},
getEvent: function (this: EventBlock): storageModuleContent.Event {
Expand Down
1 change: 1 addition & 0 deletions src/blocks/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export function customTokens(t: (key: string) => string): typeof Blockly.Msg {
CALL_COMPONENT_INSTANCE_METHOD_TOOLTIP: t('BLOCKLY.TOOLTIP.CALL_COMPONENT_INSTANCE_METHOD'),
CALL_ROBOT_INSTANCE_METHOD_TOOLTIP: t('BLOCKLY.TOOLTIP.CALL_ROBOT_INSTANCE_METHOD'),
CALL_MECHANISM_INSTANCE_METHOD_TOOLTIP: t('BLOCKLY.TOOLTIP.CALL_MECHANISM_INSTANCE_METHOD'),
WARNING_EVENT_NOT_IN_HOLDER: t('BLOCKLY.WARNING.EVENT_NOT_IN_HOLDER'),
MRC_CATEGORY_HARDWARE: t('BLOCKLY.CATEGORY.HARDWARE'),
MRC_CATEGORY_ROBOT: t('BLOCKLY.CATEGORY.ROBOT'),
MRC_CATEGORY_COMPONENTS: t('BLOCKLY.CATEGORY.COMPONENTS'),
Expand Down
13 changes: 12 additions & 1 deletion src/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const EMPTY_TOOLBOX: Blockly.utils.toolbox.ToolboxInfo = {
};

const MRC_ON_LOAD = 'mrcOnLoad';
const MRC_ON_MOVE = 'mrcOnMove';
const MRC_VALIDATE = 'mrcValidate';

export class Editor {
Expand Down Expand Up @@ -121,7 +122,17 @@ export class Editor {
if (this.blocklyWorkspace.isDragging()) {
return;
}
// TODO(lizlooney): do we need to do anything here?

if (event.type === Blockly.Events.BLOCK_MOVE) {
const blockMoveEvent = event as Blockly.Events.BlockMove;
const block = this.blocklyWorkspace.getBlockById(blockMoveEvent.blockId!);
if (!block) {
return;
}
if (MRC_ON_MOVE in block && typeof block[MRC_ON_MOVE] === 'function') {
block[MRC_ON_MOVE]();
}
}
}

public makeCurrent(
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@
"CALL_ROBOT_INSTANCE_METHOD_MISSING_METHOD": "This block calls a method that no longer exists in the robot.",
"CALL_MECHANISM_INSTANCE_METHOD_INSIDE_MECHANISM": "This block is not allowed to be used inside a mechanism.",
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_METHOD": "This block calls a method that no longer exists in the mechanism.",
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_MECHANISM": "This block calls a method in a mechanism that no longer exists."
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_MECHANISM": "This block calls a method in a mechanism that no longer exists.",
"EVENT_NOT_IN_HOLDER": "This block can only go in the events section of the robot or mechanism."
}
}
}
3 changes: 2 additions & 1 deletion src/i18n/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@
"CALL_ROBOT_INSTANCE_METHOD_MISSING_METHOD": "Este bloque llama a un método que ya no existe en el robot.",
"CALL_MECHANISM_INSTANCE_METHOD_INSIDE_MECHANISM": "No se permite utilizar este bloque dentro de un mecanismo.",
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_METHOD": "Este bloque llama a un método que ya no existe en el mecanismo.",
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_MECHANISM": "Este bloque llama a un método en un mecanismo que ya no existe."
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_MECHANISM": "Este bloque llama a un método en un mecanismo que ya no existe.",
"EVENT_NOT_IN_HOLDER": "Este bloque solo puede ir en la sección de eventos del robot o mecanismo."
}
}
}
3 changes: 2 additions & 1 deletion src/i18n/locales/he/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@
"CALL_ROBOT_INSTANCE_METHOD_MISSING_METHOD": "בלוק זה קורא למתודה שכבר לא קיימת ברובוט.",
"CALL_MECHANISM_INSTANCE_METHOD_INSIDE_MECHANISM": "בלוק זה אינו מורשה לשימוש בתוך מנגנון.",
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_METHOD": "בלוק זה קורא למתודה שכבר לא קיימת במנגנון.",
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_MECHANISM": "בלוק זה קורא למתודה במנגנון שכבר לא קיים."
"CALL_MECHANISM_INSTANCE_METHOD_MISSING_MECHANISM": "בלוק זה קורא למתודה במנגנון שכבר לא קיים.",
"EVENT_NOT_IN_HOLDER": "בלוק זה יכול להיכנס רק לאזור האירועים של הרובוט או המנגנון."
}
}
}