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")]
|
#[cfg(feature = "model_tr")]
|
||||||
impl<T: Clone + AsRef<str>> ButtonDetails<T> {
|
impl ButtonDetails {
|
||||||
pub fn print(&self) {
|
pub fn print(&self) {
|
||||||
let text: String<20> = if let Some(text) = self.text.clone() {
|
let text: String<20> = if let Some(text) = self.text.clone() {
|
||||||
text.as_ref().into()
|
text.as_ref().into()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
micropython::buffer::StrBuffer,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
ui::{
|
ui::{
|
||||||
component::{Component, Event, EventCtx},
|
component::{Component, Event, EventCtx},
|
||||||
@ -27,16 +28,16 @@ pub enum ButtonPos {
|
|||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Button<T> {
|
pub struct Button {
|
||||||
bounds: Rect,
|
bounds: Rect,
|
||||||
pos: ButtonPos,
|
pos: ButtonPos,
|
||||||
content: ButtonContent<T>,
|
content: ButtonContent,
|
||||||
styles: ButtonStyleSheet,
|
styles: ButtonStyleSheet,
|
||||||
state: State,
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsRef<str>> Button<T> {
|
impl Button {
|
||||||
pub fn new(pos: ButtonPos, content: ButtonContent<T>, styles: ButtonStyleSheet) -> Self {
|
pub fn new(pos: ButtonPos, content: ButtonContent, styles: ButtonStyleSheet) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pos,
|
pos,
|
||||||
content,
|
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)
|
Self::new(pos, ButtonContent::Text(text), styles)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ impl<T: AsRef<str>> Button<T> {
|
|||||||
Self::new(pos, ButtonContent::Icon(image), styles)
|
Self::new(pos, ButtonContent::Icon(image), styles)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn content(&self) -> &ButtonContent<T> {
|
pub fn content(&self) -> &ButtonContent {
|
||||||
&self.content
|
&self.content
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ impl<T: AsRef<str>> Button<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Changing the text content of the button.
|
/// 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);
|
self.content = ButtonContent::Text(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,10 +168,7 @@ impl<T: AsRef<str>> Button<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Component for Button<T>
|
impl Component for Button {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
type Msg = ButtonMsg;
|
type Msg = ButtonMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -265,10 +263,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for Button<T>
|
impl crate::trace::Trace for Button {
|
||||||
where
|
|
||||||
T: AsRef<str> + crate::trace::Trace,
|
|
||||||
{
|
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.open("Button");
|
t.open("Button");
|
||||||
match &self.content {
|
match &self.content {
|
||||||
@ -285,8 +280,8 @@ enum State {
|
|||||||
Pressed,
|
Pressed,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ButtonContent<T> {
|
pub enum ButtonContent {
|
||||||
Text(T),
|
Text(StrBuffer),
|
||||||
Icon(Icon),
|
Icon(Icon),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,9 +348,9 @@ impl ButtonStyleSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Describing the button on the screen - only visuals.
|
/// Describing the button on the screen - only visuals.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone)]
|
||||||
pub struct ButtonDetails<T> {
|
pub struct ButtonDetails {
|
||||||
pub text: Option<T>,
|
pub text: Option<StrBuffer>,
|
||||||
pub icon: Option<Icon>,
|
pub icon: Option<Icon>,
|
||||||
pub duration: Option<Duration>,
|
pub duration: Option<Duration>,
|
||||||
pub with_outline: bool,
|
pub with_outline: bool,
|
||||||
@ -364,9 +359,9 @@ pub struct ButtonDetails<T> {
|
|||||||
pub offset: Option<Offset>,
|
pub offset: Option<Offset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + AsRef<str>> ButtonDetails<T> {
|
impl ButtonDetails {
|
||||||
/// Text button.
|
/// Text button.
|
||||||
pub fn text(text: T) -> Self {
|
pub fn text(text: StrBuffer) -> Self {
|
||||||
Self {
|
Self {
|
||||||
text: Some(text),
|
text: Some(text),
|
||||||
icon: None,
|
icon: None,
|
||||||
@ -392,7 +387,7 @@ impl<T: Clone + AsRef<str>> ButtonDetails<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Text with arms signalling double press.
|
/// 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()
|
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.
|
/// Holding the button details for all three possible buttons.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ButtonLayout<T> {
|
pub struct ButtonLayout {
|
||||||
pub btn_left: Option<ButtonDetails<T>>,
|
pub btn_left: Option<ButtonDetails>,
|
||||||
pub btn_middle: Option<ButtonDetails<T>>,
|
pub btn_middle: Option<ButtonDetails>,
|
||||||
pub btn_right: Option<ButtonDetails<T>>,
|
pub btn_right: Option<ButtonDetails>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsRef<str>> ButtonLayout<T> {
|
impl ButtonLayout {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
btn_left: Option<ButtonDetails<T>>,
|
btn_left: Option<ButtonDetails>,
|
||||||
btn_middle: Option<ButtonDetails<T>>,
|
btn_middle: Option<ButtonDetails>,
|
||||||
btn_right: Option<ButtonDetails<T>>,
|
btn_right: Option<ButtonDetails>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
btn_left,
|
btn_left,
|
||||||
@ -513,16 +508,14 @@ impl<T: AsRef<str>> ButtonLayout<T> {
|
|||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self::new(None, None, None)
|
Self::new(None, None, None)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ButtonLayout<&'static str> {
|
|
||||||
/// Default button layout for all three buttons - icons.
|
/// Default button layout for all three buttons - icons.
|
||||||
pub fn default_three_icons() -> Self {
|
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.
|
/// 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(
|
Self::new(
|
||||||
Some(ButtonDetails::left_arrow_icon()),
|
Some(ButtonDetails::left_arrow_icon()),
|
||||||
Some(ButtonDetails::armed_text(middle_text)),
|
Some(ButtonDetails::armed_text(middle_text)),
|
||||||
@ -531,7 +524,7 @@ impl ButtonLayout<&'static str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Left and right texts.
|
/// 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(
|
Self::new(
|
||||||
Some(ButtonDetails::text(text_left)),
|
Some(ButtonDetails::text(text_left)),
|
||||||
None,
|
None,
|
||||||
@ -540,7 +533,7 @@ impl ButtonLayout<&'static str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Only right text.
|
/// 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)))
|
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.
|
/// 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(
|
Self::new(
|
||||||
Some(ButtonDetails::cancel_icon()),
|
Some(ButtonDetails::cancel_icon()),
|
||||||
None,
|
None,
|
||||||
@ -581,7 +574,7 @@ impl ButtonLayout<&'static str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Cancel cross on left and hold-to-confirm text on the right.
|
/// 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(
|
Self::new(
|
||||||
Some(ButtonDetails::cancel_icon()),
|
Some(ButtonDetails::cancel_icon()),
|
||||||
None,
|
None,
|
||||||
@ -590,7 +583,7 @@ impl ButtonLayout<&'static str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Arrow back on left and hold-to-confirm text on the right.
|
/// 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(
|
Self::new(
|
||||||
Some(ButtonDetails::left_arrow_icon()),
|
Some(ButtonDetails::left_arrow_icon()),
|
||||||
None,
|
None,
|
||||||
@ -599,7 +592,7 @@ impl ButtonLayout<&'static str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Arrow back on left and text on the right.
|
/// 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(
|
Self::new(
|
||||||
Some(ButtonDetails::left_arrow_icon()),
|
Some(ButtonDetails::left_arrow_icon()),
|
||||||
None,
|
None,
|
||||||
@ -608,12 +601,12 @@ impl ButtonLayout<&'static str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Only armed text in the middle.
|
/// 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)
|
Self::new(None, Some(ButtonDetails::armed_text(text)), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Only hold-to-confirm with text on the right.
|
/// 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(
|
Self::new(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
@ -628,10 +621,7 @@ impl ButtonLayout<&'static str> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for ButtonDetails<T>
|
impl crate::trace::Trace for ButtonDetails {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.open("ButtonDetails");
|
t.open("ButtonDetails");
|
||||||
let mut btn_text: String<30> = String::new();
|
let mut btn_text: String<30> = String::new();
|
||||||
|
@ -46,18 +46,14 @@ pub enum ButtonControllerMsg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Defines what kind of button should be currently used.
|
/// Defines what kind of button should be currently used.
|
||||||
pub enum ButtonType<T> {
|
pub enum ButtonType {
|
||||||
Button(Button<T>),
|
Button(Button),
|
||||||
HoldToConfirm(HoldToConfirm<T>),
|
HoldToConfirm(HoldToConfirm),
|
||||||
Nothing,
|
Nothing,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ButtonType<T>
|
impl ButtonType {
|
||||||
where
|
pub fn from_button_details(pos: ButtonPos, btn_details: Option<ButtonDetails>) -> Self {
|
||||||
T: AsRef<str>,
|
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
pub fn from_button_details(pos: ButtonPos, btn_details: Option<ButtonDetails<T>>) -> Self {
|
|
||||||
if let Some(btn_details) = btn_details {
|
if let Some(btn_details) = btn_details {
|
||||||
if btn_details.duration.is_some() {
|
if btn_details.duration.is_some() {
|
||||||
Self::HoldToConfirm(Self::get_hold_to_confirm(pos, btn_details))
|
Self::HoldToConfirm(Self::get_hold_to_confirm(pos, btn_details))
|
||||||
@ -70,7 +66,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create `Button` component from `btn_details`.
|
/// 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
|
// Deciding between text and icon
|
||||||
if let Some(text) = btn_details.clone().text {
|
if let Some(text) = btn_details.clone().text {
|
||||||
Button::with_text(pos, text, btn_details.style())
|
Button::with_text(pos, text, btn_details.style())
|
||||||
@ -82,7 +78,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create `HoldToConfirm` component from `btn_details`.
|
/// 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
|
let duration = btn_details
|
||||||
.duration
|
.duration
|
||||||
.unwrap_or_else(|| Duration::from_millis(1000));
|
.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.
|
/// Users have a choice of a normal button or Hold-to-confirm button.
|
||||||
/// `button_type` specified what from those two is used, if anything.
|
/// `button_type` specified what from those two is used, if anything.
|
||||||
pub struct ButtonContainer<T> {
|
pub struct ButtonContainer {
|
||||||
pos: ButtonPos,
|
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
|
/// Supplying `None` as `btn_details` marks the button inactive
|
||||||
/// (it can be later activated in `set()`).
|
/// (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 {
|
Self {
|
||||||
pos,
|
pos,
|
||||||
button_type: ButtonType::from_button_details(pos, btn_details),
|
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.
|
/// Changing the state of the button.
|
||||||
///
|
///
|
||||||
/// Passing `None` as `btn_details` will mark the button as inactive.
|
/// 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 = ButtonType::from_button_details(self.pos, btn_details);
|
||||||
self.button_type.place(button_area);
|
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`,
|
/// Only "final" button events are returned in `ButtonControllerMsg::Triggered`,
|
||||||
/// based upon the buttons being long-press or not.
|
/// based upon the buttons being long-press or not.
|
||||||
pub struct ButtonController<T> {
|
pub struct ButtonController {
|
||||||
pad: Pad,
|
pad: Pad,
|
||||||
left_btn: ButtonContainer<T>,
|
left_btn: ButtonContainer,
|
||||||
middle_btn: ButtonContainer<T>,
|
middle_btn: ButtonContainer,
|
||||||
right_btn: ButtonContainer<T>,
|
right_btn: ButtonContainer,
|
||||||
state: ButtonState,
|
state: ButtonState,
|
||||||
// Button area is needed so the buttons
|
// Button area is needed so the buttons
|
||||||
// can be "re-placed" after their text is changed
|
// can be "re-placed" after their text is changed
|
||||||
@ -217,8 +213,8 @@ pub struct ButtonController<T> {
|
|||||||
button_area: Rect,
|
button_area: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + AsRef<str>> ButtonController<T> {
|
impl ButtonController {
|
||||||
pub fn new(btn_layout: ButtonLayout<T>) -> Self {
|
pub fn new(btn_layout: ButtonLayout) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pad: Pad::with_background(theme::BG).with_clear(),
|
pad: Pad::with_background(theme::BG).with_clear(),
|
||||||
left_btn: ButtonContainer::new(ButtonPos::Left, btn_layout.btn_left),
|
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.
|
/// 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.pad.clear();
|
||||||
self.left_btn.set(btn_layout.btn_left, self.button_area);
|
self.left_btn.set(btn_layout.btn_left, self.button_area);
|
||||||
self.middle_btn.set(btn_layout.btn_middle, 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;
|
type Msg = ButtonControllerMsg;
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
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;
|
use super::ButtonContent;
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for ButtonContainer<T>
|
impl crate::trace::Trace for ButtonContainer {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.open("ButtonContainer");
|
t.open("ButtonContainer");
|
||||||
|
|
||||||
@ -477,10 +470,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for ButtonController<T>
|
impl crate::trace::Trace for ButtonController {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.open("ButtonController");
|
t.open("ButtonController");
|
||||||
t.field("left_btn", &self.left_btn);
|
t.field("left_btn", &self.left_btn);
|
||||||
|
@ -24,7 +24,7 @@ pub struct Flow<F, const M: usize> {
|
|||||||
content_area: Rect,
|
content_area: Rect,
|
||||||
title_area: Rect,
|
title_area: Rect,
|
||||||
pad: Pad,
|
pad: Pad,
|
||||||
buttons: Child<ButtonController<&'static str>>,
|
buttons: Child<ButtonController>,
|
||||||
page_counter: u8,
|
page_counter: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ where
|
|||||||
pub struct Page<const M: usize> {
|
pub struct Page<const M: usize> {
|
||||||
ops: Vec<Op, M>,
|
ops: Vec<Op, M>,
|
||||||
text_layout: TextLayout,
|
text_layout: TextLayout,
|
||||||
btn_layout: ButtonLayout<&'static str>,
|
btn_layout: ButtonLayout,
|
||||||
btn_actions: ButtonActions,
|
btn_actions: ButtonActions,
|
||||||
current_page: usize,
|
current_page: usize,
|
||||||
page_count: usize,
|
page_count: usize,
|
||||||
@ -68,7 +68,7 @@ pub struct Page<const M: usize> {
|
|||||||
// For `layout.rs`
|
// For `layout.rs`
|
||||||
impl<const M: usize> Page<M> {
|
impl<const M: usize> Page<M> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
btn_layout: ButtonLayout<&'static str>,
|
btn_layout: ButtonLayout,
|
||||||
btn_actions: ButtonActions,
|
btn_actions: ButtonActions,
|
||||||
initial_text_font: Font,
|
initial_text_font: Font,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -99,7 +99,7 @@ impl<const M: usize> Page<M> {
|
|||||||
self.layout_content(&mut TextRenderer);
|
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,
|
// When we are in pagination inside this flow,
|
||||||
// show the up and down arrows on appropriate sides.
|
// show the up and down arrows on appropriate sides.
|
||||||
let current = self.btn_layout.clone();
|
let current = self.btn_layout.clone();
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
use super::{common, theme, ScrollBar};
|
use super::{common, theme, ScrollBar};
|
||||||
use crate::ui::{
|
use crate::{
|
||||||
component::{Child, Component, Event, EventCtx},
|
micropython::buffer::StrBuffer,
|
||||||
geometry::{Insets, Rect},
|
ui::{
|
||||||
|
component::{Child, Component, Event, EventCtx},
|
||||||
|
geometry::{Insets, Rect},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Component for holding another component and displaying a title.
|
/// Component for holding another component and displaying a title.
|
||||||
/// Also is allocating space for a scrollbar.
|
/// Also is allocating space for a scrollbar.
|
||||||
pub struct Frame<T, U> {
|
pub struct Frame<T> {
|
||||||
area: Rect,
|
area: Rect,
|
||||||
title: U,
|
title: StrBuffer,
|
||||||
title_centered: bool,
|
title_centered: bool,
|
||||||
account_for_scrollbar: bool,
|
account_for_scrollbar: bool,
|
||||||
content: Child<T>,
|
content: Child<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> Frame<T, U>
|
impl<T> Frame<T>
|
||||||
where
|
where
|
||||||
T: Component,
|
T: Component,
|
||||||
U: AsRef<str>,
|
|
||||||
{
|
{
|
||||||
pub fn new(title: U, content: T) -> Self {
|
pub fn new(title: StrBuffer, content: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
title,
|
title,
|
||||||
area: Rect::zero(),
|
area: Rect::zero(),
|
||||||
@ -51,10 +53,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> Component for Frame<T, U>
|
impl<T> Component for Frame<T>
|
||||||
where
|
where
|
||||||
T: Component,
|
T: Component,
|
||||||
U: AsRef<str>,
|
|
||||||
{
|
{
|
||||||
type Msg = T::Msg;
|
type Msg = T::Msg;
|
||||||
|
|
||||||
@ -96,10 +97,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T, U> crate::trace::Trace for Frame<T, U>
|
impl<T> crate::trace::Trace for Frame<T>
|
||||||
where
|
where
|
||||||
T: crate::trace::Trace,
|
T: crate::trace::Trace,
|
||||||
U: crate::trace::Trace + AsRef<str>,
|
|
||||||
{
|
{
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.open("Frame");
|
t.open("Frame");
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
micropython::buffer::StrBuffer,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
ui::{
|
ui::{
|
||||||
component::{Component, Event, EventCtx},
|
component::{Component, Event, EventCtx},
|
||||||
@ -13,15 +14,20 @@ pub enum HoldToConfirmMsg {
|
|||||||
FailedToConfirm,
|
FailedToConfirm,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HoldToConfirm<T> {
|
pub struct HoldToConfirm {
|
||||||
area: Rect,
|
area: Rect,
|
||||||
pos: ButtonPos,
|
pos: ButtonPos,
|
||||||
loader: Loader<T>,
|
loader: Loader,
|
||||||
text_width: i16,
|
text_width: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsRef<str>> HoldToConfirm<T> {
|
impl HoldToConfirm {
|
||||||
pub fn text(pos: ButtonPos, text: T, styles: LoaderStyleSheet, duration: Duration) -> Self {
|
pub fn text(
|
||||||
|
pos: ButtonPos,
|
||||||
|
text: StrBuffer,
|
||||||
|
styles: LoaderStyleSheet,
|
||||||
|
duration: Duration,
|
||||||
|
) -> Self {
|
||||||
let text_width = styles.normal.font.text_width(text.as_ref());
|
let text_width = styles.normal.font.text_width(text.as_ref());
|
||||||
Self {
|
Self {
|
||||||
area: Rect::zero(),
|
area: Rect::zero(),
|
||||||
@ -32,8 +38,8 @@ impl<T: AsRef<str>> HoldToConfirm<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Updating the text of the component and re-placing it.
|
/// Updating the text of the component and re-placing it.
|
||||||
pub fn set_text(&mut self, text: T, button_area: Rect) {
|
pub fn set_text(&mut self, text: StrBuffer, button_area: Rect) {
|
||||||
self.text_width = self.loader.get_text_width(&text) as i16;
|
self.text_width = self.loader.get_text_width(text.clone()) as i16;
|
||||||
self.loader.set_text(text);
|
self.loader.set_text(text);
|
||||||
self.place(button_area);
|
self.place(button_area);
|
||||||
}
|
}
|
||||||
@ -50,7 +56,7 @@ impl<T: AsRef<str>> HoldToConfirm<T> {
|
|||||||
self.loader.get_duration()
|
self.loader.get_duration()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_text(&self) -> &T {
|
pub fn get_text(&self) -> &StrBuffer {
|
||||||
self.loader.get_text()
|
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;
|
type Msg = HoldToConfirmMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -103,7 +109,7 @@ impl<T: AsRef<str>> Component for HoldToConfirm<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[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) {
|
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||||
d.open("HoldToConfirm");
|
d.open("HoldToConfirm");
|
||||||
self.loader.trace(d);
|
self.loader.trace(d);
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use crate::ui::{
|
use crate::{
|
||||||
component::{Component, Event, EventCtx, Pad},
|
micropython::buffer::StrBuffer,
|
||||||
display::Font,
|
ui::{
|
||||||
event::{ButtonEvent, USBEvent},
|
component::{Component, Event, EventCtx, Pad},
|
||||||
geometry::{Offset, Point, Rect},
|
display::Font,
|
||||||
model_tr::constant,
|
event::{ButtonEvent, USBEvent},
|
||||||
|
geometry::{Offset, Point, Rect},
|
||||||
|
model_tr::constant,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{common::display_center, theme};
|
use super::{common::display_center, theme};
|
||||||
@ -14,9 +17,9 @@ const LABEL_Y: i16 = 62;
|
|||||||
const LOCKED_Y: i16 = 32;
|
const LOCKED_Y: i16 = 32;
|
||||||
const TAP_Y: i16 = 47;
|
const TAP_Y: i16 = 47;
|
||||||
|
|
||||||
pub struct Homescreen<T> {
|
pub struct Homescreen {
|
||||||
label: T,
|
label: StrBuffer,
|
||||||
notification: Option<(T, u8)>,
|
notification: Option<(StrBuffer, u8)>,
|
||||||
usb_connected: bool,
|
usb_connected: bool,
|
||||||
pad: Pad,
|
pad: Pad,
|
||||||
}
|
}
|
||||||
@ -25,11 +28,8 @@ pub enum HomescreenMsg {
|
|||||||
Dismissed,
|
Dismissed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Homescreen<T>
|
impl Homescreen {
|
||||||
where
|
pub fn new(label: StrBuffer, notification: Option<(StrBuffer, u8)>) -> Self {
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
pub fn new(label: T, notification: Option<(T, u8)>) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
label,
|
label,
|
||||||
notification,
|
notification,
|
||||||
@ -57,10 +57,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Component for Homescreen<T>
|
impl Component for Homescreen {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
type Msg = HomescreenMsg;
|
type Msg = HomescreenMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -89,7 +86,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[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) {
|
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||||
d.open("Homescreen");
|
d.open("Homescreen");
|
||||||
d.kw_pair("active_page", "0");
|
d.kw_pair("active_page", "0");
|
||||||
@ -99,21 +96,18 @@ impl<T: AsRef<str>> crate::trace::Trace for Homescreen<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Lockscreen<T> {
|
pub struct Lockscreen {
|
||||||
label: T,
|
label: StrBuffer,
|
||||||
bootscreen: bool,
|
bootscreen: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Lockscreen<T> {
|
impl Lockscreen {
|
||||||
pub fn new(label: T, bootscreen: bool) -> Self {
|
pub fn new(label: StrBuffer, bootscreen: bool) -> Self {
|
||||||
Lockscreen { label, bootscreen }
|
Lockscreen { label, bootscreen }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Component for Lockscreen<T>
|
impl Component for Lockscreen {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
type Msg = HomescreenMsg;
|
type Msg = HomescreenMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -144,10 +138,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for Lockscreen<T>
|
impl crate::trace::Trace for Lockscreen {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||||
d.open("Lockscreen");
|
d.open("Lockscreen");
|
||||||
d.field("label", &self.label.as_ref());
|
d.field("label", &self.label.as_ref());
|
||||||
|
@ -58,8 +58,11 @@ impl ChoiceFactory for ChoiceFactoryBIP39 {
|
|||||||
match self {
|
match self {
|
||||||
Self::Letters(letter_choices) => {
|
Self::Letters(letter_choices) => {
|
||||||
if choice_index >= letter_choices.len() as u8 {
|
if choice_index >= letter_choices.len() as u8 {
|
||||||
ChoiceItem::new("DELETE", ButtonLayout::three_icons_middle_text("CONFIRM"))
|
ChoiceItem::new(
|
||||||
.with_icon(Icon::new(theme::ICON_DELETE))
|
"DELETE",
|
||||||
|
ButtonLayout::three_icons_middle_text("CONFIRM".into()),
|
||||||
|
)
|
||||||
|
.with_icon(Icon::new(theme::ICON_DELETE))
|
||||||
} else {
|
} else {
|
||||||
let letter = letter_choices[choice_index as usize];
|
let letter = letter_choices[choice_index as usize];
|
||||||
ChoiceItem::new(
|
ChoiceItem::new(
|
||||||
@ -70,9 +73,11 @@ impl ChoiceFactory for ChoiceFactoryBIP39 {
|
|||||||
}
|
}
|
||||||
Self::Words(word_choices) => {
|
Self::Words(word_choices) => {
|
||||||
if choice_index >= word_choices.len() as u8 {
|
if choice_index >= word_choices.len() as u8 {
|
||||||
let mut item =
|
let mut item = ChoiceItem::new(
|
||||||
ChoiceItem::new("DELETE", ButtonLayout::three_icons_middle_text("CONFIRM"))
|
"DELETE",
|
||||||
.with_icon(Icon::new(theme::ICON_DELETE));
|
ButtonLayout::three_icons_middle_text("CONFIRM".into()),
|
||||||
|
)
|
||||||
|
.with_icon(Icon::new(theme::ICON_DELETE));
|
||||||
item.set_right_btn(None);
|
item.set_right_btn(None);
|
||||||
item
|
item
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,7 +27,7 @@ pub trait Choice {
|
|||||||
fn paint_right(&self, _area: Rect, _show_incomplete: bool) -> Option<i16> {
|
fn paint_right(&self, _area: Rect, _show_incomplete: bool) -> Option<i16> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn btn_layout(&self) -> ButtonLayout<&'static str> {
|
fn btn_layout(&self) -> ButtonLayout {
|
||||||
ButtonLayout::default_three_icons()
|
ButtonLayout::default_three_icons()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ where
|
|||||||
{
|
{
|
||||||
choices: F,
|
choices: F,
|
||||||
pad: Pad,
|
pad: Pad,
|
||||||
buttons: Child<ButtonController<&'static str>>,
|
buttons: Child<ButtonController>,
|
||||||
page_counter: u8,
|
page_counter: u8,
|
||||||
/// How many pixels from top should we render the items.
|
/// How many pixels from top should we render the items.
|
||||||
y_baseline: i16,
|
y_baseline: i16,
|
||||||
|
@ -15,12 +15,12 @@ use super::super::{
|
|||||||
pub struct ChoiceItem {
|
pub struct ChoiceItem {
|
||||||
text: String<50>,
|
text: String<50>,
|
||||||
icon: Option<Icon>,
|
icon: Option<Icon>,
|
||||||
btn_layout: ButtonLayout<&'static str>,
|
btn_layout: ButtonLayout,
|
||||||
font: Font,
|
font: Font,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChoiceItem {
|
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
|
where
|
||||||
T: AsRef<str>,
|
T: AsRef<str>,
|
||||||
{
|
{
|
||||||
@ -105,17 +105,17 @@ impl ChoiceItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Setting left button.
|
/// 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;
|
self.btn_layout.btn_left = btn_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Setting middle button.
|
/// 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;
|
self.btn_layout.btn_middle = btn_middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Setting right button.
|
/// 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;
|
self.btn_layout.btn_right = btn_right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ impl Choice for ChoiceItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Getting current button layout.
|
/// Getting current button layout.
|
||||||
fn btn_layout(&self) -> ButtonLayout<&'static str> {
|
fn btn_layout(&self) -> ButtonLayout {
|
||||||
self.btn_layout.clone()
|
self.btn_layout.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,10 +111,14 @@ impl ChoiceFactoryPassphrase {
|
|||||||
// Including accept button on the left and cancel on the very right.
|
// Including accept button on the left and cancel on the very right.
|
||||||
// TODO: could have some icons instead of the shortcut text
|
// TODO: could have some icons instead of the shortcut text
|
||||||
if choice_index == 0 {
|
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 {
|
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.
|
// Including icons for some items.
|
||||||
@ -131,7 +135,10 @@ impl ChoiceFactoryPassphrase {
|
|||||||
/// return back
|
/// return back
|
||||||
fn get_character_item(&self, choice_index: u8) -> ChoiceItem {
|
fn get_character_item(&self, choice_index: u8) -> ChoiceItem {
|
||||||
if is_menu_choice(&self.current_category, choice_index) {
|
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 {
|
} else {
|
||||||
let ch = get_char(&self.current_category, choice_index);
|
let ch = get_char(&self.current_category, choice_index);
|
||||||
ChoiceItem::new(char_to_string::<1>(ch), ButtonLayout::default_three_icons())
|
ChoiceItem::new(char_to_string::<1>(ch), ButtonLayout::default_three_icons())
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
micropython::buffer::StrBuffer,
|
||||||
trezorhal::random,
|
trezorhal::random,
|
||||||
ui::{
|
ui::{
|
||||||
component::{text::common::TextBox, Child, Component, ComponentExt, Event, EventCtx},
|
component::{text::common::TextBox, Child, Component, ComponentExt, Event, EventCtx},
|
||||||
@ -48,7 +49,7 @@ impl ChoiceFactory for ChoiceFactoryPIN {
|
|||||||
|
|
||||||
// Action buttons have different middle button text
|
// Action buttons have different middle button text
|
||||||
if [DELETE_INDEX, SHOW_INDEX, ENTER_INDEX].contains(&(choice_index as usize)) {
|
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));
|
choice_item.set_middle_btn(Some(confirm_btn));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,20 +71,17 @@ impl ChoiceFactory for ChoiceFactoryPIN {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Component for entering a PIN.
|
/// Component for entering a PIN.
|
||||||
pub struct PinEntry<T> {
|
pub struct PinEntry {
|
||||||
choice_page: ChoicePage<ChoiceFactoryPIN>,
|
choice_page: ChoicePage<ChoiceFactoryPIN>,
|
||||||
pin_line: Child<ChangingTextLine<String<MAX_PIN_LENGTH>>>,
|
pin_line: Child<ChangingTextLine<String<MAX_PIN_LENGTH>>>,
|
||||||
subprompt_line: Child<ChangingTextLine<T>>,
|
subprompt_line: Child<ChangingTextLine<StrBuffer>>,
|
||||||
prompt: T,
|
prompt: StrBuffer,
|
||||||
show_real_pin: bool,
|
show_real_pin: bool,
|
||||||
textbox: TextBox<MAX_PIN_LENGTH>,
|
textbox: TextBox<MAX_PIN_LENGTH>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> PinEntry<T>
|
impl PinEntry {
|
||||||
where
|
pub fn new(prompt: StrBuffer, subprompt: StrBuffer) -> Self {
|
||||||
T: AsRef<str> + Clone,
|
|
||||||
{
|
|
||||||
pub fn new(prompt: T, subprompt: T) -> Self {
|
|
||||||
let choices = ChoiceFactoryPIN::new();
|
let choices = ChoiceFactoryPIN::new();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -158,10 +156,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Component for PinEntry<T>
|
impl Component for PinEntry {
|
||||||
where
|
|
||||||
T: AsRef<str> + Clone,
|
|
||||||
{
|
|
||||||
type Msg = PinEntryMsg;
|
type Msg = PinEntryMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -224,10 +219,7 @@ where
|
|||||||
use super::super::{ButtonAction, ButtonPos};
|
use super::super::{ButtonAction, ButtonPos};
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for PinEntry<T>
|
impl crate::trace::Trace for PinEntry {
|
||||||
where
|
|
||||||
T: AsRef<str> + Clone,
|
|
||||||
{
|
|
||||||
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
||||||
match pos {
|
match pos {
|
||||||
ButtonPos::Left => ButtonAction::PrevPage.string(),
|
ButtonPos::Left => ButtonAction::PrevPage.string(),
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::ui::{
|
use crate::{
|
||||||
component::{Component, Event, EventCtx},
|
micropython::buffer::StrBuffer,
|
||||||
geometry::Rect,
|
ui::{
|
||||||
|
component::{Component, Event, EventCtx},
|
||||||
|
geometry::Rect,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::super::{ButtonLayout, ChoiceFactory, ChoiceItem, ChoicePage, ChoicePageMsg};
|
use super::super::{ButtonLayout, ChoiceFactory, ChoiceItem, ChoicePage, ChoicePageMsg};
|
||||||
@ -13,24 +16,18 @@ pub enum SimpleChoiceMsg {
|
|||||||
Result(String<50>),
|
Result(String<50>),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChoiceFactorySimple<T, const N: usize> {
|
struct ChoiceFactorySimple<const N: usize> {
|
||||||
choices: Vec<T, N>,
|
choices: Vec<StrBuffer, N>,
|
||||||
carousel: bool,
|
carousel: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const N: usize> ChoiceFactorySimple<T, N>
|
impl<const N: usize> ChoiceFactorySimple<N> {
|
||||||
where
|
fn new(choices: Vec<StrBuffer, N>, carousel: bool) -> Self {
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn new(choices: Vec<T, N>, carousel: bool) -> Self {
|
|
||||||
Self { choices, carousel }
|
Self { choices, carousel }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const N: usize> ChoiceFactory for ChoiceFactorySimple<T, N>
|
impl<const N: usize> ChoiceFactory for ChoiceFactorySimple<N> {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
type Item = ChoiceItem;
|
type Item = ChoiceItem;
|
||||||
|
|
||||||
fn count(&self) -> u8 {
|
fn count(&self) -> u8 {
|
||||||
@ -58,21 +55,13 @@ where
|
|||||||
|
|
||||||
/// Simple wrapper around `ChoicePage` that allows for
|
/// Simple wrapper around `ChoicePage` that allows for
|
||||||
/// inputting a list of values and receiving the chosen one.
|
/// inputting a list of values and receiving the chosen one.
|
||||||
pub struct SimpleChoice<T, const N: usize>
|
pub struct SimpleChoice<const N: usize> {
|
||||||
where
|
choices: Vec<StrBuffer, N>,
|
||||||
T: AsRef<str>,
|
choice_page: ChoicePage<ChoiceFactorySimple<N>>,
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
choices: Vec<T, N>,
|
|
||||||
choice_page: ChoicePage<ChoiceFactorySimple<T, N>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const N: usize> SimpleChoice<T, N>
|
impl<const N: usize> SimpleChoice<N> {
|
||||||
where
|
pub fn new(str_choices: Vec<StrBuffer, N>, carousel: bool, show_incomplete: bool) -> Self {
|
||||||
T: AsRef<str>,
|
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
pub fn new(str_choices: Vec<T, N>, carousel: bool, show_incomplete: bool) -> Self {
|
|
||||||
let choices = ChoiceFactorySimple::new(str_choices.clone(), carousel);
|
let choices = ChoiceFactorySimple::new(str_choices.clone(), carousel);
|
||||||
Self {
|
Self {
|
||||||
choices: str_choices,
|
choices: str_choices,
|
||||||
@ -83,11 +72,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const N: usize> Component for SimpleChoice<T, N>
|
impl<const N: usize> Component for SimpleChoice<N> {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
type Msg = SimpleChoiceMsg;
|
type Msg = SimpleChoiceMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -111,11 +96,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T, const N: usize> crate::trace::Trace for SimpleChoice<T, N>
|
impl<const N: usize> crate::trace::Trace for SimpleChoice<N> {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
||||||
match pos {
|
match pos {
|
||||||
ButtonPos::Left => match self.choice_page.has_previous_choice() {
|
ButtonPos::Left => match self.choice_page.has_previous_choice() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
micropython::buffer::StrBuffer,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
ui::{
|
ui::{
|
||||||
animation::Animation,
|
animation::Animation,
|
||||||
@ -21,19 +22,19 @@ enum State {
|
|||||||
Grown,
|
Grown,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Loader<T> {
|
pub struct Loader {
|
||||||
area: Rect,
|
area: Rect,
|
||||||
state: State,
|
state: State,
|
||||||
growing_duration: Duration,
|
growing_duration: Duration,
|
||||||
shrinking_duration: Duration,
|
shrinking_duration: Duration,
|
||||||
text_overlay: display::TextOverlay<T>,
|
text_overlay: display::TextOverlay<StrBuffer>,
|
||||||
styles: LoaderStyleSheet,
|
styles: LoaderStyleSheet,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsRef<str>> Loader<T> {
|
impl Loader {
|
||||||
pub const SIZE: Offset = Offset::new(120, 120);
|
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 {
|
Self {
|
||||||
area: Rect::zero(),
|
area: Rect::zero(),
|
||||||
state: State::Initial,
|
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);
|
let text_overlay = display::TextOverlay::new(text, styles.normal.font);
|
||||||
|
|
||||||
Self::new(text_overlay, styles)
|
Self::new(text_overlay, styles)
|
||||||
@ -64,17 +65,17 @@ impl<T: AsRef<str>> Loader<T> {
|
|||||||
self.growing_duration
|
self.growing_duration
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_text(&self) -> &T {
|
pub fn get_text(&self) -> &StrBuffer {
|
||||||
self.text_overlay.get_text()
|
self.text_overlay.get_text()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the text of the loader.
|
/// 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);
|
self.text_overlay.set_text(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return width of given text according to current style.
|
/// 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())
|
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;
|
type Msg = LoaderMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -241,7 +242,7 @@ impl LoaderStyleSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[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) {
|
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||||
d.open("Loader");
|
d.open("Loader");
|
||||||
d.close();
|
d.close();
|
||||||
|
@ -1,70 +1,39 @@
|
|||||||
use crate::{
|
use crate::ui::{
|
||||||
micropython::buffer::StrBuffer,
|
component::{Child, Component, ComponentExt, Event, EventCtx, Pad, PageMsg, Paginate},
|
||||||
ui::{
|
display::Color,
|
||||||
component::{Child, Component, ComponentExt, Event, EventCtx, Pad, PageMsg, Paginate},
|
geometry::{Insets, Offset, Rect},
|
||||||
display::Color,
|
|
||||||
geometry::{Insets, Offset, Rect},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
theme, ButtonController, ButtonControllerMsg, ButtonDetails, ButtonLayout, ButtonPos, ScrollBar,
|
theme, ButtonController, ButtonControllerMsg, ButtonDetails, ButtonLayout, ButtonPos, ScrollBar,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ButtonPage<S, T> {
|
pub struct ButtonPage<T> {
|
||||||
content: Child<T>,
|
content: Child<T>,
|
||||||
scrollbar: Child<ScrollBar>,
|
scrollbar: Child<ScrollBar>,
|
||||||
/// Optional available area for scrollbar defined by parent component.
|
/// Optional available area for scrollbar defined by parent component.
|
||||||
parent_scrollbar_area: Option<Rect>,
|
parent_scrollbar_area: Option<Rect>,
|
||||||
pad: Pad,
|
pad: Pad,
|
||||||
/// Left button of the first screen
|
/// Left button of the first screen
|
||||||
cancel_btn_details: Option<ButtonDetails<S>>,
|
cancel_btn_details: Option<ButtonDetails>,
|
||||||
/// Right button of the last screen
|
/// Right button of the last screen
|
||||||
confirm_btn_details: Option<ButtonDetails<S>>,
|
confirm_btn_details: Option<ButtonDetails>,
|
||||||
/// Left button of the last page
|
/// 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
|
/// 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
|
/// Right button of every screen apart the last one
|
||||||
next_btn_details: Option<ButtonDetails<S>>,
|
next_btn_details: Option<ButtonDetails>,
|
||||||
buttons: Child<ButtonController<S>>,
|
buttons: Child<ButtonController>,
|
||||||
/// Scrollbar may or may not be shown (but will be counting pages anyway).
|
/// Scrollbar may or may not be shown (but will be counting pages anyway).
|
||||||
show_scrollbar: bool,
|
show_scrollbar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ButtonPage<&'static str, T>
|
impl<T> ButtonPage<T>
|
||||||
where
|
where
|
||||||
T: Paginate,
|
T: Component + Paginate,
|
||||||
T: Component,
|
|
||||||
{
|
{
|
||||||
/// Constructor for `&'static str` button-text type.
|
pub fn new(content: T, background: Color) -> Self {
|
||||||
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 {
|
|
||||||
Self {
|
Self {
|
||||||
content: Child::new(content),
|
content: Child::new(content),
|
||||||
scrollbar: Child::new(ScrollBar::to_be_filled_later()),
|
scrollbar: Child::new(ScrollBar::to_be_filled_later()),
|
||||||
@ -82,31 +51,23 @@ where
|
|||||||
show_scrollbar: true,
|
show_scrollbar: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, T> ButtonPage<S, T>
|
pub fn with_cancel_btn(mut self, btn_details: Option<ButtonDetails>) -> Self {
|
||||||
where
|
|
||||||
T: Paginate,
|
|
||||||
T: Component,
|
|
||||||
S: AsRef<str>,
|
|
||||||
S: Clone,
|
|
||||||
{
|
|
||||||
pub fn with_cancel_btn(mut self, btn_details: Option<ButtonDetails<S>>) -> Self {
|
|
||||||
self.cancel_btn_details = btn_details;
|
self.cancel_btn_details = btn_details;
|
||||||
self
|
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.confirm_btn_details = btn_details;
|
||||||
self
|
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.back_btn_details = btn_details;
|
||||||
self
|
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.next_btn_details = btn_details;
|
||||||
self
|
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_left = self.get_left_button_details(!has_prev, !has_next);
|
||||||
let btn_right = self.get_right_button_details(has_next);
|
let btn_right = self.get_right_button_details(has_next);
|
||||||
ButtonLayout::new(btn_left, None, btn_right)
|
ButtonLayout::new(btn_left, None, btn_right)
|
||||||
@ -155,7 +116,7 @@ where
|
|||||||
|
|
||||||
/// Get the let button details, depending whether the page is first, last,
|
/// Get the let button details, depending whether the page is first, last,
|
||||||
/// or in the middle.
|
/// 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 {
|
if is_first {
|
||||||
self.cancel_btn_details.clone()
|
self.cancel_btn_details.clone()
|
||||||
} else if is_last {
|
} else if is_last {
|
||||||
@ -167,7 +128,7 @@ where
|
|||||||
|
|
||||||
/// Get the right button details, depending on whether there is a next
|
/// Get the right button details, depending on whether there is a next
|
||||||
/// page.
|
/// 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 {
|
if has_next_page {
|
||||||
self.next_btn_details.clone()
|
self.next_btn_details.clone()
|
||||||
} else {
|
} else {
|
||||||
@ -176,12 +137,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, T> Component for ButtonPage<S, T>
|
impl<T> Component for ButtonPage<T>
|
||||||
where
|
where
|
||||||
S: Clone,
|
T: Component + Paginate,
|
||||||
S: AsRef<str>,
|
|
||||||
T: Component,
|
|
||||||
T: Paginate,
|
|
||||||
{
|
{
|
||||||
type Msg = PageMsg<T::Msg, bool>;
|
type Msg = PageMsg<T::Msg, bool>;
|
||||||
|
|
||||||
@ -278,10 +236,9 @@ use super::ButtonAction;
|
|||||||
use heapless::String;
|
use heapless::String;
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<S, T> crate::trace::Trace for ButtonPage<S, T>
|
impl<T> crate::trace::Trace for ButtonPage<T>
|
||||||
where
|
where
|
||||||
T: crate::trace::Trace,
|
T: crate::trace::Trace,
|
||||||
S: AsRef<str>,
|
|
||||||
{
|
{
|
||||||
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
||||||
match pos {
|
match pos {
|
||||||
|
@ -2,11 +2,12 @@ use core::mem;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
|
micropython::buffer::StrBuffer,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
base::ComponentExt,
|
base::ComponentExt,
|
||||||
paginated::Paginate,
|
paginated::Paginate,
|
||||||
text::paragraphs::{Paragraph, ParagraphStrType, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
Child, Component, Event, EventCtx, Label, Never, Pad,
|
Child, Component, Event, EventCtx, Label, Never, Pad,
|
||||||
},
|
},
|
||||||
display::{self, Font},
|
display::{self, Font},
|
||||||
@ -18,27 +19,24 @@ use crate::{
|
|||||||
|
|
||||||
use super::theme;
|
use super::theme;
|
||||||
|
|
||||||
pub struct Progress<T> {
|
pub struct Progress {
|
||||||
title: Child<Label<T>>,
|
title: Child<Label<StrBuffer>>,
|
||||||
value: u16,
|
value: u16,
|
||||||
loader_y_offset: i16,
|
loader_y_offset: i16,
|
||||||
indeterminate: bool,
|
indeterminate: bool,
|
||||||
description: Child<Paragraphs<Paragraph<T>>>,
|
description: Child<Paragraphs<Paragraph<StrBuffer>>>,
|
||||||
description_pad: Pad,
|
description_pad: Pad,
|
||||||
update_description: fn(&str) -> Result<T, Error>,
|
update_description: fn(&str) -> Result<StrBuffer, Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Progress<T>
|
impl Progress {
|
||||||
where
|
|
||||||
T: ParagraphStrType,
|
|
||||||
{
|
|
||||||
const AREA: Rect = constant::screen();
|
const AREA: Rect = constant::screen();
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
title: T,
|
title: StrBuffer,
|
||||||
indeterminate: bool,
|
indeterminate: bool,
|
||||||
description: T,
|
description: StrBuffer,
|
||||||
update_description: fn(&str) -> Result<T, Error>,
|
update_description: fn(&str) -> Result<StrBuffer, Error>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
title: Label::centered(title, theme::TEXT_HEADER).into_child(),
|
title: Label::centered(title, theme::TEXT_HEADER).into_child(),
|
||||||
@ -55,10 +53,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Component for Progress<T>
|
impl Component for Progress {
|
||||||
where
|
|
||||||
T: ParagraphStrType,
|
|
||||||
{
|
|
||||||
type Msg = Never;
|
type Msg = Never;
|
||||||
|
|
||||||
fn place(&mut self, _bounds: Rect) -> Rect {
|
fn place(&mut self, _bounds: Rect) -> Rect {
|
||||||
@ -126,10 +121,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<T> crate::trace::Trace for Progress<T>
|
impl crate::trace::Trace for Progress {
|
||||||
where
|
|
||||||
T: ParagraphStrType,
|
|
||||||
{
|
|
||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.open("Progress");
|
t.open("Progress");
|
||||||
t.close();
|
t.close();
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use crate::ui::{
|
use crate::{
|
||||||
component::{Child, Component, Event, EventCtx},
|
micropython::buffer::StrBuffer,
|
||||||
display::{self, Font},
|
ui::{
|
||||||
geometry::Rect,
|
component::{Child, Component, Event, EventCtx},
|
||||||
|
display::{self, Font},
|
||||||
|
geometry::Rect,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{theme, ButtonController, ButtonControllerMsg, ButtonLayout, ButtonPos};
|
use super::{theme, ButtonController, ButtonControllerMsg, ButtonLayout, ButtonPos};
|
||||||
@ -11,18 +14,15 @@ pub enum QRCodePageMessage {
|
|||||||
Cancelled,
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct QRCodePage<F, T> {
|
pub struct QRCodePage<T> {
|
||||||
title: T,
|
title: StrBuffer,
|
||||||
title_area: Rect,
|
title_area: Rect,
|
||||||
qr_code: F,
|
qr_code: T,
|
||||||
buttons: Child<ButtonController<T>>,
|
buttons: Child<ButtonController>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, T> QRCodePage<F, T>
|
impl<T> QRCodePage<T> {
|
||||||
where
|
pub fn new(title: StrBuffer, qr_code: T, btn_layout: ButtonLayout) -> Self {
|
||||||
T: AsRef<str> + Clone,
|
|
||||||
{
|
|
||||||
pub fn new(title: T, qr_code: F, btn_layout: ButtonLayout<T>) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
title,
|
title,
|
||||||
title_area: Rect::zero(),
|
title_area: Rect::zero(),
|
||||||
@ -32,10 +32,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, T> Component for QRCodePage<F, T>
|
impl<T> Component for QRCodePage<T>
|
||||||
where
|
where
|
||||||
T: AsRef<str> + Clone,
|
T: Component,
|
||||||
F: Component,
|
|
||||||
{
|
{
|
||||||
type Msg = QRCodePageMessage;
|
type Msg = QRCodePageMessage;
|
||||||
|
|
||||||
@ -86,10 +85,7 @@ use super::ButtonAction;
|
|||||||
use heapless::String;
|
use heapless::String;
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl<F, T> crate::trace::Trace for QRCodePage<F, T>
|
impl<T> crate::trace::Trace for QRCodePage<T> {
|
||||||
where
|
|
||||||
T: AsRef<str> + Clone,
|
|
||||||
{
|
|
||||||
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
fn get_btn_action(&self, pos: ButtonPos) -> String<25> {
|
||||||
match pos {
|
match pos {
|
||||||
ButtonPos::Left => ButtonAction::Cancel.string(),
|
ButtonPos::Left => ButtonAction::Cancel.string(),
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
micropython::buffer::StrBuffer,
|
||||||
time::Instant,
|
time::Instant,
|
||||||
ui::{
|
ui::{
|
||||||
component::{
|
component::{
|
||||||
text::paragraphs::{Paragraph, ParagraphStrType, Paragraphs},
|
text::paragraphs::{Paragraph, Paragraphs},
|
||||||
Child, Component, ComponentExt, Event, EventCtx, Label, Pad,
|
Child, Component, ComponentExt, Event, EventCtx, Label, Pad,
|
||||||
},
|
},
|
||||||
constant::screen,
|
constant::screen,
|
||||||
@ -20,14 +21,14 @@ pub enum ResultPopupMsg {
|
|||||||
Confirmed,
|
Confirmed,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ResultPopup<S> {
|
pub struct ResultPopup {
|
||||||
area: Rect,
|
area: Rect,
|
||||||
pad: Pad,
|
pad: Pad,
|
||||||
result_anim: Child<ResultAnim>,
|
result_anim: Child<ResultAnim>,
|
||||||
headline_baseline: Point,
|
headline_baseline: Point,
|
||||||
headline: Option<Label<&'static str>>,
|
headline: Option<Label<&'static str>>,
|
||||||
text: Child<Paragraphs<Paragraph<S>>>,
|
text: Child<Paragraphs<Paragraph<StrBuffer>>>,
|
||||||
buttons: Option<Child<ButtonController<&'static str>>>,
|
buttons: Option<Child<ButtonController>>,
|
||||||
autoclose: bool,
|
autoclose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,10 +38,10 @@ const ANIM_POS: i16 = 32;
|
|||||||
const ANIM_POS_ADJ_HEADLINE: i16 = 10;
|
const ANIM_POS_ADJ_HEADLINE: i16 = 10;
|
||||||
const ANIM_POS_ADJ_BUTTON: i16 = 6;
|
const ANIM_POS_ADJ_BUTTON: i16 = 6;
|
||||||
|
|
||||||
impl<S: ParagraphStrType> ResultPopup<S> {
|
impl ResultPopup {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
icon: &'static [u8],
|
icon: &'static [u8],
|
||||||
text: S,
|
text: StrBuffer,
|
||||||
headline: Option<&'static str>,
|
headline: Option<&'static str>,
|
||||||
button_text: Option<&'static str>,
|
button_text: Option<&'static str>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -48,7 +49,7 @@ impl<S: ParagraphStrType> ResultPopup<S> {
|
|||||||
.with_placement(LinearPlacement::vertical().align_at_center());
|
.with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
let buttons = button_text.map(|text| {
|
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))
|
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;
|
type Msg = ResultPopupMsg;
|
||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
@ -155,7 +156,7 @@ impl<S: ParagraphStrType> Component for ResultPopup<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[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) {
|
fn trace(&self, d: &mut dyn crate::trace::Tracer) {
|
||||||
d.open("ResultPopup");
|
d.open("ResultPopup");
|
||||||
self.text.trace(d);
|
self.text.trace(d);
|
||||||
|
@ -20,8 +20,7 @@ use crate::{
|
|||||||
paginated::{PageMsg, Paginate},
|
paginated::{PageMsg, Paginate},
|
||||||
painter,
|
painter,
|
||||||
text::paragraphs::{
|
text::paragraphs::{
|
||||||
Paragraph, ParagraphSource, ParagraphStrType, ParagraphVecLong, ParagraphVecShort,
|
Paragraph, ParagraphSource, ParagraphVecLong, ParagraphVecShort, Paragraphs, VecExt,
|
||||||
Paragraphs, VecExt,
|
|
||||||
},
|
},
|
||||||
ComponentExt, Empty, Timeout, TimeoutMsg,
|
ComponentExt, Empty, Timeout, TimeoutMsg,
|
||||||
},
|
},
|
||||||
@ -74,11 +73,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, T> ComponentMsgObj for ButtonPage<S, T>
|
impl<T> ComponentMsgObj for ButtonPage<T>
|
||||||
where
|
where
|
||||||
T: Component + Paginate,
|
T: Component + Paginate,
|
||||||
S: AsRef<str>,
|
|
||||||
S: Clone,
|
|
||||||
{
|
{
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
match msg {
|
match msg {
|
||||||
@ -102,10 +99,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, T> ComponentMsgObj for QRCodePage<F, T>
|
impl<T> ComponentMsgObj for QRCodePage<T>
|
||||||
where
|
where
|
||||||
T: AsRef<str> + Clone,
|
T: Component,
|
||||||
F: Component,
|
|
||||||
{
|
{
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
match msg {
|
match msg {
|
||||||
@ -115,10 +111,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ComponentMsgObj for PinEntry<T>
|
impl ComponentMsgObj for PinEntry {
|
||||||
where
|
|
||||||
T: AsRef<str> + Clone,
|
|
||||||
{
|
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
match msg {
|
match msg {
|
||||||
PinEntryMsg::Confirmed => self.pin().try_into(),
|
PinEntryMsg::Confirmed => self.pin().try_into(),
|
||||||
@ -127,11 +120,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, const N: usize> ComponentMsgObj for SimpleChoice<T, N>
|
impl<const N: usize> ComponentMsgObj for SimpleChoice<N> {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
T: Clone,
|
|
||||||
{
|
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
match msg {
|
match msg {
|
||||||
SimpleChoiceMsg::Result(choice) => choice.as_str().try_into(),
|
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
|
where
|
||||||
T: ComponentMsgObj,
|
T: ComponentMsgObj,
|
||||||
U: AsRef<str>,
|
|
||||||
{
|
{
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
self.inner().msg_try_into_obj(msg)
|
self.inner().msg_try_into_obj(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ComponentMsgObj for Progress<T>
|
impl ComponentMsgObj for Progress {
|
||||||
where
|
|
||||||
T: ParagraphStrType,
|
|
||||||
{
|
|
||||||
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ComponentMsgObj for Homescreen<T>
|
impl ComponentMsgObj for Homescreen {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
match msg {
|
match msg {
|
||||||
HomescreenMsg::Dismissed => Ok(CANCELLED.as_obj()),
|
HomescreenMsg::Dismissed => Ok(CANCELLED.as_obj()),
|
||||||
@ -186,10 +168,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ComponentMsgObj for Lockscreen<T>
|
impl ComponentMsgObj for Lockscreen {
|
||||||
where
|
|
||||||
T: AsRef<str>,
|
|
||||||
{
|
|
||||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||||
match msg {
|
match msg {
|
||||||
HomescreenMsg::Dismissed => Ok(CANCELLED.as_obj()),
|
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());
|
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_cancel_btn(cancel_btn)
|
||||||
.with_confirm_btn(confirm_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 {
|
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);
|
content = content.with_confirm_btn(confirm_btn);
|
||||||
}
|
}
|
||||||
let obj = LayoutObj::new(Frame::new(title, content))?;
|
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 {
|
extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||||
let block = |_args: &[Obj], kwargs: &Map| {
|
let block = |_args: &[Obj], kwargs: &Map| {
|
||||||
let address: StrBuffer = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?;
|
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 =
|
let truncated_address: StrBuffer =
|
||||||
kwargs.get(Qstr::MP_QSTR_truncated_address)?.try_into()?;
|
kwargs.get(Qstr::MP_QSTR_truncated_address)?.try_into()?;
|
||||||
let amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount)?.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(
|
let btn_layout = ButtonLayout::new(
|
||||||
Some(ButtonDetails::cancel_icon()),
|
Some(ButtonDetails::cancel_icon()),
|
||||||
None,
|
None,
|
||||||
Some(ButtonDetails::text("CONTINUE")),
|
Some(ButtonDetails::text("CONTINUE".into())),
|
||||||
);
|
);
|
||||||
let btn_actions = ButtonActions::cancel_next();
|
let btn_actions = ButtonActions::cancel_next();
|
||||||
Page::<20>::new(btn_layout, btn_actions, Font::MONO).icon_label_text(
|
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(
|
let btn_layout = ButtonLayout::new(
|
||||||
Some(ButtonDetails::cancel_icon()),
|
Some(ButtonDetails::cancel_icon()),
|
||||||
None,
|
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();
|
let btn_actions = ButtonActions::cancel_confirm();
|
||||||
Page::<20>::new(btn_layout, btn_actions, Font::MONO)
|
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(
|
let btn_layout = ButtonLayout::new(
|
||||||
Some(ButtonDetails::cancel_icon()),
|
Some(ButtonDetails::cancel_icon()),
|
||||||
None,
|
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();
|
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(
|
fn tutorial_screen(
|
||||||
title: StrBuffer,
|
title: StrBuffer,
|
||||||
text: StrBuffer,
|
text: StrBuffer,
|
||||||
btn_layout: ButtonLayout<&'static str>,
|
btn_layout: ButtonLayout,
|
||||||
btn_actions: ButtonActions,
|
btn_actions: ButtonActions,
|
||||||
) -> Page<10> {
|
) -> Page<10> {
|
||||||
let mut page = Page::<10>::new(
|
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(
|
tutorial_screen(
|
||||||
"HOLD TO CONFIRM".into(),
|
"HOLD TO CONFIRM".into(),
|
||||||
"Press and hold right to approve important operations.".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(),
|
ButtonActions::prev_next(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -521,7 +497,7 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
|
|||||||
tutorial_screen(
|
tutorial_screen(
|
||||||
"SCREEN SCROLL".into(),
|
"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(),
|
"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(),
|
ButtonActions::prev_next(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -529,14 +505,14 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
|
|||||||
tutorial_screen(
|
tutorial_screen(
|
||||||
"CONFIRM".into(),
|
"CONFIRM".into(),
|
||||||
"Press both left and right at the same time to 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(),
|
ButtonActions::prev_next_with_middle(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
// This page is special
|
// This page is special
|
||||||
5 => {
|
5 => {
|
||||||
Page::<10>::new(
|
Page::<10>::new(
|
||||||
ButtonLayout::left_right_text("AGAIN", "FINISH"),
|
ButtonLayout::left_right_text("AGAIN".into(), "FINISH".into()),
|
||||||
ButtonActions::beginning_confirm(),
|
ButtonActions::beginning_confirm(),
|
||||||
Font::MONO,
|
Font::MONO,
|
||||||
)
|
)
|
||||||
@ -551,7 +527,7 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
|
|||||||
tutorial_screen(
|
tutorial_screen(
|
||||||
"SKIP TUTORIAL".into(),
|
"SKIP TUTORIAL".into(),
|
||||||
"Are you sure you want to skip the 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(),
|
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_obj: Obj = kwargs.get(Qstr::MP_QSTR_share_words)?;
|
||||||
let share_words: Vec<StrBuffer, 24> = iter_into_vec(share_words_obj)?;
|
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(
|
let obj = LayoutObj::new(
|
||||||
ButtonPage::new_str(ShareWords::new(share_words), theme::BG)
|
ButtonPage::new(ShareWords::new(share_words), theme::BG).with_confirm_btn(confirm_btn),
|
||||||
.with_confirm_btn(confirm_btn),
|
|
||||||
)?;
|
)?;
|
||||||
Ok(obj.into())
|
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 block = |_args: &[Obj], kwargs: &Map| {
|
||||||
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
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)))?;
|
let obj = LayoutObj::new(Frame::new(title, SimpleChoice::new(choices, false, false)))?;
|
||||||
Ok(obj.into())
|
Ok(obj.into())
|
||||||
|
Loading…
Reference in New Issue
Block a user