mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-22 20:53:19 +00:00
fix(block): make inner
aware of title positions (#657)
Previously, when computing the inner rendering area of a block, all titles were assumed to be positioned at the top, which caused the height of the inner area to be miscalculated.
This commit is contained in:
parent
753e246531
commit
56fc410105
2 changed files with 96 additions and 3 deletions
|
@ -508,14 +508,15 @@ impl<'a> Block<'a> {
|
|||
inner.x = inner.x.saturating_add(1).min(inner.right());
|
||||
inner.width = inner.width.saturating_sub(1);
|
||||
}
|
||||
if self.borders.intersects(Borders::TOP) || !self.titles.is_empty() {
|
||||
if self.borders.intersects(Borders::TOP) || self.have_title_at_position(Position::Top) {
|
||||
inner.y = inner.y.saturating_add(1).min(inner.bottom());
|
||||
inner.height = inner.height.saturating_sub(1);
|
||||
}
|
||||
if self.borders.intersects(Borders::RIGHT) {
|
||||
inner.width = inner.width.saturating_sub(1);
|
||||
}
|
||||
if self.borders.intersects(Borders::BOTTOM) {
|
||||
if self.borders.intersects(Borders::BOTTOM) || self.have_title_at_position(Position::Bottom)
|
||||
{
|
||||
inner.height = inner.height.saturating_sub(1);
|
||||
}
|
||||
|
||||
|
@ -532,6 +533,12 @@ impl<'a> Block<'a> {
|
|||
inner
|
||||
}
|
||||
|
||||
fn have_title_at_position(&self, position: Position) -> bool {
|
||||
self.titles
|
||||
.iter()
|
||||
.any(|title| title.position.unwrap_or(self.titles_position) == position)
|
||||
}
|
||||
|
||||
/// Defines the padding inside a `Block`.
|
||||
///
|
||||
/// See [`Padding`] for more information.
|
||||
|
@ -939,6 +946,78 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inner_takes_into_account_border_and_title() {
|
||||
let test_rect = Rect::new(0, 0, 0, 2);
|
||||
|
||||
let top_top = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.borders(Borders::TOP);
|
||||
assert_eq!(top_top.inner(test_rect), Rect::new(0, 1, 0, 1));
|
||||
|
||||
let top_bot = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.borders(Borders::BOTTOM);
|
||||
assert_eq!(top_bot.inner(test_rect), Rect::new(0, 1, 0, 0));
|
||||
|
||||
let bot_top = Block::default()
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.borders(Borders::TOP);
|
||||
assert_eq!(bot_top.inner(test_rect), Rect::new(0, 1, 0, 0));
|
||||
|
||||
let bot_bot = Block::default()
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.borders(Borders::BOTTOM);
|
||||
assert_eq!(bot_bot.inner(test_rect), Rect::new(0, 0, 0, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn have_title_at_position_takes_into_account_all_positioning_declarations() {
|
||||
let block = Block::default();
|
||||
assert!(!block.have_title_at_position(Position::Top));
|
||||
assert!(!block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::default().title(Title::from("Test").position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(!block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::default().title(Title::from("Test").position(Position::Bottom));
|
||||
assert!(!block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.title_position(Position::Bottom);
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(!block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.title_position(Position::Top);
|
||||
assert!(!block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.title(Title::from("Test").position(Position::Bottom));
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.title(Title::from("Test"))
|
||||
.title_position(Position::Bottom);
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test"))
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.title_position(Position::Top);
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn border_type_can_be_const() {
|
||||
const _PLAIN: border::Set = BorderType::border_symbols(BorderType::Plain);
|
||||
|
|
|
@ -295,7 +295,7 @@ mod test {
|
|||
backend::TestBackend,
|
||||
style::{Color, Modifier, Stylize},
|
||||
text::{Line, Span},
|
||||
widgets::Borders,
|
||||
widgets::{block::Position, Borders},
|
||||
Terminal,
|
||||
};
|
||||
|
||||
|
@ -478,6 +478,20 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_render_paragraph_with_block_with_bottom_title_and_border() {
|
||||
let block = Block::default()
|
||||
.title("Title")
|
||||
.title_position(Position::Bottom)
|
||||
.borders(Borders::BOTTOM);
|
||||
let paragraph = Paragraph::new("Hello, world!").block(block);
|
||||
|
||||
test_case(
|
||||
¶graph,
|
||||
Buffer::with_lines(vec!["Hello, world! ", "Title──────────"]),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_render_paragraph_with_word_wrap() {
|
||||
let text = "This is a long line of text that should wrap and contains a superultramegagigalong word.";
|
||||
|
|
Loading…
Reference in a new issue