alpha
Login
or
Join now
arthomnix.dev
/
eepy
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
Star
0
Fork
0
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
Pulls
Pipelines
fw16-epd-gui: add button element
author
arthomnix
date
1 year ago
(Jan 11, 2025, 6:17 PM UTC)
commit
5ffed47f
5ffed47f6e63b052e90c2b5e2515da70ff9483f0
parent
001ba5a6
001ba5a6b839ae09f91080e42605ea11ccdc1068
+141
-14
5 changed files
Expand all
Collapse all
Unified
Split
fw16-epd-gui
src
element
button.rs
mod.rs
fw16-epd-main
src
gui.rs
fw16-epd-program-interface
Cargo.toml
src
lib.rs
+88
fw16-epd-gui/src/element/button.rs
Reviewed
···
1
1
+
use core::fmt::Binary;
2
2
+
use embedded_graphics::prelude::*;
3
3
+
use embedded_graphics::mono_font::MonoTextStyle;
4
4
+
use embedded_graphics::pixelcolor::BinaryColor;
5
5
+
use embedded_graphics::primitives::{PrimitiveStyle, Rectangle, RoundedRectangle};
6
6
+
use embedded_graphics::text::{Alignment, Baseline, Text, TextStyle, TextStyleBuilder};
7
7
+
use fw16_epd_program_interface::{TouchEvent, TouchEventType};
8
8
+
use crate::draw_target::EpdDrawTarget;
9
9
+
use crate::element::GuiElement;
10
10
+
11
11
+
const CENTRE_STYLE: TextStyle = TextStyleBuilder::new()
12
12
+
.alignment(Alignment::Center)
13
13
+
.baseline(Baseline::Middle)
14
14
+
.build();
15
15
+
16
16
+
#[derive(Copy, Clone, Debug, Eq, PartialEq, defmt::Format)]
17
17
+
enum ClickState {
18
18
+
/// The button has not been clicked
19
19
+
None,
20
20
+
/// The button has been pressed, but not released
21
21
+
Pressed,
22
22
+
/// The button has been fully clicked and released
23
23
+
Clicked,
24
24
+
}
25
25
+
26
26
+
#[derive(Debug, defmt::Format)]
27
27
+
pub struct Button<'a> {
28
28
+
rect: RoundedRectangle,
29
29
+
label: &'a str,
30
30
+
rect_style: PrimitiveStyle<BinaryColor>,
31
31
+
char_style: MonoTextStyle<'a, BinaryColor>,
32
32
+
click_state: ClickState,
33
33
+
}
34
34
+
35
35
+
impl<'a> Button<'a> {
36
36
+
pub fn new(rect: RoundedRectangle, label: &'a str, rect_style: PrimitiveStyle<BinaryColor>, char_style: MonoTextStyle<'a, BinaryColor>) -> Self {
37
37
+
Self {
38
38
+
rect,
39
39
+
label,
40
40
+
rect_style,
41
41
+
char_style,
42
42
+
click_state: ClickState::None,
43
43
+
}
44
44
+
}
45
45
+
46
46
+
pub fn clicked(&mut self, clear: bool) -> bool {
47
47
+
if self.click_state == ClickState::Clicked {
48
48
+
if clear {
49
49
+
self.click_state = ClickState::None;
50
50
+
}
51
51
+
52
52
+
true
53
53
+
} else {
54
54
+
false
55
55
+
}
56
56
+
}
57
57
+
}
58
58
+
59
59
+
impl<'a> GuiElement for Button<'a> {
60
60
+
fn draw_element(&self, target: &mut EpdDrawTarget) {
61
61
+
self.rect
62
62
+
.into_styled(self.rect_style)
63
63
+
.draw(target)
64
64
+
.unwrap();
65
65
+
66
66
+
Text::with_text_style(
67
67
+
self.label,
68
68
+
self.rect.bounding_box().center(),
69
69
+
self.char_style,
70
70
+
CENTRE_STYLE
71
71
+
)
72
72
+
.draw(target)
73
73
+
.unwrap();
74
74
+
}
75
75
+
76
76
+
fn handle_touch(&mut self, ev: TouchEvent) {
77
77
+
if self.rect.contains(ev.eg_point()) {
78
78
+
match (self.click_state, ev.ev_type) {
79
79
+
(ClickState::None, TouchEventType::Down) => self.click_state = ClickState::Pressed,
80
80
+
(ClickState::Pressed, TouchEventType::Up) => self.click_state = ClickState::Clicked,
81
81
+
_ => {},
82
82
+
}
83
83
+
} else if self.click_state == ClickState::Pressed {
84
84
+
// user dragged their finger out of the button bounding box
85
85
+
self.click_state = ClickState::None;
86
86
+
}
87
87
+
}
88
88
+
}
+22
fw16-epd-gui/src/element/mod.rs
Reviewed
···
1
1
+
pub mod button;
2
2
+
3
3
+
use embedded_graphics::pixelcolor::BinaryColor;
4
4
+
use embedded_graphics::prelude::*;
5
5
+
use fw16_epd_program_interface::TouchEvent;
6
6
+
use crate::draw_target::EpdDrawTarget;
7
7
+
8
8
+
pub trait GuiElement {
9
9
+
fn draw_element(&self, target: &mut EpdDrawTarget);
10
10
+
11
11
+
fn handle_touch(&mut self, ev: TouchEvent);
12
12
+
}
13
13
+
14
14
+
impl<T: Drawable<Color = BinaryColor>> GuiElement for T {
15
15
+
fn draw_element(&self, target: &mut EpdDrawTarget) {
16
16
+
self.draw(target).unwrap();
17
17
+
}
18
18
+
19
19
+
fn handle_touch(&mut self, _ev: TouchEvent) {
20
20
+
// no-op
21
21
+
}
22
22
+
}
+24
-13
fw16-epd-main/src/gui.rs
Reviewed
···
1
1
use core::fmt::Write;
2
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
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
10
-
use fw16_epd_program_interface::TouchEvent;
10
10
+
use fw16_epd_gui::element::button::Button;
11
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
19
+
let mut button = Button::new(
20
20
+
RoundedRectangle::with_equal_corners(Rectangle::new(Point::new(10, 40), Size::new(100, 20)), Size::new(3, 3)),
21
21
+
"Click me",
22
22
+
PrimitiveStyle::with_stroke(BinaryColor::On, 2),
23
23
+
MonoTextStyle::new(&FONT_10X20, BinaryColor::On)
24
24
+
);
25
25
+
button.draw_element(&mut draw_target);
26
26
+
draw_target.refresh(true, false);
27
27
+
28
28
+
let mut counter = 0;
29
29
+
18
30
loop {
19
19
-
let mut touch_event: Option<TouchEvent> = None;
20
31
while let Some(ev) = next_touch_event().into() {
21
21
-
debug!("{}", ev);
22
22
-
touch_event = Some(ev);
32
32
+
button.handle_touch(ev);
23
33
}
24
34
25
25
-
if let Some(ev) = touch_event {
26
26
-
draw_target.clear(BinaryColor::Off).unwrap();
35
35
+
if button.clicked(true) {
36
36
+
counter += 1;
27
37
28
28
-
let mut s = String::<32>::new();
29
29
-
write!(s, "{ev}").unwrap();
38
38
+
let mut s = String::<10>::new();
39
39
+
write!(s, "{counter}").unwrap();
30
40
31
31
-
Text::new(s.as_str(), Point::new(10, 40), MonoTextStyle::new(&FONT_10X20, BinaryColor::On))
32
32
-
.draw(&mut draw_target)
33
33
-
.unwrap();
34
34
-
debug!("triggering refresh");
41
41
+
draw_target.clear(BinaryColor::Off).unwrap();
42
42
+
button.draw_element(&mut draw_target);
43
43
+
44
44
+
Text::new(&s, Point::new(10, 80), MonoTextStyle::new(&FONT_10X20, BinaryColor::On))
45
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
Reviewed
···
5
5
6
6
[dependencies]
7
7
tp370pgh01 = { path = "../tp370pgh01" }
8
8
-
defmt.workspace = true
8
8
+
defmt.workspace = true
9
9
+
embedded-graphics = { workspace = true, optional = true }
+5
fw16-epd-program-interface/src/lib.rs
Reviewed
···
61
61
y: u16::MAX,
62
62
}
63
63
}
64
64
+
65
65
+
#[cfg(feature = "embedded-graphics")]
66
66
+
pub fn eg_point(&self) -> embedded_graphics::prelude::Point {
67
67
+
embedded_graphics::prelude::Point::new(self.x as i32, self.y as i32)
68
68
+
}
64
69
}
65
70
66
71
impl Display for TouchEvent {