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