@@ -34,6 +34,36 @@ export interface IView {
3434 setVisible ?( visible : boolean ) : void ;
3535}
3636
37+ export interface ISerializableView extends IView {
38+ toJSON ( ) : object ;
39+ }
40+
41+ export interface IViewDeserializer < T extends ISerializableView > {
42+ fromJSON ( json : any ) : T ;
43+ }
44+
45+ export interface ISerializedLeafNode {
46+ type : 'leaf' ;
47+ data : any ;
48+ size : number ;
49+ visible ?: boolean ;
50+ }
51+
52+ export interface ISerializedBranchNode {
53+ type : 'branch' ;
54+ data : ISerializedNode [ ] ;
55+ size : number ;
56+ }
57+
58+ export type ISerializedNode = ISerializedLeafNode | ISerializedBranchNode ;
59+
60+ export interface ISerializedGridView {
61+ root : ISerializedNode ;
62+ orientation : Orientation ;
63+ width : number ;
64+ height : number ;
65+ }
66+
3767export function orthogonal ( orientation : Orientation ) : Orientation {
3868 return orientation === Orientation . VERTICAL ? Orientation . HORIZONTAL : Orientation . VERTICAL ;
3969}
@@ -179,18 +209,49 @@ class BranchNode implements ISplitView, IDisposable {
179209 styles : IGridViewStyles ,
180210 readonly proportionalLayout : boolean ,
181211 size : number = 0 ,
182- orthogonalSize : number = 0
212+ orthogonalSize : number = 0 ,
213+ childDescriptors ?: INodeDescriptor [ ]
183214 ) {
184215 this . _styles = styles ;
185216 this . _size = size ;
186217 this . _orthogonalSize = orthogonalSize ;
187218
188219 this . element = $ ( '.monaco-grid-branch-node' ) ;
189- this . splitview = new SplitView ( this . element , { orientation, styles, proportionalLayout } ) ;
190- this . splitview . layout ( size , orthogonalSize ) ;
220+
221+ if ( ! childDescriptors ) {
222+ // Normal behavior, we have no children yet, just set up the splitview
223+ this . splitview = new SplitView ( this . element , { orientation, styles, proportionalLayout } ) ;
224+ this . splitview . layout ( size , orthogonalSize ) ;
225+ } else {
226+ // Reconstruction behavior, we want to reconstruct a splitview
227+ const descriptor = {
228+ views : childDescriptors . map ( childDescriptor => {
229+ return {
230+ view : childDescriptor . node ,
231+ size : childDescriptor . node . size ,
232+ visible : childDescriptor . node instanceof LeafNode && childDescriptor . visible !== undefined ? childDescriptor . visible : true
233+ } ;
234+ } ) ,
235+ size : this . orthogonalSize
236+ } ;
237+
238+ const options = { proportionalLayout, orientation, styles } ;
239+
240+ this . children = childDescriptors . map ( c => c . node ) ;
241+ this . splitview = new SplitView ( this . element , { ...options , descriptor } ) ;
242+
243+ this . children . forEach ( ( node , index ) => {
244+ // Set up orthogonal sashes for children
245+ node . orthogonalStartSash = this . splitview . sashes [ index - 1 ] ;
246+ node . orthogonalEndSash = this . splitview . sashes [ index ] ;
247+ } ) ;
248+ }
191249
192250 const onDidSashReset = Event . map ( this . splitview . onDidSashReset , i => [ i ] ) ;
193251 this . splitviewSashResetDisposable = onDidSashReset ( this . _onDidSashReset . fire , this . _onDidSashReset ) ;
252+
253+ const onDidChildrenSashReset = Event . any ( ...this . children . map ( ( c , i ) => Event . map ( c . onDidSashReset , location => [ i , ...location ] ) ) ) ;
254+ this . childrenSashResetDisposable = onDidChildrenSashReset ( this . _onDidSashReset . fire , this . _onDidSashReset ) ;
194255 }
195256
196257 style ( styles : IGridViewStyles ) : void {
@@ -226,7 +287,7 @@ class BranchNode implements ISplitView, IDisposable {
226287 }
227288 }
228289
229- addChild ( node : Node , size : number | Sizing , index : number ) : void {
290+ addChild ( node : Node , size : number | Sizing , index : number , skipLayout ?: boolean ) : void {
230291 if ( index < 0 || index > this . children . length ) {
231292 throw new Error ( 'Invalid index' ) ;
232293 }
@@ -484,9 +545,11 @@ class LeafNode implements ISplitView, IDisposable {
484545 readonly view : IView ,
485546 readonly orientation : Orientation ,
486547 readonly layoutController : ILayoutController ,
487- orthogonalSize : number
548+ orthogonalSize : number ,
549+ size : number = 0
488550 ) {
489551 this . _orthogonalSize = orthogonalSize ;
552+ this . _size = size ;
490553
491554 this . _onDidViewChange = Event . map ( this . view . onDidChange , e => e && ( this . orientation === Orientation . VERTICAL ? e . width : e . height ) ) ;
492555 this . onDidChange = Event . any ( this . _onDidViewChange , this . _onDidSetLinkedNode . event , this . _onDidLinkedWidthNodeChange . event , this . _onDidLinkedHeightNodeChange . event ) ;
@@ -577,6 +640,11 @@ class LeafNode implements ISplitView, IDisposable {
577640
578641type Node = BranchNode | LeafNode ;
579642
643+ export interface INodeDescriptor {
644+ node : Node ;
645+ visible ?: boolean ;
646+ }
647+
580648function flipNode < T extends Node > ( node : T , size : number , orthogonalSize : number ) : T {
581649 if ( node instanceof BranchNode ) {
582650 const result = new BranchNode ( orthogonal ( node . orientation ) , node . layoutController , node . styles , node . proportionalLayout , size , orthogonalSize ) ;
@@ -680,6 +748,18 @@ export class GridView implements IDisposable {
680748 this . root = new BranchNode ( Orientation . VERTICAL , this . layoutController , this . styles , this . proportionalLayout ) ;
681749 }
682750
751+ getViewMap ( map : Map < IView , HTMLElement > , node ?: Node ) : void {
752+ if ( ! node ) {
753+ node = this . root ;
754+ }
755+
756+ if ( node instanceof BranchNode ) {
757+ node . children . forEach ( child => this . getViewMap ( map , child ) ) ;
758+ } else {
759+ map . set ( node . view , node . element ) ;
760+ }
761+ }
762+
683763 style ( styles : IGridViewStyles ) : void {
684764 this . styles = styles ;
685765 this . root . style ( styles ) ;
@@ -953,6 +1033,47 @@ export class GridView implements IDisposable {
9531033 return this . _getViews ( node , this . orientation , { top : 0 , left : 0 , width : this . width , height : this . height } ) ;
9541034 }
9551035
1036+ static deserialize < T extends ISerializableView > ( json : ISerializedGridView , deserializer : IViewDeserializer < T > , options : IGridViewOptions = { } ) : GridView {
1037+ if ( typeof json . orientation !== 'number' ) {
1038+ throw new Error ( 'Invalid JSON: \'orientation\' property must be a number.' ) ;
1039+ } else if ( typeof json . width !== 'number' ) {
1040+ throw new Error ( 'Invalid JSON: \'width\' property must be a number.' ) ;
1041+ } else if ( typeof json . height !== 'number' ) {
1042+ throw new Error ( 'Invalid JSON: \'height\' property must be a number.' ) ;
1043+ }
1044+
1045+ const orientation = json . orientation ;
1046+ const height = json . height ;
1047+
1048+ const result = new GridView ( options ) ;
1049+ result . _deserialize ( json . root as ISerializedBranchNode , orientation , deserializer , height ) ;
1050+
1051+ return result ;
1052+ }
1053+
1054+ private _deserialize ( root : ISerializedBranchNode , orientation : Orientation , deserializer : IViewDeserializer < ISerializableView > , orthogonalSize : number ) : void {
1055+ this . root = this . _deserializeNode ( root , orientation , deserializer , orthogonalSize ) as BranchNode ;
1056+ }
1057+
1058+ private _deserializeNode ( node : ISerializedNode , orientation : Orientation , deserializer : IViewDeserializer < ISerializableView > , orthogonalSize : number ) : Node {
1059+ let result : Node ;
1060+ if ( node . type === 'branch' ) {
1061+ const serializedChildren = node . data as ISerializedNode [ ] ;
1062+ const children = serializedChildren . map ( serializedChild => {
1063+ return {
1064+ node : this . _deserializeNode ( serializedChild , orthogonal ( orientation ) , deserializer , node . size ) ,
1065+ visible : ( serializedChild as { visible ?: boolean } ) . visible
1066+ } as INodeDescriptor ;
1067+ } ) ;
1068+
1069+ result = new BranchNode ( orientation , this . layoutController , this . styles , this . proportionalLayout , node . size , orthogonalSize , children ) ;
1070+ } else {
1071+ result = new LeafNode ( deserializer . fromJSON ( node . data ) , orientation , this . layoutController , orthogonalSize , node . size ) ;
1072+ }
1073+
1074+ return result ;
1075+ }
1076+
9561077 private _getViews ( node : Node , orientation : Orientation , box : Box , cachedVisibleSize ?: number ) : GridNode {
9571078 if ( node instanceof LeafNode ) {
9581079 return { view : node . view , box, cachedVisibleSize } ;
0 commit comments