1
- import { FlowOptions , ChildInfo } from './flow-interface' ;
1
+ import { FlowOptions , ChildInfo , FlowDirection } from './flow-interface' ;
2
2
3
3
export class Arrangements {
4
4
constructor (
@@ -21,12 +21,12 @@ export class Arrangements {
21
21
22
22
for ( const baseNode of baseNodes ) {
23
23
if ( this . direction === 'horizontal' ) {
24
- this . positionDependents ( baseNode , currentX , 0 , newItems ) ;
25
- currentX += baseNode . elRect . width + this . horizontalPadding ;
24
+ this . positionDependents ( baseNode , 0 , currentY , newItems ) ;
25
+ currentY += baseNode . elRect . height + this . verticalPadding ;
26
26
} else {
27
27
// Vertical arrangement
28
- this . positionDependents ( baseNode , 0 , currentY , newItems ) ;
29
- currentY += baseNode . elRect . height + this . horizontalPadding ;
28
+ this . positionDependents ( baseNode , 0 , currentX , newItems ) ;
29
+ currentX += baseNode . elRect . width + this . verticalPadding ;
30
30
}
31
31
}
32
32
@@ -116,3 +116,110 @@ export class Arrangements {
116
116
return { consumedSpace, dep : dependents . length > 0 } ;
117
117
}
118
118
}
119
+
120
+ const ROOT_DATA = new Map < string , ArrangeNode > ( ) ;
121
+ const ROOT_DEPS = new Map < string , string [ ] > ( ) ;
122
+ const HORIZONTAL_PADDING = 100 ;
123
+ const VERTICAL_PADDING = 20 ;
124
+
125
+ export class Arrangements2 {
126
+ root : string [ ] = [ ] ;
127
+
128
+ constructor (
129
+ private list : ChildInfo [ ] ,
130
+ private direction : FlowDirection = 'vertical' ,
131
+ public horizontalPadding = 100 ,
132
+ public verticalPadding = 20 ,
133
+ public groupPadding = 20
134
+ ) {
135
+ ROOT_DATA . clear ( ) ;
136
+ ROOT_DEPS . clear ( ) ;
137
+ this . list . forEach ( ( item ) => {
138
+ ROOT_DATA . set (
139
+ item . position . id ,
140
+ new ArrangeNode ( item . position , item . elRect )
141
+ ) ;
142
+ item . position . deps . forEach ( ( dep ) => {
143
+ let d = ROOT_DEPS . get ( dep ) || [ ] ;
144
+ d . push ( item . position . id ) ;
145
+ ROOT_DEPS . set ( dep , d ) ;
146
+ } ) ;
147
+
148
+ if ( item . position . deps . length === 0 ) {
149
+ this . root . push ( item . position . id ) ;
150
+ }
151
+ } ) ;
152
+ }
153
+
154
+ public autoArrange ( ) : Map < string , FlowOptions > {
155
+ this . root . forEach ( ( id ) => {
156
+ const node = ROOT_DATA . get ( id ) ! ;
157
+ node . arrange ( 0 , 0 , this . direction ) ;
158
+ } ) ;
159
+
160
+ const newItems = new Map < string , FlowOptions > ( ) ;
161
+
162
+ for ( const item of this . list ) {
163
+ newItems . set ( item . position . id , item . position ) ;
164
+ }
165
+ return newItems ;
166
+ }
167
+ }
168
+
169
+ interface Coordinates {
170
+ x : number ;
171
+ y : number ;
172
+ }
173
+
174
+ export class ArrangeNode {
175
+ constructor ( public position : FlowOptions , public elRect : DOMRect ) { }
176
+
177
+ get deps ( ) {
178
+ return ROOT_DEPS . get ( this . position . id ) || [ ] ;
179
+ }
180
+
181
+ // we need to recursively call this method to get all the dependents of the node
182
+ // and then we need to position them
183
+ arrange ( x = 0 , y = 0 , direction : FlowDirection ) : Coordinates {
184
+ const dependents = ROOT_DEPS . get ( this . position . id ) || [ ] ;
185
+ let startX = x ;
186
+ let startY = y ;
187
+ let len = dependents . length ;
188
+
189
+ if ( len ) {
190
+ if ( direction === 'horizontal' ) {
191
+ startX += this . elRect . width + HORIZONTAL_PADDING ;
192
+ } else {
193
+ startY += this . elRect . height + HORIZONTAL_PADDING ;
194
+ }
195
+ let first , last : Coordinates ;
196
+ for ( let i = 0 ; i < len ; i ++ ) {
197
+ const dep = dependents [ i ] ;
198
+ const dependent = ROOT_DATA . get ( dep ) ! ;
199
+ const { x, y } = dependent . arrange ( startX , startY , direction ) ;
200
+ // capture the first and last dependent
201
+ if ( i === 0 ) first = dependent . position ;
202
+ if ( i === len - 1 ) last = dependent . position ;
203
+
204
+ if ( direction === 'horizontal' ) {
205
+ startY = y + VERTICAL_PADDING ;
206
+ } else {
207
+ startX = x + VERTICAL_PADDING ;
208
+ }
209
+ }
210
+ if ( direction === 'horizontal' ) {
211
+ startY -= VERTICAL_PADDING + this . elRect . height ;
212
+ y = first ! . y + ( last ! . y - first ! . y ) / 2 ;
213
+ } else {
214
+ startX -= VERTICAL_PADDING + this . elRect . width ;
215
+ x = first ! . x + ( last ! . x - first ! . x ) / 2 ;
216
+ }
217
+ }
218
+ this . position . x = x ;
219
+ this . position . y = y ;
220
+
221
+ return direction === 'horizontal'
222
+ ? { x : startX , y : startY + this . elRect . height }
223
+ : { x : startX + this . elRect . width , y : startY } ;
224
+ }
225
+ }
0 commit comments