vertigo/dom/
callback.rs

1use std::rc::Rc;
2
3use vertigo_macro::bind;
4
5use crate::computed::{struct_mut::ValueMut, Computed, DropResource};
6
7pub enum Callback<R> {
8    Basic(Rc<dyn Fn() -> R + 'static>),
9    Computed(Computed<Rc<dyn Fn() -> R + 'static>>),
10}
11
12impl<R> From<Rc<dyn Fn() -> R + 'static>> for Callback<R> {
13    fn from(value: Rc<dyn Fn() -> R + 'static>) -> Self {
14        Callback::Basic(value)
15    }
16}
17
18impl<R, F: Fn() -> R + 'static> From<F> for Callback<R> {
19    fn from(value: F) -> Self {
20        Callback::Basic(Rc::new(value))
21    }
22}
23
24impl<R> From<Computed<Rc<dyn Fn() -> R + 'static>>> for Callback<R> {
25    fn from(value: Computed<Rc<dyn Fn() -> R + 'static>>) -> Self {
26        Callback::Computed(value)
27    }
28}
29
30impl<R: 'static> Callback<R> {
31    pub fn subscribe(&self) -> (Rc<dyn Fn() -> R + 'static>, Option<DropResource>) {
32        match self {
33            Self::Basic(func) => (func.clone(), None),
34            Self::Computed(computed) => {
35                let current = Rc::new(ValueMut::new(None));
36
37                let drop = computed.clone().subscribe_all(bind!(current, |new_fn| {
38                    current.set(Some(new_fn));
39                }));
40
41                let callback = Rc::new(move || -> R {
42                    let callback = current.get();
43
44                    let Some(callback) = callback else {
45                        unreachable!();
46                    };
47
48                    callback()
49                });
50
51                (callback, Some(drop))
52            }
53        }
54    }
55}
56
57pub enum Callback1<T, R> {
58    Basic(Rc<dyn Fn(T) -> R + 'static>),
59    Rc(Rc<dyn Fn(T) -> R + 'static>),
60    Computed(Computed<Rc<dyn Fn(T) -> R + 'static>>),
61}
62
63impl<T, R, F: Fn(T) -> R + 'static> From<F> for Callback1<T, R> {
64    fn from(value: F) -> Self {
65        Callback1::Basic(Rc::new(value))
66    }
67}
68
69impl<T, R> From<Rc<dyn Fn(T) -> R + 'static>> for Callback1<T, R> {
70    fn from(value: Rc<dyn Fn(T) -> R + 'static>) -> Self {
71        Callback1::Rc(value)
72    }
73}
74
75impl<T, R> From<Computed<Rc<dyn Fn(T) -> R + 'static>>> for Callback1<T, R> {
76    fn from(value: Computed<Rc<dyn Fn(T) -> R + 'static>>) -> Self {
77        Callback1::Computed(value)
78    }
79}
80
81impl<T: 'static, R: 'static> Callback1<T, R> {
82    pub fn subscribe(&self) -> (Rc<dyn Fn(T) -> R + 'static>, Option<DropResource>) {
83        match self {
84            Self::Basic(func) => (func.clone(), None),
85            Self::Rc(func) => (func.clone(), None),
86            Self::Computed(computed) => {
87                let current = Rc::new(ValueMut::new(None));
88
89                let drop = computed.clone().subscribe_all(bind!(current, |new_fn| {
90                    current.set(Some(new_fn));
91                }));
92
93                let callback = Rc::new(move |param: T| -> R {
94                    let callback = current.get();
95
96                    let Some(callback) = callback else {
97                        unreachable!();
98                    };
99
100                    callback(param)
101                });
102
103                (callback, Some(drop))
104            }
105        }
106    }
107}