fgr/reactivity/
node.rs

1use super::context::{batch, clear_dirty_flag_at_end, mark_nodes_to_be_updated, outer_node};
2use std::cell::{Cell, RefCell, Ref, RefMut};
3use std::ops::{Deref, DerefMut};
4use std::rc::{Rc, Weak};
5
6pub struct Node {
7    pub this: Rc<RefCell<Option<Weak<dyn HasNode>>>>,
8    pub update_op: RefCell<Option<Box<dyn FnMut()->bool>>>,
9    pub visited: Cell<bool>,
10    pub dirty: Cell<bool>,
11    pub dependencies: RefCell<Vec<Rc<dyn HasNode>>>,
12    pub dependents: RefCell<Vec<Weak<dyn HasNode>>>,
13}
14
15pub trait HasNode {
16    fn node(&self) -> &Node;
17}
18
19impl HasNode for Node {
20    fn node(&self) -> &Node {
21        self
22    }
23}
24
25impl Node {
26    pub fn new(this: Rc<RefCell<Option<Weak<dyn HasNode>>>>) -> Node {
27        Node {
28            this,
29            update_op: RefCell::new(None),
30            visited: Cell::new(false),
31            dirty: Cell::new(false),
32            dependencies: RefCell::new(Vec::new()),
33            dependents: RefCell::new(Vec::new()),
34        }
35    }
36}
37
38impl Drop for Node {
39    fn drop(&mut self) {
40        let this = self.this.borrow();
41        let this = this.as_ref().unwrap();
42        for dependency in &*self.dependencies.borrow() {
43            dependency.node().dependents.borrow_mut().retain(|x| !x.ptr_eq(this));
44        }
45    }
46}
47
48pub struct NodeWithValue<A> {
49    pub value: RefCell<Option<A>>,
50    pub node: Node,
51}
52
53impl<A> NodeWithValue<A> {
54    pub fn new(this: Rc<RefCell<Option<Weak<dyn HasNode>>>>, value: A) -> NodeWithValue<A> {
55        NodeWithValue {
56            value: RefCell::new(Some(value)),
57            node: Node::new(this),
58        }
59    }
60
61    pub fn new2(node: Node) -> NodeWithValue<A> {
62        NodeWithValue {
63            value: RefCell::new(None),
64            node,
65        }
66    }
67}
68
69impl<A> HasNode for NodeWithValue<A> {
70    fn node(&self) -> &Node {
71        &self.node
72    }
73}
74
75pub struct NodeValRef<'a,A> {
76    x: Ref<'a,Option<A>>,
77    read: Cell<bool>,
78    node: Rc<dyn HasNode>,
79}
80
81impl<'a,A> NodeValRef<'a,A> {
82    pub fn new(node_with_value: &'a NodeWithValue<A>, node: Rc<dyn HasNode>) -> NodeValRef<'a,A> {
83        NodeValRef {
84            x: node_with_value.value.borrow(),
85            read: Cell::new(false),
86            node
87        }
88    }
89}
90
91impl<'a,A> Deref for NodeValRef<'a,A> {
92    type Target = A;
93
94    fn deref(&self) -> &Self::Target {
95        self.read.set(true);
96        self.x.deref().as_ref().unwrap()
97    }
98}
99
100impl<'a,A> Drop for NodeValRef<'a,A> {
101    fn drop(&mut self) {
102        if self.read.get() {
103            if let Some(outer_node) = outer_node() {
104                outer_node.node().dependencies.borrow_mut().push(self.node.clone());
105                self.node.node().dependents.borrow_mut().push(Rc::downgrade(&outer_node));
106            }
107        }
108    }
109}
110
111pub struct NodeValRefMut<'a,A> {
112    x: Option<RefMut<'a,Option<A>>>,
113    written: Cell<bool>,
114    node: Rc<dyn HasNode>,
115}
116
117impl<'a,A> NodeValRefMut<'a,A> {
118    pub fn new(node_with_value: &'a NodeWithValue<A>, node: Rc<dyn HasNode>) -> NodeValRefMut<'a,A> {
119        NodeValRefMut {
120            x: Some(node_with_value.value.borrow_mut()),
121            written: Cell::new(false),
122            node
123        }
124    }
125}
126
127impl<'a,A> Deref for NodeValRefMut<'a,A> {
128    type Target = A;
129
130    fn deref(&self) -> &Self::Target {
131        self.x.as_ref().unwrap().deref().as_ref().unwrap()
132    }
133}
134
135impl<'a,A> DerefMut for NodeValRefMut<'a,A> {
136    fn deref_mut(&mut self) -> &mut Self::Target {
137        self.written.set(true);
138        self.x.as_mut().unwrap().deref_mut().as_mut().unwrap()
139    }
140}
141
142impl<'a,A> Drop for NodeValRefMut<'a,A> {
143    fn drop(&mut self) {
144        self.x = None;
145        if self.written.get() {
146            batch(|| {
147                self.node.node().dirty.set(true);
148                clear_dirty_flag_at_end(Rc::downgrade(&self.node));
149                mark_nodes_to_be_updated([Rc::downgrade(&self.node)].iter().cloned());
150            });
151        }
152    }
153}