buffer-graphics-lib 0.9.5

Simple graphics library for buffers
Documentation
pub mod mutation;
pub mod shape_box;

use crate::drawing::Renderable;
use crate::prelude::collection::shape_box::FromDrawable;
use crate::prelude::*;
use crate::shapes::collection::shape_box::{FromShape, ShapeBox};
use crate::Graphics;
use graphics_shapes::coord::Coord;
use graphics_shapes::rect::Rect;
use graphics_shapes::Shape;
use std::fmt::Debug;
use std::slice::Iter;

pub mod prelude {
    pub use crate::shapes::collection::shape_box::*;
    pub use crate::shapes::collection::*;
}

#[derive(Debug, Clone)]
pub struct ShapeCollection {
    shapes: Vec<ShapeBox>,
    bounds: Rect,
}

pub fn calc_bounds(list: &[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 ShapeCollection {
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        ShapeCollection {
            shapes: vec![],
            bounds: Rect::new((0, 0), (0, 0)),
        }
    }
}

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

    pub fn len(&self) -> usize {
        self.shapes.len()
    }

    pub fn is_empty(&self) -> bool {
        self.shapes.is_empty()
    }

    fn update_bounds(&mut self) {
        self.bounds = calc_bounds(&self.shapes);
    }

    pub fn remove(&mut self, idx: usize) -> ShapeBox {
        self.shapes.remove(idx)
    }

    pub fn left(&self) -> isize {
        self.bounds.left()
    }

    pub fn top(&self) -> isize {
        self.bounds.top()
    }

    pub fn bottom(&self) -> isize {
        self.bounds.bottom()
    }

    pub fn right(&self) -> isize {
        self.bounds.right()
    }

    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);
        }
    }
}

impl<S: Clone> InsertDrawable<S> for ShapeCollection
where
    ShapeBox: FromDrawable<S>,
{
    fn insert(&mut self, index: usize, drawable: Drawable<S>) {
        InsertShapeBox::insert(self, index, ShapeBox::from_drawable(drawable));
    }

    fn insert_above(&mut self, drawable: Drawable<S>) {
        InsertShapeBox::insert_above(self, ShapeBox::from_drawable(drawable));
    }

    fn insert_under(&mut self, drawable: Drawable<S>) {
        InsertShapeBox::insert_under(self, ShapeBox::from_drawable(drawable));
    }
}

impl<S> InsertShape<S> for ShapeCollection
where
    ShapeBox: FromShape<S>,
{
    fn insert(&mut self, index: usize, shape: S, draw_type: DrawType) {
        InsertShapeBox::insert(self, index, ShapeBox::from_shape(shape, draw_type));
    }

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

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

impl InsertShapeBox for ShapeCollection {
    fn insert(&mut self, index: usize, shape_box: ShapeBox) {
        self.shapes.insert(index, shape_box);
        self.update_bounds();
    }

    fn insert_above(&mut self, shape_box: ShapeBox) {
        InsertShapeBox::insert(self, 0, shape_box);
        self.update_bounds();
    }

    fn insert_under(&mut self, shape_box: ShapeBox) {
        self.shapes.push(shape_box);
        self.update_bounds();
    }
}

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);
    fn insert_above(&mut self, shape_box: ShapeBox);
    fn insert_under(&mut self, shape_box: ShapeBox);
}