1use crate::{Style, Text};
2
3#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
4pub struct Cell {
5 content: Text,
6 style: Style,
7 column_span: u16,
8}
9
10impl Cell {
11 pub fn new<T>(content: T) -> Self
12 where
13 T: Into<Text>,
14 {
15 Self {
16 content: content.into(),
17 style: Style::default(),
18 column_span: 1,
19 }
20 }
21
22 pub fn content<T>(mut self, content: T) -> Self
23 where
24 T: Into<Text>,
25 {
26 self.content = content.into();
27 self
28 }
29
30 pub const fn column_span(mut self, column_span: u16) -> Self {
31 self.column_span = column_span;
32 self
33 }
34
35 pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
36 self.style = style.into();
37 self
38 }
39
40 pub fn text(&self) -> &Text {
41 &self.content
42 }
43
44 pub const fn style_value(&self) -> Style {
45 self.style
46 }
47
48 pub const fn column_span_value(&self) -> u16 {
49 self.column_span
50 }
51
52 pub fn width(&self) -> usize {
53 self.content.width()
54 }
55
56 pub fn height(&self) -> usize {
57 self.content.height()
58 }
59}
60
61impl<T> From<T> for Cell
62where
63 T: Into<Text>,
64{
65 fn from(value: T) -> Self {
66 Self::new(value)
67 }
68}
69
70#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
71pub struct Row {
72 cells: Vec<Cell>,
73 height: u16,
74 top_margin: u16,
75 bottom_margin: u16,
76 style: Style,
77}
78
79impl Row {
80 pub fn new<T>(cells: T) -> Self
81 where
82 T: IntoIterator,
83 T::Item: Into<Cell>,
84 {
85 let cells: Vec<Cell> = cells.into_iter().map(Into::into).collect();
86 let height = cells
87 .iter()
88 .map(|cell| cell.height() as u16)
89 .max()
90 .unwrap_or(1)
91 .max(1);
92 Self {
93 cells,
94 height,
95 top_margin: 0,
96 bottom_margin: 0,
97 style: Style::default(),
98 }
99 }
100
101 pub fn cells<T>(mut self, cells: T) -> Self
102 where
103 T: IntoIterator,
104 T::Item: Into<Cell>,
105 {
106 self.cells = cells.into_iter().map(Into::into).collect();
107 self.height = self
108 .cells
109 .iter()
110 .map(|cell| cell.height() as u16)
111 .max()
112 .unwrap_or(1)
113 .max(1);
114 self
115 }
116
117 pub const fn height(mut self, height: u16) -> Self {
118 self.height = height;
119 self
120 }
121
122 pub const fn top_margin(mut self, margin: u16) -> Self {
123 self.top_margin = margin;
124 self
125 }
126
127 pub const fn bottom_margin(mut self, margin: u16) -> Self {
128 self.bottom_margin = margin;
129 self
130 }
131
132 pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
133 self.style = style.into();
134 self
135 }
136
137 pub fn cells_ref(&self) -> &[Cell] {
138 &self.cells
139 }
140
141 pub const fn height_value(&self) -> u16 {
142 self.height
143 }
144
145 pub const fn top_margin_value(&self) -> u16 {
146 self.top_margin
147 }
148
149 pub const fn bottom_margin_value(&self) -> u16 {
150 self.bottom_margin
151 }
152
153 pub const fn style_value(&self) -> Style {
154 self.style
155 }
156
157 pub const fn height_with_margin(&self) -> u16 {
158 self.height
159 .saturating_add(self.top_margin)
160 .saturating_add(self.bottom_margin)
161 }
162
163 pub fn column_count(&self) -> usize {
164 self.cells
165 .iter()
166 .map(|cell| cell.column_span.max(1) as usize)
167 .sum()
168 }
169}
170
171impl<T> From<T> for Row
172where
173 T: IntoIterator,
174 T::Item: Into<Cell>,
175{
176 fn from(value: T) -> Self {
177 Self::new(value)
178 }
179}
180
181impl<Item> FromIterator<Item> for Row
182where
183 Item: Into<Cell>,
184{
185 fn from_iter<Iter: IntoIterator<Item = Item>>(iter: Iter) -> Self {
186 Self::new(iter)
187 }
188}