sauron_core/dom/
window.rs

1use crate::dom::{dom_node::intern, util, window, Cmd};
2use futures::channel::mpsc;
3use wasm_bindgen::{prelude::*, JsCast};
4use web_sys::MouseEvent;
5
6/// Provides function for window related functions
7#[derive(Clone, Copy)]
8pub struct Window;
9
10impl Window {
11    /// Create a recurring Cmd which will be triggered
12    /// everytime the window is resized
13    pub fn on_resize<F, MSG>(mut cb: F) -> Cmd<MSG>
14    where
15        F: FnMut(i32, i32) -> MSG + Clone + 'static,
16        MSG: 'static,
17    {
18        let (mut tx, rx) = mpsc::unbounded();
19        let resize_callback: Closure<dyn FnMut(web_sys::Event)> =
20            Closure::new(move |_e: web_sys::Event| {
21                let (w, h) = util::get_window_size();
22                let msg = cb(w, h);
23                tx.start_send(msg).expect("send");
24            });
25        window()
26            .add_event_listener_with_callback(
27                intern("resize"),
28                resize_callback.as_ref().unchecked_ref(),
29            )
30            .expect("add event callback");
31
32        Cmd::recurring(rx, resize_callback)
33    }
34
35    ///
36    pub fn on_mousemove<F, MSG>(mut cb: F) -> Cmd<MSG>
37    where
38        F: FnMut(web_sys::MouseEvent) -> MSG + Clone + 'static,
39        MSG: 'static,
40    {
41        let (mut tx, rx) = mpsc::unbounded();
42        let mousemove_cb: Closure<dyn FnMut(web_sys::Event)> =
43            Closure::new(move |event: web_sys::Event| {
44                let mouse_event: MouseEvent = event.dyn_into().expect("must be mouse event");
45                let msg = cb(mouse_event);
46                tx.start_send(msg).expect("send");
47            });
48        window()
49            .add_event_listener_with_callback(
50                intern("mousemove"),
51                mousemove_cb.as_ref().unchecked_ref(),
52            )
53            .expect("add event callback");
54        Cmd::recurring(rx, mousemove_cb)
55    }
56
57    ///
58    pub fn on_mouseup<F, MSG>(mut cb: F) -> Cmd<MSG>
59    where
60        F: FnMut(web_sys::MouseEvent) -> MSG + Clone + 'static,
61        MSG: 'static,
62    {
63        let (mut tx, rx) = mpsc::unbounded();
64        let mousemove_cb: Closure<dyn FnMut(web_sys::Event)> =
65            Closure::new(move |event: web_sys::Event| {
66                let mouse_event: MouseEvent = event.dyn_into().expect("must be mouse event");
67                let msg = cb(mouse_event);
68                tx.start_send(msg).expect("send");
69            });
70        window()
71            .add_event_listener_with_callback(
72                intern("mouseup"),
73                mousemove_cb.as_ref().unchecked_ref(),
74            )
75            .expect("add event callback");
76        Cmd::recurring(rx, mousemove_cb)
77    }
78
79    ///
80    pub fn on_mousedown<F, MSG>(mut cb: F) -> Cmd<MSG>
81    where
82        F: FnMut(web_sys::MouseEvent) -> MSG + Clone + 'static,
83        MSG: 'static,
84    {
85        let (mut tx, rx) = mpsc::unbounded();
86        let mousemove_cb: Closure<dyn FnMut(web_sys::Event)> =
87            Closure::new(move |event: web_sys::Event| {
88                let mouse_event: MouseEvent = event.dyn_into().expect("must be mouse event");
89                let msg = cb(mouse_event);
90                tx.start_send(msg).expect("send");
91            });
92        window()
93            .add_event_listener_with_callback(
94                intern("mousedown"),
95                mousemove_cb.as_ref().unchecked_ref(),
96            )
97            .expect("add event callback");
98        Cmd::recurring(rx, mousemove_cb)
99    }
100
101    ///
102    pub fn on_click<F, MSG>(mut cb: F) -> Cmd<MSG>
103    where
104        F: FnMut(web_sys::MouseEvent) -> MSG + Clone + 'static,
105        MSG: 'static,
106    {
107        let (mut tx, rx) = mpsc::unbounded();
108        let mousemove_cb: Closure<dyn FnMut(web_sys::Event)> =
109            Closure::new(move |event: web_sys::Event| {
110                let mouse_event: MouseEvent = event.dyn_into().expect("must be mouse event");
111                let msg = cb(mouse_event);
112                tx.start_send(msg).expect("send");
113            });
114        window()
115            .add_event_listener_with_callback(
116                intern("click"),
117                mousemove_cb.as_ref().unchecked_ref(),
118            )
119            .expect("add event callback");
120        Cmd::recurring(rx, mousemove_cb)
121    }
122
123    ///
124    pub fn on_keyup<F, MSG>(mut cb: F) -> Cmd<MSG>
125    where
126        F: FnMut(web_sys::KeyboardEvent) -> MSG + Clone + 'static,
127        MSG: 'static,
128    {
129        let (mut tx, rx) = mpsc::unbounded();
130        let closure_cb: Closure<dyn FnMut(web_sys::Event)> =
131            Closure::new(move |event: web_sys::Event| {
132                let key_event: web_sys::KeyboardEvent =
133                    event.dyn_into().expect("must be key event");
134                let msg = cb(key_event);
135                tx.start_send(msg).expect("send");
136            });
137        window()
138            .add_event_listener_with_callback(intern("keyup"), closure_cb.as_ref().unchecked_ref())
139            .expect("add event callback");
140        Cmd::recurring(rx, closure_cb)
141    }
142
143    ///
144    pub fn on_keydown<F, MSG>(mut cb: F) -> Cmd<MSG>
145    where
146        F: FnMut(web_sys::KeyboardEvent) -> MSG + Clone + 'static,
147        MSG: 'static,
148    {
149        let (mut tx, rx) = mpsc::unbounded();
150        let closure_cb: Closure<dyn FnMut(web_sys::Event)> =
151            Closure::new(move |event: web_sys::Event| {
152                let key_event: web_sys::KeyboardEvent =
153                    event.dyn_into().expect("must be key event");
154                let msg = cb(key_event);
155                tx.start_send(msg).expect("send");
156            });
157        window()
158            .add_event_listener_with_callback(
159                intern("keydown"),
160                closure_cb.as_ref().unchecked_ref(),
161            )
162            .expect("add event callback");
163        Cmd::recurring(rx, closure_cb)
164    }
165
166    /// scroll the window to the top of the document
167    pub fn scroll_to_top<MSG>(msg: MSG) -> Cmd<MSG>
168    where
169        MSG: 'static,
170    {
171        use std::future::ready;
172        Cmd::once(ready({
173            util::scroll_window_to_top();
174            msg
175        }))
176    }
177
178    ///
179    pub fn on_popstate<F, MSG>(mut cb: F) -> Cmd<MSG>
180    where
181        F: FnMut(web_sys::PopStateEvent) -> MSG + 'static,
182        MSG: 'static,
183    {
184        let (mut tx, rx) = mpsc::unbounded();
185        let closure_cb: Closure<dyn FnMut(web_sys::Event)> =
186            Closure::new(move |event: web_sys::Event| {
187                let popstate_event: web_sys::PopStateEvent =
188                    event.dyn_into().expect("popstate event");
189                let msg = cb(popstate_event);
190                tx.start_send(msg).expect("send");
191            });
192        window()
193            .add_event_listener_with_callback(
194                intern("popstate"),
195                closure_cb.as_ref().unchecked_ref(),
196            )
197            .expect("add event callback");
198        Cmd::recurring(rx, closure_cb)
199    }
200}