1use crate::{Brush, Color, Modifier, Rect, Transform};
2use std::{rc::Rc, sync::Arc};
3
4pub type ViewId = u64;
5
6pub type ImageHandle = u64;
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum ImageFit {
9 Contain,
10 Cover,
11 FitWidth,
12 FitHeight,
13}
14
15pub type Callback = Rc<dyn Fn()>;
16pub type ScrollCallback = Rc<dyn Fn(crate::Vec2) -> crate::Vec2>;
17
18#[derive(Clone)]
19pub enum ViewKind {
20 Surface,
21 Box,
22 Row,
23 Column,
24 Stack,
25 ScrollV {
26 on_scroll: Option<ScrollCallback>,
27 set_viewport_height: Option<Rc<dyn Fn(f32)>>,
28 set_content_height: Option<Rc<dyn Fn(f32)>>,
29 get_scroll_offset: Option<Rc<dyn Fn() -> f32>>,
30 set_scroll_offset: Option<Rc<dyn Fn(f32)>>,
31 },
32 ScrollXY {
33 on_scroll: Option<ScrollCallback>,
34 set_viewport_width: Option<Rc<dyn Fn(f32)>>,
35 set_viewport_height: Option<Rc<dyn Fn(f32)>>,
36 set_content_width: Option<Rc<dyn Fn(f32)>>,
37 set_content_height: Option<Rc<dyn Fn(f32)>>,
38 get_scroll_offset_xy: Option<Rc<dyn Fn() -> (f32, f32)>>,
39 set_scroll_offset_xy: Option<Rc<dyn Fn(f32, f32)>>,
40 },
41 Text {
42 text: String,
43 color: Color,
44 font_size: f32,
45 soft_wrap: bool,
46 max_lines: Option<usize>,
47 overflow: TextOverflow,
48 },
49 Button {
50 on_click: Option<Callback>,
51 },
52 TextField {
53 state_key: ViewId,
54 hint: String,
55 multiline: bool,
56 on_change: Option<Rc<dyn Fn(String)>>,
57 on_submit: Option<Rc<dyn Fn(String)>>,
58 },
59 Checkbox {
60 checked: bool,
61 on_change: Option<Rc<dyn Fn(bool)>>,
62 },
63 RadioButton {
64 selected: bool,
65 on_select: Option<Callback>,
66 },
67 Switch {
68 checked: bool,
69 on_change: Option<Rc<dyn Fn(bool)>>,
70 },
71 Slider {
72 value: f32,
73 min: f32,
74 max: f32,
75 step: Option<f32>,
76 on_change: Option<CallbackF32>,
77 },
78 RangeSlider {
79 start: f32,
80 end: f32,
81 min: f32,
82 max: f32,
83 step: Option<f32>,
84 on_change: Option<CallbackRange>,
85 },
86 ProgressBar {
87 value: f32,
88 min: f32,
89 max: f32,
90 circular: bool,
91 },
92 Image {
93 handle: ImageHandle,
94 tint: Color, fit: ImageFit,
96 },
97 Ellipse {
98 rect: Rect,
99 color: Color,
100 },
101 EllipseBorder {
102 rect: Rect,
103 color: Color,
104 width: f32, },
106}
107
108impl std::fmt::Debug for ViewKind {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 match self {
111 ViewKind::Checkbox { checked, .. } => f
112 .debug_struct("Checkbox")
113 .field("checked", checked)
114 .finish(),
115 ViewKind::RadioButton { selected, .. } => f
116 .debug_struct("RadioButton")
117 .field("selected", selected)
118 .finish(),
119 ViewKind::Switch { checked, .. } => {
120 f.debug_struct("Switch").field("checked", checked).finish()
121 }
122 ViewKind::Surface => write!(f, "Surface"),
123 ViewKind::Box => write!(f, "Box"),
124 ViewKind::Row => write!(f, "Row"),
125 ViewKind::Column => write!(f, "Column"),
126 ViewKind::Stack => write!(f, "Stack"),
127 ViewKind::ScrollV { .. } => write!(f, "ScrollV"),
128 ViewKind::ScrollXY { .. } => write!(f, "ScrollXY"),
129 ViewKind::Text {
130 text,
131 color,
132 font_size,
133 soft_wrap,
134 max_lines,
135 overflow,
136 } => f
137 .debug_struct("Text")
138 .field("text", text)
139 .field("color", color)
140 .field("font_size", font_size)
141 .field("soft_wrap", soft_wrap)
142 .field("max_lines", max_lines)
143 .field("overflow", overflow)
144 .finish(),
145 ViewKind::Image { handle, tint, fit } => f
146 .debug_struct("Image")
147 .field("handle", handle)
148 .field("tint", tint)
149 .field("fit", fit)
150 .finish(),
151 ViewKind::Button { .. } => f
152 .debug_struct("Button")
153 .field("on_click", &"<callback>")
154 .finish(),
155 ViewKind::TextField {
156 state_key,
157 hint,
158 multiline,
159 on_change,
160 on_submit,
161 } => f
162 .debug_struct("TextField")
163 .field("state_key", state_key)
164 .field("hint", hint)
165 .field("multiline", multiline)
166 .finish(),
167 ViewKind::Slider {
168 value,
169 min,
170 max,
171 step,
172 ..
173 } => f
174 .debug_struct("Slider")
175 .field("value", value)
176 .field("min", min)
177 .field("max", max)
178 .field("step", step)
179 .finish(),
180 ViewKind::RangeSlider {
181 start,
182 end,
183 min,
184 max,
185 step,
186 ..
187 } => f
188 .debug_struct("RangeSlider")
189 .field("start", start)
190 .field("end", end)
191 .field("min", min)
192 .field("max", max)
193 .field("step", step)
194 .finish(),
195 ViewKind::ProgressBar {
196 value,
197 min,
198 max,
199 circular,
200 } => f
201 .debug_struct("ProgressBar")
202 .field("value", value)
203 .field("min", min)
204 .field("max", max)
205 .field("circular", circular)
206 .finish(),
207 ViewKind::Ellipse { rect, color } => f
208 .debug_struct("Ellipse")
209 .field("rect", rect)
210 .field("color", color)
211 .finish(),
212 ViewKind::EllipseBorder { rect, color, width } => f
213 .debug_struct("EllipseBorder")
214 .field("rect", rect)
215 .field("color", color)
216 .field("width", width)
217 .finish(),
218 }
219 }
220}
221
222#[derive(Clone, Debug)]
223pub struct View {
224 pub id: ViewId,
225 pub kind: ViewKind,
226 pub modifier: Modifier,
227 pub children: Vec<View>,
228 pub semantics: Option<crate::semantics::Semantics>,
229}
230
231impl View {
232 pub fn new(id: ViewId, kind: ViewKind) -> Self {
233 View {
234 id,
235 kind,
236 modifier: Modifier::default(),
237 children: vec![],
238 semantics: None,
239 }
240 }
241 pub fn modifier(mut self, m: Modifier) -> Self {
242 self.modifier = m;
243 self
244 }
245 pub fn with_children(mut self, kids: Vec<View>) -> Self {
246 self.children = kids;
247 self
248 }
249 pub fn semantics(mut self, s: crate::semantics::Semantics) -> Self {
250 self.semantics = Some(s);
251 self
252 }
253}
254
255#[derive(Clone, Debug, Default)]
257pub struct Scene {
258 pub clear_color: Color,
259 pub nodes: Vec<SceneNode>,
260}
261
262#[derive(Clone, Debug)]
263pub enum SceneNode {
264 Rect {
265 rect: Rect,
266 brush: Brush,
267 radius: f32,
268 },
269 Border {
270 rect: Rect,
271 color: Color,
272 width: f32,
273 radius: f32,
274 },
275 Text {
276 rect: Rect,
277 text: Arc<str>,
278 color: Color,
279 size: f32,
280 },
281 Ellipse {
282 rect: Rect,
283 brush: Brush,
284 },
285 EllipseBorder {
286 rect: Rect,
287 color: Color,
288 width: f32, },
290 PushClip {
291 rect: Rect,
292 radius: f32,
293 },
294 PopClip,
295 PushTransform {
296 transform: Transform,
297 },
298 PopTransform,
299 Image {
300 rect: Rect,
301 handle: ImageHandle,
302 tint: Color,
303 fit: ImageFit,
304 },
305}
306
307pub type CallbackF32 = Rc<dyn Fn(f32)>;
308pub type CallbackRange = Rc<dyn Fn(f32, f32)>;
309
310#[derive(Clone, Copy, Debug, PartialEq, Eq)]
311pub enum TextOverflow {
312 Visible,
313 Clip,
314 Ellipsis,
315}