use std::io::prelude::*;
use super::Color;
pub struct Gui {
width: i64,
height: i64,
foreground_color_buffer: Vec<Vec<Color>>,
background_color_buffer: Vec<Vec<Color>>,
character_buffer: Vec<Vec<char>>,
print_buffer: Vec<char>
}
impl Gui {
pub fn new(width: i64, height: i64) -> Self {
let width = width as usize; let height = height as usize;
let mut foreground_color_buffer = Vec::with_capacity(height);
let mut background_color_buffer = Vec::with_capacity(height);
let mut character_buffer = Vec::with_capacity(height);
let mut color_buffer = Vec::with_capacity(width);
for _ in 0..width {
color_buffer.push(Color::new(0, 0, 0));
}
let mut line_buffer = Vec::with_capacity(width);
for _ in 0..width {
line_buffer.push(' ');
}
for _ in 0..height {
foreground_color_buffer.push(color_buffer.clone());
background_color_buffer.push(color_buffer.clone());
character_buffer.push(line_buffer.clone());
}
let pixel_count = width * height;
let new_line_count = width;
let ansi_code_count = 39 * pixel_count + 3;
let mut print_buffer = Vec::with_capacity(pixel_count + new_line_count + ansi_code_count);
for _ in 0..print_buffer.capacity() {
print_buffer.push(' ');
}
let mut index = 0;
for _ in 0..height {
for _ in 0..width { print_buffer[index] = '\x1b'; index += 1;
print_buffer[index] = '['; index += 1;
print_buffer[index] = '3'; index += 1;
print_buffer[index] = '8'; index += 1;
print_buffer[index] = ';'; index += 1;
print_buffer[index] = '2'; index += 1;
print_buffer[index] = ';'; index += 4;
print_buffer[index] = ';'; index += 4;
print_buffer[index] = ';'; index += 4;
print_buffer[index] = 'm'; index += 1;
print_buffer[index] = '\x1b'; index += 1;
print_buffer[index] = '['; index += 1;
print_buffer[index] = '4'; index += 1;
print_buffer[index] = '8'; index += 1;
print_buffer[index] = ';'; index += 1;
print_buffer[index] = '2'; index += 1;
print_buffer[index] = ';'; index += 4;
print_buffer[index] = ';'; index += 4;
print_buffer[index] = ';'; index += 4;
print_buffer[index] = 'm'; index += 2;
}
print_buffer[index] = '\n'; index += 1;
}
print_buffer[index] = '\x1b'; index += 1;
print_buffer[index] = '['; index += 1;
print_buffer[index] = 'm';
let width = width as i64;
let height = height as i64;
Self {
width,
height,
foreground_color_buffer,
background_color_buffer,
character_buffer,
print_buffer
}
}
pub fn display(&mut self) {
let mut index = 0;
for y in 0..self.height as usize {
for x in 0..self.width as usize {
let c = self.character_buffer[y][x];
let fg = self.foreground_color_buffer[y][x];
let bg = self.background_color_buffer[y][x];
let fg_red = format!("{:0>3}", fg.r).chars().collect::<Vec<_>>();
let fg_green = format!("{:0>3}", fg.g).chars().collect::<Vec<_>>();
let fg_blue = format!("{:0>3}", fg.b).chars().collect::<Vec<_>>();
let bg_red = format!("{:0>3}", bg.r).chars().collect::<Vec<_>>();
let bg_green = format!("{:0>3}", bg.g).chars().collect::<Vec<_>>();
let bg_blue = format!("{:0>3}", bg.b).chars().collect::<Vec<_>>();
index += 7;
self.print_buffer[index] = fg_red[0]; index += 1; self.print_buffer[index] = fg_red[1]; index += 1;
self.print_buffer[index] = fg_red[2]; index += 2;
self.print_buffer[index] = fg_green[0]; index += 1; self.print_buffer[index] = fg_green[1]; index += 1;
self.print_buffer[index] = fg_green[2]; index += 2;
self.print_buffer[index] = fg_blue[0]; index += 1; self.print_buffer[index] = fg_blue[1]; index += 1;
self.print_buffer[index] = fg_blue[2]; index += 9;
self.print_buffer[index] = bg_red[0]; index += 1; self.print_buffer[index] = bg_red[1]; index += 1;
self.print_buffer[index] = bg_red[2]; index += 2;
self.print_buffer[index] = bg_green[0]; index += 1; self.print_buffer[index] = bg_green[1]; index += 1;
self.print_buffer[index] = bg_green[2]; index += 2;
self.print_buffer[index] = bg_blue[0]; index += 1; self.print_buffer[index] = bg_blue[1]; index += 1;
self.print_buffer[index] = bg_blue[2]; index += 2;
self.print_buffer[index] = c; index += 1; }
index += 1;
}
let mut print_string = self.print_buffer.iter().collect::<String>();
print_string = print_string.trim_end_matches(" ").to_string();
print!("\x1b[H{}", print_string);
std::io::stdout().flush().unwrap();
}
}
impl Gui {
pub fn width(&self) -> &i64 {
&self.width
}
pub fn height(&self) -> &i64 {
&self.height
}
}
impl Gui { pub fn clear_terminal(&self) {
print!("\x1b[H\x1b[2J");
std::io::stdout().flush().unwrap();
}
pub fn hide_cursor(&self) {
print!("\x1b[?25l");
std::io::stdout().flush().unwrap();
}
pub fn show_cursor(&self) {
print!("\x1b[?25h");
std::io::stdout().flush().unwrap();
}
}
impl Gui { pub fn pixel(&mut self, x: i64, y: i64, c: char, fg: Color, bg: Color) {
if x >= self.width || y >= self.height || x < 0 || y < 0 {
return;
}
let x = x as usize;
let y = y as usize;
self.character_buffer[y][x] = c;
if fg != Color::DEFAULT {
self.foreground_color_buffer[y][x] = fg;
}
if bg != Color::DEFAULT {
self.background_color_buffer[y][x] = bg;
}
}
pub fn clear(&mut self, c: char, fg: Color, bg: Color) {
for y in 0..self.height {
for x in 0..self.width {
self.pixel(x, y, c, fg, bg);
}
}
}
pub fn stroke_rect(&mut self, x: i64, y: i64, width: i64, height: i64, c: char, fg: Color, bg: Color) {
for x in x..x+width {
self.pixel(x, y, c, fg, bg);
self.pixel(x, y+height-1, c, fg, bg);
}
for y in y..y+height {
self.pixel(x, y, c, fg, bg);
self.pixel(x+width-1, y-1, c, fg, bg);
}
}
pub fn fill_rect(&mut self, x: i64, y: i64, width: i64, height: i64, c: char, fg: Color, bg: Color) {
for y in y..y+height {
for x in x..x+width {
self.pixel(x, y, c, fg, bg);
}
}
}
pub fn rect(&mut self, x: i64, y: i64, width: i64, height: i64, stroke_char: char, fill_char: char, stroke_fg: Color, stroke_bg: Color, fill_fg: Color, fill_bg: Color) {
for y_coord in 0..height {
for x_coord in 0..width {
if x_coord == 0 || x_coord == width - 1 || y_coord == 0 || y_coord == height - 1 {
self.pixel(x + x_coord, y + y_coord, stroke_char, stroke_fg, stroke_bg);
}
else {
self.pixel(x + x_coord, y + y_coord, fill_char, fill_fg, fill_bg);
}
}
}
}
pub fn horizontal_text(&mut self, x: i64, y: i64, text: &str, fg: Color, bg: Color) {
for i in 0..text.len() as i64 {
self.pixel(x + i, y, text.chars().collect::<Vec<_>>()[i as usize], fg, bg);
}
}
pub fn vertical_text(&mut self, x: i64, y: i64, text: &str, fg: Color, bg: Color) {
for i in 0..text.len() as i64 {
self.pixel(x, y + i, text.chars().collect::<Vec<_>>()[i as usize], fg, bg);
}
}
pub fn line(&mut self, mut x0: i64, mut y0: i64, mut x1: i64, mut y1: i64, c: char, fg: Color, bg: Color) { let mut dx = x1 - x0;
let mut dy = y1 - y0;
if dy == 0 { if x0 > x1 {
let temp = x0;
x0 = x1;
x1 = temp;
y0 = y1;
}
for x in x0..=x1 {
self.pixel(x, y0, c, fg, bg);
}
return;
}
else if dx == 0 { if y0 > y1 {
x0 = x1;
let temp = y0;
y0 = y1;
y1 = temp;
}
for y in y0..=y1 {
self.pixel(x0, y, c, fg, bg);
}
return;
}
if x0 > x1 { let mut temp = x0;
x0 = x1;
x1 = temp;
temp = y0;
y0 = y1;
y1 = temp;
dx = x1 - x0;
dy = y1 - y0;
}
let loop_x = dy.abs() <= dx.abs();
if loop_x {
if x0 > x1 {
let mut temp = x0;
x0 = x1;
x1 = temp;
temp = y0;
y0 = y1;
y1 = temp;
dx = x1 - x0;
dy = y1 - y0;
}
let res_mod = if dy > 0 {1} else {-1};
let mut y = y0;
let mut err = -dx;
let slope = dy;
let dx2 = dx << 1;
for x in x0..=x1 {
self.pixel(x, y, c, fg, bg);
err += 2 * slope.abs();
if err >= 0 {
err -= dx2;
y += res_mod;
}
}
}
else {
if y0 > y1 {
let mut temp = x0;
x0 = x1;
x1 = temp;
temp = y0;
y0 = y1;
y1 = temp;
dx = x1 - x0;
dy = y1 - y0;
}
let res_mod = if dx > 0 {1} else {-1};
let mut x = x0;
let mut err = -dy;
let slope = dx;
let dy2 = dy << 1;
for y in y0..=y1 {
self.pixel(x, y, c, fg, bg);
err += 2 * slope.abs();
if err >= 0 {
err -= dy2;
x += res_mod;
}
}
}
}
}