refactor(core/rust): allow model_t1 and model_tt at once

[no changelog]
pull/1948/head
Martin Milata 3 years ago
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…
Cancel
Save