This commit is contained in:
2025-08-15 15:48:00 -04:00
parent c5aa0a02e2
commit 78ea738b8e
8 changed files with 222 additions and 52 deletions

View File

@@ -1,34 +1,57 @@
use std::marker::PhantomData;
use crate::{
Painter, Sense, SenseFn, SenseShape, SenseTrigger, Ui, Widget, WidgetFn, WidgetId, WidgetLike,
};
use crate::{Painter, Widget, WidgetFn, WidgetId, WidgetLike};
pub struct Sensor<F: SenseFn<Ctx>, Ctx> {
pub struct Sensor<Ctx> {
inner: WidgetId,
f: F,
_pd: PhantomData<Ctx>,
sense: Sense,
f: Box<dyn SenseFn<Ctx>>,
}
impl<F: SenseFn<Ctx>, Ctx: 'static> Widget<Ctx> for Sensor<F, Ctx> {
impl<Ctx: 'static> Widget<Ctx> for Sensor<Ctx> {
fn draw(&self, painter: &mut Painter<Ctx>) {
(self.f)(painter.ctx_mut());
painter.draw(&self.inner);
painter.sense(
SenseTrigger {
shape: painter.region,
sense: self.sense,
},
self.f.box_clone(),
);
painter.draw(self.inner.as_any());
}
}
pub trait SenseFn<Ctx> = Fn(&mut Ctx) + 'static;
pub trait Sensable<Ctx: 'static, Tag> {
fn sense<F: SenseFn<Ctx>>(self, f: F) -> impl WidgetFn<Sensor<F, Ctx>, Ctx>;
pub trait SenseCtx: 'static {
fn active(&mut self, trigger: &SenseTrigger) -> bool;
}
impl<W: WidgetLike<Ctx, Tag>, Ctx: 'static, Tag> Sensable<Ctx, Tag> for W {
fn sense<F: SenseFn<Ctx>>(self, f: F) -> impl WidgetFn<Sensor<F, Ctx>, Ctx> {
|ui| {
let inner = self.add(ui).erase_type();
pub trait WidgetSenseFn<W: Widget<Ctx>, Ctx> = Fn(&WidgetId<W>, &mut Ui<Ctx>, &mut Ctx) + 'static;
pub trait Sensable<W: Widget<Ctx>, Ctx: 'static, Tag> {
// copied here so LSP can at least get the UI and id
fn sense<F: Fn(&WidgetId<W>, &mut Ui<Ctx>, &mut Ctx) + 'static + Clone>(
self,
sense: Sense,
f: F,
) -> impl WidgetFn<Sensor<Ctx>, Ctx>;
}
impl<W: WidgetLike<Ctx, Tag>, Ctx: SenseCtx, Tag> Sensable<W::Widget, Ctx, Tag> for W
where
W::Widget: Widget<Ctx>,
{
fn sense<F: WidgetSenseFn<W::Widget, Ctx> + Clone>(
self,
sense: Sense,
f: F,
) -> impl WidgetFn<Sensor<Ctx>, Ctx> {
move |ui| {
let inner_arg = self.add(ui);
let inner = inner_arg.clone().erase_type();
Sensor {
inner,
f,
_pd: PhantomData,
sense,
f: Box::new(move |ui, ctx| (f)(&inner_arg, ui, ctx)),
}
}
}