|
|
|
@ -6,17 +6,25 @@ use unicode_segmentation::UnicodeSegmentation;
|
|
|
|
|
use layout::Rect;
|
|
|
|
|
use style::Color;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct Cell<'a> {
|
|
|
|
|
pub symbol: &'a str,
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
|
pub struct Cell {
|
|
|
|
|
pub symbol: String,
|
|
|
|
|
pub fg: Color,
|
|
|
|
|
pub bg: Color,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> Default for Cell<'a> {
|
|
|
|
|
fn default() -> Cell<'a> {
|
|
|
|
|
impl Cell {
|
|
|
|
|
pub fn reset(&mut self) {
|
|
|
|
|
self.symbol = " ".into();
|
|
|
|
|
self.fg = Color::Reset;
|
|
|
|
|
self.bg = Color::Reset;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for Cell {
|
|
|
|
|
fn default() -> Cell {
|
|
|
|
|
Cell {
|
|
|
|
|
symbol: "",
|
|
|
|
|
symbol: " ".into(),
|
|
|
|
|
fg: Color::Reset,
|
|
|
|
|
bg: Color::Reset,
|
|
|
|
|
}
|
|
|
|
@ -24,13 +32,13 @@ impl<'a> Default for Cell<'a> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct Buffer<'a> {
|
|
|
|
|
area: Rect,
|
|
|
|
|
content: Vec<Cell<'a>>,
|
|
|
|
|
pub struct Buffer {
|
|
|
|
|
pub area: Rect,
|
|
|
|
|
pub content: Vec<Cell>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> Default for Buffer<'a> {
|
|
|
|
|
fn default() -> Buffer<'a> {
|
|
|
|
|
impl Default for Buffer {
|
|
|
|
|
fn default() -> Buffer {
|
|
|
|
|
Buffer {
|
|
|
|
|
area: Default::default(),
|
|
|
|
|
content: Vec::new(),
|
|
|
|
@ -38,13 +46,13 @@ impl<'a> Default for Buffer<'a> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> Buffer<'a> {
|
|
|
|
|
pub fn empty(area: Rect) -> Buffer<'a> {
|
|
|
|
|
impl Buffer {
|
|
|
|
|
pub fn empty(area: Rect) -> Buffer {
|
|
|
|
|
let cell: Cell = Default::default();
|
|
|
|
|
Buffer::filled(area, cell)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn filled(area: Rect, cell: Cell<'a>) -> Buffer<'a> {
|
|
|
|
|
pub fn filled(area: Rect, cell: Cell) -> Buffer {
|
|
|
|
|
let size = area.area() as usize;
|
|
|
|
|
let mut content = Vec::with_capacity(size);
|
|
|
|
|
for _ in 0..size {
|
|
|
|
@ -56,7 +64,7 @@ impl<'a> Buffer<'a> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn content(&'a self) -> &'a [Cell<'a>] {
|
|
|
|
|
pub fn content(&self) -> &[Cell] {
|
|
|
|
|
&self.content
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -64,79 +72,59 @@ impl<'a> Buffer<'a> {
|
|
|
|
|
&self.area
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn index_of(&self, x: u16, y: u16) -> Option<usize> {
|
|
|
|
|
let index = (y * self.area.width + x) as usize;
|
|
|
|
|
if index < self.content.len() {
|
|
|
|
|
Some(index)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
pub fn at(&self, x: u16, y: u16) -> &Cell {
|
|
|
|
|
let i = self.index_of(x, y);
|
|
|
|
|
&self.content[i]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn pos_of(&self, i: usize) -> Option<(u16, u16)> {
|
|
|
|
|
if self.area.width > 0 {
|
|
|
|
|
Some((i as u16 % self.area.width, i as u16 / self.area.width))
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
pub fn index_of(&self, x: u16, y: u16) -> usize {
|
|
|
|
|
let index = (y * self.area.width + x) as usize;
|
|
|
|
|
debug_assert!(index < self.content.len());
|
|
|
|
|
index
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn next_pos(&self, x: u16, y: u16) -> Option<(u16, u16)> {
|
|
|
|
|
let (nx, ny) = if x + 1 > self.area.width {
|
|
|
|
|
(0, y + 1)
|
|
|
|
|
} else {
|
|
|
|
|
(x + 1, y)
|
|
|
|
|
};
|
|
|
|
|
if ny >= self.area.height {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some((nx, ny))
|
|
|
|
|
}
|
|
|
|
|
pub fn pos_of(&self, i: usize) -> (u16, u16) {
|
|
|
|
|
debug_assert!(self.area.width > 0);
|
|
|
|
|
(i as u16 % self.area.width, i as u16 / self.area.width)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set(&mut self, x: u16, y: u16, cell: Cell<'a>) {
|
|
|
|
|
if let Some(i) = self.index_of(x, y) {
|
|
|
|
|
self.content[i] = cell;
|
|
|
|
|
}
|
|
|
|
|
pub fn set(&mut self, x: u16, y: u16, cell: Cell) {
|
|
|
|
|
let i = self.index_of(x, y);
|
|
|
|
|
self.content[i] = cell;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_symbol(&mut self, x: u16, y: u16, symbol: &'a str) {
|
|
|
|
|
if let Some(i) = self.index_of(x, y) {
|
|
|
|
|
self.content[i].symbol = symbol;
|
|
|
|
|
}
|
|
|
|
|
pub fn set_symbol<S>(&mut self, x: u16, y: u16, symbol: S)
|
|
|
|
|
where S: Into<String>
|
|
|
|
|
{
|
|
|
|
|
let i = self.index_of(x, y);
|
|
|
|
|
self.content[i].symbol = symbol.into();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_fg(&mut self, x: u16, y: u16, color: Color) {
|
|
|
|
|
if let Some(i) = self.index_of(x, y) {
|
|
|
|
|
self.content[i].fg = color;
|
|
|
|
|
}
|
|
|
|
|
let i = self.index_of(x, y);
|
|
|
|
|
self.content[i].fg = color;
|
|
|
|
|
}
|
|
|
|
|
pub fn set_bg(&mut self, x: u16, y: u16, color: Color) {
|
|
|
|
|
if let Some(i) = self.index_of(x, y) {
|
|
|
|
|
self.content[i].bg = color;
|
|
|
|
|
}
|
|
|
|
|
let i = self.index_of(x, y);
|
|
|
|
|
self.content[i].bg = color;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_string(&mut self, x: u16, y: u16, string: &'a str, fg: Color, bg: Color) {
|
|
|
|
|
pub fn set_string(&mut self, x: u16, y: u16, string: &str, fg: Color, bg: Color) {
|
|
|
|
|
self.set_characters(x, y, string, usize::MAX, fg, bg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_characters(&mut self,
|
|
|
|
|
x: u16,
|
|
|
|
|
y: u16,
|
|
|
|
|
string: &'a str,
|
|
|
|
|
string: &str,
|
|
|
|
|
limit: usize,
|
|
|
|
|
fg: Color,
|
|
|
|
|
bg: Color) {
|
|
|
|
|
let index = self.index_of(x, y);
|
|
|
|
|
if index.is_none() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let mut index = index.unwrap();
|
|
|
|
|
let mut index = self.index_of(x, y);
|
|
|
|
|
let graphemes = UnicodeSegmentation::graphemes(string, true).collect::<Vec<&str>>();
|
|
|
|
|
let max_index = min((self.area.width - x) as usize, limit);
|
|
|
|
|
for s in graphemes.iter().take(max_index) {
|
|
|
|
|
self.content[index].symbol = s;
|
|
|
|
|
for s in graphemes.into_iter().take(max_index) {
|
|
|
|
|
self.content[index].symbol = s.into();
|
|
|
|
|
self.content[index].fg = fg;
|
|
|
|
|
self.content[index].bg = bg;
|
|
|
|
|
index += 1;
|
|
|
|
@ -145,21 +133,37 @@ impl<'a> Buffer<'a> {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn update_colors(&mut self, x: u16, y: u16, fg: Color, bg: Color) {
|
|
|
|
|
if let Some(i) = self.index_of(x, y) {
|
|
|
|
|
self.content[i].fg = fg;
|
|
|
|
|
self.content[i].bg = bg;
|
|
|
|
|
let i = self.index_of(x, y);
|
|
|
|
|
self.content[i].fg = fg;
|
|
|
|
|
self.content[i].bg = bg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update_cell<S>(&mut self, x: u16, y: u16, symbol: S, fg: Color, bg: Color)
|
|
|
|
|
where S: Into<String>
|
|
|
|
|
{
|
|
|
|
|
let i = self.index_of(x, y);
|
|
|
|
|
self.content[i].symbol = symbol.into();
|
|
|
|
|
self.content[i].fg = fg;
|
|
|
|
|
self.content[i].bg = bg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn resize(&mut self, area: Rect) {
|
|
|
|
|
let length = area.area() as usize;
|
|
|
|
|
if self.content.len() > length {
|
|
|
|
|
self.content.truncate(length);
|
|
|
|
|
} else {
|
|
|
|
|
self.content.resize(length, Default::default());
|
|
|
|
|
}
|
|
|
|
|
self.area = area;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update_cell(&mut self, x: u16, y: u16, symbol: &'a str, fg: Color, bg: Color) {
|
|
|
|
|
if let Some(i) = self.index_of(x, y) {
|
|
|
|
|
self.content[i].symbol = symbol;
|
|
|
|
|
self.content[i].fg = fg;
|
|
|
|
|
self.content[i].bg = bg;
|
|
|
|
|
pub fn reset(&mut self) {
|
|
|
|
|
for c in &mut self.content {
|
|
|
|
|
c.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn merge(&'a mut self, other: Buffer<'a>) {
|
|
|
|
|
pub fn merge(&mut self, other: Buffer) {
|
|
|
|
|
let area = self.area.union(&other.area);
|
|
|
|
|
let cell: Cell = Default::default();
|
|
|
|
|
self.content.resize(area.area() as usize, cell.clone());
|
|
|
|
@ -169,7 +173,7 @@ impl<'a> Buffer<'a> {
|
|
|
|
|
let offset_y = self.area.y - area.y;
|
|
|
|
|
let size = self.area.area() as usize;
|
|
|
|
|
for i in (0..size).rev() {
|
|
|
|
|
let (x, y) = self.pos_of(i).unwrap();
|
|
|
|
|
let (x, y) = self.pos_of(i);
|
|
|
|
|
// New index in content
|
|
|
|
|
let k = ((y + offset_y) * area.width + (x + offset_x)) as usize;
|
|
|
|
|
self.content[k] = self.content[i].clone();
|
|
|
|
@ -184,7 +188,7 @@ impl<'a> Buffer<'a> {
|
|
|
|
|
let offset_y = other.area.y - area.y;
|
|
|
|
|
let size = other.area.area() as usize;
|
|
|
|
|
for i in 0..size {
|
|
|
|
|
let (x, y) = other.pos_of(i).unwrap();
|
|
|
|
|
let (x, y) = other.pos_of(i);
|
|
|
|
|
// New index in content
|
|
|
|
|
let k = ((y + offset_y) * area.width + (x + offset_x)) as usize;
|
|
|
|
|
self.content[k] = other.content[i].clone();
|
|
|
|
|