use druid::{Data, Env, EventCtx, UpdateCtx, Widget, WidgetPod};
pub type ShowIfCallback<T> = fn(&T, &Env) -> bool;
pub struct ShowIf<T> {
inner: WidgetPod<T, Box<dyn Widget<T>>>,
showed: bool,
callback: ShowIfCallback<T>,
}
impl<T> ShowIf<T> {
pub fn new(inner: impl Widget<T> + 'static, callback: ShowIfCallback<T>) -> Self {
Self {
inner: WidgetPod::new(Box::new(inner)),
showed: false,
callback,
}
}
}
impl<T: Data> Widget<T> for ShowIf<T> {
fn event(&mut self, ctx: &mut EventCtx, event: &druid::Event, data: &mut T, env: &Env) {
let should_show = (self.callback)(data, env);
if self.showed != should_show {
ctx.children_changed();
self.showed = should_show;
} else if should_show {
self.inner.event(ctx, event, data, env);
}
}
fn lifecycle(
&mut self,
ctx: &mut druid::LifeCycleCtx,
event: &druid::LifeCycle,
data: &T,
env: &Env,
) {
let should_show = (self.callback)(data, env);
if let druid::LifeCycle::WidgetAdded = event {
self.inner.lifecycle(ctx, event, data, env);
} else if self.showed != should_show {
ctx.children_changed();
self.showed = should_show;
} else if should_show {
self.inner.lifecycle(ctx, event, data, env);
}
}
fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &T, data: &T, env: &Env) {
let should_show = (self.callback)(data, env);
if self.showed != should_show {
ctx.children_changed();
self.showed = should_show;
if should_show {
self.inner.update(ctx, data, env);
}
} else if self.showed {
self.inner.update(ctx, data, env);
}
}
fn layout(
&mut self,
ctx: &mut druid::LayoutCtx,
bc: &druid::BoxConstraints,
data: &T,
env: &Env,
) -> druid::Size {
let should_show = (self.callback)(data, env);
if should_show {
let size = self.inner.layout(ctx, bc, data, env);
self.inner.set_origin(ctx, druid::Point::ZERO);
size
} else {
bc.constrain((0., 0.))
}
}
fn paint(&mut self, ctx: &mut druid::PaintCtx, data: &T, env: &Env) {
let should_show = (self.callback)(data, env);
if should_show {
self.inner.paint(ctx, data, env)
}
}
}