mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-25 06:00:34 +00:00
fix(block): fix crash on empty right aligned title (#933)
- Simplified implementation of the rendering for block. - Introduces a subtle rendering change where centered titles that are odd in length will now be rendered one character to the left compared to before. This aligns with other places that we render centered text and is a more consistent behavior. See https://github.com/ratatui-org/ratatui/pull/807#discussion_r1455645954 for another example of this. Fixes: https://github.com/ratatui-org/ratatui/pull/929
This commit is contained in:
parent
8fb46301a0
commit
2202059259
2 changed files with 513 additions and 401 deletions
|
@ -5,6 +5,7 @@
|
|||
//! In its simplest form, a `Block` is a [border](Borders) around another widget. It can have a
|
||||
//! [title](Block::title) and [padding](Block::padding).
|
||||
|
||||
use itertools::Itertools;
|
||||
use strum::{Display, EnumString};
|
||||
|
||||
use crate::{prelude::*, symbols::border, widgets::Borders};
|
||||
|
@ -147,7 +148,6 @@ pub struct Block<'a> {
|
|||
titles_alignment: Alignment,
|
||||
/// The default position of the titles that don't have one
|
||||
titles_position: Position,
|
||||
|
||||
/// Visible borders
|
||||
borders: Borders,
|
||||
/// Border style
|
||||
|
@ -525,9 +525,11 @@ impl Widget for Block<'_> {
|
|||
|
||||
impl WidgetRef for Block<'_> {
|
||||
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
||||
let area = area.intersection(buf.area);
|
||||
if area.is_empty() {
|
||||
return;
|
||||
}
|
||||
buf.set_style(area, self.style);
|
||||
self.render_borders(area, buf);
|
||||
self.render_titles(area, buf);
|
||||
}
|
||||
|
@ -535,185 +537,227 @@ impl WidgetRef for Block<'_> {
|
|||
|
||||
impl Block<'_> {
|
||||
fn render_borders(&self, area: Rect, buf: &mut Buffer) {
|
||||
buf.set_style(area, self.style);
|
||||
let symbols = self.border_set;
|
||||
self.render_left_side(area, buf);
|
||||
self.render_top_side(area, buf);
|
||||
self.render_right_side(area, buf);
|
||||
self.render_bottom_side(area, buf);
|
||||
|
||||
// Sides
|
||||
if self.borders.intersects(Borders::LEFT) {
|
||||
for y in area.top()..area.bottom() {
|
||||
buf.get_mut(area.left(), y)
|
||||
.set_symbol(symbols.vertical_left)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
if self.borders.intersects(Borders::TOP) {
|
||||
for x in area.left()..area.right() {
|
||||
buf.get_mut(x, area.top())
|
||||
.set_symbol(symbols.horizontal_top)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
if self.borders.intersects(Borders::RIGHT) {
|
||||
let x = area.right() - 1;
|
||||
for y in area.top()..area.bottom() {
|
||||
buf.get_mut(x, y)
|
||||
.set_symbol(symbols.vertical_right)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
if self.borders.intersects(Borders::BOTTOM) {
|
||||
let y = area.bottom() - 1;
|
||||
for x in area.left()..area.right() {
|
||||
buf.get_mut(x, y)
|
||||
.set_symbol(symbols.horizontal_bottom)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
|
||||
// Corners
|
||||
if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) {
|
||||
buf.get_mut(area.right() - 1, area.bottom() - 1)
|
||||
.set_symbol(symbols.bottom_right)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
if self.borders.contains(Borders::RIGHT | Borders::TOP) {
|
||||
buf.get_mut(area.right() - 1, area.top())
|
||||
.set_symbol(symbols.top_right)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
if self.borders.contains(Borders::LEFT | Borders::BOTTOM) {
|
||||
buf.get_mut(area.left(), area.bottom() - 1)
|
||||
.set_symbol(symbols.bottom_left)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
if self.borders.contains(Borders::LEFT | Borders::TOP) {
|
||||
buf.get_mut(area.left(), area.top())
|
||||
.set_symbol(symbols.top_left)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
|
||||
/* Titles Rendering */
|
||||
fn get_title_y(&self, position: Position, area: Rect) -> u16 {
|
||||
match position {
|
||||
Position::Bottom => area.bottom() - 1,
|
||||
Position::Top => area.top(),
|
||||
}
|
||||
}
|
||||
|
||||
fn title_filter(&self, title: &Title, alignment: Alignment, position: Position) -> bool {
|
||||
title.alignment.unwrap_or(self.titles_alignment) == alignment
|
||||
&& title.position.unwrap_or(self.titles_position) == position
|
||||
}
|
||||
|
||||
fn calculate_title_area_offsets(&self, area: Rect) -> (u16, u16, u16) {
|
||||
let left_border_dx = u16::from(self.borders.intersects(Borders::LEFT));
|
||||
let right_border_dx = u16::from(self.borders.intersects(Borders::RIGHT));
|
||||
|
||||
let title_area_width = area
|
||||
.width
|
||||
.saturating_sub(left_border_dx)
|
||||
.saturating_sub(right_border_dx);
|
||||
|
||||
(left_border_dx, right_border_dx, title_area_width)
|
||||
}
|
||||
|
||||
fn render_left_titles(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
let (left_border_dx, _, title_area_width) = self.calculate_title_area_offsets(area);
|
||||
|
||||
let mut current_offset = left_border_dx;
|
||||
self.titles
|
||||
.iter()
|
||||
.filter(|title| self.title_filter(title, Alignment::Left, position))
|
||||
.for_each(|title| {
|
||||
let title_x = current_offset;
|
||||
current_offset += title.content.width() as u16 + 1;
|
||||
|
||||
// Clone the title's content, applying block title style then the title style
|
||||
let mut content = title.content.clone();
|
||||
for span in content.spans.iter_mut() {
|
||||
span.style = self.titles_style.patch(span.style);
|
||||
}
|
||||
|
||||
buf.set_line(
|
||||
title_x + area.left(),
|
||||
self.get_title_y(position, area),
|
||||
&content,
|
||||
title_area_width,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn render_center_titles(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
let (_, _, title_area_width) = self.calculate_title_area_offsets(area);
|
||||
|
||||
let titles = self
|
||||
.titles
|
||||
.iter()
|
||||
.filter(|title| self.title_filter(title, Alignment::Center, position));
|
||||
|
||||
let titles_sum = titles
|
||||
.clone()
|
||||
.fold(-1, |acc, f| acc + f.content.width() as i16 + 1); // First element isn't spaced
|
||||
|
||||
let mut current_offset = area.width.saturating_sub(titles_sum as u16) / 2;
|
||||
titles.for_each(|title| {
|
||||
let title_x = current_offset;
|
||||
current_offset += title.content.width() as u16 + 1;
|
||||
|
||||
// Clone the title's content, applying block title style then the title style
|
||||
let mut content = title.content.clone();
|
||||
for span in content.spans.iter_mut() {
|
||||
span.style = self.titles_style.patch(span.style);
|
||||
}
|
||||
|
||||
buf.set_line(
|
||||
title_x + area.left(),
|
||||
self.get_title_y(position, area),
|
||||
&content,
|
||||
title_area_width,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn render_right_titles(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
let (_, right_border_dx, title_area_width) = self.calculate_title_area_offsets(area);
|
||||
|
||||
let mut current_offset = right_border_dx;
|
||||
self.titles
|
||||
.iter()
|
||||
.filter(|title| self.title_filter(title, Alignment::Right, position))
|
||||
.rev() // so that the titles appear in the order they have been set
|
||||
.for_each(|title| {
|
||||
current_offset += title.content.width() as u16 + 1;
|
||||
let title_x = current_offset - 1; // First element isn't spaced
|
||||
|
||||
// Clone the title's content, applying block title style then the title style
|
||||
let mut content = title.content.clone();
|
||||
for span in content.spans.iter_mut() {
|
||||
span.style = self.titles_style.patch(span.style);
|
||||
}
|
||||
|
||||
buf.set_line(
|
||||
area.width.saturating_sub(title_x) + area.left(),
|
||||
self.get_title_y(position, area),
|
||||
&content,
|
||||
title_area_width,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn render_title_position(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
// Note: the order in which these functions are called define the overlapping behavior
|
||||
self.render_right_titles(position, area, buf);
|
||||
self.render_center_titles(position, area, buf);
|
||||
self.render_left_titles(position, area, buf);
|
||||
self.render_bottom_right_corner(buf, area);
|
||||
self.render_top_right_corner(buf, area);
|
||||
self.render_bottom_left_corner(buf, area);
|
||||
self.render_top_left_corner(buf, area);
|
||||
}
|
||||
|
||||
fn render_titles(&self, area: Rect, buf: &mut Buffer) {
|
||||
self.render_title_position(Position::Top, area, buf);
|
||||
self.render_title_position(Position::Bottom, area, buf);
|
||||
}
|
||||
|
||||
fn render_title_position(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
// NOTE: the order in which these functions are called defines the overlapping behavior
|
||||
self.render_right_titles(position, area, buf);
|
||||
self.render_center_titles(position, area, buf);
|
||||
self.render_left_titles(position, area, buf);
|
||||
}
|
||||
|
||||
fn render_left_side(&self, area: Rect, buf: &mut Buffer) {
|
||||
if self.borders.contains(Borders::LEFT) {
|
||||
for y in area.top()..area.bottom() {
|
||||
buf.get_mut(area.left(), y)
|
||||
.set_symbol(self.border_set.vertical_left)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_top_side(&self, area: Rect, buf: &mut Buffer) {
|
||||
if self.borders.contains(Borders::TOP) {
|
||||
for x in area.left()..area.right() {
|
||||
buf.get_mut(x, area.top())
|
||||
.set_symbol(self.border_set.horizontal_top)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_right_side(&self, area: Rect, buf: &mut Buffer) {
|
||||
if self.borders.contains(Borders::RIGHT) {
|
||||
let x = area.right() - 1;
|
||||
for y in area.top()..area.bottom() {
|
||||
buf.get_mut(x, y)
|
||||
.set_symbol(self.border_set.vertical_right)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_bottom_side(&self, area: Rect, buf: &mut Buffer) {
|
||||
if self.borders.contains(Borders::BOTTOM) {
|
||||
let y = area.bottom() - 1;
|
||||
for x in area.left()..area.right() {
|
||||
buf.get_mut(x, y)
|
||||
.set_symbol(self.border_set.horizontal_bottom)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render_bottom_right_corner(&self, buf: &mut Buffer, area: Rect) {
|
||||
if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) {
|
||||
buf.get_mut(area.right() - 1, area.bottom() - 1)
|
||||
.set_symbol(self.border_set.bottom_right)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_top_right_corner(&self, buf: &mut Buffer, area: Rect) {
|
||||
if self.borders.contains(Borders::RIGHT | Borders::TOP) {
|
||||
buf.get_mut(area.right() - 1, area.top())
|
||||
.set_symbol(self.border_set.top_right)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_bottom_left_corner(&self, buf: &mut Buffer, area: Rect) {
|
||||
if self.borders.contains(Borders::LEFT | Borders::BOTTOM) {
|
||||
buf.get_mut(area.left(), area.bottom() - 1)
|
||||
.set_symbol(self.border_set.bottom_left)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_top_left_corner(&self, buf: &mut Buffer, area: Rect) {
|
||||
if self.borders.contains(Borders::LEFT | Borders::TOP) {
|
||||
buf.get_mut(area.left(), area.top())
|
||||
.set_symbol(self.border_set.top_left)
|
||||
.set_style(self.border_style);
|
||||
}
|
||||
}
|
||||
|
||||
/// Render titles aligned to the right of the block
|
||||
///
|
||||
/// Currently (due to the way lines are truncated), the right side of the leftmost title will
|
||||
/// be cut off if the block is too small to fit all titles. This is not ideal and should be
|
||||
/// the left side of that leftmost that is cut off. This is due to the line being truncated
|
||||
/// incorrectly. See https://github.com/ratatui-org/ratatui/issues/932
|
||||
fn render_right_titles(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
let titles = self.filtered_titles(position, Alignment::Right);
|
||||
let mut titles_area = self.titles_area(area, position);
|
||||
|
||||
// render titles in reverse order to align them to the right
|
||||
for title in titles.rev() {
|
||||
if titles_area.is_empty() {
|
||||
break;
|
||||
}
|
||||
let title_width = title.content.width() as u16;
|
||||
let title_area = Rect {
|
||||
x: titles_area
|
||||
.right()
|
||||
.saturating_sub(title_width)
|
||||
.max(titles_area.left()),
|
||||
..titles_area
|
||||
};
|
||||
buf.set_style(title_area, self.titles_style);
|
||||
title.content.render_ref(title_area, buf);
|
||||
|
||||
// bump the width of the titles area to the left
|
||||
titles_area.width = titles_area
|
||||
.width
|
||||
.saturating_sub(title_width)
|
||||
.saturating_sub(1); // space between titles
|
||||
}
|
||||
}
|
||||
|
||||
/// Render titles in the center of the block
|
||||
///
|
||||
/// Currently this method aligns the titles to the left inside a centered area. This is not
|
||||
/// ideal and should be fixed in the future to align the titles to the center of the block and
|
||||
/// truncate both sides of the titles if the block is too small to fit all titles.
|
||||
fn render_center_titles(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
let titles = self
|
||||
.filtered_titles(position, Alignment::Center)
|
||||
.collect_vec();
|
||||
let total_width = titles
|
||||
.iter()
|
||||
.map(|title| title.content.width() as u16 + 1) // space between titles
|
||||
.sum::<u16>()
|
||||
.saturating_sub(1); // no space for the last title
|
||||
|
||||
let titles_area = self.titles_area(area, position);
|
||||
let mut titles_area = Rect {
|
||||
x: titles_area.left() + (titles_area.width.saturating_sub(total_width) / 2),
|
||||
..titles_area
|
||||
};
|
||||
for title in titles {
|
||||
if titles_area.is_empty() {
|
||||
break;
|
||||
}
|
||||
let title_width = title.content.width() as u16;
|
||||
let title_area = Rect {
|
||||
width: title_width.min(titles_area.width),
|
||||
..titles_area
|
||||
};
|
||||
buf.set_style(title_area, self.titles_style);
|
||||
title.content.render_ref(title_area, buf);
|
||||
|
||||
// bump the titles area to the right and reduce its width
|
||||
titles_area.x = titles_area.x.saturating_add(title_width + 1);
|
||||
titles_area.width = titles_area.width.saturating_sub(title_width + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Render titles aligned to the left of the block
|
||||
fn render_left_titles(&self, position: Position, area: Rect, buf: &mut Buffer) {
|
||||
let titles = self.filtered_titles(position, Alignment::Left);
|
||||
let mut titles_area = self.titles_area(area, position);
|
||||
for title in titles {
|
||||
if titles_area.is_empty() {
|
||||
break;
|
||||
}
|
||||
let title_width = title.content.width() as u16;
|
||||
let title_area = Rect {
|
||||
width: title_width.min(titles_area.width),
|
||||
..titles_area
|
||||
};
|
||||
buf.set_style(title_area, self.titles_style);
|
||||
title.content.render_ref(title_area, buf);
|
||||
|
||||
// bump the titles area to the right and reduce its width
|
||||
titles_area.x = titles_area.x.saturating_add(title_width + 1);
|
||||
titles_area.width = titles_area.width.saturating_sub(title_width + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the titles that match the position and alignment
|
||||
fn filtered_titles(
|
||||
&self,
|
||||
position: Position,
|
||||
alignment: Alignment,
|
||||
) -> impl DoubleEndedIterator<Item = &Title> {
|
||||
self.titles.iter().filter(move |title| {
|
||||
title.position.unwrap_or(self.titles_position) == position
|
||||
&& title.alignment.unwrap_or(self.titles_alignment) == alignment
|
||||
})
|
||||
}
|
||||
|
||||
/// An area that is one line tall and spans the width of the block excluding the borders and
|
||||
/// is positioned at the top or bottom of the block.
|
||||
fn titles_area(&self, area: Rect, position: Position) -> Rect {
|
||||
let left_border = u16::from(self.borders.contains(Borders::LEFT));
|
||||
let right_border = u16::from(self.borders.contains(Borders::RIGHT));
|
||||
Rect {
|
||||
x: area.left() + left_border,
|
||||
y: match position {
|
||||
Position::Top => area.top(),
|
||||
Position::Bottom => area.bottom() - 1,
|
||||
},
|
||||
width: area
|
||||
.width
|
||||
.saturating_sub(left_border)
|
||||
.saturating_sub(right_border),
|
||||
height: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension trait for [`Block`] that provides some convenience methods.
|
||||
|
@ -752,7 +796,7 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::{
|
||||
assert_buffer_eq,
|
||||
layout::Rect,
|
||||
layout::{Alignment, Rect},
|
||||
style::{Color, Modifier, Stylize},
|
||||
};
|
||||
|
||||
|
@ -1120,6 +1164,24 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
/// This is a regression test for bug https://github.com/ratatui-org/ratatui/issues/929
|
||||
#[test]
|
||||
fn render_right_aligned_empty_title() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::default()
|
||||
.title("")
|
||||
.title_alignment(Alignment::Right)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
buffer,
|
||||
Buffer::with_lines(vec![
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn title_position() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 4, 2));
|
||||
|
|
|
@ -15,21 +15,11 @@ use ratatui::{
|
|||
fn widgets_block_renders() {
|
||||
let backend = TestBackend::new(10, 10);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
let block = Block::default()
|
||||
.title(Span::styled("Title", Style::default().fg(Color::LightBlue)))
|
||||
.borders(Borders::ALL);
|
||||
terminal
|
||||
.draw(|f| {
|
||||
let block = Block::default()
|
||||
.title(Span::styled("Title", Style::default().fg(Color::LightBlue)))
|
||||
.borders(Borders::ALL);
|
||||
f.render_widget(
|
||||
block,
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 8,
|
||||
height: 8,
|
||||
},
|
||||
);
|
||||
})
|
||||
.draw(|frame| frame.render_widget(block, Rect::new(0, 0, 8, 8)))
|
||||
.unwrap();
|
||||
let mut expected = Buffer::with_lines(vec![
|
||||
"┌Title─┐ ",
|
||||
|
@ -51,16 +41,15 @@ fn widgets_block_renders() {
|
|||
|
||||
#[test]
|
||||
fn widgets_block_titles_overlap() {
|
||||
let test_case = |block, area: Rect, expected| {
|
||||
#[track_caller]
|
||||
fn test_case(block: Block, area: Rect, expected: Buffer) {
|
||||
let backend = TestBackend::new(area.width, area.height);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
terminal
|
||||
.draw(|f| {
|
||||
f.render_widget(block, area);
|
||||
})
|
||||
.draw(|frame| frame.render_widget(block, area))
|
||||
.unwrap();
|
||||
terminal.backend().assert_buffer(&expected);
|
||||
};
|
||||
}
|
||||
|
||||
// Left overrides the center
|
||||
test_case(
|
||||
|
@ -68,12 +57,7 @@ fn widgets_block_titles_overlap() {
|
|||
.title(Title::from("aaaaa").alignment(Alignment::Left))
|
||||
.title(Title::from("bbb").alignment(Alignment::Center))
|
||||
.title(Title::from("ccc").alignment(Alignment::Right)),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 10, 1),
|
||||
Buffer::with_lines(vec!["aaaaab ccc"]),
|
||||
);
|
||||
|
||||
|
@ -83,12 +67,7 @@ fn widgets_block_titles_overlap() {
|
|||
.title(Title::from("aaaaa").alignment(Alignment::Left))
|
||||
.title(Title::from("bbbbb").alignment(Alignment::Center))
|
||||
.title(Title::from("ccccc").alignment(Alignment::Right)),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 11,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 11, 1),
|
||||
Buffer::with_lines(vec!["aaaaabbbccc"]),
|
||||
);
|
||||
|
||||
|
@ -99,12 +78,7 @@ fn widgets_block_titles_overlap() {
|
|||
.title(Title::from("aaaaa").alignment(Alignment::Left))
|
||||
.title(Title::from("bbbbb").alignment(Alignment::Center))
|
||||
.title(Title::from("ccccc").alignment(Alignment::Right)),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 11,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 11, 1),
|
||||
Buffer::with_lines(vec!["aaaaabaaaaa"]),
|
||||
);
|
||||
|
||||
|
@ -113,28 +87,22 @@ fn widgets_block_titles_overlap() {
|
|||
Block::default()
|
||||
.title(Title::from("bbbbb").alignment(Alignment::Center))
|
||||
.title(Title::from("ccccccccccc").alignment(Alignment::Right)),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 11,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 11, 1),
|
||||
Buffer::with_lines(vec!["cccbbbbbccc"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn widgets_block_renders_on_small_areas() {
|
||||
let test_case = |block, area: Rect, expected| {
|
||||
#[track_caller]
|
||||
fn test_case(block: Block, area: Rect, expected: Buffer) {
|
||||
let backend = TestBackend::new(area.width, area.height);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
terminal
|
||||
.draw(|f| {
|
||||
f.render_widget(block, area);
|
||||
})
|
||||
.draw(|frame| frame.render_widget(block, area))
|
||||
.unwrap();
|
||||
terminal.backend().assert_buffer(&expected);
|
||||
};
|
||||
}
|
||||
|
||||
let one_cell_test_cases = [
|
||||
(Borders::NONE, "T"),
|
||||
|
@ -147,152 +115,78 @@ fn widgets_block_renders_on_small_areas() {
|
|||
for (borders, symbol) in one_cell_test_cases.iter().cloned() {
|
||||
test_case(
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
},
|
||||
Buffer::empty(Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}),
|
||||
Rect::new(0, 0, 0, 0),
|
||||
Buffer::empty(Rect::new(0, 0, 0, 0)),
|
||||
);
|
||||
test_case(
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1,
|
||||
height: 0,
|
||||
},
|
||||
Buffer::empty(Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1,
|
||||
height: 0,
|
||||
}),
|
||||
Rect::new(0, 0, 1, 0),
|
||||
Buffer::empty(Rect::new(0, 0, 1, 0)),
|
||||
);
|
||||
test_case(
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 1,
|
||||
},
|
||||
Buffer::empty(Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 1,
|
||||
}),
|
||||
Rect::new(0, 0, 0, 1),
|
||||
Buffer::empty(Rect::new(0, 0, 0, 1)),
|
||||
);
|
||||
test_case(
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 1, 1),
|
||||
Buffer::with_lines(vec![symbol]),
|
||||
);
|
||||
}
|
||||
test_case(
|
||||
Block::default().title("Test").borders(Borders::LEFT),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 4,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["│Tes"]),
|
||||
);
|
||||
test_case(
|
||||
Block::default().title("Test").borders(Borders::RIGHT),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 4,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["Tes│"]),
|
||||
);
|
||||
test_case(
|
||||
Block::default().title("Test").borders(Borders::RIGHT),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 4,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["Tes│"]),
|
||||
);
|
||||
test_case(
|
||||
Block::default()
|
||||
.title("Test")
|
||||
.borders(Borders::LEFT | Borders::RIGHT),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 4,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["│Te│"]),
|
||||
);
|
||||
test_case(
|
||||
Block::default().title("Test").borders(Borders::TOP),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 4,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["Test"]),
|
||||
);
|
||||
test_case(
|
||||
Block::default().title("Test").borders(Borders::TOP),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 5,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 5, 1),
|
||||
Buffer::with_lines(vec!["Test─"]),
|
||||
);
|
||||
test_case(
|
||||
Block::default()
|
||||
.title("Test")
|
||||
.borders(Borders::LEFT | Borders::TOP),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 5,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 5, 1),
|
||||
Buffer::with_lines(vec!["┌Test"]),
|
||||
);
|
||||
test_case(
|
||||
Block::default()
|
||||
.title("Test")
|
||||
.borders(Borders::LEFT | Borders::TOP),
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 6,
|
||||
height: 1,
|
||||
},
|
||||
Rect::new(0, 0, 6, 1),
|
||||
Buffer::with_lines(vec!["┌Test─"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn widgets_block_title_alignment() {
|
||||
let test_case = |alignment, borders, expected| {
|
||||
let backend = TestBackend::new(15, 2);
|
||||
#[track_caller]
|
||||
fn test_case(alignment: Alignment, borders: Borders, expected: Buffer) {
|
||||
let backend = TestBackend::new(15, 3);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
|
||||
let block1 = Block::default()
|
||||
|
@ -304,270 +198,371 @@ fn widgets_block_title_alignment() {
|
|||
.title_alignment(alignment)
|
||||
.borders(borders);
|
||||
|
||||
let area = Rect {
|
||||
x: 1,
|
||||
y: 0,
|
||||
width: 13,
|
||||
height: 2,
|
||||
};
|
||||
let area = Rect::new(1, 0, 13, 3);
|
||||
|
||||
for block in [block1, block2] {
|
||||
terminal
|
||||
.draw(|f| {
|
||||
f.render_widget(block, area);
|
||||
})
|
||||
.draw(|frame| frame.render_widget(block, area))
|
||||
.unwrap();
|
||||
|
||||
terminal.backend().assert_buffer(&expected);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// title top-left with all borders
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌Title──────┐ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌Title──────┐ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left without top border
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::LEFT | Borders::BOTTOM | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" │Title │ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" │Title │ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left with no left border
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" Title───────┐ ", " ────────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" Title───────┐ ",
|
||||
" │ ",
|
||||
" ────────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left without right border
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌Title─────── ", " └──────────── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌Title─────── ",
|
||||
" │ ",
|
||||
" └──────────── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left without borders
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" Title ", " "]),
|
||||
Buffer::with_lines(vec![
|
||||
" Title ",
|
||||
" ",
|
||||
" ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center with all borders
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌───Title───┐ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───Title───┐ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without top border
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::LEFT | Borders::BOTTOM | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" │ Title │ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" │ Title │ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center with no left border
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ────Title───┐ ", " ────────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ───Title────┐ ",
|
||||
" │ ",
|
||||
" ────────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without right border
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌───Title──── ", " └──────────── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───Title──── ",
|
||||
" │ ",
|
||||
" └──────────── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without borders
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" Title ", " "]),
|
||||
Buffer::with_lines(vec![
|
||||
" Title ",
|
||||
" ",
|
||||
" ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right with all borders
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌──────Title┐ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌──────Title┐ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right without top border
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::LEFT | Borders::BOTTOM | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" │ Title│ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" │ Title│ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right with no left border
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ───────Title┐ ", " ────────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ───────Title┐ ",
|
||||
" │ ",
|
||||
" ────────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right without right border
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌───────Title ", " └──────────── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───────Title ",
|
||||
" │ ",
|
||||
" └──────────── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right without borders
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" Title ", " "]),
|
||||
Buffer::with_lines(vec![
|
||||
" Title ",
|
||||
" ",
|
||||
" ",
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn widgets_block_title_alignment_bottom() {
|
||||
let test_case = |alignment, borders, expected| {
|
||||
let backend = TestBackend::new(15, 2);
|
||||
#[track_caller]
|
||||
fn test_case(alignment: Alignment, borders: Borders, expected: Buffer) {
|
||||
let backend = TestBackend::new(15, 3);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
|
||||
let block = Block::default()
|
||||
.title(
|
||||
Title::from(Span::styled("Title", Style::default()))
|
||||
.alignment(alignment)
|
||||
.position(Position::Bottom),
|
||||
)
|
||||
.borders(borders);
|
||||
|
||||
let area = Rect {
|
||||
x: 1,
|
||||
y: 0,
|
||||
width: 13,
|
||||
height: 2,
|
||||
};
|
||||
|
||||
let title = Title::from(Span::styled("Title", Style::default()))
|
||||
.alignment(alignment)
|
||||
.position(Position::Bottom);
|
||||
let block = Block::default().title(title).borders(borders);
|
||||
let area = Rect::new(1, 0, 13, 3);
|
||||
terminal
|
||||
.draw(|f| {
|
||||
f.render_widget(block, area);
|
||||
})
|
||||
.draw(|frame| frame.render_widget(block, area))
|
||||
.unwrap();
|
||||
|
||||
terminal.backend().assert_buffer(&expected);
|
||||
};
|
||||
}
|
||||
|
||||
// title bottom-left with all borders
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌───────────┐ ", " └Title──────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───────────┐ ",
|
||||
" │ │ ",
|
||||
" └Title──────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-left without bottom border
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::LEFT | Borders::TOP | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" ┌───────────┐ ", " │Title │ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───────────┐ ",
|
||||
" │ │ ",
|
||||
" │Title │ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-left with no left border
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ────────────┐ ", " Title───────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ────────────┐ ",
|
||||
" │ ",
|
||||
" Title───────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-left without right border
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌──────────── ", " └Title─────── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌──────────── ",
|
||||
" │ ",
|
||||
" └Title─────── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-left without borders
|
||||
test_case(
|
||||
Alignment::Left,
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" ", " Title "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ",
|
||||
" ",
|
||||
" Title ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center with all borders
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌───────────┐ ", " └───Title───┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───────────┐ ",
|
||||
" │ │ ",
|
||||
" └───Title───┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without bottom border
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::LEFT | Borders::TOP | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" ┌───────────┐ ", " │ Title │ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───────────┐ ",
|
||||
" │ │ ",
|
||||
" │ Title │ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center with no left border
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ────────────┐ ", " ────Title───┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ────────────┐ ",
|
||||
" │ ",
|
||||
" ───Title────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without right border
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌──────────── ", " └───Title──── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌──────────── ",
|
||||
" │ ",
|
||||
" └───Title──── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without borders
|
||||
test_case(
|
||||
Alignment::Center,
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" ", " Title "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ",
|
||||
" ",
|
||||
" Title ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-right with all borders
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌───────────┐ ", " └──────Title┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───────────┐ ",
|
||||
" │ │ ",
|
||||
" └──────Title┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-right without bottom border
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::LEFT | Borders::TOP | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" ┌───────────┐ ", " │ Title│ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌───────────┐ ",
|
||||
" │ │ ",
|
||||
" │ Title│ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-right with no left border
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ────────────┐ ", " ───────Title┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ────────────┐ ",
|
||||
" │ ",
|
||||
" ───────Title┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-right without right border
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌──────────── ", " └───────Title "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌──────────── ",
|
||||
" │ ",
|
||||
" └───────Title ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title bottom-right without borders
|
||||
test_case(
|
||||
Alignment::Right,
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" ", " Title "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ",
|
||||
" ",
|
||||
" Title ",
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn widgets_block_multiple_titles() {
|
||||
let test_case = |title_a, title_b, borders, expected| {
|
||||
let backend = TestBackend::new(15, 2);
|
||||
#[track_caller]
|
||||
fn test_case(title_a: Title, title_b: Title, borders: Borders, expected: Buffer) {
|
||||
let backend = TestBackend::new(15, 3);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
|
||||
let block = Block::default()
|
||||
|
@ -575,12 +570,7 @@ fn widgets_block_multiple_titles() {
|
|||
.title(title_b)
|
||||
.borders(borders);
|
||||
|
||||
let area = Rect {
|
||||
x: 1,
|
||||
y: 0,
|
||||
width: 13,
|
||||
height: 2,
|
||||
};
|
||||
let area = Rect::new(1, 0, 13, 3);
|
||||
|
||||
terminal
|
||||
.draw(|f| {
|
||||
|
@ -589,14 +579,18 @@ fn widgets_block_multiple_titles() {
|
|||
.unwrap();
|
||||
|
||||
terminal.backend().assert_buffer(&expected);
|
||||
};
|
||||
}
|
||||
|
||||
// title bottom-left with all borders
|
||||
test_case(
|
||||
Title::from("foo"),
|
||||
Title::from("bar"),
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌foo─bar────┐ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌foo─bar────┐ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left without top border
|
||||
|
@ -604,7 +598,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo"),
|
||||
Title::from("bar"),
|
||||
Borders::LEFT | Borders::BOTTOM | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" │foo bar │ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" │foo bar │ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left with no left border
|
||||
|
@ -612,7 +610,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo"),
|
||||
Title::from("bar"),
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" foo─bar─────┐ ", " ────────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" foo─bar─────┐ ",
|
||||
" │ ",
|
||||
" ────────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left without right border
|
||||
|
@ -620,7 +622,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo"),
|
||||
Title::from("bar"),
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌foo─bar───── ", " └──────────── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌foo─bar───── ",
|
||||
" │ ",
|
||||
" └──────────── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-left without borders
|
||||
|
@ -628,7 +634,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo"),
|
||||
Title::from("bar"),
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" foo bar ", " "]),
|
||||
Buffer::with_lines(vec![
|
||||
" foo bar ",
|
||||
" ",
|
||||
" ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center with all borders
|
||||
|
@ -636,7 +646,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Center),
|
||||
Title::from("bar").alignment(Alignment::Center),
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌──foo─bar──┐ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌──foo─bar──┐ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without top border
|
||||
|
@ -644,7 +658,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Center),
|
||||
Title::from("bar").alignment(Alignment::Center),
|
||||
Borders::LEFT | Borders::BOTTOM | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" │ foo bar │ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" │ foo bar │ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center with no left border
|
||||
|
@ -652,7 +670,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Center),
|
||||
Title::from("bar").alignment(Alignment::Center),
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ───foo─bar──┐ ", " ────────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ──foo─bar───┐ ",
|
||||
" │ ",
|
||||
" ────────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without right border
|
||||
|
@ -660,7 +682,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Center),
|
||||
Title::from("bar").alignment(Alignment::Center),
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌──foo─bar─── ", " └──────────── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌──foo─bar─── ",
|
||||
" │ ",
|
||||
" └──────────── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title center without borders
|
||||
|
@ -668,7 +694,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Center),
|
||||
Title::from("bar").alignment(Alignment::Center),
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" foo bar ", " "]),
|
||||
Buffer::with_lines(vec![
|
||||
" foo bar ",
|
||||
" ",
|
||||
" ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right with all borders
|
||||
|
@ -676,7 +706,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Right),
|
||||
Title::from("bar").alignment(Alignment::Right),
|
||||
Borders::ALL,
|
||||
Buffer::with_lines(vec![" ┌────foo─bar┐ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌────foo─bar┐ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right without top border
|
||||
|
@ -684,7 +718,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Right),
|
||||
Title::from("bar").alignment(Alignment::Right),
|
||||
Borders::LEFT | Borders::BOTTOM | Borders::RIGHT,
|
||||
Buffer::with_lines(vec![" │ foo bar│ ", " └───────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" │ foo bar│ ",
|
||||
" │ │ ",
|
||||
" └───────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right with no left border
|
||||
|
@ -692,7 +730,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Right),
|
||||
Title::from("bar").alignment(Alignment::Right),
|
||||
Borders::TOP | Borders::RIGHT | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ─────foo─bar┐ ", " ────────────┘ "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ─────foo─bar┐ ",
|
||||
" │ ",
|
||||
" ────────────┘ ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right without right border
|
||||
|
@ -700,7 +742,11 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Right),
|
||||
Title::from("bar").alignment(Alignment::Right),
|
||||
Borders::LEFT | Borders::TOP | Borders::BOTTOM,
|
||||
Buffer::with_lines(vec![" ┌─────foo─bar ", " └──────────── "]),
|
||||
Buffer::with_lines(vec![
|
||||
" ┌─────foo─bar ",
|
||||
" │ ",
|
||||
" └──────────── ",
|
||||
]),
|
||||
);
|
||||
|
||||
// title top-right without borders
|
||||
|
@ -708,6 +754,10 @@ fn widgets_block_multiple_titles() {
|
|||
Title::from("foo").alignment(Alignment::Right),
|
||||
Title::from("bar").alignment(Alignment::Right),
|
||||
Borders::NONE,
|
||||
Buffer::with_lines(vec![" foo bar ", " "]),
|
||||
Buffer::with_lines(vec![
|
||||
" foo bar ",
|
||||
" ",
|
||||
" ",
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue