use crate::tui::helpers::render_styled_paragraph_with_scrollbar;
use ratatui::text::Text;
#[derive(Debug, Clone)]
pub struct ScrollableTextWidget {
text_cache: Option<Text<'static>>,
scroll_position: usize,
max_scroll: usize,
}
impl ScrollableTextWidget {
pub fn new() -> Self {
Self {
text_cache: None,
scroll_position: 0,
max_scroll: 0,
}
}
pub fn set_text(&mut self, text: Text<'static>) {
self.text_cache = Some(text);
self.scroll_position = 0;
self.max_scroll = 0;
}
pub fn text(&self) -> Text<'static> {
self.text_cache
.as_ref()
.cloned()
.unwrap_or_else(|| Text::from("Loading..."))
}
pub fn scroll_up(&mut self) {
self.scroll_position = self.scroll_position.saturating_sub(1);
}
pub fn scroll_down(&mut self) {
self.scroll_position = (self.scroll_position + 1).min(self.max_scroll);
}
pub fn scroll_to_top(&mut self) {
self.scroll_position = 0;
}
pub fn scroll_to_bottom(&mut self) {
self.scroll_position = self.max_scroll;
}
pub fn scroll_position(&self) -> usize {
self.scroll_position
}
pub fn render(
&mut self,
f: &mut ratatui::Frame,
area: ratatui::layout::Rect,
title: &str,
is_focused: bool,
) {
let content = self.text();
let total_lines = content.lines.len();
let visible_height = area.height.saturating_sub(2) as usize; self.max_scroll = total_lines.saturating_sub(visible_height);
render_styled_paragraph_with_scrollbar(
f,
area,
content,
self.scroll_position,
title,
is_focused,
);
}
pub fn has_content(&self) -> bool {
self.text_cache.is_some()
}
pub fn clear(&mut self) {
self.text_cache = None;
self.scroll_position = 0;
self.max_scroll = 0;
}
}
impl Default for ScrollableTextWidget {
fn default() -> Self {
Self::new()
}
}