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