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 struct OverlayEntry {
20 pub id: u64,
21 pub view: Box<View>,
22}
23
24#[derive(Clone)]
25pub enum ViewKind {
26 Surface,
27 Box,
28 Row,
29 Column,
30 Stack,
31 OverlayHost,
32 ScrollV {
33 on_scroll: Option<ScrollCallback>,
34 set_viewport_height: Option<Rc<dyn Fn(f32)>>,
35 set_content_height: Option<Rc<dyn Fn(f32)>>,
36 get_scroll_offset: Option<Rc<dyn Fn() -> f32>>,
37 set_scroll_offset: Option<Rc<dyn Fn(f32)>>,
38 },
39 ScrollXY {
40 on_scroll: Option<ScrollCallback>,
41 set_viewport_width: Option<Rc<dyn Fn(f32)>>,
42 set_viewport_height: Option<Rc<dyn Fn(f32)>>,
43 set_content_width: Option<Rc<dyn Fn(f32)>>,
44 set_content_height: Option<Rc<dyn Fn(f32)>>,
45 get_scroll_offset_xy: Option<Rc<dyn Fn() -> (f32, f32)>>,
46 set_scroll_offset_xy: Option<Rc<dyn Fn(f32, f32)>>,
47 },
48 Text {
49 text: String,
50 color: Color,
51 font_size: f32,
52 soft_wrap: bool,
53 max_lines: Option<usize>,
54 overflow: TextOverflow,
55 },
56 Button {
57 on_click: Option<Callback>,
58 },
59 TextField {
60 state_key: ViewId,
61 hint: String,
62 multiline: bool,
63 on_change: Option<Rc<dyn Fn(String)>>,
64 on_submit: Option<Rc<dyn Fn(String)>>,
65 },
66 Checkbox {
67 checked: bool,
68 on_change: Option<Rc<dyn Fn(bool)>>,
69 },
70 RadioButton {
71 selected: bool,
72 on_select: Option<Callback>,
73 },
74 Switch {
75 checked: bool,
76 on_change: Option<Rc<dyn Fn(bool)>>,
77 },
78 Slider {
79 value: f32,
80 min: f32,
81 max: f32,
82 step: Option<f32>,
83 on_change: Option<CallbackF32>,
84 },
85 RangeSlider {
86 start: f32,
87 end: f32,
88 min: f32,
89 max: f32,
90 step: Option<f32>,
91 on_change: Option<CallbackRange>,
92 },
93 ProgressBar {
94 value: f32,
95 min: f32,
96 max: f32,
97 circular: bool,
98 },
99 Image {
100 handle: ImageHandle,
101 tint: Color, fit: ImageFit,
103 },
104 Ellipse {
105 rect: Rect,
106 color: Color,
107 },
108 EllipseBorder {
109 rect: Rect,
110 color: Color,
111 width: f32, },
113}
114
115impl std::fmt::Debug for ViewKind {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 match self {
118 ViewKind::Checkbox { checked, .. } => f
119 .debug_struct("Checkbox")
120 .field("checked", checked)
121 .finish(),
122 ViewKind::RadioButton { selected, .. } => f
123 .debug_struct("RadioButton")
124 .field("selected", selected)
125 .finish(),
126 ViewKind::Switch { checked, .. } => {
127 f.debug_struct("Switch").field("checked", checked).finish()
128 }
129 ViewKind::Slider { value, .. } => {
130 f.debug_struct("Slider").field("value", value).finish()
131 }
132 ViewKind::RangeSlider { start, end, .. } => f
133 .debug_struct("RangeSlider")
134 .field("start", start)
135 .field("end", end)
136 .finish(),
137 ViewKind::ProgressBar { value, .. } => {
138 f.debug_struct("ProgressBar").field("value", value).finish()
139 }
140 ViewKind::ScrollV { .. } => f.debug_struct("ScrollV").finish(),
141 ViewKind::ScrollXY { .. } => f.debug_struct("ScrollXY").finish(),
142 ViewKind::Text { text, .. } => f.debug_struct("Text").field("text", text).finish(),
143 ViewKind::Button { .. } => f.debug_struct("Button").finish(),
144 ViewKind::TextField { hint, .. } => {
145 f.debug_struct("TextField").field("hint", hint).finish()
146 }
147 ViewKind::Surface => f.debug_struct("Surface").finish(),
148 ViewKind::Box => f.debug_struct("Box").finish(),
149 ViewKind::Row => f.debug_struct("Row").finish(),
150 ViewKind::Column => f.debug_struct("Column").finish(),
151 ViewKind::Stack => f.debug_struct("Stack").finish(),
152 ViewKind::OverlayHost => f.debug_struct("OverlayHost").finish(),
153 ViewKind::Image { .. } => f.debug_struct("Image").finish(),
154 ViewKind::Ellipse { .. } => f.debug_struct("Ellipse").finish(),
155 ViewKind::EllipseBorder { .. } => f.debug_struct("EllipseBorder").finish(),
156 }
157 }
158}
159
160#[derive(Clone, Debug)]
161pub struct View {
162 pub id: ViewId,
163 pub kind: ViewKind,
164 pub modifier: Modifier,
165 pub children: Vec<View>,
166 pub semantics: Option<crate::semantics::Semantics>,
167}
168
169impl View {
170 pub fn new(id: ViewId, kind: ViewKind) -> Self {
171 View {
172 id,
173 kind,
174 modifier: Modifier::default(),
175 children: vec![],
176 semantics: None,
177 }
178 }
179 pub fn modifier(mut self, m: Modifier) -> Self {
180 self.modifier = m;
181 self
182 }
183 pub fn with_children(mut self, kids: Vec<View>) -> Self {
184 self.children = kids;
185 self
186 }
187 pub fn semantics(mut self, s: crate::semantics::Semantics) -> Self {
188 self.semantics = Some(s);
189 self
190 }
191}
192
193#[derive(Clone, Debug, Default)]
195pub struct Scene {
196 pub clear_color: Color,
197 pub nodes: Vec<SceneNode>,
198}
199
200#[derive(Clone, Debug)]
201pub enum SceneNode {
202 Rect {
203 rect: Rect,
204 brush: Brush,
205 radius: f32,
206 },
207 Border {
208 rect: Rect,
209 color: Color,
210 width: f32,
211 radius: f32,
212 },
213 Text {
214 rect: Rect,
215 text: Arc<str>,
216 color: Color,
217 size: f32,
218 },
219 Ellipse {
220 rect: Rect,
221 brush: Brush,
222 },
223 EllipseBorder {
224 rect: Rect,
225 color: Color,
226 width: f32, },
228 PushClip {
229 rect: Rect,
230 radius: f32,
231 },
232 PopClip,
233 PushTransform {
234 transform: Transform,
235 },
236 PopTransform,
237 Image {
238 rect: Rect,
239 handle: ImageHandle,
240 tint: Color,
241 fit: ImageFit,
242 },
243}
244
245pub type CallbackF32 = Rc<dyn Fn(f32)>;
246pub type CallbackRange = Rc<dyn Fn(f32, f32)>;
247
248#[derive(Clone, Copy, Debug, PartialEq, Eq)]
249pub enum TextOverflow {
250 Visible,
251 Clip,
252 Ellipsis,
253}