use std::{ cell::{Ref, RefMut}, fmt::Display, marker::PhantomData, ops::{Add, Div, Mul, Sub}, }; mod rt; use dioxus_core::ScopeState; pub use rt::*; pub fn use_init_signal_rt(cx: &ScopeState) { cx.use_hook(|| { let rt = crate::rt::claim_rt(cx.schedule_update_any()); cx.provide_context(rt); }); } pub fn use_signal(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal { cx.use_hook(|| { let rt: &'static SignalRt = cx.consume_context().unwrap(); let id = rt.init(f()); rt.subscribe(id, cx.scope_id()); struct SignalHook { signal: Signal, } impl Drop for SignalHook { fn drop(&mut self) { self.signal.rt.remove(self.signal.id); } } SignalHook { signal: Signal { id, rt, t: PhantomData, }, } }) .signal } pub struct Signal { id: usize, rt: &'static SignalRt, t: PhantomData, } impl Signal { pub fn read(&self) -> Ref { self.rt.read(self.id) } pub fn write(&self) -> RefMut { self.rt.write(self.id) } pub fn set(&mut self, value: T) { self.rt.set(self.id, value); } pub fn update(&self, _f: impl FnOnce(&mut T) -> O) -> O { let mut write = self.write(); _f(&mut *write) } } impl Signal { pub fn get(&self) -> T { self.rt.get(self.id) } } // impl std::ops::Deref for Signal { // type Target = dyn Fn() -> T; // fn deref(&self) -> &Self::Target { // todo!() // } // } impl std::clone::Clone for Signal { fn clone(&self) -> Self { Self { t: PhantomData, id: self.id, rt: self.rt, } } } impl Copy for Signal {} impl Display for Signal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.rt.with::(self.id, |v| T::fmt(v, f)) } } impl + Copy + 'static> std::ops::AddAssign for Signal { fn add_assign(&mut self, rhs: T) { self.set(self.get() + rhs); } } impl + Copy + 'static> std::ops::SubAssign for Signal { fn sub_assign(&mut self, rhs: T) { self.set(self.get() - rhs); } } impl + Copy + 'static> std::ops::MulAssign for Signal { fn mul_assign(&mut self, rhs: T) { self.set(self.get() * rhs); } } impl + Copy + 'static> std::ops::DivAssign for Signal { fn div_assign(&mut self, rhs: T) { self.set(self.get() / rhs); } } // impl + Copy> std::ops::AddAssign for Signal { // fn add_assign(&mut self, rhs: T) { // self.set((*self.current()) + rhs); // } // } // impl + Copy> std::ops::SubAssign for Signal { // fn sub_assign(&mut self, rhs: T) { // self.set((*self.current()) - rhs); // } // } // impl + Copy> std::ops::MulAssign for Signal { // fn mul_assign(&mut self, rhs: T) { // self.set((*self.current()) * rhs); // } // } // impl + Copy> std::ops::DivAssign for Signal { // fn div_assign(&mut self, rhs: T) { // self.set((*self.current()) / rhs); // } // }