trnovel 0.10.0

Terminal reader for novel
Documentation
use ratatui::{
    layout::{Margin, Rect},
    widgets::{Scrollbar, ScrollbarState},
};
use ratatui_kit::{Hook, Hooks};

pub trait UseScrollbar {
    fn use_scrollbar(&mut self, content_length: usize, position: Option<usize>);
}

#[derive(Debug, Default)]
pub struct UseScrollbarImpl {
    area: Rect,
    content_length: usize,
    position: Option<usize>,
}

impl Hook for UseScrollbarImpl {
    fn pre_component_draw(&mut self, drawer: &mut ratatui_kit::ComponentDrawer) {
        self.area = drawer.area;
    }

    fn post_component_draw(&mut self, drawer: &mut ratatui_kit::ComponentDrawer) {
        let height = drawer.area.height;

        if self.content_length as u16 > height && self.content_length > 0 {
            let content_len = (self.content_length as f32 / (height as f32)) as usize;
            let position =
                (self.position.unwrap_or_default() as f32 / (height as f32)).floor() as usize;
            let mut scrollbar_state = ScrollbarState::default()
                .content_length(content_len)
                .position(position);

            drawer.render_stateful_widget(
                Scrollbar::default(),
                self.area.inner(Margin::new(0, 1)),
                &mut scrollbar_state,
            );
        }
    }
}

impl UseScrollbar for Hooks<'_, '_> {
    fn use_scrollbar(&mut self, content_length: usize, position: Option<usize>) {
        let scrollbar = self.use_hook(UseScrollbarImpl::default);
        scrollbar.content_length = content_length;
        scrollbar.position = position;
    }
}