You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.9 KiB
128 lines
3.9 KiB
use crate::{
|
|
strutil::TString,
|
|
ui::{
|
|
display::{Color, Font},
|
|
geometry::{Alignment, Rect},
|
|
shape::Renderer,
|
|
},
|
|
};
|
|
|
|
use super::{
|
|
layout::{LayoutFit, TextLayout},
|
|
TextStyle,
|
|
};
|
|
|
|
/// Draws longer multiline texts inside an area.
|
|
/// Splits lines on word boundaries/whitespace.
|
|
/// When a word is too long to fit one line, splitting
|
|
/// it on multiple lines with "-" at the line-ends.
|
|
///
|
|
/// If it fits, returns the rest of the area.
|
|
/// If it does not fit, returns `None`.
|
|
pub fn text_multiline(
|
|
area: Rect,
|
|
text: TString<'_>,
|
|
font: Font,
|
|
fg_color: Color,
|
|
bg_color: Color,
|
|
alignment: Alignment,
|
|
) -> Option<Rect> {
|
|
let text_style = TextStyle::new(font, fg_color, bg_color, fg_color, fg_color);
|
|
let text_layout = TextLayout::new(text_style)
|
|
.with_bounds(area)
|
|
.with_align(alignment);
|
|
let layout_fit = text.map(|t| text_layout.render_text(t));
|
|
match layout_fit {
|
|
LayoutFit::Fitting { height, .. } => Some(area.split_top(height).1),
|
|
LayoutFit::OutOfBounds { .. } => None,
|
|
}
|
|
}
|
|
|
|
/// Draws longer multiline texts inside an area.
|
|
/// Splits lines on word boundaries/whitespace.
|
|
/// When a word is too long to fit one line, splitting
|
|
/// it on multiple lines with "-" at the line-ends.
|
|
///
|
|
/// If it fits, returns the rest of the area.
|
|
/// If it does not fit, returns `None`.
|
|
pub fn text_multiline2<'s>(
|
|
target: &mut impl Renderer<'s>,
|
|
area: Rect,
|
|
text: TString<'_>,
|
|
font: Font,
|
|
fg_color: Color,
|
|
bg_color: Color,
|
|
alignment: Alignment,
|
|
) -> Option<Rect> {
|
|
let text_style = TextStyle::new(font, fg_color, bg_color, fg_color, fg_color);
|
|
let text_layout = TextLayout::new(text_style)
|
|
.with_bounds(area)
|
|
.with_align(alignment);
|
|
let layout_fit = text.map(|t| text_layout.render_text2(t, target));
|
|
match layout_fit {
|
|
LayoutFit::Fitting { height, .. } => Some(area.split_top(height).1),
|
|
LayoutFit::OutOfBounds { .. } => None,
|
|
}
|
|
}
|
|
|
|
/// Same as `text_multiline` above, but aligns the text to the bottom of the
|
|
/// area.
|
|
pub fn text_multiline_bottom(
|
|
area: Rect,
|
|
text: TString<'_>,
|
|
font: Font,
|
|
fg_color: Color,
|
|
bg_color: Color,
|
|
alignment: Alignment,
|
|
) -> Option<Rect> {
|
|
let text_style = TextStyle::new(font, fg_color, bg_color, fg_color, fg_color);
|
|
let mut text_layout = TextLayout::new(text_style)
|
|
.with_bounds(area)
|
|
.with_align(alignment);
|
|
// When text fits the area, displaying it in the bottom part.
|
|
// When not, render it "normally".
|
|
text.map(|t| match text_layout.fit_text(t) {
|
|
LayoutFit::Fitting { height, .. } => {
|
|
let (top, bottom) = area.split_bottom(height);
|
|
text_layout = text_layout.with_bounds(bottom);
|
|
text_layout.render_text(t);
|
|
Some(top)
|
|
}
|
|
LayoutFit::OutOfBounds { .. } => {
|
|
text_layout.render_text(t);
|
|
None
|
|
}
|
|
})
|
|
}
|
|
|
|
/// Same as `text_multiline` above, but aligns the text to the bottom of the
|
|
/// area.
|
|
pub fn text_multiline_bottom2<'s>(
|
|
target: &mut impl Renderer<'s>,
|
|
area: Rect,
|
|
text: TString<'_>,
|
|
font: Font,
|
|
fg_color: Color,
|
|
bg_color: Color,
|
|
alignment: Alignment,
|
|
) -> Option<Rect> {
|
|
let text_style = TextStyle::new(font, fg_color, bg_color, fg_color, fg_color);
|
|
let mut text_layout = TextLayout::new(text_style)
|
|
.with_bounds(area)
|
|
.with_align(alignment);
|
|
// When text fits the area, displaying it in the bottom part.
|
|
// When not, render it "normally".
|
|
text.map(|t| match text_layout.fit_text(t) {
|
|
LayoutFit::Fitting { height, .. } => {
|
|
let (top, bottom) = area.split_bottom(height);
|
|
text_layout = text_layout.with_bounds(bottom);
|
|
text_layout.render_text2(t, target);
|
|
Some(top)
|
|
}
|
|
LayoutFit::OutOfBounds { .. } => {
|
|
text_layout.render_text2(t, target);
|
|
None
|
|
}
|
|
})
|
|
}
|