1     type Splitter @mut =
2         inherit Panel
3     
4         var ratio : f32 = 0
5         var is_vertical = false
6     
7         let mut first : Option<Control> = None
8         let mut second : Option<Control> = None
9     
10        let update () =
11            first = if items.size > 0 then Some items[0] else None
12            second = if items.size > 1 then Some items[1] else None
13    
14        items |> Obs.subscribe { update } |> push_token
15    
16        def Control.measure self w h =
17            let maybe_first = self.first.filter { _.is_visible }
18            let maybe_second = self.second.filter { _.is_visible }
19            let ratio = self.ratio
20            let is_vertical = self.is_vertical
21    
22            let (res_w, res_h) = case (maybe_first, maybe_second) of
23                None, None -> (0, 0)
24                Some first, None ->
25                    measure_clamped first w h
26                    (first.measure_width, first.measure_height)
27    
28                None, Some second ->
29                    measure_clamped second w h
30                    (second.measure_width, second.measure_height)
31    
32                Some first, Some second ->
33                    if ratio == 0 || ratio == 1 then
34                        if ratio == 0 then
35                            measure_clamped first w h
36    
37                            if is_vertical then
38                                let max_h = if h > first.measure_height
39                                            then h - first.measure_height
40                                            else 0
41                                measure_clamped second w max_h
42                            else
43                                let max_w = if w == 0 then 0 else w - first.measure_width
44                                measure_clamped second max_w h
45                        else
46                            assert ratio == 1
47                            measure_clamped second w h
48    
49                            if is_vertical then
50                                measure_clamped first w (h - second.measure_height)
51                            else
52                                let max_w = if w == 0 then 0 else w - second.measure_width
53                                measure_clamped first max_w h
54    
55                        if is_vertical then
56                            (first.measure_width.max second.measure_width
57                             first.measure_height + second.measure_height)
58                        else
59                            (first.measure_width + second.measure_width
60                             first.measure_height.max second.measure_height)
61                    else
62                        if is_vertical then
63                            let first_h = h as f32 * ratio |> round as u32
64                            let second_h = h - first_h
65                            measure_clamped first w first_h
66                            measure_clamped second w second_h
67    
68                            let res_w = first.measure_width.max second.measure_width
69                            let res_h = first.measure_height as f32 / ratio
70                                |> max (second.measure_height as f32 / (1 - ratio))
71                                |> round as u32
72    
73                            (res_w, res_h)
74                        else
75                            let first_w = w as f32 * ratio |> round as u32
76                            let second_w = w - first_w
77                            measure_clamped first first_w h
78                            measure_clamped second second_w h
79    
80                            let res_w = first.measure_width as f32 / ratio
81                                |> max (second.measure_width as f32 / (1 - ratio))
82                                |> round as u32
83    
84                            let res_h = first.measure_height.max second.measure_height
85                            (res_w, res_h)
86    
87            self.measure_width = res_w
88                 measure_height = res_h
89    
90        def Control.arrange self =
91            let ratio = self.ratio
92            let is_vertical = self.is_vertical
93            let splitter_width = self.width
94            let splitter_height = self.height
95    
96            let maybe_first = self.first.filter { _.is_visible }
97            let maybe_second = self.second.filter { _.is_visible }
98    
99            let first_measure_value = maybe_first
100               |> map { x -> if is_vertical
101                             then x.measure_height
102                             else x.measure_width }
103               |> unwrap_or 0
104   
105           let second_measure_value = maybe_second
106               |> map { x -> if is_vertical
107                             then x.measure_height
108                             else x.measure_width }
109               |> unwrap_or 0
110   
111           let splitter_value = if is_vertical
112                                then splitter_height
113                                else splitter_width
114   
115           let first_value = case ratio of
116               0 -> first_measure_value
117               1 -> splitter_value - second_measure_value
118               else -> splitter_value as f32 * ratio |> round as u32
119   
120           let second_value = case ratio of
121               1 -> second_measure_value
122               0 -> splitter_value - first_value
123               else -> splitter_value as f32 * (1 - ratio) |> round as u32
124   
125           let f (control : Control) (offset : u32) (max_value : u32) =
126               let (offset_x, offset_y) = if is_vertical
127                                          then (0, offset)
128                                          else (offset, 0)
129   
130               let max_control_width = if is_vertical
131                                       then splitter_width
132                                       else max_value
133   
134               let max_control_height = if is_vertical
135                                        then max_value
136                                        else splitter_height
137               do
138                   let width = if control.align_h == AlignH/Stretch
139                               then max_control_width
140                               else control.measure_width.min max_control_width
141   
142                   let height = if control.align_v == AlignV/Stretch
143                                then max_control_height
144                                else control.measure_height.min max_control_height
145   
146                   control.width = width
147                           height = height
148   
149                   assert control.width <= max_control_width
150                   control.arrange
151   
152               let width = control.width
153               let height = control.height
154   
155               let x = case control.align_h of
156                           AlignH/Left | AlignH/Stretch -> 0
157                           AlignH/Right -> max_control_width - width
158                           AlignH/Center -> (max_control_width - width) / 2
159                       + offset_x
160   
161               let y = case control.align_v of
162                           AlignV/Up | AlignV/Stretch -> 0
163                           AlignV/Down -> max_control_height - height
164                           AlignV/Center -> (max_control_height.max height - height) / 2
165                       + offset_y
166   
167               control.position = Vector3 x.as<f32> y.as<f32> Control.offset_z
168   
169           if maybe_first ? Some first then
170               f first 0 first_value
171   
172           if maybe_second ? Some second then
173               f second first_value second_value
174