1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-27 04:29:03 +00:00

refactor(core/rust/ui): redesign Label to make use of TextLayout machinery

also replace LabelStyle with TextStyle

[no changelog]
This commit is contained in:
matejcik 2022-11-23 12:53:57 +01:00 committed by matejcik
parent 3f6ea00e02
commit 4200539546
7 changed files with 68 additions and 114 deletions

View File

@ -2,45 +2,37 @@ use core::ops::Deref;
use crate::ui::{ use crate::ui::{
component::{Component, Event, EventCtx, Never}, component::{Component, Event, EventCtx, Never},
display::{self, Color, Font}, display::Font,
geometry::{Alignment, Offset, Rect}, geometry::{Alignment, Offset, Rect},
}; };
pub struct LabelStyle { use super::{text::TextStyle, TextLayout};
pub font: Font,
pub text_color: Color,
pub background_color: Color,
}
pub struct Label<T> { pub struct Label<T> {
area: Rect,
align: Alignment,
style: LabelStyle,
text: T, text: T,
layout: TextLayout,
} }
impl<T> Label<T> impl<T> Label<T>
where where
T: Deref<Target = str>, T: Deref<Target = str>,
{ {
pub fn new(text: T, align: Alignment, style: LabelStyle) -> Self { pub fn new(text: T, align: Alignment, style: TextStyle) -> Self {
Self { Self {
area: Rect::zero(),
align,
style,
text, text,
layout: TextLayout::new(style).with_align(align),
} }
} }
pub fn left_aligned(text: T, style: LabelStyle) -> Self { pub fn left_aligned(text: T, style: TextStyle) -> Self {
Self::new(text, Alignment::Start, style) Self::new(text, Alignment::Start, style)
} }
pub fn right_aligned(text: T, style: LabelStyle) -> Self { pub fn right_aligned(text: T, style: TextStyle) -> Self {
Self::new(text, Alignment::End, style) Self::new(text, Alignment::End, style)
} }
pub fn centered(text: T, style: LabelStyle) -> Self { pub fn centered(text: T, style: TextStyle) -> Self {
Self::new(text, Alignment::Center, style) Self::new(text, Alignment::Center, style)
} }
@ -48,11 +40,21 @@ where
&self.text &self.text
} }
pub fn size(&self) -> Offset { pub fn set_text(&mut self, text: T) {
Offset::new( self.text = text;
self.style.font.text_width(&self.text), }
self.style.font.text_height(),
) pub fn font(&self) -> Font {
self.layout.style.text_font
}
pub fn area(&self) -> Rect {
self.layout.bounds
}
pub fn max_size(&self) -> Offset {
let font = self.font();
Offset::new(font.text_width(&self.text), font.text_max_height())
} }
} }
@ -63,15 +65,9 @@ where
type Msg = Never; type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
let origin = match self.align { let line_bounds = bounds.with_height(self.font().text_max_height());
Alignment::Start => bounds.top_left(), self.layout = self.layout.with_bounds(line_bounds);
Alignment::Center => bounds.top_left().center(bounds.top_right()), line_bounds
Alignment::End => bounds.top_right(),
};
let size = self.size();
let top_left = size.snap(origin, self.align, Alignment::Start);
self.area = Rect::from_top_left_and_size(top_left, size);
self.area
} }
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> { fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
@ -79,17 +75,11 @@ where
} }
fn paint(&mut self) { fn paint(&mut self) {
display::text( self.layout.render_text(&self.text);
self.area.bottom_left(),
&self.text,
self.style.font,
self.style.text_color,
self.style.background_color,
);
} }
fn bounds(&self, sink: &mut dyn FnMut(Rect)) { fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.area) sink(self.layout.bounds)
} }
} }

View File

@ -18,7 +18,7 @@ pub use base::{Child, Component, ComponentExt, Event, EventCtx, Never, TimerToke
pub use border::Border; pub use border::Border;
pub use empty::Empty; pub use empty::Empty;
pub use image::Image; pub use image::Image;
pub use label::{Label, LabelStyle}; pub use label::Label;
pub use map::Map; pub use map::Map;
pub use maybe::Maybe; pub use maybe::Maybe;
pub use pad::Pad; pub use pad::Pad;

View File

@ -3,7 +3,7 @@ use crate::{
ui::{ ui::{
component::{ component::{
text::paragraphs::{Paragraph, Paragraphs}, text::paragraphs::{Paragraph, Paragraphs},
Child, Component, ComponentExt, Event, EventCtx, Label, LabelStyle, Pad, Child, Component, ComponentExt, Event, EventCtx, Label, Pad,
}, },
constant::screen, constant::screen,
display::Font, display::Font,
@ -55,12 +55,6 @@ impl ResultPopup {
)) ))
}); });
let headline_style = LabelStyle {
background_color: theme::BG,
text_color: theme::FG,
font: Font::BOLD,
};
let mut pad = Pad::with_background(theme::BG); let mut pad = Pad::with_background(theme::BG);
pad.clear(); pad.clear();
@ -68,7 +62,7 @@ impl ResultPopup {
area: Rect::zero(), area: Rect::zero(),
pad, pad,
result_anim: Child::new(ResultAnim::new(icon)), result_anim: Child::new(ResultAnim::new(icon)),
headline: headline.map(|a| Label::new(a, Alignment::Center, headline_style)), headline: headline.map(|a| Label::new(a, Alignment::Center, theme::TEXT_BOLD)),
headline_baseline: Point::zero(), headline_baseline: Point::zero(),
text: Child::new(p1), text: Child::new(p1),
button, button,
@ -105,7 +99,7 @@ impl Component for ResultPopup {
let mut button_height = 0; let mut button_height = 0;
if let Some(h) = self.headline.as_mut() { if let Some(h) = self.headline.as_mut() {
headline_height = h.size().y; headline_height = h.max_size().y;
anim_adjust += ANIM_POS_ADJ_HEADLINE; anim_adjust += ANIM_POS_ADJ_HEADLINE;
} }
if self.button.is_some() { if self.button.is_some() {

View File

@ -95,7 +95,7 @@ where
let input_area = grid.row_col(0, 1).union(grid.row_col(0, 3)); let input_area = grid.row_col(0, 1).union(grid.row_col(0, 3));
let prompt_center = grid.row_col(0, 0).union(grid.row_col(0, 3)).center(); let prompt_center = grid.row_col(0, 0).union(grid.row_col(0, 3)).center();
let prompt_size = self.prompt.inner().inner().size(); let prompt_size = self.prompt.inner().inner().max_size();
let prompt_top_left = prompt_size.snap(prompt_center, Alignment::Center, Alignment::Center); let prompt_top_left = prompt_size.snap(prompt_center, Alignment::Center, Alignment::Center);
let prompt_area = Rect::from_top_left_and_size(prompt_top_left, prompt_size); let prompt_area = Rect::from_top_left_and_size(prompt_top_left, prompt_size);

View File

@ -296,18 +296,18 @@ impl Component for Input {
// Accounting for the pending marker, which draws itself one pixel longer than // Accounting for the pending marker, which draws itself one pixel longer than
// the last character // the last character
let available_area_width = self.area.width() - 1; let available_area_width = self.area.width() - 1;
let text_to_display = if style.font.text_width(text) <= available_area_width { let text_to_display = if style.text_font.text_width(text) <= available_area_width {
text // whole text can fit text // whole text can fit
} else { } else {
// Text is longer, showing its right end with ellipsis at the beginning. // Text is longer, showing its right end with ellipsis at the beginning.
let ellipsis = "..."; let ellipsis = "...";
let ellipsis_width = style.font.text_width(ellipsis); let ellipsis_width = style.text_font.text_width(ellipsis);
// Drawing the ellipsis and moving the baseline for the rest of the text. // Drawing the ellipsis and moving the baseline for the rest of the text.
display::text( display::text(
text_baseline, text_baseline,
ellipsis, ellipsis,
style.font, style.text_font,
style.text_color, style.text_color,
style.background_color, style.background_color,
); );
@ -316,7 +316,9 @@ impl Component for Input {
// Finding out how many additional text characters will fit in, // Finding out how many additional text characters will fit in,
// starting from the right end. // starting from the right end.
let remaining_available_width = available_area_width - ellipsis_width; let remaining_available_width = available_area_width - ellipsis_width;
let chars_from_right = style.font.longest_suffix(remaining_available_width, text); let chars_from_right = style
.text_font
.longest_suffix(remaining_available_width, text);
&text[text.len() - chars_from_right..] &text[text.len() - chars_from_right..]
}; };
@ -324,14 +326,19 @@ impl Component for Input {
display::text( display::text(
text_baseline, text_baseline,
text_to_display, text_to_display,
style.font, style.text_font,
style.text_color, style.text_color,
style.background_color, style.background_color,
); );
// Paint the pending marker. // Paint the pending marker.
if self.multi_tap.pending_key().is_some() { if self.multi_tap.pending_key().is_some() {
paint_pending_marker(text_baseline, text_to_display, style.font, style.text_color); paint_pending_marker(
text_baseline,
text_to_display,
style.text_font,
style.text_color,
);
} }
} }

View File

@ -6,8 +6,8 @@ use crate::{
trezorhal::random, trezorhal::random,
ui::{ ui::{
component::{ component::{
base::ComponentExt, Child, Component, Event, EventCtx, Label, LabelStyle, Maybe, Never, base::ComponentExt, text::TextStyle, Child, Component, Event, EventCtx, Label, Maybe,
Pad, TimerToken, Never, Pad, TimerToken,
}, },
display::{self, Font}, display::{self, Font},
event::TouchEvent, event::TouchEvent,
@ -281,7 +281,7 @@ where
struct PinDots { struct PinDots {
area: Rect, area: Rect,
pad: Pad, pad: Pad,
style: LabelStyle, style: TextStyle,
digits: String<MAX_LENGTH>, digits: String<MAX_LENGTH>,
display_digits: bool, display_digits: bool,
} }
@ -291,7 +291,7 @@ impl PinDots {
const PADDING: i16 = 6; const PADDING: i16 = 6;
const TWITCH: i16 = 4; const TWITCH: i16 = 4;
fn new(style: LabelStyle) -> Self { fn new(style: TextStyle) -> Self {
Self { Self {
area: Rect::zero(), area: Rect::zero(),
pad: Pad::with_background(style.background_color), pad: Pad::with_background(style.background_color),

View File

@ -1,6 +1,5 @@
use crate::ui::{ use crate::ui::{
component::{ component::{
label::LabelStyle,
text::{formatted::FormattedFonts, TextStyle}, text::{formatted::FormattedFonts, TextStyle},
FixedHeightBar, FixedHeightBar,
}, },
@ -72,76 +71,40 @@ pub const DOT_ACTIVE: &[u8] = include_res!("model_tt/res/scroll-active.toif");
pub const DOT_INACTIVE: &[u8] = include_res!("model_tt/res/scroll-inactive.toif"); pub const DOT_INACTIVE: &[u8] = include_res!("model_tt/res/scroll-inactive.toif");
pub const DOT_SMALL: &[u8] = include_res!("model_tt/res/scroll-small.toif"); pub const DOT_SMALL: &[u8] = include_res!("model_tt/res/scroll-small.toif");
pub fn label_default() -> LabelStyle { pub const fn label_default() -> TextStyle {
LabelStyle { TEXT_NORMAL
font: Font::NORMAL,
text_color: FG,
background_color: BG,
}
} }
pub fn label_keyboard() -> LabelStyle { pub const fn label_keyboard() -> TextStyle {
LabelStyle { TextStyle::new(Font::DEMIBOLD, OFF_WHITE, BG, GREY_LIGHT, GREY_LIGHT)
font: Font::DEMIBOLD,
text_color: OFF_WHITE,
background_color: BG,
}
} }
pub fn label_keyboard_warning() -> LabelStyle { pub const fn label_keyboard_warning() -> TextStyle {
LabelStyle { TextStyle::new(Font::DEMIBOLD, RED, BG, GREY_LIGHT, GREY_LIGHT)
font: Font::DEMIBOLD,
text_color: RED,
background_color: BG,
}
} }
pub fn label_keyboard_minor() -> LabelStyle { pub const fn label_keyboard_minor() -> TextStyle {
LabelStyle { TEXT_NORMAL_OFF_WHITE
font: Font::NORMAL,
text_color: OFF_WHITE,
background_color: BG,
}
} }
pub fn label_page_hint() -> LabelStyle { pub const fn label_page_hint() -> TextStyle {
LabelStyle { TextStyle::new(Font::BOLD, GREY_LIGHT, BG, GREY_LIGHT, GREY_LIGHT)
font: Font::BOLD,
text_color: GREY_LIGHT,
background_color: BG,
}
} }
pub fn label_warning() -> LabelStyle { pub const fn label_warning() -> TextStyle {
LabelStyle { TEXT_DEMIBOLD
font: Font::DEMIBOLD,
text_color: FG,
background_color: BG,
}
} }
pub fn label_warning_value() -> LabelStyle { pub const fn label_warning_value() -> TextStyle {
LabelStyle { TEXT_NORMAL_OFF_WHITE
font: Font::NORMAL,
text_color: OFF_WHITE,
background_color: BG,
}
} }
pub fn label_recovery_title() -> LabelStyle { pub const fn label_recovery_title() -> TextStyle {
LabelStyle { TEXT_BOLD
font: Font::BOLD,
text_color: FG,
background_color: BG,
}
} }
pub fn label_recovery_description() -> LabelStyle { pub const fn label_recovery_description() -> TextStyle {
LabelStyle { TEXT_NORMAL_OFF_WHITE
font: Font::NORMAL,
text_color: OFF_WHITE,
background_color: BG,
}
} }
pub fn button_default() -> ButtonStyleSheet { pub fn button_default() -> ButtonStyleSheet {