1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Deserialize, Serialize, Clone, Copy)]
9pub struct Color {
10 pub r: u8,
12 pub g: u8,
14 pub b: u8,
16 pub a: f32,
18}
19
20#[derive(Debug, Deserialize, Serialize, Clone)]
22pub struct Font {
23 pub name: String,
25 pub size: f32,
27 pub bold: bool,
29 pub italic: bool,
31 pub underline: bool,
33}
34
35#[derive(Debug, Deserialize, Serialize, Clone, Copy)]
37pub struct Padding {
38 pub top: f32,
40 pub right: f32,
42 pub bottom: f32,
44 pub left: f32,
46}
47
48#[derive(Debug, Deserialize, Serialize, Clone, Copy)]
50pub struct Border {
51 pub width: f32,
53 pub color: Color,
55 pub radius: f32,
57}
58
59#[derive(Debug, Deserialize, Serialize, Clone)]
61pub struct Style {
62 pub background: Option<Color>,
64 pub foreground: Option<Color>,
66 pub font: Option<Font>,
68 pub padding: Option<Padding>,
70 pub border: Option<Border>,
72 pub width: Option<f32>,
74 pub height: Option<f32>,
76 pub horizontal_align: Option<Alignment>,
78 pub vertical_align: Option<Alignment>,
80}
81
82#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
84pub enum Alignment {
85 Start,
87 Center,
89 End,
91}
92
93impl Color {
94 pub fn new(r: u8, g: u8, b: u8, a: f32) -> Self {
105 Self { r, g, b, a: a.clamp(0.0, 1.0) }
106 }
107
108 pub fn rgb(r: u8, g: u8, b: u8) -> Self {
118 Self::new(r, g, b, 1.0)
119 }
120
121 pub fn rgba(r: u8, g: u8, b: u8, a: f32) -> Self {
132 Self::new(r, g, b, a)
133 }
134
135 pub const BLACK: Self = Self { r: 0, g: 0, b: 0, a: 1.0 };
137
138 pub const WHITE: Self = Self { r: 255, g: 255, b: 255, a: 1.0 };
140
141 pub const RED: Self = Self { r: 255, g: 0, b: 0, a: 1.0 };
143
144 pub const GREEN: Self = Self { r: 0, g: 255, b: 0, a: 1.0 };
146
147 pub const BLUE: Self = Self { r: 0, g: 0, b: 255, a: 1.0 };
149
150 pub const YELLOW: Self = Self { r: 255, g: 255, b: 0, a: 1.0 };
152
153 pub const CYAN: Self = Self { r: 0, g: 255, b: 255, a: 1.0 };
155
156 pub const MAGENTA: Self = Self { r: 255, g: 0, b: 255, a: 1.0 };
158
159 pub const GRAY: Self = Self { r: 128, g: 128, b: 128, a: 1.0 };
161
162 pub const LIGHT_GRAY: Self = Self { r: 200, g: 200, b: 200, a: 1.0 };
164
165 pub const DARK_GRAY: Self = Self { r: 64, g: 64, b: 64, a: 1.0 };
167}
168
169impl Font {
170 pub fn new(name: &str, size: f32, bold: bool, italic: bool, underline: bool) -> Self {
182 Self { name: name.to_string(), size: size.max(1.0), bold, italic, underline }
183 }
184
185 pub fn default() -> Self {
190 Self::new("Arial", 14.0, false, false, false)
191 }
192}
193
194impl Padding {
195 pub fn new(top: f32, right: f32, bottom: f32, left: f32) -> Self {
206 Self { top: top.max(0.0), right: right.max(0.0), bottom: bottom.max(0.0), left: left.max(0.0) }
207 }
208
209 pub fn symmetric(vertical: f32, horizontal: f32) -> Self {
218 Self::new(vertical, horizontal, vertical, horizontal)
219 }
220
221 pub fn uniform(all: f32) -> Self {
229 Self::new(all, all, all, all)
230 }
231
232 pub const DEFAULT: Self = Self { top: 8.0, right: 8.0, bottom: 8.0, left: 8.0 };
234}
235
236impl Border {
237 pub fn new(width: f32, color: Color, radius: f32) -> Self {
247 Self { width: width.max(0.0), color, radius: radius.max(0.0) }
248 }
249
250 pub fn default() -> Self {
255 Self::new(1.0, Color::GRAY, 0.0)
256 }
257}
258
259impl Style {
260 pub fn new() -> Self {
265 Self {
266 background: None,
267 foreground: None,
268 font: None,
269 padding: None,
270 border: None,
271 width: None,
272 height: None,
273 horizontal_align: None,
274 vertical_align: None,
275 }
276 }
277
278 pub fn with_background(mut self, color: Color) -> Self {
286 self.background = Some(color);
287 self
288 }
289
290 pub fn with_foreground(mut self, color: Color) -> Self {
298 self.foreground = Some(color);
299 self
300 }
301
302 pub fn with_font(mut self, font: Font) -> Self {
310 self.font = Some(font);
311 self
312 }
313
314 pub fn with_padding(mut self, padding: Padding) -> Self {
322 self.padding = Some(padding);
323 self
324 }
325
326 pub fn with_border(mut self, border: Border) -> Self {
334 self.border = Some(border);
335 self
336 }
337
338 pub fn with_width(mut self, width: f32) -> Self {
346 self.width = Some(width.max(0.0));
347 self
348 }
349
350 pub fn with_height(mut self, height: f32) -> Self {
358 self.height = Some(height.max(0.0));
359 self
360 }
361
362 pub fn with_horizontal_align(mut self, align: Alignment) -> Self {
370 self.horizontal_align = Some(align);
371 self
372 }
373
374 pub fn with_vertical_align(mut self, align: Alignment) -> Self {
382 self.vertical_align = Some(align);
383 self
384 }
385
386 pub fn default() -> Self {
388 Self::new()
389 }
390}