use std::rc::Rc;
use crate::DropResource;
use super::{
Computed, Context, GraphId, ToComputed, dependencies::get_dependencies, value_inner::ValueInner,
};
#[derive(Clone)]
pub struct Value<T: Clone + PartialEq + 'static> {
inner: Rc<ValueInner<T>>,
}
impl<T: Clone + PartialEq + Default + 'static> Default for Value<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: Clone + PartialEq> PartialEq for Value<T> {
fn eq(&self, other: &Self) -> bool {
self.inner.id.eq(&other.inner.id)
}
}
impl<T: Clone + PartialEq + 'static> ToComputed<T> for Value<T> {
fn to_computed(&self) -> Computed<T> {
self.to_computed()
}
}
impl<T: Clone + PartialEq + 'static> ToComputed<T> for &Value<T> {
fn to_computed(&self) -> Computed<T> {
(*self).to_computed()
}
}
impl<T: Clone + PartialEq + 'static> Value<T> {
pub fn new(value: T) -> Self {
Value {
inner: Rc::new(ValueInner::new(value)),
}
}
pub fn with_connect<F>(value: T, create: F) -> Computed<T>
where
F: Fn(&Value<T>) -> DropResource + 'static,
{
let value = Value::new(value);
let value_clone = value.clone();
value
.to_computed()
.when_connect(move || create(&value_clone))
}
pub fn get(&self, context: &Context) -> T {
context.add_parent(self.inner.id, self.inner.clone());
self.inner.get()
}
pub fn map<K: Clone + 'static, F: 'static + Fn(T) -> K>(&self, fun: F) -> Computed<K> {
Computed::from({
let myself = self.clone();
move |context| fun(myself.get(context))
})
}
pub fn id(&self) -> GraphId {
self.inner.id
}
pub fn to_computed(&self) -> Computed<T> {
let myself = self.clone();
Computed::from(move |context| myself.get(context))
}
pub fn change(&self, change_fn: impl FnOnce(&mut T)) {
get_dependencies().transaction(|ctx| {
let mut value = self.get(ctx);
change_fn(&mut value);
self.set(value);
});
}
pub fn set(&self, value: T) {
get_dependencies().transaction(|_| {
let need_refresh = self.inner.set(value);
if need_refresh {
get_dependencies().report_set(self.inner.id);
}
});
}
pub fn add_event(&self, callback: impl Fn(T) + 'static) -> DropResource {
self.inner.add_event(callback)
}
}