use std::ops::{Index, IndexMut, Deref, DerefMut};
use core::position::{Pos, Size, HasSize};
pub trait CellAccessor: HasSize {
fn cellvec(&self) -> &Vec<Cell>;
fn cellvec_mut(&mut self) -> &mut Vec<Cell>;
fn clear(&mut self, blank: Cell) {
for cell in self.cellvec_mut().iter_mut() {
*cell = blank;
}
}
fn pos_to_index(&self, x: usize, y: usize) -> Option<usize> {
let (cols, rows) = self.size();
if x < cols && y < rows {
Some((cols * y) + x)
} else {
None
}
}
fn get(&self, x: usize, y: usize) -> Option<&Cell> {
match self.pos_to_index(x, y) {
Some(i) => self.cellvec().get(i),
None => None,
}
}
fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut Cell> {
match self.pos_to_index(x, y) {
Some(i) => self.cellvec_mut().get_mut(i),
None => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CellBuffer {
cols: usize,
rows: usize,
buf: Vec<Cell>,
}
impl CellBuffer {
pub fn new(cols: usize, rows: usize, cell: Cell) -> CellBuffer {
CellBuffer {
cols: cols,
rows: rows,
buf: vec![cell; cols * rows],
}
}
pub fn resize(&mut self, newcols: usize, newrows: usize, blank: Cell) {
let newlen = newcols * newrows;
let mut newbuf: Vec<Cell> = Vec::with_capacity(newlen);
for y in 0..newrows {
for x in 0..newcols {
let cell = self.get(x, y).unwrap_or(&blank);
newbuf.push(*cell);
}
}
self.buf = newbuf;
self.cols = newcols;
self.rows = newrows;
}
}
impl HasSize for CellBuffer {
fn size(&self) -> Size {
(self.cols, self.rows)
}
}
impl CellAccessor for CellBuffer {
fn cellvec(&self) -> &Vec<Cell> {
&self.buf
}
fn cellvec_mut(&mut self) -> &mut Vec<Cell> {
&mut self.buf
}
}
impl Deref for CellBuffer {
type Target = [Cell];
fn deref<'a>(&'a self) -> &'a [Cell] {
&self.buf
}
}
impl DerefMut for CellBuffer {
fn deref_mut<'a>(&'a mut self) -> &'a mut [Cell] {
&mut self.buf
}
}
impl Index<Pos> for CellBuffer {
type Output = Cell;
fn index<'a>(&'a self, index: Pos) -> &'a Cell {
let (x, y) = index;
self.get(x, y).expect("index out of bounds")
}
}
impl IndexMut<Pos> for CellBuffer {
fn index_mut<'a>(&'a mut self, index: Pos) -> &'a mut Cell {
let (x, y) = index;
self.get_mut(x, y).expect("index out of bounds")
}
}
impl Default for CellBuffer {
fn default() -> CellBuffer {
CellBuffer::new(0, 0, Cell::default())
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Cell {
ch: char,
fg: Color,
bg: Color,
attrs: Attr,
}
impl Cell {
pub fn new(ch: char, fg: Color, bg: Color, attrs: Attr) -> Cell {
Cell {
ch: ch,
fg: fg,
bg: bg,
attrs: attrs,
}
}
pub fn with_char(ch: char) -> Cell {
Cell::new(ch, Color::Default, Color::Default, Attr::Default)
}
pub fn with_style(fg: Color, bg: Color, attr: Attr) -> Cell {
Cell::new(' ', fg, bg, attr)
}
pub fn ch(&self) -> char {
self.ch
}
pub fn set_ch(&mut self, newch: char) -> &mut Cell {
self.ch = newch;
self
}
pub fn fg(&self) -> Color {
self.fg
}
pub fn set_fg(&mut self, newfg: Color) -> &mut Cell {
self.fg = newfg;
self
}
pub fn bg(&self) -> Color {
self.bg
}
pub fn set_bg(&mut self, newbg: Color) -> &mut Cell {
self.bg = newbg;
self
}
pub fn attrs(&self) -> Attr {
self.attrs
}
pub fn set_attrs(&mut self, newattrs: Attr) -> &mut Cell {
self.attrs = newattrs;
self
}
}
impl Default for Cell {
fn default() -> Cell {
Cell::new(' ', Color::Default, Color::Default, Attr::Default)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Color {
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
Byte(u8),
Default,
}
impl Color {
pub fn as_byte(&self) -> u8 {
match *self {
Color::Black => 0x00,
Color::Red => 0x01,
Color::Green => 0x02,
Color::Yellow => 0x03,
Color::Blue => 0x04,
Color::Magenta => 0x05,
Color::Cyan => 0x06,
Color::White => 0x07,
Color::Byte(b) => b,
Color::Default => panic!("Attempted to cast default color to u8"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Attr {
Default = 0b000,
Bold = 0b001,
Underline = 0b010,
BoldUnderline = 0b011,
Reverse = 0b100,
BoldReverse = 0b101,
UnderlineReverse = 0b110,
BoldReverseUnderline = 0b111,
}