Skip to main content

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
66impl Component for Tile {
67    fn render(&self) -> impl IntoElement {
68        let mut status = use_state(|| TileStatus::Idle);
69
70        let on_press = {
71            let on_select = self.on_select.clone();
72            move |e: Event<PressEventData>| {
73                if let Some(on_select) = &on_select {
74                    e.stop_propagation();
75                    on_select.call(());
76                }
77            }
78        };
79
80        let on_pointer_enter = {
81            move |_| {
82                *status.write() = TileStatus::Hovering;
83            }
84        };
85
86        let on_pointer_leave = {
87            move |_| {
88                *status.write() = TileStatus::Idle;
89            }
90        };
91
92        rect()
93            .direction(Direction::Horizontal)
94            .padding(8.)
95            .spacing(8.)
96            .cross_align(Alignment::center())
97            .on_press(on_press)
98            .on_pointer_enter(on_pointer_enter)
99            .on_pointer_leave(on_pointer_leave)
100            .maybe_child(
101                self.leading
102                    .clone()
103                    .map(|leading| rect().padding(Gaps::new_all(4.0)).child(leading)),
104            )
105            .children(self.children.clone())
106    }
107
108    fn render_key(&self) -> DiffKey {
109        self.key.clone().or(self.default_key())
110    }
111}