2016-04-10 19:19:39 -04:00
|
|
|
//! Functions for computing properties of the terminal grid
|
|
|
|
|
2016-06-08 13:39:49 -04:00
|
|
|
use std::ops::{Index, IndexMut, Deref, DerefMut, Range, RangeTo, RangeFrom};
|
2016-06-04 22:40:30 -04:00
|
|
|
use std::slice::{Iter, IterMut};
|
2016-05-30 23:44:37 -04:00
|
|
|
|
2016-06-08 13:39:49 -04:00
|
|
|
use util::Rotate;
|
|
|
|
|
|
|
|
use term::{Cursor, DEFAULT_FG, DEFAULT_BG};
|
2016-05-30 23:44:37 -04:00
|
|
|
use ::Rgb;
|
2016-04-10 19:19:39 -04:00
|
|
|
|
2016-05-30 23:44:37 -04:00
|
|
|
#[derive(Clone, Debug)]
|
2016-04-10 19:19:39 -04:00
|
|
|
pub struct Cell {
|
2016-05-30 23:44:37 -04:00
|
|
|
pub c: char,
|
|
|
|
pub fg: Rgb,
|
|
|
|
pub bg: Rgb,
|
2016-06-06 19:54:15 -04:00
|
|
|
pub flags: CellFlags,
|
|
|
|
}
|
|
|
|
|
|
|
|
bitflags! {
|
|
|
|
pub flags CellFlags: u32 {
|
2016-06-06 20:43:14 -04:00
|
|
|
const INVERSE = 0b00000001,
|
|
|
|
const BOLD = 0b00000010,
|
|
|
|
const ITALIC = 0b00000100,
|
|
|
|
const UNDERLINE = 0b00001000,
|
2016-06-06 19:54:15 -04:00
|
|
|
}
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Cell {
|
2016-05-30 23:44:37 -04:00
|
|
|
pub fn new(c: char) -> Cell {
|
2016-04-10 19:19:39 -04:00
|
|
|
Cell {
|
2016-05-30 23:44:37 -04:00
|
|
|
c: c.into(),
|
|
|
|
bg: Default::default(),
|
|
|
|
fg: Default::default(),
|
2016-06-06 19:54:15 -04:00
|
|
|
flags: CellFlags::empty(),
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
|
|
|
}
|
2016-06-08 13:39:49 -04:00
|
|
|
|
|
|
|
pub fn reset(&mut self) {
|
|
|
|
self.c = ' ';
|
|
|
|
self.flags = CellFlags::empty();
|
|
|
|
|
|
|
|
// FIXME shouldn't know about term
|
|
|
|
self.bg = DEFAULT_BG;
|
|
|
|
self.fg = DEFAULT_FG;
|
|
|
|
}
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Represents the terminal display contents
|
2016-05-30 23:44:37 -04:00
|
|
|
#[derive(Clone)]
|
2016-04-10 19:19:39 -04:00
|
|
|
pub struct Grid {
|
|
|
|
/// Rows in the grid. Each row holds a list of cells corresponding to the columns in that row.
|
2016-06-08 13:39:49 -04:00
|
|
|
raw: Vec<Row>,
|
2016-04-10 19:19:39 -04:00
|
|
|
|
|
|
|
/// Number of columns
|
2016-04-11 11:05:19 -04:00
|
|
|
cols: usize,
|
2016-04-10 19:19:39 -04:00
|
|
|
|
|
|
|
/// Number of rows.
|
|
|
|
///
|
|
|
|
/// Invariant: rows is equivalent to cells.len()
|
|
|
|
rows: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Grid {
|
|
|
|
pub fn new(rows: usize, cols: usize) -> Grid {
|
2016-06-08 13:39:49 -04:00
|
|
|
let mut raw = Vec::with_capacity(rows);
|
2016-06-06 20:44:06 -04:00
|
|
|
for _ in 0..rows {
|
2016-06-08 13:39:49 -04:00
|
|
|
raw.push(Row::new(cols));
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Grid {
|
|
|
|
raw: raw,
|
2016-04-11 11:05:19 -04:00
|
|
|
cols: cols,
|
2016-04-10 19:19:39 -04:00
|
|
|
rows: rows,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-06 20:45:09 -04:00
|
|
|
#[inline]
|
2016-06-08 13:39:49 -04:00
|
|
|
pub fn rows(&self) -> Iter<Row> {
|
2016-06-04 22:40:30 -04:00
|
|
|
self.raw.iter()
|
|
|
|
}
|
|
|
|
|
2016-06-06 20:45:09 -04:00
|
|
|
#[inline]
|
2016-06-08 13:39:49 -04:00
|
|
|
pub fn rows_mut(&mut self) -> IterMut<Row> {
|
2016-06-04 22:40:30 -04:00
|
|
|
self.raw.iter_mut()
|
|
|
|
}
|
|
|
|
|
2016-06-06 20:45:09 -04:00
|
|
|
#[inline]
|
2016-06-04 22:40:30 -04:00
|
|
|
pub fn num_rows(&self) -> usize {
|
2016-06-06 20:45:09 -04:00
|
|
|
self.raw.len()
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
2016-04-11 11:05:19 -04:00
|
|
|
|
2016-06-06 20:45:09 -04:00
|
|
|
#[inline]
|
2016-06-04 22:40:30 -04:00
|
|
|
pub fn num_cols(&self) -> usize {
|
2016-06-06 20:45:09 -04:00
|
|
|
self.raw[0].len()
|
2016-04-11 11:05:19 -04:00
|
|
|
}
|
2016-05-30 23:44:37 -04:00
|
|
|
|
2016-06-08 13:39:49 -04:00
|
|
|
pub fn scroll(&mut self, region: Range<usize>, positions: isize) {
|
|
|
|
self.raw[region].rotate(positions)
|
2016-05-30 23:44:37 -04:00
|
|
|
}
|
|
|
|
|
2016-06-08 13:39:49 -04:00
|
|
|
#[inline]
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
let region = 0..self.num_rows();
|
|
|
|
self.clear_region(region);
|
2016-05-30 23:44:37 -04:00
|
|
|
}
|
|
|
|
|
2016-06-08 13:39:49 -04:00
|
|
|
pub fn clear_region(&mut self, region: Range<usize>) {
|
|
|
|
for row in self.raw[region].iter_mut() {
|
2016-05-30 23:44:37 -04:00
|
|
|
for cell in row.iter_mut() {
|
2016-06-08 13:39:49 -04:00
|
|
|
cell.reset();
|
2016-05-30 23:44:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Index<usize> for Grid {
|
|
|
|
type Output = Row;
|
|
|
|
|
2016-05-30 23:44:37 -04:00
|
|
|
#[inline]
|
2016-04-10 19:19:39 -04:00
|
|
|
fn index<'a>(&'a self, index: usize) -> &'a Row {
|
|
|
|
&self.raw[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IndexMut<usize> for Grid {
|
2016-05-30 23:44:37 -04:00
|
|
|
#[inline]
|
2016-04-10 19:19:39 -04:00
|
|
|
fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Row {
|
|
|
|
&mut self.raw[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 23:44:37 -04:00
|
|
|
impl Index<Cursor> for Grid {
|
|
|
|
type Output = Cell;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index<'a>(&'a self, cursor: Cursor) -> &'a Cell {
|
|
|
|
&self.raw[cursor.y as usize][cursor.x as usize]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IndexMut<Cursor> for Grid {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut<'a>(&'a mut self, cursor: Cursor) -> &'a mut Cell {
|
|
|
|
&mut self.raw[cursor.y as usize][cursor.x as usize]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-10 19:19:39 -04:00
|
|
|
/// A row in the grid
|
2016-05-30 23:44:37 -04:00
|
|
|
#[derive(Debug, Clone)]
|
2016-04-10 19:19:39 -04:00
|
|
|
pub struct Row(Vec<Cell>);
|
|
|
|
|
|
|
|
impl Row {
|
|
|
|
pub fn new(columns: usize) -> Row {
|
2016-05-30 23:44:37 -04:00
|
|
|
Row(vec![Cell::new(' '); columns])
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
|
|
|
|
2016-06-04 22:40:30 -04:00
|
|
|
pub fn cells(&self) -> Iter<Cell> {
|
|
|
|
self.0.iter()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn cells_mut(&mut self) -> IterMut<Cell> {
|
|
|
|
self.0.iter_mut()
|
2016-04-10 19:19:39 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-30 23:44:37 -04:00
|
|
|
impl Deref for Row {
|
|
|
|
type Target = Vec<Cell>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DerefMut for Row {
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
&mut self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-10 19:19:39 -04:00
|
|
|
impl Index<usize> for Row {
|
|
|
|
type Output = Cell;
|
|
|
|
|
2016-05-30 23:44:37 -04:00
|
|
|
#[inline]
|
2016-04-10 19:19:39 -04:00
|
|
|
fn index<'a>(&'a self, index: usize) -> &'a Cell {
|
|
|
|
&self.0[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IndexMut<usize> for Row {
|
2016-05-30 23:44:37 -04:00
|
|
|
#[inline]
|
2016-04-10 19:19:39 -04:00
|
|
|
fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Cell {
|
|
|
|
&mut self.0[index]
|
|
|
|
}
|
|
|
|
}
|
2016-06-08 13:39:49 -04:00
|
|
|
|
|
|
|
impl Index<RangeFrom<usize>> for Row {
|
|
|
|
type Output = [Cell];
|
|
|
|
#[inline]
|
|
|
|
fn index<'a>(&'a self, index: RangeFrom<usize>) -> &'a [Cell] {
|
|
|
|
&self.0[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IndexMut<RangeFrom<usize>> for Row {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut<'a>(&'a mut self, index: RangeFrom<usize>) -> &'a mut [Cell] {
|
|
|
|
&mut self.0[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Index<RangeTo<usize>> for Row {
|
|
|
|
type Output = [Cell];
|
|
|
|
#[inline]
|
|
|
|
fn index<'a>(&'a self, index: RangeTo<usize>) -> &'a [Cell] {
|
|
|
|
&self.0[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IndexMut<RangeTo<usize>> for Row {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut<'a>(&'a mut self, index: RangeTo<usize>) -> &'a mut [Cell] {
|
|
|
|
&mut self.0[index]
|
|
|
|
}
|
|
|
|
}
|