mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-10 23:40:58 +00:00
refactor(core/rust/ui): uPy buffer support for TT buttons
[no changelog]
This commit is contained in:
parent
f167a2bef2
commit
695d80bf54
@ -20,6 +20,12 @@ impl Trace for &[u8] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Trace for &[u8; N] {
|
||||||
|
fn trace(&self, t: &mut dyn Tracer) {
|
||||||
|
t.bytes(&self[..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Trace for &str {
|
impl Trace for &str {
|
||||||
fn trace(&self, t: &mut dyn Tracer) {
|
fn trace(&self, t: &mut dyn Tracer) {
|
||||||
t.string(self);
|
t.string(self);
|
||||||
|
@ -11,15 +11,15 @@ pub enum ButtonMsg {
|
|||||||
Clicked,
|
Clicked,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Button {
|
pub struct Button<T> {
|
||||||
area: Rect,
|
area: Rect,
|
||||||
content: ButtonContent,
|
content: ButtonContent<T>,
|
||||||
styles: ButtonStyleSheet,
|
styles: ButtonStyleSheet,
|
||||||
state: State,
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Button {
|
impl<T> Button<T> {
|
||||||
pub fn new(area: Rect, content: ButtonContent) -> Self {
|
pub fn new(area: Rect, content: ButtonContent<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
area,
|
area,
|
||||||
content,
|
content,
|
||||||
@ -28,7 +28,7 @@ impl Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_text(area: Rect, text: &'static [u8]) -> Self {
|
pub fn with_text(area: Rect, text: T) -> Self {
|
||||||
Self::new(area, ButtonContent::Text(text))
|
Self::new(area, ButtonContent::Text(text))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ impl Button {
|
|||||||
matches!(self.state, State::Disabled)
|
matches!(self.state, State::Disabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn content(&self) -> &ButtonContent {
|
pub fn content(&self) -> &ButtonContent<T> {
|
||||||
&self.content
|
&self.content
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +88,10 @@ impl Button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Button {
|
impl<T> Component for Button<T>
|
||||||
|
where
|
||||||
|
T: AsRef<[u8]>,
|
||||||
|
{
|
||||||
type Msg = ButtonMsg;
|
type Msg = ButtonMsg;
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
@ -175,6 +178,7 @@ impl Component for Button {
|
|||||||
|
|
||||||
match &self.content {
|
match &self.content {
|
||||||
ButtonContent::Text(text) => {
|
ButtonContent::Text(text) => {
|
||||||
|
let text = text.as_ref();
|
||||||
let width = display::text_width(text, style.font);
|
let width = display::text_width(text, style.font);
|
||||||
let height = style.font.text_height();
|
let height = style.font.text_height();
|
||||||
let start_of_baseline = self.area.center() + Offset::new(-width / 2, height / 2);
|
let start_of_baseline = self.area.center() + Offset::new(-width / 2, height / 2);
|
||||||
@ -199,11 +203,14 @@ impl Component for Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
impl crate::trace::Trace for Button {
|
impl<T> crate::trace::Trace for Button<T>
|
||||||
|
where
|
||||||
|
T: AsRef<[u8]> + 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 {
|
||||||
ButtonContent::Text(text) => t.field("text", &text),
|
ButtonContent::Text(text) => t.field("text", text),
|
||||||
ButtonContent::Icon(_) => t.symbol("icon"),
|
ButtonContent::Icon(_) => t.symbol("icon"),
|
||||||
}
|
}
|
||||||
t.close();
|
t.close();
|
||||||
@ -218,8 +225,8 @@ enum State {
|
|||||||
Disabled,
|
Disabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ButtonContent {
|
pub enum ButtonContent<T> {
|
||||||
Text(&'static [u8]),
|
Text(T),
|
||||||
Icon(&'static [u8]),
|
Icon(&'static [u8]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ pub enum HoldToConfirmMsg<T> {
|
|||||||
pub struct HoldToConfirm<T> {
|
pub struct HoldToConfirm<T> {
|
||||||
loader: Loader,
|
loader: Loader,
|
||||||
content: Child<T>,
|
content: Child<T>,
|
||||||
cancel: Child<Button>,
|
cancel: Child<Button<&'static str>>,
|
||||||
confirm: Child<Button>,
|
confirm: Child<Button<&'static str>>,
|
||||||
pad: Pad,
|
pad: Pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,8 +31,8 @@ where
|
|||||||
Self {
|
Self {
|
||||||
loader: Loader::new(0),
|
loader: Loader::new(0),
|
||||||
content: content(layout.content).into_child(),
|
content: content(layout.content).into_child(),
|
||||||
cancel: Button::with_text(layout.left, b"Cancel").into_child(),
|
cancel: Button::with_text(layout.left, "Cancel").into_child(),
|
||||||
confirm: Button::with_text(layout.right, b"Hold").into_child(),
|
confirm: Button::with_text(layout.right, "Hold").into_child(),
|
||||||
pad: Pad::with_background(layout.content, theme::BG),
|
pad: Pad::with_background(layout.content, theme::BG),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ pub enum PassphraseKeyboardMsg {
|
|||||||
pub struct PassphraseKeyboard {
|
pub struct PassphraseKeyboard {
|
||||||
page_swipe: Swipe,
|
page_swipe: Swipe,
|
||||||
textbox: Child<TextBox>,
|
textbox: Child<TextBox>,
|
||||||
back_btn: Child<Button>,
|
back_btn: Child<Button<&'static str>>,
|
||||||
confirm_btn: Child<Button>,
|
confirm_btn: Child<Button<&'static str>>,
|
||||||
key_btns: [[Child<Button>; KEYS]; PAGES],
|
key_btns: [[Child<Button<&'static [u8]>>; KEYS]; PAGES],
|
||||||
key_page: usize,
|
key_page: usize,
|
||||||
pending: Option<Pending>,
|
pending: Option<Pending>,
|
||||||
}
|
}
|
||||||
@ -60,10 +60,10 @@ impl PassphraseKeyboard {
|
|||||||
let text = Vec::new();
|
let text = Vec::new();
|
||||||
let page_swipe = Swipe::horizontal(area);
|
let page_swipe = Swipe::horizontal(area);
|
||||||
let textbox = TextBox::new(textbox_area, text).into_child();
|
let textbox = TextBox::new(textbox_area, text).into_child();
|
||||||
let confirm_btn = Button::with_text(confirm_btn_area, b"Confirm")
|
let confirm_btn = Button::with_text(confirm_btn_area, "Confirm")
|
||||||
.styled(theme::button_confirm())
|
.styled(theme::button_confirm())
|
||||||
.into_child();
|
.into_child();
|
||||||
let back_btn = Button::with_text(back_btn_area, b"Back")
|
let back_btn = Button::with_text(back_btn_area, "Back")
|
||||||
.styled(theme::button_clear())
|
.styled(theme::button_clear())
|
||||||
.into_child();
|
.into_child();
|
||||||
let key_btns = Self::generate_keyboard(&key_grid);
|
let key_btns = Self::generate_keyboard(&key_grid);
|
||||||
@ -79,17 +79,17 @@ impl PassphraseKeyboard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_keyboard(grid: &Grid) -> [[Child<Button>; KEYS]; PAGES] {
|
fn generate_keyboard(grid: &Grid) -> [[Child<Button<&'static [u8]>>; KEYS]; PAGES] {
|
||||||
// can't use a range because the result is a fixed-size array
|
// can't use a range because the result is a fixed-size array
|
||||||
[0, 1, 2, 3].map(|i| Self::generate_key_page(grid, i))
|
[0, 1, 2, 3].map(|i| Self::generate_key_page(grid, i))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_key_page(grid: &Grid, page: usize) -> [Child<Button>; KEYS] {
|
fn generate_key_page(grid: &Grid, page: usize) -> [Child<Button<&'static [u8]>>; KEYS] {
|
||||||
// can't use a range because the result is a fixed-size array
|
// can't use a range because the result is a fixed-size array
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(|i| Self::generate_key(grid, page, i))
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(|i| Self::generate_key(grid, page, i))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_key(grid: &Grid, page: usize, key: usize) -> Child<Button> {
|
fn generate_key(grid: &Grid, page: usize, key: usize) -> Child<Button<&'static [u8]>> {
|
||||||
// Assign the keys in each page to buttons on a 5x3 grid, starting from the
|
// Assign the keys in each page to buttons on a 5x3 grid, starting from the
|
||||||
// second row.
|
// second row.
|
||||||
let area = grid.cell(if key < 9 {
|
let area = grid.cell(if key < 9 {
|
||||||
|
@ -31,10 +31,10 @@ pub struct PinDialog {
|
|||||||
major_prompt: Label<&'static [u8]>,
|
major_prompt: Label<&'static [u8]>,
|
||||||
minor_prompt: Label<&'static [u8]>,
|
minor_prompt: Label<&'static [u8]>,
|
||||||
dots: Child<PinDots>,
|
dots: Child<PinDots>,
|
||||||
reset_btn: Child<Button>,
|
reset_btn: Child<Button<&'static str>>,
|
||||||
cancel_btn: Child<Button>,
|
cancel_btn: Child<Button<&'static str>>,
|
||||||
confirm_btn: Child<Button>,
|
confirm_btn: Child<Button<&'static str>>,
|
||||||
digit_btns: [Child<Button>; DIGIT_COUNT],
|
digit_btns: [Child<Button<&'static str>>; DIGIT_COUNT],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PinDialog {
|
impl PinDialog {
|
||||||
@ -63,7 +63,7 @@ impl PinDialog {
|
|||||||
|
|
||||||
// Control buttons.
|
// Control buttons.
|
||||||
let grid = Grid::new(area, 5, 3);
|
let grid = Grid::new(area, 5, 3);
|
||||||
let reset_btn = Button::with_text(grid.row_col(4, 0), b"Reset")
|
let reset_btn = Button::with_text(grid.row_col(4, 0), "Reset")
|
||||||
.styled(theme::button_clear())
|
.styled(theme::button_clear())
|
||||||
.into_child();
|
.into_child();
|
||||||
let cancel_btn = Button::with_icon(grid.row_col(4, 0), theme::ICON_CANCEL)
|
let cancel_btn = Button::with_icon(grid.row_col(4, 0), theme::ICON_CANCEL)
|
||||||
@ -88,9 +88,9 @@ impl PinDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_digit_buttons(grid: &Grid) -> [Child<Button>; DIGIT_COUNT] {
|
fn generate_digit_buttons(grid: &Grid) -> [Child<Button<&'static str>>; DIGIT_COUNT] {
|
||||||
// Generate a random sequence of digits from 0 to 9.
|
// Generate a random sequence of digits from 0 to 9.
|
||||||
let mut digits = [b"0", b"1", b"2", b"3", b"4", b"5", b"6", b"7", b"8", b"9"];
|
let mut digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
|
||||||
random::shuffle(&mut digits);
|
random::shuffle(&mut digits);
|
||||||
|
|
||||||
// Assign the digits to buttons on a 5x3 grid, starting from the second row.
|
// Assign the digits to buttons on a 5x3 grid, starting from the second row.
|
||||||
@ -102,7 +102,7 @@ impl PinDialog {
|
|||||||
// For the last key (the "0" position) we skip one cell.
|
// For the last key (the "0" position) we skip one cell.
|
||||||
i + 1 + 3
|
i + 1 + 3
|
||||||
});
|
});
|
||||||
let text: &[u8; 1] = digits[i];
|
let text = digits[i];
|
||||||
Child::new(Button::with_text(area, text))
|
Child::new(Button::with_text(area, text))
|
||||||
};
|
};
|
||||||
[
|
[
|
||||||
@ -159,7 +159,7 @@ impl Component for PinDialog {
|
|||||||
for btn in &mut self.digit_btns {
|
for btn in &mut self.digit_btns {
|
||||||
if let Some(Clicked) = btn.event(ctx, event) {
|
if let Some(Clicked) = btn.event(ctx, event) {
|
||||||
if let ButtonContent::Text(text) = btn.inner().content() {
|
if let ButtonContent::Text(text) = btn.inner().content() {
|
||||||
if self.digits.extend_from_slice(text).is_err() {
|
if self.digits.extend_from_slice(text.as_ref()).is_err() {
|
||||||
// `self.pin` is full and wasn't able to accept all of
|
// `self.pin` is full and wasn't able to accept all of
|
||||||
// `text`. Should not happen.
|
// `text`. Should not happen.
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user