Skip to content

Commit a94de8d

Browse files
authored
Make the toolbox categories stay expanded or collapsed when the toolbox is updated. (#246)
Use Blockly.utils.toolbox.ToolboxInfo instead of Blockly.utils.toolbox.ToolboxDefinition.
1 parent 3adb51f commit a94de8d

File tree

3 files changed

+78
-7
lines changed

3 files changed

+78
-7
lines changed

src/editor/editor.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ 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';
3333
//import { testAllBlocksInToolbox } from '../toolbox/toolbox_tests';
34-
import { getToolboxJSON } from '../toolbox/toolbox';
34+
import { applyExpandedCategories, getToolboxJSON } from '../toolbox/toolbox';
3535

36-
const EMPTY_TOOLBOX: Blockly.utils.toolbox.ToolboxDefinition = {
36+
const EMPTY_TOOLBOX: Blockly.utils.toolbox.ToolboxInfo = {
3737
kind: 'categoryToolbox',
3838
contents: [],
3939
};
@@ -58,7 +58,7 @@ export class Editor {
5858
private mechanismClassNameToModuleContent: {[mechanismClassName: string]: storageModuleContent.ModuleContent} = {};
5959
private bindedOnChange: any = null;
6060
private shownPythonToolboxCategories: Set<string> | null = null;
61-
private toolbox: Blockly.utils.toolbox.ToolboxDefinition = EMPTY_TOOLBOX;
61+
private toolbox: Blockly.utils.toolbox.ToolboxInfo = EMPTY_TOOLBOX;
6262

6363
constructor(
6464
blocklyWorkspace: Blockly.WorkspaceSvg,
@@ -199,6 +199,10 @@ export class Editor {
199199
return;
200200
}
201201
const toolbox = getToolboxJSON(this.shownPythonToolboxCategories, this);
202+
const previousToolbox = this.blocklyWorkspace.getToolbox();
203+
if (previousToolbox) {
204+
applyExpandedCategories(previousToolbox, toolbox);
205+
}
202206
if (toolbox != this.toolbox) {
203207
this.toolbox = toolbox;
204208
this.blocklyWorkspace.updateToolbox(toolbox);

src/toolbox/toolbox.ts

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import { getCategory as getEventCategory } from './event_category';
88

99
export function getToolboxJSON(
1010
shownPythonToolboxCategories: Set<string> | null,
11-
editor: Editor): Blockly.utils.toolbox.ToolboxDefinition {
11+
editor: Editor): Blockly.utils.toolbox.ToolboxInfo {
1212

13-
const toolbox: Blockly.utils.toolbox.ToolboxDefinition = {
13+
const toolbox: Blockly.utils.toolbox.ToolboxInfo = {
1414
kind: 'categoryToolbox',
1515
contents: []
1616
};
@@ -34,3 +34,70 @@ export function getToolboxJSON(
3434
// This trouble is prevented by stringifying and parsing.
3535
return JSON.parse(JSON.stringify(toolbox));
3636
}
37+
38+
/**
39+
* Collects the expanded/collapsed state of categories in the previous toolbox and applies them
40+
* to the new toolbox.
41+
*/
42+
export function applyExpandedCategories(
43+
previousToolbox: Blockly.IToolbox,
44+
newToolbox: Blockly.utils.toolbox.ToolboxInfo) {
45+
const expanded: {[categoryPath: string]: boolean} = {};
46+
recursivelyCollectExpandedCategories((previousToolbox as any).getToolboxItems(), expanded, '', null);
47+
recursivelyApplyExpandedCategories(newToolbox.contents, expanded, '');
48+
}
49+
50+
/**
51+
* Collects the expanded/collapsed state for all collapsible items.
52+
*/
53+
function recursivelyCollectExpandedCategories(
54+
items: Blockly.IToolboxItem[],
55+
expanded: {[categoryPath: string]: boolean},
56+
parentPath: string,
57+
parent: Blockly.IToolboxItem | null) {
58+
items
59+
.filter(item => item.getParent() == parent)
60+
.filter(item => item.isCollapsible())
61+
.forEach(item => {
62+
const collapsibleItem = item as Blockly.ICollapsibleToolboxItem;
63+
const path = makePath(parentPath, collapsibleItem.getName());
64+
expanded[path] = collapsibleItem.isExpanded();
65+
recursivelyCollectExpandedCategories(
66+
collapsibleItem.getChildToolboxItems(), expanded, path, item);
67+
});
68+
}
69+
70+
/**
71+
* Applies previously collected expanded/collapsed state to the given toolbox categories.
72+
*/
73+
function recursivelyApplyExpandedCategories(
74+
contents: toolboxItems.ContentsType[],
75+
expanded: {[categoryPath: string]: boolean},
76+
parentPath: string) {
77+
contents
78+
.filter(item => item.kind === 'category')
79+
.forEach(item => {
80+
const category = item as toolboxItems.Category;
81+
const path = makePath(parentPath, category.name);
82+
if (path in expanded) {
83+
if (expanded[path]) {
84+
category.expanded = true;
85+
} else {
86+
delete category.expanded;
87+
}
88+
}
89+
if (category.contents) {
90+
recursivelyApplyExpandedCategories(category.contents, expanded, path);
91+
}
92+
});
93+
}
94+
95+
/**
96+
* Returns a string that combines the given parentPath with the given child.
97+
*/
98+
function makePath(parentPath: string, child: string) {
99+
if (parentPath) {
100+
return parentPath + '\u2705' + child;
101+
}
102+
return child;
103+
}

src/toolbox/toolbox_tests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import * as toolboxItems from './items';
2525

2626
// Tests
2727

28-
export function testAllBlocksInToolbox(toolbox : Blockly.utils.toolbox.ToolboxDefinition) {
29-
const contents = (toolbox as toolboxItems.Category).contents;
28+
export function testAllBlocksInToolbox(toolbox : Blockly.utils.toolbox.ToolboxInfo) {
29+
const contents = toolbox.contents;
3030
alert('Press OK to run tests on all blocks from the toolbox.');
3131
const toolboxTestData = new ToolboxTestData(contents, () => {
3232
alert('Completed tests on all blocks in the toolbox. See console for any errors.');

0 commit comments

Comments
 (0)