feat(core/ui): vertical alignment for FormattedText

[no changelog]
pull/2966/head
Martin Milata 1 year ago
parent f481590bb7
commit 312f6899c7

@ -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<T: StringType + Clone> {
op_layout: OpTextLayout<T>,
vertical: Alignment,
char_offset: usize,
y_offset: i16,
}
impl<T: StringType + Clone> FormattedText<T> {
pub fn new(op_layout: OpTextLayout<T>) -> 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<T: StringType + Clone> Paginate for FormattedText<T> {
// 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<T: StringType + Clone> Paginate for FormattedText<T> {
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<T: StringType + Clone> Component for FormattedText<T> {
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
}

@ -46,14 +46,19 @@ impl<'a, T: StringType + Clone + 'a> OpTextLayout<T> {
/// 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<T: StringType + Clone> OpTextLayout<T> {
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)]

Loading…
Cancel
Save