freya_components/
cursor_area.rs

1use freya_core::prelude::*;
2
3/// A container that changes the cursor icon when hovered.
4///
5/// When the component is dropped while still being hovered, the cursor
6/// is automatically reset to the default.
7///
8/// # Example
9///
10/// ```rust
11/// # use freya::prelude::*;
12/// fn app() -> impl IntoElement {
13///     CursorArea::new().child("Hover me!")
14/// }
15/// ```
16#[derive(Clone, PartialEq)]
17pub struct CursorArea {
18    children: Vec<Element>,
19    layout: LayoutData,
20    key: DiffKey,
21    cursor_icon: CursorIcon,
22}
23
24impl Default for CursorArea {
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30impl ChildrenExt for CursorArea {
31    fn get_children(&mut self) -> &mut Vec<Element> {
32        &mut self.children
33    }
34}
35
36impl KeyExt for CursorArea {
37    fn write_key(&mut self) -> &mut DiffKey {
38        &mut self.key
39    }
40}
41
42impl LayoutExt for CursorArea {
43    fn get_layout(&mut self) -> &mut LayoutData {
44        &mut self.layout
45    }
46}
47
48impl ContainerExt for CursorArea {}
49
50impl CursorArea {
51    pub fn new() -> Self {
52        Self {
53            children: Vec::new(),
54            layout: LayoutData::default(),
55            key: DiffKey::None,
56            cursor_icon: CursorIcon::Pointer,
57        }
58    }
59
60    /// Set the cursor icon to show when hovered.
61    /// Default is [CursorIcon::Pointer].
62    pub fn icon(mut self, cursor_icon: CursorIcon) -> Self {
63        self.cursor_icon = cursor_icon;
64        self
65    }
66}
67
68impl Render for CursorArea {
69    fn render(&self) -> impl IntoElement {
70        let mut hovering = use_state(|| false);
71        let cursor_icon = self.cursor_icon;
72
73        use_drop(move || {
74            if hovering() {
75                Cursor::set(CursorIcon::default());
76            }
77        });
78
79        let on_pointer_enter = move |_: Event<PointerEventData>| {
80            hovering.set(true);
81            Cursor::set(cursor_icon);
82        };
83
84        let on_pointer_leave = move |_: Event<PointerEventData>| {
85            hovering.set(false);
86            Cursor::set(CursorIcon::default());
87        };
88
89        rect()
90            .layout(self.layout.clone())
91            .on_pointer_enter(on_pointer_enter)
92            .on_pointer_leave(on_pointer_leave)
93            .children(self.children.clone())
94    }
95
96    fn render_key(&self) -> DiffKey {
97        self.key.clone().or(self.default_key())
98    }
99}