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