Implement proper title wrapping

This commit is contained in:
Andreas Tsouchlos 2025-12-29 23:03:37 +02:00
parent 912eae8daf
commit db570abd96

130
src/ui.rs
View File

@ -1,5 +1,3 @@
use std::fmt::format;
use crate::{ use crate::{
app::{ActivePane, App}, app::{ActivePane, App},
snowballing::Publication, snowballing::Publication,
@ -7,14 +5,9 @@ use crate::{
use ratatui::{ use ratatui::{
Frame, Frame,
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
style::{ style::{Color, Modifier, Style, Stylize},
Color, Modifier, Style, Stylize, palette::material::AccentedPalette,
},
text::{Line, Span}, text::{Line, Span},
widgets::{ widgets::{Block, Borders, List, ListItem},
Block, Borders, List, ListItem, Scrollbar, ScrollbarOrientation,
ScrollbarState,
},
}; };
pub fn draw(f: &mut Frame, app: &mut App) { pub fn draw(f: &mut Frame, app: &mut App) {
@ -27,6 +20,91 @@ pub fn draw(f: &mut Frame, app: &mut App) {
draw_right_pane(f, app, chunks[1]); draw_right_pane(f, app, chunks[1]);
} }
fn format_title<'a>(
idx: usize,
title: &Option<String>,
year: &Option<u32>,
available_width: usize,
is_selected: bool,
) -> Vec<Line<'a>> {
let idx_text = format!("[{}]", idx + 1);
let title_text =
title.clone().unwrap_or("[No title available]".to_string());
let year_text = year
.map(|val| format!("({})", val))
.unwrap_or("[unknown]".to_string());
let wrapped = textwrap::fill(
&format!("{} {} {}", idx_text, title_text, year_text),
available_width,
);
let lines: Vec<&str> = wrapped.lines().collect();
let mut result = Vec::<Line>::new();
let (border_char, border_style) = if is_selected {
(
"",
Style::default()
.fg(Color::Gray)
.add_modifier(Modifier::BOLD),
)
} else {
(" ", Style::default())
};
if lines.len() == 1 {
let line = lines[0];
result.push(Line::from(vec![
Span::styled(border_char, border_style),
Span::styled(
line[0..idx_text.len()].to_string(),
Style::default().fg(Color::DarkGray),
),
Span::raw(
line[idx_text.len()..line.len() - year_text.len()].to_string(),
),
Span::styled(
line[line.len() - year_text.len()..].to_string(),
Style::default().fg(Color::Yellow),
),
]));
} else {
let first_line = lines[0];
let middle_lines = &lines[1..lines.len() - 1];
let last_line = lines[lines.len() - 1];
result.push(Line::from(vec![
Span::styled(border_char, border_style),
Span::styled(
first_line[0..idx_text.len()].to_string(),
Style::default().fg(Color::DarkGray),
),
Span::raw(first_line[idx_text.len()..].to_string()),
]));
for line in middle_lines {
result.push(Line::from(vec![
Span::styled(border_char, border_style),
Span::raw(line.to_string()),
]));
}
result.push(Line::from(vec![
Span::styled(border_char, border_style),
Span::raw(
last_line[..last_line.len() - year_text.len()].to_string(),
),
Span::styled(
last_line[last_line.len() - year_text.len()..].to_string(),
Style::default().fg(Color::Yellow),
),
]));
}
result
}
fn create_publication_item_list( fn create_publication_item_list(
publications: &Vec<Publication>, publications: &Vec<Publication>,
selected_idx: Option<usize>, selected_idx: Option<usize>,
@ -50,31 +128,23 @@ fn create_publication_item_list(
(" ", Style::default()) (" ", Style::default())
}; };
let mut lines = vec![ let mut lines = Vec::<Line>::new();
Line::from(vec![
Span::styled(border_char, border_style), lines.append(&mut format_title(
Span::raw(format!("[{}] ", idx + 1)), idx,
Span::raw( &publ.get_title(),
publ.get_title() &publ.get_year(),
.unwrap_or("[No title available]".to_string()), available_width,
), is_selected,
Span::styled( ));
format!(
" ({})", lines.push(Line::from(vec![
publ.publication_year
.map_or("".to_string(), |val| val.to_string())
),
Style::default().fg(Color::Yellow),
),
]),
Line::from(vec![
Span::styled(border_char, border_style), Span::styled(border_char, border_style),
Span::styled( Span::styled(
publ.get_author_text(), publ.get_author_text(),
Style::default().fg(Color::Blue), Style::default().fg(Color::Blue),
), ),
]), ]));
];
if show_abstract { if show_abstract {
let wrapped = textwrap::fill( let wrapped = textwrap::fill(
@ -151,7 +221,7 @@ fn draw_left_pane(frame: &mut Frame, app: &mut App, area: Rect) {
Span::raw("Step: "), Span::raw("Step: "),
Span::styled( Span::styled(
app.snowballing_step.to_string(), app.snowballing_step.to_string(),
Style::default().fg(Color::Yellow), Style::default().fg(Color::Cyan),
), ),
]), ]),
]; ];