use crate::component::{Component, EventCx, LayoutCx, MeasureCx};
use crate::event::Event;
use crate::geom::{Rect, Size};
use crate::layout::Constraint;
use crate::node::Node;
use crate::render::RenderCx;
use crate::style::{Layout, Style};
pub struct Stack {
children: Vec<Node>,
style: Style,
}
impl Stack {
pub fn new() -> Self {
Self {
children: Vec::new(),
style: Style::default().layout(Layout::Horizontal),
}
}
pub fn child(mut self, component: impl Component + 'static) -> Self {
self.children.push(Node::new(component));
self
}
pub fn padding(mut self, value: u16) -> Self {
self.style = self.style.padding(value);
self
}
}
impl Component for Stack {
fn render(&self, cx: &mut RenderCx) {
for child in &self.children {
child.render_with_parent(cx.buffer, cx.focused_id, cx.clip_rect, cx.wrap, cx.truncate, cx.align, Some(&cx.style));
}
}
fn for_each_child(&self, f: &mut dyn FnMut(&Node)) {
for child in &self.children {
f(child);
}
}
fn for_each_child_mut(&mut self, f: &mut dyn FnMut(&mut Node)) {
for child in &mut self.children {
f(child);
}
}
fn measure(&self, constraint: Constraint, _cx: &mut MeasureCx) -> Size {
let mut max_w: u16 = 0;
let mut max_h: u16 = 0;
for child in &self.children {
let s = child.measure(constraint);
max_w = max_w.max(s.width);
max_h = max_h.max(s.height);
}
Size {
width: max_w.saturating_add(self.style.padding.left).saturating_add(self.style.padding.right),
height: max_h.saturating_add(self.style.padding.top).saturating_add(self.style.padding.bottom),
}
}
fn focusable(&self) -> bool {
false
}
fn event(&mut self, event: &Event, cx: &mut EventCx) {
if matches!(event, Event::Focus | Event::Blur | Event::Tick) {
return;
}
for child in self.children.iter_mut().rev() {
let mut child_cx =
EventCx::with_task_sender(&mut child.dirty, cx.global_dirty, cx.quit, cx.phase, cx.propagation_stopped, cx.task_sender.clone());
child.component.event(event, &mut child_cx);
}
}
fn layout(&mut self, rect: Rect, _cx: &mut LayoutCx) {
let inner = rect.inner(self.style.padding);
for child in &mut self.children {
child.layout(inner);
}
}
fn style(&self) -> Style {
self.style.clone()
}
}