1use std::cell::{RefCell, RefMut};
2
3use crate::{
4 canvas::{Canvas, LogicalRect},
5 context::EventContext,
6 events::{Event, Message},
7 layout::{Flow, Layer, Measure, compute_split},
8 listeners::{DrawListener, ErasedListenerBucket, ListenerStore},
9 state::{State, StateOwner},
10};
11
12pub type FactoryFn<P> = fn(Component, P) -> Node;
13
14pub trait Props: Clone + 'static {}
15
16impl Props for () {}
17
18#[derive(Default)]
19pub struct Component {
20 inner: RefCell<Spec>,
21}
22
23impl Component {
24 fn get_inner_mut(&self) -> RefMut<'_, Spec> {
25 self.inner.borrow_mut()
26 }
27}
28
29impl Component {
30 pub fn draw(&self, listener: impl Fn(&mut Canvas) + 'static) {
31 self.get_inner_mut().renderer = Some(Box::new(listener));
32 }
33
34 pub fn listen<E: Event>(&self, listener: impl FnMut(&mut EventContext<E>) + 'static) {
35 self.get_inner_mut().listeners.push(Box::new(listener));
36 }
37
38 pub fn state<T: 'static>(&self, value: T) -> State<T> {
39 self.get_inner_mut().state.insert(value)
40 }
41}
42
43pub struct Node {
44 spec: Spec,
45 composition: Composition,
46}
47
48impl From<Component> for Node {
49 fn from(value: Component) -> Self {
50 let Component { inner } = value;
51
52 Self {
53 spec: inner.into_inner(),
54 composition: Composition::default(),
55 }
56 }
57}
58
59impl Node {
60 pub fn new(component: Component) -> Self {
61 Self::from(component)
62 }
63
64 pub fn from_factory<P: Props>(factory: FactoryFn<P>, props: P) -> Self {
65 factory(Component::default(), props)
66 }
67
68 pub(crate) fn get_renderer(&self) -> Option<&DrawListener> {
69 self.spec.renderer.as_ref()
70 }
71
72 pub(crate) fn get_listeners(
73 &mut self,
74 msg: &Message,
75 ) -> Option<&mut Box<dyn ErasedListenerBucket>> {
76 self.spec.listeners.get_mut(msg)
77 }
78
79 pub(crate) fn composition(&self) -> &Composition {
80 &self.composition
81 }
82}
83
84impl Node {
85 pub fn child<P: Props>(mut self, measure: Measure, factory: FactoryFn<P>, props: P) -> Self {
86 let factory = Box::new(move || Node::from_factory(factory, props.clone()));
87 self.composition.push(Child::Static(factory), measure);
88 self
89 }
90
91 pub fn set_flow(mut self, flow: Flow) -> Self {
92 self.composition.flow = flow;
93 self
94 }
95
96 pub(crate) fn get_layer(&self) -> Layer {
97 self.composition.layer
98 }
99}
100
101#[derive(Default)]
102pub(crate) struct Spec {
103 pub renderer: Option<DrawListener>,
104 pub listeners: ListenerStore,
105 pub state: StateOwner,
106}
107
108pub(crate) enum Child {
109 Static(Box<dyn Fn() -> Node>),
110}
111
112#[derive(Default)]
113pub(crate) struct Composition {
114 flow: Flow,
115 layer: Layer,
116 children: Vec<(Child, Measure)>,
117}
118
119impl Composition {
120 pub fn push(&mut self, child: Child, measure: Measure) {
121 self.children.push((child, measure));
122 }
123
124 pub fn children(&self) -> impl Iterator<Item = &(Child, Measure)> {
125 self.children.iter()
126 }
127
128 pub fn split(&self, area: LogicalRect, measures: &[Measure]) -> Vec<LogicalRect> {
129 compute_split(self.flow, area, measures)
130 }
131}