use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::{Color, Style};
use ratatui::text::Line;
use ratatui::widgets::{Block, Borders};
use crate::ui::{gradient, theme};
pub fn block_with_bg<'a>(title: Line<'a>, focused: bool, bg: Color) -> Block<'a> {
let border_style = if focused {
theme::border_focused_style()
} else {
theme::border_style()
};
Block::default()
.title(title)
.borders(Borders::ALL)
.border_style(border_style)
.style(Style::default().bg(bg))
}
const BOX_CHARS: &[char] = &['┌', '┐', '└', '┘', '─', '│'];
fn is_box_char(ch: char) -> bool {
BOX_CHARS.contains(&ch)
}
pub fn apply_gradient_border_with_bg(
buf: &mut Buffer,
area: Rect,
start: Color,
end: Color,
phase: f32,
bg: Color,
) {
let bounds = *buf.area();
gradient::walk_perimeter(area, |x, y, i, total| {
if x < bounds.x
|| x >= bounds.x + bounds.width
|| y < bounds.y
|| y >= bounds.y + bounds.height
{
return;
}
let cell = &mut buf[(x, y)];
let ch = cell.symbol().chars().next().unwrap_or(' ');
if !is_box_char(ch) {
return;
}
let color = gradient::perimeter_color(i, total, start, end, phase);
cell.set_style(Style::default().fg(color).bg(bg));
});
}
pub fn scroll_offset(total: usize, selected: usize, visible_height: usize) -> usize {
if total <= visible_height || selected < visible_height / 2 {
0
} else if selected > total - visible_height / 2 {
total - visible_height
} else {
selected - visible_height / 2
}
}