embedded_menu/selection_indicator/style/
border.rs

1use embedded_graphics::{
2    prelude::{DrawTarget, Size},
3    primitives::{Primitive, PrimitiveStyle, Rectangle},
4    Drawable,
5};
6
7use crate::{
8    interaction::InputState,
9    selection_indicator::{
10        style::{interpolate, IndicatorStyle},
11        Insets,
12    },
13    theme::Theme,
14};
15
16#[derive(Clone, Copy)]
17pub struct Border;
18
19impl IndicatorStyle for Border {
20    type Shape = Rectangle;
21    type State = ();
22
23    fn padding(&self, _state: &Self::State, _height: i32) -> Insets {
24        Insets {
25            left: 2,
26            top: 1,
27            right: 1,
28            bottom: 1,
29        }
30    }
31
32    fn shape(&self, _state: &Self::State, bounds: Rectangle, _fill_width: u32) -> Self::Shape {
33        bounds
34    }
35
36    fn draw<T, D>(
37        &self,
38        _state: &Self::State,
39        input_state: InputState,
40        theme: &T,
41        display: &mut D,
42    ) -> Result<Self::Shape, D::Error>
43    where
44        T: Theme,
45        D: DrawTarget<Color = T::Color>,
46    {
47        let display_area = display.bounding_box();
48
49        let fill_width = if let InputState::InProgress(progress) = input_state {
50            interpolate(progress as u32, 0, 255, 0, display_area.size.width)
51        } else {
52            0
53        };
54
55        display_area
56            .into_styled(PrimitiveStyle::with_stroke(theme.selection_color(), 1))
57            .draw(display)?;
58
59        Rectangle::new(
60            display_area.top_left,
61            Size::new(fill_width, display_area.size.height),
62        )
63        .into_styled(PrimitiveStyle::with_fill(theme.selection_color()))
64        .draw(display)?;
65
66        Ok(Rectangle::new(
67            display_area.top_left,
68            Size::new(fill_width, display_area.size.height),
69        ))
70    }
71}