scrin 0.1.1

A terminal UI toolkit with panes, widgets, overlays, animations, and Aisling-powered effects/loaders.
Documentation
use crate::core::buffer::Buffer;
use crate::core::rect::Rect;
use crate::style::Style;
use crate::widgets::Widget;

#[derive(Debug, Clone)]
pub struct Paragraph<'a> {
    pub text: &'a str,
    pub style: Style,
    pub word_wrap: bool,
    pub scroll: (u16, u16),
}

impl<'a> Paragraph<'a> {
    pub fn new(text: &'a str) -> Self {
        Self {
            text,
            style: Style::new(),
            word_wrap: false,
            scroll: (0, 0),
        }
    }

    pub fn with_style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }

    pub fn with_word_wrap(mut self, wrap: bool) -> Self {
        self.word_wrap = wrap;
        self
    }

    pub fn with_scroll(mut self, x: u16, y: u16) -> Self {
        self.scroll = (x, y);
        self
    }
}

impl<'a> Widget for Paragraph<'a> {
    fn render(&self, buffer: &mut Buffer, area: Rect) {
        let fg = self.style.fg_or_default();
        let bg = self.style.bg;
        let lines: Vec<&str> = self.text.lines().collect();
        let start_y = self.scroll.1 as usize;
        for (line_idx, line) in lines.iter().enumerate() {
            let y = area.y as usize + line_idx;
            if y >= area.bottom() as usize {
                break;
            }
            if line_idx < start_y {
                continue;
            }
            let display_y = y;
            let chars: Vec<char> = line.chars().collect();
            let start_x = self.scroll.0 as usize;
            for (i, &ch) in chars.iter().enumerate() {
                let x = area.x as usize + i;
                if x >= area.right() as usize {
                    break;
                }
                if i < start_x {
                    continue;
                }
                buffer.set(
                    x,
                    display_y,
                    crate::core::buffer::Cell {
                        ch,
                        fg,
                        bg,
                        bold: self.style.bold,
                        italic: self.style.italic,
                        underlined: self.style.underlined,
                    },
                );
            }
        }
    }
}