1     type Aligner =
2         inherit Panel
3     
4         def Control.measure w h =
5             let mut max_w = 0
6             let mut max_h = 0
7             for control in items do
8                 measure_clamped control w h
9                 max_w = max_w.max control.measure_width
10                max_h = max_h.max control.measure_height
11    
12            measure_width = max_w
13            measure_height = max_h
14    
15        def Control.arrange self =
16            let aligner_width = self.width
17            let prev_aligner_height = self.height
18            let mut max_item_height = 0
19            let stretched = List.new
20            for control in self.items do
21                let align_h = control.align_h
22                let align_v = control.align_v
23    
24                let width = if align_h == AlignH/Stretch
25                            then aligner_width
26                            else control.measure_width.min aligner_width
27    
28                control.width = width
29    
30                if align_v == AlignV/Stretch then
31                    stretched.add control
32                else
33                    let height = control.measure_height
34                    control.height = height
35                    control.arrange
36                    max_item_height = max_item_height.max control.height
37    
38            if max_item_height == 0 && stretched.is_not_empty then
39                max_item_height = stretched.max_of { _.measure_height }
40    
41            max_item_height = max_item_height.max prev_aligner_height
42    
43            repeat
44                let prev_max_height = max_item_height
45                for control in stretched do
46                    control.height = max_item_height
47                    control.arrange
48                    max_item_height = max_item_height.max control.height
49    
50                if max_item_height == prev_max_height then
51                    break
52    
53            if max_item_height > prev_aligner_height then
54                self.height = max_item_height
55    
56            let aligner_height = self.height
57            for control in self.items do
58                let align_h = control.align_h
59                let align_v = control.align_v
60                let width = control.width
61                let height = control.height
62                assert width <= aligner_width
63                let middle_x = if aligner_width > width
64                               then (aligner_width - width) / 2 |> as<f32>
65                               else 0
66    
67                let middle_y = if aligner_height > height
68                               then (aligner_height - height) / 2 |> as<f32>
69                               else 0
70    
71                let right_x = if aligner_width > width
72                              then aligner_width - width |> as<f32>
73                              else 0
74    
75                let down_y = if aligner_height > height
76                             then aligner_height - height |> as<f32>
77                             else 0
78    
79                let index = self.items.index_of control
80                let z = -0.001 * index as f32
81                let position = case align_h of
82                    AlignH/Left -> case align_v of
83                        AlignV/Up -> Vector3.new
84                        AlignV/Center -> Vector3 0 middle_y z
85                        AlignV/Stretch -> Vector3 0 0 z
86                        AlignV/Down -> Vector3 0 down_y z
87    
88                    AlignH/Right -> case align_v of
89                        AlignV/Up -> Vector3 right_x 0 z
90                        AlignV/Center -> Vector3 right_x middle_y z
91                        AlignV/Stretch -> Vector3 right_x 0 z
92                        AlignV/Down -> Vector3 right_x down_y z
93    
94                    AlignH/Center -> case align_v of
95                        AlignV/Up -> Vector3 middle_x 0 z
96                        AlignV/Center -> Vector3 middle_x middle_y z
97                        AlignV/Stretch -> Vector3 middle_x 0 z
98                        AlignV/Down -> Vector3 middle_x down_y z
99    
100                   AlignH/Stretch -> case align_v of
101                       AlignV/Up -> Vector3 0 0 z
102                       AlignV/Center -> Vector3 0 middle_y z
103                       AlignV/Stretch -> Vector3 0 0 z
104                       AlignV/Down -> Vector3 0 down_y z
105   
106               control.position = position
107