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 ?
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 {
@ -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(&timestamps.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,

View File

@ -591,19 +591,24 @@ impl<A> DomBuilder<A> where A: AsRef<Node> {
self.set_text_signal(value);
self
}
}
impl<A> DomBuilder<A> where A: AsRef<Node> {
#[inline]
pub fn children_signal_vec<B>(mut self, children: B) -> Self
where B: SignalVec<Item = Dom> + '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<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> {

View File

@ -1,4 +1,3 @@
#![recursion_limit="128"]
#![warn(unreachable_pub)]
#![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::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)
where A: SignalVec<Item = Dom> + 'static {
// TODO does this create a new struct type every time ?
struct State {
is_inserted: bool,
children: Vec<Dom>,
}
// 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<A>(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<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>) {
match change {
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 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);
}));