Skip to content

Commit cba87c2

Browse files
committed
ui: add button labels that tell the user which button does what
The legend is drawn at the right of the screen using rotated text. The embedded_graphics library does not have support for rotating elements like text, so we instead provide it with a _view_ of the screen that is rotated and onto which it can render its text as normal. Signed-off-by: Leonard Göhrs <[email protected]>
1 parent fada2f6 commit cba87c2

18 files changed

+175
-19
lines changed

src/ui/display.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ pub struct ScreenShooter {
7373
inner: Arc<Mutex<DisplayExclusive>>,
7474
}
7575

76+
pub struct DisplayRotated<'a> {
77+
inner: &'a mut DisplayExclusive,
78+
}
79+
7680
impl Display {
7781
pub fn new() -> Self {
7882
let mut fb = Framebuffer::new("/dev/fb0").unwrap();
@@ -136,6 +140,20 @@ impl ScreenShooter {
136140
}
137141
}
138142

143+
impl DisplayExclusive {
144+
/// Return an DrawTarget that draws everything rotated by 90deg
145+
///
146+
/// Drawing a pixel to the bottom of DisplayRotated results in the pixel
147+
/// appearing on the right of the actual screen.
148+
pub fn rotate(&mut self) -> DisplayRotated {
149+
// This could easily be made more generic, by accepting a direction
150+
// parameter, but that would result in dead code because we only
151+
// draw the button legend rotated.
152+
153+
DisplayRotated { inner: self }
154+
}
155+
}
156+
139157
impl DrawTarget for DisplayExclusive {
140158
type Color = BinaryColor;
141159
type Error = core::convert::Infallible;
@@ -176,3 +194,30 @@ impl OriginDimensions for DisplayExclusive {
176194
Size::new(self.0.var_screen_info.xres, self.0.var_screen_info.yres)
177195
}
178196
}
197+
198+
impl<'a> DrawTarget for DisplayRotated<'a> {
199+
type Color = BinaryColor;
200+
type Error = core::convert::Infallible;
201+
202+
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
203+
where
204+
I: IntoIterator<Item = Pixel<Self::Color>>,
205+
{
206+
let res = self.size();
207+
let res_y = res.height as i32;
208+
209+
let rotated_pixels = pixels
210+
.into_iter()
211+
.map(|Pixel(coord, color)| Pixel(Point::new(coord.y, res_y - coord.x), color));
212+
213+
self.inner.draw_iter(rotated_pixels)
214+
}
215+
}
216+
217+
impl<'a> OriginDimensions for DisplayRotated<'a> {
218+
fn size(&self) -> Size {
219+
let orig = self.inner.size();
220+
221+
Size::new(orig.height, orig.width)
222+
}
223+
}

src/ui/screens/dig_out.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const SCREEN_TYPE: NormalScreen = NormalScreen::DigOut;
3333
const VOLTAGE_MAX: f32 = 5.0;
3434
const OFFSET_INDICATOR: Point = Point::new(170, -10);
3535
const OFFSET_BAR: Point = Point::new(140, -14);
36-
const WIDTH_BAR: u32 = 72;
36+
const WIDTH_BAR: u32 = 62;
3737
const HEIGHT_BAR: u32 = 18;
3838

3939
pub struct DigOutScreen {
@@ -80,6 +80,7 @@ impl ActivatableScreen for DigOutScreen {
8080

8181
display.with_lock(|target| {
8282
draw_border(target, "Digital Out", SCREEN_TYPE);
83+
draw_button_legend(target, "Action", "Screen");
8384

8485
for (idx, name, _, _) in ports {
8586
let anchor_name = row_anchor(idx * 4);

src/ui/screens/help.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ impl ActivatableScreen for HelpScreen {
9696
}
9797

9898
fn activate(&mut self, ui: &Ui, display: Display) -> Box<dyn ActiveScreen> {
99+
display.with_lock(|target| draw_button_legend(target, "Action", "Leave"));
100+
99101
let mut widgets = WidgetContainer::new(display);
100102

101103
let up = Topic::anonymous(Some(false));

src/ui/screens/iobus.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ impl ActivatableScreen for IoBusScreen {
5656

5757
display.with_lock(|target| {
5858
draw_border(target, "IOBus", SCREEN_TYPE);
59+
draw_button_legend(target, "Toggle", "Screen");
5960

6061
Text::new("CAN Status:", row_anchor(0), ui_text_style)
6162
.draw(target)

src/ui/screens/iobus_health.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ impl ActivatableScreen for IoBusHealthScreen {
7676
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On);
7777

7878
display.with_lock(|target| {
79+
draw_button_legend(target, "Dismiss", "-");
80+
7981
Text::new(
8082
"IOBus supply overload",
8183
row_anchor(0) - (row_anchor(1) - row_anchor(0)),

src/ui/screens/locator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ impl ActivatableScreen for LocatorScreen {
8181
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On);
8282

8383
display.with_lock(|target| {
84+
draw_button_legend(target, "Found it!", "-");
85+
8486
Text::with_alignment(
8587
"Locating this TAC",
8688
Point::new(120, 80),

src/ui/screens/overtemperature.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ impl ActivatableScreen for OverTemperatureScreen {
7575
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On);
7676

7777
display.with_lock(|target| {
78+
// This screen can only be left by resolving the underlying issue
79+
draw_button_legend(target, "-", "-");
80+
7881
Text::new("Temperature alert!", row_anchor(0), ui_text_style)
7982
.draw(target)
8083
.unwrap();

src/ui/screens/power.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const CURRENT_LIMIT: f32 = 5.0;
3333
const VOLTAGE_LIMIT: f32 = 48.0;
3434
const OFFSET_INDICATOR: Point = Point::new(155, -10);
3535
const OFFSET_BAR: Point = Point::new(112, -14);
36-
const WIDTH_BAR: u32 = 100;
36+
const WIDTH_BAR: u32 = 90;
3737
const HEIGHT_BAR: u32 = 18;
3838

3939
pub struct PowerScreen;
@@ -56,7 +56,10 @@ impl ActivatableScreen for PowerScreen {
5656
}
5757

5858
fn activate(&mut self, ui: &Ui, display: Display) -> Box<dyn ActiveScreen> {
59-
display.with_lock(|target| draw_border(target, "DUT Power", SCREEN_TYPE));
59+
display.with_lock(|target| {
60+
draw_border(target, "DUT Power", SCREEN_TYPE);
61+
draw_button_legend(target, "Toggle", "Screen");
62+
});
6063

6164
let mut widgets = WidgetContainer::new(display);
6265

src/ui/screens/power_fail.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ impl ActivatableScreen for PowerFailScreen {
9999
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On);
100100

101101
display.with_lock(|target| {
102+
draw_button_legend(target, "Select", "-");
103+
102104
Text::new(
103105
"DUT Power error",
104106
row_anchor(0) - (row_anchor(1) - row_anchor(0)),
@@ -121,12 +123,16 @@ impl ActivatableScreen for PowerFailScreen {
121123
"The error was resolved"
122124
}
123125
OutputState::InvertedPolarity => {
124-
"Output disabled due to\ninverted polarity."
126+
"Output disabled due\nto inverted polarity."
127+
}
128+
OutputState::OverCurrent => {
129+
"DUT powered off due\nto an overcurrent\nevent."
130+
}
131+
OutputState::OverVoltage => {
132+
"DUT powered off due\nto an overvoltage\nevent."
125133
}
126-
OutputState::OverCurrent => "DUT powered off due to\nan overcurrent event.",
127-
OutputState::OverVoltage => "DUT powered off due to\nan overvoltage event.",
128134
OutputState::RealtimeViolation => {
129-
"Output disabled due to\na realtime violation."
135+
"Output disabled due\n to a realtime\nviolation."
130136
}
131137
OutputState::Changing => "",
132138
};
@@ -145,8 +151,8 @@ impl ActivatableScreen for PowerFailScreen {
145151
row_anchor(6),
146152
Box::new(|highlight: &Highlight| {
147153
let msg = match highlight {
148-
Highlight::TurnOn => "> Turn output back on\n Keep output off",
149-
Highlight::KeepOff => " Turn output back on\n> Keep output off",
154+
Highlight::TurnOn => "> Turn back on\n Keep output off",
155+
Highlight::KeepOff => " Turn back on\n> Keep output off",
150156
};
151157

152158
msg.to_string()

src/ui/screens/reboot.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ fn rly(text: &str, display: &Display) {
7171
let text_style: MonoTextStyle<BinaryColor> = MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On);
7272

7373
display.with_lock(|target| {
74-
Text::with_alignment(text, Point::new(120, 80), text_style, Alignment::Center)
74+
draw_button_legend(target, "Reboot", "Dismiss");
75+
76+
Text::with_alignment(text, Point::new(115, 80), text_style, Alignment::Center)
7577
.draw(target)
7678
.unwrap()
7779
});
@@ -135,7 +137,8 @@ impl ActiveScreen for Active {
135137

136138
fn input(&mut self, ev: InputEvent) {
137139
match ev {
138-
InputEvent::NextScreen | InputEvent::ToggleAction(_) => self.reboot_message.set(None),
140+
InputEvent::NextScreen => self.reboot_message.set(None),
141+
InputEvent::ToggleAction(_) => {}
139142
InputEvent::PerformAction(_) => {
140143
brb(&self.display);
141144
self.reboot.set(true);

0 commit comments

Comments
 (0)