freya_components/
tile.rs

1use freya_core::prelude::*;
2use torin::prelude::*;
3
4#[derive(Debug, Default, PartialEq, Clone, Copy)]
5pub enum TileStatus {
6    #[default]
7    Idle,
8    Hovering,
9}
10
11#[derive(Clone, PartialEq)]
12pub struct Tile {
13    children: Vec<Element>,
14    leading: Option<Element>,
15    on_select: Option<EventHandler<()>>,
16    key: DiffKey,
17}
18
19impl KeyExt for Tile {
20    fn write_key(&mut self) -> &mut DiffKey {
21        &mut self.key
22    }
23}
24
25impl Default for Tile {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl ChildrenExt for Tile {
32    fn get_children(&mut self) -> &mut Vec<Element> {
33        &mut self.children
34    }
35}
36
37impl Tile {
38    pub fn new() -> Self {
39        Self {
40            children: Vec::new(),
41            leading: None,
42            on_select: None,
43            key: DiffKey::None,
44        }
45    }
46
47    pub fn leading(mut self, leading: impl Into<Element>) -> Self {
48        self.leading = Some(leading.into());
49        self
50    }
51
52    pub fn on_select(mut self, on_select: impl FnMut(()) + 'static) -> Self {
53        self.on_select = Some(EventHandler::new(on_select));
54        self
55    }
56
57    pub fn key(mut self, key: impl Into<DiffKey>) -> Self {
58        self.key = key.into();
59        self
60    }
61}
62
63impl Render for Tile {
64    fn render(&self) -> impl IntoElement {
65        let mut status = use_state(|| TileStatus::Idle);
66
67        let on_press = {
68            let on_select = self.on_select.clone();
69            move |e: Event<PressEventData>| {
70                if let Some(on_select) = &on_select {
71                    e.stop_propagation();
72                    on_select.call(());
73                }
74            }
75        };
76
77        let on_pointer_enter = {
78            move |_| {
79                *status.write() = TileStatus::Hovering;
80            }
81        };
82
83        let on_pointer_leave = {
84            move |_| {
85                *status.write() = TileStatus::Idle;
86            }
87        };
88
89        rect()
90            .direction(Direction::Horizontal)
91            .padding(8.)
92            .spacing(8.)
93            .cross_align(Alignment::center())
94            .on_press(on_press)
95            .on_pointer_enter(on_pointer_enter)
96            .on_pointer_leave(on_pointer_leave)
97            .maybe_child(
98                self.leading
99                    .clone()
100                    .map(|leading| rect().padding(Gaps::new_all(4.0)).child(leading)),
101            )
102            .children(self.children.clone())
103    }
104
105    fn render_key(&self) -> DiffKey {
106        self.key.clone().or(self.default_key())
107    }
108}