mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-23 15:08:19 +00:00
WIP - replacing T: AsRef<str> by StrBuffer
This commit is contained in:
parent
e5c52da136
commit
96c10e9b42
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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(),
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
@ -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())
|
||||
|
Loading…
Reference in New Issue
Block a user