kdash/kdash_client/src/fb/widgets/status_box.rs
2024-11-15 23:02:35 +01:00

154 lines
4.4 KiB
Rust

use embedded_graphics::{
mono_font::{
ascii::{FONT_10X20, FONT_6X12},
MonoFont, MonoTextStyle,
},
pixelcolor::Gray8,
prelude::*,
primitives::{CornerRadiiBuilder, PrimitiveStyleBuilder, Rectangle, RoundedRectangle},
text::Text,
};
use embedded_layout::prelude::*;
pub const DEFAULT_PADDING: Size = Size::new(20, 20);
pub struct StatusBox<'a> {
pub text: &'a str,
pub font: &'a MonoFont<'a>,
pub bounds: Rectangle,
pub bar_bounds: Rectangle,
pub bar_text_bounds: Rectangle,
pub bar_font: &'a MonoFont<'a>,
pub bar_text: &'a str,
pub inside_bounds: Rectangle,
}
impl<'a> StatusBox<'a> {
pub fn new(
top_left: Point,
padding: Size,
border_stroke_width: u32,
bar_font: &'a MonoFont,
bar_text: &'a str,
font: &'a MonoFont,
text: &'a str,
) -> Self {
let text_width = (text.len() as u32) * (font.character_size.width + font.character_spacing);
let text_height = font.character_size.width;
let bar_height = bar_font.character_size.height + (2 * border_stroke_width);
let bounds = Rectangle::new(
top_left,
Size::new(
text_width + (2 * padding.width),
text_height + (2 * padding.height) + bar_height,
),
);
Self {
text,
font,
bounds,
bar_bounds: Rectangle::new(bounds.top_left, Size::new(bounds.size.width, bar_height)),
bar_text_bounds: Rectangle::new(
Point::new(
bounds.top_left.x + (border_stroke_width as i32),
bounds.top_left.y + (border_stroke_width as i32),
),
Size::new(
bounds.size.width - (2 * border_stroke_width),
bar_height - (2 * border_stroke_width),
),
),
bar_font,
bar_text,
inside_bounds: Rectangle::new(
Point::new(top_left.x, top_left.y + (bar_height as i32)),
Size::new(
text_width + (2 * padding.width),
text_height + (2 * padding.height),
),
),
}
}
pub fn new_with_default_style(top_left: Point, bar_text: &'a str, text: &'a str) -> Self {
Self::new(
top_left,
Size::new(30, 30),
5,
&FONT_6X12,
bar_text,
&FONT_10X20,
text,
)
}
}
impl View for StatusBox<'_> {
fn translate_impl(&mut self, by: Point) {
Transform::translate_mut(&mut self.bounds, by);
Transform::translate_mut(&mut self.bar_bounds, by);
Transform::translate_mut(&mut self.bar_text_bounds, by);
Transform::translate_mut(&mut self.inside_bounds, by);
}
fn bounds(&self) -> Rectangle {
self.bounds
}
}
impl Drawable for StatusBox<'_> {
type Color = Gray8;
type Output = ();
fn draw<D>(&self, target: &mut D) -> std::result::Result<Self::Output, D::Error>
where
D: DrawTarget<Color = Self::Color>,
{
let corner_radius = Size::new(10, 10);
let rect_style = PrimitiveStyleBuilder::new()
.stroke_width(5)
.stroke_color(Gray8::BLACK)
.fill_color(Gray8::WHITE)
.build();
let rect = RoundedRectangle::with_equal_corners(self.bounds, corner_radius)
.into_styled(rect_style);
let bar_style = PrimitiveStyleBuilder::new()
.fill_color(Gray8::BLACK)
.build();
let bar_radii = CornerRadiiBuilder::new()
.top_left(corner_radius)
.top_right(corner_radius)
.bottom(Size::zero())
.build();
let bar = RoundedRectangle::new(self.bar_bounds, bar_radii).into_styled(bar_style);
let bar_text = Text::new(
self.bar_text,
Point::zero(),
MonoTextStyle::new(self.bar_font, Gray8::WHITE),
)
.align_to(&self.bar_text_bounds, horizontal::Right, vertical::Center);
let text = Text::new(
self.text,
Point::zero(),
MonoTextStyle::new(self.font, Gray8::BLACK),
)
.align_to(&self.inside_bounds, horizontal::Center, vertical::Center);
rect.draw(target)?;
bar.draw(target)?;
bar_text.draw(target)?;
text.draw(target)?;
Ok(())
}
}