1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-22 22:48:20 +00:00

WIP - replacing T: AsRef<str> by StrBuffer

This commit is contained in:
grdddj 2023-01-01 14:05:49 +01:00
parent e5c52da136
commit 96c10e9b42
20 changed files with 269 additions and 382 deletions

View File

@ -104,7 +104,7 @@ impl Font {
}
#[cfg(feature = "model_tr")]
impl<T: Clone + AsRef<str>> ButtonDetails<T> {
impl ButtonDetails {
pub fn print(&self) {
let text: String<20> = if let Some(text) = self.text.clone() {
text.as_ref().into()

View File

@ -1,4 +1,5 @@
use crate::{
micropython::buffer::StrBuffer,
time::Duration,
ui::{
component::{Component, Event, EventCtx},
@ -27,16 +28,16 @@ pub enum ButtonPos {
Right,
}
pub struct Button<T> {
pub struct Button {
bounds: Rect,
pos: ButtonPos,
content: ButtonContent<T>,
content: ButtonContent,
styles: ButtonStyleSheet,
state: State,
}
impl<T: AsRef<str>> Button<T> {
pub fn new(pos: ButtonPos, content: ButtonContent<T>, styles: ButtonStyleSheet) -> Self {
impl Button {
pub fn new(pos: ButtonPos, content: ButtonContent, styles: ButtonStyleSheet) -> Self {
Self {
pos,
content,
@ -46,7 +47,7 @@ impl<T: AsRef<str>> Button<T> {
}
}
pub fn with_text(pos: ButtonPos, text: T, styles: ButtonStyleSheet) -> Self {
pub fn with_text(pos: ButtonPos, text: StrBuffer, styles: ButtonStyleSheet) -> Self {
Self::new(pos, ButtonContent::Text(text), styles)
}
@ -54,7 +55,7 @@ impl<T: AsRef<str>> Button<T> {
Self::new(pos, ButtonContent::Icon(image), styles)
}
pub fn content(&self) -> &ButtonContent<T> {
pub fn content(&self) -> &ButtonContent {
&self.content
}
@ -71,7 +72,7 @@ impl<T: AsRef<str>> Button<T> {
}
/// Changing the text content of the button.
pub fn set_text(&mut self, text: T) {
pub fn set_text(&mut self, text: StrBuffer) {
self.content = ButtonContent::Text(text);
}
@ -167,10 +168,7 @@ impl<T: AsRef<str>> Button<T> {
}
}
impl<T> Component for Button<T>
where
T: AsRef<str>,
{
impl Component for Button {
type Msg = ButtonMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -265,10 +263,7 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Button<T>
where
T: AsRef<str> + crate::trace::Trace,
{
impl crate::trace::Trace for Button {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Button");
match &self.content {
@ -285,8 +280,8 @@ enum State {
Pressed,
}
pub enum ButtonContent<T> {
Text(T),
pub enum ButtonContent {
Text(StrBuffer),
Icon(Icon),
}
@ -353,9 +348,9 @@ impl ButtonStyleSheet {
}
/// Describing the button on the screen - only visuals.
#[derive(Clone, Copy)]
pub struct ButtonDetails<T> {
pub text: Option<T>,
#[derive(Clone)]
pub struct ButtonDetails {
pub text: Option<StrBuffer>,
pub icon: Option<Icon>,
pub duration: Option<Duration>,
pub with_outline: bool,
@ -364,9 +359,9 @@ pub struct ButtonDetails<T> {
pub offset: Option<Offset>,
}
impl<T: Clone + AsRef<str>> ButtonDetails<T> {
impl ButtonDetails {
/// Text button.
pub fn text(text: T) -> Self {
pub fn text(text: StrBuffer) -> Self {
Self {
text: Some(text),
icon: None,
@ -392,7 +387,7 @@ impl<T: Clone + AsRef<str>> ButtonDetails<T> {
}
/// Text with arms signalling double press.
pub fn armed_text(text: T) -> Self {
pub fn armed_text(text: StrBuffer) -> Self {
Self::text(text).with_arms()
}
@ -489,17 +484,17 @@ impl<T: Clone + AsRef<str>> ButtonDetails<T> {
/// Holding the button details for all three possible buttons.
#[derive(Clone)]
pub struct ButtonLayout<T> {
pub btn_left: Option<ButtonDetails<T>>,
pub btn_middle: Option<ButtonDetails<T>>,
pub btn_right: Option<ButtonDetails<T>>,
pub struct ButtonLayout {
pub btn_left: Option<ButtonDetails>,
pub btn_middle: Option<ButtonDetails>,
pub btn_right: Option<ButtonDetails>,
}
impl<T: AsRef<str>> ButtonLayout<T> {
impl ButtonLayout {
pub fn new(
btn_left: Option<ButtonDetails<T>>,
btn_middle: Option<ButtonDetails<T>>,
btn_right: Option<ButtonDetails<T>>,
btn_left: Option<ButtonDetails>,
btn_middle: Option<ButtonDetails>,
btn_right: Option<ButtonDetails>,
) -> Self {
Self {
btn_left,
@ -513,16 +508,14 @@ impl<T: AsRef<str>> ButtonLayout<T> {
pub fn empty() -> Self {
Self::new(None, None, None)
}
}
impl ButtonLayout<&'static str> {
/// Default button layout for all three buttons - icons.
pub fn default_three_icons() -> Self {
Self::three_icons_middle_text("SELECT")
Self::three_icons_middle_text("SELECT".into())
}
/// Special middle text for default icon layout.
pub fn three_icons_middle_text(middle_text: &'static str) -> Self {
pub fn three_icons_middle_text(middle_text: StrBuffer) -> Self {
Self::new(
Some(ButtonDetails::left_arrow_icon()),
Some(ButtonDetails::armed_text(middle_text)),
@ -531,7 +524,7 @@ impl ButtonLayout<&'static str> {
}
/// Left and right texts.
pub fn left_right_text(text_left: &'static str, text_right: &'static str) -> Self {
pub fn left_right_text(text_left: StrBuffer, text_right: StrBuffer) -> Self {
Self::new(
Some(ButtonDetails::text(text_left)),
None,
@ -540,7 +533,7 @@ impl ButtonLayout<&'static str> {
}
/// Only right text.
pub fn only_right_text(text_right: &'static str) -> Self {
pub fn only_right_text(text_right: StrBuffer) -> Self {
Self::new(None, None, Some(ButtonDetails::text(text_right)))
}
@ -572,7 +565,7 @@ impl ButtonLayout<&'static str> {
}
/// Cancel cross on left and text on the right.
pub fn cancel_and_text(text: &'static str) -> Self {
pub fn cancel_and_text(text: StrBuffer) -> Self {
Self::new(
Some(ButtonDetails::cancel_icon()),
None,
@ -581,7 +574,7 @@ impl ButtonLayout<&'static str> {
}
/// Cancel cross on left and hold-to-confirm text on the right.
pub fn cancel_and_htc_text(text: &'static str, duration: Duration) -> Self {
pub fn cancel_and_htc_text(text: StrBuffer, duration: Duration) -> Self {
Self::new(
Some(ButtonDetails::cancel_icon()),
None,
@ -590,7 +583,7 @@ impl ButtonLayout<&'static str> {
}
/// Arrow back on left and hold-to-confirm text on the right.
pub fn back_and_htc_text(text: &'static str, duration: Duration) -> Self {
pub fn back_and_htc_text(text: StrBuffer, duration: Duration) -> Self {
Self::new(
Some(ButtonDetails::left_arrow_icon()),
None,
@ -599,7 +592,7 @@ impl ButtonLayout<&'static str> {
}
/// Arrow back on left and text on the right.
pub fn back_and_text(text: &'static str) -> Self {
pub fn back_and_text(text: StrBuffer) -> Self {
Self::new(
Some(ButtonDetails::left_arrow_icon()),
None,
@ -608,12 +601,12 @@ impl ButtonLayout<&'static str> {
}
/// Only armed text in the middle.
pub fn middle_armed_text(text: &'static str) -> Self {
pub fn middle_armed_text(text: StrBuffer) -> Self {
Self::new(None, Some(ButtonDetails::armed_text(text)), None)
}
/// Only hold-to-confirm with text on the right.
pub fn htc_only(text: &'static str, duration: Duration) -> Self {
pub fn htc_only(text: StrBuffer, duration: Duration) -> Self {
Self::new(
None,
None,
@ -628,10 +621,7 @@ impl ButtonLayout<&'static str> {
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for ButtonDetails<T>
where
T: AsRef<str>,
{
impl crate::trace::Trace for ButtonDetails {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("ButtonDetails");
let mut btn_text: String<30> = String::new();

View File

@ -46,18 +46,14 @@ pub enum ButtonControllerMsg {
}
/// Defines what kind of button should be currently used.
pub enum ButtonType<T> {
Button(Button<T>),
HoldToConfirm(HoldToConfirm<T>),
pub enum ButtonType {
Button(Button),
HoldToConfirm(HoldToConfirm),
Nothing,
}
impl<T> ButtonType<T>
where
T: AsRef<str>,
T: Clone,
{
pub fn from_button_details(pos: ButtonPos, btn_details: Option<ButtonDetails<T>>) -> Self {
impl ButtonType {
pub fn from_button_details(pos: ButtonPos, btn_details: Option<ButtonDetails>) -> Self {
if let Some(btn_details) = btn_details {
if btn_details.duration.is_some() {
Self::HoldToConfirm(Self::get_hold_to_confirm(pos, btn_details))
@ -70,7 +66,7 @@ where
}
/// Create `Button` component from `btn_details`.
fn get_button(pos: ButtonPos, btn_details: ButtonDetails<T>) -> Button<T> {
fn get_button(pos: ButtonPos, btn_details: ButtonDetails) -> Button {
// Deciding between text and icon
if let Some(text) = btn_details.clone().text {
Button::with_text(pos, text, btn_details.style())
@ -82,7 +78,7 @@ where
}
/// Create `HoldToConfirm` component from `btn_details`.
fn get_hold_to_confirm(pos: ButtonPos, btn_details: ButtonDetails<T>) -> HoldToConfirm<T> {
fn get_hold_to_confirm(pos: ButtonPos, btn_details: ButtonDetails) -> HoldToConfirm {
let duration = btn_details
.duration
.unwrap_or_else(|| Duration::from_millis(1000));
@ -123,15 +119,15 @@ where
///
/// Users have a choice of a normal button or Hold-to-confirm button.
/// `button_type` specified what from those two is used, if anything.
pub struct ButtonContainer<T> {
pub struct ButtonContainer {
pos: ButtonPos,
button_type: ButtonType<T>,
button_type: ButtonType,
}
impl<T: Clone + AsRef<str>> ButtonContainer<T> {
impl ButtonContainer {
/// Supplying `None` as `btn_details` marks the button inactive
/// (it can be later activated in `set()`).
pub fn new(pos: ButtonPos, btn_details: Option<ButtonDetails<T>>) -> Self {
pub fn new(pos: ButtonPos, btn_details: Option<ButtonDetails>) -> Self {
Self {
pos,
button_type: ButtonType::from_button_details(pos, btn_details),
@ -141,7 +137,7 @@ impl<T: Clone + AsRef<str>> ButtonContainer<T> {
/// Changing the state of the button.
///
/// Passing `None` as `btn_details` will mark the button as inactive.
pub fn set(&mut self, btn_details: Option<ButtonDetails<T>>, button_area: Rect) {
pub fn set(&mut self, btn_details: Option<ButtonDetails>, button_area: Rect) {
self.button_type = ButtonType::from_button_details(self.pos, btn_details);
self.button_type.place(button_area);
}
@ -205,11 +201,11 @@ impl<T: Clone + AsRef<str>> ButtonContainer<T> {
///
/// Only "final" button events are returned in `ButtonControllerMsg::Triggered`,
/// based upon the buttons being long-press or not.
pub struct ButtonController<T> {
pub struct ButtonController {
pad: Pad,
left_btn: ButtonContainer<T>,
middle_btn: ButtonContainer<T>,
right_btn: ButtonContainer<T>,
left_btn: ButtonContainer,
middle_btn: ButtonContainer,
right_btn: ButtonContainer,
state: ButtonState,
// Button area is needed so the buttons
// can be "re-placed" after their text is changed
@ -217,8 +213,8 @@ pub struct ButtonController<T> {
button_area: Rect,
}
impl<T: Clone + AsRef<str>> ButtonController<T> {
pub fn new(btn_layout: ButtonLayout<T>) -> Self {
impl ButtonController {
pub fn new(btn_layout: ButtonLayout) -> Self {
Self {
pad: Pad::with_background(theme::BG).with_clear(),
left_btn: ButtonContainer::new(ButtonPos::Left, btn_layout.btn_left),
@ -230,7 +226,7 @@ impl<T: Clone + AsRef<str>> ButtonController<T> {
}
/// Updating all the three buttons to the wanted states.
pub fn set(&mut self, btn_layout: ButtonLayout<T>) {
pub fn set(&mut self, btn_layout: ButtonLayout) {
self.pad.clear();
self.left_btn.set(btn_layout.btn_left, self.button_area);
self.middle_btn.set(btn_layout.btn_middle, self.button_area);
@ -279,7 +275,7 @@ impl<T: Clone + AsRef<str>> ButtonController<T> {
}
}
impl<T: Clone + AsRef<str>> Component for ButtonController<T> {
impl Component for ButtonController {
type Msg = ButtonControllerMsg;
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
@ -443,10 +439,7 @@ impl<T: Clone + AsRef<str>> Component for ButtonController<T> {
use super::ButtonContent;
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for ButtonContainer<T>
where
T: AsRef<str>,
{
impl crate::trace::Trace for ButtonContainer {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("ButtonContainer");
@ -477,10 +470,7 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for ButtonController<T>
where
T: AsRef<str>,
{
impl crate::trace::Trace for ButtonController {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("ButtonController");
t.field("left_btn", &self.left_btn);

View File

@ -24,7 +24,7 @@ pub struct Flow<F, const M: usize> {
content_area: Rect,
title_area: Rect,
pad: Pad,
buttons: Child<ButtonController<&'static str>>,
buttons: Child<ButtonController>,
page_counter: u8,
}

View File

@ -58,7 +58,7 @@ where
pub struct Page<const M: usize> {
ops: Vec<Op, M>,
text_layout: TextLayout,
btn_layout: ButtonLayout<&'static str>,
btn_layout: ButtonLayout,
btn_actions: ButtonActions,
current_page: usize,
page_count: usize,
@ -68,7 +68,7 @@ pub struct Page<const M: usize> {
// For `layout.rs`
impl<const M: usize> Page<M> {
pub fn new(
btn_layout: ButtonLayout<&'static str>,
btn_layout: ButtonLayout,
btn_actions: ButtonActions,
initial_text_font: Font,
) -> Self {
@ -99,7 +99,7 @@ impl<const M: usize> Page<M> {
self.layout_content(&mut TextRenderer);
}
pub fn btn_layout(&self) -> ButtonLayout<&'static str> {
pub fn btn_layout(&self) -> ButtonLayout {
// When we are in pagination inside this flow,
// show the up and down arrows on appropriate sides.
let current = self.btn_layout.clone();

View File

@ -1,25 +1,27 @@
use super::{common, theme, ScrollBar};
use crate::ui::{
component::{Child, Component, Event, EventCtx},
geometry::{Insets, Rect},
use crate::{
micropython::buffer::StrBuffer,
ui::{
component::{Child, Component, Event, EventCtx},
geometry::{Insets, Rect},
},
};
/// Component for holding another component and displaying a title.
/// Also is allocating space for a scrollbar.
pub struct Frame<T, U> {
pub struct Frame<T> {
area: Rect,
title: U,
title: StrBuffer,
title_centered: bool,
account_for_scrollbar: bool,
content: Child<T>,
}
impl<T, U> Frame<T, U>
impl<T> Frame<T>
where
T: Component,
U: AsRef<str>,
{
pub fn new(title: U, content: T) -> Self {
pub fn new(title: StrBuffer, content: T) -> Self {
Self {
title,
area: Rect::zero(),
@ -51,10 +53,9 @@ where
}
}
impl<T, U> Component for Frame<T, U>
impl<T> Component for Frame<T>
where
T: Component,
U: AsRef<str>,
{
type Msg = T::Msg;
@ -96,10 +97,9 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T, U> crate::trace::Trace for Frame<T, U>
impl<T> crate::trace::Trace for Frame<T>
where
T: crate::trace::Trace,
U: crate::trace::Trace + AsRef<str>,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Frame");

View File

@ -1,4 +1,5 @@
use crate::{
micropython::buffer::StrBuffer,
time::{Duration, Instant},
ui::{
component::{Component, Event, EventCtx},
@ -13,15 +14,20 @@ pub enum HoldToConfirmMsg {
FailedToConfirm,
}
pub struct HoldToConfirm<T> {
pub struct HoldToConfirm {
area: Rect,
pos: ButtonPos,
loader: Loader<T>,
loader: Loader,
text_width: i16,
}
impl<T: AsRef<str>> HoldToConfirm<T> {
pub fn text(pos: ButtonPos, text: T, styles: LoaderStyleSheet, duration: Duration) -> Self {
impl HoldToConfirm {
pub fn text(
pos: ButtonPos,
text: StrBuffer,
styles: LoaderStyleSheet,
duration: Duration,
) -> Self {
let text_width = styles.normal.font.text_width(text.as_ref());
Self {
area: Rect::zero(),
@ -32,8 +38,8 @@ impl<T: AsRef<str>> HoldToConfirm<T> {
}
/// Updating the text of the component and re-placing it.
pub fn set_text(&mut self, text: T, button_area: Rect) {
self.text_width = self.loader.get_text_width(&text) as i16;
pub fn set_text(&mut self, text: StrBuffer, button_area: Rect) {
self.text_width = self.loader.get_text_width(text.clone()) as i16;
self.loader.set_text(text);
self.place(button_area);
}
@ -50,7 +56,7 @@ impl<T: AsRef<str>> HoldToConfirm<T> {
self.loader.get_duration()
}
pub fn get_text(&self) -> &T {
pub fn get_text(&self) -> &StrBuffer {
self.loader.get_text()
}
@ -64,7 +70,7 @@ impl<T: AsRef<str>> HoldToConfirm<T> {
}
}
impl<T: AsRef<str>> Component for HoldToConfirm<T> {
impl Component for HoldToConfirm {
type Msg = HoldToConfirmMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -103,7 +109,7 @@ impl<T: AsRef<str>> Component for HoldToConfirm<T> {
}
#[cfg(feature = "ui_debug")]
impl<T: AsRef<str>> crate::trace::Trace for HoldToConfirm<T> {
impl crate::trace::Trace for HoldToConfirm {
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
d.open("HoldToConfirm");
self.loader.trace(d);

View File

@ -1,9 +1,12 @@
use crate::ui::{
component::{Component, Event, EventCtx, Pad},
display::Font,
event::{ButtonEvent, USBEvent},
geometry::{Offset, Point, Rect},
model_tr::constant,
use crate::{
micropython::buffer::StrBuffer,
ui::{
component::{Component, Event, EventCtx, Pad},
display::Font,
event::{ButtonEvent, USBEvent},
geometry::{Offset, Point, Rect},
model_tr::constant,
},
};
use super::{common::display_center, theme};
@ -14,9 +17,9 @@ const LABEL_Y: i16 = 62;
const LOCKED_Y: i16 = 32;
const TAP_Y: i16 = 47;
pub struct Homescreen<T> {
label: T,
notification: Option<(T, u8)>,
pub struct Homescreen {
label: StrBuffer,
notification: Option<(StrBuffer, u8)>,
usb_connected: bool,
pad: Pad,
}
@ -25,11 +28,8 @@ pub enum HomescreenMsg {
Dismissed,
}
impl<T> Homescreen<T>
where
T: AsRef<str>,
{
pub fn new(label: T, notification: Option<(T, u8)>) -> Self {
impl Homescreen {
pub fn new(label: StrBuffer, notification: Option<(StrBuffer, u8)>) -> Self {
Self {
label,
notification,
@ -57,10 +57,7 @@ where
}
}
impl<T> Component for Homescreen<T>
where
T: AsRef<str>,
{
impl Component for Homescreen {
type Msg = HomescreenMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -89,7 +86,7 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T: AsRef<str>> crate::trace::Trace for Homescreen<T> {
impl crate::trace::Trace for Homescreen {
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
d.open("Homescreen");
d.kw_pair("active_page", "0");
@ -99,21 +96,18 @@ impl<T: AsRef<str>> crate::trace::Trace for Homescreen<T> {
}
}
pub struct Lockscreen<T> {
label: T,
pub struct Lockscreen {
label: StrBuffer,
bootscreen: bool,
}
impl<T> Lockscreen<T> {
pub fn new(label: T, bootscreen: bool) -> Self {
impl Lockscreen {
pub fn new(label: StrBuffer, bootscreen: bool) -> Self {
Lockscreen { label, bootscreen }
}
}
impl<T> Component for Lockscreen<T>
where
T: AsRef<str>,
{
impl Component for Lockscreen {
type Msg = HomescreenMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -144,10 +138,7 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Lockscreen<T>
where
T: AsRef<str>,
{
impl crate::trace::Trace for Lockscreen {
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
d.open("Lockscreen");
d.field("label", &self.label.as_ref());

View File

@ -58,8 +58,11 @@ impl ChoiceFactory for ChoiceFactoryBIP39 {
match self {
Self::Letters(letter_choices) => {
if choice_index >= letter_choices.len() as u8 {
ChoiceItem::new("DELETE", ButtonLayout::three_icons_middle_text("CONFIRM"))
.with_icon(Icon::new(theme::ICON_DELETE))
ChoiceItem::new(
"DELETE",
ButtonLayout::three_icons_middle_text("CONFIRM".into()),
)
.with_icon(Icon::new(theme::ICON_DELETE))
} else {
let letter = letter_choices[choice_index as usize];
ChoiceItem::new(
@ -70,9 +73,11 @@ impl ChoiceFactory for ChoiceFactoryBIP39 {
}
Self::Words(word_choices) => {
if choice_index >= word_choices.len() as u8 {
let mut item =
ChoiceItem::new("DELETE", ButtonLayout::three_icons_middle_text("CONFIRM"))
.with_icon(Icon::new(theme::ICON_DELETE));
let mut item = ChoiceItem::new(
"DELETE",
ButtonLayout::three_icons_middle_text("CONFIRM".into()),
)
.with_icon(Icon::new(theme::ICON_DELETE));
item.set_right_btn(None);
item
} else {

View File

@ -27,7 +27,7 @@ pub trait Choice {
fn paint_right(&self, _area: Rect, _show_incomplete: bool) -> Option<i16> {
None
}
fn btn_layout(&self) -> ButtonLayout<&'static str> {
fn btn_layout(&self) -> ButtonLayout {
ButtonLayout::default_three_icons()
}
}
@ -69,7 +69,7 @@ where
{
choices: F,
pad: Pad,
buttons: Child<ButtonController<&'static str>>,
buttons: Child<ButtonController>,
page_counter: u8,
/// How many pixels from top should we render the items.
y_baseline: i16,

View File

@ -15,12 +15,12 @@ use super::super::{
pub struct ChoiceItem {
text: String<50>,
icon: Option<Icon>,
btn_layout: ButtonLayout<&'static str>,
btn_layout: ButtonLayout,
font: Font,
}
impl ChoiceItem {
pub fn new<T>(text: T, btn_layout: ButtonLayout<&'static str>) -> Self
pub fn new<T>(text: T, btn_layout: ButtonLayout) -> Self
where
T: AsRef<str>,
{
@ -105,17 +105,17 @@ impl ChoiceItem {
}
/// Setting left button.
pub fn set_left_btn(&mut self, btn_left: Option<ButtonDetails<&'static str>>) {
pub fn set_left_btn(&mut self, btn_left: Option<ButtonDetails>) {
self.btn_layout.btn_left = btn_left;
}
/// Setting middle button.
pub fn set_middle_btn(&mut self, btn_middle: Option<ButtonDetails<&'static str>>) {
pub fn set_middle_btn(&mut self, btn_middle: Option<ButtonDetails>) {
self.btn_layout.btn_middle = btn_middle;
}
/// Setting right button.
pub fn set_right_btn(&mut self, btn_right: Option<ButtonDetails<&'static str>>) {
pub fn set_right_btn(&mut self, btn_right: Option<ButtonDetails>) {
self.btn_layout.btn_right = btn_right;
}
@ -193,7 +193,7 @@ impl Choice for ChoiceItem {
}
/// Getting current button layout.
fn btn_layout(&self) -> ButtonLayout<&'static str> {
fn btn_layout(&self) -> ButtonLayout {
self.btn_layout.clone()
}
}

View File

@ -111,10 +111,14 @@ impl ChoiceFactoryPassphrase {
// Including accept button on the left and cancel on the very right.
// TODO: could have some icons instead of the shortcut text
if choice_index == 0 {
menu_item.set_left_btn(Some(ButtonDetails::text("ACC").with_default_duration()));
menu_item.set_left_btn(Some(
ButtonDetails::text("ACC".into()).with_default_duration(),
));
}
if choice_index == MENU.len() as u8 - 1 {
menu_item.set_right_btn(Some(ButtonDetails::text("CAN").with_default_duration()));
menu_item.set_right_btn(Some(
ButtonDetails::text("CAN".into()).with_default_duration(),
));
}
// Including icons for some items.
@ -131,7 +135,10 @@ impl ChoiceFactoryPassphrase {
/// return back
fn get_character_item(&self, choice_index: u8) -> ChoiceItem {
if is_menu_choice(&self.current_category, choice_index) {
ChoiceItem::new("MENU", ButtonLayout::three_icons_middle_text("RETURN"))
ChoiceItem::new(
"MENU",
ButtonLayout::three_icons_middle_text("RETURN".into()),
)
} else {
let ch = get_char(&self.current_category, choice_index);
ChoiceItem::new(char_to_string::<1>(ch), ButtonLayout::default_three_icons())

View File

@ -1,4 +1,5 @@
use crate::{
micropython::buffer::StrBuffer,
trezorhal::random,
ui::{
component::{text::common::TextBox, Child, Component, ComponentExt, Event, EventCtx},
@ -48,7 +49,7 @@ impl ChoiceFactory for ChoiceFactoryPIN {
// Action buttons have different middle button text
if [DELETE_INDEX, SHOW_INDEX, ENTER_INDEX].contains(&(choice_index as usize)) {
let confirm_btn = ButtonDetails::armed_text("CONFIRM");
let confirm_btn = ButtonDetails::armed_text("CONFIRM".into());
choice_item.set_middle_btn(Some(confirm_btn));
}
@ -70,20 +71,17 @@ impl ChoiceFactory for ChoiceFactoryPIN {
}
/// Component for entering a PIN.
pub struct PinEntry<T> {
pub struct PinEntry {
choice_page: ChoicePage<ChoiceFactoryPIN>,
pin_line: Child<ChangingTextLine<String<MAX_PIN_LENGTH>>>,
subprompt_line: Child<ChangingTextLine<T>>,
prompt: T,
subprompt_line: Child<ChangingTextLine<StrBuffer>>,
prompt: StrBuffer,
show_real_pin: bool,
textbox: TextBox<MAX_PIN_LENGTH>,
}
impl<T> PinEntry<T>
where
T: AsRef<str> + Clone,
{
pub fn new(prompt: T, subprompt: T) -> Self {
impl PinEntry {
pub fn new(prompt: StrBuffer, subprompt: StrBuffer) -> Self {
let choices = ChoiceFactoryPIN::new();
Self {
@ -158,10 +156,7 @@ where
}
}
impl<T> Component for PinEntry<T>
where
T: AsRef<str> + Clone,
{
impl Component for PinEntry {
type Msg = PinEntryMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -224,10 +219,7 @@ where
use super::super::{ButtonAction, ButtonPos};
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for PinEntry<T>
where
T: AsRef<str> + Clone,
{
impl crate::trace::Trace for PinEntry {
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
match pos {
ButtonPos::Left => ButtonAction::PrevPage.string(),

View File

@ -1,6 +1,9 @@
use crate::ui::{
component::{Component, Event, EventCtx},
geometry::Rect,
use crate::{
micropython::buffer::StrBuffer,
ui::{
component::{Component, Event, EventCtx},
geometry::Rect,
},
};
use super::super::{ButtonLayout, ChoiceFactory, ChoiceItem, ChoicePage, ChoicePageMsg};
@ -13,24 +16,18 @@ pub enum SimpleChoiceMsg {
Result(String<50>),
}
struct ChoiceFactorySimple<T, const N: usize> {
choices: Vec<T, N>,
struct ChoiceFactorySimple<const N: usize> {
choices: Vec<StrBuffer, N>,
carousel: bool,
}
impl<T, const N: usize> ChoiceFactorySimple<T, N>
where
T: AsRef<str>,
{
fn new(choices: Vec<T, N>, carousel: bool) -> Self {
impl<const N: usize> ChoiceFactorySimple<N> {
fn new(choices: Vec<StrBuffer, N>, carousel: bool) -> Self {
Self { choices, carousel }
}
}
impl<T, const N: usize> ChoiceFactory for ChoiceFactorySimple<T, N>
where
T: AsRef<str>,
{
impl<const N: usize> ChoiceFactory for ChoiceFactorySimple<N> {
type Item = ChoiceItem;
fn count(&self) -> u8 {
@ -58,21 +55,13 @@ where
/// Simple wrapper around `ChoicePage` that allows for
/// inputting a list of values and receiving the chosen one.
pub struct SimpleChoice<T, const N: usize>
where
T: AsRef<str>,
T: Clone,
{
choices: Vec<T, N>,
choice_page: ChoicePage<ChoiceFactorySimple<T, N>>,
pub struct SimpleChoice<const N: usize> {
choices: Vec<StrBuffer, N>,
choice_page: ChoicePage<ChoiceFactorySimple<N>>,
}
impl<T, const N: usize> SimpleChoice<T, N>
where
T: AsRef<str>,
T: Clone,
{
pub fn new(str_choices: Vec<T, N>, carousel: bool, show_incomplete: bool) -> Self {
impl<const N: usize> SimpleChoice<N> {
pub fn new(str_choices: Vec<StrBuffer, N>, carousel: bool, show_incomplete: bool) -> Self {
let choices = ChoiceFactorySimple::new(str_choices.clone(), carousel);
Self {
choices: str_choices,
@ -83,11 +72,7 @@ where
}
}
impl<T, const N: usize> Component for SimpleChoice<T, N>
where
T: AsRef<str>,
T: Clone,
{
impl<const N: usize> Component for SimpleChoice<N> {
type Msg = SimpleChoiceMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -111,11 +96,7 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T, const N: usize> crate::trace::Trace for SimpleChoice<T, N>
where
T: AsRef<str>,
T: Clone,
{
impl<const N: usize> crate::trace::Trace for SimpleChoice<N> {
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
match pos {
ButtonPos::Left => match self.choice_page.has_previous_choice() {

View File

@ -1,4 +1,5 @@
use crate::{
micropython::buffer::StrBuffer,
time::{Duration, Instant},
ui::{
animation::Animation,
@ -21,19 +22,19 @@ enum State {
Grown,
}
pub struct Loader<T> {
pub struct Loader {
area: Rect,
state: State,
growing_duration: Duration,
shrinking_duration: Duration,
text_overlay: display::TextOverlay<T>,
text_overlay: display::TextOverlay<StrBuffer>,
styles: LoaderStyleSheet,
}
impl<T: AsRef<str>> Loader<T> {
impl Loader {
pub const SIZE: Offset = Offset::new(120, 120);
pub fn new(text_overlay: display::TextOverlay<T>, styles: LoaderStyleSheet) -> Self {
pub fn new(text_overlay: display::TextOverlay<StrBuffer>, styles: LoaderStyleSheet) -> Self {
Self {
area: Rect::zero(),
state: State::Initial,
@ -44,7 +45,7 @@ impl<T: AsRef<str>> Loader<T> {
}
}
pub fn text(text: T, styles: LoaderStyleSheet) -> Self {
pub fn text(text: StrBuffer, styles: LoaderStyleSheet) -> Self {
let text_overlay = display::TextOverlay::new(text, styles.normal.font);
Self::new(text_overlay, styles)
@ -64,17 +65,17 @@ impl<T: AsRef<str>> Loader<T> {
self.growing_duration
}
pub fn get_text(&self) -> &T {
pub fn get_text(&self) -> &StrBuffer {
self.text_overlay.get_text()
}
/// Change the text of the loader.
pub fn set_text(&mut self, text: T) {
pub fn set_text(&mut self, text: StrBuffer) {
self.text_overlay.set_text(text);
}
/// Return width of given text according to current style.
pub fn get_text_width(&self, text: &T) -> i16 {
pub fn get_text_width(&self, text: StrBuffer) -> i16 {
self.styles.normal.font.text_width(text.as_ref())
}
@ -161,7 +162,7 @@ impl<T: AsRef<str>> Loader<T> {
}
}
impl<T: AsRef<str>> Component for Loader<T> {
impl Component for Loader {
type Msg = LoaderMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -241,7 +242,7 @@ impl LoaderStyleSheet {
}
#[cfg(feature = "ui_debug")]
impl<T: AsRef<str>> crate::trace::Trace for Loader<T> {
impl crate::trace::Trace for Loader {
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
d.open("Loader");
d.close();

View File

@ -1,70 +1,39 @@
use crate::{
micropython::buffer::StrBuffer,
ui::{
component::{Child, Component, ComponentExt, Event, EventCtx, Pad, PageMsg, Paginate},
display::Color,
geometry::{Insets, Offset, Rect},
},
use crate::ui::{
component::{Child, Component, ComponentExt, Event, EventCtx, Pad, PageMsg, Paginate},
display::Color,
geometry::{Insets, Offset, Rect},
};
use super::{
theme, ButtonController, ButtonControllerMsg, ButtonDetails, ButtonLayout, ButtonPos, ScrollBar,
};
pub struct ButtonPage<S, T> {
pub struct ButtonPage<T> {
content: Child<T>,
scrollbar: Child<ScrollBar>,
/// Optional available area for scrollbar defined by parent component.
parent_scrollbar_area: Option<Rect>,
pad: Pad,
/// Left button of the first screen
cancel_btn_details: Option<ButtonDetails<S>>,
cancel_btn_details: Option<ButtonDetails>,
/// Right button of the last screen
confirm_btn_details: Option<ButtonDetails<S>>,
confirm_btn_details: Option<ButtonDetails>,
/// Left button of the last page
last_back_btn_details: Option<ButtonDetails<S>>,
last_back_btn_details: Option<ButtonDetails>,
/// Left button of every screen in the middle
back_btn_details: Option<ButtonDetails<S>>,
back_btn_details: Option<ButtonDetails>,
/// Right button of every screen apart the last one
next_btn_details: Option<ButtonDetails<S>>,
buttons: Child<ButtonController<S>>,
next_btn_details: Option<ButtonDetails>,
buttons: Child<ButtonController>,
/// Scrollbar may or may not be shown (but will be counting pages anyway).
show_scrollbar: bool,
}
impl<T> ButtonPage<&'static str, T>
impl<T> ButtonPage<T>
where
T: Paginate,
T: Component,
T: Component + Paginate,
{
/// Constructor for `&'static str` button-text type.
pub fn new_str(content: T, background: Color) -> Self {
Self {
content: Child::new(content),
scrollbar: Child::new(ScrollBar::to_be_filled_later()),
parent_scrollbar_area: None,
pad: Pad::with_background(background).with_clear(),
cancel_btn_details: Some(ButtonDetails::cancel_icon()),
confirm_btn_details: Some(ButtonDetails::text("CONFIRM")),
back_btn_details: Some(ButtonDetails::up_arrow_icon_wide()),
last_back_btn_details: Some(ButtonDetails::up_arrow_icon()),
next_btn_details: Some(ButtonDetails::down_arrow_icon_wide()),
// Setting empty layout for now, we do not yet know the page count.
// Initial button layout will be set in `place()` after we can call
// `content.page_count()`.
buttons: Child::new(ButtonController::new(ButtonLayout::empty())),
show_scrollbar: true,
}
}
}
impl<T> ButtonPage<StrBuffer, T>
where
T: Paginate,
T: Component,
{
/// Constructor for `StrBuffer` button-text type.
pub fn new_str_buf(content: T, background: Color) -> Self {
pub fn new(content: T, background: Color) -> Self {
Self {
content: Child::new(content),
scrollbar: Child::new(ScrollBar::to_be_filled_later()),
@ -82,31 +51,23 @@ where
show_scrollbar: true,
}
}
}
impl<S, T> ButtonPage<S, T>
where
T: Paginate,
T: Component,
S: AsRef<str>,
S: Clone,
{
pub fn with_cancel_btn(mut self, btn_details: Option<ButtonDetails<S>>) -> Self {
pub fn with_cancel_btn(mut self, btn_details: Option<ButtonDetails>) -> Self {
self.cancel_btn_details = btn_details;
self
}
pub fn with_confirm_btn(mut self, btn_details: Option<ButtonDetails<S>>) -> Self {
pub fn with_confirm_btn(mut self, btn_details: Option<ButtonDetails>) -> Self {
self.confirm_btn_details = btn_details;
self
}
pub fn with_back_btn(mut self, btn_details: Option<ButtonDetails<S>>) -> Self {
pub fn with_back_btn(mut self, btn_details: Option<ButtonDetails>) -> Self {
self.back_btn_details = btn_details;
self
}
pub fn with_next_btn(mut self, btn_details: Option<ButtonDetails<S>>) -> Self {
pub fn with_next_btn(mut self, btn_details: Option<ButtonDetails>) -> Self {
self.next_btn_details = btn_details;
self
}
@ -147,7 +108,7 @@ where
});
}
fn get_button_layout(&self, has_prev: bool, has_next: bool) -> ButtonLayout<S> {
fn get_button_layout(&self, has_prev: bool, has_next: bool) -> ButtonLayout {
let btn_left = self.get_left_button_details(!has_prev, !has_next);
let btn_right = self.get_right_button_details(has_next);
ButtonLayout::new(btn_left, None, btn_right)
@ -155,7 +116,7 @@ where
/// Get the let button details, depending whether the page is first, last,
/// or in the middle.
fn get_left_button_details(&self, is_first: bool, is_last: bool) -> Option<ButtonDetails<S>> {
fn get_left_button_details(&self, is_first: bool, is_last: bool) -> Option<ButtonDetails> {
if is_first {
self.cancel_btn_details.clone()
} else if is_last {
@ -167,7 +128,7 @@ where
/// Get the right button details, depending on whether there is a next
/// page.
fn get_right_button_details(&self, has_next_page: bool) -> Option<ButtonDetails<S>> {
fn get_right_button_details(&self, has_next_page: bool) -> Option<ButtonDetails> {
if has_next_page {
self.next_btn_details.clone()
} else {
@ -176,12 +137,9 @@ where
}
}
impl<S, T> Component for ButtonPage<S, T>
impl<T> Component for ButtonPage<T>
where
S: Clone,
S: AsRef<str>,
T: Component,
T: Paginate,
T: Component + Paginate,
{
type Msg = PageMsg<T::Msg, bool>;
@ -278,10 +236,9 @@ use super::ButtonAction;
use heapless::String;
#[cfg(feature = "ui_debug")]
impl<S, T> crate::trace::Trace for ButtonPage<S, T>
impl<T> crate::trace::Trace for ButtonPage<T>
where
T: crate::trace::Trace,
S: AsRef<str>,
{
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
match pos {

View File

@ -2,11 +2,12 @@ use core::mem;
use crate::{
error::Error,
micropython::buffer::StrBuffer,
ui::{
component::{
base::ComponentExt,
paginated::Paginate,
text::paragraphs::{Paragraph, ParagraphStrType, Paragraphs},
text::paragraphs::{Paragraph, Paragraphs},
Child, Component, Event, EventCtx, Label, Never, Pad,
},
display::{self, Font},
@ -18,27 +19,24 @@ use crate::{
use super::theme;
pub struct Progress<T> {
title: Child<Label<T>>,
pub struct Progress {
title: Child<Label<StrBuffer>>,
value: u16,
loader_y_offset: i16,
indeterminate: bool,
description: Child<Paragraphs<Paragraph<T>>>,
description: Child<Paragraphs<Paragraph<StrBuffer>>>,
description_pad: Pad,
update_description: fn(&str) -> Result<T, Error>,
update_description: fn(&str) -> Result<StrBuffer, Error>,
}
impl<T> Progress<T>
where
T: ParagraphStrType,
{
impl Progress {
const AREA: Rect = constant::screen();
pub fn new(
title: T,
title: StrBuffer,
indeterminate: bool,
description: T,
update_description: fn(&str) -> Result<T, Error>,
description: StrBuffer,
update_description: fn(&str) -> Result<StrBuffer, Error>,
) -> Self {
Self {
title: Label::centered(title, theme::TEXT_HEADER).into_child(),
@ -55,10 +53,7 @@ where
}
}
impl<T> Component for Progress<T>
where
T: ParagraphStrType,
{
impl Component for Progress {
type Msg = Never;
fn place(&mut self, _bounds: Rect) -> Rect {
@ -126,10 +121,7 @@ where
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Progress<T>
where
T: ParagraphStrType,
{
impl crate::trace::Trace for Progress {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Progress");
t.close();

View File

@ -1,7 +1,10 @@
use crate::ui::{
component::{Child, Component, Event, EventCtx},
display::{self, Font},
geometry::Rect,
use crate::{
micropython::buffer::StrBuffer,
ui::{
component::{Child, Component, Event, EventCtx},
display::{self, Font},
geometry::Rect,
},
};
use super::{theme, ButtonController, ButtonControllerMsg, ButtonLayout, ButtonPos};
@ -11,18 +14,15 @@ pub enum QRCodePageMessage {
Cancelled,
}
pub struct QRCodePage<F, T> {
title: T,
pub struct QRCodePage<T> {
title: StrBuffer,
title_area: Rect,
qr_code: F,
buttons: Child<ButtonController<T>>,
qr_code: T,
buttons: Child<ButtonController>,
}
impl<F, T> QRCodePage<F, T>
where
T: AsRef<str> + Clone,
{
pub fn new(title: T, qr_code: F, btn_layout: ButtonLayout<T>) -> Self {
impl<T> QRCodePage<T> {
pub fn new(title: StrBuffer, qr_code: T, btn_layout: ButtonLayout) -> Self {
Self {
title,
title_area: Rect::zero(),
@ -32,10 +32,9 @@ where
}
}
impl<F, T> Component for QRCodePage<F, T>
impl<T> Component for QRCodePage<T>
where
T: AsRef<str> + Clone,
F: Component,
T: Component,
{
type Msg = QRCodePageMessage;
@ -86,10 +85,7 @@ use super::ButtonAction;
use heapless::String;
#[cfg(feature = "ui_debug")]
impl<F, T> crate::trace::Trace for QRCodePage<F, T>
where
T: AsRef<str> + Clone,
{
impl<T> crate::trace::Trace for QRCodePage<T> {
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
match pos {
ButtonPos::Left => ButtonAction::Cancel.string(),

View File

@ -1,8 +1,9 @@
use crate::{
micropython::buffer::StrBuffer,
time::Instant,
ui::{
component::{
text::paragraphs::{Paragraph, ParagraphStrType, Paragraphs},
text::paragraphs::{Paragraph, Paragraphs},
Child, Component, ComponentExt, Event, EventCtx, Label, Pad,
},
constant::screen,
@ -20,14 +21,14 @@ pub enum ResultPopupMsg {
Confirmed,
}
pub struct ResultPopup<S> {
pub struct ResultPopup {
area: Rect,
pad: Pad,
result_anim: Child<ResultAnim>,
headline_baseline: Point,
headline: Option<Label<&'static str>>,
text: Child<Paragraphs<Paragraph<S>>>,
buttons: Option<Child<ButtonController<&'static str>>>,
text: Child<Paragraphs<Paragraph<StrBuffer>>>,
buttons: Option<Child<ButtonController>>,
autoclose: bool,
}
@ -37,10 +38,10 @@ const ANIM_POS: i16 = 32;
const ANIM_POS_ADJ_HEADLINE: i16 = 10;
const ANIM_POS_ADJ_BUTTON: i16 = 6;
impl<S: ParagraphStrType> ResultPopup<S> {
impl ResultPopup {
pub fn new(
icon: &'static [u8],
text: S,
text: StrBuffer,
headline: Option<&'static str>,
button_text: Option<&'static str>,
) -> Self {
@ -48,7 +49,7 @@ impl<S: ParagraphStrType> ResultPopup<S> {
.with_placement(LinearPlacement::vertical().align_at_center());
let buttons = button_text.map(|text| {
let btn_layout = ButtonLayout::only_right_text(text);
let btn_layout = ButtonLayout::only_right_text(text.into());
Child::new(ButtonController::new(btn_layout))
});
@ -84,7 +85,7 @@ impl<S: ParagraphStrType> ResultPopup<S> {
}
}
impl<S: ParagraphStrType> Component for ResultPopup<S> {
impl Component for ResultPopup {
type Msg = ResultPopupMsg;
fn place(&mut self, bounds: Rect) -> Rect {
@ -155,7 +156,7 @@ impl<S: ParagraphStrType> Component for ResultPopup<S> {
}
#[cfg(feature = "ui_debug")]
impl<S: ParagraphStrType> crate::trace::Trace for ResultPopup<S> {
impl crate::trace::Trace for ResultPopup {
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
d.open("ResultPopup");
self.text.trace(d);

View File

@ -20,8 +20,7 @@ use crate::{
paginated::{PageMsg, Paginate},
painter,
text::paragraphs::{
Paragraph, ParagraphSource, ParagraphStrType, ParagraphVecLong, ParagraphVecShort,
Paragraphs, VecExt,
Paragraph, ParagraphSource, ParagraphVecLong, ParagraphVecShort, Paragraphs, VecExt,
},
ComponentExt, Empty, Timeout, TimeoutMsg,
},
@ -74,11 +73,9 @@ where
}
}
impl<S, T> ComponentMsgObj for ButtonPage<S, T>
impl<T> ComponentMsgObj for ButtonPage<T>
where
T: Component + Paginate,
S: AsRef<str>,
S: Clone,
{
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
@ -102,10 +99,9 @@ where
}
}
impl<F, T> ComponentMsgObj for QRCodePage<F, T>
impl<T> ComponentMsgObj for QRCodePage<T>
where
T: AsRef<str> + Clone,
F: Component,
T: Component,
{
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
@ -115,10 +111,7 @@ where
}
}
impl<T> ComponentMsgObj for PinEntry<T>
where
T: AsRef<str> + Clone,
{
impl ComponentMsgObj for PinEntry {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
PinEntryMsg::Confirmed => self.pin().try_into(),
@ -127,11 +120,7 @@ where
}
}
impl<T, const N: usize> ComponentMsgObj for SimpleChoice<T, N>
where
T: AsRef<str>,
T: Clone,
{
impl<const N: usize> ComponentMsgObj for SimpleChoice<N> {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
SimpleChoiceMsg::Result(choice) => choice.as_str().try_into(),
@ -156,29 +145,22 @@ impl ComponentMsgObj for PassphraseEntry {
}
}
impl<T, U> ComponentMsgObj for Frame<T, U>
impl<T> ComponentMsgObj for Frame<T>
where
T: ComponentMsgObj,
U: AsRef<str>,
{
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
self.inner().msg_try_into_obj(msg)
}
}
impl<T> ComponentMsgObj for Progress<T>
where
T: ParagraphStrType,
{
impl ComponentMsgObj for Progress {
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
unreachable!()
}
}
impl<T> ComponentMsgObj for Homescreen<T>
where
T: AsRef<str>,
{
impl ComponentMsgObj for Homescreen {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
HomescreenMsg::Dismissed => Ok(CANCELLED.as_obj()),
@ -186,10 +168,7 @@ where
}
}
impl<T> ComponentMsgObj for Lockscreen<T>
where
T: AsRef<str>,
{
impl ComponentMsgObj for Lockscreen {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
HomescreenMsg::Dismissed => Ok(CANCELLED.as_obj()),
@ -250,7 +229,7 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
confirm_btn = confirm_btn.map(|btn| btn.with_default_duration());
}
let content = ButtonPage::new_str_buf(paragraphs, theme::BG)
let content = ButtonPage::new(paragraphs, theme::BG)
.with_cancel_btn(cancel_btn)
.with_confirm_btn(confirm_btn);
@ -292,9 +271,9 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
}
}
let mut content = ButtonPage::new_str(paragraphs.into_paragraphs(), theme::BG);
let mut content = ButtonPage::new(paragraphs.into_paragraphs(), theme::BG);
if hold {
let confirm_btn = Some(ButtonDetails::text("CONFIRM").with_default_duration());
let confirm_btn = Some(ButtonDetails::text("CONFIRM".into()).with_default_duration());
content = content.with_confirm_btn(confirm_btn);
}
let obj = LayoutObj::new(Frame::new(title, content))?;
@ -306,9 +285,6 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| {
let address: StrBuffer = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?;
// Getting this from micropython so it is also a `StrBuffer`, not having
// to handle the string operation in Rust, which would make it a `String`
// (which would them cause issues with general `T: AsRef<str>` parameter)
let truncated_address: StrBuffer =
kwargs.get(Qstr::MP_QSTR_truncated_address)?.try_into()?;
let amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount)?.try_into()?;
@ -322,7 +298,7 @@ extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut M
let btn_layout = ButtonLayout::new(
Some(ButtonDetails::cancel_icon()),
None,
Some(ButtonDetails::text("CONTINUE")),
Some(ButtonDetails::text("CONTINUE".into())),
);
let btn_actions = ButtonActions::cancel_next();
Page::<20>::new(btn_layout, btn_actions, Font::MONO).icon_label_text(
@ -336,7 +312,7 @@ extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut M
let btn_layout = ButtonLayout::new(
Some(ButtonDetails::cancel_icon()),
None,
Some(ButtonDetails::text("HOLD TO CONFIRM").with_default_duration()),
Some(ButtonDetails::text("HOLD TO CONFIRM".into()).with_default_duration()),
);
let btn_actions = ButtonActions::cancel_confirm();
Page::<20>::new(btn_layout, btn_actions, Font::MONO)
@ -377,7 +353,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
let btn_layout = ButtonLayout::new(
Some(ButtonDetails::cancel_icon()),
None,
Some(ButtonDetails::text("HOLD TO SEND").with_default_duration()),
Some(ButtonDetails::text("HOLD TO SEND".into()).with_default_duration()),
);
let btn_actions = ButtonActions::cancel_confirm();
@ -461,7 +437,7 @@ extern "C" fn new_show_info(n_args: usize, args: *const Obj, kwargs: *mut Map) -
fn tutorial_screen(
title: StrBuffer,
text: StrBuffer,
btn_layout: ButtonLayout<&'static str>,
btn_layout: ButtonLayout,
btn_actions: ButtonActions,
) -> Page<10> {
let mut page = Page::<10>::new(
@ -513,7 +489,7 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
tutorial_screen(
"HOLD TO CONFIRM".into(),
"Press and hold right to approve important operations.".into(),
ButtonLayout::back_and_htc_text("HOLD TO CONFIRM", Duration::from_millis(1000)),
ButtonLayout::back_and_htc_text("HOLD TO CONFIRM".into(), Duration::from_millis(1000)),
ButtonActions::prev_next(),
)
},
@ -521,7 +497,7 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
tutorial_screen(
"SCREEN SCROLL".into(),
"Press right to scroll down to read all content when text\ndoesn't fit on one screen. Press left to scroll up.".into(),
ButtonLayout::back_and_text("GOT IT"),
ButtonLayout::back_and_text("GOT IT".into()),
ButtonActions::prev_next(),
)
},
@ -529,14 +505,14 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
tutorial_screen(
"CONFIRM".into(),
"Press both left and right at the same time to confirm.".into(),
ButtonLayout::middle_armed_text("CONFIRM"),
ButtonLayout::middle_armed_text("CONFIRM".into()),
ButtonActions::prev_next_with_middle(),
)
},
// This page is special
5 => {
Page::<10>::new(
ButtonLayout::left_right_text("AGAIN", "FINISH"),
ButtonLayout::left_right_text("AGAIN".into(), "FINISH".into()),
ButtonActions::beginning_confirm(),
Font::MONO,
)
@ -551,7 +527,7 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
tutorial_screen(
"SKIP TUTORIAL".into(),
"Are you sure you want to skip the tutorial?".into(),
ButtonLayout::cancel_and_text("SKIP"),
ButtonLayout::cancel_and_text("SKIP".into()),
ButtonActions::beginning_cancel(),
)
},
@ -585,11 +561,11 @@ extern "C" fn new_show_share_words(n_args: usize, args: *const Obj, kwargs: *mut
let share_words_obj: Obj = kwargs.get(Qstr::MP_QSTR_share_words)?;
let share_words: Vec<StrBuffer, 24> = iter_into_vec(share_words_obj)?;
let confirm_btn = Some(ButtonDetails::text("HOLD TO CONFIRM").with_default_duration());
let confirm_btn =
Some(ButtonDetails::text("HOLD TO CONFIRM".into()).with_default_duration());
let obj = LayoutObj::new(
ButtonPage::new_str(ShareWords::new(share_words), theme::BG)
.with_confirm_btn(confirm_btn),
ButtonPage::new(ShareWords::new(share_words), theme::BG).with_confirm_btn(confirm_btn),
)?;
Ok(obj.into())
};
@ -615,7 +591,9 @@ extern "C" fn new_request_word_count(n_args: usize, args: *const Obj, kwargs: *m
let block = |_args: &[Obj], kwargs: &Map| {
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let choices: Vec<&str, 3> = ["12", "18", "24"].into_iter().collect();
let choices: Vec<StrBuffer, 3> = ["12".into(), "18".into(), "24".into()]
.into_iter()
.collect();
let obj = LayoutObj::new(Frame::new(title, SimpleChoice::new(choices, false, false)))?;
Ok(obj.into())