@@ -8,9 +8,9 @@ import { getCategory as getEventCategory } from './event_category';
88
99export 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+ }
0 commit comments