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
7 changes: 4 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ import * as commonStorage from './storage/common_storage';
import * as clientSideStorage from './storage/client_side_storage';

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 {mutatorOpenListener} from './blocks/mrc_class_method_def';

import { initialize as initializePythonBlocks } from './blocks/utils/python';
import * as ChangeFramework from './blocks/utils/change_framework'
import { mutatorOpenListener } from './blocks/mrc_param_container'

/** Storage key for shown toolbox categories. */
const SHOWN_TOOLBOX_CATEGORIES_KEY = 'shownPythonToolboxCategories';
Expand Down
27 changes: 24 additions & 3 deletions src/blocks/mrc_call_python_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,17 @@ import * as toolboxItems from '../toolbox/items';

export const BLOCK_NAME = 'mrc_call_python_function';

enum FunctionKind {
export enum FunctionKind {
MODULE = 'module',
STATIC = 'static',
CONSTRUCTOR = 'constructor',
INSTANCE = 'instance',
INSTANCE_WITHIN = 'instance_within',
INSTANCE_COMPONENT = 'instance_component'
INSTANCE_COMPONENT = 'instance_component',
EVENT = 'event',
}

const RETURN_TYPE_NONE = 'None';
export const RETURN_TYPE_NONE = 'None';

const FIELD_MODULE_OR_CLASS_NAME = 'MODULE_OR_CLASS';
const FIELD_FUNCTION_NAME = 'FUNC';
Expand Down Expand Up @@ -318,6 +319,11 @@ const CALL_PYTHON_FUNCTION = {
tooltip = 'Calls the instance method ' + functionName + '.';
break;
}
case FunctionKind.EVENT: {
const functionName = this.getFieldValue(FIELD_FUNCTION_NAME);
tooltip = 'Fires the event ' + functionName + '.';
break;
}
case FunctionKind.INSTANCE_COMPONENT: {
const className = this.mrcComponentClassName;
const functionName = this.getFieldValue(FIELD_FUNCTION_NAME);
Expand Down Expand Up @@ -459,6 +465,15 @@ const CALL_PYTHON_FUNCTION = {
}
break;
}
case FunctionKind.EVENT: {
const input = this.getInput('TITLE');
if (!input) {
this.appendDummyInput('TITLE')
.appendField('fire')
.appendField(createFieldNonEditableText(''), FIELD_FUNCTION_NAME);
}
break;
}
case FunctionKind.INSTANCE_COMPONENT: {
const componentNames = Editor.getComponentNames(this.workspace, this.mrcComponentClassName);
const componentName = this.getComponentName();
Expand Down Expand Up @@ -586,6 +601,12 @@ export const pythonFromBlock = function(
code = 'self.' + functionName;
break;
}
case FunctionKind.EVENT: {
const blocklyName = block.getFieldValue(FIELD_FUNCTION_NAME);
const functionName = generator.getProcedureName(blocklyName);
code = 'if self.events.get("' + functionName + '", None):\n' + generator.INDENT + 'self.events["' + functionName + '"]';
break;
}
case FunctionKind.INSTANCE_COMPONENT: {
const componentName = callPythonFunctionBlock.getComponentName();
const functionName = callPythonFunctionBlock.mrcActualFunctionName
Expand Down
136 changes: 5 additions & 131 deletions src/blocks/mrc_class_method_def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,15 @@ import * as Blockly from 'blockly';
import { MRC_STYLE_CLASS_BLOCKS } from '../themes/styles';
import { createFieldNonEditableText } from '../fields/FieldNonEditableText'
import { createFieldFlydown } from '../fields/field_flydown';
import * as ChangeFramework from './utils/change_framework'
import { getLegalName } from './utils/python';
import { Order } from 'blockly/python';
import { ExtendedPythonGenerator } from '../editor/extended_python_generator';
import { renameMethodCallers, mutateMethodCallers } from './mrc_call_python_function'
import { findConnectedBlocksOfType } from './utils/find_connected_blocks';
import { BLOCK_NAME as MRC_GET_PARAMETER_BLOCK_NAME } from './mrc_get_parameter';

import { MUTATOR_BLOCK_NAME, PARAM_CONTAINER_BLOCK_NAME, MethodMutatorArgBlock } from './mrc_param_container'

export const BLOCK_NAME = 'mrc_class_method_def';

export const MUTATOR_BLOCK_NAME = 'methods_mutatorarg';
const PARAM_CONTAINER_BLOCK_NAME = 'method_param_container';

export type Parameter = {
name: string,
type?: string,
Expand Down Expand Up @@ -314,133 +309,8 @@ function isMethodNameUsed(
return false;
}

const METHOD_PARAM_CONTAINER = {
init: function (this: Blockly.Block) {
this.appendDummyInput("TITLE").appendField('Parameters');
this.appendStatementInput('STACK');
this.setStyle(MRC_STYLE_CLASS_BLOCKS);
this.contextMenu = false;
},
};

type MethodMutatorArgBlock = Blockly.Block & MethodMutatorArgMixin & Blockly.BlockSvg;
interface MethodMutatorArgMixin extends MethodMutatorArgMixinType {
originalName: string,
}

type MethodMutatorArgMixinType = typeof METHODS_MUTATORARG;

function setName(block: Blockly.BlockSvg) {
const parentBlock = ChangeFramework.getParentOfType(block, PARAM_CONTAINER_BLOCK_NAME);
if (parentBlock) {
const variableBlocks = parentBlock!.getDescendants(true)
const otherNames: string[] = []
variableBlocks?.forEach(function (variableBlock) {
if (variableBlock != block) {
otherNames.push(variableBlock.getFieldValue('NAME'));
}
});
const currentName = block.getFieldValue('NAME');
block.setFieldValue(getLegalName(currentName, otherNames), 'NAME');
updateMutatorFlyout(block.workspace);
}
}

const METHODS_MUTATORARG = {
init: function (this: MethodMutatorArgBlock) {
this.appendDummyInput()
.appendField(new Blockly.FieldTextInput(Blockly.Procedures.DEFAULT_ARG), 'NAME');
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setStyle(MRC_STYLE_CLASS_BLOCKS);
this.originalName = '';
this.contextMenu = false;
ChangeFramework.registerCallback(MUTATOR_BLOCK_NAME, [Blockly.Events.BLOCK_MOVE, Blockly.Events.BLOCK_CHANGE], this.onBlockChanged);
},
onBlockChanged: function (block: Blockly.BlockSvg, blockEvent: Blockly.Events.BlockBase) {
if (blockEvent.type == Blockly.Events.BLOCK_MOVE) {
let blockMoveEvent = blockEvent as Blockly.Events.BlockMove;
if (blockMoveEvent.reason?.includes('connect')) {
setName(block);
}
}
else {
if (blockEvent.type == Blockly.Events.BLOCK_CHANGE) {
setName(block);
}
}
},
}


/**
* Updates the procedure mutator's flyout so that the arg block is not a
* duplicate of another arg.
*
* @param workspace The procedure mutator's workspace. This workspace's flyout
* is what is being updated.
*/
function updateMutatorFlyout(workspace: Blockly.WorkspaceSvg) {
const usedNames = [];
const blocks = workspace.getBlocksByType(MUTATOR_BLOCK_NAME, false);
for (let i = 0, block; (block = blocks[i]); i++) {
usedNames.push(block.getFieldValue('NAME'));
}
const argValue = Blockly.Variables.generateUniqueNameFromOptions(
Blockly.Procedures.DEFAULT_ARG,
usedNames,
);
const jsonBlock = {
kind: 'block',
type: MUTATOR_BLOCK_NAME,
fields: {
NAME: argValue,
},
};

workspace.updateToolbox({ contents: [jsonBlock] });
}


/**
* Listens for when a procedure mutator is opened. Then it triggers a flyout
* update and adds a mutator change listener to the mutator workspace.
*
* @param e The event that triggered this listener.
* @internal
*/
export function mutatorOpenListener(e: Blockly.Events.Abstract) {
if (e.type != Blockly.Events.BUBBLE_OPEN) {
return;
}
const bubbleEvent = e as Blockly.Events.BubbleOpen;
if (
!(bubbleEvent.bubbleType === 'mutator' && bubbleEvent.isOpen) ||
!bubbleEvent.blockId
) {
return;
}
const workspaceId = bubbleEvent.workspaceId;
const block = Blockly.common
.getWorkspaceById(workspaceId)!
.getBlockById(bubbleEvent.blockId) as Blockly.BlockSvg;

if (block.type !== BLOCK_NAME) {
return;
}
const workspace = (
block.getIcon(Blockly.icons.MutatorIcon.TYPE) as Blockly.icons.MutatorIcon
).getWorkspace()!;

updateMutatorFlyout(workspace);
ChangeFramework.setup(workspace);
}


export const setup = function () {
Blockly.Blocks[BLOCK_NAME] = CLASS_METHOD_DEF;
Blockly.Blocks[MUTATOR_BLOCK_NAME] = METHODS_MUTATORARG;
Blockly.Blocks[PARAM_CONTAINER_BLOCK_NAME] = METHOD_PARAM_CONTAINER;
};

export const pythonFromBlock = function (
Expand Down Expand Up @@ -486,6 +356,10 @@ export const pythonFromBlock = function (
branch = generator.INDENT + 'super().__init__(' + class_specific + ')\n' +
generator.defineClassVariables() + branch;
}
else if (funcName == 'update'){
// Special case for update, to also call the update method of the base class
branch = generator.INDENT + 'self.update()\n' + branch;
}
if (returnValue) {
returnValue = generator.INDENT + 'return ' + returnValue + '\n';
} else if (!branch) {
Expand Down
Loading