termrs_core 0.3.0

The core library of termrs
Documentation
use std::{borrow::Cow, marker::PhantomData};

use crate::{
    render::{Position, RenderContext, Size},
    widget::{LayoutInfo, SimpleRenderInfo, Widget},
};

#[derive(Default, Debug, Clone, PartialEq)]
pub struct TextBlock<'a, Message> {
    text: Cow<'a, str>,
    phantom_message: PhantomData<Message>,
}

impl<'a, Message> TextBlock<'a, Message> {
    pub fn new(text: Cow<'a, str>) -> Self {
        Self {
            text,
            phantom_message: PhantomData,
        }
    }

    pub fn with_text(mut self, text: Cow<'a, str>) -> Self {
        self.text = text;
        self
    }
}

impl<'a, Message> Widget<Message> for TextBlock<'a, Message> {
    type LayoutInfo = Size;
    type RenderInfo = SimpleRenderInfo;

    fn render(
        &self,
        position: Position,
        layout: &Self::LayoutInfo,
        context: &mut dyn RenderContext,
    ) -> std::io::Result<Self::RenderInfo> {
        let bounds = layout.bounds();

        if bounds.height() > 0 {
            context.set_position(position)?;

            let symbols = &self.text;

            let width = (bounds.width() as usize).min(symbols.len());

            // Get the symbols, which fit the width
            let symbols = &symbols[0..width];

            context.render_symbols(symbols.as_bytes())?;
        }

        Ok(SimpleRenderInfo::new(bounds, position))
    }

    fn layout(&self, available_size: Size) -> Size {
        if available_size.is_empty() {
            return Size::EMPTY;
        }

        let len = self.text.len();
        let width = if len > u16::MAX as usize {
            u16::MAX
        } else {
            len as u16
        };

        Size::new(width, 1)
    }
}