mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-12 14:16:06 +00:00
feat(eckhart): implement ErrorScreen
This commit is contained in:
parent
e0ddc1c596
commit
aa965a8144
@ -1,52 +1,44 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
strutil::TString,
|
strutil::TString,
|
||||||
ui::{
|
ui::{
|
||||||
component::{Component, Event, EventCtx, Label, Never, Pad},
|
component::{Component, Event, EventCtx, Label, Never},
|
||||||
constant::screen,
|
constant::SCREEN,
|
||||||
geometry::{Alignment2D, Point, Rect},
|
geometry::{Insets, Rect},
|
||||||
shape,
|
|
||||||
shape::Renderer,
|
shape::Renderer,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::super::{
|
||||||
super::{
|
cshape::ScreenBorder,
|
||||||
constant::WIDTH,
|
theme::{
|
||||||
theme::{FATAL_ERROR_COLOR, ICON_WARNING40, RESULT_FOOTER_START, RESULT_PADDING, WHITE},
|
ACTION_BAR_HEIGHT, HEADER_HEIGHT, RED, SIDE_INSETS, TEXT_NORMAL, TEXT_SMALL,
|
||||||
|
TEXT_SMALL_GREY, TEXT_SMALL_RED, TEXT_VERTICAL_SPACING,
|
||||||
},
|
},
|
||||||
ResultFooter, ResultStyle,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ICON_TOP: i16 = 23;
|
/// Full-screen component showing Eckhart RSOD. To keep it minimal, this screen
|
||||||
const TITLE_AREA_START: i16 = 70;
|
/// does not use any other components.
|
||||||
const MESSAGE_AREA_START: i16 = 90;
|
|
||||||
|
|
||||||
#[cfg(feature = "bootloader")]
|
|
||||||
const STYLE: &ResultStyle = &crate::ui::layout_eckhart::theme::bootloader::RESULT_WIPE;
|
|
||||||
#[cfg(not(feature = "bootloader"))]
|
|
||||||
const STYLE: &ResultStyle = &super::super::theme::RESULT_ERROR;
|
|
||||||
|
|
||||||
pub struct ErrorScreen<'a> {
|
pub struct ErrorScreen<'a> {
|
||||||
bg: Pad,
|
header: Label<'a>,
|
||||||
title: Label<'a>,
|
title: Label<'a>,
|
||||||
message: Label<'a>,
|
message: Label<'a>,
|
||||||
footer: ResultFooter<'a>,
|
footer: Label<'a>,
|
||||||
|
screen_border: ScreenBorder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ErrorScreen<'a> {
|
impl<'a> ErrorScreen<'a> {
|
||||||
pub fn new(title: TString<'a>, message: TString<'a>, footer: TString<'a>) -> Self {
|
pub fn new(title: TString<'a>, message: TString<'a>, footer: TString<'a>) -> Self {
|
||||||
let title = Label::centered(title, STYLE.title_style());
|
let header = Label::left_aligned("Failure".into(), TEXT_SMALL_RED).vertically_centered();
|
||||||
let message = Label::centered(message, STYLE.message_style()).vertically_centered();
|
let title = Label::left_aligned(title, TEXT_NORMAL);
|
||||||
let footer = ResultFooter::new(
|
let message = Label::left_aligned(message, TEXT_SMALL);
|
||||||
Label::centered(footer, STYLE.title_style()).vertically_centered(),
|
let footer = Label::centered(footer, TEXT_SMALL_GREY).vertically_centered();
|
||||||
STYLE,
|
|
||||||
);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
bg: Pad::with_background(FATAL_ERROR_COLOR).with_clear(),
|
header,
|
||||||
title,
|
title,
|
||||||
message,
|
message,
|
||||||
footer,
|
footer,
|
||||||
|
screen_border: ScreenBorder::new(RED),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,24 +47,23 @@ impl<'a> Component for ErrorScreen<'a> {
|
|||||||
type Msg = Never;
|
type Msg = Never;
|
||||||
|
|
||||||
fn place(&mut self, _bounds: Rect) -> Rect {
|
fn place(&mut self, _bounds: Rect) -> Rect {
|
||||||
self.bg.place(screen());
|
let area = SCREEN.inset(SIDE_INSETS);
|
||||||
|
|
||||||
let title_area = Rect::new(
|
let (header_area, area) = area.split_top(HEADER_HEIGHT);
|
||||||
Point::new(RESULT_PADDING, TITLE_AREA_START),
|
let (area, footer_area) = area.split_bottom(ACTION_BAR_HEIGHT);
|
||||||
Point::new(WIDTH - RESULT_PADDING, MESSAGE_AREA_START),
|
|
||||||
);
|
let title_height = self.title.text_height(area.width());
|
||||||
|
let message_height = self.message.text_height(area.width());
|
||||||
|
let (title_area, area) = area.split_top(title_height);
|
||||||
|
let (message_area, _) = area
|
||||||
|
.inset(Insets::top(TEXT_VERTICAL_SPACING))
|
||||||
|
.split_top(message_height);
|
||||||
|
|
||||||
|
self.header.place(header_area);
|
||||||
self.title.place(title_area);
|
self.title.place(title_area);
|
||||||
|
|
||||||
let message_area = Rect::new(
|
|
||||||
Point::new(RESULT_PADDING, MESSAGE_AREA_START),
|
|
||||||
Point::new(WIDTH - RESULT_PADDING, RESULT_FOOTER_START),
|
|
||||||
);
|
|
||||||
self.message.place(message_area);
|
self.message.place(message_area);
|
||||||
|
self.footer.place(footer_area);
|
||||||
let (_, bottom_area) = ResultFooter::<'a>::split_bounds();
|
SCREEN
|
||||||
self.footer.place(bottom_area);
|
|
||||||
|
|
||||||
screen()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||||
@ -80,17 +71,10 @@ impl<'a> Component for ErrorScreen<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||||
self.bg.render(target);
|
self.header.render(target);
|
||||||
|
|
||||||
let icon = ICON_WARNING40;
|
|
||||||
shape::ToifImage::new(Point::new(screen().center().x, ICON_TOP), icon.toif)
|
|
||||||
.with_fg(WHITE)
|
|
||||||
.with_bg(FATAL_ERROR_COLOR)
|
|
||||||
.with_align(Alignment2D::TOP_CENTER)
|
|
||||||
.render(target);
|
|
||||||
|
|
||||||
self.title.render(target);
|
self.title.render(target);
|
||||||
self.message.render(target);
|
self.message.render(target);
|
||||||
self.footer.render(target);
|
self.footer.render(target);
|
||||||
|
self.screen_border.render(u8::MAX, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user