use std::slice;
use prototty::*;
use cgmath::Vector2;
use ansi_colour::Colour;
use defaults::*;
use super::iterators::*;
const BLANK: char = ' ';
pub type Iter<'a> = slice::Iter<'a, CanvasCell>;
pub type IterMut<'a> = slice::IterMut<'a, CanvasCell>;
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct CanvasCell {
pub character: char,
pub foreground_colour: Colour,
pub background_colour: Colour,
pub bold: bool,
pub underline: bool,
}
impl Default for CanvasCell {
fn default() -> Self {
Self {
character: BLANK,
foreground_colour: DEFAULT_FG,
background_colour: DEFAULT_BG,
bold: false,
underline: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Canvas {
size: Vector2<u16>,
cells: Vec<CanvasCell>,
}
impl Canvas {
pub fn new<D: Into<Vector2<u16>>>(size: D) -> Self {
let size = size.into();
let capacity = (size.x * size.y) as usize;
let mut cells = Vec::with_capacity(capacity);
cells.resize(capacity, Default::default());
Self {
size,
cells,
}
}
pub fn get_mut<C: Into<Vector2<i16>>>(&mut self, coord: C) -> Option<&mut CanvasCell> {
let coord = coord.into();
if coord.x < 0 || coord.y < 0 {
return None;
}
let coord: Vector2<u16> = coord.cast();
if coord.x >= self.size.x || coord.y >= self.size.y {
return None;
}
Some(&mut self.cells[(coord.y * self.size.x + coord.x) as usize])
}
pub fn get<C: Into<Vector2<i16>>>(&self, coord: C) -> Option<&CanvasCell> {
let coord = coord.into();
if coord.x < 0 || coord.y < 0 {
return None;
}
let coord: Vector2<u16> = coord.cast();
if coord.x >= self.size.x || coord.y >= self.size.y {
return None;
}
Some(&self.cells[(coord.y * self.size.x + coord.x) as usize])
}
pub fn coords(&self) -> CoordIter {
CoordIter::new(self.size)
}
pub fn iter(&self) -> Iter {
self.cells.iter()
}
pub fn iter_mut(&mut self) -> IterMut {
self.cells.iter_mut()
}
pub fn enumerate(&self) -> CoordEnumerate<CanvasCell> {
CoordEnumerate::new(self.coords(), self.iter())
}
pub fn enumerate_mut(&mut self) -> CoordEnumerateMut<CanvasCell> {
CoordEnumerateMut::new(self.coords(), self.iter_mut())
}
}
impl View for Canvas {
fn view<G: ViewGrid>(&self, offset: Vector2<i16>, depth: i16, grid: &mut G) {
for (coord, canvas_cell) in izip!(CoordIter::new(self.size), self.cells.iter()) {
let coord = offset + coord;
if let Some(terminal_cell) = grid.get_mut(coord) {
terminal_cell.update_with_style(canvas_cell.character, depth,
canvas_cell.foreground_colour,
canvas_cell.background_colour,
canvas_cell.bold,
canvas_cell.underline);
}
}
}
}
impl ViewSize for Canvas {
fn size(&self) -> Vector2<u16> { self.size }
}