1use crate::attr::Attr;
3use crate::cell::Cell;
4use crate::Result;
5use unicode_width::UnicodeWidthChar;
6
7pub trait Canvas {
8 fn size(&self) -> Result<(usize, usize)>;
10
11 fn clear(&mut self) -> Result<()>;
13
14 fn put_cell(&mut self, row: usize, col: usize, cell: Cell) -> Result<usize>;
18
19 fn put_char_with_attr(
22 &mut self,
23 row: usize,
24 col: usize,
25 ch: char,
26 attr: Attr,
27 ) -> Result<usize> {
28 self.put_cell(row, col, Cell { ch, attr })
29 }
30
31 fn print_with_attr(
36 &mut self,
37 row: usize,
38 col: usize,
39 content: &str,
40 attr: Attr,
41 ) -> Result<usize> {
42 let mut cell = Cell {
43 attr,
44 ..Cell::default()
45 };
46
47 let mut width = 0;
48 for ch in content.chars() {
49 cell.ch = ch;
50 width += self.put_cell(row, col + width, cell)?;
51 }
52 Ok(width)
53 }
54
55 fn print(&mut self, row: usize, col: usize, content: &str) -> Result<usize> {
57 self.print_with_attr(row, col, content, Attr::default())
58 }
59
60 fn set_cursor(&mut self, row: usize, col: usize) -> Result<()>;
62
63 fn show_cursor(&mut self, show: bool) -> Result<()>;
65}
66
67pub struct BoundedCanvas<'a> {
71 canvas: &'a mut dyn Canvas,
72 top: usize,
73 left: usize,
74 width: usize,
75 height: usize,
76}
77
78impl<'a> BoundedCanvas<'a> {
79 pub fn new(
80 top: usize,
81 left: usize,
82 width: usize,
83 height: usize,
84 canvas: &'a mut dyn Canvas,
85 ) -> Self {
86 Self {
87 canvas,
88 top,
89 left,
90 width,
91 height,
92 }
93 }
94}
95
96impl<'a> Canvas for BoundedCanvas<'a> {
97 fn size(&self) -> Result<(usize, usize)> {
98 Ok((self.width, self.height))
99 }
100
101 fn clear(&mut self) -> Result<()> {
102 for row in self.top..(self.top + self.height) {
103 for col in self.left..(self.left + self.width) {
104 let _ = self.canvas.put_cell(row, col, Cell::empty());
105 }
106 }
107
108 Ok(())
109 }
110
111 fn put_cell(&mut self, row: usize, col: usize, cell: Cell) -> Result<usize> {
112 if row >= self.height || col >= self.width {
113 Ok(cell.ch.width().unwrap_or(2))
115 } else {
116 self.canvas.put_cell(row + self.top, col + self.left, cell)
117 }
118 }
119
120 fn set_cursor(&mut self, row: usize, col: usize) -> Result<()> {
121 if row >= self.height || col >= self.width {
122 Ok(())
124 } else {
125 self.canvas.set_cursor(row + self.top, col + self.left)
126 }
127 }
128
129 fn show_cursor(&mut self, show: bool) -> Result<()> {
130 self.canvas.show_cursor(show)
131 }
132}