feat(core/rust/ui): implement confirm_action

[no changelog]
mmilata/tt-pin-keyboard
Martin Milata 2 years ago
parent 6d1227d839
commit b64c69c3ff

@ -23,12 +23,6 @@
#include "librust.h"
#if TREZOR_MODEL == T
/// def layout_new_example(text: str) -> None:
/// """Example layout."""
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui2_layout_new_example_obj,
ui_layout_new_example);
#elif TREZOR_MODEL == 1
/// def layout_new_confirm_action(
/// *,
/// title: str,
@ -38,30 +32,37 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui2_layout_new_example_obj,
/// verb_cancel: str | None,
/// hold: bool | None,
/// reverse: bool,
/// ) -> int:
/// ) -> object:
/// """Example layout."""
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_trezorui2_layout_new_confirm_action_obj,
0, ui_layout_new_confirm_action);
#if TREZOR_MODEL == T
/// def layout_new_example(text: str) -> object:
/// """Example layout."""
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui2_layout_new_example_obj,
ui_layout_new_example);
#elif TREZOR_MODEL == 1
/// def layout_new_confirm_text(
/// *,
/// title: str,
/// data: str,
/// description: str | None,
/// ) -> int:
/// ) -> object:
/// """Example layout."""
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_trezorui2_layout_new_confirm_text_obj, 0,
ui_layout_new_confirm_text);
#endif
STATIC const mp_rom_map_elem_t mp_module_trezorui2_globals_table[] = {
#if TREZOR_MODEL == T
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorui2)},
{MP_ROM_QSTR(MP_QSTR_layout_new_confirm_action),
MP_ROM_PTR(&mod_trezorui2_layout_new_confirm_action_obj)},
#if TREZOR_MODEL == T
{MP_ROM_QSTR(MP_QSTR_layout_new_example),
MP_ROM_PTR(&mod_trezorui2_layout_new_example_obj)},
#elif TREZOR_MODEL == 1
{MP_ROM_QSTR(MP_QSTR_layout_new_confirm_action),
MP_ROM_PTR(&mod_trezorui2_layout_new_confirm_action_obj)},
{MP_ROM_QSTR(MP_QSTR_layout_new_confirm_text),
MP_ROM_PTR(&mod_trezorui2_layout_new_confirm_text_obj)},
#endif

@ -9,6 +9,7 @@ use crate::ui::{
use super::layout::{DefaultTextTheme, LayoutFit, TextLayout, TextNoOp, TextRenderer};
pub const MAX_PARAGRAPHS: usize = 6;
pub const DEFAULT_SPACING: i32 = 3;
pub struct Paragraphs<T> {
area: Rect,
@ -26,7 +27,9 @@ where
Self {
area,
list: Vec::new(),
layout: LinearLayout::vertical().align_at_center().with_spacing(10),
layout: LinearLayout::vertical()
.align_at_center()
.with_spacing(DEFAULT_SPACING),
para_offset: 0,
char_offset: 0,
}
@ -37,6 +40,11 @@ where
self
}
pub fn with_spacing(mut self, spacing: i32) -> Self {
self.layout = self.layout.with_spacing(spacing);
self
}
pub fn add<D: DefaultTextTheme>(mut self, text_font: Font, content: T) -> Self {
if content.as_ref().is_empty() {
return self;

@ -13,7 +13,7 @@ use crate::{
typ::Type,
},
time::Duration,
ui::component::{Child, Component, Event, EventCtx, Never, TimerToken},
ui::component::{Child, Component, Event, EventCtx, Never, PageMsg, TimerToken},
util,
};
@ -277,6 +277,17 @@ impl TryFrom<Duration> for Obj {
}
}
impl<T> TryFrom<PageMsg<T, bool>> for Obj {
type Error = Error;
fn try_from(val: PageMsg<T, bool>) -> Result<Self, Self::Error> {
match val {
PageMsg::Content(_) => Err(Error::TypeError),
PageMsg::Controls(c) => Ok(c.into()),
}
}
}
impl From<Never> for Obj {
fn from(_: Never) -> Self {
unreachable!()

@ -1,10 +1,9 @@
use core::convert::{TryFrom, TryInto};
use core::convert::TryInto;
use crate::{
error::Error,
micropython::{buffer::Buffer, map::Map, obj::Obj, qstr::Qstr},
ui::{
component::{text::paragraphs::Paragraphs, Child, FormattedText, PageMsg},
component::{text::paragraphs::Paragraphs, Child, FormattedText},
display,
layout::obj::LayoutObj,
},
@ -16,17 +15,6 @@ use super::{
theme,
};
impl<T> TryFrom<PageMsg<T, bool>> for Obj {
type Error = Error;
fn try_from(val: PageMsg<T, bool>) -> Result<Self, Self::Error> {
match val {
PageMsg::Content(_) => 2.try_into(),
PageMsg::Controls(c) => Ok(c.into()),
}
}
}
#[no_mangle]
extern "C" fn ui_layout_new_confirm_action(
n_args: usize,
@ -106,7 +94,8 @@ extern "C" fn ui_layout_new_confirm_text(
#[cfg(test)]
mod tests {
use crate::{
trace::{Trace, Tracer},
error::Error,
trace::Trace,
ui::model_t1::component::{Dialog, DialogMsg},
};

@ -2,9 +2,9 @@ use core::convert::{TryFrom, TryInto};
use crate::{
error::Error,
micropython::obj::Obj,
micropython::{buffer::Buffer, map::Map, obj::Obj, qstr::Qstr},
ui::{
component::{Child, FormattedText},
component::{base::ComponentExt, text::paragraphs::Paragraphs, Child, FormattedText},
display,
layout::obj::LayoutObj,
},
@ -12,7 +12,7 @@ use crate::{
};
use super::{
component::{ButtonMsg, DialogMsg, HoldToConfirm, HoldToConfirmMsg},
component::{Button, ButtonMsg, DialogMsg, Frame, HoldToConfirm, HoldToConfirmMsg, SwipePage},
theme,
};
@ -64,6 +64,61 @@ extern "C" fn ui_layout_new_example(_param: Obj) -> Obj {
unsafe { util::try_or_raise(block) }
}
#[no_mangle]
extern "C" fn ui_layout_new_confirm_action(
n_args: usize,
args: *const Obj,
kwargs: *const Map,
) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: Buffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let action: Option<Buffer> = kwargs.get(Qstr::MP_QSTR_action)?.try_into_option()?;
let description: Option<Buffer> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let verb: Option<Buffer> = kwargs.get(Qstr::MP_QSTR_verb)?.try_into_option()?;
let reverse: bool = kwargs.get(Qstr::MP_QSTR_reverse)?.try_into()?;
let obj = LayoutObj::new(
Frame::new(theme::borders(), title, |area| {
SwipePage::new(
area,
theme::BG,
|area| {
let action = action.unwrap_or("".into());
let description = description.unwrap_or("".into());
let mut para = Paragraphs::new(area);
if !reverse {
para = para
.add::<theme::TTDefaultText>(theme::FONT_BOLD, action)
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description);
} else {
para = para
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description)
.add::<theme::TTDefaultText>(theme::FONT_BOLD, action);
}
para
},
|area| {
Button::array2(
area,
|area| Button::with_icon(area, theme::ICON_CANCEL),
|msg| (matches!(msg, ButtonMsg::Clicked)).then(|| false),
|area| {
Button::with_text(area, verb.unwrap_or("CONFIRM".into()))
.styled(theme::button_confirm())
},
|msg| (matches!(msg, ButtonMsg::Clicked)).then(|| true),
)
},
)
})
.into_child(),
)?;
Ok(obj.into())
};
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
#[cfg(test)]
mod tests {
use crate::{
@ -130,9 +185,7 @@ mod tests {
));
assert_eq!(
trace(&layout),
r#"<Dialog content:<Text content:Testing text layout, with
some text, and some more
text. And parameters! > left:<Button text:Left > right:<Button text:Right > >"#
"<Dialog content:<Text content:Testing text layout, with\nsome text, and some more\ntext. And parameters! > left:<Button text:Left > right:<Button text:Right > >",
)
}
}

@ -53,37 +53,65 @@ pub fn label_default() -> LabelStyle {
pub fn button_default() -> ButtonStyleSheet {
ButtonStyleSheet {
normal: &ButtonStyle {
font: FONT_NORMAL,
font: FONT_BOLD,
text_color: FG,
button_color: GREY_DARK,
background_color: BG,
border_color: BG,
border_radius: RADIUS,
border_width: 2,
border_width: 1,
},
active: &ButtonStyle {
font: FONT_NORMAL,
font: FONT_BOLD,
text_color: BG,
button_color: FG,
background_color: BG,
border_color: FG,
border_radius: RADIUS,
border_width: 2,
border_width: 1,
},
disabled: &ButtonStyle {
font: FONT_NORMAL,
font: FONT_BOLD,
text_color: GREY_LIGHT,
button_color: GREY_DARK,
background_color: BG,
border_color: BG,
border_radius: RADIUS,
border_width: 2,
border_width: 1,
},
}
}
pub fn button_confirm() -> ButtonStyleSheet {
button_default()
ButtonStyleSheet {
normal: &ButtonStyle {
font: FONT_BOLD,
text_color: FG,
button_color: GREEN,
background_color: BG,
border_color: BG,
border_radius: RADIUS,
border_width: 1,
},
active: &ButtonStyle {
font: FONT_BOLD,
text_color: BG,
button_color: FG,
background_color: BG,
border_color: FG,
border_radius: RADIUS,
border_width: 1,
},
disabled: &ButtonStyle {
font: FONT_BOLD,
text_color: GREY_LIGHT,
button_color: GREEN,
background_color: BG,
border_color: BG,
border_radius: RADIUS,
border_width: 1,
},
}
}
pub fn button_cancel() -> ButtonStyleSheet {
@ -125,3 +153,20 @@ impl DefaultTextTheme for TTDefaultText {
const BOLD_FONT: Font = FONT_BOLD;
const MONO_FONT: Font = FONT_MONO;
}
pub const CONTENT_BORDER: i32 = 5;
/// +----------+
/// | 13 |
/// | +----+ |
/// |10| | 5|
/// | +----+ |
/// | 14 |
/// +----------+
pub fn borders() -> Rect {
let (_left_border, area) = display::screen().vsplit(10);
let (area, _right_area) = area.vsplit(-5);
let (_top_border, area) = area.hsplit(13);
let (area, _bottom_border) = area.hsplit(-14);
area
}

Loading…
Cancel
Save