Adding in child_signal method

This commit is contained in:
Pauan 2020-01-08 09:52:00 +01:00
parent 2befdc7aa4
commit 1c08b3043b
4 changed files with 78 additions and 23 deletions

View File

@ -145,7 +145,7 @@ impl Signal for Timestamps {
// TODO somehow share this safely between threads ? // TODO somehow share this safely between threads ?
thread_local! { thread_local! {
static TIMESTAMPS_MANAGER: Arc<Mutex<TimestampsManager>> = Arc::new(Mutex::new(TimestampsManager::new())); static TIMESTAMPS_MANAGER: Rc<RefCell<TimestampsManager>> = Rc::new(RefCell::new(TimestampsManager::new()));
} }
pub fn timestamps() -> Timestamps { pub fn timestamps() -> Timestamps {
@ -153,7 +153,7 @@ pub fn timestamps() -> Timestamps {
let timestamps = Timestamps::new(); let timestamps = Timestamps::new();
{ {
let mut lock = timestamps_manager.lock().unwrap_throw(); let mut lock = timestamps_manager.borrow_mut();
lock.states.push(Arc::downgrade(&timestamps.state)); lock.states.push(Arc::downgrade(&timestamps.state));
@ -161,7 +161,7 @@ pub fn timestamps() -> Timestamps {
let timestamps_manager = timestamps_manager.clone(); let timestamps_manager = timestamps_manager.clone();
lock.raf = Some(Raf::new(move |time| { 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| { lock.states.retain(|state| {
if let Some(state) = state.upgrade() { if let Some(state) = state.upgrade() {
@ -619,6 +619,7 @@ impl Signal for MutableAnimationSignal {
} }
// TODO verify that this is Sync and Send
struct MutableAnimationState { struct MutableAnimationState {
playing: bool, playing: bool,
duration: f64, duration: f64,

View File

@ -591,19 +591,24 @@ impl<A> DomBuilder<A> where A: AsRef<Node> {
self.set_text_signal(value); self.set_text_signal(value);
self self
} }
}
impl<A> DomBuilder<A> where A: AsRef<Node> {
#[inline] #[inline]
pub fn children_signal_vec<B>(mut self, children: B) -> Self pub fn children_signal_vec<B>(mut self, children: B) -> Self
where B: SignalVec<Item = Dom> + 'static { where B: SignalVec<Item = Dom> + 'static {
assert_eq!(self.has_children, false); self.check_children();
self.has_children = true;
operations::insert_children_signal_vec(self.element.as_ref().clone(), &mut self.callbacks, children); operations::insert_children_signal_vec(self.element.as_ref().clone(), &mut self.callbacks, children);
self self
} }
#[inline]
pub fn child_signal<B>(mut self, child: B) -> Self
where B: Signal<Item = Option<Dom>> + 'static {
self.check_children();
operations::insert_child_signal(self.element.as_ref().clone(), &mut self.callbacks, child);
self
}
} }
impl<A> DomBuilder<A> where A: AsRef<Element> { impl<A> DomBuilder<A> where A: AsRef<Element> {

View File

@ -1,4 +1,3 @@
#![recursion_limit="128"]
#![warn(unreachable_pub)] #![warn(unreachable_pub)]
#![deny(warnings)] #![deny(warnings)]

View File

@ -1,4 +1,5 @@
use std::sync::{Arc, Mutex}; use std::rc::Rc;
use std::cell::RefCell;
use std::future::Future; use std::future::Future;
use std::iter::IntoIterator; use std::iter::IntoIterator;
@ -64,17 +65,74 @@ pub(crate) fn insert_children_iter<'a, A: IntoIterator<Item = &'a mut Dom>>(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<A>(element: Node, callbacks: &mut Callbacks, signal: A)
where A: Signal<Item = Option<Dom>> + 'static {
struct State {
is_inserted: bool,
child: Option<Dom>,
}
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<A>(element: Node, callbacks: &mut Callbacks, signal: A) pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callbacks, signal: A)
where A: SignalVec<Item = Dom> + 'static { where A: SignalVec<Item = Dom> + 'static {
// TODO does this create a new struct type every time ?
struct State { struct State {
is_inserted: bool, is_inserted: bool,
children: Vec<Dom>, children: Vec<Dom>,
} }
// TODO use two separate Arcs ? let state = Rc::new(RefCell::new(State {
let state = Arc::new(Mutex::new(State {
is_inserted: false, is_inserted: false,
children: vec![], children: vec![],
})); }));
@ -83,7 +141,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
let state = state.clone(); let state = state.clone();
callbacks.after_insert(move |_| { callbacks.after_insert(move |_| {
let mut state = state.lock().unwrap_throw(); let mut state = state.borrow_mut();
if !state.is_inserted { if !state.is_inserted {
state.is_inserted = true; state.is_inserted = true;
@ -115,14 +173,6 @@ pub(crate) fn insert_children_signal_vec<A>(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<Dom>) { fn process_change(state: &mut State, element: &Node, change: VecDiff<Dom>) {
match change { match change {
VecDiff::Replace { values } => { VecDiff::Replace { values } => {
@ -204,7 +254,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
// TODO maybe move this into the after_insert callback and remove State // TODO maybe move this into the after_insert callback and remove State
// TODO verify that this will drop `children` // TODO verify that this will drop `children`
callbacks.after_remove(for_each_vec(signal, move |change| { 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); process_change(&mut state, &element, change);
})); }));