charm_ui/
component.rs

1use super::layout::Bounds;
2use super::{CharmResult, Color};
3
4#[derive(Clone, Copy)]
5pub struct RenderCtx {
6    pub(crate) bounds: Bounds,
7}
8
9pub struct Renderer<'a> {
10    pub(crate) canvas: &'a mut sdl2::render::WindowCanvas,
11}
12
13impl<'a> Renderer<'a> {
14    pub fn fill_rect(
15        &mut self,
16        bounds: impl Into<Bounds>,
17        color: impl Into<Color>,
18    ) -> CharmResult<()> {
19        let bounds = bounds.into();
20        let color = color.into();
21
22        self.canvas.set_draw_color(color);
23        self.canvas
24            .fill_rect(sdl2::rect::Rect::new(
25                bounds.x as i32,
26                bounds.y as i32,
27                bounds.width as u32,
28                bounds.height as u32,
29            ))
30            .unwrap();
31
32        Ok(())
33    }
34}
35
36pub trait Component<Store> {
37    fn render<'a>(
38        &self,
39        ctx: RenderCtx,
40        renderer: &mut Renderer<'a>,
41        store: &Store,
42    ) -> CharmResult<Bounds>;
43}
44
45pub struct Parameter<T, Store> {
46    thunk: Box<dyn Fn(&Store) -> T>,
47}
48
49impl<T, Store> Parameter<T, Store> {
50    pub fn constant(constant: impl Into<T>) -> Self
51    where
52        T: 'static + Clone,
53    {
54        let constant = constant.into();
55        let thunk = move |_: &Store| constant.clone();
56
57        Self {
58            thunk: Box::new(thunk),
59        }
60    }
61
62    pub fn closure<O>(thunk: impl Fn(&Store) -> O + 'static) -> Self
63    where
64        O: Into<T>,
65    {
66        Self {
67            thunk: Box::new(move |store| thunk(store).into()),
68        }
69    }
70
71    pub(crate) fn resolve(&self, store: &Store) -> T {
72        (self.thunk)(store)
73    }
74}
75
76pub trait IntoParameter<P, Store> {
77    fn into_parameter(self) -> Parameter<P, Store>;
78}
79
80impl<P, Store> IntoParameter<P, Store> for P
81where
82    P: Clone + 'static,
83{
84    fn into_parameter(self) -> Parameter<P, Store> {
85        Parameter::constant(self)
86    }
87}
88
89impl<P, Store> IntoParameter<P, Store> for Parameter<P, Store> {
90    fn into_parameter(self) -> Parameter<P, Store> {
91        self
92    }
93}