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