use std::cell::Ref;
use crate::{
connect_node_update::NodeUpdate,
connect_structs::Connect,
connect_update::ConnectUpdate,
node_traits::{AnyDynNode, ConnectNode, NodeValueAccess},
};
pub(crate) trait ConnectNodeUpdateInitiator {
fn before_get_node(&mut self, node: ConnectNode);
fn after_set_node(&mut self, node: ConnectNode);
fn after_set_nodes(&mut self, modified_nodes: Vec<AnyDynNode>);
}
impl ConnectNodeUpdateInitiator for Connect {
fn before_get_node<'a>(&mut self, node: ConnectNode) {
self.add_to_current_update_dependencies(&node);
}
fn after_set_node<'a>(&mut self, node: ConnectNode) {
match &mut self.modified_nodes {
None => {
self.after_set_nodes(vec![node.into()]);
}
Some(modified_nodes) => {
modified_nodes.push(node.into());
}
}
}
fn after_set_nodes(&mut self, mut modified_nodes: Vec<AnyDynNode>) {
let update_list = self.get_update_list(&mut modified_nodes);
self.recalculate_update_list(&mut modified_nodes, update_list);
}
}
trait ConnectNodeAccess {
fn get_concrete_from_node<'a, N: ?Sized, R>(&self, node: &N) -> &'a R;
fn get_mut_concrete_from_node<'a, N: ?Sized, R>(&self, node: &mut N) -> &'a mut R;
}
impl ConnectNodeAccess for Connect {
fn get_concrete_from_node<'a, N: ?Sized, R>(&self, node: &N) -> &'a R {
let node_dyn_ptr: *const N = node;
let node_ptr = node_dyn_ptr.cast::<R>();
unsafe {
if let Some(node_ref) = node_ptr.as_ref() {
node_ref
} else {
unreachable!()
}
}
}
fn get_mut_concrete_from_node<'a, N: ?Sized, R>(&self, node: &mut N) -> &'a mut R {
let node_dyn_ptr: *mut N = node;
let node_ptr = node_dyn_ptr.cast::<R>();
unsafe {
if let Some(node_mut) = node_ptr.as_mut() {
node_mut
} else {
unreachable!()
}
}
}
}
pub trait ConnectNodeInterface {
fn get<'a, T: NodeValueAccess + Into<ConnectNode> + Clone + 'static>(
&mut self,
node: &'a T,
) -> Ref<'a, T::Value>;
fn set<T: NodeValueAccess + Into<ConnectNode> + Clone + 'static>(
&mut self,
node: &'_ T,
value: T::Value,
) -> T::Value;
}
impl ConnectNodeInterface for Connect {
fn get<'a, T: NodeValueAccess + Into<ConnectNode> + Clone + 'static>(
&mut self,
node: &'a T,
) -> Ref<'a, T::Value> {
self.before_get_node(node.clone().into());
node.get_inert()
}
fn set<T: NodeValueAccess + Into<ConnectNode> + Clone + 'static>(
&mut self,
node: &'_ T,
value: T::Value,
) -> T::Value {
let prev_value = node.set_inert(value);
let is_changed = !node.equal(&prev_value);
if is_changed {
self.after_set_node(node.clone().into());
}
prev_value
}
}