fix(core/rust/ui): adjust spacing for confirm_action

[no changelog]
mmilata/tt-pin-keyboard
Martin Milata 2 years ago
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…
Cancel
Save