fp_tui 0.2.2

A very basic tui library
Documentation
use std::rc::Rc;
use std::cell::RefCell;

use crate::Widget;
use crate::common::{BoundingBox, Dimensions, Position};

/// #### Description
/// A basic text widget. It can be single lined if your text fits within the
/// width of the widget or it canbe multilined if your text exceeds it and its
/// height is greater than 1
/// 
pub struct LabelWidget {
    /// #### Description
    /// The text to display
    /// 
    text: String,

    /// #### Description
    /// The bounds of the widget
    /// 
    bounding_box: BoundingBox
}

impl LabelWidget {
    /// #### Description
    /// Creates a new label
    /// 
    /// #### Arguments
    /// * `x`: [i32] - The x position of the label
    /// * `y`: [i32] - The y position of the label
    /// * `max_width`: [i32] - The maximum width of the label
    /// * `max_height`: [i32] - The maximum height of the label
    /// * `text`: &[str] - The text to be shown on the label  
    /// 
    /// #### Returns
    /// [Rc]<[RefCell]<[LabelWidget]>> - A newly created label widget
    /// 
    pub fn new(
        x: i32, y: i32, max_width: u32, max_height: u32, text: &str
    ) -> Rc<RefCell<Self>> {
        return Rc::new(RefCell::new(Self {
            text: text.to_string(),
            bounding_box: BoundingBox::new(
                Position::new(x, y), 
                Dimensions::new(max_width, max_height)
            )
        }));
    }

    /// #### Description
    /// Sets the text of the label
    /// 
    /// #### Arguments
    /// * `new_text`: &[str] - The text to set the label to
    /// 
    pub fn set_text(&mut self, new_text: &str) {
        self.text = new_text.to_string();
    }

    /// #### Description
    /// Gets the current text of the label
    /// 
    /// #### Returns
    /// [String] - The text of the label
    /// 
    pub fn get_text(&mut self) -> String {
        return self.text.clone();
    }
}

impl Widget for LabelWidget {
    fn draw(
            &mut self,
            positioning_algorithm: &Box<dyn crate::PositioningAlgorithm>,
            display_buffer: &mut crate::DisplayBuffer
        ) {

        if self.bounding_box.get_width() == 0 || 
           self.bounding_box.get_height() == 0 
        {
            // nothign can be displayed and we can return
            return;
        }

        let abs_pos = positioning_algorithm.calculate_position(
            self.bounding_box.get_position()
        );


        // create every line

        // Vector to store lines in
        let mut lines: Vec<String> = vec![];

        // Each entry into this vector represents a line as intended by the
        // programmer. It will be further split based upon the dimensions of the
        // widget
        let user_set_lines: Vec<_> = self.text.split('\n').collect();

        for line in user_set_lines {
            if line.chars().count() < self.bounding_box.get_width() as usize {
                // the line fits in the width of the widget
                lines.push(line.to_string());
            }
            else {
                // the line does not fit and needs to be split

                // The string which holds the line we are constructing
                let mut label_line = String::new();

                for c in line.chars().collect::<Vec<_>>() {
                    label_line.push(c);

                    if label_line.chars().count() == 
                       self.bounding_box.get_width() as usize
                    {
                        lines.push(label_line.clone());
                        label_line.clear();
                    }
                }
            }
        }

        let mut x = 0;
        let mut y = 0;

        for line in lines {
            for c in line.chars().collect::<Vec<_>>() {
                display_buffer.set_char(
                    c,
                    x + abs_pos.get_x(),
                    y + abs_pos.get_y()
                );

                x += 1;
            }

            x = 0;
            y += 1;
        }
    }

    fn get_bounding_box(&self) -> BoundingBox {
        return self.bounding_box;
    }
}