use druid::kurbo::{Point, Rect, Size};
use druid::{
BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx, PaintCtx,
UpdateCtx, Widget, WidgetPod,
};
pub struct Stack<T: Data> {
children: Vec<WidgetPod<T, Box<dyn Widget<T>>>>,
}
impl<T: Data> Stack<T> {
pub fn new() -> Self {
Stack {
children: Vec::new(),
}
}
pub fn with_child(mut self, child: impl Widget<T> + 'static) -> Self {
self.add_child(child);
self
}
pub fn add_child(&mut self, child: impl Widget<T> + 'static) {
self.children.push(WidgetPod::new(child).boxed());
}
}
impl<T: Data> Widget<T> for Stack<T> {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
self.children.reverse();
for child in &mut self.children {
child.event(ctx, event, data, env);
if ctx.is_handled() {
break;
}
}
self.children.reverse()
}
fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {
for child in &mut self.children {
child.lifecycle(ctx, event, data, env);
}
}
fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &T, data: &T, env: &Env) {
for child in &mut self.children {
child.update(ctx, data, env);
}
}
fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size {
for child in &mut self.children {
child.layout(ctx, bc, data, env);
child.set_layout_rect(
ctx,
data,
env,
Rect::from_origin_size(Point::ORIGIN, bc.max()),
)
}
bc.max()
}
fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {
for child in &mut self.children {
child.paint(ctx, data, env);
}
}
}