refactor(core/bootloader): simplify Confirm arguments

pull/2879/head
matejcik 1 year ago
parent a9a18bf80d
commit d1d373a51f

@ -1,7 +1,7 @@
use crate::ui::{
component::{Component, Event, EventCtx, Never},
display::Font,
geometry::{Alignment, Insets, Offset, Rect},
geometry::{Alignment, Insets, Offset, Point, Rect},
};
use super::{text::TextStyle, TextLayout};
@ -61,6 +61,14 @@ where
let font = self.font();
Offset::new(font.text_width(self.text.as_ref()), font.text_max_height())
}
pub fn text_height(&self, width: i16) -> i16 {
let bounds = Rect::from_top_left_and_size(Point::zero(), Offset::new(width, i16::MAX));
self.layout
.with_bounds(bounds)
.fit_text(self.text.as_ref())
.height()
}
}
impl<T> Component for Label<T>
@ -70,11 +78,7 @@ where
type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect {
let height = self
.layout
.with_bounds(bounds)
.fit_text(self.text.as_ref())
.height();
let height = self.text_height(bounds.width());
let diff = bounds.height() - height;
let insets = match self.vertical {
Alignment::Start => Insets::bottom(diff),

@ -16,8 +16,12 @@ use crate::ui::{
};
const ICON_TOP: i16 = 17;
const CONTENT_START_WITH_ICON: i16 = 40 + CONTENT_PADDING;
const CONTENT_START: i16 = 58;
const CONTENT_START: i16 = 72;
const CONTENT_AREA: Rect = Rect::new(
Point::new(CONTENT_PADDING, CONTENT_START),
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING),
);
#[derive(Copy, Clone, ToPrimitive)]
pub enum ConfirmMsg {
@ -25,6 +29,11 @@ pub enum ConfirmMsg {
Confirm = 2,
}
pub enum ConfirmTitle<'a> {
Text(Label<&'a str>),
Icon(Icon),
}
pub struct ConfirmInfo<'a> {
pub title: Child<Label<&'a str>>,
pub text: Child<Label<&'a str>>,
@ -36,8 +45,7 @@ pub struct Confirm<'a> {
bg: Pad,
content_pad: Pad,
bg_color: Color,
icon: Option<Icon>,
title: Option<Child<Label<&'a str>>>,
title: ConfirmTitle<'a>,
message: Child<Label<&'a str>>,
alert: Option<Child<Label<&'a str>>>,
left_button: Child<Button<&'static str>>,
@ -47,25 +55,22 @@ pub struct Confirm<'a> {
}
impl<'a> Confirm<'a> {
#[allow(clippy::too_many_arguments)]
pub fn new(
bg_color: Color,
icon: Option<Icon>,
left_button: Button<&'static str>,
right_button: Button<&'static str>,
title: Option<Label<&'a str>>,
msg: Label<&'a str>,
title: ConfirmTitle<'a>,
message: Label<&'a str>,
alert: Option<Label<&'a str>>,
info: Option<(&'a str, &'a str)>,
) -> Self {
let mut instance = Self {
bg: Pad::with_background(bg_color),
Self {
bg: Pad::with_background(bg_color).with_clear(),
content_pad: Pad::with_background(bg_color),
bg_color,
icon,
title: title.map(|title| Child::new(title.vertically_aligned(Alignment::Center))),
message: Child::new(msg),
alert: alert.map(Child::new),
title,
message: Child::new(message.vertically_aligned(Alignment::Center)),
alert: alert.map(|alert| Child::new(alert.vertically_aligned(Alignment::Center))),
left_button: Child::new(left_button),
right_button: Child::new(right_button),
info: info.map(|(title, text)| ConfirmInfo {
@ -89,9 +94,7 @@ impl<'a> Confirm<'a> {
),
}),
show_info: false,
};
instance.bg.clear();
instance
}
}
}
@ -105,45 +108,31 @@ impl<'a> Component for Confirm<'a> {
Point::new(WIDTH, BUTTON_AREA_START),
));
let content_area_start = if self.icon.is_some() {
CONTENT_START_WITH_ICON
} else {
CONTENT_START
};
let content_area = Rect::new(
Point::new(CONTENT_PADDING, content_area_start),
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING),
);
let mut content_area = CONTENT_AREA;
self.message.place(content_area);
let message_height = self.message.inner().area().height();
match &mut self.title {
ConfirmTitle::Icon(_) => {
// XXX HACK: when icon is present (wipe device screen), we know the
// string is long and we need to go outside the content padding
content_area = content_area.inset(Insets::sides(-CONTENT_PADDING));
}
ConfirmTitle::Text(title) => {
title.place(TITLE_AREA);
}
};
if let Some(alert) = &mut self.alert {
alert.place(content_area);
let alert_height = alert.inner().area().height();
if self.alert.is_some() {
let message_height = self.message.inner().text_height(content_area.width());
self.message.place(Rect::from_top_left_and_size(
content_area.top_left(),
Offset::new(content_area.width(), message_height),
));
let space_height = (content_area.height() - message_height - alert_height) / 3;
let (_, alert_bounds) = content_area.split_top(message_height);
self.message.place(Rect::new(
Point::new(CONTENT_PADDING, content_area_start + space_height),
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START),
));
self.alert.place(Rect::new(
Point::new(
CONTENT_PADDING,
content_area_start + 2 * space_height + message_height,
),
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START),
));
self.alert.place(alert_bounds);
} else {
self.message.place(Rect::new(
Point::new(
CONTENT_PADDING,
content_area.center().y - (message_height / 2),
),
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING),
));
self.message.place(content_area);
}
let button_size = Offset::new((WIDTH - 3 * CONTENT_PADDING) / 2, BUTTON_HEIGHT);
@ -156,10 +145,6 @@ impl<'a> Component for Confirm<'a> {
button_size,
));
if let Some(title) = self.title.as_mut() {
title.place(TITLE_AREA);
}
if let Some(info) = self.info.as_mut() {
info.info_button.place(CORNER_BUTTON_AREA);
info.close_button.place(CORNER_BUTTON_AREA);
@ -178,8 +163,8 @@ impl<'a> Component for Confirm<'a> {
if let Some(Clicked) = info.close_button.event(ctx, event) {
self.show_info = false;
self.content_pad.clear();
self.title.request_complete_repaint(ctx);
self.message.request_complete_repaint(ctx);
self.alert.request_complete_repaint(ctx);
return None;
}
} else if let Some(Clicked) = info.info_button.event(ctx, event) {
@ -218,18 +203,20 @@ impl<'a> Component for Confirm<'a> {
}
}
self.title.paint();
self.message.paint();
self.alert.paint();
self.left_button.paint();
self.right_button.paint();
if let Some(icon) = self.icon {
icon.draw(
Point::new(screen().center().x, ICON_TOP),
TOP_CENTER,
WHITE,
self.bg_color,
);
match &mut self.title {
ConfirmTitle::Text(label) => label.paint(),
ConfirmTitle::Icon(icon) => {
icon.draw(
Point::new(screen().center().x, ICON_TOP),
TOP_CENTER,
WHITE,
self.bg_color,
);
}
}
}

@ -26,6 +26,7 @@ use crate::{
geometry::{Alignment, TOP_CENTER},
model_tt::{
bootloader::{
confirm::ConfirmTitle,
connect::Connect,
theme::{
button_bld, button_confirm, button_wipe_cancel, button_wipe_confirm, BLD_BG,
@ -157,25 +158,21 @@ extern "C" fn screen_install_confirm(
unwrap!(version_str.push_str("\nby "));
unwrap!(version_str.push_str(text));
let title = if downgrade {
Label::new("DOWNGRADE FW", Alignment::Start, theme::TEXT_BOLD)
let title_str = if downgrade {
"DOWNGRADE FW"
} else if vendor {
Label::new("CHANGE FW\nVENDOR", Alignment::Start, theme::TEXT_BOLD)
"CHANGE FW\nVENDOR"
} else {
Label::new("UPDATE FIRMWARE", Alignment::Start, theme::TEXT_BOLD)
"UPDATE FIRMWARE"
};
let title = Label::new(title_str, Alignment::Start, theme::TEXT_BOLD)
.vertically_aligned(Alignment::Center);
let msg = Label::new(version_str.as_ref(), Alignment::Start, theme::TEXT_NORMAL);
let alert = if vendor || downgrade {
Some(Label::new(
"SEED WILL BE ERASED!",
Alignment::Start,
theme::TEXT_BOLD,
))
} else {
None
};
let alert = (vendor || downgrade).then_some(Label::new(
"SEED WILL BE ERASED!",
Alignment::Start,
theme::TEXT_BOLD,
));
let (left, right) = if !(vendor || downgrade) {
let l = Button::with_text("CANCEL").styled(button_bld());
@ -189,10 +186,9 @@ extern "C" fn screen_install_confirm(
let mut frame = Confirm::new(
BLD_BG,
None,
left,
right,
Some(title),
ConfirmTitle::Text(title),
msg,
alert,
Some(("FW FINGERPRINT", fingerprint_str)),
@ -203,7 +199,7 @@ extern "C" fn screen_install_confirm(
#[no_mangle]
extern "C" fn screen_wipe_confirm() -> u32 {
let icon = Some(Icon::new(FIRE40));
let icon = Icon::new(FIRE40);
let msg = Label::new(
"Are you sure you want to factory reset the device?",
@ -221,10 +217,9 @@ extern "C" fn screen_wipe_confirm() -> u32 {
let mut frame = Confirm::new(
BLD_WIPE_COLOR,
icon,
left,
right,
None,
ConfirmTitle::Icon(icon),
msg,
Some(alert),
None,

Loading…
Cancel
Save