fix(widgets/block): allow Block to render on small areas

This commit is contained in:
Florian Dehau 2020-11-14 20:26:16 +01:00
parent 8543523f18
commit 8a27036a54
2 changed files with 176 additions and 11 deletions

View file

@ -135,13 +135,12 @@ impl<'a> Block<'a> {
impl<'a> Widget for Block<'a> { impl<'a> Widget for Block<'a> {
fn render(self, area: Rect, buf: &mut Buffer) { fn render(self, area: Rect, buf: &mut Buffer) {
buf.set_style(area, self.style); if area.area() == 0 {
if area.width < 2 || area.height < 2 {
return; return;
} }
buf.set_style(area, self.style);
let symbols = BorderType::line_symbols(self.border_type); let symbols = BorderType::line_symbols(self.border_type);
// Sides // Sides
if self.borders.intersects(Borders::LEFT) { if self.borders.intersects(Borders::LEFT) {
for y in area.top()..area.bottom() { for y in area.top()..area.bottom() {
@ -175,9 +174,9 @@ impl<'a> Widget for Block<'a> {
} }
// Corners // Corners
if self.borders.contains(Borders::LEFT | Borders::TOP) { if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) {
buf.get_mut(area.left(), area.top()) buf.get_mut(area.right() - 1, area.bottom() - 1)
.set_symbol(symbols.top_left) .set_symbol(symbols.bottom_right)
.set_style(self.border_style); .set_style(self.border_style);
} }
if self.borders.contains(Borders::RIGHT | Borders::TOP) { if self.borders.contains(Borders::RIGHT | Borders::TOP) {
@ -190,9 +189,9 @@ impl<'a> Widget for Block<'a> {
.set_symbol(symbols.bottom_left) .set_symbol(symbols.bottom_left)
.set_style(self.border_style); .set_style(self.border_style);
} }
if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) { if self.borders.contains(Borders::LEFT | Borders::TOP) {
buf.get_mut(area.right() - 1, area.bottom() - 1) buf.get_mut(area.left(), area.top())
.set_symbol(symbols.bottom_right) .set_symbol(symbols.top_left)
.set_style(self.border_style); .set_style(self.border_style);
} }
@ -207,7 +206,7 @@ impl<'a> Widget for Block<'a> {
} else { } else {
0 0
}; };
let width = area.width - lx - rx; let width = area.width.saturating_sub(lx).saturating_sub(rx);
buf.set_spans(area.left() + lx, area.top(), &title, width); buf.set_spans(area.left() + lx, area.top(), &title, width);
} }
} }

View file

@ -45,3 +45,169 @@ fn widgets_block_renders() {
} }
terminal.backend().assert_buffer(&expected); terminal.backend().assert_buffer(&expected);
} }
#[test]
fn widgets_block_renders_on_small_areas() {
let test_case = |block, area: Rect, expected| {
let backend = TestBackend::new(area.width, area.height);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| {
f.render_widget(block, area);
})
.unwrap();
terminal.backend().assert_buffer(&expected);
};
let one_cell_test_cases = [
(Borders::NONE, "T"),
(Borders::LEFT, ""),
(Borders::TOP, "T"),
(Borders::RIGHT, ""),
(Borders::BOTTOM, "T"),
(Borders::ALL, ""),
];
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,
}),
);
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,
}),
);
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,
}),
);
test_case(
Block::default().title("Test").borders(borders),
Rect {
x: 0,
y: 0,
width: 1,
height: 1,
},
Buffer::with_lines(vec![symbol]),
);
}
test_case(
Block::default().title("Test").borders(Borders::LEFT),
Rect {
x: 0,
y: 0,
width: 4,
height: 1,
},
Buffer::with_lines(vec!["│Tes"]),
);
test_case(
Block::default().title("Test").borders(Borders::RIGHT),
Rect {
x: 0,
y: 0,
width: 4,
height: 1,
},
Buffer::with_lines(vec!["Tes│"]),
);
test_case(
Block::default().title("Test").borders(Borders::RIGHT),
Rect {
x: 0,
y: 0,
width: 4,
height: 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,
},
Buffer::with_lines(vec!["│Te│"]),
);
test_case(
Block::default().title("Test").borders(Borders::TOP),
Rect {
x: 0,
y: 0,
width: 4,
height: 1,
},
Buffer::with_lines(vec!["Test"]),
);
test_case(
Block::default().title("Test").borders(Borders::TOP),
Rect {
x: 0,
y: 0,
width: 5,
height: 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,
},
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,
},
Buffer::with_lines(vec!["┌Test─"]),
);
}