owen 0.0.1

Terminal User Interface library
Documentation
use crate::{
    arrangement::{Position, Size},
    style::Style,
};

// Represents a character in the terminal
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Cell {
    pub symbol: char,
    pub style: Style,
}

impl Default for Cell {
    fn default() -> Self {
        Cell {
            symbol: ' ',
            style: Style::default(),
        }
    }
}

pub struct Buffer {
    content: Vec<Cell>,
    size: Size,
}

impl Buffer {
    pub fn new(size: Size) -> Buffer {
        Buffer {
            content: vec![Cell::default(); size.area() as usize],
            size,
        }
    }

    // Gets the size of the buffer
    pub fn size(&self) -> Size {
        self.size
    }

    // Resizes the buffer to a new size
    pub fn resize(&mut self, size: Size) {
        self.content
            .resize_with(size.area().into(), Default::default);
        self.size = size;
    }

    // Gets the index of the position in the buffer
    fn index_of(&self, position: Position) -> Option<usize> {
        // Don't return an index of a position that isn't in the buffer
        if position.row > self.size.rows || position.column > self.size.columns {
            return None;
        }
        let index = (position.row * self.size.columns) + position.column;
        Some((index).into())
    }

    // Gets the cell at a position
    pub fn cell(&self, position: Position) -> Option<&Cell> {
        let index = self.index_of(position)?;
        Some(&self.content[index])
    }

    // Gets a mutable reference to a cell at a position
    pub fn cell_mut(&mut self, position: Position) -> Option<&mut Cell> {
        let index = self.index_of(position)?;
        Some(&mut self.content[index])
    }

    // Gets all the cells that are different from itself
    pub fn diff<'d>(
        &self,
        other: &'d Buffer,
        position: Position,
        size: Size,
    ) -> Vec<(&'d Cell, Position)> {
        let mut diff = Vec::new();
        for row in position.row..size.rows {
            for column in position.column..size.columns {
                let position = Position::from(row, column);
                match (other.cell(position), self.cell(position)) {
                    (Some(other_cell), Some(buffer_cell)) => {
                        if other_cell != buffer_cell {
                            diff.push((other_cell, position));
                        }
                    }
                    (Some(other_cell), None) => diff.push((other_cell, position)),
                    _ => (),
                }
            }
        }
        diff
    }
}