arkham/src/ui/view.rs

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(())
}
}