parent
06eb7c7d5e
commit
2d6dfd74f6
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,50 @@
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, Never, Pad},
|
||||
constant::screen,
|
||||
display::{self, Font},
|
||||
geometry::{Offset, Rect},
|
||||
model_tr::bootloader::theme::{BLD_BG, BLD_FG},
|
||||
};
|
||||
|
||||
pub struct Connect {
|
||||
bg: Pad,
|
||||
message: &'static str,
|
||||
}
|
||||
|
||||
impl Connect {
|
||||
pub fn new(message: &'static str) -> Self {
|
||||
let mut instance = Self {
|
||||
bg: Pad::with_background(BLD_BG),
|
||||
message,
|
||||
};
|
||||
|
||||
instance.bg.clear();
|
||||
instance
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Connect {
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.bg.place(screen());
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
let font = Font::NORMAL;
|
||||
|
||||
self.bg.paint();
|
||||
display::text_center(
|
||||
screen().center() + Offset::y(font.text_height() / 2),
|
||||
self.message,
|
||||
Font::NORMAL,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,46 +1,149 @@
|
||||
#[cfg(feature = "ui_debug")]
|
||||
use crate::trace::{Trace, Tracer};
|
||||
use crate::ui::{
|
||||
component::{Child, Component, Event, EventCtx, Never, Pad},
|
||||
geometry::{Point, Rect},
|
||||
component::{Child, Component, ComponentExt, Event, EventCtx, Pad},
|
||||
constant::screen,
|
||||
display,
|
||||
display::{Font, Icon},
|
||||
geometry::{Offset, Rect, CENTER},
|
||||
model_tr::{
|
||||
bootloader::{
|
||||
theme::{BLD_BG, BLD_FG, ICON_EXIT, ICON_REDO, ICON_TRASH},
|
||||
ReturnToC,
|
||||
},
|
||||
component::{Choice, ChoiceFactory, ChoicePage, ChoicePageMsg},
|
||||
},
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
bootloader::{theme::BLD_BG, title::Title},
|
||||
constant::{HEIGHT, WIDTH},
|
||||
};
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum MenuMsg {
|
||||
Close = 1,
|
||||
Reboot = 2,
|
||||
FactoryReset = 3,
|
||||
}
|
||||
impl ReturnToC for MenuMsg {
|
||||
fn return_to_c(self) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
const CHOICE_LENGTH: usize = 3;
|
||||
|
||||
pub struct MenuChoice {
|
||||
text1: &'static str,
|
||||
text2: &'static str,
|
||||
icon: &'static [u8],
|
||||
}
|
||||
|
||||
impl MenuChoice {
|
||||
pub fn new(text1: &'static str, text2: &'static str, icon: &'static [u8]) -> Self {
|
||||
Self { text1, text2, icon }
|
||||
}
|
||||
}
|
||||
|
||||
impl Choice<&'static str> for MenuChoice {
|
||||
fn paint_center(&self, _area: Rect, _inverse: bool) {
|
||||
Icon::new(self.icon).draw(screen().center() + Offset::y(-20), CENTER, BLD_FG, BLD_BG);
|
||||
|
||||
display::text_center(
|
||||
screen().center() + Offset::y(0),
|
||||
self.text1,
|
||||
Font::NORMAL,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
display::text_center(
|
||||
screen().center() + Offset::y(10),
|
||||
self.text2,
|
||||
Font::NORMAL,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl Trace for MenuChoice {
|
||||
fn trace(&self, t: &mut dyn Tracer) {
|
||||
t.open("MenuChoice");
|
||||
t.close();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MenuChoiceFactory;
|
||||
|
||||
impl MenuChoiceFactory {
|
||||
const CHOICES: [(&'static str, &'static str, &'static [u8]); CHOICE_LENGTH] = [
|
||||
("Factory", "Reset", ICON_TRASH),
|
||||
("Reboot", "Trezor", ICON_REDO),
|
||||
("Exit", "Menu", ICON_EXIT),
|
||||
];
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl ChoiceFactory<&'static str> for MenuChoiceFactory {
|
||||
type Item = MenuChoice;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
CHOICE_LENGTH
|
||||
}
|
||||
|
||||
fn get(&self, choice_index: usize) -> MenuChoice {
|
||||
MenuChoice::new(
|
||||
MenuChoiceFactory::CHOICES[choice_index].0,
|
||||
MenuChoiceFactory::CHOICES[choice_index].1,
|
||||
MenuChoiceFactory::CHOICES[choice_index].2,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Menu {
|
||||
bg: Pad,
|
||||
title: Child<Title>,
|
||||
pg: Child<ChoicePage<MenuChoiceFactory, &'static str>>,
|
||||
}
|
||||
|
||||
impl Menu {
|
||||
pub fn new(bld_version: &'static str) -> Self {
|
||||
let mut instance = Self {
|
||||
bg: Pad::with_background(BLD_BG),
|
||||
title: Child::new(Title::new(bld_version)),
|
||||
};
|
||||
instance.bg.clear();
|
||||
instance
|
||||
pub fn new() -> Self {
|
||||
let choices = MenuChoiceFactory::new();
|
||||
Self {
|
||||
bg: Pad::with_background(BLD_BG).with_clear(),
|
||||
pg: ChoicePage::new(choices)
|
||||
.with_carousel(true)
|
||||
.with_only_one_item(true)
|
||||
.into_child(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Menu {
|
||||
type Msg = Never;
|
||||
type Msg = MenuMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.bg
|
||||
.place(Rect::new(Point::new(0, 0), Point::new(WIDTH, HEIGHT)));
|
||||
self.title
|
||||
.place(Rect::new(Point::new(10, 0), Point::new(128, 8)));
|
||||
self.bg.place(bounds);
|
||||
self.pg.place(bounds);
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
match self.pg.event(ctx, event) {
|
||||
Some(ChoicePageMsg::Choice(0)) => Some(MenuMsg::FactoryReset),
|
||||
Some(ChoicePageMsg::Choice(1)) => Some(MenuMsg::Reboot),
|
||||
Some(ChoicePageMsg::Choice(2)) => Some(MenuMsg::Close),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.bg.paint();
|
||||
self.title.paint();
|
||||
self.pg.paint();
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_bounds")]
|
||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||
self.pg.bounds(sink)
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,19 @@
|
||||
use crate::ui::{
|
||||
component::text::TextStyle,
|
||||
display::{Color, Font},
|
||||
geometry::Offset,
|
||||
};
|
||||
|
||||
use super::super::{
|
||||
component::ButtonStyleSheet,
|
||||
theme::{BG, BLACK, FG, WHITE},
|
||||
};
|
||||
|
||||
pub const WHITE: Color = Color::white();
|
||||
pub const BLACK: Color = Color::black();
|
||||
pub const BLD_BG: Color = BLACK;
|
||||
pub const BLD_FG: Color = WHITE;
|
||||
|
||||
pub fn bld_button_default() -> ButtonStyleSheet {
|
||||
ButtonStyleSheet::new(BG, FG, false, false, None, Offset::zero())
|
||||
}
|
||||
|
||||
pub fn bld_button_cancel() -> ButtonStyleSheet {
|
||||
ButtonStyleSheet::new(FG, BG, false, false, None, Offset::zero())
|
||||
}
|
||||
pub const LOGO_EMPTY: &[u8] = include_res!("model_tr/res/logo_22_33_empty.toif");
|
||||
pub const ICON_TRASH: &[u8] = include_res!("model_tr/res/trash.toif");
|
||||
pub const ICON_ALERT: &[u8] = include_res!("model_tr/res/alert.toif");
|
||||
pub const ICON_SPINNER: &[u8] = include_res!("model_tr/res/spinner.toif");
|
||||
pub const ICON_REDO: &[u8] = include_res!("model_tr/res/redo.toif");
|
||||
pub const ICON_EXIT: &[u8] = include_res!("model_tr/res/exit.toif");
|
||||
|
||||
pub const TEXT_NORMAL: TextStyle = TextStyle::new(Font::NORMAL, BLD_FG, BLD_BG, BLD_FG, BLD_FG);
|
||||
pub const TEXT_BOLD: TextStyle = TextStyle::new(Font::NORMAL, BLD_FG, BLD_BG, BLD_FG, BLD_FG);
|
||||
pub const TEXT_BOLD: TextStyle = TextStyle::new(Font::BOLD, BLD_FG, BLD_BG, BLD_FG, BLD_FG);
|
||||
|
@ -1,54 +0,0 @@
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, Never},
|
||||
display::{self, Font},
|
||||
geometry::{Point, Rect},
|
||||
};
|
||||
|
||||
use super::theme::{BLD_BG, BLD_FG};
|
||||
|
||||
pub struct Title {
|
||||
version: &'static str,
|
||||
area: Rect,
|
||||
}
|
||||
|
||||
impl Title {
|
||||
pub fn new(version: &'static str) -> Self {
|
||||
Self {
|
||||
version,
|
||||
area: Rect::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Title {
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.area = bounds;
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
display::text_top_left(
|
||||
self.area.top_left(),
|
||||
"BOOTLOADER",
|
||||
Font::NORMAL,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
display::text_top_left(
|
||||
Point::new(self.area.top_left().x + 65, self.area.top_left().y),
|
||||
self.version,
|
||||
Font::NORMAL,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_bounds")]
|
||||
fn bounds(&self, _sink: &mut dyn FnMut(Rect)) {}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, Never, Pad},
|
||||
constant::screen,
|
||||
display::{self, Font},
|
||||
geometry::{Offset, Rect},
|
||||
model_tr::bootloader::theme::{BLD_BG, BLD_FG},
|
||||
};
|
||||
|
||||
pub struct Welcome {
|
||||
bg: Pad,
|
||||
}
|
||||
|
||||
impl Welcome {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
bg: Pad::with_background(BLD_BG).with_clear(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Welcome {
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.bg.place(screen());
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.bg.paint();
|
||||
display::text_center(
|
||||
screen().top_center() + Offset::y(20),
|
||||
"Get started with",
|
||||
Font::NORMAL,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
display::text_center(
|
||||
screen().top_center() + Offset::y(35),
|
||||
"your Trezor at",
|
||||
Font::NORMAL,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
display::text_center(
|
||||
screen().top_center() + Offset::y(50),
|
||||
"trezor.io/start",
|
||||
Font::BOLD,
|
||||
BLD_FG,
|
||||
BLD_BG,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
use crate::ui::{
|
||||
component::{Child, Component, Event, EventCtx, Label, Never, Pad},
|
||||
constant::screen,
|
||||
display,
|
||||
display::Icon,
|
||||
geometry::{Alignment::Center, Offset, Point, Rect, TOP_LEFT, TOP_RIGHT},
|
||||
};
|
||||
|
||||
use crate::ui::model_tr::{
|
||||
theme,
|
||||
theme::{BG, FG},
|
||||
};
|
||||
|
||||
pub struct ErrorScreen<T> {
|
||||
bg: Pad,
|
||||
show_icons: bool,
|
||||
title: Child<Label<T>>,
|
||||
message: Child<Label<T>>,
|
||||
footer: Child<Label<T>>,
|
||||
area: Rect,
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> ErrorScreen<T> {
|
||||
pub fn new(title: T, message: T, footer: T) -> Self {
|
||||
let title = Label::new(title, Center, theme::TEXT_BOLD);
|
||||
let message = Label::new(message, Center, theme::TEXT_NORMAL).vertically_aligned(Center);
|
||||
let footer = Label::new(footer, Center, theme::TEXT_NORMAL).vertically_aligned(Center);
|
||||
|
||||
Self {
|
||||
bg: Pad::with_background(BG).with_clear(),
|
||||
show_icons: true,
|
||||
title: Child::new(title),
|
||||
message: Child::new(message),
|
||||
footer: Child::new(footer),
|
||||
area: Rect::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> Component for ErrorScreen<T> {
|
||||
type Msg = Never;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
self.bg.place(screen());
|
||||
|
||||
let title_area = Rect::new(screen().top_left(), screen().top_right() + Offset::y(11));
|
||||
self.title.place(title_area);
|
||||
|
||||
let text_width = self.title.inner().max_size().x;
|
||||
|
||||
if text_width > title_area.width() - 2 * 12 {
|
||||
self.show_icons = false;
|
||||
}
|
||||
|
||||
let message_area = Rect::new(
|
||||
title_area.bottom_left(),
|
||||
title_area.bottom_right() + Offset::y(32),
|
||||
);
|
||||
self.message.place(message_area);
|
||||
|
||||
let footer_area = Rect::new(
|
||||
screen().bottom_left() + Offset::y(-20),
|
||||
screen().bottom_right(),
|
||||
);
|
||||
self.footer.place(footer_area);
|
||||
|
||||
self.area = bounds;
|
||||
screen()
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
self.bg.paint();
|
||||
|
||||
if self.show_icons {
|
||||
Icon::new(theme::ICON_WARN_TITLE).draw(screen().top_left(), TOP_LEFT, FG, BG);
|
||||
Icon::new(theme::ICON_WARN_TITLE).draw(screen().top_right(), TOP_RIGHT, FG, BG);
|
||||
}
|
||||
self.title.paint();
|
||||
self.message.paint();
|
||||
// divider line
|
||||
let bar = Rect::from_center_and_size(
|
||||
Point::new(self.area.center().x, 43),
|
||||
Offset::new(self.area.width(), 1),
|
||||
);
|
||||
display::rect_fill(bar, FG);
|
||||
|
||||
self.footer.paint();
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
||||
Subproject commit e63e8b868ef717ae84a694eaa6782899a396a1af
|
||||
Subproject commit a973bbca756ca0c9219deefea2873d3cc774839d
|
Loading…
Reference in new issue