use kas::prelude::*;
use std::fmt::Debug;
use std::marker::PhantomData;
impl_scope! {
#[autoimpl(Deref, DerefMut using self.inner)]
#[autoimpl(Scrollable using self.inner where W: trait)]
#[widget {
layout = self.inner;
}]
pub struct Adapt<A, W: Widget<Data = S>, S: Debug> {
core: widget_core!(),
state: S,
#[widget(&self.state)]
inner: W,
event_handler: Option<Box<dyn Fn(&mut EventCx, &A, &mut S, Event) -> IsUsed>>,
message_handlers: Vec<Box<dyn Fn(&mut EventCx, &A, &mut S) -> bool>>,
update_handler: Option<Box<dyn Fn(&mut ConfigCx, &A, &mut S)>>,
}
impl Self {
#[inline]
pub fn new(inner: W, state: S) -> Self {
Adapt {
core: Default::default(),
state,
inner,
event_handler: None,
message_handlers: vec![],
update_handler: None,
}
}
pub fn on_event<H>(mut self, handler: H) -> Self
where
H: Fn(&mut EventCx, &A, &mut S, Event) -> IsUsed + 'static,
{
debug_assert!(self.event_handler.is_none());
self.event_handler = Some(Box::new(handler));
self
}
pub fn on_message<M, H>(self, handler: H) -> Self
where
M: Debug + 'static,
H: Fn(&A, &mut S, M) + 'static,
{
self.on_messages(move |cx, data, state| {
if let Some(m) = cx.try_pop() {
handler(data, state, m);
true
} else {
false
}
})
}
pub fn on_messages<H>(mut self, handler: H) -> Self
where
H: Fn(&mut EventCx, &A, &mut S) -> bool + 'static,
{
self.message_handlers.push(Box::new(handler));
self
}
pub fn on_update<F>(mut self, update_handler: F) -> Self
where
F: Fn(&mut ConfigCx, &A, &mut S) + 'static,
{
debug_assert!(self.update_handler.is_none());
self.update_handler = Some(Box::new(update_handler));
self
}
}
impl Events for Self {
type Data = A;
fn update(&mut self, cx: &mut ConfigCx, data: &A) {
if let Some(handler) = self.update_handler.as_ref() {
handler(cx, data, &mut self.state);
}
}
fn handle_event(&mut self, cx: &mut EventCx, data: &Self::Data, event: Event) -> IsUsed {
if let Some(handler) = self.event_handler.as_ref() {
let is_used = handler(cx, data, &mut self.state, event);
if is_used.into() {
cx.update(self.as_node(data));
}
is_used
} else {
Unused
}
}
fn handle_messages(&mut self, cx: &mut EventCx, data: &A) {
let mut update = false;
for handler in self.message_handlers.iter() {
update |= handler(cx, data, &mut self.state);
}
if update {
cx.update(self.as_node(data));
}
}
}
}
impl_scope! {
#[autoimpl(Deref, DerefMut using self.inner)]
#[autoimpl(Scrollable using self.inner where W: trait)]
#[widget {
Data = A;
layout = self.inner;
}]
pub struct Map<A, W: Widget, F>
where
F: for<'a> Fn(&'a A) -> &'a W::Data,
{
core: widget_core!(),
#[widget((self.map_fn)(data))]
inner: W,
map_fn: F,
_data: PhantomData<A>,
}
impl Self {
pub fn new(inner: W, map_fn: F) -> Self {
Map {
core: Default::default(),
inner,
map_fn,
_data: PhantomData,
}
}
}
}