use druid::{Data, Widget, WidgetPod};
pub struct Store<F, T> {
inner: WidgetPod<T, Box<dyn Widget<T>>>,
pre_data_processor: fn(&F, &mut T),
post_data_processor: fn(&T, &mut F),
post_data: T,
}
impl<F: Data, T: Data> Store<F, T> {
pub fn new(
inner: impl Widget<T> + 'static,
pre_data_processor: fn(&F, &mut T),
post_data_processor: fn(&T, &mut F),
initial_post_data: T,
) -> Self {
Self {
inner: WidgetPod::new(inner).boxed(),
pre_data_processor,
post_data_processor,
post_data: initial_post_data,
}
}
}
impl<F: Data, T: Data + Default> Store<F, T> {
#[inline]
pub fn new_default(
inner: impl Widget<T> + 'static,
pre_data_processor: fn(&F, &mut T),
post_data_processor: fn(&T, &mut F),
) -> Self {
Self::new(inner, pre_data_processor, post_data_processor, T::default())
}
}
impl<F: Data, T: Data> Widget<F> for Store<F, T> {
fn event(
&mut self,
ctx: &mut druid::EventCtx,
event: &druid::Event,
data: &mut F,
env: &druid::Env,
) {
tracing::trace!("Event Called");
let mut post_data = self.post_data.to_owned();
self.inner.event(ctx, event, &mut post_data, env);
if !post_data.same(&self.post_data) {
self.post_data = post_data;
(self.post_data_processor)(&self.post_data, data);
tracing::trace!("Post Data Updated");
ctx.request_update();
}
}
fn lifecycle(
&mut self,
ctx: &mut druid::LifeCycleCtx,
event: &druid::LifeCycle,
_data: &F,
env: &druid::Env,
) {
tracing::trace!("Lifecycle Called");
self.inner.lifecycle(ctx, event, &self.post_data, env)
}
fn update(&mut self, ctx: &mut druid::UpdateCtx, _old_data: &F, data: &F, env: &druid::Env) {
let mut post_data = self.post_data.to_owned();
(self.pre_data_processor)(data, &mut post_data);
if !post_data.same(&self.post_data) {
tracing::trace!("Update Called");
self.inner.update(ctx, &self.post_data, env);
}
}
fn layout(
&mut self,
ctx: &mut druid::LayoutCtx,
bc: &druid::BoxConstraints,
_data: &F,
env: &druid::Env,
) -> druid::Size {
tracing::trace!("Layout Called");
self.inner.layout(ctx, bc, &self.post_data, env)
}
fn paint(&mut self, ctx: &mut druid::PaintCtx, _data: &F, env: &druid::Env) {
tracing::trace!("Paint Called");
self.inner.paint(ctx, &self.post_data, env)
}
}