1use std::{
2 cell::{Ref, RefCell},
3 rc::Rc,
4};
5
6use crate::{
7 cell::Cell,
8 drawable::Drawable,
9 layout::{
10 sized::{KnownHeight, KnownWidth},
11 Dims, Pos,
12 },
13};
14
15pub struct Buffer {
16 buffer: Vec<Vec<Cell>>,
17 size: Dims,
18}
19
20impl Buffer {
21 pub fn new(size: impl Into<Dims>) -> Self {
22 let size = size.into();
23 let mut buffer = Vec::new();
24 for _ in 0..size.y {
25 buffer.push(vec![Cell::new(' '); size.x as usize]);
26 }
27 Buffer { buffer, size }
28 }
29
30 pub fn buf_ref(&self) -> &[Vec<Cell>] {
31 &self.buffer
32 }
33
34 pub fn buf_mut(&mut self) -> &mut [Vec<Cell>] {
35 &mut self.buffer
36 }
37
38 pub fn resize(&mut self, size: impl Into<Dims>) {
39 let size = size.into();
40 if self.size == size {
41 return;
42 }
43
44 self.size = size;
45 self.buffer.resize(size.y as usize, Vec::new());
46 for row in self.buffer.iter_mut() {
47 row.resize(size.x as usize, Cell::new(' '));
48 }
49 }
50
51 pub fn size(&self) -> Dims {
52 self.size
53 }
54}
55
56pub trait CanvasLike: KnownWidth + KnownHeight {
57 fn set(&mut self, pos: Dims, cell: Cell);
58 fn pos(&self) -> Dims;
59 fn size(&self) -> Dims;
60
61 fn setd(&mut self, pos: impl Into<Dims>, cell: Cell)
64 where
65 Self: Sized,
66 {
67 self.set(pos.into(), cell);
68 }
69
70 fn fill(&mut self, cell: Cell) {
71 let size = self.size();
72 for y in 0..size.y {
73 for x in 0..size.x {
74 self.set(Pos::new(x, y), cell);
75 }
76 }
77 }
78}
79
80#[derive(Clone)]
81pub struct Canvas {
82 pub buffer: Rc<RefCell<Buffer>>,
83}
84
85impl Canvas {
86 pub fn new(buf: Buffer) -> Self {
87 Self {
88 buffer: Rc::new(RefCell::new(buf)),
89 }
90 }
91
92 pub fn from_dims(size: impl Into<Dims>) -> Self {
93 Self::new(Buffer::new(size))
94 }
95
96 pub fn set(&mut self, pos: impl Into<Dims>, cell: Cell) {
97 let pos = pos.into();
98 if let Some(c) = self
99 .buffer
100 .borrow_mut() .buf_mut() .get_mut(pos.y as usize) .and_then(|r| r.get_mut(pos.x as usize))
104 {
105 *c = cell;
106 }
107 }
108
109 pub fn size(&self) -> Dims {
110 self.buffer.borrow().size()
111 }
112
113 pub fn get(&self, pos: impl Into<Dims>) -> Option<Cell> {
114 let pos = pos.into();
115 self.buffer
116 .borrow() .buf_ref() .get(pos.y as usize) .and_then(|r| r.get(pos.x as usize))
120 .copied()
121 }
122
123 pub fn get_buf(&self) -> Ref<Buffer> {
124 self.buffer.borrow()
125 }
126
127 pub fn resize(&mut self, size: impl Into<Dims>) {
128 self.buffer.borrow_mut().resize(size);
129 }
130
131 pub fn clear(&mut self) {
132 for row in self.buffer.borrow_mut().buf_mut().iter_mut() {
133 for cell in row.iter_mut() {
134 *cell = Cell::new(' ');
135 }
136 }
137 }
138}
139
140impl CanvasLike for Canvas {
141 fn set(&mut self, pos: Dims, cell: Cell) {
142 Canvas::set(self, pos, cell); }
144 fn pos(&self) -> Dims {
145 (0, 0).into()
146 }
147
148 fn size(&self) -> Dims {
149 self.size()
150 }
151}
152
153impl<T> CanvasLike for &mut T
154where
155 T: CanvasLike,
156{
157 fn set(&mut self, pos: Dims, cell: Cell) {
158 (**self).set(pos, cell);
159 }
160
161 fn pos(&self) -> Dims {
162 (**self).pos()
163 }
164
165 fn size(&self) -> Dims {
166 (**self).size()
167 }
168}
169
170pub trait CanvasLikeExt: CanvasLike {
171 fn show<D>(&mut self, pos: impl Into<Pos<D::X, D::Y>>, content: &D)
172 where
173 D: Drawable;
174}
175
176impl<C> CanvasLikeExt for C
177where
178 C: CanvasLike,
179{
180 #[inline]
181 fn show<D>(&mut self, pos: impl Into<Pos<D::X, D::Y>>, content: &D)
182 where
183 D: Drawable,
184 {
185 content.draw(pos, self);
186 }
187}