mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-03 16:56:07 +00:00
refactor(core/rust): allow model_t1 and model_tt at once
[no changelog]
This commit is contained in:
parent
52f719ad81
commit
7cc9f13605
@ -12,7 +12,8 @@ static void _librust_qstrs(void) {
|
|||||||
// layout
|
// layout
|
||||||
MP_QSTR_Layout;
|
MP_QSTR_Layout;
|
||||||
MP_QSTR_set_timer_fn;
|
MP_QSTR_set_timer_fn;
|
||||||
MP_QSTR_hid_event;
|
MP_QSTR_touch_event;
|
||||||
|
MP_QSTR_button_event;
|
||||||
MP_QSTR_timer;
|
MP_QSTR_timer;
|
||||||
MP_QSTR_paint;
|
MP_QSTR_paint;
|
||||||
MP_QSTR_trace;
|
MP_QSTR_trace;
|
||||||
|
@ -44,7 +44,10 @@ extern "C" {
|
|||||||
) -> bool;
|
) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::ui::component::model::constants::{HEIGHT, WIDTH};
|
#[cfg(not(feature = "model_tt"))]
|
||||||
|
use crate::ui::model_t1::constant;
|
||||||
|
#[cfg(feature = "model_tt")]
|
||||||
|
use crate::ui::model_tt::constant;
|
||||||
|
|
||||||
pub struct ToifInfo {
|
pub struct ToifInfo {
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
@ -53,11 +56,11 @@ pub struct ToifInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn width() -> i32 {
|
pub fn width() -> i32 {
|
||||||
WIDTH
|
constant::WIDTH
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height() -> i32 {
|
pub fn height() -> i32 {
|
||||||
HEIGHT
|
constant::HEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backlight(val: i32) -> i32 {
|
pub fn backlight(val: i32) -> i32 {
|
||||||
|
@ -2,7 +2,10 @@ use core::{mem, time::Duration};
|
|||||||
|
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
|
|
||||||
use crate::ui::{model_t1::event::ButtonEvent, model_tt::event::TouchEvent};
|
#[cfg(feature = "model_t1")]
|
||||||
|
use crate::ui::model_t1::event::ButtonEvent;
|
||||||
|
#[cfg(feature = "model_tt")]
|
||||||
|
use crate::ui::model_tt::event::TouchEvent;
|
||||||
|
|
||||||
/// Type used by components that do not return any messages.
|
/// Type used by components that do not return any messages.
|
||||||
///
|
///
|
||||||
@ -81,7 +84,10 @@ where
|
|||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
HumanInput(HidEvent),
|
#[cfg(feature = "model_t1")]
|
||||||
|
Button(ButtonEvent),
|
||||||
|
#[cfg(feature = "model_tt")]
|
||||||
|
Touch(TouchEvent),
|
||||||
Timer(TimerToken),
|
Timer(TimerToken),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,6 @@ use crate::ui::{
|
|||||||
geometry::{Offset, Point, Rect},
|
geometry::{Offset, Point, Rect},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::model::theme;
|
|
||||||
|
|
||||||
pub const MAX_ARGUMENTS: usize = 6;
|
pub const MAX_ARGUMENTS: usize = 6;
|
||||||
|
|
||||||
pub struct Text<F, T> {
|
pub struct Text<F, T> {
|
||||||
@ -23,9 +21,9 @@ pub struct Text<F, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F, T> Text<F, T> {
|
impl<F, T> Text<F, T> {
|
||||||
pub fn new(area: Rect, format: F) -> Self {
|
pub fn new<D: DefaultTextTheme>(area: Rect, format: F) -> Self {
|
||||||
Self {
|
Self {
|
||||||
layout: TextLayout::new(area),
|
layout: TextLayout::new::<D>(area),
|
||||||
format,
|
format,
|
||||||
args: LinearMap::new(),
|
args: LinearMap::new(),
|
||||||
}
|
}
|
||||||
@ -80,9 +78,9 @@ where
|
|||||||
self.format.as_ref(),
|
self.format.as_ref(),
|
||||||
|arg| match arg {
|
|arg| match arg {
|
||||||
Token::Literal(literal) => Some(Op::Text(literal)),
|
Token::Literal(literal) => Some(Op::Text(literal)),
|
||||||
Token::Argument(b"mono") => Some(Op::Font(theme::FONT_MONO)),
|
Token::Argument(b"mono") => Some(Op::Font(self.layout.mono_font)),
|
||||||
Token::Argument(b"bold") => Some(Op::Font(theme::FONT_BOLD)),
|
Token::Argument(b"bold") => Some(Op::Font(self.layout.bold_font)),
|
||||||
Token::Argument(b"normal") => Some(Op::Font(theme::FONT_NORMAL)),
|
Token::Argument(b"normal") => Some(Op::Font(self.layout.normal_font)),
|
||||||
Token::Argument(argument) => self
|
Token::Argument(argument) => self
|
||||||
.args
|
.args
|
||||||
.get(argument)
|
.get(argument)
|
||||||
@ -204,21 +202,44 @@ pub struct TextLayout {
|
|||||||
pub ellipsis_font: Font,
|
pub ellipsis_font: Font,
|
||||||
/// Foreground color used for drawing the ellipsis.
|
/// Foreground color used for drawing the ellipsis.
|
||||||
pub ellipsis_color: Color,
|
pub ellipsis_color: Color,
|
||||||
|
|
||||||
|
/// Font used to format `{normal}`.
|
||||||
|
pub normal_font: Font,
|
||||||
|
/// Font used to format `{bold}`.
|
||||||
|
pub bold_font: Font,
|
||||||
|
/// Font used to format `{mono}`.
|
||||||
|
pub mono_font: Font,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DefaultTextTheme {
|
||||||
|
const BACKGROUND_COLOR: Color;
|
||||||
|
const TEXT_FONT: Font;
|
||||||
|
const TEXT_COLOR: Color;
|
||||||
|
const HYPHEN_FONT: Font;
|
||||||
|
const HYPHEN_COLOR: Color;
|
||||||
|
const ELLIPSIS_FONT: Font;
|
||||||
|
const ELLIPSIS_COLOR: Color;
|
||||||
|
const NORMAL_FONT: Font;
|
||||||
|
const BOLD_FONT: Font;
|
||||||
|
const MONO_FONT: Font;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextLayout {
|
impl TextLayout {
|
||||||
pub fn new(bounds: Rect) -> Self {
|
pub fn new<T: DefaultTextTheme>(bounds: Rect) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bounds,
|
bounds,
|
||||||
background_color: theme::BG,
|
background_color: T::BACKGROUND_COLOR,
|
||||||
text_color: theme::FG,
|
text_color: T::TEXT_COLOR,
|
||||||
text_font: theme::FONT_NORMAL,
|
text_font: T::TEXT_FONT,
|
||||||
line_breaking: LineBreaking::BreakAtWhitespace,
|
line_breaking: LineBreaking::BreakAtWhitespace,
|
||||||
hyphen_font: theme::FONT_BOLD,
|
hyphen_font: T::HYPHEN_FONT,
|
||||||
hyphen_color: theme::GREY_LIGHT,
|
hyphen_color: T::HYPHEN_COLOR,
|
||||||
page_breaking: PageBreaking::CutAndInsertEllipsis,
|
page_breaking: PageBreaking::CutAndInsertEllipsis,
|
||||||
ellipsis_font: theme::FONT_BOLD,
|
ellipsis_font: T::ELLIPSIS_FONT,
|
||||||
ellipsis_color: theme::GREY_LIGHT,
|
ellipsis_color: T::ELLIPSIS_COLOR,
|
||||||
|
normal_font: T::NORMAL_FONT,
|
||||||
|
bold_font: T::BOLD_FONT,
|
||||||
|
mono_font: T::MONO_FONT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use crate::trezorhal::display;
|
use crate::trezorhal::display;
|
||||||
|
|
||||||
use super::{
|
#[cfg(not(feature = "model_tt"))]
|
||||||
component::model::constants,
|
use crate::ui::model_t1::constant;
|
||||||
geometry::{Offset, Point, Rect},
|
#[cfg(feature = "model_tt")]
|
||||||
};
|
use crate::ui::model_tt::constant;
|
||||||
|
|
||||||
|
use super::geometry::{Offset, Point, Rect};
|
||||||
|
|
||||||
pub fn width() -> i32 {
|
pub fn width() -> i32 {
|
||||||
display::width()
|
display::width()
|
||||||
@ -97,11 +99,11 @@ pub fn text_width(text: &[u8], font: Font) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_height() -> i32 {
|
pub fn text_height() -> i32 {
|
||||||
constants::TEXT_HEIGHT
|
constant::TEXT_HEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn line_height() -> i32 {
|
pub fn line_height() -> i32 {
|
||||||
constants::LINE_HEIGHT
|
constant::LINE_HEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
@ -13,10 +13,16 @@ use crate::{
|
|||||||
qstr::Qstr,
|
qstr::Qstr,
|
||||||
typ::Type,
|
typ::Type,
|
||||||
},
|
},
|
||||||
ui::component::{model::HidEvent, Child, Component, Event, EventCtx, Never, TimerToken},
|
ui::component::{Child, Component, Event, EventCtx, Never, TimerToken},
|
||||||
util,
|
util,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "model_tt")]
|
||||||
|
use crate::ui::model_tt::event::TouchEvent;
|
||||||
|
|
||||||
|
#[cfg(feature = "model_t1")]
|
||||||
|
use crate::ui::model_t1::event::ButtonEvent;
|
||||||
|
|
||||||
/// Conversion trait implemented by components that know how to convert their
|
/// Conversion trait implemented by components that know how to convert their
|
||||||
/// message values into MicroPython `Obj`s. We can automatically implement
|
/// message values into MicroPython `Obj`s. We can automatically implement
|
||||||
/// `ComponentMsgObj` for components whose message types implement `TryInto`.
|
/// `ComponentMsgObj` for components whose message types implement `TryInto`.
|
||||||
@ -204,7 +210,8 @@ impl LayoutObj {
|
|||||||
name: Qstr::MP_QSTR_Layout,
|
name: Qstr::MP_QSTR_Layout,
|
||||||
locals: &obj_dict!(obj_map! {
|
locals: &obj_dict!(obj_map! {
|
||||||
Qstr::MP_QSTR_set_timer_fn => obj_fn_2!(ui_layout_set_timer_fn).as_obj(),
|
Qstr::MP_QSTR_set_timer_fn => obj_fn_2!(ui_layout_set_timer_fn).as_obj(),
|
||||||
Qstr::MP_QSTR_hid_event => obj_fn_var!(4, 4, ui_layout_hid_event).as_obj(),
|
Qstr::MP_QSTR_touch_event => obj_fn_var!(4, 4, ui_layout_touch_event).as_obj(),
|
||||||
|
Qstr::MP_QSTR_button_event => obj_fn_var!(3, 3, ui_layout_button_event).as_obj(),
|
||||||
Qstr::MP_QSTR_timer => obj_fn_2!(ui_layout_timer).as_obj(),
|
Qstr::MP_QSTR_timer => obj_fn_2!(ui_layout_timer).as_obj(),
|
||||||
Qstr::MP_QSTR_paint => obj_fn_1!(ui_layout_paint).as_obj(),
|
Qstr::MP_QSTR_paint => obj_fn_1!(ui_layout_paint).as_obj(),
|
||||||
Qstr::MP_QSTR_trace => obj_fn_2!(ui_layout_trace).as_obj(),
|
Qstr::MP_QSTR_trace => obj_fn_2!(ui_layout_trace).as_obj(),
|
||||||
@ -281,23 +288,48 @@ extern "C" fn ui_layout_set_timer_fn(this: Obj, timer_fn: Obj) -> Obj {
|
|||||||
unsafe { util::try_or_raise(block) }
|
unsafe { util::try_or_raise(block) }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn ui_layout_hid_event(n_args: usize, args: *const Obj) -> Obj {
|
#[cfg(feature = "model_tt")]
|
||||||
|
extern "C" fn ui_layout_touch_event(n_args: usize, args: *const Obj) -> Obj {
|
||||||
let block = |args: &[Obj], _kwargs: &Map| {
|
let block = |args: &[Obj], _kwargs: &Map| {
|
||||||
if args.len() != 4 {
|
if args.len() != 4 {
|
||||||
return Err(Error::TypeError);
|
return Err(Error::TypeError);
|
||||||
}
|
}
|
||||||
let this: Gc<LayoutObj> = args[0].try_into()?;
|
let this: Gc<LayoutObj> = args[0].try_into()?;
|
||||||
let event = HidEvent::new(
|
let event = TouchEvent::new(
|
||||||
args[1].try_into()?,
|
args[1].try_into()?,
|
||||||
args[2].try_into()?,
|
args[2].try_into()?,
|
||||||
args[3].try_into()?,
|
args[3].try_into()?,
|
||||||
)?;
|
)?;
|
||||||
let msg = this.obj_event(Event::HumanInput(event))?;
|
let msg = this.obj_event(Event::Touch(event))?;
|
||||||
Ok(msg)
|
Ok(msg)
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, &Map::EMPTY, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, &Map::EMPTY, block) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "model_tt"))]
|
||||||
|
extern "C" fn ui_layout_touch_event(_n_args: usize, _args: *const Obj) -> Obj {
|
||||||
|
Obj::const_none()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "model_t1")]
|
||||||
|
extern "C" fn ui_layout_button_event(n_args: usize, args: *const Obj) -> Obj {
|
||||||
|
let block = |args: &[Obj], _kwargs: &Map| {
|
||||||
|
if args.len() != 3 {
|
||||||
|
return Err(Error::TypeError);
|
||||||
|
}
|
||||||
|
let this: Gc<LayoutObj> = args[0].try_into()?;
|
||||||
|
let event = ButtonEvent::new(args[1].try_into()?, args[2].try_into()?)?;
|
||||||
|
let msg = this.obj_event(Event::Button(event))?;
|
||||||
|
Ok(msg)
|
||||||
|
};
|
||||||
|
unsafe { util::try_with_args_and_kwargs(n_args, args, &Map::EMPTY, block) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "model_t1"))]
|
||||||
|
extern "C" fn ui_layout_button_event(_n_args: usize, _args: *const Obj) -> Obj {
|
||||||
|
Obj::const_none()
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn ui_layout_timer(this: Obj, token: Obj) -> Obj {
|
extern "C" fn ui_layout_timer(this: Obj, token: Obj) -> Obj {
|
||||||
let block = || {
|
let block = || {
|
||||||
let this: Gc<LayoutObj> = this.try_into()?;
|
let this: Gc<LayoutObj> = this.try_into()?;
|
||||||
|
@ -6,5 +6,7 @@ pub mod display;
|
|||||||
pub mod geometry;
|
pub mod geometry;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
|
|
||||||
|
#[cfg(feature = "model_t1")]
|
||||||
pub mod model_t1;
|
pub mod model_t1;
|
||||||
|
#[cfg(feature = "model_tt")]
|
||||||
pub mod model_tt;
|
pub mod model_tt;
|
||||||
|
@ -125,7 +125,7 @@ mod tests {
|
|||||||
let layout = Child::new(Dialog::new(
|
let layout = Child::new(Dialog::new(
|
||||||
display::screen(),
|
display::screen(),
|
||||||
|area| {
|
|area| {
|
||||||
Text::new(
|
Text::new::<theme::T1DefaultText>(
|
||||||
area,
|
area,
|
||||||
"Testing text layout, with some text, and some more text. And {param}",
|
"Testing text layout, with some text, and some more text. And {param}",
|
||||||
)
|
)
|
||||||
|
@ -47,7 +47,7 @@ pub fn button_cancel() -> ButtonStyleSheet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum T1DefaultText {}
|
pub struct T1DefaultText;
|
||||||
|
|
||||||
impl DefaultTextTheme for T1DefaultText {
|
impl DefaultTextTheme for T1DefaultText {
|
||||||
const BACKGROUND_COLOR: Color = BG;
|
const BACKGROUND_COLOR: Color = BG;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
use super::event::TouchEvent;
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
component::{Component, Event, EventCtx},
|
component::{Component, Event, EventCtx},
|
||||||
display::{self, Color, Font},
|
display::{self, Color, Font},
|
||||||
geometry::{Offset, Rect},
|
geometry::{Offset, Rect},
|
||||||
};
|
};
|
||||||
use super::event::TouchEvent;
|
|
||||||
|
|
||||||
pub enum ButtonMsg {
|
pub enum ButtonMsg {
|
||||||
Clicked,
|
Clicked,
|
||||||
|
@ -9,5 +9,4 @@ pub use button::{Button, ButtonContent, ButtonMsg, ButtonStyle, ButtonStyleSheet
|
|||||||
pub use dialog::{Dialog, DialogMsg};
|
pub use dialog::{Dialog, DialogMsg};
|
||||||
pub use swipe::{Swipe, SwipeDirection};
|
pub use swipe::{Swipe, SwipeDirection};
|
||||||
|
|
||||||
use super::event;
|
use super::{event, theme};
|
||||||
use super::theme;
|
|
||||||
|
@ -4,7 +4,7 @@ use crate::ui::{
|
|||||||
geometry::{Point, Rect},
|
geometry::{Point, Rect},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{theme, event::TouchEvent};
|
use super::{event::TouchEvent, theme};
|
||||||
|
|
||||||
pub enum SwipeDirection {
|
pub enum SwipeDirection {
|
||||||
Up,
|
Up,
|
||||||
|
@ -2,7 +2,6 @@ use core::convert::TryInto;
|
|||||||
|
|
||||||
use crate::{error, ui::geometry::Point};
|
use crate::{error, ui::geometry::Point};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum TouchEvent {
|
pub enum TouchEvent {
|
||||||
TouchStart(Point),
|
TouchStart(Point),
|
||||||
|
@ -39,7 +39,7 @@ extern "C" fn ui_layout_new_example(param: Obj) -> Obj {
|
|||||||
let layout = LayoutObj::new(Child::new(Dialog::new(
|
let layout = LayoutObj::new(Child::new(Dialog::new(
|
||||||
display::screen(),
|
display::screen(),
|
||||||
|area| {
|
|area| {
|
||||||
Text::new(area, param)
|
Text::new::<theme::TTDefaultText>(area, param)
|
||||||
.with(b"some", "a few")
|
.with(b"some", "a few")
|
||||||
.with(b"param", "xx")
|
.with(b"param", "xx")
|
||||||
},
|
},
|
||||||
@ -99,7 +99,7 @@ mod tests {
|
|||||||
let layout = Child::new(Dialog::new(
|
let layout = Child::new(Dialog::new(
|
||||||
display::screen(),
|
display::screen(),
|
||||||
|area| {
|
|area| {
|
||||||
Text::new(
|
Text::new::<theme::TTDefaultText>(
|
||||||
area,
|
area,
|
||||||
"Testing text layout, with some text, and some more text. And {param}",
|
"Testing text layout, with some text, and some more text. And {param}",
|
||||||
)
|
)
|
||||||
|
@ -91,3 +91,19 @@ pub fn button_cancel() -> ButtonStyleSheet {
|
|||||||
pub fn button_clear() -> ButtonStyleSheet {
|
pub fn button_clear() -> ButtonStyleSheet {
|
||||||
button_default()
|
button_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TTDefaultText;
|
||||||
|
|
||||||
|
impl DefaultTextTheme for TTDefaultText {
|
||||||
|
const BACKGROUND_COLOR: Color = BG;
|
||||||
|
const TEXT_FONT: Font = FONT_NORMAL;
|
||||||
|
const TEXT_COLOR: Color = FG;
|
||||||
|
const HYPHEN_FONT: Font = FONT_BOLD;
|
||||||
|
const HYPHEN_COLOR: Color = GREY_LIGHT;
|
||||||
|
const ELLIPSIS_FONT: Font = FONT_BOLD;
|
||||||
|
const ELLIPSIS_COLOR: Color = GREY_LIGHT;
|
||||||
|
|
||||||
|
const NORMAL_FONT: Font = FONT_NORMAL;
|
||||||
|
const BOLD_FONT: Font = FONT_BOLD;
|
||||||
|
const MONO_FONT: Font = FONT_MONO;
|
||||||
|
}
|
||||||
|
@ -457,8 +457,8 @@ if utils.MODEL == "1":
|
|||||||
if event is RENDER:
|
if event is RENDER:
|
||||||
self.layout.paint()
|
self.layout.paint()
|
||||||
elif event in (io.BUTTON_PRESSED, io.BUTTON_RELEASED):
|
elif event in (io.BUTTON_PRESSED, io.BUTTON_RELEASED):
|
||||||
msg = self.layout.hid_event(event, x, 0)
|
msg = self.layout.button_event(event, x)
|
||||||
# elif event in (io.TOUCH_START, io.TOUCH_MOVE, io.TOUCH_END):
|
# elif event in (io.TOUCH_START, io.TOUCH_MOVE, io.TOUCH_END):
|
||||||
# self.layout.hid_event(event, x, y)
|
# self.layout.touch_event(event, x, y)
|
||||||
if msg is not None:
|
if msg is not None:
|
||||||
raise Result(msg)
|
raise Result(msg)
|
||||||
|
Loading…
Reference in New Issue
Block a user