use std::cell::RefCell;
use std::rc::Rc;
use crate::reactive::context;
#[derive(Clone)]
pub struct Signal<T> {
value: Rc<RefCell<T>>,
id: usize,
}
static SIGNAL_COUNTER: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
impl<T> Signal<T> {
pub fn new(value: T) -> Self {
let id = SIGNAL_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
Signal {
value: Rc::new(RefCell::new(value)),
id,
}
}
pub fn get(&self) -> std::cell::Ref<'_, T> {
context::track_signal(self.id);
self.value.borrow()
}
pub fn set(&self, new_value: T) {
*self.value.borrow_mut() = new_value;
context::trigger_effects(self.id);
}
pub fn update<F: FnOnce(&mut T)>(&self, f: F) {
f(&mut *self.value.borrow_mut());
context::trigger_effects(self.id);
}
pub fn id(&self) -> usize {
self.id
}
}
impl<T: Clone> Signal<T> {
pub fn get_clone(&self) -> T {
self.get().clone()
}
}
impl<T: Clone + 'static> Signal<T> {
pub fn from_ref(signal: &Signal<T>) -> Self {
let val = signal.get_clone();
let new = Signal::new(val);
new
}
}
pub fn signal<T>(value: T) -> Signal<T> {
Signal::new(value)
}