@@ -27,12 +27,17 @@ import { Order } from 'blockly/python';
2727import { ExtendedPythonGenerator } from '../editor/extended_python_generator' ;
2828import * as commonStorage from '../storage/common_storage' ;
2929import { renameMethodCallers , mutateMethodCallers } from './mrc_call_python_function'
30+ import * as toolboxItems from '../toolbox/items' ;
31+ import { getClassData } from './utils/python' ;
32+ import { FunctionData } from './utils/python_json_types' ;
3033import { findConnectedBlocksOfType } from './utils/find_connected_blocks' ;
3134import { BLOCK_NAME as MRC_GET_PARAMETER_BLOCK_NAME } from './mrc_get_parameter' ;
3235import { MUTATOR_BLOCK_NAME , PARAM_CONTAINER_BLOCK_NAME , MethodMutatorArgBlock } from './mrc_param_container'
3336
3437export const BLOCK_NAME = 'mrc_class_method_def' ;
3538
39+ const FIELD_METHOD_NAME = 'NAME' ;
40+
3641export type Parameter = {
3742 name : string ,
3843 type ?: string ,
@@ -88,7 +93,7 @@ const CLASS_METHOD_DEF = {
8893 */
8994 init : function ( this : ClassMethodDefBlock ) : void {
9095 this . appendDummyInput ( "TITLE" )
91- . appendField ( '' , 'NAME' ) ;
96+ . appendField ( '' , FIELD_METHOD_NAME ) ;
9297 this . setOutput ( false ) ;
9398 this . setStyle ( MRC_STYLE_FUNCTIONS ) ;
9499 this . appendStatementInput ( 'STACK' ) . appendField ( '' ) ;
@@ -143,27 +148,27 @@ const CLASS_METHOD_DEF = {
143148 } ) ;
144149 } ) ;
145150 this . updateBlock_ ( ) ;
146- mutateMethodCallers ( this . workspace , this . getFieldValue ( 'NAME' ) , this . saveExtraState ( ) ) ;
151+ mutateMethodCallers ( this . workspace , this . getFieldValue ( FIELD_METHOD_NAME ) , this . saveExtraState ( ) ) ;
147152 } ,
148153 /**
149154 * Update the block to reflect the newly loaded extra state.
150155 */
151156 updateBlock_ : function ( this : ClassMethodDefBlock ) : void {
152- const name = this . getFieldValue ( 'NAME' ) ;
157+ const name = this . getFieldValue ( FIELD_METHOD_NAME ) ;
153158 const input = this . getInput ( 'TITLE' ) ;
154159 if ( ! input ) {
155160 return ;
156161 }
157- input . removeField ( 'NAME' ) ;
162+ input . removeField ( FIELD_METHOD_NAME ) ;
158163
159164 if ( this . mrcCanChangeSignature ) {
160165 const nameField = new Blockly . FieldTextInput ( name ) ;
161- input . insertFieldAt ( 0 , nameField , 'NAME' ) ;
166+ input . insertFieldAt ( 0 , nameField , FIELD_METHOD_NAME ) ;
162167 this . setMutator ( new Blockly . icons . MutatorIcon ( [ MUTATOR_BLOCK_NAME ] , this ) ) ;
163168 nameField . setValidator ( this . mrcNameFieldValidator . bind ( this , nameField ) ) ;
164169 }
165170 else {
166- input . insertFieldAt ( 0 , createFieldNonEditableText ( name ) , 'NAME' ) ;
171+ input . insertFieldAt ( 0 , createFieldNonEditableText ( name ) , FIELD_METHOD_NAME ) ;
167172 //Case because a current bug in blockly where it won't allow passing null to Blockly.Block.setMutator makes it necessary.
168173 ( this as Blockly . BlockSvg ) . setMutator ( null ) ;
169174 }
@@ -189,7 +194,7 @@ const CLASS_METHOD_DEF = {
189194 paramBlock . nextConnection && paramBlock . nextConnection . targetBlock ( ) ;
190195 }
191196 this . mrcUpdateParams ( ) ;
192- mutateMethodCallers ( this . workspace , this . getFieldValue ( 'NAME' ) , this . saveExtraState ( ) ) ;
197+ mutateMethodCallers ( this . workspace , this . getFieldValue ( FIELD_METHOD_NAME ) , this . saveExtraState ( ) ) ;
193198 } ,
194199 decompose : function ( this : ClassMethodDefBlock , workspace : Blockly . Workspace ) {
195200 // This is a special sub-block that only gets created in the mutator UI.
@@ -268,7 +273,7 @@ const CLASS_METHOD_DEF = {
268273 return this . mrcCanChangeSignature ;
269274 } ,
270275 getMethodName : function ( this : ClassMethodDefBlock ) : string {
271- return this . getFieldValue ( 'NAME' ) ;
276+ return this . getFieldValue ( FIELD_METHOD_NAME ) ;
272277 } ,
273278} ;
274279
@@ -315,7 +320,7 @@ function isMethodNameUsed(
315320 if ( block === opt_exclude ) {
316321 continue ;
317322 }
318- if ( nameLowerCase === block . getFieldValue ( 'NAME' ) . toLowerCase ( ) ) {
323+ if ( nameLowerCase === block . getFieldValue ( FIELD_METHOD_NAME ) . toLowerCase ( ) ) {
319324 return true ;
320325 }
321326 const classMethodDefBlock = block as ClassMethodDefBlock ;
@@ -335,7 +340,7 @@ export const pythonFromBlock = function (
335340 block : ClassMethodDefBlock ,
336341 generator : ExtendedPythonGenerator ,
337342) {
338- const blocklyName = block . mrcPythonMethodName ? block . mrcPythonMethodName : block . getFieldValue ( 'NAME' ) ;
343+ const blocklyName = block . mrcPythonMethodName ? block . mrcPythonMethodName : block . getFieldValue ( FIELD_METHOD_NAME ) ;
339344
340345 const funcName = generator . getProcedureName ( blocklyName ) ;
341346
@@ -415,7 +420,7 @@ export const pythonFromBlock = function (
415420 // Update the mrcMethod.
416421 block . mrcMethod = {
417422 blockId : block . id ,
418- visibleName : block . getFieldValue ( 'NAME' ) ,
423+ visibleName : block . getFieldValue ( FIELD_METHOD_NAME ) ,
419424 pythonName : funcName ,
420425 returnType : block . mrcReturnType ,
421426 args : [ {
@@ -433,3 +438,58 @@ export const pythonFromBlock = function (
433438
434439 return '' ;
435440}
441+
442+ // Functions used for creating blocks for the toolbox.
443+
444+ export function createCustomMethodBlock ( ) : toolboxItems . Block {
445+ const extraState : ClassMethodDefExtraState = {
446+ canChangeSignature : true ,
447+ canBeCalledWithinClass : true ,
448+ canBeCalledOutsideClass : true ,
449+ returnType : 'None' ,
450+ params : [ ] ,
451+ } ;
452+ const fields : { [ key : string ] : any } = { } ;
453+ fields [ FIELD_METHOD_NAME ] = 'my_method' ;
454+ return new toolboxItems . Block ( BLOCK_NAME , extraState , fields , null ) ;
455+ }
456+
457+ export function getBaseClassBlocks (
458+ baseClassName : string ) : toolboxItems . Block [ ] {
459+ const blocks : toolboxItems . Block [ ] = [ ] ;
460+ const classData = getClassData ( baseClassName ) ;
461+ if ( classData ) {
462+ classData . instanceMethods . forEach ( functionData => {
463+ blocks . push ( createClassMethodDefBlock (
464+ functionData ,
465+ /* canChangeSignature */ false ,
466+ /* canBeCalledWithinClass */ false ,
467+ /* canBeCalledOutsideClass */ false ,
468+ ) ) ;
469+ } ) ;
470+ }
471+ return blocks ;
472+ }
473+
474+ function createClassMethodDefBlock (
475+ functionData : FunctionData ,
476+ canChangeSignature : boolean ,
477+ canBeCalledWithinClass : boolean ,
478+ canBeCalledOutsideClass : boolean ) : toolboxItems . Block {
479+ const extraState : ClassMethodDefExtraState = {
480+ canChangeSignature,
481+ canBeCalledWithinClass,
482+ canBeCalledOutsideClass,
483+ returnType : functionData . returnType ,
484+ params : [ ] ,
485+ } ;
486+ for ( let i = 1 ; i < functionData . args . length ; i ++ ) {
487+ extraState . params . push ( {
488+ 'name' : functionData . args [ i ] . name ,
489+ 'type' : functionData . args [ i ] . type ,
490+ } ) ;
491+ }
492+ const fields : { [ key : string ] : any } = { } ;
493+ fields [ FIELD_METHOD_NAME ] = functionData . functionName ;
494+ return new toolboxItems . Block ( BLOCK_NAME , extraState , fields , null ) ;
495+ }
0 commit comments