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