mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-22 04:33:13 +00:00
fix(text): truncate based on alignment (#1432)
This is a follow-up PR to https://github.com/ratatui/ratatui/pull/987, which implemented alignment-aware truncation for the `Line` widget. However, the truncation only checked the `Line::alignment` field, and any alignment inherited from a parent's `Text::alignment` field would not be used. This commit updates the truncation of `Line` to depend both on the individual `Line::alignment`, and on any alignment inherited from the parent's `Text::alignment`. Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
This commit is contained in:
parent
381ec75329
commit
a52ee82fc7
2 changed files with 48 additions and 19 deletions
21
src/text/line.rs
Normal file → Executable file
21
src/text/line.rs
Normal file → Executable file
|
@ -687,6 +687,21 @@ impl Widget for Line<'_> {
|
|||
|
||||
impl WidgetRef for Line<'_> {
|
||||
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_with_alignment(area, buf, None);
|
||||
}
|
||||
}
|
||||
|
||||
impl Line<'_> {
|
||||
/// An internal implementation method for `WidgetRef::render_ref`
|
||||
///
|
||||
/// Allows the parent widget to define a default alignment, to be
|
||||
/// used if `Line::alignment` is `None`.
|
||||
pub(crate) fn render_with_alignment(
|
||||
&self,
|
||||
area: Rect,
|
||||
buf: &mut Buffer,
|
||||
parent_alignment: Option<Alignment>,
|
||||
) {
|
||||
let area = area.intersection(buf.area);
|
||||
if area.is_empty() {
|
||||
return;
|
||||
|
@ -699,10 +714,12 @@ impl WidgetRef for Line<'_> {
|
|||
|
||||
buf.set_style(area, self.style);
|
||||
|
||||
let alignment = self.alignment.or(parent_alignment);
|
||||
|
||||
let area_width = usize::from(area.width);
|
||||
let can_render_complete_line = line_width <= area_width;
|
||||
if can_render_complete_line {
|
||||
let indent_width = match self.alignment {
|
||||
let indent_width = match alignment {
|
||||
Some(Alignment::Center) => (area_width.saturating_sub(line_width)) / 2,
|
||||
Some(Alignment::Right) => area_width.saturating_sub(line_width),
|
||||
Some(Alignment::Left) | None => 0,
|
||||
|
@ -713,7 +730,7 @@ impl WidgetRef for Line<'_> {
|
|||
} else {
|
||||
// There is not enough space to render the whole line. As the right side is truncated by
|
||||
// the area width, only truncate the left.
|
||||
let skip_width = match self.alignment {
|
||||
let skip_width = match alignment {
|
||||
Some(Alignment::Center) => (line_width.saturating_sub(area_width)) / 2,
|
||||
Some(Alignment::Right) => line_width.saturating_sub(area_width),
|
||||
Some(Alignment::Left) | None => 0,
|
||||
|
|
46
src/text/text.rs
Normal file → Executable file
46
src/text/text.rs
Normal file → Executable file
|
@ -735,23 +735,8 @@ impl WidgetRef for Text<'_> {
|
|||
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
||||
let area = area.intersection(buf.area);
|
||||
buf.set_style(area, self.style);
|
||||
for (line, row) in self.iter().zip(area.rows()) {
|
||||
let line_width = line.width() as u16;
|
||||
|
||||
let x_offset = match (self.alignment, line.alignment) {
|
||||
(Some(Alignment::Center), None) => area.width.saturating_sub(line_width) / 2,
|
||||
(Some(Alignment::Right), None) => area.width.saturating_sub(line_width),
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
let line_area = Rect {
|
||||
x: area.x + x_offset,
|
||||
y: row.y,
|
||||
width: area.width - x_offset,
|
||||
height: 1,
|
||||
};
|
||||
|
||||
line.render(line_area, buf);
|
||||
for (line, line_area) in self.iter().zip(area.rows()) {
|
||||
line.render_with_alignment(line_area, buf, self.alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1196,6 +1181,33 @@ mod tests {
|
|||
assert_eq!(buf, Buffer::with_lines([" foo "]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_right_aligned_with_truncation() {
|
||||
let text = Text::from("123456789").alignment(Alignment::Right);
|
||||
let area = Rect::new(0, 0, 5, 1);
|
||||
let mut buf = Buffer::empty(area);
|
||||
text.render(area, &mut buf);
|
||||
assert_eq!(buf, Buffer::with_lines(["56789"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_centered_odd_with_truncation() {
|
||||
let text = Text::from("123456789").alignment(Alignment::Center);
|
||||
let area = Rect::new(0, 0, 5, 1);
|
||||
let mut buf = Buffer::empty(area);
|
||||
text.render(area, &mut buf);
|
||||
assert_eq!(buf, Buffer::with_lines(["34567"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_centered_even_with_truncation() {
|
||||
let text = Text::from("123456789").alignment(Alignment::Center);
|
||||
let area = Rect::new(0, 0, 6, 1);
|
||||
let mut buf = Buffer::empty(area);
|
||||
text.render(area, &mut buf);
|
||||
assert_eq!(buf, Buffer::with_lines(["234567"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_one_line_right() {
|
||||
let text = Text::from(vec![
|
||||
|
|
Loading…
Reference in a new issue