1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 06:48:16 +00:00

refactor(core/bootloader): simplify Confirm arguments

This commit is contained in:
matejcik 2023-03-30 14:57:09 +02:00
parent a9a18bf80d
commit d1d373a51f
3 changed files with 77 additions and 91 deletions

View File

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

View File

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

View File

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