78 lines
2.0 KiB
Rust
78 lines
2.0 KiB
Rust
use super::Rect;
|
|
use std::io::Write;
|
|
|
|
use crossterm::{
|
|
cursor::{MoveDown, MoveTo, MoveToColumn},
|
|
queue, terminal,
|
|
};
|
|
|
|
use crate::Result;
|
|
|
|
use super::{Cell, Pos};
|
|
|
|
pub struct View {
|
|
cells: Vec<Cell>,
|
|
width: u16,
|
|
#[allow(dead_code)]
|
|
height: u16,
|
|
}
|
|
|
|
impl View {
|
|
pub fn new(width: u16, height: u16) -> Self {
|
|
Self {
|
|
width,
|
|
height,
|
|
cells: vec![Cell::default(); (width * height) as usize],
|
|
}
|
|
}
|
|
|
|
pub fn fullscreen() -> Self {
|
|
let (width, height) = terminal::size().expect("Couldnt detect terminal size");
|
|
Self {
|
|
width,
|
|
height,
|
|
cells: vec![Cell::default(); (width * height) as usize],
|
|
}
|
|
}
|
|
|
|
pub fn get(&self, pos: Pos) -> Option<&Cell> {
|
|
self.cells.get((pos.y() * self.width + pos.x()) as usize)
|
|
}
|
|
|
|
pub fn set(&mut self, pos: Pos, cell: Cell) {
|
|
self.cells[(pos.y() * self.width + pos.x()) as usize] = cell;
|
|
}
|
|
|
|
pub fn fill(&mut self, rect: Rect, cell: Cell) {
|
|
for y in rect.pos.y()..rect.pos.y() + rect.height {
|
|
for x in rect.pos.x()..rect.pos.x() + rect.width {
|
|
self.set(Pos::new(x, y), cell);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn fill_all(&mut self, cell: Cell) {
|
|
self.cells.fill(cell);
|
|
}
|
|
|
|
pub fn merge(&mut self, pos: Pos, view: View) {
|
|
for (idx, line) in view.cells.chunks(view.width as usize).enumerate() {
|
|
let start = ((pos.y() + idx as u16) * self.width + pos.x()) as usize;
|
|
let end = start + line.len();
|
|
self.cells.splice(start..end, line.iter().cloned());
|
|
}
|
|
}
|
|
|
|
pub fn render(&mut self, pos: Pos, output: &mut impl Write) -> Result<()> {
|
|
queue!(output, MoveTo(pos.x(), pos.y()))?;
|
|
for line in self.cells.chunks(self.width as usize) {
|
|
for cell in line {
|
|
cell.render(output)?;
|
|
}
|
|
queue!(output, MoveDown(1))?;
|
|
queue!(output, MoveToColumn(pos.x()))?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|