Skip to main content

vizia_core/binding/
res.rs

1use crate::prelude::*;
2use vizia_reactive::{
3    DerivedSignal, Memo, ReadSignal, Signal, SignalGet, SyncDerivedSignal, SyncReadSignal,
4    SyncSignal,
5};
6
7#[macro_export]
8/// A macro for implementing the [Res] trait for simple `Copy` types.
9macro_rules! impl_res_simple {
10    ($t:ty) => {
11        impl Res<$t> for $t {
12            fn get_value(&self, _: &impl DataContext) -> $t {
13                *self
14            }
15        }
16    };
17}
18
19#[macro_export]
20/// A macro for implementing the [Res] trait for `Clone` types.
21macro_rules! impl_res_clone {
22    ($t:ty) => {
23        impl Res<$t> for $t {
24            fn get_value(&self, _: &impl DataContext) -> $t {
25                self.clone()
26            }
27        }
28    };
29}
30
31/// A trait which allows passing a value or reactive source to a view or modifier.
32///
33/// For example, the `Label` view constructor takes a type which implements `Res<T>` where
34/// `T` implements `ToString`. This allows the user to pass a type which implements `ToString`,
35/// such as `String` or `&str`, or a signal/resource producing a type which implements `ToString`.
36pub trait Res<T> {
37    /// Returns the value of a resource by value.
38    fn get_value(&self, _: &impl DataContext) -> T;
39
40    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
41    where
42        Self: Sized,
43        F: 'static + Fn(&mut Context, Self),
44    {
45        (closure)(cx, self);
46    }
47
48    /// Converts this signal into a signal mirror tied to `entity`.
49    ///
50    /// Reactive signals keep the returned signal updated over time,
51    /// while non-reactive values initialize it once.
52    fn to_signal(self, cx: &mut Context) -> Signal<T>
53    where
54        Self: Sized + 'static,
55        T: Clone + 'static,
56    {
57        let signal = Signal::new(self.get_value(cx));
58        self.set_or_bind(cx, move |cx, res| {
59            signal.set(res.get_value(cx));
60        });
61        signal
62    }
63}
64
65impl<T: Clone + 'static> Res<T> for Signal<T> {
66    fn get_value(&self, _: &impl DataContext) -> T {
67        SignalGet::get(self)
68    }
69
70    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
71    where
72        F: 'static + Fn(&mut Context, Self),
73    {
74        Binding::new(cx, self, move |cx| {
75            (closure)(cx, self);
76        });
77    }
78
79    fn to_signal(self, _cx: &mut Context) -> Signal<T>
80    where
81        Self: Sized + 'static,
82        T: Clone + 'static,
83    {
84        self
85    }
86}
87
88impl<T: Clone + Send + Sync + 'static> Res<T> for SyncSignal<T> {
89    fn get_value(&self, _: &impl DataContext) -> T {
90        SignalGet::get(self)
91    }
92
93    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
94    where
95        F: 'static + Fn(&mut Context, Self),
96    {
97        Binding::new(cx, self, move |cx| {
98            (closure)(cx, self);
99        });
100    }
101}
102
103impl<T: Clone + 'static> Res<T> for ReadSignal<T> {
104    fn get_value(&self, _: &impl DataContext) -> T {
105        SignalGet::get(self)
106    }
107
108    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
109    where
110        F: 'static + Fn(&mut Context, Self),
111    {
112        Binding::new(cx, self, move |cx| {
113            (closure)(cx, self);
114        });
115    }
116}
117
118impl<T: Clone + Send + Sync + 'static> Res<T> for SyncReadSignal<T> {
119    fn get_value(&self, _: &impl DataContext) -> T {
120        SignalGet::get(self)
121    }
122
123    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
124    where
125        F: 'static + Fn(&mut Context, Self),
126    {
127        Binding::new(cx, self, move |cx| {
128            (closure)(cx, self);
129        });
130    }
131}
132
133impl<T: Clone + PartialEq + 'static> Res<T> for Memo<T> {
134    fn get_value(&self, _: &impl DataContext) -> T {
135        SignalGet::get(self)
136    }
137
138    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
139    where
140        F: 'static + Fn(&mut Context, Self),
141    {
142        Binding::new(cx, self, move |cx| {
143            (closure)(cx, self);
144        });
145    }
146}
147
148impl<T, O, GF, UF> Res<O> for DerivedSignal<T, O, GF, UF>
149where
150    T: Clone + 'static,
151    O: Clone + 'static,
152    GF: Fn(&T) -> O + Copy + 'static,
153    UF: Fn(&O) -> T + Copy + 'static,
154{
155    fn get_value(&self, _: &impl DataContext) -> O {
156        SignalGet::get(self)
157    }
158
159    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
160    where
161        F: 'static + Fn(&mut Context, Self),
162    {
163        Binding::new(cx, self, move |cx| {
164            (closure)(cx, self);
165        });
166    }
167}
168
169impl<T, O, GF, UF> Res<O> for SyncDerivedSignal<T, O, GF, UF>
170where
171    T: Clone + Send + Sync + 'static,
172    O: Clone + Send + Sync + 'static,
173    GF: Fn(&T) -> O + Copy + Send + Sync + 'static,
174    UF: Fn(&O) -> T + Copy + Send + Sync + 'static,
175{
176    fn get_value(&self, _: &impl DataContext) -> O {
177        SignalGet::get(self)
178    }
179
180    fn set_or_bind<F>(self, cx: &mut Context, closure: F)
181    where
182        F: 'static + Fn(&mut Context, Self),
183    {
184        Binding::new(cx, self, move |cx| {
185            (closure)(cx, self);
186        });
187    }
188}
189
190impl_res_simple!(i8);
191impl_res_simple!(i16);
192impl_res_simple!(i32);
193impl_res_simple!(i64);
194impl_res_simple!(i128);
195impl_res_simple!(isize);
196impl_res_simple!(u8);
197impl_res_simple!(u16);
198impl_res_simple!(u32);
199impl_res_simple!(u64);
200impl_res_simple!(u128);
201impl_res_simple!(usize);
202impl_res_simple!(char);
203impl_res_simple!(bool);
204impl_res_simple!(f32);
205impl_res_simple!(f64);
206impl_res_simple!(CursorIcon);
207impl_res_simple!(Overflow);
208impl_res_simple!(LengthValue);
209impl_res_simple!(FontWeight);
210impl_res_simple!(FontWeightKeyword);
211impl_res_simple!(FontSlant);
212impl_res_simple!(Angle);
213impl_res_simple!(TextAlign);
214impl_res_simple!(TextOverflow);
215impl_res_simple!(LineClamp);
216impl_res_clone!(Shadow);
217impl_res_clone!(LinearGradientBuilder);
218impl_res_clone!(ShadowBuilder);
219impl_res_simple!(FontVariation);
220impl_res_clone!(Filter);
221impl_res_simple!(Opacity);
222impl_res_simple!(FontWidth);
223impl_res_clone!(Translate);
224impl_res_clone!(Scale);
225impl_res_clone!(Position);
226impl_res_simple!(PointerEvents);
227impl_res_simple!(ButtonVariant);
228impl_res_simple!(AvatarVariant);
229impl_res_clone!(FamilyOwned);
230impl_res_simple!(TextDecorationLine);
231impl_res_clone!(TextStroke);
232impl_res_clone!(TextStrokeStyle);
233impl_res_simple!(Alignment);
234impl_res_simple!(WindowPosition);
235impl_res_simple!(Anchor);
236impl_res_simple!(AnchorTarget);
237impl_res_clone!(std::ops::Range<f32>);
238impl_res_simple!(Direction);
239impl_res_simple!(LayoutWrap);
240impl_res_clone!(BackgroundSize);
241impl_res_simple!(FontSizeKeyword);
242
243impl<'i> Res<FontFamily<'i>> for FontFamily<'i> {
244    fn get_value(&self, _: &impl DataContext) -> Self {
245        self.clone()
246    }
247}
248
249impl<'i> Res<BackgroundImage<'i>> for BackgroundImage<'i> {
250    fn get_value(&self, _: &impl DataContext) -> Self {
251        self.clone()
252    }
253}
254
255impl<'s> Res<&'s str> for &'s str {
256    fn get_value(&self, _: &impl DataContext) -> &'s str {
257        self
258    }
259}
260
261impl<'s> Res<&'s String> for &'s String {
262    fn get_value(&self, _: &impl DataContext) -> Self {
263        self
264    }
265}
266
267impl Res<String> for String {
268    fn get_value(&self, _: &impl DataContext) -> Self {
269        self.clone()
270    }
271}
272
273impl Res<Transform> for Transform {
274    fn get_value(&self, _: &impl DataContext) -> Transform {
275        self.clone()
276    }
277}
278
279impl Res<Color> for Color {
280    fn get_value(&self, _: &impl DataContext) -> Color {
281        *self
282    }
283}
284
285impl Res<LinearGradient> for LinearGradient {
286    fn get_value(&self, _: &impl DataContext) -> LinearGradient {
287        self.clone()
288    }
289}
290
291impl Res<Units> for Units {
292    fn get_value(&self, _: &impl DataContext) -> Units {
293        *self
294    }
295}
296
297impl Res<Visibility> for Visibility {
298    fn get_value(&self, _: &impl DataContext) -> Visibility {
299        *self
300    }
301}
302
303impl Res<Display> for Display {
304    fn get_value(&self, _: &impl DataContext) -> Display {
305        *self
306    }
307}
308
309impl Res<LayoutType> for LayoutType {
310    fn get_value(&self, _: &impl DataContext) -> LayoutType {
311        *self
312    }
313}
314
315impl Res<PositionType> for PositionType {
316    fn get_value(&self, _: &impl DataContext) -> PositionType {
317        *self
318    }
319}
320
321impl Res<BorderStyleKeyword> for BorderStyleKeyword {
322    fn get_value(&self, _: &impl DataContext) -> BorderStyleKeyword {
323        *self
324    }
325}
326
327impl<T: Clone + Res<T>> Res<Option<T>> for Option<T> {
328    fn get_value(&self, _: &impl DataContext) -> Option<T> {
329        self.clone()
330    }
331}
332
333impl Res<Length> for Length {
334    fn get_value(&self, _: &impl DataContext) -> Self {
335        self.clone()
336    }
337}
338
339impl Res<LengthOrPercentage> for LengthOrPercentage {
340    fn get_value(&self, _: &impl DataContext) -> Self {
341        self.clone()
342    }
343}
344
345impl Res<RGBA> for RGBA {
346    fn get_value(&self, _: &impl DataContext) -> Self {
347        *self
348    }
349}
350
351impl<T: Clone + Res<T>> Res<Vec<T>> for Vec<T> {
352    fn get_value(&self, _: &impl DataContext) -> Vec<T> {
353        self.clone()
354    }
355}
356
357impl<T: Clone + Res<T>, const N: usize> Res<[T; N]> for [T; N] {
358    fn get_value(&self, _: &impl DataContext) -> Self {
359        self.clone()
360    }
361}
362
363impl<T: Clone + 'static> Res<Vec<T>> for &'static [T] {
364    fn get_value(&self, _: &impl DataContext) -> Vec<T> {
365        self.to_vec()
366    }
367}
368
369impl<T1: Clone, T2: Clone> Res<(T1, T2)> for (T1, T2) {
370    fn get_value(&self, _cx: &impl DataContext) -> (T1, T2) {
371        self.clone()
372    }
373}
374
375impl<T1: Clone, T2: Clone, T3: Clone> Res<(T1, T2, T3)> for (T1, T2, T3) {
376    fn get_value(&self, _cx: &impl DataContext) -> (T1, T2, T3) {
377        self.clone()
378    }
379}
380
381impl<T1: Clone, T2: Clone, T3: Clone, T4: Clone> Res<(T1, T2, T3, T4)> for (T1, T2, T3, T4) {
382    fn get_value(&self, _cx: &impl DataContext) -> (T1, T2, T3, T4) {
383        self.clone()
384    }
385}