use std::{
cell::{Ref, RefCell},
rc::Rc,
};
use crate::{
cell::Cell,
drawable::Drawable,
layout::{
sized::{KnownHeight, KnownWidth},
Dims, Pos,
},
};
pub struct Buffer {
buffer: Vec<Vec<Cell>>,
size: Dims,
}
impl Buffer {
pub fn new(size: impl Into<Dims>) -> Self {
let size = size.into();
let mut buffer = Vec::new();
for _ in 0..size.y {
buffer.push(vec![Cell::new(' '); size.x as usize]);
}
Buffer { buffer, size }
}
pub fn buf_ref(&self) -> &[Vec<Cell>] {
&self.buffer
}
pub fn buf_mut(&mut self) -> &mut [Vec<Cell>] {
&mut self.buffer
}
pub fn resize(&mut self, size: impl Into<Dims>) {
let size = size.into();
if self.size == size {
return;
}
self.size = size;
self.buffer.resize(size.y as usize, Vec::new());
for row in self.buffer.iter_mut() {
row.resize(size.x as usize, Cell::new(' '));
}
}
pub fn size(&self) -> Dims {
self.size
}
}
pub trait CanvasLike: KnownWidth + KnownHeight {
fn set(&mut self, pos: Dims, cell: Cell);
fn pos(&self) -> Dims;
fn size(&self) -> Dims;
fn setd(&mut self, pos: impl Into<Dims>, cell: Cell)
where
Self: Sized,
{
self.set(pos.into(), cell);
}
fn fill(&mut self, cell: Cell) {
let size = self.size();
for y in 0..size.y {
for x in 0..size.x {
self.set(Pos::new(x, y), cell);
}
}
}
}
#[derive(Clone)]
pub struct Canvas {
pub buffer: Rc<RefCell<Buffer>>,
}
impl Canvas {
pub fn new(buf: Buffer) -> Self {
Self {
buffer: Rc::new(RefCell::new(buf)),
}
}
pub fn from_dims(size: impl Into<Dims>) -> Self {
Self::new(Buffer::new(size))
}
pub fn set(&mut self, pos: impl Into<Dims>, cell: Cell) {
let pos = pos.into();
if let Some(c) = self
.buffer
.borrow_mut() .buf_mut() .get_mut(pos.y as usize) .and_then(|r| r.get_mut(pos.x as usize))
{
*c = cell;
}
}
pub fn size(&self) -> Dims {
self.buffer.borrow().size()
}
pub fn get(&self, pos: impl Into<Dims>) -> Option<Cell> {
let pos = pos.into();
self.buffer
.borrow() .buf_ref() .get(pos.y as usize) .and_then(|r| r.get(pos.x as usize))
.copied()
}
pub fn get_buf(&self) -> Ref<Buffer> {
self.buffer.borrow()
}
pub fn resize(&mut self, size: impl Into<Dims>) {
self.buffer.borrow_mut().resize(size);
}
pub fn clear(&mut self) {
for row in self.buffer.borrow_mut().buf_mut().iter_mut() {
for cell in row.iter_mut() {
*cell = Cell::new(' ');
}
}
}
}
impl CanvasLike for Canvas {
fn set(&mut self, pos: Dims, cell: Cell) {
Canvas::set(self, pos, cell); }
fn pos(&self) -> Dims {
(0, 0).into()
}
fn size(&self) -> Dims {
self.size()
}
}
impl<T> CanvasLike for &mut T
where
T: CanvasLike,
{
fn set(&mut self, pos: Dims, cell: Cell) {
(**self).set(pos, cell);
}
fn pos(&self) -> Dims {
(**self).pos()
}
fn size(&self) -> Dims {
(**self).size()
}
}
pub trait CanvasLikeExt: CanvasLike {
fn show<D>(&mut self, pos: impl Into<Pos<D::X, D::Y>>, content: &D)
where
D: Drawable;
}
impl<C> CanvasLikeExt for C
where
C: CanvasLike,
{
#[inline]
fn show<D>(&mut self, pos: impl Into<Pos<D::X, D::Y>>, content: &D)
where
D: Drawable,
{
content.draw(pos, self);
}
}