summaryrefslogtreecommitdiffstats
path: root/graphics/src/layer/menu.rs
blob: e94ef964b73ca45fbe966ee1b88a1c56dfa8ec52 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::backend::Backend;
use crate::{Primitive, Renderer};
use iced_native::{
    layer, mouse, Background, Color, Font, HorizontalAlignment, Point,
    Rectangle, VerticalAlignment,
};

impl<B> layer::menu::Renderer for Renderer<B>
where
    B: Backend,
{
    fn decorate(
        &mut self,
        bounds: Rectangle,
        _cursor_position: Point,
        (primitives, mouse_cursor): Self::Output,
    ) -> Self::Output {
        (
            Primitive::Group {
                primitives: vec![
                    Primitive::Quad {
                        bounds,
                        background: Background::Color(
                            [0.87, 0.87, 0.87].into(),
                        ),
                        border_color: [0.7, 0.7, 0.7].into(),
                        border_width: 1,
                        border_radius: 0,
                    },
                    primitives,
                ],
            },
            mouse_cursor,
        )
    }

    fn draw<T: ToString>(
        &mut self,
        bounds: Rectangle,
        cursor_position: Point,
        options: &[T],
        hovered_option: Option<usize>,
        text_size: u16,
        padding: u16,
    ) -> Self::Output {
        use std::f32;

        let is_mouse_over = bounds.contains(cursor_position);

        let mut primitives = Vec::new();

        for (i, option) in options.iter().enumerate() {
            let is_selected = hovered_option == Some(i);

            let bounds = Rectangle {
                x: bounds.x,
                y: bounds.y
                    + ((text_size as usize + padding as usize * 2) * i) as f32,
                width: bounds.width,
                height: f32::from(text_size + padding * 2),
            };

            if is_selected {
                primitives.push(Primitive::Quad {
                    bounds,
                    background: Background::Color([0.4, 0.4, 1.0].into()),
                    border_color: Color::TRANSPARENT,
                    border_width: 0,
                    border_radius: 0,
                });
            }

            primitives.push(Primitive::Text {
                content: option.to_string(),
                bounds: Rectangle {
                    x: bounds.x + f32::from(padding),
                    y: bounds.center_y(),
                    width: f32::INFINITY,
                    ..bounds
                },
                size: f32::from(text_size),
                font: Font::Default,
                color: if is_selected {
                    Color::WHITE
                } else {
                    Color::BLACK
                },
                horizontal_alignment: HorizontalAlignment::Left,
                vertical_alignment: VerticalAlignment::Center,
            });
        }

        (
            Primitive::Group { primitives },
            if is_mouse_over {
                mouse::Interaction::Pointer
            } else {
                mouse::Interaction::default()
            },
        )
    }
}