@@ -41,17 +41,20 @@ export const BLOCK_NAME = 'mrc_mechanism_component_holder';
41
41
42
42
const INPUT_MECHANISMS = 'MECHANISMS' ;
43
43
const INPUT_COMPONENTS = 'COMPONENTS' ;
44
+ const INPUT_PRIVATE_COMPONENTS = 'PRIVATE_COMPONENTS' ;
44
45
const INPUT_EVENTS = 'EVENTS' ;
45
46
46
47
export const TOOLBOX_UPDATE_EVENT = 'toolbox-update-requested' ;
47
48
48
49
type MechanismComponentHolderExtraState = {
49
50
hideMechanisms ?: boolean ;
51
+ hidePrivateComponents ?: boolean ;
50
52
}
51
53
52
54
export type MechanismComponentHolderBlock = Blockly . Block & MechanismComponentHolderMixin ;
53
55
interface MechanismComponentHolderMixin extends MechanismComponentHolderMixinType {
54
56
mrcHideMechanisms : boolean ;
57
+ mrcHidePrivateComponents : boolean ;
55
58
}
56
59
type MechanismComponentHolderMixinType = typeof MECHANISM_COMPONENT_HOLDER ;
57
60
@@ -72,15 +75,10 @@ function setName(block: Blockly.BlockSvg){
72
75
73
76
const MECHANISM_COMPONENT_HOLDER = {
74
77
/**
75
- * Block initialization.
76
- */
78
+ * Block initialization.
79
+ */
77
80
init : function ( this : MechanismComponentHolderBlock ) : void {
78
81
this . setInputsInline ( false ) ;
79
- this . appendStatementInput ( INPUT_MECHANISMS ) . setCheck ( MECHANISM_OUTPUT ) . appendField ( Blockly . Msg . MECHANISMS ) ;
80
- this . appendStatementInput ( INPUT_COMPONENTS ) . setCheck ( COMPONENT_OUTPUT ) . appendField ( Blockly . Msg . COMPONENTS ) ;
81
- this . appendStatementInput ( INPUT_EVENTS ) . setCheck ( EVENT_OUTPUT ) . appendField ( Blockly . Msg . EVENTS ) ;
82
-
83
-
84
82
this . setOutput ( false ) ;
85
83
this . setStyle ( MRC_STYLE_MECHANISMS ) ;
86
84
ChangeFramework . registerCallback ( MRC_COMPONENT_NAME , [ Blockly . Events . BLOCK_MOVE , Blockly . Events . BLOCK_CHANGE ] , this . onBlockChanged ) ;
@@ -95,30 +93,49 @@ const MECHANISM_COMPONENT_HOLDER = {
95
93
if ( this . mrcHideMechanisms == true ) {
96
94
extraState . hideMechanisms = this . mrcHideMechanisms ;
97
95
}
96
+ if ( this . mrcHidePrivateComponents == true ) {
97
+ extraState . hidePrivateComponents = this . mrcHidePrivateComponents ;
98
+ }
98
99
return extraState ;
99
100
} ,
100
101
/**
101
- * Applies the given state to this block.
102
- */
102
+ * Applies the given state to this block.
103
+ */
103
104
loadExtraState : function ( this : MechanismComponentHolderBlock , extraState : MechanismComponentHolderExtraState ) : void {
104
105
this . mrcHideMechanisms = ( extraState . hideMechanisms == undefined ) ? false : extraState . hideMechanisms ;
106
+ this . mrcHidePrivateComponents = ( extraState . hidePrivateComponents == undefined ) ? false : extraState . hidePrivateComponents ;
105
107
this . updateBlock_ ( ) ;
106
108
} ,
107
109
/**
108
- * Update the block to reflect the newly loaded extra state.
109
- */
110
+ * Update the block to reflect the newly loaded extra state.
111
+ */
110
112
updateBlock_ : function ( this : MechanismComponentHolderBlock ) : void {
111
- if ( this . mrcHideMechanisms ) {
112
- if ( this . getInput ( INPUT_MECHANISMS ) ) {
113
- this . removeInput ( INPUT_MECHANISMS )
114
- }
113
+ // Handle mechanisms input visibility
114
+ if ( ! this . mrcHideMechanisms ) {
115
+ this . appendStatementInput ( INPUT_MECHANISMS )
116
+ . setCheck ( MECHANISM_OUTPUT )
117
+ . appendField ( Blockly . Msg . MECHANISMS ) ;
115
118
}
116
- else {
117
- if ( this . getInput ( INPUT_MECHANISMS ) == null ) {
118
- this . appendStatementInput ( INPUT_MECHANISMS ) . setCheck ( MECHANISM_OUTPUT ) . appendField ( 'Mechanisms' ) ;
119
- this . moveInputBefore ( INPUT_MECHANISMS , INPUT_COMPONENTS )
120
- }
119
+
120
+ const componentsField = new Blockly . FieldLabel ( Blockly . Msg . COMPONENTS ) ;
121
+ this . appendStatementInput ( INPUT_COMPONENTS )
122
+ . setCheck ( COMPONENT_OUTPUT )
123
+ . appendField ( componentsField ) ;
124
+
125
+ // Handle private components input visibility
126
+ if ( ! this . mrcHidePrivateComponents ) {
127
+ const privateComponentsField = new Blockly . FieldLabel ( Blockly . Msg . PRIVATE_COMPONENTS ) ;
128
+ this . appendStatementInput ( INPUT_PRIVATE_COMPONENTS )
129
+ . setCheck ( COMPONENT_OUTPUT )
130
+ . appendField ( privateComponentsField ) ;
131
+ // Set tooltips on both componentsField and privateComponentsField.
132
+ componentsField . setTooltip ( Blockly . Msg . COMPONENTS_TOOLTIP ) ;
133
+ privateComponentsField . setTooltip ( Blockly . Msg . PRIVATE_COMPONENTS_TOOLTIP ) ;
121
134
}
135
+
136
+ this . appendStatementInput ( INPUT_EVENTS )
137
+ . setCheck ( EVENT_OUTPUT )
138
+ . appendField ( Blockly . Msg . EVENTS ) ;
122
139
} ,
123
140
onBlockChanged : function ( block : Blockly . BlockSvg , blockEvent : Blockly . Events . BlockBase ) {
124
141
if ( blockEvent . type == Blockly . Events . BLOCK_MOVE ) {
@@ -179,6 +196,28 @@ const MECHANISM_COMPONENT_HOLDER = {
179
196
180
197
return components ;
181
198
} ,
199
+ getPrivateComponents : function ( this : MechanismComponentHolderBlock ) : storageModuleContent . Component [ ] {
200
+ const components : storageModuleContent . Component [ ] = [ ]
201
+
202
+ // Get component blocks from the PRIVATE_COMPONENTS input
203
+ const privateComponentsInput = this . getInput ( INPUT_PRIVATE_COMPONENTS ) ;
204
+ if ( privateComponentsInput && privateComponentsInput . connection ) {
205
+ // Walk through all connected component blocks.
206
+ let componentBlock = privateComponentsInput . connection . targetBlock ( ) ;
207
+ while ( componentBlock ) {
208
+ if ( componentBlock . type === MRC_COMPONENT_NAME ) {
209
+ const component = ( componentBlock as ComponentBlock ) . getComponent ( ) ;
210
+ if ( component ) {
211
+ components . push ( component ) ;
212
+ }
213
+ }
214
+ // Move to the next block in the chain
215
+ componentBlock = componentBlock . getNextBlock ( ) ;
216
+ }
217
+ }
218
+
219
+ return components ;
220
+ } ,
182
221
getEvents : function ( this : MechanismComponentHolderBlock ) : storageModuleContent . Event [ ] {
183
222
const events : storageModuleContent . Event [ ] = [ ]
184
223
@@ -243,9 +282,11 @@ function pythonFromBlockInMechanism(block: MechanismComponentHolderBlock, genera
243
282
code += '):\n' ;
244
283
245
284
const components = generator . statementToCode ( block , INPUT_COMPONENTS ) ;
285
+ const privateComponents = generator . statementToCode ( block , INPUT_PRIVATE_COMPONENTS ) ;
246
286
247
- if ( components ) {
248
- code += components ;
287
+ const allComponents = components + privateComponents ;
288
+ if ( allComponents ) {
289
+ code += allComponents ;
249
290
generator . addClassMethodDefinition ( 'define_hardware' , code ) ;
250
291
}
251
292
}
@@ -266,12 +307,13 @@ export const pythonFromBlock = function (
266
307
267
308
// Misc
268
309
269
- /**n
310
+ /**
270
311
* Returns true if the given workspace has a mrc_mechanism_component_holder
271
312
* block that contains at least one component.
272
313
*/
273
314
export function hasAnyComponents ( workspace : Blockly . Workspace ) : boolean {
274
315
for ( const block of workspace . getBlocksByType ( BLOCK_NAME ) ) {
316
+ // Check regular components
275
317
const componentsInput = block . getInput ( INPUT_COMPONENTS ) ;
276
318
if ( componentsInput && componentsInput . connection ) {
277
319
// Walk through all connected component blocks.
@@ -284,6 +326,20 @@ export function hasAnyComponents(workspace: Blockly.Workspace): boolean {
284
326
componentBlock = componentBlock . getNextBlock ( ) ;
285
327
}
286
328
}
329
+
330
+ // Check private components
331
+ const privateComponentsInput = block . getInput ( INPUT_PRIVATE_COMPONENTS ) ;
332
+ if ( privateComponentsInput && privateComponentsInput . connection ) {
333
+ // Walk through all connected private component blocks.
334
+ let componentBlock = privateComponentsInput . connection . targetBlock ( ) ;
335
+ while ( componentBlock ) {
336
+ if ( componentBlock . type === MRC_COMPONENT_NAME && componentBlock . isEnabled ( ) ) {
337
+ return true ;
338
+ }
339
+ // Move to the next block in the chain
340
+ componentBlock = componentBlock . getNextBlock ( ) ;
341
+ }
342
+ }
287
343
}
288
344
return false ;
289
345
}
@@ -305,6 +361,20 @@ export function getComponentPorts(workspace: Blockly.Workspace, ports: {[key: st
305
361
componentBlock = componentBlock . getNextBlock ( ) ;
306
362
}
307
363
}
364
+
365
+ // Also include private components for port collection
366
+ const privateComponentsInput = block . getInput ( INPUT_PRIVATE_COMPONENTS ) ;
367
+ if ( privateComponentsInput && privateComponentsInput . connection ) {
368
+ // Walk through all connected private component blocks.
369
+ let componentBlock = privateComponentsInput . connection . targetBlock ( ) ;
370
+ while ( componentBlock ) {
371
+ if ( componentBlock . type === MRC_COMPONENT_NAME && componentBlock . isEnabled ( ) ) {
372
+ ( componentBlock as ComponentBlock ) . getComponentPorts ( ports ) ;
373
+ }
374
+ // Move to the next block in the chain
375
+ componentBlock = componentBlock . getNextBlock ( ) ;
376
+ }
377
+ }
308
378
} ) ;
309
379
}
310
380
@@ -330,6 +400,25 @@ export function getComponents(
330
400
} ) ;
331
401
}
332
402
403
+ export function getPrivateComponents (
404
+ workspace : Blockly . Workspace ,
405
+ components : storageModuleContent . Component [ ] ) : void {
406
+ // Get the holder block and ask it for the private components.
407
+ workspace . getBlocksByType ( BLOCK_NAME ) . forEach ( block => {
408
+ const privateComponentsFromHolder : storageModuleContent . Component [ ] =
409
+ ( block as MechanismComponentHolderBlock ) . getPrivateComponents ( ) ;
410
+ components . push ( ...privateComponentsFromHolder ) ;
411
+ } ) ;
412
+ }
413
+
414
+ export function getAllComponents (
415
+ workspace : Blockly . Workspace ,
416
+ components : storageModuleContent . Component [ ] ) : void {
417
+ // Get both regular and private components for when creating a mechanism
418
+ getComponents ( workspace , components ) ;
419
+ getPrivateComponents ( workspace , components ) ;
420
+ }
421
+
333
422
export function getEvents (
334
423
workspace : Blockly . Workspace ,
335
424
events : storageModuleContent . Event [ ] ) : void {
@@ -340,3 +429,17 @@ export function getEvents(
340
429
events . push ( ...eventsFromHolder ) ;
341
430
} ) ;
342
431
}
432
+
433
+ /**
434
+ * Hide private components.
435
+ * This function should only be called when upgrading old projects.
436
+ */
437
+ export function hidePrivateComponents ( workspace : Blockly . Workspace ) {
438
+ // Make sure the workspace is headless.
439
+ if ( workspace . rendered ) {
440
+ throw new Error ( 'hidePrivateComponents should never be called with a rendered workspace.' ) ;
441
+ }
442
+ workspace . getBlocksByType ( BLOCK_NAME ) . forEach ( block => {
443
+ ( block as MechanismComponentHolderBlock ) . mrcHidePrivateComponents = true ;
444
+ } ) ;
445
+ }
0 commit comments