use std::any::{self, Any};
use glam::Vec2;
use crate::{
BoxConstraints, Callback, DrawContext, Event, EventContext, LayoutContext, RequestRedrawEvent,
SendSync, SharedSignal, Style,
};
#[allow(unused_variables)]
pub trait View: SendSync + 'static {
type State: SendSync + 'static;
fn build(&self) -> Self::State;
fn style(&self) -> Style {
Style::default()
}
fn event(&self, state: &mut Self::State, cx: &mut EventContext, event: &Event) {}
fn layout(&self, state: &mut Self::State, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2 {
bc.min
}
fn draw(&self, state: &mut Self::State, cx: &mut DrawContext) {}
}
pub trait AnyView: SendSync {
fn style(&self) -> Style;
fn event(&self, state: &mut dyn Any, cx: &mut EventContext, event: &Event);
fn layout(&self, state: &mut dyn Any, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2;
fn draw(&self, state: &mut dyn Any, cx: &mut DrawContext);
}
impl<T: View> AnyView for T {
fn style(&self) -> Style {
self.style()
}
fn event(&self, state: &mut dyn Any, cx: &mut EventContext, event: &Event) {
if let Some(state) = state.downcast_mut::<T::State>() {
self.event(state, cx, event);
} else {
tracing::warn!("invalid state type on {}", any::type_name::<T>());
}
}
fn layout(&self, state: &mut dyn Any, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2 {
if let Some(state) = state.downcast_mut::<T::State>() {
self.layout(state, cx, bc)
} else {
tracing::warn!("invalid state type on {}", any::type_name::<T>());
bc.min
}
}
fn draw(&self, state: &mut dyn Any, cx: &mut DrawContext) {
if let Some(state) = state.downcast_mut::<T::State>() {
self.draw(state, cx);
} else {
tracing::warn!("invalid state type on {}", any::type_name::<T>());
}
}
}
impl<V: View + SendSync> View for SharedSignal<V> {
type State = (Callback<'static, ()>, V::State);
fn build(&self) -> Self::State {
(Callback::default(), self.get_untracked().build())
}
fn style(&self) -> Style {
self.get_untracked().style()
}
fn event(&self, (_, state): &mut Self::State, cx: &mut EventContext, event: &Event) {
self.get().event(state, cx, event);
}
fn layout(
&self,
(_, state): &mut Self::State,
cx: &mut LayoutContext,
bc: BoxConstraints,
) -> Vec2 {
self.get().layout(state, cx, bc)
}
fn draw(&self, (callback, state): &mut Self::State, cx: &mut DrawContext) {
let event_sink = cx.event_sink.clone();
*callback = Callback::new(move |&()| event_sink.send(RequestRedrawEvent));
self.emitter().subscribe_weak(callback.downgrade());
self.get().draw(state, cx);
}
}
impl View for () {
type State = ();
fn build(&self) -> Self::State {}
fn event(&self, _state: &mut Self::State, _cx: &mut EventContext, _event: &Event) {}
fn layout(
&self,
_state: &mut Self::State,
_cx: &mut LayoutContext,
bc: BoxConstraints,
) -> Vec2 {
bc.min
}
fn draw(&self, _state: &mut Self::State, _cx: &mut DrawContext) {}
}