mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-26 23:32:03 +00:00
fix(core/rust/ui): adjust spacing for confirm_action
[no changelog]
This commit is contained in:
parent
5378492ea9
commit
ab0eef5de0
@ -34,7 +34,9 @@ where
|
|||||||
break; // TODO: We should consider if there's more content
|
break; // TODO: We should consider if there's more content
|
||||||
// to render.
|
// to render.
|
||||||
}
|
}
|
||||||
LayoutFit::OutOfBounds { processed_chars } => {
|
LayoutFit::OutOfBounds {
|
||||||
|
processed_chars, ..
|
||||||
|
} => {
|
||||||
page_count += 1;
|
page_count += 1;
|
||||||
char_offset += processed_chars;
|
char_offset += processed_chars;
|
||||||
self.set_char_offset(char_offset);
|
self.set_char_offset(char_offset);
|
||||||
@ -62,7 +64,9 @@ where
|
|||||||
break; // TODO: We should consider if there's more content
|
break; // TODO: We should consider if there's more content
|
||||||
// to render.
|
// to render.
|
||||||
}
|
}
|
||||||
LayoutFit::OutOfBounds { processed_chars } => {
|
LayoutFit::OutOfBounds {
|
||||||
|
processed_chars, ..
|
||||||
|
} => {
|
||||||
active_page += 1;
|
active_page += 1;
|
||||||
char_offset += processed_chars;
|
char_offset += processed_chars;
|
||||||
self.set_char_offset(char_offset);
|
self.set_char_offset(char_offset);
|
||||||
|
@ -29,6 +29,13 @@ pub struct TextLayout {
|
|||||||
/// Bounding box restricting the layout dimensions.
|
/// Bounding box restricting the layout dimensions.
|
||||||
pub bounds: Rect,
|
pub bounds: Rect,
|
||||||
|
|
||||||
|
/// Additional space before beginning of text, can be negative to shift text
|
||||||
|
/// upwards.
|
||||||
|
pub padding_top: i32,
|
||||||
|
/// Additional space between end of text and bottom of bounding box, can be
|
||||||
|
/// negative.
|
||||||
|
pub padding_bottom: i32,
|
||||||
|
|
||||||
/// Background color.
|
/// Background color.
|
||||||
pub background_color: Color,
|
pub background_color: Color,
|
||||||
/// Text color. Can be overridden by `Op::Color`.
|
/// Text color. Can be overridden by `Op::Color`.
|
||||||
@ -78,6 +85,8 @@ impl TextLayout {
|
|||||||
pub fn new<T: DefaultTextTheme>(bounds: Rect) -> Self {
|
pub fn new<T: DefaultTextTheme>(bounds: Rect) -> Self {
|
||||||
Self {
|
Self {
|
||||||
bounds,
|
bounds,
|
||||||
|
padding_top: 0,
|
||||||
|
padding_bottom: 0,
|
||||||
background_color: T::BACKGROUND_COLOR,
|
background_color: T::BACKGROUND_COLOR,
|
||||||
text_color: T::TEXT_COLOR,
|
text_color: T::TEXT_COLOR,
|
||||||
text_font: T::TEXT_FONT,
|
text_font: T::TEXT_FONT,
|
||||||
@ -95,10 +104,7 @@ impl TextLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn initial_cursor(&self) -> Point {
|
pub fn initial_cursor(&self) -> Point {
|
||||||
Point::new(
|
self.bounds.top_left() + Offset::y(self.text_font.text_height() + self.padding_top)
|
||||||
self.bounds.top_left().x,
|
|
||||||
self.bounds.top_left().y + self.text_font.line_height(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_ops<'o>(
|
pub fn layout_ops<'o>(
|
||||||
@ -107,7 +113,7 @@ impl TextLayout {
|
|||||||
cursor: &mut Point,
|
cursor: &mut Point,
|
||||||
sink: &mut dyn LayoutSink,
|
sink: &mut dyn LayoutSink,
|
||||||
) -> LayoutFit {
|
) -> LayoutFit {
|
||||||
let init_cursor: Point = *cursor;
|
let init_cursor = *cursor;
|
||||||
let mut total_processed_chars = 0;
|
let mut total_processed_chars = 0;
|
||||||
|
|
||||||
for op in ops {
|
for op in ops {
|
||||||
@ -124,11 +130,14 @@ impl TextLayout {
|
|||||||
} => {
|
} => {
|
||||||
total_processed_chars += processed_chars;
|
total_processed_chars += processed_chars;
|
||||||
}
|
}
|
||||||
LayoutFit::OutOfBounds { processed_chars } => {
|
LayoutFit::OutOfBounds {
|
||||||
|
processed_chars, ..
|
||||||
|
} => {
|
||||||
total_processed_chars += processed_chars;
|
total_processed_chars += processed_chars;
|
||||||
|
|
||||||
return LayoutFit::OutOfBounds {
|
return LayoutFit::OutOfBounds {
|
||||||
processed_chars: total_processed_chars,
|
processed_chars: total_processed_chars,
|
||||||
|
height: self.layout_height(init_cursor, *cursor),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -137,10 +146,7 @@ impl TextLayout {
|
|||||||
|
|
||||||
LayoutFit::Fitting {
|
LayoutFit::Fitting {
|
||||||
processed_chars: total_processed_chars,
|
processed_chars: total_processed_chars,
|
||||||
size: Offset::new(
|
height: self.layout_height(init_cursor, *cursor),
|
||||||
self.bounds.width(),
|
|
||||||
cursor.y - init_cursor.y + self.text_font.line_height(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,13 +156,17 @@ impl TextLayout {
|
|||||||
cursor: &mut Point,
|
cursor: &mut Point,
|
||||||
sink: &mut dyn LayoutSink,
|
sink: &mut dyn LayoutSink,
|
||||||
) -> LayoutFit {
|
) -> LayoutFit {
|
||||||
let init_cursor: Point = *cursor;
|
let init_cursor = *cursor;
|
||||||
|
let bottom = (self.bounds.y1 - self.padding_bottom).max(self.bounds.y0);
|
||||||
let mut remaining_text = text;
|
let mut remaining_text = text;
|
||||||
|
|
||||||
// Check if bounding box is high enough for at least one line.
|
// Check if bounding box is high enough for at least one line.
|
||||||
if cursor.y > self.bounds.y1 {
|
if cursor.y > bottom {
|
||||||
sink.out_of_bounds();
|
sink.out_of_bounds();
|
||||||
return LayoutFit::OutOfBounds { processed_chars: 0 };
|
return LayoutFit::OutOfBounds {
|
||||||
|
processed_chars: 0,
|
||||||
|
height: 0,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
while !remaining_text.is_empty() {
|
while !remaining_text.is_empty() {
|
||||||
@ -185,7 +195,7 @@ impl TextLayout {
|
|||||||
sink.hyphen(*cursor, self);
|
sink.hyphen(*cursor, self);
|
||||||
}
|
}
|
||||||
// Check the amount of vertical space we have left.
|
// Check the amount of vertical space we have left.
|
||||||
if cursor.y + span.advance.y > self.bounds.y1 {
|
if cursor.y + span.advance.y > bottom {
|
||||||
if !remaining_text.is_empty() {
|
if !remaining_text.is_empty() {
|
||||||
// Append ellipsis to indicate more content is available, but only if we
|
// Append ellipsis to indicate more content is available, but only if we
|
||||||
// haven't already appended a hyphen.
|
// haven't already appended a hyphen.
|
||||||
@ -205,6 +215,7 @@ impl TextLayout {
|
|||||||
|
|
||||||
return LayoutFit::OutOfBounds {
|
return LayoutFit::OutOfBounds {
|
||||||
processed_chars: text.len() - remaining_text.len(),
|
processed_chars: text.len() - remaining_text.len(),
|
||||||
|
height: self.layout_height(init_cursor, *cursor),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Advance the cursor to the beginning of the next line.
|
// Advance the cursor to the beginning of the next line.
|
||||||
@ -220,38 +231,42 @@ impl TextLayout {
|
|||||||
|
|
||||||
LayoutFit::Fitting {
|
LayoutFit::Fitting {
|
||||||
processed_chars: text.len(),
|
processed_chars: text.len(),
|
||||||
size: Offset::new(
|
height: self.layout_height(init_cursor, *cursor),
|
||||||
self.bounds.width(),
|
|
||||||
cursor.y - init_cursor.y + self.text_font.line_height(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn measure_ops_height(self, ops: &mut dyn Iterator<Item = Op>) -> i32 {
|
pub fn measure_ops_height(self, ops: &mut dyn Iterator<Item = Op>) -> i32 {
|
||||||
match self.layout_ops(ops, &mut self.initial_cursor(), &mut TextNoOp) {
|
self.layout_ops(ops, &mut self.initial_cursor(), &mut TextNoOp)
|
||||||
LayoutFit::Fitting { size, .. } => size.y,
|
.height()
|
||||||
LayoutFit::OutOfBounds { processed_chars: 0 } => 0,
|
|
||||||
_ => self.bounds.height(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn measure_text_height(self, text: &[u8]) -> i32 {
|
pub fn measure_text_height(self, text: &[u8]) -> i32 {
|
||||||
match self.layout_text(text, &mut self.initial_cursor(), &mut TextNoOp) {
|
self.layout_text(text, &mut self.initial_cursor(), &mut TextNoOp)
|
||||||
LayoutFit::Fitting { size, .. } => size.y,
|
.height()
|
||||||
LayoutFit::OutOfBounds { processed_chars: 0 } => 0,
|
}
|
||||||
_ => self.bounds.height(),
|
|
||||||
}
|
fn layout_height(&self, init_cursor: Point, end_cursor: Point) -> i32 {
|
||||||
|
self.padding_top
|
||||||
|
+ self.text_font.text_height()
|
||||||
|
+ (end_cursor.y - init_cursor.y)
|
||||||
|
+ self.padding_bottom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LayoutFit {
|
pub enum LayoutFit {
|
||||||
/// Entire content fits. Bounding box is returned in `size`.
|
/// Entire content fits. Vertical size is returned in `height`.
|
||||||
Fitting {
|
Fitting { processed_chars: usize, height: i32 },
|
||||||
processed_chars: usize,
|
|
||||||
size: Offset,
|
|
||||||
},
|
|
||||||
/// Content fits partially or not at all.
|
/// Content fits partially or not at all.
|
||||||
OutOfBounds { processed_chars: usize },
|
OutOfBounds { processed_chars: usize, height: i32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutFit {
|
||||||
|
pub fn height(&self) -> i32 {
|
||||||
|
match self {
|
||||||
|
LayoutFit::Fitting { height, .. } => *height,
|
||||||
|
LayoutFit::OutOfBounds { height, .. } => *height,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor for text segment operations.
|
/// Visitor for text segment operations.
|
||||||
|
@ -9,7 +9,15 @@ use crate::ui::{
|
|||||||
use super::layout::{DefaultTextTheme, LayoutFit, TextLayout, TextNoOp, TextRenderer};
|
use super::layout::{DefaultTextTheme, LayoutFit, TextLayout, TextNoOp, TextRenderer};
|
||||||
|
|
||||||
pub const MAX_PARAGRAPHS: usize = 6;
|
pub const MAX_PARAGRAPHS: usize = 6;
|
||||||
pub const DEFAULT_SPACING: i32 = 3;
|
/// Maximum space between paragraphs. Actual result may be smaller (even 0) if
|
||||||
|
/// it would make paragraphs overflow the bounding box.
|
||||||
|
pub const DEFAULT_SPACING: i32 = 0;
|
||||||
|
/// Offset of paragraph text from the top of the paragraph bounding box. Tweak
|
||||||
|
/// these values to get nice alignment of baselines relative to the surrounding
|
||||||
|
/// components.
|
||||||
|
pub const PARAGRAPH_TOP_SPACE: i32 = -1;
|
||||||
|
/// Offset of paragraph bounding box bottom relative to bottom of its text.
|
||||||
|
pub const PARAGRAPH_BOTTOM_SPACE: i32 = 5;
|
||||||
|
|
||||||
pub struct Paragraphs<T> {
|
pub struct Paragraphs<T> {
|
||||||
area: Rect,
|
area: Rect,
|
||||||
@ -53,6 +61,8 @@ where
|
|||||||
content,
|
content,
|
||||||
TextLayout {
|
TextLayout {
|
||||||
text_font,
|
text_font,
|
||||||
|
padding_top: PARAGRAPH_TOP_SPACE,
|
||||||
|
padding_bottom: PARAGRAPH_BOTTOM_SPACE,
|
||||||
..TextLayout::new::<D>(self.area)
|
..TextLayout::new::<D>(self.area)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -228,9 +238,9 @@ where
|
|||||||
&mut TextNoOp,
|
&mut TextNoOp,
|
||||||
);
|
);
|
||||||
match fit {
|
match fit {
|
||||||
LayoutFit::Fitting { size, .. } => {
|
LayoutFit::Fitting { height, .. } => {
|
||||||
// Text fits, update remaining area.
|
// Text fits, update remaining area.
|
||||||
remaining_area = remaining_area.inset(Insets::top(size.y));
|
remaining_area = remaining_area.inset(Insets::top(height));
|
||||||
|
|
||||||
// Continue with start of next paragraph.
|
// Continue with start of next paragraph.
|
||||||
current.par += 1;
|
current.par += 1;
|
||||||
@ -238,7 +248,9 @@ where
|
|||||||
progress = true;
|
progress = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LayoutFit::OutOfBounds { processed_chars } => {
|
LayoutFit::OutOfBounds {
|
||||||
|
processed_chars, ..
|
||||||
|
} => {
|
||||||
// Text does not fit, assume whatever fits takes the entire remaining area.
|
// Text does not fit, assume whatever fits takes the entire remaining area.
|
||||||
current.chr += processed_chars;
|
current.chr += processed_chars;
|
||||||
if processed_chars == 0 && !progress {
|
if processed_chars == 0 && !progress {
|
||||||
|
@ -2,7 +2,7 @@ use super::theme;
|
|||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
component::{Child, Component, ComponentExt, Event, EventCtx},
|
component::{Child, Component, ComponentExt, Event, EventCtx},
|
||||||
display,
|
display,
|
||||||
geometry::Rect,
|
geometry::{Insets, Rect},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Frame<T, U> {
|
pub struct Frame<T, U> {
|
||||||
@ -26,14 +26,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn areas(area: Rect) -> (Rect, Rect) {
|
fn areas(area: Rect) -> (Rect, Rect) {
|
||||||
const HEADER_SPACE: i32 = 14;
|
// Same as PageLayout::BUTTON_SPACE.
|
||||||
let header_height = theme::FONT_BOLD.line_height() - theme::CONTENT_BORDER;
|
const TITLE_SPACE: i32 = 6;
|
||||||
|
|
||||||
let (header_area, content_area) = area.split_top(header_height);
|
let (title_area, content_area) = area.split_top(theme::FONT_BOLD.text_height());
|
||||||
let (_space, header_area) = header_area.split_left(theme::CONTENT_BORDER);
|
let title_area = title_area.inset(Insets::left(theme::CONTENT_BORDER));
|
||||||
let (_space, content_area) = content_area.split_top(HEADER_SPACE);
|
let content_area = content_area.inset(Insets::top(TITLE_SPACE));
|
||||||
|
|
||||||
(header_area, content_area)
|
(title_area, content_area)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub const GREY_LIGHT: Color = Color::rgb(168, 168, 168); // greyish
|
|||||||
pub const GREY_DARK: Color = Color::rgb(51, 51, 51); // black
|
pub const GREY_DARK: Color = Color::rgb(51, 51, 51); // black
|
||||||
|
|
||||||
// Commonly used corner radius (i.e. for buttons).
|
// Commonly used corner radius (i.e. for buttons).
|
||||||
pub const RADIUS: u8 = 4;
|
pub const RADIUS: u8 = 2;
|
||||||
|
|
||||||
// Size of icons in the UI (i.e. inside buttons).
|
// Size of icons in the UI (i.e. inside buttons).
|
||||||
pub const ICON_SIZE: i32 = 16;
|
pub const ICON_SIZE: i32 = 16;
|
||||||
@ -59,7 +59,7 @@ pub fn button_default() -> ButtonStyleSheet {
|
|||||||
background_color: BG,
|
background_color: BG,
|
||||||
border_color: BG,
|
border_color: BG,
|
||||||
border_radius: RADIUS,
|
border_radius: RADIUS,
|
||||||
border_width: 1,
|
border_width: 0,
|
||||||
},
|
},
|
||||||
active: &ButtonStyle {
|
active: &ButtonStyle {
|
||||||
font: FONT_BOLD,
|
font: FONT_BOLD,
|
||||||
@ -68,7 +68,7 @@ pub fn button_default() -> ButtonStyleSheet {
|
|||||||
background_color: BG,
|
background_color: BG,
|
||||||
border_color: FG,
|
border_color: FG,
|
||||||
border_radius: RADIUS,
|
border_radius: RADIUS,
|
||||||
border_width: 1,
|
border_width: 0,
|
||||||
},
|
},
|
||||||
disabled: &ButtonStyle {
|
disabled: &ButtonStyle {
|
||||||
font: FONT_BOLD,
|
font: FONT_BOLD,
|
||||||
@ -77,7 +77,7 @@ pub fn button_default() -> ButtonStyleSheet {
|
|||||||
background_color: BG,
|
background_color: BG,
|
||||||
border_color: BG,
|
border_color: BG,
|
||||||
border_radius: RADIUS,
|
border_radius: RADIUS,
|
||||||
border_width: 1,
|
border_width: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ pub fn button_confirm() -> ButtonStyleSheet {
|
|||||||
background_color: BG,
|
background_color: BG,
|
||||||
border_color: BG,
|
border_color: BG,
|
||||||
border_radius: RADIUS,
|
border_radius: RADIUS,
|
||||||
border_width: 1,
|
border_width: 0,
|
||||||
},
|
},
|
||||||
active: &ButtonStyle {
|
active: &ButtonStyle {
|
||||||
font: FONT_BOLD,
|
font: FONT_BOLD,
|
||||||
@ -100,7 +100,7 @@ pub fn button_confirm() -> ButtonStyleSheet {
|
|||||||
background_color: BG,
|
background_color: BG,
|
||||||
border_color: FG,
|
border_color: FG,
|
||||||
border_radius: RADIUS,
|
border_radius: RADIUS,
|
||||||
border_width: 1,
|
border_width: 0,
|
||||||
},
|
},
|
||||||
disabled: &ButtonStyle {
|
disabled: &ButtonStyle {
|
||||||
font: FONT_BOLD,
|
font: FONT_BOLD,
|
||||||
@ -109,7 +109,7 @@ pub fn button_confirm() -> ButtonStyleSheet {
|
|||||||
background_color: BG,
|
background_color: BG,
|
||||||
border_color: BG,
|
border_color: BG,
|
||||||
border_radius: RADIUS,
|
border_radius: RADIUS,
|
||||||
border_width: 1,
|
border_width: 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user