Skip to content

Commit b4a1834

Browse files
authored
Merge pull request #8 from lizlooney/pr_private_components_in_mechanism
Regular and private components in mechanism
2 parents 6e4eb38 + d7cbbb3 commit b4a1834

File tree

10 files changed

+316
-205
lines changed

10 files changed

+316
-205
lines changed

src/blocks/mrc_call_python_function.ts

Lines changed: 144 additions & 97 deletions
Large diffs are not rendered by default.

src/blocks/mrc_mechanism.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,9 @@ const MECHANISM = {
205205
}
206206

207207
if (foundMechanism) {
208-
const components: storageModuleContent.Component[] = [];
209-
components.push(...editor.getAllComponentsFromMechanism(foundMechanism));
208+
// Here we need all the components (regular and private) from the mechanism because we need
209+
// to create port parameters for all the components.
210+
const components = editor.getAllComponentsFromMechanism(foundMechanism);
210211

211212
// If the mechanism class name has changed, update this blcok.
212213
if (this.getFieldValue(FIELD_TYPE) !== foundMechanism.className) {

src/blocks/mrc_mechanism_component_holder.ts

Lines changed: 44 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,10 @@ function setName(block: Blockly.BlockSvg){
7575

7676
const MECHANISM_COMPONENT_HOLDER = {
7777
/**
78-
* Block initialization.
79-
*/
78+
* Block initialization.
79+
*/
8080
init: function (this: MechanismComponentHolderBlock): void {
8181
this.setInputsInline(false);
82-
this.appendStatementInput(INPUT_MECHANISMS).setCheck(MECHANISM_OUTPUT).appendField(Blockly.Msg.MECHANISMS);
83-
this.appendStatementInput(INPUT_COMPONENTS).setCheck(COMPONENT_OUTPUT).appendField(Blockly.Msg.COMPONENTS);
84-
const privateComponentsInput = this.appendStatementInput(INPUT_PRIVATE_COMPONENTS).setCheck(COMPONENT_OUTPUT).appendField(Blockly.Msg.PRIVATE_COMPONENTS);
85-
// Set tooltip on the private components field
86-
const privateComponentsField = privateComponentsInput.fieldRow[0];
87-
if (privateComponentsField) {
88-
privateComponentsField.setTooltip(Blockly.Msg.PRIVATE_COMPONENTS_TOOLTIP);
89-
}
90-
this.appendStatementInput(INPUT_EVENTS).setCheck(EVENT_OUTPUT).appendField(Blockly.Msg.EVENTS);
91-
92-
// Update components tooltip based on private components visibility
93-
this.updateComponentsTooltip_();
94-
9582
this.setOutput(false);
9683
this.setStyle(MRC_STYLE_MECHANISMS);
9784
ChangeFramework.registerCallback(MRC_COMPONENT_NAME, [Blockly.Events.BLOCK_MOVE, Blockly.Events.BLOCK_CHANGE], this.onBlockChanged);
@@ -112,65 +99,43 @@ const MECHANISM_COMPONENT_HOLDER = {
11299
return extraState;
113100
},
114101
/**
115-
* Applies the given state to this block.
116-
*/
102+
* Applies the given state to this block.
103+
*/
117104
loadExtraState: function (this: MechanismComponentHolderBlock, extraState: MechanismComponentHolderExtraState): void {
118105
this.mrcHideMechanisms = (extraState.hideMechanisms == undefined) ? false : extraState.hideMechanisms;
119106
this.mrcHidePrivateComponents = (extraState.hidePrivateComponents == undefined) ? false : extraState.hidePrivateComponents;
120107
this.updateBlock_();
121108
},
122109
/**
123-
* Update the components tooltip based on private components visibility.
110+
* Update the block to reflect the newly loaded extra state.
124111
*/
125-
updateComponentsTooltip_: function (this: MechanismComponentHolderBlock): void {
126-
const componentsInput = this.getInput(INPUT_COMPONENTS);
127-
if (componentsInput && componentsInput.fieldRow[0]) {
128-
const componentsField = componentsInput.fieldRow[0];
129-
// Only show tooltip if private components are also visible (not hidden)
130-
if (!this.mrcHidePrivateComponents) {
131-
componentsField.setTooltip(Blockly.Msg.COMPONENTS_TOOLTIP);
132-
} else {
133-
componentsField.setTooltip('');
134-
}
135-
}
136-
},
137-
/**
138-
* Update the block to reflect the newly loaded extra state.
139-
*/
140112
updateBlock_: function (this: MechanismComponentHolderBlock): void {
141113
// Handle mechanisms input visibility
142-
if (this.mrcHideMechanisms) {
143-
if (this.getInput(INPUT_MECHANISMS)) {
144-
this.removeInput(INPUT_MECHANISMS)
145-
}
146-
}
147-
else {
148-
if (this.getInput(INPUT_MECHANISMS) == null) {
149-
this.appendStatementInput(INPUT_MECHANISMS).setCheck(MECHANISM_OUTPUT).appendField(Blockly.Msg.MECHANISMS);
150-
this.moveInputBefore(INPUT_MECHANISMS, INPUT_COMPONENTS)
151-
}
114+
if (!this.mrcHideMechanisms) {
115+
this.appendStatementInput(INPUT_MECHANISMS)
116+
.setCheck(MECHANISM_OUTPUT)
117+
.appendField(Blockly.Msg.MECHANISMS);
152118
}
153119

120+
const componentsField = new Blockly.FieldLabel(Blockly.Msg.COMPONENTS);
121+
this.appendStatementInput(INPUT_COMPONENTS)
122+
.setCheck(COMPONENT_OUTPUT)
123+
.appendField(componentsField);
124+
154125
// Handle private components input visibility
155-
if (this.mrcHidePrivateComponents) {
156-
if (this.getInput(INPUT_PRIVATE_COMPONENTS)) {
157-
this.removeInput(INPUT_PRIVATE_COMPONENTS)
158-
}
159-
}
160-
else {
161-
if (this.getInput(INPUT_PRIVATE_COMPONENTS) == null) {
162-
const privateComponentsInput = this.appendStatementInput(INPUT_PRIVATE_COMPONENTS).setCheck(COMPONENT_OUTPUT).appendField(Blockly.Msg.PRIVATE_COMPONENTS);
163-
// Set tooltip on the field
164-
const privateComponentsField = privateComponentsInput.fieldRow[0];
165-
if (privateComponentsField) {
166-
privateComponentsField.setTooltip(Blockly.Msg.PRIVATE_COMPONENTS_TOOLTIP);
167-
}
168-
this.moveInputBefore(INPUT_PRIVATE_COMPONENTS, INPUT_EVENTS)
169-
}
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);
170134
}
171-
172-
// Update components tooltip based on private components visibility
173-
this.updateComponentsTooltip_();
135+
136+
this.appendStatementInput(INPUT_EVENTS)
137+
.setCheck(EVENT_OUTPUT)
138+
.appendField(Blockly.Msg.EVENTS);
174139
},
175140
onBlockChanged: function (block: Blockly.BlockSvg, blockEvent: Blockly.Events.BlockBase) {
176141
if (blockEvent.type == Blockly.Events.BLOCK_MOVE) {
@@ -319,9 +284,9 @@ function pythonFromBlockInMechanism(block: MechanismComponentHolderBlock, genera
319284
const components = generator.statementToCode(block, INPUT_COMPONENTS);
320285
const privateComponents = generator.statementToCode(block, INPUT_PRIVATE_COMPONENTS);
321286

322-
const body = components + privateComponents;
323-
if (body) {
324-
code += body;
287+
const allComponents = components + privateComponents;
288+
if (allComponents) {
289+
code += allComponents;
325290
generator.addClassMethodDefinition('define_hardware', code);
326291
}
327292
}
@@ -342,7 +307,7 @@ export const pythonFromBlock = function (
342307

343308
// Misc
344309

345-
/**n
310+
/**
346311
* Returns true if the given workspace has a mrc_mechanism_component_holder
347312
* block that contains at least one component.
348313
*/
@@ -464,3 +429,17 @@ export function getEvents(
464429
events.push(...eventsFromHolder);
465430
});
466431
}
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+
}

src/editor/editor.ts

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -246,25 +246,26 @@ export class Editor {
246246
const blocks = Blockly.serialization.workspaces.save(this.blocklyWorkspace);
247247
const mechanisms: storageModuleContent.MechanismInRobot[] = this.getMechanismsFromWorkspace();
248248
const components: storageModuleContent.Component[] = this.getComponentsFromWorkspace();
249+
const privateComponents: storageModuleContent.Component[] = this.getPrivateComponentsFromWorkspace();
249250
const events: storageModuleContent.Event[] = this.getEventsFromWorkspace();
250251
const methods: storageModuleContent.Method[] = (
251252
this.currentModule?.moduleType === storageModule.ModuleType.ROBOT ||
252253
this.currentModule?.moduleType === storageModule.ModuleType.MECHANISM)
253254
? this.getMethodsForOutsideFromWorkspace()
254255
: [];
255256
return storageModuleContent.makeModuleContentText(
256-
this.currentModule, blocks, mechanisms, components, events, methods);
257+
this.currentModule, blocks, mechanisms, components, privateComponents, events, methods);
257258
}
258259

259-
public getMechanismsFromWorkspace(): storageModuleContent.MechanismInRobot[] {
260+
private getMechanismsFromWorkspace(): storageModuleContent.MechanismInRobot[] {
260261
const mechanisms: storageModuleContent.MechanismInRobot[] = [];
261262
if (this.currentModule?.moduleType === storageModule.ModuleType.ROBOT) {
262263
mechanismComponentHolder.getMechanisms(this.blocklyWorkspace, mechanisms);
263264
}
264265
return mechanisms;
265266
}
266267

267-
public getComponentsFromWorkspace(): storageModuleContent.Component[] {
268+
private getComponentsFromWorkspace(): storageModuleContent.Component[] {
268269
const components: storageModuleContent.Component[] = [];
269270
if (this.currentModule?.moduleType === storageModule.ModuleType.ROBOT ||
270271
this.currentModule?.moduleType === storageModule.ModuleType.MECHANISM) {
@@ -273,6 +274,14 @@ export class Editor {
273274
return components;
274275
}
275276

277+
private getPrivateComponentsFromWorkspace(): storageModuleContent.Component[] {
278+
const components: storageModuleContent.Component[] = [];
279+
if (this.currentModule?.moduleType === storageModule.ModuleType.MECHANISM) {
280+
mechanismComponentHolder.getPrivateComponents(this.blocklyWorkspace, components);
281+
}
282+
return components;
283+
}
284+
276285
public getAllComponentsFromWorkspace(): storageModuleContent.Component[] {
277286
const components: storageModuleContent.Component[] = [];
278287
if (this.currentModule?.moduleType === storageModule.ModuleType.ROBOT ||
@@ -288,7 +297,7 @@ export class Editor {
288297
return methods;
289298
}
290299

291-
public getMethodsForOutsideFromWorkspace(): storageModuleContent.Method[] {
300+
private getMethodsForOutsideFromWorkspace(): storageModuleContent.Method[] {
292301
const methods: storageModuleContent.Method[] = [];
293302
classMethodDef.getMethodsForOutside(this.blocklyWorkspace, methods);
294303
return methods;
@@ -433,24 +442,12 @@ export class Editor {
433442
return this.getAllComponentsFromWorkspace();
434443
}
435444
if (mechanism.className in this.mechanismClassNameToModuleContent) {
436-
// For saved mechanisms, we need to reconstruct all components from the blocks
437-
// since only public components are saved in the module content
438445
const moduleContent = this.mechanismClassNameToModuleContent[mechanism.className];
439-
const blocks = moduleContent.getBlocks();
440-
441-
// Create a temporary workspace to load the mechanism's blocks
442-
const tempWorkspace = new Blockly.Workspace();
443-
try {
444-
Blockly.serialization.workspaces.load(blocks, tempWorkspace);
445-
446-
// Extract all components (public and private) from the temporary workspace
447-
const allComponents: storageModuleContent.Component[] = [];
448-
mechanismComponentHolder.getAllComponents(tempWorkspace, allComponents);
449-
450-
return allComponents;
451-
} finally {
452-
tempWorkspace.dispose();
453-
}
446+
const allComponents: storageModuleContent.Component[] = [
447+
...moduleContent.getComponents(),
448+
...moduleContent.getPrivateComponents(),
449+
]
450+
return allComponents;
454451
}
455452
throw new Error('getAllComponentsFromMechanism: mechanism not found: ' + mechanism.className);
456453
}

src/modules/mechanism_start.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
{
66
"type": "mrc_class_method_def",
77
"x": 10,
8-
"y": 110,
8+
"y": 150,
99
"deletable": false,
1010
"editable": false,
1111
"extraState": {
@@ -23,7 +23,7 @@
2323
{
2424
"type": "mrc_class_method_def",
2525
"x": 10,
26-
"y": 190,
26+
"y": 230,
2727
"deletable": false,
2828
"editable": false,
2929
"extraState": {

src/modules/robot_start.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
"y": 10,
2727
"deletable": false,
2828
"editable": false,
29-
"extraState": {}
29+
"extraState": {
30+
"hidePrivateComponents" : true
31+
}
3032
}
3133
]
3234
}

src/storage/module_content.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,18 @@ export type Event = {
6060
};
6161

6262
function startingBlocksToModuleContentText(
63-
module: storageModule.Module, startingBlocks: { [key: string]: any }): string {
63+
module: storageModule.Module, startingBlocks: {[key: string]: any}): string {
6464
const mechanisms: MechanismInRobot[] = [];
6565
const components: Component[] = [];
66+
const privateComponents: Component[] = [];
6667
const events: Event[] = [];
6768
const methods: Method[] = [];
6869
return makeModuleContentText(
6970
module,
7071
startingBlocks,
7172
mechanisms,
7273
components,
74+
privateComponents,
7375
events,
7476
methods);
7577
}
@@ -125,9 +127,10 @@ export function newOpModeContent(projectName: string, opModeClassName: string):
125127
*/
126128
export function makeModuleContentText(
127129
module: storageModule.Module,
128-
blocks: { [key: string]: any },
130+
blocks: {[key: string]: any},
129131
mechanisms: MechanismInRobot[],
130132
components: Component[],
133+
privateComponents: Component[],
131134
events: Event[],
132135
methods: Method[]): string {
133136
if (!module.moduleId) {
@@ -139,6 +142,7 @@ export function makeModuleContentText(
139142
blocks,
140143
mechanisms,
141144
components,
145+
privateComponents,
142146
events,
143147
methods);
144148
return moduleContent.getModuleContentText();
@@ -151,6 +155,7 @@ export function parseModuleContentText(moduleContentText: string): ModuleContent
151155
!('blocks' in parsedContent) ||
152156
!('mechanisms' in parsedContent) ||
153157
!('components' in parsedContent) ||
158+
!('privateComponents' in parsedContent) ||
154159
!('events' in parsedContent) ||
155160
!('methods' in parsedContent)) {
156161
throw new Error('Module content text is not valid.');
@@ -161,6 +166,7 @@ export function parseModuleContentText(moduleContentText: string): ModuleContent
161166
parsedContent.blocks,
162167
parsedContent.mechanisms,
163168
parsedContent.components,
169+
parsedContent.privateComponents,
164170
parsedContent.events,
165171
parsedContent.methods);
166172
}
@@ -169,9 +175,10 @@ export class ModuleContent {
169175
constructor(
170176
private moduleType: storageModule.ModuleType,
171177
private moduleId: string,
172-
private blocks : { [key: string]: any },
178+
private blocks : {[key: string]: any},
173179
private mechanisms: MechanismInRobot[],
174180
private components: Component[],
181+
private privateComponents: Component[],
175182
private events: Event[],
176183
private methods: Method[]) {
177184
}
@@ -188,10 +195,14 @@ export class ModuleContent {
188195
return this.moduleId;
189196
}
190197

191-
getBlocks(): { [key: string]: any } {
198+
getBlocks(): {[key: string]: any} {
192199
return this.blocks;
193200
}
194201

202+
setBlocks(blocks: {[key: string]: any}): void {
203+
this.blocks = blocks;
204+
}
205+
195206
getMechanisms(): MechanismInRobot[] {
196207
return this.mechanisms;
197208
}
@@ -200,6 +211,10 @@ export class ModuleContent {
200211
return this.components;
201212
}
202213

214+
getPrivateComponents(): Component[] {
215+
return this.privateComponents;
216+
}
217+
203218
getEvents(): Event[] {
204219
return this.events;
205220
}
@@ -252,3 +267,15 @@ export class ModuleContent {
252267
}
253268
}
254269
}
270+
271+
/**
272+
* Add privateComponents field.
273+
* This function should only called when upgrading old projects.
274+
*/
275+
export function addPrivateComponents(moduleContentText: string): string {
276+
const parsedContent = JSON.parse(moduleContentText);
277+
if (!('privateComponents' in parsedContent)) {
278+
parsedContent.privateComponents = [];
279+
}
280+
return JSON.stringify(parsedContent, null, 2);
281+
}

0 commit comments

Comments
 (0)