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}