1     type App =
2         let name : String
3         let is_resizable @param = false
4         val os_window = OsWindow.create 1920 1080 name is_resizable
5         Glfw.set_window_size_limits os_window.window 1200 600 Glfw.dont_care
6                                     Glfw.dont_care
7         Glfw.make_context_current os_window.window
8         val display = Display os_window
9         val mouse = Mouse.create os_window display.overlay.controls
10                                 display.controls display.focus@atom
11    
12        val captured@atom = mouse.capture@atom.option_map { _.control }
13    
14        let update_cursor () =
15            let maybe_control = captured.or_else mouse.hover
16            let shape = case maybe_control of
17                Some control -> case control.parent of
18                    Some parent if parent is Resizer -> MouseShape/ResizeEw
19                    else -> MouseShape/Arrow
20    
21                None -> MouseShape/Arrow
22    
23            if shape <> mouse.shape then
24                mouse.set_cursor os_window shape
25    
26        let cursor_hover_token = mouse.hover@atom.subscribe { update_cursor }
27        let cursor_captured_token = captured@atom.subscribe { update_cursor }
28    
29        val tick = Stream<f32>.new
30        let presenter = Presenter.new
31        let canvas = Canvas presenter
32    
33        display.controls.add canvas
34    
35        let f (control : Control) =
36            control.set_fixed_width os_window.width
37                    set_fixed_height os_window.height
38    
39        f canvas
40        f presenter
41    
42        let size_token = os_window.sizes.subscribe {
43            f canvas
44            f presenter }
45    
46        def run =
47            let frame_length_micros = 1000 / 0.06 |> as<u64>
48            let mut last_frame_time = Time.now - Duration 1 0
49            while not self.os_window.should_close do
50                repeat
51                    let elapsed_micros = last_frame_time.elapsed.to_microseconds
52                    if elapsed_micros + 200 >= frame_length_micros then
53                        break
54                    else
55                        let sleep_duration =
56                            frame_length_micros - elapsed_micros - 150
57                            |> Duration.from_microseconds
58    
59                        thread/sleep sleep_duration
60    
61                while frame_length_micros > last_frame_time.elapsed.to_microseconds
62                do
63                    thread/yield
64    
65                let dt = last_frame_time.elapsed.to_seconds_f32 |> min 0.049
66                last_frame_time = Time.now
67                os_window.update
68                glfw/update
69                tick.push dt
70    
71        def add_window (window : Window) =
72            canvas.items.add window
73            bring_to_front window
74    
75        val remove_window = { window ->
76            canvas.items.remove window
77    
78            if captured.is_some && window.contains captured.unwrap then
79                mouse.capture = None }<Window>
80    
81        def contains_window (window : Window) =
82            canvas.items.contains window
83    
84        def set_content (content : Option<Control>) =
85            presenter.content = content
86    
87        def discard =
88            size_token.discard
89            cursor_captured_token.discard
90            cursor_hover_token.discard
91            os_window.discard
92            Glfw.terminate
93    
94    type Dependencies =
95        val os_window : OsWindow
96        val captured : Atom<Option<Control>>
97        val remove_window : Window -> Unit
98        val overlay : Overlay
99    
100   type App
101       val dependencies = Dependencies
102           =os_window
103           captured = captured@atom
104           =remove_window
105           overlay = display.overlay
106