mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-12 06:06:07 +00:00
chore(eckhart): delete old bootloader components
This commit is contained in:
parent
1ede3c7de7
commit
a9ef1284a6
@ -1,246 +0,0 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{Child, Component, ComponentExt, Event, EventCtx, Label, Pad},
|
||||
constant,
|
||||
constant::screen,
|
||||
display::{Color, Icon},
|
||||
geometry::{Alignment2D, Insets, Offset, Point, Rect},
|
||||
shape,
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
component::{Button, ButtonMsg::Clicked, ButtonStyleSheet},
|
||||
constant::WIDTH,
|
||||
theme::{
|
||||
bootloader::{
|
||||
text_fingerprint, text_title, BUTTON_AREA_START, BUTTON_HEIGHT, CONTENT_PADDING,
|
||||
CORNER_BUTTON_AREA, CORNER_BUTTON_TOUCH_EXPANSION, INFO32, TITLE_AREA, X32,
|
||||
},
|
||||
WHITE,
|
||||
},
|
||||
};
|
||||
|
||||
const ICON_TOP: i16 = 17;
|
||||
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 {
|
||||
Cancel = 1,
|
||||
Confirm = 2,
|
||||
}
|
||||
|
||||
pub enum ConfirmTitle {
|
||||
Text(Label<'static>),
|
||||
Icon(Icon),
|
||||
}
|
||||
|
||||
pub struct ConfirmInfo<'a> {
|
||||
pub title: Child<Label<'a>>,
|
||||
pub text: Child<Label<'a>>,
|
||||
pub info_button: Child<Button>,
|
||||
pub close_button: Child<Button>,
|
||||
}
|
||||
|
||||
pub struct ConfirmScreen<'a> {
|
||||
bg: Pad,
|
||||
content_pad: Pad,
|
||||
bg_color: Color,
|
||||
title: ConfirmTitle,
|
||||
message: Child<Label<'a>>,
|
||||
alert: Option<Child<Label<'static>>>,
|
||||
left_button: Child<Button>,
|
||||
right_button: Child<Button>,
|
||||
info: Option<ConfirmInfo<'a>>,
|
||||
show_info: bool,
|
||||
}
|
||||
|
||||
impl<'a> ConfirmScreen<'a> {
|
||||
pub fn new(
|
||||
bg_color: Color,
|
||||
left_button: Button,
|
||||
right_button: Button,
|
||||
title: ConfirmTitle,
|
||||
message: Label<'a>,
|
||||
) -> Self {
|
||||
Self {
|
||||
bg: Pad::with_background(bg_color).with_clear(),
|
||||
content_pad: Pad::with_background(bg_color),
|
||||
bg_color,
|
||||
title,
|
||||
message: Child::new(message.vertically_centered()),
|
||||
left_button: Child::new(left_button),
|
||||
right_button: Child::new(right_button),
|
||||
alert: None,
|
||||
info: None,
|
||||
show_info: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_alert(mut self, alert: Label<'static>) -> Self {
|
||||
self.alert = Some(Child::new(alert.vertically_centered()));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_info(
|
||||
mut self,
|
||||
title: TString<'a>,
|
||||
text: TString<'a>,
|
||||
menu_button: ButtonStyleSheet,
|
||||
) -> Self {
|
||||
self.info = Some(ConfirmInfo {
|
||||
title: Child::new(
|
||||
Label::left_aligned(title, text_title(self.bg_color)).vertically_centered(),
|
||||
),
|
||||
text: Child::new(
|
||||
Label::left_aligned(text, text_fingerprint(self.bg_color)).vertically_centered(),
|
||||
),
|
||||
info_button: Child::new(
|
||||
Button::with_icon(Icon::new(INFO32))
|
||||
.styled(menu_button)
|
||||
.with_expanded_touch_area(Insets::uniform(CORNER_BUTTON_TOUCH_EXPANSION)),
|
||||
),
|
||||
close_button: Child::new(
|
||||
Button::with_icon(Icon::new(X32))
|
||||
.styled(menu_button)
|
||||
.with_expanded_touch_area(Insets::uniform(CORNER_BUTTON_TOUCH_EXPANSION)),
|
||||
),
|
||||
});
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ConfirmScreen<'_> {
|
||||
type Msg = ConfirmMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.bg.place(constant::screen());
|
||||
self.content_pad.place(Rect::new(
|
||||
Point::zero(),
|
||||
Point::new(WIDTH, BUTTON_AREA_START),
|
||||
));
|
||||
|
||||
let mut content_area = CONTENT_AREA;
|
||||
|
||||
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 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 (_, alert_bounds) = content_area.split_top(message_height);
|
||||
|
||||
self.alert.place(alert_bounds);
|
||||
} else {
|
||||
self.message.place(content_area);
|
||||
}
|
||||
|
||||
let button_size = Offset::new((WIDTH - 3 * CONTENT_PADDING) / 2, BUTTON_HEIGHT);
|
||||
self.left_button.place(Rect::from_top_left_and_size(
|
||||
Point::new(CONTENT_PADDING, BUTTON_AREA_START),
|
||||
button_size,
|
||||
));
|
||||
self.right_button.place(Rect::from_top_left_and_size(
|
||||
Point::new(2 * CONTENT_PADDING + button_size.x, BUTTON_AREA_START),
|
||||
button_size,
|
||||
));
|
||||
|
||||
if let Some(info) = self.info.as_mut() {
|
||||
info.info_button.place(CORNER_BUTTON_AREA);
|
||||
info.close_button.place(CORNER_BUTTON_AREA);
|
||||
info.title.place(TITLE_AREA);
|
||||
info.text.place(Rect::new(
|
||||
Point::new(CONTENT_PADDING, TITLE_AREA.y1),
|
||||
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START),
|
||||
));
|
||||
}
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if let Some(info) = self.info.as_mut() {
|
||||
if self.show_info {
|
||||
if let Some(Clicked) = info.close_button.event(ctx, event) {
|
||||
self.show_info = false;
|
||||
self.content_pad.clear();
|
||||
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) {
|
||||
self.show_info = true;
|
||||
info.text.request_complete_repaint(ctx);
|
||||
info.title.request_complete_repaint(ctx);
|
||||
self.content_pad.clear();
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if let Some(Clicked) = self.left_button.event(ctx, event) {
|
||||
return Some(Self::Msg::Cancel);
|
||||
};
|
||||
if let Some(Clicked) = self.right_button.event(ctx, event) {
|
||||
return Some(Self::Msg::Confirm);
|
||||
};
|
||||
None
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.content_pad.render(target);
|
||||
|
||||
if let Some(info) = self.info.as_ref() {
|
||||
if self.show_info {
|
||||
info.close_button.render(target);
|
||||
info.title.render(target);
|
||||
info.text.render(target);
|
||||
self.left_button.render(target);
|
||||
self.right_button.render(target);
|
||||
// short-circuit before painting the main components
|
||||
return;
|
||||
} else {
|
||||
info.info_button.render(target);
|
||||
// pass through to the rest of the paint
|
||||
}
|
||||
}
|
||||
|
||||
self.message.render(target);
|
||||
self.alert.render(target);
|
||||
self.left_button.render(target);
|
||||
self.right_button.render(target);
|
||||
match &self.title {
|
||||
ConfirmTitle::Text(label) => label.render(target),
|
||||
ConfirmTitle::Icon(icon) => {
|
||||
shape::ToifImage::new(Point::new(screen().center().x, ICON_TOP), icon.toif)
|
||||
.with_align(Alignment2D::TOP_CENTER)
|
||||
.with_fg(WHITE)
|
||||
.render(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl crate::trace::Trace for ConfirmScreen<'_> {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.component("BlConfirm");
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{Child, Component, Event, EventCtx, Label, Pad},
|
||||
constant::screen,
|
||||
display::Icon,
|
||||
geometry::{Alignment, Insets, Point, Rect},
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
component::{Button, ButtonMsg::Clicked},
|
||||
constant::WIDTH,
|
||||
theme::bootloader::{
|
||||
button_bld, button_bld_menu, text_title, BLD_BG, BUTTON_AREA_START, BUTTON_HEIGHT,
|
||||
CONTENT_PADDING, CORNER_BUTTON_AREA, MENU32, TEXT_NORMAL, TEXT_WARNING, TITLE_AREA,
|
||||
},
|
||||
};
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, ToPrimitive)]
|
||||
pub enum IntroMsg {
|
||||
Menu = 1,
|
||||
Host = 2,
|
||||
}
|
||||
|
||||
pub struct Intro<'a> {
|
||||
bg: Pad,
|
||||
title: Child<Label<'a>>,
|
||||
menu: Child<Button>,
|
||||
host: Child<Button>,
|
||||
text: Child<Label<'a>>,
|
||||
warn: Option<Child<Label<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> Intro<'a> {
|
||||
pub fn new(title: TString<'a>, content: TString<'a>, fw_ok: bool) -> Self {
|
||||
Self {
|
||||
bg: Pad::with_background(BLD_BG).with_clear(),
|
||||
title: Child::new(Label::left_aligned(title, text_title(BLD_BG)).vertically_centered()),
|
||||
menu: Child::new(
|
||||
Button::with_icon(Icon::new(MENU32))
|
||||
.styled(button_bld_menu())
|
||||
.with_expanded_touch_area(Insets::uniform(13)),
|
||||
),
|
||||
host: Child::new(
|
||||
Button::with_text("INSTALL FIRMWARE".into())
|
||||
.styled(button_bld())
|
||||
.with_text_align(Alignment::Center),
|
||||
),
|
||||
text: Child::new(Label::left_aligned(content, TEXT_NORMAL).vertically_centered()),
|
||||
warn: (!fw_ok).then_some(Child::new(
|
||||
Label::new("FIRMWARE CORRUPTED".into(), Alignment::Start, TEXT_WARNING)
|
||||
.vertically_centered(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Component for Intro<'a> {
|
||||
type Msg = IntroMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.bg.place(screen());
|
||||
|
||||
self.title.place(TITLE_AREA);
|
||||
self.menu.place(CORNER_BUTTON_AREA);
|
||||
self.host.place(Rect::new(
|
||||
Point::new(CONTENT_PADDING, BUTTON_AREA_START),
|
||||
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START + BUTTON_HEIGHT),
|
||||
));
|
||||
if self.warn.is_some() {
|
||||
self.warn.place(Rect::new(
|
||||
Point::new(CONTENT_PADDING, TITLE_AREA.y1 + CONTENT_PADDING),
|
||||
Point::new(
|
||||
WIDTH - CONTENT_PADDING,
|
||||
TITLE_AREA.y1 + CONTENT_PADDING + 30,
|
||||
),
|
||||
));
|
||||
self.text.place(Rect::new(
|
||||
Point::new(CONTENT_PADDING, TITLE_AREA.y1 + CONTENT_PADDING + 30),
|
||||
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING),
|
||||
));
|
||||
} else {
|
||||
self.text.place(Rect::new(
|
||||
Point::new(CONTENT_PADDING, TITLE_AREA.y1 + CONTENT_PADDING),
|
||||
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START - CONTENT_PADDING),
|
||||
));
|
||||
}
|
||||
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if let Some(Clicked) = self.menu.event(ctx, event) {
|
||||
return Some(Self::Msg::Menu);
|
||||
};
|
||||
if let Some(Clicked) = self.host.event(ctx, event) {
|
||||
return Some(Self::Msg::Host);
|
||||
};
|
||||
None
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.title.render(target);
|
||||
self.text.render(target);
|
||||
self.warn.render(target);
|
||||
self.host.render(target);
|
||||
self.menu.render(target);
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
use crate::{
|
||||
trezorhal::secbool::{secbool, sectrue},
|
||||
ui::{
|
||||
component::{Child, Component, Event, EventCtx, Label, Pad},
|
||||
constant::{screen, WIDTH},
|
||||
display::Icon,
|
||||
geometry::{Insets, Point, Rect},
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
component::{Button, ButtonMsg::Clicked, IconText},
|
||||
theme::bootloader::{
|
||||
button_bld, button_bld_menu, text_title, BLD_BG, BUTTON_HEIGHT, CONTENT_PADDING,
|
||||
CORNER_BUTTON_AREA, CORNER_BUTTON_TOUCH_EXPANSION, FIRE24, REFRESH24, TITLE_AREA, X32,
|
||||
},
|
||||
};
|
||||
|
||||
const BUTTON_AREA_START: i16 = 56;
|
||||
const BUTTON_SPACING: i16 = 8;
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, ToPrimitive)]
|
||||
pub enum MenuMsg {
|
||||
Close = 0xAABBCCDD,
|
||||
Reboot = 0x11223344,
|
||||
FactoryReset = 0x55667788,
|
||||
}
|
||||
|
||||
pub struct Menu {
|
||||
bg: Pad,
|
||||
title: Child<Label<'static>>,
|
||||
close: Child<Button>,
|
||||
reboot: Child<Button>,
|
||||
reset: Child<Button>,
|
||||
}
|
||||
|
||||
impl Menu {
|
||||
pub fn new(firmware_present: secbool) -> Self {
|
||||
let content_reboot = IconText::new("REBOOT TREZOR", Icon::new(REFRESH24));
|
||||
let content_reset = IconText::new("FACTORY RESET", Icon::new(FIRE24));
|
||||
|
||||
let mut instance = Self {
|
||||
bg: Pad::with_background(BLD_BG),
|
||||
title: Child::new(
|
||||
Label::left_aligned("BOOTLOADER".into(), text_title(BLD_BG)).vertically_centered(),
|
||||
),
|
||||
close: Child::new(
|
||||
Button::with_icon(Icon::new(X32))
|
||||
.styled(button_bld_menu())
|
||||
.with_expanded_touch_area(Insets::uniform(CORNER_BUTTON_TOUCH_EXPANSION)),
|
||||
),
|
||||
reboot: Child::new(
|
||||
Button::with_icon_and_text(content_reboot)
|
||||
.styled(button_bld())
|
||||
.initially_enabled(sectrue == firmware_present),
|
||||
),
|
||||
reset: Child::new(Button::with_icon_and_text(content_reset).styled(button_bld())),
|
||||
};
|
||||
instance.bg.clear();
|
||||
instance
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Menu {
|
||||
type Msg = MenuMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.bg.place(screen());
|
||||
self.title.place(TITLE_AREA);
|
||||
self.close.place(CORNER_BUTTON_AREA);
|
||||
self.reboot.place(Rect::new(
|
||||
Point::new(CONTENT_PADDING, BUTTON_AREA_START),
|
||||
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START + BUTTON_HEIGHT),
|
||||
));
|
||||
self.reset.place(Rect::new(
|
||||
Point::new(
|
||||
CONTENT_PADDING,
|
||||
BUTTON_AREA_START + BUTTON_HEIGHT + BUTTON_SPACING,
|
||||
),
|
||||
Point::new(
|
||||
WIDTH - CONTENT_PADDING,
|
||||
BUTTON_AREA_START + 2 * BUTTON_HEIGHT + BUTTON_SPACING,
|
||||
),
|
||||
));
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if let Some(Clicked) = self.close.event(ctx, event) {
|
||||
return Some(Self::Msg::Close);
|
||||
}
|
||||
if let Some(Clicked) = self.reboot.event(ctx, event) {
|
||||
return Some(Self::Msg::Reboot);
|
||||
}
|
||||
if let Some(Clicked) = self.reset.event(ctx, event) {
|
||||
return Some(Self::Msg::FactoryReset);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.title.render(target);
|
||||
self.close.render(target);
|
||||
self.reboot.render(target);
|
||||
self.reset.render(target);
|
||||
}
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
mod button;
|
||||
mod error;
|
||||
mod result;
|
||||
mod welcome_screen;
|
||||
|
||||
pub use button::{Button, ButtonContent, ButtonMsg, ButtonStyle, ButtonStyleSheet, IconText};
|
||||
pub use error::ErrorScreen;
|
||||
pub use result::{ResultFooter, ResultScreen, ResultStyle};
|
||||
pub use welcome_screen::WelcomeScreen;
|
||||
|
@ -1,188 +0,0 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{text::TextStyle, Component, Event, EventCtx, Label, Never, Pad},
|
||||
constant::screen,
|
||||
display::{Color, Icon},
|
||||
geometry::{Alignment2D, Insets, Offset, Point, Rect},
|
||||
shape,
|
||||
shape::Renderer,
|
||||
},
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
constant::WIDTH,
|
||||
fonts,
|
||||
theme::{FG, RESULT_FOOTER_START, RESULT_PADDING},
|
||||
};
|
||||
|
||||
const MESSAGE_AREA_START: i16 = 97;
|
||||
const ICON_CENTER_Y: i16 = 62;
|
||||
|
||||
pub struct ResultStyle {
|
||||
pub fg_color: Color,
|
||||
pub bg_color: Color,
|
||||
pub divider_color: Color,
|
||||
}
|
||||
|
||||
impl ResultStyle {
|
||||
pub const fn new(fg_color: Color, bg_color: Color, divider_color: Color) -> Self {
|
||||
Self {
|
||||
fg_color,
|
||||
bg_color,
|
||||
divider_color,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn message_style(&self) -> TextStyle {
|
||||
TextStyle::new(
|
||||
fonts::FONT_SATOSHI_REGULAR_38,
|
||||
self.fg_color,
|
||||
self.bg_color,
|
||||
FG,
|
||||
FG,
|
||||
)
|
||||
}
|
||||
|
||||
pub const fn title_style(&self) -> TextStyle {
|
||||
TextStyle::new(
|
||||
fonts::FONT_SATOSHI_MEDIUM_26,
|
||||
self.fg_color,
|
||||
self.bg_color,
|
||||
FG,
|
||||
FG,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ResultFooter<'a> {
|
||||
style: &'a ResultStyle,
|
||||
text: Label<'a>,
|
||||
area: Rect,
|
||||
}
|
||||
|
||||
impl<'a> ResultFooter<'a> {
|
||||
pub fn new(text: Label<'a>, style: &'a ResultStyle) -> Self {
|
||||
Self {
|
||||
style,
|
||||
text,
|
||||
area: Rect::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResultFooter<'_> {
|
||||
pub const fn split_bounds() -> (Rect, Rect) {
|
||||
let main_area = Rect::new(
|
||||
Point::new(RESULT_PADDING, 0),
|
||||
Point::new(WIDTH - RESULT_PADDING, RESULT_FOOTER_START),
|
||||
);
|
||||
let footer_area = Rect::new(
|
||||
Point::new(RESULT_PADDING, RESULT_FOOTER_START),
|
||||
Point::new(WIDTH - RESULT_PADDING, screen().height()),
|
||||
);
|
||||
(main_area, footer_area)
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ResultFooter<'_> {
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.area = bounds;
|
||||
self.text.place(bounds);
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// divider line
|
||||
let bar = Rect::from_center_and_size(
|
||||
Point::new(self.area.center().x, self.area.y0),
|
||||
Offset::new(self.area.width(), 1),
|
||||
);
|
||||
shape::Bar::new(bar)
|
||||
.with_fg(self.style.divider_color)
|
||||
.render(target);
|
||||
|
||||
// footer text
|
||||
self.text.render(target);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ResultScreen<'a> {
|
||||
bg: Pad,
|
||||
footer_pad: Pad,
|
||||
style: &'a ResultStyle,
|
||||
icon: Icon,
|
||||
message: Label<'a>,
|
||||
footer: ResultFooter<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ResultScreen<'a> {
|
||||
pub fn new(
|
||||
style: &'a ResultStyle,
|
||||
icon: Icon,
|
||||
message: TString<'a>,
|
||||
footer: Label<'a>,
|
||||
complete_draw: bool,
|
||||
) -> Self {
|
||||
let mut instance = Self {
|
||||
bg: Pad::with_background(style.bg_color),
|
||||
footer_pad: Pad::with_background(style.bg_color),
|
||||
style,
|
||||
icon,
|
||||
message: Label::centered(message, style.message_style()),
|
||||
footer: ResultFooter::new(footer, style),
|
||||
};
|
||||
|
||||
if complete_draw {
|
||||
instance.bg.clear();
|
||||
} else {
|
||||
instance.footer_pad.clear();
|
||||
}
|
||||
instance
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Component for ResultScreen<'a> {
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, _bounds: Rect) -> Rect {
|
||||
self.bg.place(screen());
|
||||
|
||||
let (main_area, footer_area) = ResultFooter::split_bounds();
|
||||
|
||||
self.footer_pad.place(footer_area);
|
||||
self.footer.place(footer_area);
|
||||
|
||||
let message_area = main_area.inset(Insets::top(MESSAGE_AREA_START));
|
||||
self.message.place(message_area);
|
||||
|
||||
screen()
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.footer_pad.render(target);
|
||||
|
||||
shape::ToifImage::new(
|
||||
Point::new(screen().center().x, ICON_CENTER_Y),
|
||||
self.icon.toif,
|
||||
)
|
||||
.with_align(Alignment2D::CENTER)
|
||||
.with_fg(self.style.fg_color)
|
||||
.with_bg(self.style.bg_color)
|
||||
.render(target);
|
||||
|
||||
self.message.render(target);
|
||||
self.footer.render(target);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user