1pub trait Widget {
5 fn measure(&self, constraints: &Constraints) -> Size;
7
8 fn layout(&mut self, size: Size);
10
11 fn paint(&self, canvas: &mut dyn Canvas);
13}
14
15#[derive(Debug, Clone, Copy, Default, PartialEq)]
17pub struct Size {
18 pub width: f32,
19 pub height: f32,
20}
21
22impl Size {
23 pub const fn new(width: f32, height: f32) -> Self {
24 Self { width, height }
25 }
26
27 pub const ZERO: Self = Self {
28 width: 0.0,
29 height: 0.0,
30 };
31}
32
33#[derive(Debug, Clone, Copy, Default, PartialEq)]
35pub struct Point {
36 pub x: f32,
37 pub y: f32,
38}
39
40impl Point {
41 pub const fn new(x: f32, y: f32) -> Self {
42 Self { x, y }
43 }
44
45 pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
46}
47
48#[derive(Debug, Clone, Copy, Default, PartialEq)]
50pub struct Rect {
51 pub x: f32,
52 pub y: f32,
53 pub width: f32,
54 pub height: f32,
55}
56
57impl Rect {
58 pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
59 Self {
60 x,
61 y,
62 width,
63 height,
64 }
65 }
66
67 pub fn from_size(size: Size) -> Self {
68 Self {
69 x: 0.0,
70 y: 0.0,
71 width: size.width,
72 height: size.height,
73 }
74 }
75
76 pub fn size(&self) -> Size {
77 Size::new(self.width, self.height)
78 }
79
80 pub fn top_left(&self) -> Point {
81 Point::new(self.x, self.y)
82 }
83}
84
85#[derive(Debug, Clone, Copy)]
87pub struct Constraints {
88 pub min_width: f32,
89 pub max_width: f32,
90 pub min_height: f32,
91 pub max_height: f32,
92}
93
94impl Constraints {
95 pub const fn new(min_width: f32, max_width: f32, min_height: f32, max_height: f32) -> Self {
96 Self {
97 min_width,
98 max_width,
99 min_height,
100 max_height,
101 }
102 }
103
104 pub fn tight(size: Size) -> Self {
105 Self {
106 min_width: size.width,
107 max_width: size.width,
108 min_height: size.height,
109 max_height: size.height,
110 }
111 }
112
113 pub fn loose(size: Size) -> Self {
114 Self {
115 min_width: 0.0,
116 max_width: size.width,
117 min_height: 0.0,
118 max_height: size.height,
119 }
120 }
121
122 pub fn constrain(&self, size: Size) -> Size {
123 Size {
124 width: size.width.clamp(self.min_width, self.max_width),
125 height: size.height.clamp(self.min_height, self.max_height),
126 }
127 }
128}
129
130impl Default for Constraints {
131 fn default() -> Self {
132 Self {
133 min_width: 0.0,
134 max_width: f32::INFINITY,
135 min_height: 0.0,
136 max_height: f32::INFINITY,
137 }
138 }
139}
140
141#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
143pub struct Color {
144 pub r: u8,
145 pub g: u8,
146 pub b: u8,
147}
148
149impl Color {
150 pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
151 Self { r, g, b }
152 }
153
154 pub const BLACK: Self = Self::rgb(0, 0, 0);
156 pub const WHITE: Self = Self::rgb(255, 255, 255);
157 pub const RED: Self = Self::rgb(255, 0, 0);
158 pub const GREEN: Self = Self::rgb(0, 255, 0);
159 pub const BLUE: Self = Self::rgb(0, 0, 255);
160 pub const YELLOW: Self = Self::rgb(255, 255, 0);
161 pub const CYAN: Self = Self::rgb(0, 255, 255);
162 pub const MAGENTA: Self = Self::rgb(255, 0, 255);
163 pub const GRAY: Self = Self::rgb(128, 128, 128);
164 pub const DARK_GRAY: Self = Self::rgb(64, 64, 64);
165 pub const LIGHT_GRAY: Self = Self::rgb(192, 192, 192);
166
167 pub const ANDON_GREEN: Self = Self::rgb(0, 200, 0);
169 pub const ANDON_YELLOW: Self = Self::rgb(255, 200, 0);
170 pub const ANDON_RED: Self = Self::rgb(255, 50, 50);
171}
172
173#[derive(Debug, Clone, Copy, Default)]
175pub struct TextStyle {
176 pub color: Color,
177 pub background: Option<Color>,
178 pub bold: bool,
179 pub italic: bool,
180 pub underline: bool,
181}
182
183impl TextStyle {
184 pub const fn new() -> Self {
185 Self {
186 color: Color::WHITE,
187 background: None,
188 bold: false,
189 italic: false,
190 underline: false,
191 }
192 }
193
194 pub const fn color(mut self, color: Color) -> Self {
195 self.color = color;
196 self
197 }
198
199 pub const fn background(mut self, color: Color) -> Self {
200 self.background = Some(color);
201 self
202 }
203
204 pub const fn bold(mut self) -> Self {
205 self.bold = true;
206 self
207 }
208}
209
210pub trait Canvas {
212 fn fill_rect(&mut self, rect: Rect, color: Color);
214
215 fn stroke_rect(&mut self, rect: Rect, color: Color, width: f32);
217
218 fn draw_text(&mut self, text: &str, pos: Point, style: &TextStyle);
220
221 fn draw_line(&mut self, from: Point, to: Point, color: Color, width: f32);
223
224 fn fill_circle(&mut self, center: Point, radius: f32, color: Color);
226
227 fn stroke_circle(&mut self, center: Point, radius: f32, color: Color, width: f32);
229
230 fn draw_path(&mut self, points: &[Point], color: Color, width: f32);
232
233 fn size(&self) -> Size;
235
236 fn clear(&mut self, color: Color);
238}