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