use std::marker::PhantomData;
use crate::{View, Node, Bind, Context, HasId, Event, IdPath, IdentifyExt};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ForEach<C, I, F, V> {
collection: C,
view_func: F,
phantom_item: PhantomData<I>,
phantom_view: PhantomData<V>,
}
impl<C, I, F, V> ForEach<C, I, F, V>
where
for<'a> &'a C: IntoIterator<Item = &'a I> + Clone,
I: HasId,
F: Fn(&I) -> V,
V: Bind
{
pub fn new(collection: C, view_func: F) -> Self {
Self {
collection,
view_func,
phantom_item: PhantomData,
phantom_view: PhantomData,
}
}
}
impl<C, I, F, V> Bind for ForEach<C, I, F, V>
where
for<'a> &'a C: IntoIterator<Item = &'a I> + Clone,
I: HasId,
F: Fn(&I) -> V,
V: Bind
{}
impl<C, I, F, V> View for ForEach<C, I, F, V>
where
for<'a> &'a C: IntoIterator<Item = &'a I> + Clone,
I: HasId,
F: Fn(&I) -> V,
V: View
{
fn fire(&self, event: &Event, id_path: &IdPath) {
if let Some(head) = id_path.head() {
if let Some(item) = self.collection.into_iter().find(|item| item.id() == head) {
(self.view_func)(item).fire(event, &id_path.tail());
}
}
}
fn render(&mut self, context: &Context) -> Node {
Node::Group {
children: self.collection
.into_iter()
.map(|item| {
let id = item.id();
(self.view_func)(item).render(&context.child(id.clone())).identify(id)
})
.collect(),
}
}
}