Skip to content

Commit 1a2c638

Browse files
authored
Remove change framework (#277)
* Change indentation from 4 spaces to 2 spaces. * Add Parameters string to i18n. mrc_param_container.ts: Add constants INPUT_STACK and FIELD_NAME. mrc_class_method_def.ts: Add constants INPUT_TITLE, FIELD_PARAM_REFIX, and INPUT_STACK. Renamed constant RETURN_VALUE to INPUT_RETURN. * mrc_param_container.ts: Replaced mutatorOpenListener function (a blockly change listener) with onMutatorOpen function, which is is called only for mutator open events on mrc_class_method_def and mrc_event blocks. mrc_class_method_def.ts and mrc_event.ts: Added mrcOnMutatorOpen method, which calls onMutatorOpen in mrc_param_container. editor.ts: Added code to handle the BubbleOpenEvent for a mutator and call mrcOnMutatorOpen on the block. App.tsx: Removed code that adds mutatorOpenListener to each blockly workspace. * Added function getMutatorIcon to mrc_param_container.ts. Call getMutatorIcon from mrc_class_method_def.ts and mrc_event.ts. * Added function createMutatorBlocks to mrc_param_container.ts Call createMutatorBlocks from EventBlock.decompose and ClassMethodDefBlock.decompose. * mrc_param_container.ts: Renamed METHOD_PARAM_CONTAINER to PARAM_CONTAINER. Added type ParamContainerBlock, interface ParamContainerMixin, and type ParamContainerMixinType. Added getParamItemBlocks function to ParamContainerBlock. Renamed MUTATOR_BLOCK_NAME to PARAM_ITEM_BLOCK_NAME. Renamed METHODS_MUTATORARG to PARAM_ITEM. Renamed MethodMutatorArgBlock to ParamItemBlock. Renamed MethodMutatorArgMixin to ParamItemMixin. Renamed MethodMutatorArgMixinType to ParamItemMixinType Added getName, getOriginalName, and setOriginalName functions to ParamItemBlock. mrc_event.ts and mrc_class_method_def.ts: Modified EventBlock.compose and ClassMethodDefBlock.compose to call getParamItemBlocks on the container block and then call getName, getOriginalName, and setOriginalName on each ParamItemBlock. * Replaced function setName with method ParamItemBlock.makeNameLegal. Changed function updateMutatorFlyout to use forEach loop. Renamed local variable argValue to uniqueName. * Use a normal blockly change listener instead of change_framework.ts.
1 parent 06b177f commit 1a2c638

File tree

11 files changed

+244
-269
lines changed

11 files changed

+244
-269
lines changed

src/App.tsx

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

4747
import { initialize as initializePythonBlocks } from './blocks/utils/python';
4848
import { registerToolboxButton } from './blocks/mrc_event_handler'
49-
import { mutatorOpenListener } from './blocks/mrc_param_container'
5049
import { TOOLBOX_UPDATE_EVENT } from './blocks/mrc_mechanism_component_holder';
5150
import { antdThemeFromString } from './reactComponents/ThemeModal';
5251
import { useTranslation } from 'react-i18next';
@@ -486,7 +485,6 @@ const AppContent: React.FC<AppContentProps> = ({ project, setProject }): React.J
486485
return;
487486
}
488487

489-
newWorkspace.addChangeListener(mutatorOpenListener);
490488
newWorkspace.addChangeListener(handleBlocksChanged);
491489

492490
registerToolboxButton(newWorkspace, messageApi);

src/blocks/mrc_class_method_def.ts

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,15 @@ import { getClassData } from './utils/python';
3333
import { FunctionData } from './utils/python_json_types';
3434
import { findConnectedBlocksOfType } from './utils/find_connected_blocks';
3535
import { BLOCK_NAME as MRC_GET_PARAMETER_BLOCK_NAME } from './mrc_get_parameter';
36-
import { MUTATOR_BLOCK_NAME, PARAM_CONTAINER_BLOCK_NAME, MethodMutatorArgBlock } from './mrc_param_container'
36+
import * as paramContainer from './mrc_param_container'
3737

3838
export const BLOCK_NAME = 'mrc_class_method_def';
3939

40+
const INPUT_TITLE = 'TITLE';
4041
export const FIELD_METHOD_NAME = 'NAME';
41-
export const RETURN_VALUE = 'RETURN';
42+
const FIELD_PARAM_PREFIX = 'PARAM_';
43+
const INPUT_STACK = 'STACK';
44+
export const INPUT_RETURN = 'RETURN';
4245

4346
export interface Parameter {
4447
name: string;
@@ -100,12 +103,12 @@ const CLASS_METHOD_DEF = {
100103
* Block initialization.
101104
*/
102105
init: function (this: ClassMethodDefBlock): void {
103-
this.appendDummyInput("TITLE")
106+
this.mrcParameters = [];
107+
this.appendDummyInput(INPUT_TITLE)
104108
.appendField('', FIELD_METHOD_NAME);
105109
this.setOutput(false);
106110
this.setStyle(MRC_STYLE_FUNCTIONS);
107-
this.appendStatementInput('STACK').appendField('');
108-
this.mrcParameters = [];
111+
this.appendStatementInput(INPUT_STACK).appendField('');
109112
this.setPreviousStatement(false);
110113
this.setNextStatement(false);
111114
this.updateBlock_();
@@ -159,7 +162,7 @@ const CLASS_METHOD_DEF = {
159162
*/
160163
updateBlock_: function (this: ClassMethodDefBlock): void {
161164
const name = this.getFieldValue(FIELD_METHOD_NAME);
162-
const input = this.getInput('TITLE');
165+
const input = this.getInput(INPUT_TITLE);
163166
if (!input) {
164167
return;
165168
}
@@ -168,7 +171,7 @@ const CLASS_METHOD_DEF = {
168171
if (this.mrcCanChangeSignature) {
169172
const nameField = new Blockly.FieldTextInput(name);
170173
input.insertFieldAt(0, nameField, FIELD_METHOD_NAME);
171-
this.setMutator(new Blockly.icons.MutatorIcon([MUTATOR_BLOCK_NAME], this));
174+
this.setMutator(paramContainer.getMutatorIcon(this));
172175
nameField.setValidator(this.mrcNameFieldValidator.bind(this, nameField));
173176
} else {
174177
input.insertFieldAt(0, createFieldNonEditableText(name), FIELD_METHOD_NAME);
@@ -178,24 +181,26 @@ const CLASS_METHOD_DEF = {
178181
this.mrcUpdateParams();
179182
this.mrcUpdateReturnInput();
180183
},
181-
compose: function (this: ClassMethodDefBlock, containerBlock: any) {
182-
// Parameter list.
184+
compose: function (this: ClassMethodDefBlock, containerBlock: Blockly.Block) {
185+
if (containerBlock.type !== paramContainer.PARAM_CONTAINER_BLOCK_NAME) {
186+
throw new Error('compose: containerBlock.type should be ' + paramContainer.PARAM_CONTAINER_BLOCK_NAME);
187+
}
188+
const paramContainerBlock = containerBlock as paramContainer.ParamContainerBlock;
189+
const paramItemBlocks: paramContainer.ParamItemBlock[] = paramContainerBlock.getParamItemBlocks();
190+
183191
this.mrcParameters = [];
184192

185-
let paramBlock = containerBlock.getInputTargetBlock('STACK');
186-
while (paramBlock) {
193+
paramItemBlocks.forEach(paramItemBlock => {
194+
const itemName = paramItemBlock.getName();
187195
const param: Parameter = {
188-
name: paramBlock.getFieldValue('NAME'),
196+
name: itemName,
189197
type: ''
190198
};
191-
if (paramBlock.originalName) {
192-
// This is a mutator arg block, so we can get the original name.
193-
this.mrcRenameParameter(paramBlock.originalName, param.name);
194-
paramBlock.originalName = param.name;
195-
}
199+
this.mrcRenameParameter(paramItemBlock.getOriginalName(), itemName);
200+
paramItemBlock.setOriginalName(itemName);
196201
this.mrcParameters.push(param);
197-
paramBlock = paramBlock.nextConnection && paramBlock.nextConnection.targetBlock();
198-
}
202+
});
203+
199204
this.mrcUpdateParams();
200205
if (this.mrcCanBeCalledWithinClass) {
201206
const methodForWithin = this.getMethodForWithin();
@@ -205,29 +210,24 @@ const CLASS_METHOD_DEF = {
205210
}
206211
},
207212
decompose: function (this: ClassMethodDefBlock, workspace: Blockly.Workspace) {
208-
// This is a special sub-block that only gets created in the mutator UI.
209-
// It acts as our "top block"
210-
const topBlock = workspace.newBlock(PARAM_CONTAINER_BLOCK_NAME);
211-
(topBlock as Blockly.BlockSvg).initSvg();
212-
213-
// Then we add one sub-block for each item in the list.
214-
let connection = topBlock!.getInput('STACK')!.connection;
215-
216-
for (let i = 0; i < this.mrcParameters.length; i++) {
217-
const itemBlock = workspace.newBlock(MUTATOR_BLOCK_NAME);
218-
(itemBlock as Blockly.BlockSvg).initSvg();
219-
itemBlock.setFieldValue(this.mrcParameters[i].name, 'NAME');
220-
(itemBlock as MethodMutatorArgBlock).originalName = this.mrcParameters[i].name;
221-
222-
connection!.connect(itemBlock.previousConnection!);
223-
connection = itemBlock.nextConnection;
224-
}
225-
return topBlock;
213+
const parameterNames: string[] = [];
214+
this.mrcParameters.forEach(parameter => {
215+
parameterNames.push(parameter.name);
216+
});
217+
return paramContainer.createMutatorBlocks(workspace, parameterNames);
218+
},
219+
/**
220+
* mrcOnMutatorOpen is called when the mutator on a ClassMethodDefBlock is opened.
221+
*/
222+
mrcOnMutatorOpen: function(this: ClassMethodDefBlock): void {
223+
paramContainer.onMutatorOpen(this);
226224
},
227225
mrcRenameParameter: function (this: ClassMethodDefBlock, oldName: string, newName: string) {
228-
const nextBlock = this.getInputTargetBlock('STACK');
226+
const nextBlock = this.getInputTargetBlock(INPUT_STACK);
229227
if (nextBlock) {
230228
findConnectedBlocksOfType(nextBlock, MRC_GET_PARAMETER_BLOCK_NAME).forEach((block) => {
229+
// TODO(lizlooney): add methods getParameterName and setParameterName to GetParameterBlock
230+
// in mrc_get_parameter.ts and call them here.
231231
if (block.getFieldValue('PARAMETER_NAME') === oldName) {
232232
block.setFieldValue(newName, 'PARAMETER_NAME');
233233
}
@@ -236,34 +236,34 @@ const CLASS_METHOD_DEF = {
236236
},
237237
mrcUpdateParams: function (this: ClassMethodDefBlock) {
238238
if (this.mrcParameters.length > 0) {
239-
const input = this.getInput('TITLE');
239+
const input = this.getInput(INPUT_TITLE);
240240
if (input) {
241241
this.removeParameterFields(input);
242242
this.mrcParameters.forEach((param) => {
243-
const paramName = 'PARAM_' + param.name;
243+
const paramName = FIELD_PARAM_PREFIX + param.name;
244244
input.appendField(createFieldFlydown(param.name, false), paramName);
245245
});
246246
}
247247
}
248248
},
249249
mrcUpdateReturnInput: function (this: ClassMethodDefBlock) {
250250
// Remove existing return input if it exists
251-
if (this.getInput(RETURN_VALUE)) {
252-
this.removeInput(RETURN_VALUE);
251+
if (this.getInput(INPUT_RETURN)) {
252+
this.removeInput(INPUT_RETURN);
253253
}
254254

255255
// Add return input if return type is not 'None'
256256
if (this.mrcReturnType && this.mrcReturnType !== 'None') {
257-
this.appendValueInput(RETURN_VALUE)
257+
this.appendValueInput(INPUT_RETURN)
258258
.setAlign(Blockly.inputs.Align.RIGHT)
259259
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
260260
// Move the return input to be after the statement input
261-
this.moveInputBefore('STACK', RETURN_VALUE);
261+
this.moveInputBefore(INPUT_STACK, INPUT_RETURN);
262262
}
263263
},
264264
removeParameterFields: function (input: Blockly.Input) {
265265
const fieldsToRemove = input.fieldRow
266-
.filter(field => field.name?.startsWith('PARAM_'))
266+
.filter(field => field.name?.startsWith(FIELD_PARAM_PREFIX))
267267
.map(field => field.name!);
268268

269269
fieldsToRemove.forEach(fieldName => {
@@ -436,12 +436,12 @@ export const pythonFromBlock = function (
436436
);
437437
}
438438
let branch = '';
439-
if (block.getInput('STACK')) {
440-
branch = generator.statementToCode(block, 'STACK');
439+
if (block.getInput(INPUT_STACK)) {
440+
branch = generator.statementToCode(block, INPUT_STACK);
441441
}
442442
let returnValue = '';
443-
if (block.getInput('RETURN')) {
444-
returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
443+
if (block.getInput(INPUT_RETURN)) {
444+
returnValue = generator.valueToCode(block, INPUT_RETURN, Order.NONE) || '';
445445
}
446446
let xfix2 = '';
447447
if (branch && returnValue) {
@@ -465,7 +465,7 @@ export const pythonFromBlock = function (
465465
}
466466

467467
const params = block.mrcParameters;
468-
let paramString = "self";
468+
let paramString = 'self';
469469
if (generator.getModuleType() === storageModule.ModuleType.MECHANISM && block.mrcPythonMethodName === '__init__') {
470470
const ports: string[] = generator.getComponentPortParameters();
471471
if (ports.length) {
@@ -527,7 +527,7 @@ export function createCustomMethodBlockWithReturn(): toolboxItems.Block {
527527
const fields: {[key: string]: any} = {};
528528
fields[FIELD_METHOD_NAME] = 'my_method_with_return';
529529
const inputs: {[key: string]: any} = {};
530-
inputs[RETURN_VALUE] = {
530+
inputs[INPUT_RETURN] = {
531531
type: 'input_value',
532532
};
533533
return new toolboxItems.Block(BLOCK_NAME, extraState, fields, inputs);

src/blocks/mrc_event.ts

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import * as Blockly from 'blockly';
2424
import { MRC_STYLE_EVENTS } from '../themes/styles'
2525
import { Parameter } from './mrc_class_method_def';
2626
import { ExtendedPythonGenerator } from '../editor/extended_python_generator';
27-
import { MUTATOR_BLOCK_NAME, PARAM_CONTAINER_BLOCK_NAME, MethodMutatorArgBlock } from './mrc_param_container'
27+
import * as paramContainer from './mrc_param_container'
2828
import {
2929
BLOCK_NAME as MRC_MECHANISM_COMPONENT_HOLDER,
3030
MechanismComponentHolderBlock,
@@ -70,12 +70,13 @@ const EVENT = {
7070
*/
7171
init: function (this: EventBlock): void {
7272
this.mrcHasNotInHolderWarning = false;
73+
this.mrcParameters = [];
7374
this.setStyle(MRC_STYLE_EVENTS);
7475
this.appendDummyInput(INPUT_TITLE)
75-
.appendField(new Blockly.FieldTextInput('my_event'), FIELD_EVENT_NAME);
76+
.appendField(new Blockly.FieldTextInput(''), FIELD_EVENT_NAME);
7677
this.setPreviousStatement(true, OUTPUT_NAME);
7778
this.setNextStatement(true, OUTPUT_NAME);
78-
this.setMutator(new Blockly.icons.MutatorIcon([MUTATOR_BLOCK_NAME], this));
79+
this.updateBlock_();
7980
},
8081

8182
/**
@@ -125,50 +126,37 @@ const EVENT = {
125126

126127
const nameField = new Blockly.FieldTextInput(name);
127128
input.insertFieldAt(0, nameField, FIELD_EVENT_NAME);
128-
this.setMutator(new Blockly.icons.MutatorIcon([MUTATOR_BLOCK_NAME], this));
129+
this.setMutator(paramContainer.getMutatorIcon(this));
129130
nameField.setValidator(this.mrcNameFieldValidator.bind(this, nameField));
130131

131132
this.mrcUpdateParams();
132133
},
133-
compose: function (this: EventBlock, containerBlock: any) {
134-
// Parameter list.
134+
compose: function (this: EventBlock, containerBlock: Blockly.Block) {
135+
if (containerBlock.type !== paramContainer.PARAM_CONTAINER_BLOCK_NAME) {
136+
throw new Error('compose: containerBlock.type should be ' + paramContainer.PARAM_CONTAINER_BLOCK_NAME);
137+
}
135138
this.mrcParameters = [];
136139

137-
let paramBlock = containerBlock.getInputTargetBlock('STACK');
138-
while (paramBlock) {
140+
const paramContainerBlock = containerBlock as paramContainer.ParamContainerBlock;
141+
paramContainerBlock.getParamItemBlocks().forEach(paramItemBlock => {
142+
const itemName = paramItemBlock.getName();
139143
const param: Parameter = {
140-
name: paramBlock.getFieldValue('NAME'),
144+
name: itemName,
141145
type: ''
142-
}
143-
if (paramBlock.originalName) {
144-
// This is a mutator arg block, so we can get the original name.
145-
paramBlock.originalName = param.name;
146-
}
146+
};
147+
paramItemBlock.setOriginalName(itemName);
147148
this.mrcParameters.push(param);
148-
paramBlock = paramBlock.nextConnection && paramBlock.nextConnection.targetBlock();
149-
}
149+
});
150+
150151
this.mrcUpdateParams();
151152
mutateMethodCallers(this.workspace, this.mrcEventId, this.getEvent());
152153
},
153154
decompose: function (this: EventBlock, workspace: Blockly.Workspace) {
154-
// This is a special sub-block that only gets created in the mutator UI.
155-
// It acts as our "top block"
156-
const topBlock = workspace.newBlock(PARAM_CONTAINER_BLOCK_NAME);
157-
(topBlock as Blockly.BlockSvg).initSvg();
158-
159-
// Then we add one sub-block for each item in the list.
160-
let connection = topBlock!.getInput('STACK')!.connection;
161-
162-
for (let i = 0; i < this.mrcParameters.length; i++) {
163-
const itemBlock = workspace.newBlock(MUTATOR_BLOCK_NAME);
164-
(itemBlock as Blockly.BlockSvg).initSvg();
165-
itemBlock.setFieldValue(this.mrcParameters[i].name, 'NAME');
166-
(itemBlock as MethodMutatorArgBlock).originalName = this.mrcParameters[i].name;
167-
168-
connection!.connect(itemBlock.previousConnection!);
169-
connection = itemBlock.nextConnection;
170-
}
171-
return topBlock;
155+
const parameterNames: string[] = [];
156+
this.mrcParameters.forEach(parameter => {
157+
parameterNames.push(parameter.name);
158+
});
159+
return paramContainer.createMutatorBlocks(workspace, parameterNames);
172160
},
173161
mrcUpdateParams: function (this: EventBlock) {
174162
if (this.mrcParameters.length > 0) {
@@ -224,6 +212,12 @@ const EVENT = {
224212
}
225213
mrcDescendantsMayHaveChanged(this.workspace);
226214
},
215+
/**
216+
* mrcOnMutatorOpen is called when the mutator on an EventBlock is opened.
217+
*/
218+
mrcOnMutatorOpen: function(this: EventBlock): void {
219+
paramContainer.onMutatorOpen(this);
220+
},
227221
checkBlockIsInHolder: function(this: EventBlock): void {
228222
const rootBlock: Blockly.Block | null = this.getRootBlock();
229223
if (rootBlock && rootBlock.type === MRC_MECHANISM_COMPONENT_HOLDER) {

0 commit comments

Comments
 (0)