mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-08 22:40:59 +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:
parent
3f6ea00e02
commit
4200539546
@ -2,45 +2,37 @@ use core::ops::Deref;
|
||||
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx, Never},
|
||||
display::{self, Color, Font},
|
||||
display::Font,
|
||||
geometry::{Alignment, Offset, Rect},
|
||||
};
|
||||
|
||||
pub struct LabelStyle {
|
||||
pub font: Font,
|
||||
pub text_color: Color,
|
||||
pub background_color: Color,
|
||||
}
|
||||
use super::{text::TextStyle, TextLayout};
|
||||
|
||||
pub struct Label<T> {
|
||||
area: Rect,
|
||||
align: Alignment,
|
||||
style: LabelStyle,
|
||||
text: T,
|
||||
layout: TextLayout,
|
||||
}
|
||||
|
||||
impl<T> Label<T>
|
||||
where
|
||||
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 {
|
||||
area: Rect::zero(),
|
||||
align,
|
||||
style,
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn right_aligned(text: T, style: LabelStyle) -> Self {
|
||||
pub fn right_aligned(text: T, style: TextStyle) -> Self {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -48,11 +40,21 @@ where
|
||||
&self.text
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Offset {
|
||||
Offset::new(
|
||||
self.style.font.text_width(&self.text),
|
||||
self.style.font.text_height(),
|
||||
)
|
||||
pub fn set_text(&mut self, text: T) {
|
||||
self.text = text;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
let origin = match self.align {
|
||||
Alignment::Start => bounds.top_left(),
|
||||
Alignment::Center => bounds.top_left().center(bounds.top_right()),
|
||||
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
|
||||
let line_bounds = bounds.with_height(self.font().text_max_height());
|
||||
self.layout = self.layout.with_bounds(line_bounds);
|
||||
line_bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||
@ -79,17 +75,11 @@ where
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
display::text(
|
||||
self.area.bottom_left(),
|
||||
&self.text,
|
||||
self.style.font,
|
||||
self.style.text_color,
|
||||
self.style.background_color,
|
||||
);
|
||||
self.layout.render_text(&self.text);
|
||||
}
|
||||
|
||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||
sink(self.area)
|
||||
sink(self.layout.bounds)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ pub use base::{Child, Component, ComponentExt, Event, EventCtx, Never, TimerToke
|
||||
pub use border::Border;
|
||||
pub use empty::Empty;
|
||||
pub use image::Image;
|
||||
pub use label::{Label, LabelStyle};
|
||||
pub use label::Label;
|
||||
pub use map::Map;
|
||||
pub use maybe::Maybe;
|
||||
pub use pad::Pad;
|
||||
|
@ -3,7 +3,7 @@ use crate::{
|
||||
ui::{
|
||||
component::{
|
||||
text::paragraphs::{Paragraph, Paragraphs},
|
||||
Child, Component, ComponentExt, Event, EventCtx, Label, LabelStyle, Pad,
|
||||
Child, Component, ComponentExt, Event, EventCtx, Label, Pad,
|
||||
},
|
||||
constant::screen,
|
||||
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);
|
||||
pad.clear();
|
||||
|
||||
@ -68,7 +62,7 @@ impl ResultPopup {
|
||||
area: Rect::zero(),
|
||||
pad,
|
||||
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(),
|
||||
text: Child::new(p1),
|
||||
button,
|
||||
@ -105,7 +99,7 @@ impl Component for ResultPopup {
|
||||
let mut button_height = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
if self.button.is_some() {
|
||||
|
@ -95,7 +95,7 @@ where
|
||||
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_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_area = Rect::from_top_left_and_size(prompt_top_left, prompt_size);
|
||||
|
||||
|
@ -296,18 +296,18 @@ impl Component for Input {
|
||||
// Accounting for the pending marker, which draws itself one pixel longer than
|
||||
// the last character
|
||||
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
|
||||
} else {
|
||||
// Text is longer, showing its right end with ellipsis at the beginning.
|
||||
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.
|
||||
display::text(
|
||||
text_baseline,
|
||||
ellipsis,
|
||||
style.font,
|
||||
style.text_font,
|
||||
style.text_color,
|
||||
style.background_color,
|
||||
);
|
||||
@ -316,7 +316,9 @@ impl Component for Input {
|
||||
// Finding out how many additional text characters will fit in,
|
||||
// starting from the right end.
|
||||
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..]
|
||||
};
|
||||
@ -324,14 +326,19 @@ impl Component for Input {
|
||||
display::text(
|
||||
text_baseline,
|
||||
text_to_display,
|
||||
style.font,
|
||||
style.text_font,
|
||||
style.text_color,
|
||||
style.background_color,
|
||||
);
|
||||
|
||||
// Paint the pending marker.
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@ use crate::{
|
||||
trezorhal::random,
|
||||
ui::{
|
||||
component::{
|
||||
base::ComponentExt, Child, Component, Event, EventCtx, Label, LabelStyle, Maybe, Never,
|
||||
Pad, TimerToken,
|
||||
base::ComponentExt, text::TextStyle, Child, Component, Event, EventCtx, Label, Maybe,
|
||||
Never, Pad, TimerToken,
|
||||
},
|
||||
display::{self, Font},
|
||||
event::TouchEvent,
|
||||
@ -281,7 +281,7 @@ where
|
||||
struct PinDots {
|
||||
area: Rect,
|
||||
pad: Pad,
|
||||
style: LabelStyle,
|
||||
style: TextStyle,
|
||||
digits: String<MAX_LENGTH>,
|
||||
display_digits: bool,
|
||||
}
|
||||
@ -291,7 +291,7 @@ impl PinDots {
|
||||
const PADDING: i16 = 6;
|
||||
const TWITCH: i16 = 4;
|
||||
|
||||
fn new(style: LabelStyle) -> Self {
|
||||
fn new(style: TextStyle) -> Self {
|
||||
Self {
|
||||
area: Rect::zero(),
|
||||
pad: Pad::with_background(style.background_color),
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::ui::{
|
||||
component::{
|
||||
label::LabelStyle,
|
||||
text::{formatted::FormattedFonts, TextStyle},
|
||||
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_SMALL: &[u8] = include_res!("model_tt/res/scroll-small.toif");
|
||||
|
||||
pub fn label_default() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::NORMAL,
|
||||
text_color: FG,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_default() -> TextStyle {
|
||||
TEXT_NORMAL
|
||||
}
|
||||
|
||||
pub fn label_keyboard() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::DEMIBOLD,
|
||||
text_color: OFF_WHITE,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_keyboard() -> TextStyle {
|
||||
TextStyle::new(Font::DEMIBOLD, OFF_WHITE, BG, GREY_LIGHT, GREY_LIGHT)
|
||||
}
|
||||
|
||||
pub fn label_keyboard_warning() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::DEMIBOLD,
|
||||
text_color: RED,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_keyboard_warning() -> TextStyle {
|
||||
TextStyle::new(Font::DEMIBOLD, RED, BG, GREY_LIGHT, GREY_LIGHT)
|
||||
}
|
||||
|
||||
pub fn label_keyboard_minor() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::NORMAL,
|
||||
text_color: OFF_WHITE,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_keyboard_minor() -> TextStyle {
|
||||
TEXT_NORMAL_OFF_WHITE
|
||||
}
|
||||
|
||||
pub fn label_page_hint() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::BOLD,
|
||||
text_color: GREY_LIGHT,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_page_hint() -> TextStyle {
|
||||
TextStyle::new(Font::BOLD, GREY_LIGHT, BG, GREY_LIGHT, GREY_LIGHT)
|
||||
}
|
||||
|
||||
pub fn label_warning() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::DEMIBOLD,
|
||||
text_color: FG,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_warning() -> TextStyle {
|
||||
TEXT_DEMIBOLD
|
||||
}
|
||||
|
||||
pub fn label_warning_value() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::NORMAL,
|
||||
text_color: OFF_WHITE,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_warning_value() -> TextStyle {
|
||||
TEXT_NORMAL_OFF_WHITE
|
||||
}
|
||||
|
||||
pub fn label_recovery_title() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::BOLD,
|
||||
text_color: FG,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_recovery_title() -> TextStyle {
|
||||
TEXT_BOLD
|
||||
}
|
||||
|
||||
pub fn label_recovery_description() -> LabelStyle {
|
||||
LabelStyle {
|
||||
font: Font::NORMAL,
|
||||
text_color: OFF_WHITE,
|
||||
background_color: BG,
|
||||
}
|
||||
pub const fn label_recovery_description() -> TextStyle {
|
||||
TEXT_NORMAL_OFF_WHITE
|
||||
}
|
||||
|
||||
pub fn button_default() -> ButtonStyleSheet {
|
||||
|
Loading…
Reference in New Issue
Block a user