use taffy::style::FlexDirection;
use crate::{
context::UpdateCx,
id::ViewId,
style::{Style, StyleClassRef},
view::{IntoView, View},
view_tuple::ViewTuple,
};
pub struct Stack {
id: ViewId,
direction: Option<FlexDirection>,
}
pub(crate) fn create_stack(
children: Vec<Box<dyn View>>,
direction: Option<FlexDirection>,
) -> Stack {
let id = ViewId::new();
id.set_children(children);
Stack { id, direction }
}
pub fn stack<VT: ViewTuple + 'static>(children: VT) -> Stack {
create_stack(children.into_views(), None)
}
pub fn h_stack<VT: ViewTuple + 'static>(children: VT) -> Stack {
create_stack(children.into_views(), Some(FlexDirection::Row))
}
pub fn v_stack<VT: ViewTuple + 'static>(children: VT) -> Stack {
create_stack(children.into_views(), Some(FlexDirection::Column))
}
fn from_iter<V>(iterator: impl IntoIterator<Item = V>, direction: Option<FlexDirection>) -> Stack
where
V: IntoView + 'static,
{
create_stack(
iterator
.into_iter()
.map(|v| -> Box<dyn View> { v.into_any() })
.collect(),
direction,
)
}
pub fn stack_from_iter<V>(iterator: impl IntoIterator<Item = V>) -> Stack
where
V: IntoView + 'static,
{
from_iter(iterator, None)
}
pub fn h_stack_from_iter<V>(iterator: impl IntoIterator<Item = V>) -> Stack
where
V: IntoView + 'static,
{
from_iter(iterator, Some(FlexDirection::Row))
}
pub fn v_stack_from_iter<V>(iterator: impl IntoIterator<Item = V>) -> Stack
where
V: IntoView + 'static,
{
from_iter(iterator, Some(FlexDirection::Column))
}
impl View for Stack {
fn id(&self) -> ViewId {
self.id
}
fn view_style(&self) -> Option<crate::style::Style> {
self.direction
.map(|direction| Style::new().flex_direction(direction))
}
fn debug_name(&self) -> std::borrow::Cow<'static, str> {
match self.direction {
Some(FlexDirection::Column) => "Vertical Stack".into(),
Some(FlexDirection::Row) => "Horizontal Stack".into(),
_ => "Stack".into(),
}
}
fn update(&mut self, _cx: &mut UpdateCx, state: Box<dyn std::any::Any>) {
if let Ok(state) = state.downcast::<Vec<Box<dyn View>>>() {
self.id.set_children(*state);
self.id.request_all();
}
}
}
impl Stack {
pub fn add_class_by_idx(self, class: impl Fn(usize) -> StyleClassRef) -> Self {
for (index, child) in self.id.children().into_iter().enumerate() {
let style_class = class(index);
child.add_class(style_class);
}
self
}
}
pub trait StackExt {
fn stack(self, direction: FlexDirection) -> Stack;
fn v_stack(self) -> Stack
where
Self: Sized,
{
StackExt::stack(self, FlexDirection::Column)
}
fn h_stack(self) -> Stack
where
Self: Sized,
{
StackExt::stack(self, FlexDirection::Row)
}
}
impl<V: IntoView + 'static, T: IntoIterator<Item = V> + 'static> StackExt for T {
fn stack(self, direction: FlexDirection) -> Stack {
from_iter(self, Some(direction))
}
}