firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

fw16-epd-gui: add button element

+141 -14
+88
fw16-epd-gui/src/element/button.rs
··· 1 + use core::fmt::Binary; 2 + use embedded_graphics::prelude::*; 3 + use embedded_graphics::mono_font::MonoTextStyle; 4 + use embedded_graphics::pixelcolor::BinaryColor; 5 + use embedded_graphics::primitives::{PrimitiveStyle, Rectangle, RoundedRectangle}; 6 + use embedded_graphics::text::{Alignment, Baseline, Text, TextStyle, TextStyleBuilder}; 7 + use fw16_epd_program_interface::{TouchEvent, TouchEventType}; 8 + use crate::draw_target::EpdDrawTarget; 9 + use crate::element::GuiElement; 10 + 11 + const CENTRE_STYLE: TextStyle = TextStyleBuilder::new() 12 + .alignment(Alignment::Center) 13 + .baseline(Baseline::Middle) 14 + .build(); 15 + 16 + #[derive(Copy, Clone, Debug, Eq, PartialEq, defmt::Format)] 17 + enum ClickState { 18 + /// The button has not been clicked 19 + None, 20 + /// The button has been pressed, but not released 21 + Pressed, 22 + /// The button has been fully clicked and released 23 + Clicked, 24 + } 25 + 26 + #[derive(Debug, defmt::Format)] 27 + pub struct Button<'a> { 28 + rect: RoundedRectangle, 29 + label: &'a str, 30 + rect_style: PrimitiveStyle<BinaryColor>, 31 + char_style: MonoTextStyle<'a, BinaryColor>, 32 + click_state: ClickState, 33 + } 34 + 35 + impl<'a> Button<'a> { 36 + pub fn new(rect: RoundedRectangle, label: &'a str, rect_style: PrimitiveStyle<BinaryColor>, char_style: MonoTextStyle<'a, BinaryColor>) -> Self { 37 + Self { 38 + rect, 39 + label, 40 + rect_style, 41 + char_style, 42 + click_state: ClickState::None, 43 + } 44 + } 45 + 46 + pub fn clicked(&mut self, clear: bool) -> bool { 47 + if self.click_state == ClickState::Clicked { 48 + if clear { 49 + self.click_state = ClickState::None; 50 + } 51 + 52 + true 53 + } else { 54 + false 55 + } 56 + } 57 + } 58 + 59 + impl<'a> GuiElement for Button<'a> { 60 + fn draw_element(&self, target: &mut EpdDrawTarget) { 61 + self.rect 62 + .into_styled(self.rect_style) 63 + .draw(target) 64 + .unwrap(); 65 + 66 + Text::with_text_style( 67 + self.label, 68 + self.rect.bounding_box().center(), 69 + self.char_style, 70 + CENTRE_STYLE 71 + ) 72 + .draw(target) 73 + .unwrap(); 74 + } 75 + 76 + fn handle_touch(&mut self, ev: TouchEvent) { 77 + if self.rect.contains(ev.eg_point()) { 78 + match (self.click_state, ev.ev_type) { 79 + (ClickState::None, TouchEventType::Down) => self.click_state = ClickState::Pressed, 80 + (ClickState::Pressed, TouchEventType::Up) => self.click_state = ClickState::Clicked, 81 + _ => {}, 82 + } 83 + } else if self.click_state == ClickState::Pressed { 84 + // user dragged their finger out of the button bounding box 85 + self.click_state = ClickState::None; 86 + } 87 + } 88 + }
+22
fw16-epd-gui/src/element/mod.rs
··· 1 + pub mod button; 2 + 3 + use embedded_graphics::pixelcolor::BinaryColor; 4 + use embedded_graphics::prelude::*; 5 + use fw16_epd_program_interface::TouchEvent; 6 + use crate::draw_target::EpdDrawTarget; 7 + 8 + pub trait GuiElement { 9 + fn draw_element(&self, target: &mut EpdDrawTarget); 10 + 11 + fn handle_touch(&mut self, ev: TouchEvent); 12 + } 13 + 14 + impl<T: Drawable<Color = BinaryColor>> GuiElement for T { 15 + fn draw_element(&self, target: &mut EpdDrawTarget) { 16 + self.draw(target).unwrap(); 17 + } 18 + 19 + fn handle_touch(&mut self, _ev: TouchEvent) { 20 + // no-op 21 + } 22 + }
+24 -13
fw16-epd-main/src/gui.rs
··· 1 1 use core::fmt::Write; 2 - use defmt::debug; 3 2 use embedded_graphics::mono_font::ascii::FONT_10X20; 4 3 use embedded_graphics::mono_font::MonoTextStyle; 5 4 use embedded_graphics::pixelcolor::BinaryColor; 6 5 use embedded_graphics::prelude::*; 6 + use embedded_graphics::primitives::{PrimitiveStyle, Rectangle, RoundedRectangle}; 7 7 use embedded_graphics::text::Text; 8 8 use heapless::String; 9 9 use fw16_epd_gui::draw_target::EpdDrawTarget; 10 - use fw16_epd_program_interface::TouchEvent; 10 + use fw16_epd_gui::element::button::Button; 11 + use fw16_epd_gui::element::GuiElement; 11 12 use crate::{next_touch_event, set_touch_enabled}; 12 13 13 14 pub(crate) fn gui_main(mut draw_target: EpdDrawTarget) -> ! { ··· 15 16 16 17 unsafe { set_touch_enabled(true) }; 17 18 19 + let mut button = Button::new( 20 + RoundedRectangle::with_equal_corners(Rectangle::new(Point::new(10, 40), Size::new(100, 20)), Size::new(3, 3)), 21 + "Click me", 22 + PrimitiveStyle::with_stroke(BinaryColor::On, 2), 23 + MonoTextStyle::new(&FONT_10X20, BinaryColor::On) 24 + ); 25 + button.draw_element(&mut draw_target); 26 + draw_target.refresh(true, false); 27 + 28 + let mut counter = 0; 29 + 18 30 loop { 19 - let mut touch_event: Option<TouchEvent> = None; 20 31 while let Some(ev) = next_touch_event().into() { 21 - debug!("{}", ev); 22 - touch_event = Some(ev); 32 + button.handle_touch(ev); 23 33 } 24 34 25 - if let Some(ev) = touch_event { 26 - draw_target.clear(BinaryColor::Off).unwrap(); 35 + if button.clicked(true) { 36 + counter += 1; 27 37 28 - let mut s = String::<32>::new(); 29 - write!(s, "{ev}").unwrap(); 38 + let mut s = String::<10>::new(); 39 + write!(s, "{counter}").unwrap(); 30 40 31 - Text::new(s.as_str(), Point::new(10, 40), MonoTextStyle::new(&FONT_10X20, BinaryColor::On)) 32 - .draw(&mut draw_target) 33 - .unwrap(); 34 - debug!("triggering refresh"); 41 + draw_target.clear(BinaryColor::Off).unwrap(); 42 + button.draw_element(&mut draw_target); 43 + 44 + Text::new(&s, Point::new(10, 80), MonoTextStyle::new(&FONT_10X20, BinaryColor::On)) 45 + .draw_element(&mut draw_target); 35 46 draw_target.refresh(true, false); 36 47 } 37 48 }
+2 -1
fw16-epd-program-interface/Cargo.toml
··· 5 5 6 6 [dependencies] 7 7 tp370pgh01 = { path = "../tp370pgh01" } 8 - defmt.workspace = true 8 + defmt.workspace = true 9 + embedded-graphics = { workspace = true, optional = true }
+5
fw16-epd-program-interface/src/lib.rs
··· 61 61 y: u16::MAX, 62 62 } 63 63 } 64 + 65 + #[cfg(feature = "embedded-graphics")] 66 + pub fn eg_point(&self) -> embedded_graphics::prelude::Point { 67 + embedded_graphics::prelude::Point::new(self.x as i32, self.y as i32) 68 + } 64 69 } 65 70 66 71 impl Display for TouchEvent {