66'use strict' ;
77
88import { ISpliceable } from 'vs/base/common/sequence' ;
9- import { IIterator } from 'vs/base/common/iterator' ;
9+ import { Tree } from 'vs/base/common/tree' ;
10+ import { tail2 } from 'vs/base/common/arrays' ;
11+ import { Trie } from 'vs/base/browser/ui/list/trie' ;
1012
1113export interface ITreeElement < T > {
1214 readonly element : T ;
1315 readonly children : ITreeElement < T > [ ] ;
1416}
1517
16- export interface ITreeNode < T > {
18+ export interface ITreeListElement < T > {
1719 readonly element : T ;
1820 readonly depth : number ;
1921}
2022
21- class TreeNodeIterator < T > implements IIterator < ITreeElement < T > > {
22-
23- private stack : TreeNode < T > [ ] = [ ] ;
24-
25- constructor ( node : TreeNode < T > ) {
26- this . stack . push ( node ) ;
27- }
28-
29- next ( ) : { readonly done : boolean ; readonly value : ITreeElement < T > ; } {
30- const value = this . stack . pop ( ) ;
31-
32- for ( let i = value . children . length - 1 ; i >= 0 ; i -- ) {
33- this . stack . push ( value . children [ i ] ) ;
34- }
35-
36- return { done : this . stack . length === 0 , value } ;
37- }
38- }
39-
40- class TreeNodesIterator < T > implements IIterator < ITreeElement < T > > {
41-
42- private index = 0 ;
43-
44- constructor ( private iterators : TreeNodeIterator < T > [ ] ) { }
45-
46- next ( ) : { readonly done : boolean ; readonly value : ITreeElement < T > | undefined ; } {
47- if ( this . index >= this . iterators . length ) {
48- return { done : true , value : undefined } ;
49- }
50-
51- const result = this . iterators [ this . index ] . next ( ) ;
52-
53- if ( result . done ) {
54- this . index ++ ;
55- }
56-
57- return result ;
58- }
59- }
60-
61- class TreeNode < T > implements ITreeNode < T > {
23+ class TreeNode < T > implements ITreeListElement < T > {
6224
6325 static createRoot < T > ( ) : TreeNode < T > {
6426 const node = new TreeNode < T > ( ) ;
@@ -68,15 +30,15 @@ class TreeNode<T> implements ITreeNode<T> {
6830 return node ;
6931 }
7032
71- static createNode < T > ( treeElement : ITreeElement < T > , depth : number , list : ITreeNode < T > [ ] ) : TreeNode < T > {
33+ static createNode < T > ( treeElement : ITreeElement < T > , depth : number , list : ITreeListElement < T > [ ] ) : TreeNode < T > {
7234 const node = new TreeNode < T > ( ) ;
7335 list . push ( node ) ;
7436
7537 let count = 1 ;
7638 const children : TreeNode < T > [ ] = [ ] ;
7739
78- for ( const element of treeElement . children ) {
79- const node = TreeNode . createNode < T > ( element , depth + 1 , list ) ;
40+ for ( const childItem of treeElement . children ) {
41+ const node = TreeNode . createNode < T > ( childItem , depth + 1 , list ) ;
8042 children . push ( node ) ;
8143 count += node . count ;
8244 }
@@ -96,51 +58,38 @@ class TreeNode<T> implements ITreeNode<T> {
9658
9759 private constructor ( ) { }
9860
99- splice ( index : number , deleteCount : number , elements : ITreeElement < T > [ ] ) : { listDeleteCount : number ; listElements : ITreeNode < T > [ ] ; deletedIterator : IIterator < ITreeElement < T > > ; } {
100- const listElements = [ ] as ITreeNode < T > [ ] ;
61+ splice ( index : number , deleteCount : number , treeElements : ITreeElement < T > [ ] ) : { listDeleteCount : number ; listElements : ITreeListElement < T > [ ] ; deletedNodes : TreeNode < T > [ ] ; } {
62+ const listElements = [ ] as ITreeListElement < T > [ ] ;
10163
102- const added = elements . map ( e => TreeNode . createNode < T > ( e , this . depth + 1 , listElements ) ) ;
64+ const added = treeElements . map ( e => TreeNode . createNode < T > ( e , this . depth + 1 , listElements ) ) ;
10365 const listAddCount = added . reduce ( ( r , n ) => r + n . count , 0 ) ;
10466
105- const deleted = this . children . splice ( index , deleteCount , ...added ) ;
106- const deletedIterator = new TreeNodesIterator ( deleted . map ( node => new TreeNodeIterator ( node ) ) ) ;
107- const listDeleteCount = deleted . reduce ( ( r , n ) => r + n . count , 0 ) ;
67+ const deletedNodes = this . children . splice ( index , deleteCount , ...added ) ;
68+ const listDeleteCount = deletedNodes . reduce ( ( r , n ) => r + n . count , 0 ) ;
10869
10970 this . count += listAddCount - listDeleteCount ;
110- return { listDeleteCount, listElements, deletedIterator } ;
71+ return { listDeleteCount, listElements, deletedNodes } ;
11172 }
11273}
11374
11475export class TreeModel < T > {
11576
11677 private root = TreeNode . createRoot < T > ( ) ;
11778
118- constructor ( private spliceable : ISpliceable < ITreeNode < T > > ) { }
79+ constructor ( private spliceable : ISpliceable < ITreeListElement < T > > ) { }
11980
120- splice ( start : number [ ] , deleteCount : number , elements : ITreeElement < T > [ ] = [ ] ) : IIterator < ITreeElement < T > > {
81+ splice ( start : number [ ] , deleteCount : number , elements : ITreeElement < T > [ ] = [ ] ) : ITreeElement < T > [ ] {
12182 if ( start . length === 0 ) {
12283 throw new Error ( 'Invalid tree location' ) ;
12384 }
12485
12586 const { parentNode, parentListIndex } = this . findParentNode ( start ) ;
12687 const lastIndex = start [ start . length - 1 ] ;
127- const { listDeleteCount, listElements, deletedIterator } = parentNode . splice ( lastIndex , deleteCount , elements ) ;
88+ const { listDeleteCount, listElements, deletedNodes } = parentNode . splice ( lastIndex , deleteCount , elements ) ;
12889
12990 this . spliceable . splice ( parentListIndex + lastIndex , listDeleteCount , listElements ) ;
13091
131- return deletedIterator ;
132- }
133-
134- getElement ( location : number [ ] ) : T | undefined {
135- const node = this . findNode ( location ) ;
136- return node && node . element ;
137- }
138-
139- private findNode ( location : number [ ] ) : TreeNode < T > {
140- const { parentNode } = this . findParentNode ( location ) ;
141- const lastIndex = location [ location . length - 1 ] ;
142-
143- return parentNode . children [ lastIndex ] ;
92+ return deletedNodes ;
14493 }
14594
14695 private findParentNode ( location : number [ ] , node : TreeNode < T > = this . root , listIndex : number = 0 ) : { parentNode : TreeNode < T > ; parentListIndex : number } {
@@ -151,6 +100,7 @@ export class TreeModel<T> {
151100 const [ i , ...rest ] = location ;
152101 const limit = Math . min ( i , node . children . length ) ;
153102
103+ // TODO@joao perf!
154104 for ( let j = 0 ; j < limit ; j ++ ) {
155105 listIndex += node . children [ j ] . count ;
156106 }
@@ -159,122 +109,60 @@ export class TreeModel<T> {
159109 }
160110}
161111
162- // type TrieNode<T> = TrieNode<T>[] | T;
163-
164- // [[], [], T]
165- // { key: 1, children: {} }
166- // { 1: { 2: {} } }
167-
168- type TrieNode < K , T > = { value : T | undefined , children : Map < K , TrieNode < K , T > > } ;
112+ export interface ICollapsibleTreeElement < T > {
113+ element : T ;
114+ collapsed : boolean ;
115+ }
169116
170- export class Trie < K , T > {
117+ export class CollapsibleTreeModel < T > {
171118
172- private root : TrieNode < K , T > ;
119+ private model = new Tree < ICollapsibleTreeElement < T > > ( ) ;
120+ private collapsedElements = new Trie < number , ITreeElement < T > > ( ) ;
121+ private visibleModel : TreeModel < T > ;
173122
174- constructor ( ) {
175- this . clear ( ) ;
123+ constructor ( spliceable : ISpliceable < ITreeListElement < T > > ) {
124+ this . visibleModel = new TreeModel < T > ( spliceable ) ;
176125 }
177126
178- set ( path : K [ ] , element : T ) : void {
179- if ( path . length === 0 ) {
180- throw new Error ( 'Invalid path length' ) ;
181- }
182-
183- let node = this . root ;
184-
185- for ( const key of path ) {
186- let child = node . children . get ( key ) ;
187-
188- if ( ! child ) {
189- child = { value : undefined , children : new Map < K , TrieNode < K , T > > ( ) } ;
190- node . children . set ( key , child ) ;
191- }
127+ splice ( start : number [ ] , deleteCount : number , items : ITreeElement < ICollapsibleTreeElement < T > > [ ] ) : void {
128+ // const elementPath = this.model.getElementPath(start);
192129
193- node = child ;
194- }
195-
196- node . value = element ;
130+ this . model . splice ( start , deleteCount , items ) ;
131+ // this.visibleModel.splice(start, deleteCount, items);
197132 }
198133
199- get ( path : K [ ] ) : T | undefined {
200- if ( path . length === 0 ) {
201- throw new Error ( 'Invalid path length' ) ;
202- }
203-
204- let node = this . root ;
134+ setCollapsed ( location : number [ ] , collapsed : boolean ) : void {
135+ const elementPath = this . model . getElementPath ( location ) ;
136+ const [ pathToElement , collapsibleElement ] = tail2 ( elementPath ) ;
205137
206- for ( const key of path ) {
207- let child = node . children . get ( key ) ;
208-
209- if ( ! child ) {
210- return undefined ;
211- }
212-
213- node = child ;
138+ if ( collapsibleElement . collapsed === collapsed ) {
139+ return ;
214140 }
215141
216- return node . value ;
217- }
218-
219- delete ( path : K [ ] ) : void {
220- if ( path . length === 0 ) {
221- throw new Error ( 'Invalid path length' ) ;
222- }
223-
224- let nodePath : { key : K , node : TrieNode < K , T > } [ ] = [ ] ;
225- let node = this . root ;
226-
227- for ( const key of path ) {
228- let child = node . children . get ( key ) ;
142+ collapsibleElement . collapsed = collapsed ;
229143
230- if ( ! child ) {
231- return ;
232- }
233-
234- nodePath . push ( { key, node } ) ;
235- node = child ;
144+ if ( pathToElement . some ( e => e . collapsed ) ) {
145+ return ;
236146 }
237147
238- for ( let i = nodePath . length - 1 ; i >= 0 ; i -- ) {
239- const { key, node } = nodePath [ i ] ;
240-
241- node . children . delete ( key ) ;
242-
243- if ( Object . keys ( node . children ) . length > 0 ) {
244- return ;
245- }
148+ if ( collapsed ) {
149+ const collapsedElement : ITreeElement < T > = {
150+ element : collapsibleElement . element ,
151+ children : [ ]
152+ } ;
153+
154+ const [ element ] = this . visibleModel . splice ( location , 1 , [ collapsedElement ] ) ;
155+ this . collapsedElements . set ( location , element ) ;
156+ } else {
157+ const expandedElement = this . collapsedElements . delete ( location ) ;
158+ this . visibleModel . splice ( location , 1 , [ expandedElement ] ) ;
246159 }
247- }
248160
249- clear ( ) : void {
250- this . root = { value : undefined , children : new Map < K , TrieNode < K , T > > ( ) } ;
251- }
252- }
253-
254- export class CollapsibleTreeModel < T > {
255161
256- private model : TreeModel < T > ;
257-
258- constructor ( spliceable : ISpliceable < ITreeNode < T > > ) {
259- this . model = new TreeModel < T > ( spliceable ) ;
260- }
261-
262- splice ( start : number [ ] , deleteCount : number , elements : ITreeElement < T > [ ] ) : void {
263- this . model . splice ( start , deleteCount , elements ) ;
162+ // gotta reflect the state on the visibleModel
264163 }
265164
266- expand ( location : number [ ] ) : boolean {
267-
268- // this.model.splice(start, deleteCount, elements);
269- // const element = this.model.getElement()
270- return false ;
271- }
272-
273- collapse ( location : number [ ] ) : boolean {
274- // const element = this.model.getElement(location);
275- // const collapsedElement: ITreeElement<T> = { element, children: [] };
276- // const deletedIterator = this.model.splice(location, 1, [collapsedElement]);
277-
278- return false ;
165+ isCollapsed ( location : number [ ] ) : boolean {
166+ return this . model . getElement ( location ) . collapsed ;
279167 }
280168}
0 commit comments