diff --git a/src/animation.rs b/src/animation.rs index c10fc1b..72deb47 100644 --- a/src/animation.rs +++ b/src/animation.rs @@ -145,7 +145,7 @@ impl Signal for Timestamps { // TODO somehow share this safely between threads ? thread_local! { - static TIMESTAMPS_MANAGER: Arc> = Arc::new(Mutex::new(TimestampsManager::new())); + static TIMESTAMPS_MANAGER: Rc> = Rc::new(RefCell::new(TimestampsManager::new())); } pub fn timestamps() -> Timestamps { @@ -153,7 +153,7 @@ pub fn timestamps() -> Timestamps { let timestamps = Timestamps::new(); { - let mut lock = timestamps_manager.lock().unwrap_throw(); + let mut lock = timestamps_manager.borrow_mut(); lock.states.push(Arc::downgrade(×tamps.state)); @@ -161,7 +161,7 @@ pub fn timestamps() -> Timestamps { let timestamps_manager = timestamps_manager.clone(); lock.raf = Some(Raf::new(move |time| { - let mut lock = timestamps_manager.lock().unwrap_throw(); + let mut lock = timestamps_manager.borrow_mut(); lock.states.retain(|state| { if let Some(state) = state.upgrade() { @@ -619,6 +619,7 @@ impl Signal for MutableAnimationSignal { } +// TODO verify that this is Sync and Send struct MutableAnimationState { playing: bool, duration: f64, diff --git a/src/dom.rs b/src/dom.rs index 20c7a40..86c52e2 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -591,19 +591,24 @@ impl DomBuilder where A: AsRef { self.set_text_signal(value); self } -} -impl DomBuilder where A: AsRef { #[inline] pub fn children_signal_vec(mut self, children: B) -> Self where B: SignalVec + 'static { - assert_eq!(self.has_children, false); - self.has_children = true; - + self.check_children(); operations::insert_children_signal_vec(self.element.as_ref().clone(), &mut self.callbacks, children); self } + + #[inline] + pub fn child_signal(mut self, child: B) -> Self + where B: Signal> + 'static { + + self.check_children(); + operations::insert_child_signal(self.element.as_ref().clone(), &mut self.callbacks, child); + self + } } impl DomBuilder where A: AsRef { diff --git a/src/lib.rs b/src/lib.rs index 64f8c66..d824b9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -#![recursion_limit="128"] #![warn(unreachable_pub)] #![deny(warnings)] diff --git a/src/operations.rs b/src/operations.rs index c4b4d8f..52bc062 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -1,4 +1,5 @@ -use std::sync::{Arc, Mutex}; +use std::rc::Rc; +use std::cell::RefCell; use std::future::Future; use std::iter::IntoIterator; @@ -64,17 +65,74 @@ pub(crate) fn insert_children_iter<'a, A: IntoIterator>(elem } +fn after_insert(is_inserted: bool, callbacks: &mut Callbacks) { + callbacks.leak(); + + if is_inserted { + callbacks.trigger_after_insert(); + } +} + + +pub(crate) fn insert_child_signal(element: Node, callbacks: &mut Callbacks, signal: A) + where A: Signal> + 'static { + + struct State { + is_inserted: bool, + child: Option, + } + + let state = Rc::new(RefCell::new(State { + is_inserted: false, + child: None, + })); + + { + let state = state.clone(); + + callbacks.after_insert(move |_| { + let mut state = state.borrow_mut(); + + if !state.is_inserted { + state.is_inserted = true; + + if let Some(ref mut child) = state.child { + child.callbacks.trigger_after_insert(); + } + } + }); + } + + // TODO verify that this will drop `child` + callbacks.after_remove(for_each(signal, move |mut child| { + let mut state = state.borrow_mut(); + + if let Some(old_child) = state.child.take() { + bindings::remove_child(&element, &old_child.element); + + old_child.callbacks.discard(); + } + + if let Some(ref mut new_child) = child { + bindings::append_child(&element, &new_child.element); + + after_insert(state.is_inserted, &mut new_child.callbacks); + } + + state.child = child; + })); +} + + pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callbacks, signal: A) where A: SignalVec + 'static { - // TODO does this create a new struct type every time ? struct State { is_inserted: bool, children: Vec, } - // TODO use two separate Arcs ? - let state = Arc::new(Mutex::new(State { + let state = Rc::new(RefCell::new(State { is_inserted: false, children: vec![], })); @@ -83,7 +141,7 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb let state = state.clone(); callbacks.after_insert(move |_| { - let mut state = state.lock().unwrap_throw(); + let mut state = state.borrow_mut(); if !state.is_inserted { state.is_inserted = true; @@ -115,14 +173,6 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb } } - fn after_insert(is_inserted: bool, callbacks: &mut Callbacks) { - callbacks.leak(); - - if is_inserted { - callbacks.trigger_after_insert(); - } - } - fn process_change(state: &mut State, element: &Node, change: VecDiff) { match change { VecDiff::Replace { values } => { @@ -204,7 +254,7 @@ pub(crate) fn insert_children_signal_vec(element: Node, callbacks: &mut Callb // TODO maybe move this into the after_insert callback and remove State // TODO verify that this will drop `children` callbacks.after_remove(for_each_vec(signal, move |change| { - let mut state = state.lock().unwrap_throw(); + let mut state = state.borrow_mut(); process_change(&mut state, &element, change); }));