mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-09 15:00:58 +00:00
refactor(core/rust/ui): text theme struct
[no changelog]
This commit is contained in:
parent
20ac679651
commit
005e4203a7
@ -12,24 +12,36 @@ use crate::ui::{
|
||||
};
|
||||
|
||||
use super::layout::{
|
||||
DefaultTextTheme, LayoutFit, LayoutSink, LineBreaking, Op, PageBreaking, TextLayout,
|
||||
TextRenderer,
|
||||
LayoutFit, LayoutSink, LineBreaking, Op, PageBreaking, TextLayout, TextRenderer, TextStyle,
|
||||
};
|
||||
|
||||
pub const MAX_ARGUMENTS: usize = 6;
|
||||
|
||||
pub struct FormattedText<F, T> {
|
||||
layout: TextLayout,
|
||||
fonts: FormattedFonts,
|
||||
format: F,
|
||||
args: LinearMap<&'static str, T, MAX_ARGUMENTS>,
|
||||
char_offset: usize,
|
||||
}
|
||||
|
||||
pub struct FormattedFonts {
|
||||
/// Font used to format `{normal}`.
|
||||
pub normal: Font,
|
||||
/// Font used to format `{medium}`.
|
||||
pub medium: Font,
|
||||
/// Font used to format `{bold}`.
|
||||
pub bold: Font,
|
||||
/// Font used to format `{mono}`.
|
||||
pub mono: Font,
|
||||
}
|
||||
|
||||
impl<F, T> FormattedText<F, T> {
|
||||
pub fn new<D: DefaultTextTheme>(format: F) -> Self {
|
||||
pub fn new(style: TextStyle, fonts: FormattedFonts, format: F) -> Self {
|
||||
Self {
|
||||
format,
|
||||
layout: TextLayout::new::<D>(),
|
||||
fonts,
|
||||
layout: TextLayout::new(style),
|
||||
args: LinearMap::new(),
|
||||
char_offset: 0,
|
||||
}
|
||||
@ -49,22 +61,22 @@ impl<F, T> FormattedText<F, T> {
|
||||
}
|
||||
|
||||
pub fn with_text_font(mut self, text_font: Font) -> Self {
|
||||
self.layout.text_font = text_font;
|
||||
self.layout.style.text_font = text_font;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_text_color(mut self, text_color: Color) -> Self {
|
||||
self.layout.text_color = text_color;
|
||||
self.layout.style.text_color = text_color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_line_breaking(mut self, line_breaking: LineBreaking) -> Self {
|
||||
self.layout.line_breaking = line_breaking;
|
||||
self.layout.style.line_breaking = line_breaking;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_page_breaking(mut self, page_breaking: PageBreaking) -> Self {
|
||||
self.layout.page_breaking = page_breaking;
|
||||
self.layout.style.page_breaking = page_breaking;
|
||||
self
|
||||
}
|
||||
|
||||
@ -91,10 +103,10 @@ where
|
||||
let mut ops = Op::skip_n_text_bytes(
|
||||
Tokenizer::new(self.format.as_ref()).flat_map(|arg| match arg {
|
||||
Token::Literal(literal) => Some(Op::Text(literal)),
|
||||
Token::Argument("mono") => Some(Op::Font(self.layout.mono_font)),
|
||||
Token::Argument("bold") => Some(Op::Font(self.layout.bold_font)),
|
||||
Token::Argument("normal") => Some(Op::Font(self.layout.normal_font)),
|
||||
Token::Argument("medium") => Some(Op::Font(self.layout.medium_font)),
|
||||
Token::Argument("mono") => Some(Op::Font(self.fonts.mono)),
|
||||
Token::Argument("bold") => Some(Op::Font(self.fonts.bold)),
|
||||
Token::Argument("normal") => Some(Op::Font(self.fonts.normal)),
|
||||
Token::Argument("medium") => Some(Op::Font(self.fonts.medium)),
|
||||
Token::Argument(argument) => self
|
||||
.args
|
||||
.get(argument)
|
||||
|
@ -37,72 +37,59 @@ pub struct TextLayout {
|
||||
/// negative.
|
||||
pub padding_bottom: i32,
|
||||
|
||||
/// Background color.
|
||||
pub background_color: Color,
|
||||
/// Text color. Can be overridden by `Op::Color`.
|
||||
pub text_color: Color,
|
||||
/// Fonts, colors, line/page breaking behavior.
|
||||
pub style: TextStyle,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct TextStyle {
|
||||
/// Text font ID. Can be overridden by `Op::Font`.
|
||||
pub text_font: Font,
|
||||
/// Text color. Can be overridden by `Op::Color`.
|
||||
pub text_color: Color,
|
||||
/// Background color.
|
||||
pub background_color: Color,
|
||||
|
||||
/// Specifies which line-breaking strategy to use.
|
||||
pub line_breaking: LineBreaking,
|
||||
/// Font used for drawing the word-breaking hyphen.
|
||||
pub hyphen_font: Font,
|
||||
/// Foreground color used for drawing the hyphen.
|
||||
pub hyphen_color: Color,
|
||||
|
||||
/// Specifies what to do at the end of the page.
|
||||
pub page_breaking: PageBreaking,
|
||||
/// Font used for drawing the ellipsis.
|
||||
pub ellipsis_font: Font,
|
||||
/// Foreground color used for drawing the ellipsis.
|
||||
pub ellipsis_color: Color,
|
||||
|
||||
/// Font used to format `{normal}`.
|
||||
pub normal_font: Font,
|
||||
/// Font used to format `{medium}`.
|
||||
pub medium_font: Font,
|
||||
/// Font used to format `{bold}`.
|
||||
pub bold_font: Font,
|
||||
/// Font used to format `{mono}`.
|
||||
pub mono_font: Font,
|
||||
/// Specifies which line-breaking strategy to use.
|
||||
pub line_breaking: LineBreaking,
|
||||
/// Specifies what to do at the end of the page.
|
||||
pub page_breaking: PageBreaking,
|
||||
}
|
||||
|
||||
pub trait DefaultTextTheme {
|
||||
const BACKGROUND_COLOR: Color;
|
||||
const TEXT_FONT: Font;
|
||||
const TEXT_COLOR: Color;
|
||||
const HYPHEN_FONT: Font;
|
||||
const HYPHEN_COLOR: Color;
|
||||
const ELLIPSIS_FONT: Font;
|
||||
const ELLIPSIS_COLOR: Color;
|
||||
const NORMAL_FONT: Font;
|
||||
const MEDIUM_FONT: Font;
|
||||
const BOLD_FONT: Font;
|
||||
const MONO_FONT: Font;
|
||||
impl TextStyle {
|
||||
pub const fn new(
|
||||
text_font: Font,
|
||||
text_color: Color,
|
||||
background_color: Color,
|
||||
hyphen_color: Color,
|
||||
ellipsis_color: Color,
|
||||
) -> Self {
|
||||
TextStyle {
|
||||
text_font,
|
||||
text_color,
|
||||
background_color,
|
||||
hyphen_color,
|
||||
ellipsis_color,
|
||||
line_breaking: LineBreaking::BreakAtWhitespace,
|
||||
page_breaking: PageBreaking::CutAndInsertEllipsis,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TextLayout {
|
||||
/// Create a new text layout, with empty size and default text parameters
|
||||
/// filled from `T`.
|
||||
pub fn new<T: DefaultTextTheme>() -> Self {
|
||||
pub fn new(style: TextStyle) -> Self {
|
||||
Self {
|
||||
bounds: Rect::zero(),
|
||||
padding_top: 0,
|
||||
padding_bottom: 0,
|
||||
background_color: T::BACKGROUND_COLOR,
|
||||
text_color: T::TEXT_COLOR,
|
||||
text_font: T::TEXT_FONT,
|
||||
line_breaking: LineBreaking::BreakAtWhitespace,
|
||||
hyphen_font: T::HYPHEN_FONT,
|
||||
hyphen_color: T::HYPHEN_COLOR,
|
||||
page_breaking: PageBreaking::CutAndInsertEllipsis,
|
||||
ellipsis_font: T::ELLIPSIS_FONT,
|
||||
ellipsis_color: T::ELLIPSIS_COLOR,
|
||||
normal_font: T::NORMAL_FONT,
|
||||
medium_font: T::MEDIUM_FONT,
|
||||
bold_font: T::BOLD_FONT,
|
||||
mono_font: T::MONO_FONT,
|
||||
style,
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +99,7 @@ impl TextLayout {
|
||||
}
|
||||
|
||||
pub fn initial_cursor(&self) -> Point {
|
||||
self.bounds.top_left() + Offset::y(self.text_font.text_height() + self.padding_top)
|
||||
self.bounds.top_left() + Offset::y(self.style.text_font.text_height() + self.padding_top)
|
||||
}
|
||||
|
||||
pub fn fit_text(&self, text: &str) -> LayoutFit {
|
||||
@ -135,10 +122,10 @@ impl TextLayout {
|
||||
for op in ops {
|
||||
match op {
|
||||
Op::Color(color) => {
|
||||
self.text_color = color;
|
||||
self.style.text_color = color;
|
||||
}
|
||||
Op::Font(font) => {
|
||||
self.text_font = font;
|
||||
self.style.text_font = font;
|
||||
}
|
||||
Op::Text(text) => match self.layout_text(text, cursor, sink) {
|
||||
LayoutFit::Fitting {
|
||||
@ -189,9 +176,8 @@ impl TextLayout {
|
||||
let span = Span::fit_horizontally(
|
||||
remaining_text,
|
||||
self.bounds.x1 - cursor.x,
|
||||
self.text_font,
|
||||
self.hyphen_font,
|
||||
self.line_breaking,
|
||||
self.style.text_font,
|
||||
self.style.line_breaking,
|
||||
);
|
||||
|
||||
// Report the span at the cursor position.
|
||||
@ -216,7 +202,7 @@ impl TextLayout {
|
||||
// Append ellipsis to indicate more content is available, but only if we
|
||||
// haven't already appended a hyphen.
|
||||
let should_append_ellipsis =
|
||||
matches!(self.page_breaking, PageBreaking::CutAndInsertEllipsis)
|
||||
matches!(self.style.page_breaking, PageBreaking::CutAndInsertEllipsis)
|
||||
&& !span.insert_hyphen_before_line_break;
|
||||
if should_append_ellipsis {
|
||||
sink.ellipsis(*cursor, self);
|
||||
@ -253,7 +239,7 @@ impl TextLayout {
|
||||
|
||||
fn layout_height(&self, init_cursor: Point, end_cursor: Point) -> i32 {
|
||||
self.padding_top
|
||||
+ self.text_font.text_height()
|
||||
+ self.style.text_font.text_height()
|
||||
+ (end_cursor.y - init_cursor.y)
|
||||
+ self.padding_bottom
|
||||
}
|
||||
@ -295,9 +281,9 @@ impl LayoutSink for TextRenderer {
|
||||
display::text(
|
||||
cursor,
|
||||
text,
|
||||
layout.text_font,
|
||||
layout.text_color,
|
||||
layout.background_color,
|
||||
layout.style.text_font,
|
||||
layout.style.text_color,
|
||||
layout.style.background_color,
|
||||
);
|
||||
}
|
||||
|
||||
@ -305,9 +291,9 @@ impl LayoutSink for TextRenderer {
|
||||
display::text(
|
||||
cursor,
|
||||
"-",
|
||||
layout.hyphen_font,
|
||||
layout.hyphen_color,
|
||||
layout.background_color,
|
||||
layout.style.text_font,
|
||||
layout.style.hyphen_color,
|
||||
layout.style.background_color,
|
||||
);
|
||||
}
|
||||
|
||||
@ -315,9 +301,9 @@ impl LayoutSink for TextRenderer {
|
||||
display::text(
|
||||
cursor,
|
||||
"...",
|
||||
layout.ellipsis_font,
|
||||
layout.ellipsis_color,
|
||||
layout.background_color,
|
||||
layout.style.text_font,
|
||||
layout.style.ellipsis_color,
|
||||
layout.style.background_color,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -401,7 +387,6 @@ impl Span {
|
||||
text: &str,
|
||||
max_width: i32,
|
||||
text_font: impl GlyphMetrics,
|
||||
hyphen_font: impl GlyphMetrics,
|
||||
breaking: LineBreaking,
|
||||
) -> Self {
|
||||
const ASCII_LF: char = '\n';
|
||||
@ -413,7 +398,7 @@ impl Span {
|
||||
ch == ASCII_SPACE || ch == ASCII_LF || ch == ASCII_CR
|
||||
}
|
||||
|
||||
let hyphen_width = hyphen_font.char_width(ASCII_HYPHEN);
|
||||
let hyphen_width = text_font.char_width(ASCII_HYPHEN);
|
||||
|
||||
// The span we return in case the line has to break. We mutate it in the
|
||||
// possible break points, and its initial value is returned in case no text
|
||||
@ -563,7 +548,6 @@ mod tests {
|
||||
remaining_text,
|
||||
max_width,
|
||||
FIXED_FONT,
|
||||
FIXED_FONT,
|
||||
LineBreaking::BreakAtWhitespace,
|
||||
);
|
||||
spans.push((
|
||||
|
@ -2,3 +2,5 @@ pub mod formatted;
|
||||
mod iter;
|
||||
pub mod layout;
|
||||
pub mod paragraphs;
|
||||
|
||||
pub use layout::TextStyle;
|
||||
|
@ -2,11 +2,10 @@ use heapless::Vec;
|
||||
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, Never, Paginate},
|
||||
display::Font,
|
||||
geometry::{Dimensions, Insets, LinearPlacement, Rect},
|
||||
};
|
||||
|
||||
use super::layout::{DefaultTextTheme, LayoutFit, TextLayout};
|
||||
use super::layout::{LayoutFit, TextLayout, TextStyle};
|
||||
|
||||
pub const MAX_PARAGRAPHS: usize = 6;
|
||||
/// Maximum space between paragraphs. Actual result may be smaller (even 0) if
|
||||
@ -53,17 +52,16 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add<D: DefaultTextTheme>(mut self, text_font: Font, content: T) -> Self {
|
||||
pub fn add(mut self, style: TextStyle, content: T) -> Self {
|
||||
if content.as_ref().is_empty() {
|
||||
return self;
|
||||
}
|
||||
let paragraph = Paragraph::new(
|
||||
content,
|
||||
TextLayout {
|
||||
text_font,
|
||||
padding_top: PARAGRAPH_TOP_SPACE,
|
||||
padding_bottom: PARAGRAPH_BOTTOM_SPACE,
|
||||
..TextLayout::new::<D>()
|
||||
..TextLayout::new(style)
|
||||
},
|
||||
);
|
||||
if self.list.push(paragraph).is_err() {
|
||||
|
@ -72,7 +72,7 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
|
||||
let obj = LayoutObj::new(Frame::new(
|
||||
title,
|
||||
ButtonPage::new(
|
||||
FormattedText::new::<theme::T1DefaultText>(format)
|
||||
FormattedText::new(theme::TEXT_NORMAL, theme::FORMATTED, format)
|
||||
.with("action", action.unwrap_or_default())
|
||||
.with("description", description.unwrap_or_default()),
|
||||
theme::BG,
|
||||
@ -94,11 +94,8 @@ extern "C" fn new_confirm_text(n_args: usize, args: *const Obj, kwargs: *mut Map
|
||||
title,
|
||||
ButtonPage::new(
|
||||
Paragraphs::new()
|
||||
.add::<theme::T1DefaultText>(
|
||||
theme::FONT_NORMAL,
|
||||
description.unwrap_or_default(),
|
||||
)
|
||||
.add::<theme::T1DefaultText>(theme::FONT_BOLD, data),
|
||||
.add(theme::TEXT_NORMAL, description.unwrap_or_default())
|
||||
.add(theme::TEXT_BOLD, data),
|
||||
theme::BG,
|
||||
),
|
||||
))?;
|
||||
@ -178,7 +175,9 @@ mod tests {
|
||||
#[test]
|
||||
fn trace_example_layout() {
|
||||
let mut layout = Dialog::new(
|
||||
FormattedText::new::<theme::T1DefaultText>(
|
||||
FormattedText::new(
|
||||
theme::TEXT_NORMAL,
|
||||
theme::FORMATTED,
|
||||
"Testing text layout, with some text, and some more text. And {param}",
|
||||
)
|
||||
.with("param", "parameters!"),
|
||||
@ -208,7 +207,9 @@ arameters! > left:<Button text:Left > right:<Button text:Right > >"#
|
||||
let mut layout = Frame::new(
|
||||
"Please confirm",
|
||||
Dialog::new(
|
||||
FormattedText::new::<theme::T1DefaultText>(
|
||||
FormattedText::new(
|
||||
theme::TEXT_NORMAL,
|
||||
theme::FORMATTED,
|
||||
"Testing text layout, with some text, and some more text. And {param}",
|
||||
)
|
||||
.with("param", "parameters!"),
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::ui::{
|
||||
component::text::layout::DefaultTextTheme,
|
||||
component::text::{formatted::FormattedFonts, TextStyle},
|
||||
display::{Color, Font},
|
||||
};
|
||||
|
||||
@ -48,19 +48,14 @@ pub fn button_cancel() -> ButtonStyleSheet {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct T1DefaultText;
|
||||
pub const TEXT_NORMAL: TextStyle = TextStyle::new(FONT_NORMAL, FG, BG, FG, FG);
|
||||
pub const TEXT_MEDIUM: TextStyle = TextStyle::new(FONT_MEDIUM, FG, BG, FG, FG);
|
||||
pub const TEXT_BOLD: TextStyle = TextStyle::new(FONT_BOLD, FG, BG, FG, FG);
|
||||
pub const TEXT_MONO: TextStyle = TextStyle::new(FONT_MONO, FG, BG, FG, FG);
|
||||
|
||||
impl DefaultTextTheme for T1DefaultText {
|
||||
const BACKGROUND_COLOR: Color = BG;
|
||||
const TEXT_FONT: Font = FONT_NORMAL;
|
||||
const TEXT_COLOR: Color = FG;
|
||||
const HYPHEN_FONT: Font = FONT_NORMAL;
|
||||
const HYPHEN_COLOR: Color = FG;
|
||||
const ELLIPSIS_FONT: Font = FONT_NORMAL;
|
||||
const ELLIPSIS_COLOR: Color = FG;
|
||||
|
||||
const NORMAL_FONT: Font = FONT_NORMAL;
|
||||
const MEDIUM_FONT: Font = FONT_MEDIUM;
|
||||
const BOLD_FONT: Font = FONT_BOLD;
|
||||
const MONO_FONT: Font = FONT_MONO;
|
||||
}
|
||||
pub const FORMATTED: FormattedFonts = FormattedFonts {
|
||||
normal: FONT_NORMAL,
|
||||
medium: FONT_MEDIUM,
|
||||
bold: FONT_BOLD,
|
||||
mono: FONT_MONO,
|
||||
};
|
||||
|
@ -2,16 +2,14 @@ use crate::{
|
||||
time::Instant,
|
||||
ui::{
|
||||
component::{
|
||||
text::{layout::DefaultTextTheme, paragraphs::Paragraphs},
|
||||
Child, Component, ComponentExt, Event, EventCtx, Label, LabelStyle, Pad,
|
||||
text::paragraphs::Paragraphs, Child, Component, ComponentExt, Event, EventCtx, Label,
|
||||
LabelStyle, Pad,
|
||||
},
|
||||
constant::screen,
|
||||
display::{Color, Font},
|
||||
geometry::{Alignment, Insets, LinearPlacement, Point, Rect},
|
||||
model_tr::{
|
||||
component::{Button, ButtonMsg, ButtonPos, ResultAnim, ResultAnimMsg},
|
||||
theme,
|
||||
theme::{TRDefaultText, FONT_BOLD, FONT_MEDIUM},
|
||||
theme::{self, FONT_BOLD},
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -31,23 +29,6 @@ pub struct ResultPopup {
|
||||
autoclose: bool,
|
||||
}
|
||||
|
||||
pub struct MessageText;
|
||||
|
||||
impl DefaultTextTheme for MessageText {
|
||||
const BACKGROUND_COLOR: Color = theme::BG;
|
||||
const TEXT_FONT: Font = FONT_MEDIUM;
|
||||
const TEXT_COLOR: Color = theme::FG;
|
||||
const HYPHEN_FONT: Font = FONT_MEDIUM;
|
||||
const HYPHEN_COLOR: Color = theme::FG;
|
||||
const ELLIPSIS_FONT: Font = FONT_MEDIUM;
|
||||
const ELLIPSIS_COLOR: Color = theme::FG;
|
||||
|
||||
const NORMAL_FONT: Font = FONT_MEDIUM;
|
||||
const MEDIUM_FONT: Font = theme::FONT_MEDIUM;
|
||||
const BOLD_FONT: Font = theme::FONT_BOLD;
|
||||
const MONO_FONT: Font = theme::FONT_MONO;
|
||||
}
|
||||
|
||||
const ANIM_SIZE: i32 = 18;
|
||||
const BUTTON_HEIGHT: i32 = 13;
|
||||
const ANIM_SPACE: i32 = 11;
|
||||
@ -63,7 +44,7 @@ impl ResultPopup {
|
||||
button_text: Option<&'static str>,
|
||||
) -> Self {
|
||||
let p1 = Paragraphs::new()
|
||||
.add::<TRDefaultText>(FONT_MEDIUM, text)
|
||||
.add(theme::TEXT_MEDIUM, text)
|
||||
.with_placement(LinearPlacement::vertical().align_at_center());
|
||||
|
||||
let button = button_text.map(|t| {
|
||||
|
@ -72,7 +72,7 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
|
||||
let obj = LayoutObj::new(Frame::new(
|
||||
title,
|
||||
ButtonPage::new(
|
||||
FormattedText::new::<theme::TRDefaultText>(format)
|
||||
FormattedText::new(theme::TEXT_NORMAL, theme::FORMATTED, format)
|
||||
.with("action", action.unwrap_or_default())
|
||||
.with("description", description.unwrap_or_default()),
|
||||
theme::BG,
|
||||
@ -94,11 +94,8 @@ extern "C" fn new_confirm_text(n_args: usize, args: *const Obj, kwargs: *mut Map
|
||||
title,
|
||||
ButtonPage::new(
|
||||
Paragraphs::new()
|
||||
.add::<theme::TRDefaultText>(
|
||||
theme::FONT_NORMAL,
|
||||
description.unwrap_or_default(),
|
||||
)
|
||||
.add::<theme::TRDefaultText>(theme::FONT_BOLD, data),
|
||||
.add(theme::TEXT_NORMAL, description.unwrap_or_default())
|
||||
.add(theme::TEXT_BOLD, data),
|
||||
theme::BG,
|
||||
),
|
||||
))?;
|
||||
@ -178,7 +175,9 @@ mod tests {
|
||||
#[test]
|
||||
fn trace_example_layout() {
|
||||
let mut layout = Dialog::new(
|
||||
FormattedText::new::<theme::TRDefaultText>(
|
||||
FormattedText::new(
|
||||
theme::TEXT_NORMAL,
|
||||
theme::FORMATTED,
|
||||
"Testing text layout, with some text, and some more text. And {param}",
|
||||
)
|
||||
.with("param", "parameters!"),
|
||||
@ -208,7 +207,9 @@ arameters! > left:<Button text:Left > right:<Button text:Right > >"#
|
||||
let mut layout = Frame::new(
|
||||
"Please confirm",
|
||||
Dialog::new(
|
||||
FormattedText::new::<theme::TRDefaultText>(
|
||||
FormattedText::new(
|
||||
theme::TEXT_NORMAL,
|
||||
theme::FORMATTED,
|
||||
"Testing text layout, with some text, and some more text. And {param}",
|
||||
)
|
||||
.with("param", "parameters!"),
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::ui::{
|
||||
component::text::layout::DefaultTextTheme,
|
||||
component::text::{formatted::FormattedFonts, TextStyle},
|
||||
display::{Color, Font},
|
||||
model_tr::component::{LoaderStyle, LoaderStyleSheet},
|
||||
};
|
||||
@ -62,19 +62,14 @@ pub fn loader_default() -> LoaderStyleSheet {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TRDefaultText;
|
||||
pub const TEXT_NORMAL: TextStyle = TextStyle::new(FONT_NORMAL, FG, BG, FG, FG);
|
||||
pub const TEXT_MEDIUM: TextStyle = TextStyle::new(FONT_MEDIUM, FG, BG, FG, FG);
|
||||
pub const TEXT_BOLD: TextStyle = TextStyle::new(FONT_BOLD, FG, BG, FG, FG);
|
||||
pub const TEXT_MONO: TextStyle = TextStyle::new(FONT_MONO, FG, BG, FG, FG);
|
||||
|
||||
impl DefaultTextTheme for TRDefaultText {
|
||||
const BACKGROUND_COLOR: Color = BG;
|
||||
const TEXT_FONT: Font = FONT_NORMAL;
|
||||
const TEXT_COLOR: Color = FG;
|
||||
const HYPHEN_FONT: Font = FONT_NORMAL;
|
||||
const HYPHEN_COLOR: Color = FG;
|
||||
const ELLIPSIS_FONT: Font = FONT_NORMAL;
|
||||
const ELLIPSIS_COLOR: Color = FG;
|
||||
|
||||
const NORMAL_FONT: Font = FONT_NORMAL;
|
||||
const MEDIUM_FONT: Font = FONT_MEDIUM;
|
||||
const BOLD_FONT: Font = FONT_BOLD;
|
||||
const MONO_FONT: Font = FONT_MONO;
|
||||
}
|
||||
pub const FORMATTED: FormattedFonts = FormattedFonts {
|
||||
normal: FONT_NORMAL,
|
||||
medium: FONT_MEDIUM,
|
||||
bold: FONT_BOLD,
|
||||
mono: FONT_MONO,
|
||||
};
|
||||
|
@ -380,12 +380,12 @@ mod tests {
|
||||
fn paragraphs_single() {
|
||||
let mut page = SwipePage::new(
|
||||
Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(
|
||||
theme::FONT_NORMAL,
|
||||
.add(
|
||||
theme::TEXT_NORMAL,
|
||||
"This is the first paragraph and it should fit on the screen entirely.",
|
||||
)
|
||||
.add::<theme::TTDefaultText>(
|
||||
theme::FONT_BOLD,
|
||||
.add(
|
||||
theme::TEXT_BOLD,
|
||||
"Second, bold, paragraph should also fit on the screen whole I think.",
|
||||
),
|
||||
Empty,
|
||||
@ -406,8 +406,8 @@ mod tests {
|
||||
fn paragraphs_one_long() {
|
||||
let mut page = SwipePage::new(
|
||||
Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(
|
||||
theme::FONT_BOLD,
|
||||
.add(
|
||||
theme::TEXT_BOLD,
|
||||
"This is somewhat long paragraph that goes on and on and on and on and on and will definitely not fit on just a single screen. You have to swipe a bit to see all the text it contains I guess. There's just so much letters in it.",
|
||||
),
|
||||
Empty,
|
||||
@ -433,16 +433,16 @@ mod tests {
|
||||
fn paragraphs_three_long() {
|
||||
let mut page = SwipePage::new(
|
||||
Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(
|
||||
theme::FONT_BOLD,
|
||||
.add(
|
||||
theme::TEXT_BOLD,
|
||||
"This paragraph is using a bold font. It doesn't need to be all that long.",
|
||||
)
|
||||
.add::<theme::TTDefaultText>(
|
||||
theme::FONT_MONO,
|
||||
.add(
|
||||
theme::TEXT_MONO,
|
||||
"And this one is using MONO. Monospace is nice for numbers, they have the same width and can be scanned quickly. Even if they span several pages or something.",
|
||||
)
|
||||
.add::<theme::TTDefaultText>(
|
||||
theme::FONT_BOLD,
|
||||
.add(
|
||||
theme::TEXT_BOLD,
|
||||
"Let's add another one for a good measure. This one should overflow all the way to the third page with a bit of luck.",
|
||||
),
|
||||
Empty,
|
||||
|
@ -206,12 +206,12 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
|
||||
let mut paragraphs = Paragraphs::new();
|
||||
if !reverse {
|
||||
paragraphs = paragraphs
|
||||
.add::<theme::TTDefaultText>(theme::FONT_BOLD, action)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description);
|
||||
.add(theme::TEXT_BOLD, action)
|
||||
.add(theme::TEXT_NORMAL, description);
|
||||
} else {
|
||||
paragraphs = paragraphs
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_BOLD, action);
|
||||
.add(theme::TEXT_NORMAL, description)
|
||||
.add(theme::TEXT_BOLD, action);
|
||||
}
|
||||
paragraphs
|
||||
};
|
||||
@ -246,9 +246,9 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
|
||||
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
|
||||
|
||||
let paragraphs = Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_BOLD, extra)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, data);
|
||||
.add(theme::TEXT_NORMAL, description)
|
||||
.add(theme::TEXT_BOLD, extra)
|
||||
.add(theme::TEXT_MONO, data);
|
||||
|
||||
let obj = if hold {
|
||||
LayoutObj::new(
|
||||
@ -302,8 +302,8 @@ extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut M
|
||||
let verb = "NEXT";
|
||||
|
||||
let paragraphs = Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, value);
|
||||
.add(theme::TEXT_NORMAL, description)
|
||||
.add(theme::TEXT_MONO, value);
|
||||
|
||||
let buttons = Button::cancel_confirm(
|
||||
Button::with_icon(theme::ICON_CANCEL),
|
||||
@ -326,8 +326,8 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
||||
let value: StrBuffer = kwargs.get(Qstr::MP_QSTR_value)?.try_into()?;
|
||||
|
||||
let paragraphs = Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, value);
|
||||
.add(theme::TEXT_NORMAL, description)
|
||||
.add(theme::TEXT_MONO, value);
|
||||
|
||||
let obj = LayoutObj::new(
|
||||
Frame::new(title, SwipeHoldPage::new(paragraphs, theme::BG)).into_child(),
|
||||
@ -343,10 +343,10 @@ extern "C" fn new_confirm_joint_total(n_args: usize, args: *const Obj, kwargs: *
|
||||
let total_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?;
|
||||
|
||||
let paragraphs = Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "You are contributing:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, spending_amount)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "To the total amount:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, total_amount);
|
||||
.add(theme::TEXT_NORMAL, "You are contributing:".into())
|
||||
.add(theme::TEXT_MONO, spending_amount)
|
||||
.add(theme::TEXT_NORMAL, "To the total amount:".into())
|
||||
.add(theme::TEXT_MONO, total_amount);
|
||||
|
||||
let obj = LayoutObj::new(
|
||||
Frame::new(
|
||||
@ -374,13 +374,13 @@ extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs:
|
||||
};
|
||||
|
||||
let paragraphs = Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "Address:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, address)
|
||||
.add(theme::TEXT_NORMAL, "Address:".into())
|
||||
.add(theme::TEXT_MONO, address)
|
||||
// FIXME pagebreak
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description.into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, amount_change)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "New amount:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, amount_new);
|
||||
.add(theme::TEXT_NORMAL, description.into())
|
||||
.add(theme::TEXT_MONO, amount_change)
|
||||
.add(theme::TEXT_NORMAL, "New amount:".into())
|
||||
.add(theme::TEXT_MONO, amount_new);
|
||||
|
||||
let buttons = Button::cancel_confirm(
|
||||
Button::with_icon(theme::ICON_CANCEL),
|
||||
@ -413,10 +413,10 @@ extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *m
|
||||
};
|
||||
|
||||
let paragraphs = Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, description.into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, change)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "\nTransaction fee:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_MONO, total_fee_new);
|
||||
.add(theme::TEXT_NORMAL, description.into())
|
||||
.add(theme::TEXT_MONO, change)
|
||||
.add(theme::TEXT_NORMAL, "\nTransaction fee:".into())
|
||||
.add(theme::TEXT_MONO, total_fee_new);
|
||||
|
||||
let buttons = Button::cancel_confirm(
|
||||
Button::with_icon(theme::ICON_CANCEL),
|
||||
@ -481,14 +481,13 @@ extern "C" fn new_confirm_payment_request(
|
||||
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
||||
let memos: Obj = kwargs.get(Qstr::MP_QSTR_memos)?;
|
||||
|
||||
let mut paragraphs =
|
||||
Paragraphs::new().add::<theme::TTDefaultText>(theme::FONT_NORMAL, description);
|
||||
let mut paragraphs = Paragraphs::new().add(theme::TEXT_NORMAL, description);
|
||||
|
||||
let mut iter_buf = IterBuf::new();
|
||||
let iter = Iter::try_from_obj_with_buf(memos, &mut iter_buf)?;
|
||||
for memo in iter {
|
||||
let text: StrBuffer = memo.try_into()?;
|
||||
paragraphs = paragraphs.add::<theme::TTDefaultText>(theme::FONT_NORMAL, text);
|
||||
paragraphs = paragraphs.add(theme::TEXT_NORMAL, text);
|
||||
}
|
||||
|
||||
let buttons = Button::cancel_info_confirm("CONFIRM", "DETAILS");
|
||||
@ -512,12 +511,12 @@ extern "C" fn new_confirm_coinjoin(n_args: usize, args: *const Obj, kwargs: *mut
|
||||
let max_feerate: StrBuffer = kwargs.get(Qstr::MP_QSTR_max_feerate)?.try_into()?;
|
||||
|
||||
let paragraphs = Paragraphs::new()
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "Coin name:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_BOLD, coin_name)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "Maximum rounds:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_BOLD, max_rounds)
|
||||
.add::<theme::TTDefaultText>(theme::FONT_NORMAL, "Maximum mining fee:".into())
|
||||
.add::<theme::TTDefaultText>(theme::FONT_BOLD, max_feerate);
|
||||
.add(theme::TEXT_NORMAL, "Coin name:".into())
|
||||
.add(theme::TEXT_BOLD, coin_name)
|
||||
.add(theme::TEXT_NORMAL, "Maximum rounds:".into())
|
||||
.add(theme::TEXT_BOLD, max_rounds)
|
||||
.add(theme::TEXT_NORMAL, "Maximum mining fee:".into())
|
||||
.add(theme::TEXT_BOLD, max_feerate);
|
||||
|
||||
let obj = LayoutObj::new(
|
||||
Frame::new(
|
||||
@ -761,7 +760,9 @@ mod tests {
|
||||
let buttons =
|
||||
Button::cancel_confirm(Button::with_text("Left"), Button::with_text("Right"), 1);
|
||||
let mut layout = Dialog::new(
|
||||
FormattedText::new::<theme::TTDefaultText>(
|
||||
FormattedText::new(
|
||||
theme::TEXT_NORMAL,
|
||||
theme::FORMATTED,
|
||||
"Testing text layout, with some text, and some more text. And {param}",
|
||||
)
|
||||
.with("param", "parameters!"),
|
||||
|
@ -1,5 +1,8 @@
|
||||
use crate::ui::{
|
||||
component::{label::LabelStyle, text::layout::DefaultTextTheme},
|
||||
component::{
|
||||
label::LabelStyle,
|
||||
text::{formatted::FormattedFonts, TextStyle},
|
||||
},
|
||||
display::{Color, Font},
|
||||
geometry::Insets,
|
||||
};
|
||||
@ -298,22 +301,17 @@ pub fn loader_default() -> LoaderStyleSheet {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TTDefaultText;
|
||||
pub const TEXT_NORMAL: TextStyle = TextStyle::new(FONT_NORMAL, FG, BG, GREY_LIGHT, GREY_LIGHT);
|
||||
pub const TEXT_MEDIUM: TextStyle = TextStyle::new(FONT_MEDIUM, FG, BG, GREY_LIGHT, GREY_LIGHT);
|
||||
pub const TEXT_BOLD: TextStyle = TextStyle::new(FONT_BOLD, FG, BG, GREY_LIGHT, GREY_LIGHT);
|
||||
pub const TEXT_MONO: TextStyle = TextStyle::new(FONT_MONO, FG, BG, GREY_LIGHT, GREY_LIGHT);
|
||||
|
||||
impl DefaultTextTheme for TTDefaultText {
|
||||
const BACKGROUND_COLOR: Color = BG;
|
||||
const TEXT_FONT: Font = FONT_NORMAL;
|
||||
const TEXT_COLOR: Color = FG;
|
||||
const HYPHEN_FONT: Font = FONT_BOLD;
|
||||
const HYPHEN_COLOR: Color = GREY_LIGHT;
|
||||
const ELLIPSIS_FONT: Font = FONT_BOLD;
|
||||
const ELLIPSIS_COLOR: Color = GREY_LIGHT;
|
||||
|
||||
const NORMAL_FONT: Font = FONT_NORMAL;
|
||||
const MEDIUM_FONT: Font = FONT_MEDIUM;
|
||||
const BOLD_FONT: Font = FONT_BOLD;
|
||||
const MONO_FONT: Font = FONT_MONO;
|
||||
}
|
||||
pub const FORMATTED: FormattedFonts = FormattedFonts {
|
||||
normal: FONT_NORMAL,
|
||||
medium: FONT_MEDIUM,
|
||||
bold: FONT_BOLD,
|
||||
mono: FONT_MONO,
|
||||
};
|
||||
|
||||
pub const CONTENT_BORDER: i32 = 5;
|
||||
pub const KEYBOARD_SPACING: i32 = 8;
|
||||
|
@ -6,8 +6,6 @@ from trezor.enums import ButtonRequestType
|
||||
|
||||
import trezorui2
|
||||
|
||||
from ...components.tt.confirm import Confirm
|
||||
from ...constants.tt import MONO_ADDR_PER_LINE
|
||||
from ..common import button_request, interact
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -419,8 +417,8 @@ async def confirm_output(
|
||||
color_to: int = ui.FG, # TODO cleanup @ redesign
|
||||
to_str: str = " to\n", # TODO cleanup @ redesign
|
||||
to_paginated: bool = False, # TODO cleanup @ redesign
|
||||
width: int = MONO_ADDR_PER_LINE,
|
||||
width_paginated: int = MONO_ADDR_PER_LINE - 1,
|
||||
width: int = 0, # TODO cleanup @ redesign
|
||||
width_paginated: int = 0, # TODO cleanup @ redesign
|
||||
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
|
||||
icon: str = ui.ICON_SEND,
|
||||
) -> None:
|
||||
@ -495,7 +493,7 @@ async def should_show_more(
|
||||
br_code: ButtonRequestType = ButtonRequestType.Other,
|
||||
icon: str = ui.ICON_DEFAULT,
|
||||
icon_color: int = ui.ORANGE_ICON,
|
||||
confirm: ButtonContent = Confirm.DEFAULT_CONFIRM,
|
||||
confirm: ButtonContent = None,
|
||||
major_confirm: bool = False,
|
||||
) -> bool:
|
||||
raise NotImplementedError
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user