firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
1use embedded_graphics::geometry::AnchorPoint;
2use embedded_graphics::pixelcolor::BinaryColor;
3use embedded_graphics::prelude::*;
4use embedded_graphics::primitives::{Circle, Line, PrimitiveStyle};
5use eepy_gui::draw_target::EpdDrawTarget;
6use eepy_gui::element::button::Button;
7use eepy_gui::element::Gui;
8use eepy_gui::element::slider::Slider;
9use eepy_sys::input_common::{Event, TouchEventType};
10use crate::ui::MainGui;
11use crate::ui::page::main::MainPage;
12
13pub(crate) struct ScratchpadPage {
14 exit_button: Button<'static>,
15 clear_button: Button<'static>,
16 toggle_button: Button<'static>,
17 slider: Slider,
18 eraser: bool,
19 prev_pos: Option<Point>,
20}
21
22impl ScratchpadPage {
23 pub(crate) fn new() -> Self {
24 let exit_button = Button::with_default_style_auto_sized(Point::new(10, 416 - 10 - 20), "Exit", true);
25
26 let next_pos = exit_button
27 .bounding_box()
28 .translate(Point::new(10, 0))
29 .anchor_point(AnchorPoint::TopRight);
30 let clear_button = Button::with_default_style_auto_sized(next_pos, "Clear", true);
31
32 let next_pos = clear_button
33 .bounding_box()
34 .translate(Point::new(10, 0))
35 .anchor_point(AnchorPoint::TopRight);
36 let toggle_button = Button::with_default_style_auto_sized(next_pos, "Eraser", true);
37
38 let slider = Slider::with_default_style(Point::new(20, 20), 100, 1, 10, 2);
39
40 Self {
41 exit_button,
42 clear_button,
43 toggle_button,
44 slider,
45 eraser: false,
46 prev_pos: None,
47 }
48 }
49}
50
51impl Gui for ScratchpadPage {
52 type Output = Option<MainGui>;
53
54 fn draw_init(&self, draw_target: &mut EpdDrawTarget) {
55 self.exit_button.draw_init(draw_target);
56 self.clear_button.draw_init(draw_target);
57 self.toggle_button.draw_init(draw_target);
58 self.slider.draw_init(draw_target);
59 }
60
61 fn tick(&mut self, draw_target: &mut EpdDrawTarget, ev: Event) -> Self::Output {
62 let mut refresh = false;
63 let mut maybe_refresh = false;
64 let mut handle_drawing: bool = true;
65
66 let e = self.exit_button.tick(draw_target, ev);
67 if e.clicked {
68 return Some(MainGui::MainPage(MainPage::new()));
69 }
70 refresh |= e.needs_refresh;
71
72 let c = self.clear_button.tick(draw_target, ev);
73 if c.clicked {
74 draw_target.clear(BinaryColor::Off).unwrap();
75 self.draw_init(draw_target);
76 draw_target.refresh(false);
77 return None;
78 }
79 refresh |= c.needs_refresh;
80
81 let t = self.toggle_button.tick(draw_target, ev);
82 if t.clicked {
83 self.eraser = !self.eraser;
84 self.toggle_button.label = if self.eraser { "Pen" } else { "Eraser" };
85 }
86 maybe_refresh |= t.clicked;
87 refresh |= t.needs_refresh;
88
89 if self.slider.tick(draw_target, ev) {
90 maybe_refresh = true;
91 handle_drawing = false;
92 }
93
94 if let Event::Touch(ev) = ev {
95 if handle_drawing && matches!(ev.ev_type, TouchEventType::Move | TouchEventType::Up) {
96 if let Some(prev) = self.prev_pos {
97 let style = PrimitiveStyle::with_stroke(BinaryColor::from(!self.eraser), self.slider.value as u32);
98 Line::new(prev, ev.eg_point())
99 .into_styled(style)
100 .draw(draw_target)
101 .unwrap();
102 // Draw a circle at each end of the line
103 let circle_style = PrimitiveStyle::with_fill(BinaryColor::from(!self.eraser));
104 Circle::with_center(prev, self.slider.value as u32 - 1)
105 .into_styled(circle_style)
106 .draw(draw_target)
107 .unwrap();
108 Circle::with_center(ev.eg_point(), self.slider.value as u32 - 1)
109 .into_styled(circle_style)
110 .draw(draw_target)
111 .unwrap();
112
113 self.draw_init(draw_target);
114
115 maybe_refresh = true;
116 }
117 }
118
119 if matches!(ev.ev_type, TouchEventType::Down | TouchEventType::Move) {
120 self.prev_pos = Some(ev.eg_point());
121 }
122 }
123
124 if refresh {
125 draw_target.refresh(true);
126 } else if maybe_refresh {
127 draw_target.maybe_refresh(true);
128 }
129
130 None
131 }
132}