use crate::*; /// Renders items from an iterator. pub struct Map where I: Iterator + Send + Sync, F: Fn() -> I + Send + Sync, { __: PhantomData<(E, B)>, /// Function that returns iterator over stacked components get_iter: F, /// Function that returns each stacked component get_item: G, } impl<'a, E, A, B, I, F, G> Map where I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a, { pub const fn new (get_iter: F, get_item: G) -> Self { Self { __: PhantomData, get_iter, get_item } } } impl<'a, E, A, B, I, F> Map>>>, I, F, fn(A, usize)->B> where E: Output, B: Render, I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a { pub const fn east ( size: E::Unit, get_iter: F, get_item: impl Fn(A, usize)->B + Send + Sync ) -> Map< E, A, Push>>, I, F, impl Fn(A, usize)->Push>> + Send + Sync > { Map { __: PhantomData, get_iter, get_item: move |item: A, index: usize|{ // FIXME: multiply let mut push: E::Unit = E::Unit::from(0u16); for _ in 0..index { push = push + size; } Push::x(push, Align::w(Fixed::x(size, get_item(item, index)))) } } } pub const fn south ( size: E::Unit, get_iter: F, get_item: impl Fn(A, usize)->B + Send + Sync ) -> Map< E, A, Push>>, I, F, impl Fn(A, usize)->Push>> + Send + Sync > where E: Output, B: Render, I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a { Map { __: PhantomData, get_iter, get_item: move |item: A, index: usize|{ // FIXME: multiply let mut push: E::Unit = E::Unit::from(0u16); for _ in 0..index { push = push + size; } Push::y(push, Align::n(Fixed::y(size, get_item(item, index)))) } } } } impl<'a, E, A, B, I, F, G> Content for Map where E: Output, B: Render, I: Iterator + Send + Sync + 'a, F: Fn() -> I + Send + Sync + 'a, G: Fn(A, usize)->B + Send + Sync { fn layout (&self, area: E::Area) -> E::Area { let Self { get_iter, get_item, .. } = self; let mut index = 0; let [mut min_x, mut min_y] = area.center(); let [mut max_x, mut max_y] = area.center(); for item in get_iter() { let [x,y,w,h] = get_item(item, index).layout(area).xywh(); min_x = min_x.min(x.into()); min_y = min_y.min(y.into()); max_x = max_x.max((x + w).into()); max_y = max_y.max((y + h).into()); index += 1; } let w = max_x - min_x; let h = max_y - min_y; //[min_x.into(), min_y.into(), w.into(), h.into()].into() area.center_xy([w.into(), h.into()].into()).into() } fn render (&self, to: &mut E) { let Self { get_iter, get_item, .. } = self; let mut index = 0; let area = Content::layout(self, to.area()); for item in get_iter() { let item = get_item(item, index); //to.place(area.into(), &item); to.place(item.layout(area), &item); index += 1; } } } #[inline] pub fn map_south( item_offset: O::Unit, item_height: O::Unit, item: impl Content ) -> impl Content { Push::y(item_offset, Fixed::y(item_height, Fill::x(item))) } #[inline] pub fn map_south_west( item_offset: O::Unit, item_height: O::Unit, item: impl Content ) -> impl Content { Push::y(item_offset, Align::nw(Fixed::y(item_height, Fill::x(item)))) } #[inline] pub fn map_east( item_offset: O::Unit, item_width: O::Unit, item: impl Content ) -> impl Content { Push::x(item_offset, Align::w(Fixed::x(item_width, Fill::y(item)))) }