Skip to main content

bexa_ui_core/
signal.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3
4/// Read-only handle to a reactive value.
5#[derive(Debug)]
6pub struct Signal<T> {
7    inner: Rc<RefCell<T>>,
8}
9
10impl<T> Clone for Signal<T> {
11    fn clone(&self) -> Self {
12        Signal { inner: self.inner.clone() }
13    }
14}
15
16impl<T: Clone> Signal<T> {
17    /// Returns a clone of the current value.
18    pub fn get(&self) -> T {
19        self.inner.borrow().clone()
20    }
21}
22
23impl<T> Signal<T> {
24    /// Borrows the current value and passes it to the closure.
25    /// Avoids cloning — preferred in hot paths like draw().
26    pub fn with<R>(&self, f: impl FnOnce(&T) -> R) -> R {
27        f(&*self.inner.borrow())
28    }
29}
30
31/// Write handle to a reactive value.
32#[derive(Debug)]
33pub struct SetSignal<T> {
34    inner: Rc<RefCell<T>>,
35}
36
37impl<T> Clone for SetSignal<T> {
38    fn clone(&self) -> Self {
39        SetSignal { inner: self.inner.clone() }
40    }
41}
42
43impl<T> SetSignal<T> {
44    /// Replaces the current value.
45    pub fn set(&self, value: T) {
46        *self.inner.borrow_mut() = value;
47    }
48
49    /// Mutates the current value via a closure.
50    pub fn update(&self, f: impl FnOnce(&mut T)) {
51        f(&mut *self.inner.borrow_mut());
52    }
53}
54
55/// Creates a signal pair: `(reader, writer)`.
56///
57/// ```
58/// let (count, set_count) = create_signal(0);
59/// set_count.set(42);
60/// assert_eq!(count.get(), 42);
61/// ```
62pub fn create_signal<T>(initial: T) -> (Signal<T>, SetSignal<T>) {
63    let inner = Rc::new(RefCell::new(initial));
64    (
65        Signal { inner: inner.clone() },
66        SetSignal { inner },
67    )
68}
69
70/// Convert various types into a `Signal<T>`.
71pub trait IntoSignal<T> {
72    fn into_signal(self) -> Signal<T>;
73}
74
75impl<T> IntoSignal<T> for Signal<T> {
76    fn into_signal(self) -> Signal<T> {
77        self
78    }
79}
80
81impl<T> IntoSignal<T> for Rc<RefCell<T>> {
82    fn into_signal(self) -> Signal<T> {
83        Signal { inner: self }
84    }
85}