Skip to content

Commit 998b73c

Browse files
authored
Merge pull request #56 from hnez/button-labels
ui: add button labels that tell the user which button does what
2 parents 3629d76 + db008f8 commit 998b73c

19 files changed

+254
-53
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.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -134,31 +134,29 @@ pub(super) trait ActivatableScreen: Sync + Send {
134134

135135
/// Draw static screen border containing a title and an indicator for the
136136
/// position of the screen in the list of screens.
137-
fn draw_border(text: &str, screen: NormalScreen, display: &Display) {
138-
display.with_lock(|target| {
139-
Text::new(
140-
text,
141-
Point::new(8, 17),
142-
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On),
143-
)
137+
fn draw_border(target: &mut DisplayExclusive, text: &str, screen: NormalScreen) {
138+
Text::new(
139+
text,
140+
Point::new(8, 17),
141+
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On),
142+
)
143+
.draw(target)
144+
.unwrap();
145+
146+
Line::new(Point::new(0, 23), Point::new(240, 23))
147+
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 2))
144148
.draw(target)
145149
.unwrap();
146150

147-
Line::new(Point::new(0, 24), Point::new(240, 24))
148-
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 2))
149-
.draw(target)
150-
.unwrap();
151-
152-
let screen_idx = screen as i32;
153-
let num_screens = (NormalScreen::Uart as i32) + 1;
154-
let x_start = screen_idx * 240 / num_screens;
155-
let x_end = (screen_idx + 1) * 240 / num_screens;
156-
157-
Line::new(Point::new(x_start, 240), Point::new(x_end, 240))
158-
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 4))
159-
.draw(target)
160-
.unwrap();
161-
});
151+
let screen_idx = screen as i32;
152+
let num_screens = (NormalScreen::Uart as i32) + 1;
153+
let x_start = screen_idx * 240 / num_screens;
154+
let x_end = (screen_idx + 1) * 240 / num_screens;
155+
156+
Line::new(Point::new(x_start, 240), Point::new(x_end, 240))
157+
.into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 4))
158+
.draw(target)
159+
.unwrap();
162160
}
163161

164162
const fn row_anchor(row_num: u8) -> Point {

src/ui/screens/dig_out.rs

Lines changed: 4 additions & 3 deletions
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 {
@@ -60,8 +60,6 @@ impl ActivatableScreen for DigOutScreen {
6060
}
6161

6262
fn activate(&mut self, ui: &Ui, display: Display) -> Box<dyn ActiveScreen> {
63-
draw_border("Digital Out", SCREEN_TYPE, &display);
64-
6563
let ports = [
6664
(
6765
0,
@@ -81,6 +79,9 @@ impl ActivatableScreen for DigOutScreen {
8179
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On);
8280

8381
display.with_lock(|target| {
82+
draw_border(target, "Digital Out", SCREEN_TYPE);
83+
draw_button_legend(target, "Action", "Screen");
84+
8485
for (idx, name, _, _) in ports {
8586
let anchor_name = row_anchor(idx * 4);
8687

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: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ impl ActivatableScreen for IoBusScreen {
5151
}
5252

5353
fn activate(&mut self, ui: &Ui, display: Display) -> Box<dyn ActiveScreen> {
54-
draw_border("IOBus", SCREEN_TYPE, &display);
55-
5654
let ui_text_style: MonoTextStyle<BinaryColor> =
5755
MonoTextStyle::new(&UI_TEXT_FONT, BinaryColor::On);
5856

5957
display.with_lock(|target| {
58+
draw_border(target, "IOBus", SCREEN_TYPE);
59+
6060
Text::new("CAN Status:", row_anchor(0), ui_text_style)
6161
.draw(target)
6262
.unwrap();
@@ -133,6 +133,21 @@ impl ActivatableScreen for IoBusScreen {
133133
)
134134
});
135135

136+
widgets.push(|display| {
137+
DynamicWidget::button_legend(
138+
ui.res.regulators.iobus_pwr_en.clone(),
139+
display,
140+
|state: &bool| {
141+
let lower = match *state {
142+
false => "Turn On",
143+
true => "Turn Off",
144+
};
145+
146+
(lower.into(), "Screen".into())
147+
},
148+
)
149+
});
150+
136151
let iobus_pwr_en = ui.res.regulators.iobus_pwr_en.clone();
137152

138153
let active = Active {

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: 17 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,7 @@ impl ActivatableScreen for PowerScreen {
5656
}
5757

5858
fn activate(&mut self, ui: &Ui, display: Display) -> Box<dyn ActiveScreen> {
59-
draw_border("DUT Power", SCREEN_TYPE, &display);
59+
display.with_lock(|target| draw_border(target, "DUT Power", SCREEN_TYPE));
6060

6161
let mut widgets = WidgetContainer::new(display);
6262

@@ -132,6 +132,21 @@ impl ActivatableScreen for PowerScreen {
132132
)
133133
});
134134

135+
widgets.push(|display| {
136+
DynamicWidget::button_legend(
137+
ui.res.dut_pwr.state.clone(),
138+
display,
139+
|state: &OutputState| {
140+
let lower = match state {
141+
OutputState::On => "Turn Off",
142+
_ => "Turn On",
143+
};
144+
145+
(lower.into(), "Screen".into())
146+
},
147+
)
148+
});
149+
135150
let power_state = ui.res.dut_pwr.state.clone();
136151
let power_request = ui.res.dut_pwr.request.clone();
137152

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()

0 commit comments

Comments
 (0)