@@ -24,7 +24,9 @@ import { Order } from 'blockly/python';
2424
2525import { MRC_STYLE_EVENTS } from '../themes/styles'
2626import { ExtendedPythonGenerator } from '../editor/extended_python_generator' ;
27- import { MUTATOR_BLOCK_NAME } from './mrc_class_method_def'
27+ import { MUTATOR_BLOCK_NAME , PARAM_CONTAINER_BLOCK_NAME , MethodMutatorArgBlock } from './mrc_param_container'
28+ import * as ChangeFramework from './utils/change_framework' ;
29+ import { BLOCK_NAME as MRC_MECHANISM_COMPONENT_HOLDER } from './mrc_mechanism_component_holder' ;
2830
2931export const BLOCK_NAME = 'mrc_event' ;
3032export const OUTPUT_NAME = 'mrc_event' ;
@@ -38,10 +40,10 @@ type EventExtraState = {
3840 params ?: Parameter [ ] ,
3941}
4042
41- type EventBlock = Blockly . Block & EventMixin & Blockly . BlockSvg ;
43+ export type EventBlock = Blockly . Block & EventMixin & Blockly . BlockSvg ;
4244
4345interface EventMixin extends EventMixinType {
44- mrcParams : Parameter [ ] ,
46+ mrcParameters : Parameter [ ] ,
4547}
4648type EventMixinType = typeof EVENT ;
4749
@@ -51,11 +53,12 @@ const EVENT = {
5153 */
5254 init : function ( this : EventBlock ) : void {
5355 this . setStyle ( MRC_STYLE_EVENTS ) ;
54- this . appendDummyInput ( )
56+ this . appendDummyInput ( "TITLE" )
5557 . appendField ( new Blockly . FieldTextInput ( 'my_event' ) , 'NAME' ) ;
5658 this . setPreviousStatement ( true , OUTPUT_NAME ) ;
5759 this . setNextStatement ( true , OUTPUT_NAME ) ;
5860 this . setMutator ( new Blockly . icons . MutatorIcon ( [ MUTATOR_BLOCK_NAME ] , this ) ) ;
61+ ChangeFramework . registerCallback ( BLOCK_NAME , [ Blockly . Events . BLOCK_MOVE ] , this . onBlockChanged ) ;
5962 } ,
6063
6164 /**
@@ -65,8 +68,8 @@ const EVENT = {
6568 const extraState : EventExtraState = {
6669 } ;
6770 extraState . params = [ ] ;
68- if ( this . mrcParams ) {
69- this . mrcParams . forEach ( ( arg ) => {
71+ if ( this . mrcParameters ) {
72+ this . mrcParameters . forEach ( ( arg ) => {
7073 extraState . params ! . push ( {
7174 'name' : arg . name ,
7275 'type' : arg . type ,
@@ -79,24 +82,117 @@ const EVENT = {
7982 * Applies the given state to this block.
8083 */
8184 loadExtraState : function ( this : EventBlock , extraState : EventExtraState ) : void {
82- this . mrcParams = [ ] ;
85+ this . mrcParameters = [ ] ;
8386
8487 if ( extraState . params ) {
8588 extraState . params . forEach ( ( arg ) => {
86- this . mrcParams . push ( {
89+ this . mrcParameters . push ( {
8790 'name' : arg . name ,
8891 'type' : arg . type ,
8992 } ) ;
9093 } ) ;
9194 }
92- this . mrcParams = extraState . params ? extraState . params : [ ] ;
95+ this . mrcParameters = extraState . params ? extraState . params : [ ] ;
9396 this . updateBlock_ ( ) ;
9497 } ,
9598 /**
9699 * Update the block to reflect the newly loaded extra state.
97100 */
98101 updateBlock_ : function ( this : EventBlock ) : void {
99- }
102+ const name = this . getFieldValue ( 'NAME' ) ;
103+ const input = this . getInput ( 'TITLE' ) ;
104+ if ( ! input ) {
105+ return ;
106+ }
107+ input . removeField ( 'NAME' ) ;
108+
109+ const nameField = new Blockly . FieldTextInput ( name ) ;
110+ input . insertFieldAt ( 0 , nameField , 'NAME' ) ;
111+ this . setMutator ( new Blockly . icons . MutatorIcon ( [ MUTATOR_BLOCK_NAME ] , this ) ) ;
112+ // nameField.setValidator(this.mrcNameFieldValidator.bind(this, nameField));
113+
114+ this . mrcUpdateParams ( ) ;
115+ } ,
116+ compose : function ( this : EventBlock , containerBlock : any ) {
117+ // Parameter list.
118+ this . mrcParameters = [ ] ;
119+
120+ let paramBlock = containerBlock . getInputTargetBlock ( 'STACK' ) ;
121+ while ( paramBlock ) {
122+ const param : Parameter = {
123+ name : paramBlock . getFieldValue ( 'NAME' ) ,
124+ type : ''
125+ }
126+ if ( paramBlock . originalName ) {
127+ // This is a mutator arg block, so we can get the original name.
128+ paramBlock . originalName = param . name ;
129+ }
130+ this . mrcParameters . push ( param ) ;
131+ paramBlock =
132+ paramBlock . nextConnection && paramBlock . nextConnection . targetBlock ( ) ;
133+ }
134+ this . mrcUpdateParams ( ) ;
135+ //mutateMethodCallers(this.workspace, this.getFieldValue('NAME'), this.saveExtraState());
136+ } ,
137+ decompose : function ( this : EventBlock , workspace : Blockly . Workspace ) {
138+ // This is a special sub-block that only gets created in the mutator UI.
139+ // It acts as our "top block"
140+ const topBlock = workspace . newBlock ( PARAM_CONTAINER_BLOCK_NAME ) ;
141+ ( topBlock as Blockly . BlockSvg ) . initSvg ( ) ;
142+
143+ // Then we add one sub-block for each item in the list.
144+ let connection = topBlock ! . getInput ( 'STACK' ) ! . connection ;
145+
146+ for ( let i = 0 ; i < this . mrcParameters . length ; i ++ ) {
147+ let itemBlock = workspace . newBlock ( MUTATOR_BLOCK_NAME ) ;
148+ ( itemBlock as Blockly . BlockSvg ) . initSvg ( ) ;
149+ itemBlock . setFieldValue ( this . mrcParameters [ i ] . name , 'NAME' ) ;
150+ ( itemBlock as MethodMutatorArgBlock ) . originalName = this . mrcParameters [ i ] . name ;
151+
152+ connection ! . connect ( itemBlock . previousConnection ! ) ;
153+ connection = itemBlock . nextConnection ;
154+ }
155+ return topBlock ;
156+ } ,
157+ mrcUpdateParams : function ( this : EventBlock ) {
158+ if ( this . mrcParameters . length > 0 ) {
159+ let input = this . getInput ( 'TITLE' ) ;
160+ if ( input ) {
161+ this . removeParameterFields ( input ) ;
162+ this . mrcParameters . forEach ( ( param ) => {
163+ const paramName = 'PARAM_' + param . name ;
164+ const field = new Blockly . FieldTextInput ( param . name ) ;
165+ field . EDITABLE = false ;
166+ input . appendField ( field , paramName ) ;
167+ } ) ;
168+ }
169+ }
170+ } ,
171+ removeParameterFields : function ( input : Blockly . Input ) {
172+ const fieldsToRemove = input . fieldRow
173+ . filter ( field => field . name ?. startsWith ( 'PARAM_' ) )
174+ . map ( field => field . name ! ) ;
175+
176+ fieldsToRemove . forEach ( fieldName => {
177+ input . removeField ( fieldName ) ;
178+ } ) ;
179+ } ,
180+ onBlockChanged ( block : Blockly . BlockSvg , blockEvent : Blockly . Events . BlockBase ) : void {
181+ const blockBlock = block as Blockly . Block ;
182+
183+ if ( blockEvent . type === Blockly . Events . BLOCK_MOVE ) {
184+ const parent = ChangeFramework . getParentOfType ( block , MRC_MECHANISM_COMPONENT_HOLDER ) ;
185+
186+ if ( parent ) {
187+ // If it is, we allow it to stay.
188+ blockBlock . setWarningText ( null ) ;
189+ return ;
190+ }
191+ // If we end up here it shouldn't be allowed
192+ block . unplug ( true ) ;
193+ blockBlock . setWarningText ( 'Events can only go in the events block' ) ;
194+ }
195+ } ,
100196}
101197
102198export const setup = function ( ) {
0 commit comments