161 lines
3.9 KiB
Rust
161 lines
3.9 KiB
Rust
use crate::ComponentStyle;
|
|
use embedded_graphics::{
|
|
mono_font::{
|
|
ascii::{FONT_10X20, FONT_7X14},
|
|
MonoTextStyle,
|
|
},
|
|
pixelcolor::{BinaryColor, PixelColor},
|
|
prelude::*,
|
|
primitives::{Line, PrimitiveStyle, Rectangle},
|
|
text::{Baseline, Text},
|
|
};
|
|
use embedded_layout::prelude::*;
|
|
|
|
pub struct ListItemData {
|
|
pub text: String,
|
|
pub icon: String,
|
|
pub progress: f32,
|
|
}
|
|
|
|
impl<'a> ListItemData {
|
|
pub fn new(icon: &'a str, text: &'a str) -> Self {
|
|
Self {
|
|
icon: String::from(icon),
|
|
text: String::from(text),
|
|
progress: 0f32,
|
|
}
|
|
}
|
|
|
|
pub fn with_progress(self, progress: f32) -> Self {
|
|
Self { progress, ..self }
|
|
}
|
|
}
|
|
|
|
pub struct List<C> {
|
|
pub style: ComponentStyle<C>,
|
|
pub top_left: Point,
|
|
pub size: Size,
|
|
pub items_shown: usize,
|
|
pub list_items: Vec<ListItemData>,
|
|
}
|
|
|
|
impl<C> Drawable for List<C>
|
|
where
|
|
C: PixelColor + From<BinaryColor>,
|
|
{
|
|
type Color = C;
|
|
type Output = ();
|
|
|
|
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
|
where
|
|
D: DrawTarget<Color = C>,
|
|
{
|
|
let rect = Rectangle::new(self.top_left, self.size);
|
|
rect
|
|
.into_styled(PrimitiveStyle::with_stroke(
|
|
self.style.bg_color,
|
|
self.style.border,
|
|
))
|
|
.draw(target)?;
|
|
rect
|
|
.into_styled(PrimitiveStyle::with_fill(self.style.bg_color))
|
|
.draw(target)?;
|
|
|
|
let height = self.size.height / self.items_shown as u32;
|
|
|
|
for (i, item) in self.list_items.iter().enumerate().take(self.items_shown) {
|
|
let list_item = ListItem {
|
|
style: self.style.clone(),
|
|
top_left: self.top_left + Point::new(0, (height as usize * i) as i32),
|
|
size: Size::new(self.size.width, height),
|
|
text: &item.text,
|
|
icon: &item.icon,
|
|
progress: item.progress,
|
|
};
|
|
list_item.draw(target)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub struct ListItem<'a, C> {
|
|
pub style: ComponentStyle<C>,
|
|
pub top_left: Point,
|
|
pub size: Size,
|
|
pub text: &'a str,
|
|
pub icon: &'a str,
|
|
pub progress: f32,
|
|
}
|
|
|
|
impl<C> Drawable for ListItem<'_, C>
|
|
where
|
|
C: PixelColor + From<BinaryColor>,
|
|
{
|
|
type Color = C;
|
|
type Output = ();
|
|
|
|
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
|
where
|
|
D: DrawTarget<Color = C>,
|
|
{
|
|
let rect = Rectangle::new(
|
|
self.top_left,
|
|
self.size + Size::new(self.style.border / 2 + 1, self.style.border / 2 + 1),
|
|
);
|
|
rect
|
|
.into_styled(PrimitiveStyle::with_fill(self.style.bg_color))
|
|
.draw(target)?;
|
|
rect
|
|
.into_styled(PrimitiveStyle::with_stroke(
|
|
self.style.border_color,
|
|
self.style.border,
|
|
))
|
|
.draw(target)?;
|
|
|
|
let icon_square = Rectangle::new(self.top_left, Size::new(rect.size.height, rect.size.height));
|
|
icon_square
|
|
.into_styled(PrimitiveStyle::with_stroke(
|
|
self.style.border_color,
|
|
self.style.border,
|
|
))
|
|
.draw(target)?;
|
|
|
|
let icon_style = MonoTextStyle::new(&FONT_10X20, self.style.hi_color);
|
|
|
|
let mut icon = Text::with_baseline(self.icon, self.top_left, icon_style, Baseline::Middle);
|
|
let icon_box = icon.bounding_box();
|
|
icon.position = self.top_left
|
|
+ Point::new(
|
|
(self.size.height / 2 - icon_box.size.width / 2) as i32,
|
|
(self.size.height / 2) as i32,
|
|
);
|
|
|
|
icon.draw(&mut target.clipped(&rect))?;
|
|
|
|
let text_style = MonoTextStyle::new(&FONT_7X14, self.style.fg_color);
|
|
|
|
let mut text = Text::with_baseline(self.text, self.top_left, text_style, Baseline::Middle);
|
|
let text_box = text.bounding_box();
|
|
text.position = self.top_left
|
|
+ Point::new(
|
|
(self.size.height as f32 * 1.2) as i32,
|
|
self.size.height as i32 / 2,
|
|
);
|
|
|
|
text.draw(&mut target.clipped(&rect))?;
|
|
|
|
if self.progress >= 100f32 {
|
|
let strikethrough = Line::new(
|
|
text.position + Point::new(0, 1),
|
|
text.position + Point::new(text_box.size.width as i32, 1),
|
|
);
|
|
strikethrough
|
|
.into_styled(PrimitiveStyle::with_stroke(self.style.fg_color, 2))
|
|
.draw(target)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|