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:
parent
a9a18bf80d
commit
d1d373a51f
@ -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),
|
||||||
|
@ -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)) {
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user