1 type AlignH = 2 | Left 3 | Right 4 | Center 5 | Stretch 6 7 type AlignV = 8 | Up 9 | Down 10 | Center 11 | Stretch 12 13 type Command @open 14 15 type Control @abstract @mut = 16 var width : u32 = 0 17 var height : u32 = 0 18 var min_width : u32 = 0 19 var max_width = u32.max 20 var min_height : u32 = 0 21 var max_height = u32.max 22 var measure_width : u32 = 0 23 var measure_height : u32 = 0 24 25 coerce@ width { _.clamp min_width max_width } 26 coerce@ height { _.clamp min_height max_height } 27 28 coerce@ measure_width { _.clamp min_width max_width } 29 coerce@ measure_height { _.clamp min_height max_height } 30 31 var align_h = AlignH/Stretch 32 var align_v = AlignV/Stretch 33 34 var parent : Option<Control> = None 35 let tokens = List<Token>.new 36 37 var origin = Vector3.new 38 var position = Vector3.new 39 var global_position @[mut private] = Vector3.new 40 41 let on_position_changed @optional (v : Vector3) 42 43 let update_global_position () = 44 global_position = position + origin 45 on_position_changed global_position 46 47 observe@ position { update_global_position } 48 observe@ origin { update_global_position } 49 50 var is_visible = true 51 var is_focused = false 52 var is_focusable = false 53 var is_resizable = false 54 var is_clickable = false 55 var is_scrollable = false 56 var is_receive_mouse_move = false 57 var is_popup = false 58 var command : Option<Command> = None 59 val events = Stream<(Control, ControlEvent)>.new 60 61 def push (event : ControlEvent) = 62 events.push (self, event) 63 64 def subscribe (f : (Control, ControlEvent) -> Unit) = 65 events.add f 66 67 observe@ width { _ w -> SizeEvent/Width w |> push } 68 observe@ height { _ h -> SizeEvent/Height h |> push } 69 observe@ min_width { _ w -> SizeEvent/MinWidth w |> push } 70 observe@ min_height { _ h -> SizeEvent/MinHeight h |> push } 71 observe@ max_width { _ w -> SizeEvent/MaxWidth w |> push } 72 observe@ max_height { _ h -> SizeEvent/MaxHeight h |> push } 73 observe@ is_visible { _ x -> FlagEvent/IsVisible x |> push } 74 observe@ is_focused { _ x -> FlagEvent/IsFocused x |> push } 75 observe@ is_focusable { _ x -> FlagEvent/IsFocusable x |> push } 76 observe@ is_resizable { _ x -> FlagEvent/IsResizable x |> push } 77 78 def measure (w : u32) (h : u32) 79 def arrange 80 81 def push_token (token : Token) = 82 tokens.add token 83 84 def set_fixed_width (w : u32) = 85 min_width = w 86 max_width = w 87 width = w 88 89 def set_fixed_height (h : u32) = 90 min_height = h 91 max_height = h 92 height = h 93 94 def set_z (z : f32) = 95 position = position.with_z z 96 97 def contains (control : Control) : bool = 98 case control.parent of 99 None -> false 100 Some x -> if x == self 101 then true 102 else contains x 103 104 def discard = 105 for token in tokens do 106 token.discard 107 108 tokens.clear 109 110 object Control = 111 val offset_z : f32 = -0.0001 112 val window_z : f32 = -0.01 113 val max_size : u32 = u32.max / 4 114 115 type Container @abstract = 116 inherit Control 117 118 def get_slice : SafeSlice<Control> 119 120 let Control.on_position_changed (v : Vector3) = 121 let slice = get_slice 122 for item in slice do 123 item.origin = v 124 125 def init_child (control : Control) (atom : Atom<Option<Control>>) = 126 atom.subscribe { prev_maybe_x maybe_x -> 127 if prev_maybe_x ? Some prev_x then 128 assert prev_x.parent == Some control 129 prev_x.parent = None 130 131 if maybe_x ? Some x then 132 assert x.parent.is_none 133 x.parent = control 134 x.origin = control.global_position } |> control.push_token 135