matrix_gui/widgets/
bar.rs1use crate::prelude::*;
8
9pub struct Bar<'a, ID, COL: PixelColor> {
21 region: &'a Region<ID>,
23 padding: Option<Size>,
25 color_filled: OptionColor<COL>,
27 color_unfilled: OptionColor<COL>,
29 border: Option<COL>,
31 filled_value: u16,
33 unfilled_value: u16,
35}
36
37impl<'a, ID: WidgetId, COL: PixelColor> Bar<'a, ID, COL> {
38 pub const fn new(
39 region: &'a Region<ID>,
40 min_value: i16,
41 max_value: i16,
42 cur_value: i16,
43 ) -> Bar<'a, ID, COL> {
44 Bar {
45 region,
46 padding: None,
47 color_filled: OptionColor::none(),
48 color_unfilled: OptionColor::none(),
49 border: None,
50 filled_value: if cur_value >= min_value {
51 (cur_value - min_value) as u16
52 } else {
53 0
54 },
55 unfilled_value: if cur_value <= max_value {
56 (max_value - cur_value) as u16
57 } else {
58 0
59 },
60 }
61 }
62
63 pub const fn with_padding(mut self, padding: Size) -> Self {
64 self.padding = Some(padding);
65 self
66 }
67
68 pub const fn with_filled_color(mut self, color_filled: COL) -> Self {
69 self.color_filled.set_color(color_filled);
70 self
71 }
72
73 pub const fn with_unfilled_color(mut self, color_unfilled: COL) -> Self {
74 self.color_unfilled.set_color(color_unfilled);
75 self
76 }
77
78 pub const fn with_border_color(mut self, border_color: COL) -> Self {
79 self.border = Some(border_color);
80 self
81 }
82}
83
84impl<DRAW: DrawTarget<Color = COL>, ID: WidgetId, COL: PixelColor> Widget<DRAW, COL>
85 for Bar<'_, ID, COL>
86{
87 fn draw(&mut self, ui: &mut Ui<DRAW, COL>) -> GuiResult<Response> {
88 let widget_state = ui.get_widget_state(self.region.id())?;
89 if widget_state.compare_set(RenderStatus::Rendered) {
90 return Ok(Response::Idle);
91 }
92
93 let bar_width = self.region.width();
94 let bar_height = self.region.height();
95
96 let area = self.region.rectangle();
97
98 let padding = if let Some(padding) = self.padding {
99 padding
100 } else {
101 ui.style().default_padding
102 };
103 let top_left = area.top_left + Point::new(padding.width as i32, padding.height as i32);
104 let indic_width = bar_width - 2 * padding.width;
105 let indic_height = bar_height - 2 * padding.height;
106 let filled_len = indic_width * self.filled_value as u32
107 / (self.filled_value + self.unfilled_value) as u32;
108 let unfilled_len = indic_width - filled_len;
109
110 ui.clear_area(&area)?;
111
112 if filled_len > 0 {
113 let filled_size = Size::new(filled_len, indic_height);
114 let filled_style = PrimitiveStyle::with_fill(self.color_filled.text_color(ui.style()));
115 let filled_area = Rectangle::new(top_left, filled_size).into_styled(filled_style);
116 ui.draw(&filled_area)?;
117 }
118 if unfilled_len > 0 {
119 let unfilled_size = Size::new(unfilled_len, indic_height);
120 let unfilled_style =
121 PrimitiveStyle::with_fill(self.color_unfilled.background_color(ui.style()));
122 let unfilled_area =
123 Rectangle::new(top_left + Point::new(filled_len as i32, 0), unfilled_size)
124 .into_styled(unfilled_style);
125 ui.draw(&unfilled_area)?;
126 }
127 if let Some(border_color) = self.border {
128 let border_style =
129 PrimitiveStyle::with_stroke(border_color, ui.style().border_width as u32);
130 let border_area = Rectangle::new(top_left, Size::new(indic_width, indic_height))
131 .into_styled(border_style);
132 ui.draw(&border_area)?;
133 }
134
135 Ok(Response::Idle)
136 }
137}