Skip to content

Commit 66ed284

Browse files
authored
In editor.ts: (wpilibsuite#318)
Added code in onChangeAfterLoading to handle VIEWPORT_CHANGE and BLOCK_CREATE events. For VIEWPORT_CHANGE, set the paste location to the center of the blockly workspace. For BLOCK_CREATE, call mrcOnCreate on the newly created block (if the block has that method). In makeCurrent, set the paste workspace and location. In mrc_call_python_function.ts, mrc_component.ts, mrc_event.ts, mrc_event_handler.ts, mrc_mechanism.ts: Added mrcOnCreate so blocks that are created or pasted are checked. In mrc_call_python_function.ts, mrc_event_handler.ts, mrc_jump_to_step.ts, mrc_mechanism.ts: Check whether getIcon(Blockly.icons.IconType.WARNING) returns null. In mrc_call_python_function.ts: Added code to checkFunction to check blocks that call an instance method defined in the same module.
1 parent ee22fe2 commit 66ed284

File tree

11 files changed

+137
-6
lines changed

11 files changed

+137
-6
lines changed

src/blocks/mrc_call_python_function.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,13 +597,57 @@ const CALL_PYTHON_FUNCTION = {
597597
mrcOnLoad: function(this: CallPythonFunctionBlock, editor: Editor): void {
598598
this.checkFunction(editor);
599599
},
600+
/**
601+
* mrcOnCreate is called for each CallPythonFunctionBlock when it is created.
602+
*/
603+
mrcOnCreate: function(this: CallPythonFunctionBlock, editor: Editor): void {
604+
this.checkFunction(editor);
605+
},
600606
/**
601607
* checkFunction checks the block, updates it, and/or adds a warning balloon if necessary.
602-
* It is called from mrcOnModuleCurrent and mrcOnLoad above.
608+
* It is called from mrcOnModuleCurrent, mrcOnLoad, and mrcOnCreate above.
603609
*/
604610
checkFunction: function(this: CallPythonFunctionBlock, editor: Editor): void {
605611
const warnings: string[] = [];
606612

613+
// If this block is calling a method defined in this module, check whether the method still
614+
// exists and whether it has been changed.
615+
// If the method doesn't exist, put a visible warning on this block.
616+
// If the robot method has changed, update the block if possible or put a
617+
// visible warning on it.
618+
if (this.mrcFunctionKind === FunctionKind.INSTANCE_WITHIN) {
619+
let foundMethod = false;
620+
const methodsFromWorkspace = editor.getMethodsForWithinFromWorkspace();
621+
for (const method of methodsFromWorkspace) {
622+
if (method.methodId === this.mrcMethodId) {
623+
foundMethod = true;
624+
if (this.mrcActualFunctionName !== method.pythonName) {
625+
this.mrcActualFunctionName = method.pythonName;
626+
}
627+
if (this.getFieldValue(FIELD_FUNCTION_NAME) !== method.visibleName) {
628+
this.setFieldValue(method.visibleName, FIELD_FUNCTION_NAME);
629+
}
630+
631+
this.mrcReturnType = method.returnType;
632+
this.mrcArgs = [];
633+
// We don't include the arg for the self argument because we don't need a socket for it.
634+
for (let i = 1; i < method.args.length; i++) {
635+
this.mrcArgs.push({
636+
name: method.args[i].name,
637+
type: method.args[i].type,
638+
});
639+
}
640+
this.updateBlock_();
641+
642+
// Since we found the method, we can break out of the loop.
643+
break;
644+
}
645+
}
646+
if (!foundMethod) {
647+
warnings.push(Blockly.Msg.WARNING_CALL_INSTANCE_WITHIN_METHOD_MISSING_METHOD);
648+
}
649+
}
650+
607651
// If this block is calling a component method, check whether the component
608652
// still exists and whether it has been changed.
609653
// If the component doesn't exist, put a visible warning on this block.
@@ -823,7 +867,10 @@ const CALL_PYTHON_FUNCTION = {
823867
// Add a warnings to the block.
824868
const warningText = warnings.join('\n\n');
825869
this.setWarningText(warningText, WARNING_ID_FUNCTION_CHANGED);
826-
this.getIcon(Blockly.icons.IconType.WARNING)!.setBubbleVisible(true);
870+
const icon = this.getIcon(Blockly.icons.IconType.WARNING);
871+
if (icon) {
872+
icon.setBubbleVisible(true);
873+
}
827874
this.bringToFront();
828875
} else {
829876
// Clear the existing warning on the block.

src/blocks/mrc_component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ const COMPONENT = {
201201
mrcOnLoad: function(this: ComponentBlock, _editor: Editor): void {
202202
this.checkBlockIsInHolder();
203203
},
204+
/**
205+
* mrcOnCreate is called for each ComponentBlock when it is created.
206+
*/
207+
mrcOnCreate: function(this: ComponentBlock, _editor: Editor): void {
208+
this.checkBlockIsInHolder();
209+
},
204210
/**
205211
* mrcOnMove is called when a ComponentBlock is moved.
206212
*/

src/blocks/mrc_event.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ const EVENT = {
200200
mrcOnLoad: function(this: EventBlock, _editor: Editor): void {
201201
this.checkBlockIsInHolder();
202202
},
203+
/**
204+
* mrcOnCreate is called for each EventBlock when it is created.
205+
*/
206+
mrcOnCreate: function(this: EventBlock, _editor: Editor): void {
207+
this.checkBlockIsInHolder();
208+
},
203209
/**
204210
* mrcOnMove is called when an EventBlock is moved.
205211
*/

src/blocks/mrc_event_handler.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,15 @@ const EVENT_HANDLER = {
180180
mrcOnLoad: function(this: EventHandlerBlock, editor: Editor): void {
181181
this.checkEvent(editor);
182182
},
183+
/**
184+
* mrcOnCreate is called for each EventHandlerBlock when it is created.
185+
*/
186+
mrcOnCreate: function(this: EventHandlerBlock, editor: Editor): void {
187+
this.checkEvent(editor);
188+
},
183189
/**
184190
* checkEvent checks the block, updates it, and/or adds a warning balloon if necessary.
185-
* It is called from mrcOnModuleCurrent and mrcOnLoad above.
191+
* It is called from mrcOnModuleCurrent, mrcOnLoad, and mrcCreate above.
186192
*/
187193
checkEvent: function(this: EventHandlerBlock, editor: Editor): void {
188194
const warnings: string[] = [];
@@ -282,7 +288,10 @@ const EVENT_HANDLER = {
282288
// Add a warnings to the block.
283289
const warningText = warnings.join('\n\n');
284290
this.setWarningText(warningText, WARNING_ID_EVENT_CHANGED);
285-
this.getIcon(Blockly.icons.IconType.WARNING)!.setBubbleVisible(true);
291+
const icon = this.getIcon(Blockly.icons.IconType.WARNING);
292+
if (icon) {
293+
icon.setBubbleVisible(true);
294+
}
286295
this.bringToFront();
287296
} else {
288297
// Clear the existing warning on the block.

src/blocks/mrc_jump_to_step.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ const JUMP_TO_STEP_BLOCK = {
8787
// Otherwise, add a warning to this block.
8888
if (!this.mrcHasWarning) {
8989
this.setWarningText(Blockly.Msg.JUMP_CAN_ONLY_GO_IN_THEIR_STEPS_BLOCK, WARNING_ID_NOT_IN_STEP);
90-
this.getIcon(Blockly.icons.IconType.WARNING)!.setBubbleVisible(true);
90+
const icon = this.getIcon(Blockly.icons.IconType.WARNING);
91+
if (icon) {
92+
icon.setBubbleVisible(true);
93+
}
9194
this.mrcHasWarning = true;
9295
}
9396
}

src/blocks/mrc_mechanism.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ const MECHANISM = {
204204
this.checkBlockIsInHolder();
205205
this.checkMechanism(editor);
206206
},
207+
/**
208+
* mrcOnCreate is called for each MechanismBlock when it is created.
209+
*/
210+
mrcOnCreate: function(this: MechanismBlock, editor: Editor): void {
211+
this.checkBlockIsInHolder();
212+
this.checkMechanism(editor);
213+
},
207214
/**
208215
* mrcOnMove is called when a MechanismBlock is moved.
209216
*/
@@ -299,7 +306,10 @@ const MECHANISM = {
299306
// Add a warnings to the block.
300307
const warningText = warnings.join('\n\n');
301308
this.setWarningText(warningText, WARNING_ID_MECHANISM_CHANGED);
302-
this.getIcon(Blockly.icons.IconType.WARNING)!.setBubbleVisible(true);
309+
const icon = this.getIcon(Blockly.icons.IconType.WARNING);
310+
if (icon) {
311+
icon.setBubbleVisible(true);
312+
}
303313
this.bringToFront();
304314
} else {
305315
// Clear the existing warning on the block.

src/blocks/tokens.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export function customTokens(t: (key: string) => string): typeof Blockly.Msg {
8686
SET_INSTANCE_VARIABLE_TOOLTIP: t('BLOCKLY.TOOLTIP.SET_INSTANCE_VARIABLE'),
8787
VAR_KIND_MUST_BE_MODULE_CLASS_OR_INSTANCE: t('BLOCKLY.ERROR.VAR_KIND_MUST_BE_MODULE_CLASS_OR_INSTANCE'),
8888
MECHANISM_NOT_FOUND_WARNING: t('BLOCKLY.WARNING.MECHANISM_NOT_FOUND'),
89+
WARNING_CALL_INSTANCE_WITHIN_METHOD_MISSING_METHOD: t('BLOCKLY.WARNING.CALL_INSTANCE_WITHIN_METHOD_MISSING_METHOD'),
8990
WARNING_CALL_COMPONENT_INSTANCE_METHOD_PRIVATE_COMPONENT: t('BLOCKLY.WARNING.CALL_COMPONENT_INSTANCE_METHOD_PRIVATE_COMPONENT'),
9091
WARNING_CALL_COMPONENT_INSTANCE_METHOD_MISSING_COMPONENT: t('BLOCKLY.WARNING.CALL_COMPONENT_INSTANCE_METHOD_MISSING_COMPONENT'),
9192
WARNING_CALL_MECHANISM_COMPONENT_INSTANCE_METHOD_MISSING_MECHANISM: t('BLOCKLY.WARNING.CALL_MECHANISM_COMPONENT_INSTANCE_METHOD_MISSING_MECHANISM'),

src/editor/editor.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const EMPTY_TOOLBOX: Blockly.utils.toolbox.ToolboxInfo = {
4242
};
4343

4444
const MRC_ON_LOAD = 'mrcOnLoad';
45+
const MRC_ON_CREATE = 'mrcOnCreate';
4546
const MRC_ON_MOVE = 'mrcOnMove';
4647
const MRC_ON_DESCENDANT_DISCONNECT = 'mrcOnDescendantDisconnect';
4748
const MRC_ON_ANCESTOR_MOVE = 'mrcOnAncestorMove';
@@ -134,6 +135,24 @@ export class Editor {
134135
return;
135136
}
136137

138+
if (event.type === Blockly.Events.VIEWPORT_CHANGE) {
139+
this.setPasteLocation();
140+
}
141+
142+
if (event.type === Blockly.Events.BLOCK_CREATE) {
143+
const blockCreateEvent = event as Blockly.Events.BlockCreate;
144+
if (blockCreateEvent.ids) {
145+
blockCreateEvent.ids.forEach(id => {
146+
const block = this.blocklyWorkspace.getBlockById(id);
147+
if (block) {
148+
if (MRC_ON_CREATE in block && typeof block[MRC_ON_CREATE] === 'function') {
149+
block[MRC_ON_CREATE](this);
150+
}
151+
}
152+
});
153+
}
154+
}
155+
137156
if (event.type === Blockly.Events.BLOCK_MOVE) {
138157
const blockMoveEvent = event as Blockly.Events.BlockMove;
139158
const reason: string[] = blockMoveEvent.reason ?? [];
@@ -165,6 +184,7 @@ export class Editor {
165184
}
166185
});
167186
}
187+
168188
if (event.type === Blockly.Events.BUBBLE_OPEN) {
169189
const bubbleOpenEvent = event as Blockly.Events.BubbleOpen;
170190
if (bubbleOpenEvent.bubbleType === 'mutator' && bubbleOpenEvent.isOpen) {
@@ -199,6 +219,16 @@ export class Editor {
199219
block[MRC_ON_MODULE_CURRENT](this);
200220
}
201221
});
222+
223+
if (Blockly.clipboard.getLastCopiedWorkspace()) {
224+
Blockly.clipboard.setLastCopiedWorkspace(this.blocklyWorkspace);
225+
226+
setTimeout(() => {
227+
this.blocklyWorkspace.markFocused();
228+
Blockly.getFocusManager().focusNode(this.blocklyWorkspace);
229+
this.setPasteLocation();
230+
});
231+
}
202232
}
203233

204234
public abandon(): void {
@@ -618,4 +648,20 @@ export class Editor {
618648
public static getCurrentEditor(): Editor | null {
619649
return Editor.currentEditor;
620650
}
651+
652+
private setPasteLocation(): void {
653+
const copyData = Blockly.clipboard.getLastCopiedData();
654+
if (copyData && copyData.paster === 'block') {
655+
const blockCopyData = copyData as Blockly.clipboard.BlockCopyData;
656+
if (blockCopyData.blockState) {
657+
const metrics = this.blocklyWorkspace.getMetrics();
658+
const center = new Blockly.utils.Coordinate(
659+
metrics.viewLeft + metrics.viewWidth / 2,
660+
metrics.viewTop + metrics.viewHeight / 2);
661+
blockCopyData.blockState.x = center.x;
662+
blockCopyData.blockState.y = center.y;
663+
Blockly.clipboard.setLastCopiedLocation(center);
664+
}
665+
}
666+
}
621667
}

src/i18n/locales/en/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@
207207
"PAGINATION_TOTAL": "{{start}}-{{end}} of {{total}} items"
208208
},
209209
"WARNING":{
210+
"CALL_INSTANCE_WITHIN_METHOD_MISSING_METHOD": "This block calls a method that does not exist in this module.",
210211
"CALL_COMPONENT_INSTANCE_METHOD_PRIVATE_COMPONENT": "This blocks calls a method on a private component in the {{mechanismClassName}} mechanism.",
211212
"CALL_COMPONENT_INSTANCE_METHOD_MISSING_COMPONENT": "This block calls a method on a component that no longer exists.",
212213
"CALL_MECHANISM_COMPONENT_INSTANCE_METHOD_MISSING_MECHANISM": "This block calls a method on a component that belongs to a mechanism that no longer exists.",

src/i18n/locales/es/translation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
"PAGINATION_TOTAL": "{{start}}-{{end}} de {{total}} elementos"
209209
},
210210
"WARNING":{
211+
"CALL_INSTANCE_WITHIN_METHOD_MISSING_METHOD": "Este bloque llama a un método que no existe en este módulo.",
211212
"CALL_COMPONENT_INSTANCE_METHOD_PRIVATE_COMPONENT": "Este bloque llama a un método en un componente privado en el mecanismo {{mechanismClassName}}.",
212213
"CALL_COMPONENT_INSTANCE_METHOD_MISSING_COMPONENT": "Este bloque llama a un método en un componente que ya no existe.",
213214
"CALL_MECHANISM_COMPONENT_INSTANCE_METHOD_MISSING_MECHANISM": "Este bloque llama a un método de un componente que pertenece a un mecanismo que ya no existe.",

0 commit comments

Comments
 (0)