Skip to content

Commit 7356de7

Browse files
committed
Added src/blocks/utils/workspaces.ts, which contains functions related to keeping track of blockly workspaces.
Modified editor to call workspaces.addWorkspace and workspaces.removeWorkspace Modified existing code that use headless blockly workspaces to call workspaces.createHeadlessWorkspace and workspaces.destroyHeadlessWorkspace.
1 parent 80ea080 commit 7356de7

File tree

6 files changed

+83
-16
lines changed

6 files changed

+83
-16
lines changed

src/blocks/utils/workspaces.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* @license
3+
* Copyright 2025 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* @author lizlooney@google.com (Liz Looney)
20+
*/
21+
22+
import * as Blockly from 'blockly/core';
23+
import * as storageModule from '../../storage/module';
24+
25+
const workspaceIdToModuleType: { [workspaceId: string]: storageModule.ModuleType } = {};
26+
27+
export function addWorkspace(workspace: Blockly.Workspace, moduleType: storageModule.ModuleType): void {
28+
workspaceIdToModuleType[workspace.id] = moduleType;
29+
}
30+
31+
export function removeWorkspace(workspace: Blockly.Workspace): void {
32+
if (workspace.id in workspaceIdToModuleType) {
33+
delete workspaceIdToModuleType[workspace.id];
34+
}
35+
}
36+
37+
export function getModuleTypeForWorkspace(workspace: Blockly.Workspace): storageModule.ModuleType {
38+
if (workspace.id in workspaceIdToModuleType) {
39+
return workspaceIdToModuleType[workspace.id];
40+
}
41+
throw new Error('getModuleTypeForWorkspace: workspaceId not found: ' + workspace.id);
42+
}
43+
44+
export function createHeadlessWorkspace(moduleType: storageModule.ModuleType): Blockly.Workspace {
45+
const workspace = new Blockly.Workspace();
46+
addWorkspace(workspace, moduleType);
47+
return workspace;
48+
}
49+
50+
export function destroyHeadlessWorkspace(workspace: Blockly.Workspace): void {
51+
removeWorkspace(workspace);
52+
workspace.dispose();
53+
}

src/editor/editor.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import * as storageProject from '../storage/project';
3030
import * as eventHandler from '../blocks/mrc_event_handler';
3131
import * as classMethodDef from '../blocks/mrc_class_method_def';
3232
import * as mechanismComponentHolder from '../blocks/mrc_mechanism_component_holder';
33+
import * as workspaces from '../blocks/utils/workspaces';
3334
//import { testAllBlocksInToolbox } from '../toolbox/toolbox_tests';
3435
import { applyExpandedCategories, getToolboxJSON } from '../toolbox/toolbox';
3536

@@ -70,6 +71,7 @@ export class Editor {
7071
project: storageProject.Project,
7172
storage: commonStorage.Storage,
7273
modulePathToContentText: {[modulePath: string]: string}) {
74+
workspaces.addWorkspace(blocklyWorkspace, module.moduleType);
7375
this.blocklyWorkspace = blocklyWorkspace;
7476
this.module = module;
7577
this.projectName = project.projectName;
@@ -186,6 +188,7 @@ export class Editor {
186188
}
187189

188190
public abandon(): void {
191+
workspaces.removeWorkspace(this.blocklyWorkspace);
189192
if (Editor.currentEditor === this) {
190193
Editor.currentEditor = null;
191194
}
@@ -250,7 +253,7 @@ export class Editor {
250253
if (toolbox != this.toolbox) {
251254
this.toolbox = toolbox;
252255
this.blocklyWorkspace.updateToolbox(toolbox);
253-
// testAllBlocksInToolbox(toolbox);
256+
// testAllBlocksInToolbox(toolbox, this.module.moduleType);
254257
}
255258
}
256259

src/storage/create_python_files.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*/
2323

2424
import * as Blockly from 'blockly/core';
25+
import * as workspaces from '../blocks/utils/workspaces';
2526
import { extendedPythonGenerator } from '../editor/extended_python_generator';
2627
import { Storage } from './common_storage';
2728
import { Module } from './module';
@@ -61,7 +62,7 @@ async function generatePythonForModule(module: Module, storage: Storage): Promis
6162
const moduleContent = parseModuleContentText(moduleContentText);
6263

6364
// Create a headless workspace
64-
const workspace = new Blockly.Workspace();
65+
const workspace = workspaces.createHeadlessWorkspace(module.moduleType);
6566

6667
// Parse and load the JSON into the workspace
6768
const blocks = moduleContent.getBlocks();
@@ -71,7 +72,7 @@ async function generatePythonForModule(module: Module, storage: Storage): Promis
7172
const pythonCode = extendedPythonGenerator.mrcWorkspaceToCode(workspace, module);
7273

7374
// Clean up the workspace
74-
workspace.dispose();
75+
workspaces.destroyHeadlessWorkspace(workspace);
7576

7677
return {
7778
moduleName: moduleName,

src/storage/module_content.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import * as storageNames from './names';
2525
import startingOpModeBlocks from '../modules/opmode_start.json';
2626
import startingMechanismBlocks from '../modules/mechanism_start.json';
2727
import startingRobotBlocks from '../modules/robot_start.json';
28+
import * as workspaces from '../blocks/utils/workspaces';
2829

2930
export type MethodArg = {
3031
name: string,
@@ -253,7 +254,7 @@ export class ModuleContent {
253254

254255
if (Object.keys(oldIdToNewId).length) {
255256
// Change the ids in the blocks.
256-
const workspace = new Blockly.Workspace();
257+
const workspace = workspaces.createHeadlessWorkspace(this.moduleType);
257258
Blockly.serialization.workspaces.load(this.blocks, workspace);
258259
workspace.getAllBlocks().forEach(block => {
259260
if ('mrcChangeIds' in block && typeof block.mrcChangeIds === "function") {
@@ -263,7 +264,7 @@ export class ModuleContent {
263264
this.blocks = Blockly.serialization.workspaces.save(workspace);
264265

265266
// Clean up the workspace
266-
workspace.dispose();
267+
workspaces.destroyHeadlessWorkspace(workspace);
267268
}
268269
}
269270
}

src/storage/upgrade_project.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import * as storageModuleContent from './module_content';
2929
import * as storageNames from './names';
3030
import * as storageProject from './project';
3131
import { ClassMethodDefBlock, BLOCK_NAME as MRC_CLASS_METHOD_DEF_BLOCK_NAME } from '../blocks/mrc_class_method_def';
32+
import * as workspaces from '../blocks/utils/workspaces';
3233

3334
export const NO_VERSION = '0.0.0';
3435
export const CURRENT_VERSION = '0.0.3';
@@ -82,14 +83,16 @@ async function upgradeFrom_001_to_002(
8283
// mrc_mechanism_component_holder block.
8384
const moduleContent = storageModuleContent.parseModuleContentText(moduleContentText);
8485
let blocks = moduleContent.getBlocks();
86+
8587
// Create a temporary workspace to upgrade the blocks.
86-
const headlessWorkspace = new Blockly.Workspace();
88+
const headlessWorkspace = workspaces.createHeadlessWorkspace(storageModule.ModuleType.ROBOT);
89+
8790
try {
8891
Blockly.serialization.workspaces.load(blocks, headlessWorkspace);
8992
mechanismComponentHolder.hidePrivateComponents(headlessWorkspace);
9093
blocks = Blockly.serialization.workspaces.save(headlessWorkspace);
9194
} finally {
92-
headlessWorkspace.dispose();
95+
workspaces.destroyHeadlessWorkspace(headlessWorkspace);
9396
}
9497
moduleContent.setBlocks(blocks);
9598
moduleContentText = moduleContent.getModuleContentText();
@@ -116,8 +119,9 @@ async function upgradeFrom_002_to_003(
116119
const moduleContent = storageModuleContent.parseModuleContentText(moduleContentText);
117120
let blocks = moduleContent.getBlocks();
118121

119-
// Create a temporary workspace to upgrade the blocks
120-
const headlessWorkspace = new Blockly.Workspace();
122+
// Create a temporary workspace to upgrade the blocks.
123+
const headlessWorkspace = workspaces.createHeadlessWorkspace(storageModule.ModuleType.ROBOT);
124+
121125
try {
122126
Blockly.serialization.workspaces.load(blocks, headlessWorkspace);
123127

@@ -127,7 +131,7 @@ async function upgradeFrom_002_to_003(
127131
});
128132
blocks = Blockly.serialization.workspaces.save(headlessWorkspace);
129133
} finally {
130-
headlessWorkspace.dispose();
134+
workspaces.destroyHeadlessWorkspace(headlessWorkspace);
131135
}
132136

133137
moduleContent.setBlocks(blocks);

src/toolbox/toolbox_tests.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
import * as Blockly from 'blockly/core';
2323
import { extendedPythonGenerator } from '../editor/extended_python_generator';
2424
import * as toolboxItems from './items';
25+
import * as storageModule from '../storage/module';
26+
import * as workspaces from '../blocks/utils/workspaces';
2527

2628
// Tests
2729

28-
export function testAllBlocksInToolbox(toolbox : Blockly.utils.toolbox.ToolboxInfo) {
29-
const contents = toolbox.contents;
30+
export function testAllBlocksInToolbox(toolbox : Blockly.utils.toolbox.ToolboxInfo, moduleType: storageModule.ModuleType) {
31+
const contents = toolbox.contents;
3032
alert('Press OK to run tests on all blocks from the toolbox.');
31-
const toolboxTestData = new ToolboxTestData(contents, () => {
33+
const toolboxTestData = new ToolboxTestData(contents, moduleType, () => {
3234
alert('Completed tests on all blocks in the toolbox. See console for any errors.');
3335
});
3436
toolboxTestData.runTests();
@@ -40,9 +42,12 @@ class ToolboxTestData {
4042
jsonBlocks: toolboxItems.Block[];
4143
index: number;
4244

43-
constructor(contents: toolboxItems.ContentsType[] | undefined, onFinish: () => void) {
45+
constructor(
46+
contents: toolboxItems.ContentsType[] | undefined,
47+
moduleType: storageModule.ModuleType,
48+
onFinish: () => void) {
4449
this.onFinish = onFinish;
45-
this.blocklyWorkspace = new Blockly.Workspace();
50+
this.blocklyWorkspace = workspaces.createHeadlessWorkspace(moduleType);
4651
this.blocklyWorkspace.MAX_UNDO = 0;
4752
this.jsonBlocks = [];
4853
if (contents){
@@ -95,7 +100,7 @@ class ToolboxTestData {
95100
if (this.index < this.jsonBlocks.length) {
96101
setTimeout(this.testCallback.bind(this), 0);
97102
} else {
98-
this.blocklyWorkspace.dispose();
103+
workspaces.destroyHeadlessWorkspace(this.blocklyWorkspace);
99104
if (this.onFinish) {
100105
this.onFinish();
101106
}

0 commit comments

Comments
 (0)