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 measure_clamped second w (h - first.measure_height) 39 else 40 let max_w = if w == 0 then 0 else w - first.measure_width 41 measure_clamped second max_w h 42 else 43 assert ratio == 1 44 measure_clamped second w h 45 46 if is_vertical then 47 measure_clamped first w (h - second.measure_height) 48 else 49 let max_w = if w == 0 then 0 else w - second.measure_width 50 measure_clamped first max_w h 51 52 if is_vertical then 53 (first.measure_width.max second.measure_width 54 first.measure_height + second.measure_height) 55 else 56 (first.measure_width + second.measure_width 57 first.measure_height.max second.measure_height) 58 else 59 if is_vertical then 60 let first_h = h as f32 * ratio |> round as u32 61 let second_h = h - first_h 62 measure_clamped first w first_h 63 measure_clamped second w second_h 64 65 let res_w = first.measure_width.max second.measure_width 66 let res_h = first.measure_height as f32 / ratio 67 |> max (second.measure_height as f32 / (1 - ratio)) 68 |> round as u32 69 70 (res_w, res_h) 71 else 72 let first_w = w as f32 * ratio |> round as u32 73 let second_w = w - first_w 74 measure_clamped first first_w h 75 measure_clamped second second_w h 76 77 let res_w = first.measure_width as f32 / ratio 78 |> max (second.measure_width as f32 / (1 - ratio)) 79 |> round as u32 80 81 let res_h = first.measure_height.max second.measure_height 82 (res_w, res_h) 83 84 self.measure_width = res_w 85 measure_height = res_h 86 87 def Control.arrange self = 88 let ratio = self.ratio 89 let is_vertical = self.is_vertical 90 let splitter_width = self.width 91 let splitter_height = self.height 92 93 let maybe_first = self.first.filter { _.is_visible } 94 let maybe_second = self.second.filter { _.is_visible } 95 96 let first_measure_value = maybe_first 97 |> map { x -> if is_vertical 98 then x.measure_height 99 else x.measure_width } 100 |> unwrap_or 0 101 102 let second_measure_value = maybe_second 103 |> map { x -> if is_vertical 104 then x.measure_height 105 else x.measure_width } 106 |> unwrap_or 0 107 108 let splitter_value = if is_vertical 109 then splitter_height 110 else splitter_width 111 112 let first_value = case ratio of 113 0 -> first_measure_value 114 1 -> splitter_value - second_measure_value 115 else -> splitter_value as f32 * ratio |> round as u32 116 117 let second_value = case ratio of 118 1 -> second_measure_value 119 0 -> splitter_value - first_value 120 else -> splitter_value as f32 * (1 - ratio) |> round as u32 121 122 let f (control : Control) (offset : u32) (max_value : u32) = 123 let (offset_x, offset_y) = if is_vertical 124 then (0, offset) 125 else (offset, 0) 126 127 let max_control_width = if is_vertical 128 then splitter_width 129 else max_value 130 131 let max_control_height = if is_vertical 132 then max_value 133 else splitter_height 134 do 135 let width = if control.align_h == AlignH/Stretch 136 then max_control_width 137 else control.measure_width.min max_control_width 138 139 let height = if control.align_v == AlignV/Stretch 140 then max_control_height 141 else control.measure_height.min max_control_height 142 143 control.width = width 144 height = height 145 146 assert control.width <= max_control_width 147 control.arrange 148 149 let width = control.width 150 let height = control.height 151 152 let x = case control.align_h of 153 AlignH/Left | AlignH/Stretch -> 0 154 AlignH/Right -> max_control_width - width 155 AlignH/Center -> (max_control_width - width) / 2 156 + offset_x 157 158 let y = case control.align_v of 159 AlignV/Up | AlignV/Stretch -> 0 160 AlignV/Down -> max_control_height - height 161 AlignV/Center -> (max_control_height.max height - height) / 2 162 + offset_y 163 164 control.position = Vector3 x.as<f32> y.as<f32> Control.offset_z 165 166 if maybe_first ? Some first then 167 f first 0 first_value 168 169 if maybe_second ? Some second then 170 f second first_value second_value 171