diff --git a/core/embed/rust/src/ui/component/text/formatted.rs b/core/embed/rust/src/ui/component/text/formatted.rs index 96183df59..9866c5c8a 100644 --- a/core/embed/rust/src/ui/component/text/formatted.rs +++ b/core/embed/rust/src/ui/component/text/formatted.rs @@ -2,7 +2,7 @@ use crate::{ strutil::StringType, ui::{ component::{Component, Event, EventCtx, Never, Paginate}, - geometry::Rect, + geometry::{Alignment, Offset, Rect}, }, }; @@ -14,19 +14,42 @@ use super::{ #[derive(Clone)] pub struct FormattedText { op_layout: OpTextLayout, + vertical: Alignment, char_offset: usize, + y_offset: i16, } impl FormattedText { pub fn new(op_layout: OpTextLayout) -> Self { Self { op_layout, + vertical: Alignment::Start, char_offset: 0, + y_offset: 0, } } + pub fn vertically_aligned(mut self, align: Alignment) -> Self { + self.vertical = align; + self + } + fn layout_content(&mut self, sink: &mut dyn LayoutSink) -> LayoutFit { - self.op_layout.layout_content(self.char_offset, sink) + self.op_layout + .layout_ops(self.char_offset, Offset::y(self.y_offset), sink) + } + + fn align_vertically(&mut self, content_height: i16) { + let bounds_height = self.op_layout.layout.bounds.height(); + if content_height >= bounds_height { + self.y_offset = 0; + return; + } + self.y_offset = match self.vertical { + Alignment::Start => 0, + Alignment::Center => (bounds_height - content_height) / 2, + Alignment::End => bounds_height - content_height, + } } } @@ -73,8 +96,8 @@ impl Paginate for FormattedText { // Looping through the content until we arrive at // the wanted page. + let mut fit = self.layout_content(&mut TextNoOp); while active_page < to_page { - let fit = self.layout_content(&mut TextNoOp); match fit { LayoutFit::Fitting { .. } => { break; // TODO: We should consider if there's more content @@ -86,9 +109,11 @@ impl Paginate for FormattedText { active_page += 1; char_offset += processed_chars; self.char_offset = char_offset; + fit = self.layout_content(&mut TextNoOp); } } } + self.align_vertically(fit.height()); } } @@ -97,6 +122,8 @@ impl Component for FormattedText { fn place(&mut self, bounds: Rect) -> Rect { self.op_layout.place(bounds); + let height = self.layout_content(&mut TextNoOp).height(); + self.align_vertically(height); bounds } diff --git a/core/embed/rust/src/ui/component/text/op.rs b/core/embed/rust/src/ui/component/text/op.rs index aef23220d..a3a3b428c 100644 --- a/core/embed/rust/src/ui/component/text/op.rs +++ b/core/embed/rust/src/ui/component/text/op.rs @@ -46,14 +46,19 @@ impl<'a, T: StringType + Clone + 'a> OpTextLayout { /// Send the layout's content into a sink. pub fn layout_content(&mut self, skip_bytes: usize, sink: &mut dyn LayoutSink) -> LayoutFit { - self.layout_ops(skip_bytes, sink) + self.layout_ops(skip_bytes, Offset::zero(), sink) } /// Perform some operations defined on `Op` for a list of those `Op`s /// - e.g. changing the color, changing the font or rendering the text. - fn layout_ops(&mut self, skip_bytes: usize, sink: &mut dyn LayoutSink) -> LayoutFit { + pub fn layout_ops( + &mut self, + skip_bytes: usize, + offset: Offset, + sink: &mut dyn LayoutSink, + ) -> LayoutFit { // TODO: make sure it is called when we have the current font (not sooner) - let mut cursor = &mut self.layout.initial_cursor(); + let mut cursor = &mut (self.layout.initial_cursor() + offset); let init_cursor = *cursor; let mut total_processed_chars = 0; @@ -219,6 +224,10 @@ impl OpTextLayout { pub fn text_bold(self, text: T) -> Self { self.font(Font::BOLD).text(text) } + + pub fn text_demibold(self, text: T) -> Self { + self.font(Font::DEMIBOLD).text(text) + } } #[derive(Clone)]