From d1d373a51fa4dc21eba2bfbade5d4b188d37f3bd Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 30 Mar 2023 14:57:09 +0200 Subject: [PATCH] refactor(core/bootloader): simplify Confirm arguments --- core/embed/rust/src/ui/component/label.rs | 16 ++- .../src/ui/model_tt/bootloader/confirm.rs | 115 ++++++++---------- .../rust/src/ui/model_tt/bootloader/mod.rs | 35 +++--- 3 files changed, 76 insertions(+), 90 deletions(-) diff --git a/core/embed/rust/src/ui/component/label.rs b/core/embed/rust/src/ui/component/label.rs index 120a99402..034c30b97 100644 --- a/core/embed/rust/src/ui/component/label.rs +++ b/core/embed/rust/src/ui/component/label.rs @@ -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 Component for Label @@ -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), diff --git a/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs b/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs index 3afbcd1d4..642737315 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/confirm.rs @@ -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>, pub text: Child>, @@ -36,8 +45,7 @@ pub struct Confirm<'a> { bg: Pad, content_pad: Pad, bg_color: Color, - icon: Option, - title: Option>>, + title: ConfirmTitle<'a>, message: Child>, alert: Option>>, left_button: Child>, @@ -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, left_button: Button<&'static str>, right_button: Button<&'static str>, - title: Option>, - msg: Label<&'a str>, + title: ConfirmTitle<'a>, + message: Label<&'a str>, alert: Option>, 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, + ); + } } } diff --git a/core/embed/rust/src/ui/model_tt/bootloader/mod.rs b/core/embed/rust/src/ui/model_tt/bootloader/mod.rs index 9cc0bd8f6..2d687878d 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/mod.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/mod.rs @@ -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,