1use std::any::{self, Any};
2
3use glam::Vec2;
4
5use crate::{
6 BoxConstraints, Callback, DrawContext, Event, EventContext, LayoutContext, RequestRedrawEvent,
7 SendSync, SharedSignal, Style,
8};
9
10#[allow(unused_variables)]
12pub trait View: SendSync + 'static {
13 type State: SendSync + 'static;
15
16 fn build(&self) -> Self::State;
18
19 fn style(&self) -> Style {
21 Style::default()
22 }
23
24 fn event(&self, state: &mut Self::State, cx: &mut EventContext, event: &Event) {}
26
27 fn layout(&self, state: &mut Self::State, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2 {
33 bc.min
34 }
35
36 fn draw(&self, state: &mut Self::State, cx: &mut DrawContext) {}
38}
39
40pub trait AnyView: SendSync {
44 fn style(&self) -> Style;
45
46 fn event(&self, state: &mut dyn Any, cx: &mut EventContext, event: &Event);
47
48 fn layout(&self, state: &mut dyn Any, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2;
49
50 fn draw(&self, state: &mut dyn Any, cx: &mut DrawContext);
51}
52
53impl<T: View> AnyView for T {
54 fn style(&self) -> Style {
55 self.style()
56 }
57
58 fn event(&self, state: &mut dyn Any, cx: &mut EventContext, event: &Event) {
59 if let Some(state) = state.downcast_mut::<T::State>() {
60 self.event(state, cx, event);
61 } else {
62 tracing::warn!("invalid state type on {}", any::type_name::<T>());
63 }
64 }
65
66 fn layout(&self, state: &mut dyn Any, cx: &mut LayoutContext, bc: BoxConstraints) -> Vec2 {
67 if let Some(state) = state.downcast_mut::<T::State>() {
68 self.layout(state, cx, bc)
69 } else {
70 tracing::warn!("invalid state type on {}", any::type_name::<T>());
71 bc.min
72 }
73 }
74
75 fn draw(&self, state: &mut dyn Any, cx: &mut DrawContext) {
76 if let Some(state) = state.downcast_mut::<T::State>() {
77 self.draw(state, cx);
78 } else {
79 tracing::warn!("invalid state type on {}", any::type_name::<T>());
80 }
81 }
82}
83
84impl<V: View + SendSync> View for SharedSignal<V> {
87 type State = (Callback<'static, ()>, V::State);
88
89 fn build(&self) -> Self::State {
90 (Callback::default(), self.get_untracked().build())
91 }
92
93 fn style(&self) -> Style {
94 self.get_untracked().style()
95 }
96
97 fn event(&self, (_, state): &mut Self::State, cx: &mut EventContext, event: &Event) {
98 self.get().event(state, cx, event);
99 }
100
101 fn layout(
102 &self,
103 (_, state): &mut Self::State,
104 cx: &mut LayoutContext,
105 bc: BoxConstraints,
106 ) -> Vec2 {
107 self.get().layout(state, cx, bc)
108 }
109
110 fn draw(&self, (callback, state): &mut Self::State, cx: &mut DrawContext) {
111 let event_sink = cx.event_sink.clone();
113 *callback = Callback::new(move |&()| event_sink.send(RequestRedrawEvent));
114
115 self.emitter().subscribe_weak(callback.downgrade());
116 self.get().draw(state, cx);
117 }
118}
119
120impl View for () {
121 type State = ();
122
123 fn build(&self) -> Self::State {}
124
125 fn event(&self, _state: &mut Self::State, _cx: &mut EventContext, _event: &Event) {}
126
127 fn layout(
128 &self,
129 _state: &mut Self::State,
130 _cx: &mut LayoutContext,
131 bc: BoxConstraints,
132 ) -> Vec2 {
133 bc.min
134 }
135
136 fn draw(&self, _state: &mut Self::State, _cx: &mut DrawContext) {}
137}