Skip to main content

freya_core/lifecycle/
writable_setter.rs

1use crate::prelude::*;
2
3/// A writable value whose updates go through a setter callback.
4///
5/// ```rust
6/// use freya::prelude::*;
7///
8/// fn app() -> impl IntoElement {
9///     let mut value = use_state(String::new);
10///     Input::new(WritableSetter::new(value, move |text| value.set(text)))
11/// }
12/// ```
13pub struct WritableSetter<T: 'static> {
14    value: Readable<T>,
15    on_change: EventHandler<T>,
16}
17
18impl<T: 'static> Clone for WritableSetter<T> {
19    fn clone(&self) -> Self {
20        Self {
21            value: self.value.clone(),
22            on_change: self.on_change.clone(),
23        }
24    }
25}
26
27impl<T: 'static> PartialEq for WritableSetter<T> {
28    fn eq(&self, other: &Self) -> bool {
29        self.value == other.value && self.on_change == other.on_change
30    }
31}
32
33impl<T: 'static> WritableSetter<T> {
34    /// The callback may transform or reject updates to the readable value.
35    pub fn new(value: impl IntoReadable<T>, on_change: impl Into<EventHandler<T>>) -> Self {
36        Self {
37            value: value.into_readable(),
38            on_change: on_change.into(),
39        }
40    }
41
42    /// Read the value and subscribe to changes.
43    pub fn read(&self) -> ReadableRef<T> {
44        self.value.read()
45    }
46
47    /// Read the value without subscribing to changes.
48    pub fn peek(&self) -> ReadableRef<T> {
49        self.value.peek()
50    }
51
52    /// Request an update through the setter callback.
53    pub fn set(&mut self, value: T) {
54        self.on_change.call(value);
55    }
56
57    /// Request an update only if the value differs from the current one.
58    pub fn set_if_modified(&mut self, value: T)
59    where
60        T: PartialEq,
61    {
62        if *self.peek() != value {
63            self.set(value);
64        }
65    }
66}
67
68pub trait IntoWritableSetter<T: 'static> {
69    fn into_writable_setter(self) -> WritableSetter<T>;
70}
71
72impl<T: 'static, Value: Into<WritableSetter<T>>> IntoWritableSetter<T> for Value {
73    fn into_writable_setter(self) -> WritableSetter<T> {
74        self.into()
75    }
76}
77
78impl<T: 'static> From<State<T>> for WritableSetter<T> {
79    fn from(value: State<T>) -> Self {
80        value.into_writable().into()
81    }
82}
83
84impl<T: 'static> From<Writable<T>> for WritableSetter<T> {
85    fn from(mut value: Writable<T>) -> Self {
86        Self::new(Readable::from(value.clone()), move |updated| {
87            *value.write() = updated;
88        })
89    }
90}
91
92impl<T: 'static> IntoReadable<T> for WritableSetter<T> {
93    fn into_readable(self) -> Readable<T> {
94        self.value
95    }
96}
97
98impl<T: 'static> From<WritableSetter<T>> for Readable<T> {
99    fn from(value: WritableSetter<T>) -> Self {
100        value.into_readable()
101    }
102}