blue_pill_more/src/hello_screen.rs

100 lines
2.7 KiB
Rust

use arrayvec::ArrayString;
use embedded_graphics::{
draw_target::DrawTarget,
mono_font::{ascii::FONT_6X9, MonoTextStyle, MonoTextStyleBuilder},
pixelcolor::BinaryColor,
prelude::*,
primitives::{Circle, PrimitiveStyle},
text::{Baseline, Text},
};
use core::fmt::Write;
#[derive(Copy, Clone)]
pub enum HelloEvent {
Tick,
Knob(i32),
Button,
}
#[derive(Clone)]
pub struct HelloDisplay<const W: i32, const H: i32> {
circle_pos: (i32, i32),
counter: i32,
textbuf: ArrayString<15>,
text_style: MonoTextStyle<'static, BinaryColor>,
title: Text<'static, MonoTextStyle<'static, BinaryColor>>,
}
impl<const W: i32, const H: i32> HelloDisplay<W, H> {
const C_RADIUS: i32 = 8;
/// Construct a new HelloDisplay
pub fn new() -> Self {
let text_style = MonoTextStyleBuilder::new()
.font(&FONT_6X9)
.text_color(BinaryColor::On)
.build();
let title =
Text::with_baseline("Hello Rust!", Point::new(20, 16), text_style, Baseline::Top);
Self {
circle_pos: (0, 0),
counter: 0,
textbuf: ArrayString::new(),
text_style,
title,
}
}
/// Draw the current state of HelloDisplay onto the DrawTarget
pub fn draw<D>(&mut self, target: &mut D) -> Result<(), D::Error>
where
D: DrawTarget<Color = BinaryColor>,
{
let (cx, cy) = self.circle_pos;
let circle = Circle::new(Point::new(cx, cy), Self::C_RADIUS as u32)
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On));
self.textbuf.clear();
write!(&mut self.textbuf, "count: {}", self.counter).unwrap();
let count = Text::with_baseline(
&self.textbuf,
Point::new(20, 36),
self.text_style,
Baseline::Top,
);
target.clear(BinaryColor::Off)?;
self.title.draw(target)?;
circle.draw(target)?;
count.draw(target)?;
Ok(())
}
/// Update the current state of HelloDisplay based on an event
pub fn event(&mut self, event: HelloEvent) {
match event {
HelloEvent::Tick => {
let (_, cy) = self.circle_pos;
let cx_next = self
.counter
.max(Self::C_RADIUS / 2)
.min(W - Self::C_RADIUS / 2);
let mut cy_next = cy + 1;
if cy_next > (H + Self::C_RADIUS) {
cy_next = -Self::C_RADIUS
};
self.circle_pos = (cx_next, cy_next);
}
HelloEvent::Knob(pos_delta) => {
self.counter = self.counter + pos_delta;
}
HelloEvent::Button => {}
}
}
}