Skip to main content

freya_core/
event_handler.rs

1use std::{
2    cell::RefCell,
3    rc::Rc,
4};
5
6use crate::{
7    current_context::CurrentContext,
8    prelude::current_scope_id,
9    scope_id::ScopeId,
10};
11
12pub struct Callback<A, R>(Rc<RefCell<dyn FnMut(A) -> R>>);
13
14impl<A, R> Callback<A, R> {
15    pub fn new(callback: impl FnMut(A) -> R + 'static) -> Self {
16        Self(Rc::new(RefCell::new(callback)))
17    }
18
19    pub fn call(&self, data: A) -> R {
20        (self.0.borrow_mut())(data)
21    }
22}
23
24impl<A, R> Clone for Callback<A, R> {
25    fn clone(&self) -> Self {
26        Self(self.0.clone())
27    }
28}
29
30impl<A, R> std::fmt::Debug for Callback<A, R> {
31    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        write!(
33            formatter,
34            "Callback<{}, {}>",
35            std::any::type_name::<A>(),
36            std::any::type_name::<R>()
37        )
38    }
39}
40
41impl<A, R> PartialEq for Callback<A, R> {
42    fn eq(&self, _other: &Self) -> bool {
43        // TODO: Decide whether event handlers should be captured or not.
44        false
45    }
46}
47
48impl<A, R, H: FnMut(A) -> R + 'static> From<H> for Callback<A, R> {
49    fn from(value: H) -> Self {
50        Callback::new(value)
51    }
52}
53
54pub struct NoArgCallback<R>(Rc<RefCell<dyn FnMut() -> R>>);
55
56impl<R> NoArgCallback<R> {
57    pub fn new(callback: impl FnMut() -> R + 'static) -> Self {
58        Self(Rc::new(RefCell::new(callback)))
59    }
60
61    pub fn call(&self) -> R {
62        (self.0.borrow_mut())()
63    }
64}
65
66impl<R> Clone for NoArgCallback<R> {
67    fn clone(&self) -> Self {
68        Self(self.0.clone())
69    }
70}
71
72impl<R> std::fmt::Debug for NoArgCallback<R> {
73    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        write!(formatter, "NoArgCallback<{}>", std::any::type_name::<R>())
75    }
76}
77
78impl<R> PartialEq for NoArgCallback<R> {
79    fn eq(&self, _other: &Self) -> bool {
80        true
81    }
82}
83
84impl<R, H: FnMut() -> R + 'static> From<H> for NoArgCallback<R> {
85    fn from(value: H) -> Self {
86        NoArgCallback::new(value)
87    }
88}
89
90pub struct EventHandler<T>(Rc<RefCell<dyn FnMut(T)>>);
91
92impl<T> EventHandler<T> {
93    pub fn new(handler: impl FnMut(T) + 'static) -> Self {
94        Self(Rc::new(RefCell::new(handler)))
95    }
96
97    /// Create an event handler that runs under the given scope.
98    ///
99    /// APIs that rely on the current scope, like [`spawn`](crate::prelude::spawn), will use
100    /// `scope_id` instead of the scope of the element that received the event.
101    pub fn new_scoped(scope_id: ScopeId, mut handler: impl FnMut(T) + 'static) -> Self {
102        Self::new(move |data| CurrentContext::run_in_scope(scope_id, || handler(data)))
103    }
104
105    /// Create an event handler that runs under the scope creating it.
106    ///
107    /// Shortcut for [`EventHandler::new_scoped`] with the current scope, so e.g tasks spawned in
108    /// the handler are cancelled once the component creating it unmounts.
109    ///
110    /// ```rust,no_run
111    /// # use freya::prelude::*;
112    /// # async fn save_document() {}
113    /// # fn save_button() -> impl IntoElement {
114    /// let on_press = EventHandler::new_current(|_| {
115    ///     spawn(async {
116    ///         save_document().await;
117    ///     });
118    /// });
119    ///
120    /// Button::new().child("Save").on_press(on_press)
121    /// # }
122    /// ```
123    pub fn new_current(handler: impl FnMut(T) + 'static) -> Self {
124        Self::new_scoped(current_scope_id(), handler)
125    }
126
127    pub fn call(&self, data: T) {
128        (self.0.borrow_mut())(data);
129    }
130}
131
132impl<T> Clone for EventHandler<T> {
133    fn clone(&self) -> Self {
134        Self(self.0.clone())
135    }
136}
137
138impl<T> std::fmt::Debug for EventHandler<T> {
139    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140        write!(formatter, "EventHandler<{}>", std::any::type_name::<T>())
141    }
142}
143
144impl<T> PartialEq for EventHandler<T> {
145    fn eq(&self, _other: &Self) -> bool {
146        // TODO: Decide whether event handlers should be captured or not.
147        false
148    }
149}
150
151impl<H: FnMut(D) + 'static, D> From<H> for EventHandler<D> {
152    fn from(value: H) -> Self {
153        EventHandler::new(value)
154    }
155}