use ratatui::{buffer::Buffer, layout::Rect, style::Color};
use super::InteractiveState;
const SCROLLBAR_TRACK: char = ' ';
const SCROLLBAR_THUMB_TOP: char = '╻';
const SCROLLBAR_THUMB_MIDDLE: char = '┃';
const SCROLLBAR_THUMB_BOTTOM: char = '╹';
fn brighten_color(color: Color, factor: f32) -> Color {
match color {
Color::Rgb(r, g, b) => {
let r = (r as f32 + (255.0 - r as f32) * factor).min(255.0) as u8;
let g = (g as f32 + (255.0 - g as f32) * factor).min(255.0) as u8;
let b = (b as f32 + (255.0 - b as f32) * factor).min(255.0) as u8;
Color::Rgb(r, g, b)
}
_ => color, }
}
impl<'a> InteractiveState<'a> {
pub(super) fn render_scrollbar(&self, buf: &mut Buffer, area: Rect, document_height: u16) {
let viewport_height = area.height;
let scrollbar_x = area.x + area.width;
for y in 0..viewport_height {
if let Some(cell) = buf.cell_mut((scrollbar_x, area.y + y)) {
cell.set_style(self.theme.document_bg_style);
cell.set_char(' ');
}
}
if document_height <= viewport_height {
return;
}
let hovered = self.viewport.scrollbar_hovered;
let dragging = self.viewport.scrollbar_dragging;
let brightness_factor = if dragging {
0.4 } else if hovered {
0.25 } else {
0.0 };
let mut scrollbar_style = self.theme.muted_style;
if brightness_factor > 0.0 {
if let Some(fg) = scrollbar_style.fg {
scrollbar_style = scrollbar_style.fg(brighten_color(fg, brightness_factor));
}
}
let thumb_size = ((viewport_height as f32 / document_height as f32)
* viewport_height as f32)
.ceil()
.max(1.0) as u16;
let scrollable_range = document_height.saturating_sub(viewport_height);
let thumb_travel = viewport_height.saturating_sub(thumb_size);
let thumb_start = if scrollable_range > 0 {
((self.viewport.scroll_offset as f32 / scrollable_range as f32) * thumb_travel as f32)
.round() as u16
} else {
0
};
let thumb_end = thumb_start + thumb_size;
for y in 0..viewport_height {
let cell = buf.cell_mut((scrollbar_x, area.y + y));
if let Some(cell) = cell {
cell.set_style(scrollbar_style);
if y < thumb_start || y >= thumb_end {
cell.set_char(SCROLLBAR_TRACK);
} else if y == thumb_start && thumb_size > 1 {
cell.set_char(SCROLLBAR_THUMB_TOP);
} else if y == thumb_end - 1 && thumb_size > 1 {
cell.set_char(SCROLLBAR_THUMB_BOTTOM);
} else {
cell.set_char(SCROLLBAR_THUMB_MIDDLE);
}
}
}
}
}