buffer-graphics-lib 0.19.1

Simple graphics library for buffers
Documentation
use crate::drawing::Renderable;
use crate::prelude::*;
use crate::{sized_renderable, Graphics};
use graphics_shapes::coord::Coord;
use graphics_shapes::rect::Rect;
use graphics_shapes::shape_box::ShapeBox;
use graphics_shapes::Shape;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::slice::Iter;

pub mod mutation;

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct ShapeCollection {
    shapes: Vec<Drawable<ShapeBox>>,
    bounds: Rect,
}

pub fn calc_bounds(list: &[Drawable<ShapeBox>]) -> Rect {
    if list.is_empty() {
        return Rect::new((0, 0), (0, 0));
    }
    let mut bounds = Rect::new(
        (list[0].left(), list[0].top()),
        (list[0].right(), list[0].bottom()),
    );
    for shape in list.iter().skip(1) {
        bounds = Rect::new(
            (
                bounds.left().min(shape.left()),
                bounds.top().min(shape.top()),
            ),
            (
                bounds.right().max(shape.right()),
                bounds.bottom().max(shape.bottom()),
            ),
        );
    }
    bounds
}

impl Default for ShapeCollection {
    fn default() -> Self {
        ShapeCollection {
            shapes: vec![],
            bounds: Rect::new((0, 0), (0, 0)),
        }
    }
}

impl ShapeCollection {
    #[inline]
    pub fn iter(&self) -> Iter<'_, Drawable<ShapeBox>> {
        self.shapes.iter()
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.shapes.len()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.shapes.is_empty()
    }

    #[inline]
    fn update_bounds(&mut self) {
        self.bounds = calc_bounds(&self.shapes);
    }

    #[inline]
    pub fn remove(&mut self, idx: usize) -> Drawable<ShapeBox> {
        self.shapes.remove(idx)
    }

    #[inline]
    pub fn bounds(&self) -> &Rect {
        &self.bounds
    }

    #[inline]
    pub fn left(&self) -> isize {
        self.bounds.left()
    }

    #[inline]
    pub fn top(&self) -> isize {
        self.bounds.top()
    }

    #[inline]
    pub fn bottom(&self) -> isize {
        self.bounds.bottom()
    }

    #[inline]
    pub fn right(&self) -> isize {
        self.bounds.right()
    }

    #[inline]
    pub fn center(&self) -> Coord {
        self.bounds.center()
    }
}

impl Renderable<ShapeCollection> for ShapeCollection {
    fn render(&self, graphics: &mut Graphics) {
        for shape in &self.shapes {
            shape.render(graphics);
        }
    }
}

sized_renderable!(
    RenderableShapeCollection,
    ShapeCollection,
    |col: &ShapeCollection| (col.bounds().width(), col.bounds().height()),
    |g: &mut Graphics, col: &ShapeCollection| col.render(g)
);

impl InsertDrawable<ShapeBox> for ShapeCollection {
    fn insert(&mut self, index: usize, drawable: Drawable<ShapeBox>) {
        self.shapes.insert(index, drawable);
        self.update_bounds();
    }

    fn insert_above(&mut self, drawable: Drawable<ShapeBox>) {
        self.shapes.push(drawable);
        self.update_bounds();
    }

    fn insert_under(&mut self, drawable: Drawable<ShapeBox>) {
        InsertDrawable::<ShapeBox>::insert(self, 0, drawable);
    }
}

impl<S: Shape> InsertShape<S> for ShapeCollection {
    fn insert(&mut self, index: usize, shape: S, draw_type: DrawType) {
        InsertShapeBox::insert(self, index, shape.to_shape_box(), draw_type);
    }

    fn insert_above(&mut self, shape: S, draw_type: DrawType) {
        InsertShapeBox::insert_above(self, shape.to_shape_box(), draw_type);
    }

    fn insert_under(&mut self, shape: S, draw_type: DrawType) {
        InsertShapeBox::insert_under(self, shape.to_shape_box(), draw_type);
    }
}

impl InsertShapeBox for ShapeCollection {
    fn insert(&mut self, index: usize, shape_box: ShapeBox, draw_type: DrawType) {
        InsertDrawable::insert(self, index, Drawable::from_obj(shape_box, draw_type))
    }

    fn insert_above(&mut self, shape_box: ShapeBox, draw_type: DrawType) {
        InsertDrawable::insert_above(self, Drawable::from_obj(shape_box, draw_type))
    }

    fn insert_under(&mut self, shape_box: ShapeBox, draw_type: DrawType) {
        InsertDrawable::insert_under(self, Drawable::from_obj(shape_box, draw_type))
    }
}

pub trait InsertDrawable<S: Clone>: InsertShapeBox {
    fn insert(&mut self, index: usize, drawable: Drawable<S>);
    fn insert_above(&mut self, drawable: Drawable<S>);
    fn insert_under(&mut self, drawable: Drawable<S>);
}

pub trait InsertShape<S> {
    fn insert(&mut self, index: usize, shape: S, draw_type: DrawType);
    fn insert_above(&mut self, shape: S, draw_type: DrawType);
    fn insert_under(&mut self, shape: S, draw_type: DrawType);
}

pub trait InsertShapeBox {
    fn insert(&mut self, index: usize, shape_box: ShapeBox, draw_type: DrawType);
    fn insert_above(&mut self, shape_box: ShapeBox, draw_type: DrawType);
    fn insert_under(&mut self, shape_box: ShapeBox, draw_type: DrawType);
}