1use super::*;
2
3pub trait DeclarativeView {
7 fn compile(
8 self,
9 scope: &UiScope,
10 context: &UiRenderContext,
11 component_id: ComponentId,
12 force_components: bool,
13 ) -> UiElement;
14}
15
16pub trait IntoElementContent {
17 fn append_to(self, children: &mut Vec<Element>);
18}
19
20pub struct Fragment {
21 pub(super) children: Vec<Element>,
22}
23
24pub struct Element {
25 pub(super) key: ElementKey,
26 render: Box<dyn FnOnce(ElementRenderCx<'_, '_, '_>) -> UiElement>,
27 interaction: Option<InteractionRole>,
28 semantics: Option<Semantics>,
29 pub(super) click_capture_handler: Option<UiEventHandler>,
30 pub(super) click_handler: Option<UiEventHandler>,
31 pub(super) input_event_handlers: Vec<UiInputEventBinding>,
32 pub(super) event_policy: Option<EventPolicy>,
33 phase: Option<RenderPhase>,
34 animations: Vec<AnimationBinding>,
35 animation_targets: Vec<(AnimProperty, bool)>,
36 paint_bounds: Option<UiRect>,
37 shadow: Option<crate::core::ShadowStyle>,
38 focus_scope: bool,
39 defer_children: bool,
40 children: Vec<Element>,
41}
42
43#[derive(Clone, Copy)]
44pub struct ElementKey {
45 file: &'static str,
46 line: u32,
47 column: u32,
48 explicit: Option<u64>,
49}
50
51pub struct ElementRenderCx<'a, 'ctx, 'scope> {
52 pub id: UiId,
53 pub scope: &'scope UiScope,
54 pub context: &'ctx UiRenderContext<'a>,
55 pub children: Vec<UiElement>,
56 pub(super) component_id: ComponentId,
57 pub(super) force_components: bool,
58 deferred_children: Option<Vec<Element>>,
59 id_counter: Cell<u32>,
60}
61
62impl ElementRenderCx<'_, '_, '_> {
63 pub fn auto_id(&self) -> UiId {
66 let n = self.id_counter.get();
67 self.id_counter.set(n + 1);
68 self.scope.id(format!("{}._{}", self.id.as_str(), n))
69 }
70
71 pub fn use_context<T>(&self) -> T
72 where
73 T: Clone + 'static,
74 {
75 self.try_use_context::<T>().unwrap_or_else(|| {
76 panic!(
77 "missing context value `{}` for element `{}`",
78 type_name::<T>(),
79 self.id.as_str()
80 )
81 })
82 }
83
84 pub fn try_use_context<T>(&self) -> Option<T>
85 where
86 T: Clone + 'static,
87 {
88 self.context.contexts().read(self.component_id)
89 }
90
91 #[doc(hidden)]
92 pub fn component_owner(&self) -> (ComponentId, bool) {
93 (self.component_id, self.force_components)
94 }
95}
96
97impl Element {
98 #[track_caller]
99 pub fn new(render: impl FnOnce(ElementRenderCx<'_, '_, '_>) -> UiElement + 'static) -> Self {
100 Self::with_key(ElementKey::caller(), render)
101 }
102
103 pub fn with_key(
104 key: ElementKey,
105 render: impl FnOnce(ElementRenderCx<'_, '_, '_>) -> UiElement + 'static,
106 ) -> Self {
107 Self {
108 key,
109 render: Box::new(render),
110 interaction: None,
111 semantics: None,
112 click_capture_handler: None,
113 click_handler: None,
114 input_event_handlers: Vec::new(),
115 event_policy: None,
116 phase: None,
117 animations: Vec::new(),
118 animation_targets: Vec::new(),
119 paint_bounds: None,
120 shadow: None,
121 focus_scope: false,
122 defer_children: false,
123 children: Vec::new(),
124 }
125 }
126
127 pub fn child(mut self, child: impl Into<Element>) -> Self {
128 self.children.push(child.into());
129 self
130 }
131
132 pub fn content(mut self, content: impl IntoElementContent) -> Self {
133 content.append_to(&mut self.children);
134 self
135 }
136
137 pub fn children(mut self, children: impl IntoIterator<Item = impl Into<Element>>) -> Self {
138 self.children.extend(children.into_iter().map(Into::into));
139 self
140 }
141
142 pub fn key(mut self, key: impl AsRef<str>) -> Self {
143 self.key.explicit = Some(stable_hash(key.as_ref()));
144 self
145 }
146
147 #[doc(hidden)]
148 pub fn source_key(mut self, key: ElementKey) -> Self {
149 self.key = key;
150 self
151 }
152
153 pub fn interaction(mut self, interaction: InteractionRole) -> Self {
154 self.interaction = Some(interaction);
155 self
156 }
157
158 pub fn semantics(mut self, semantics: Semantics) -> Self {
159 self.semantics = Some(semantics);
160 self
161 }
162
163 pub fn window_drag_region(mut self) -> Self {
167 self.interaction = Some(InteractionRole::WindowDragRegion);
168 self.event_policy = Some(EventPolicy::NONE);
169 self
170 }
171
172 pub fn phase(mut self, phase: RenderPhase) -> Self {
173 self.phase = Some(phase);
174 self
175 }
176
177 pub fn animation(mut self, binding: AnimationBinding) -> Self {
178 self.animations.push(binding);
179 self
180 }
181
182 pub fn animation_target(mut self, property: AnimProperty, active: bool) -> Self {
183 self.animation_targets.push((property, active));
184 self
185 }
186
187 pub fn paint_bounds(mut self, rect: UiRect) -> Self {
188 self.paint_bounds = Some(rect);
189 self
190 }
191
192 pub fn shadow(mut self, style: crate::core::ShadowStyle) -> Self {
194 self.shadow = Some(style);
195 self
196 }
197
198 pub fn focus_scope(mut self) -> Self {
199 self.focus_scope = true;
200 self
201 }
202
203 pub fn defer_children_compile(mut self) -> Self {
204 self.defer_children = true;
205 self
206 }
207
208 fn compile_internal(
209 self,
210 scope: &UiScope,
211 context: &UiRenderContext,
212 component_id: ComponentId,
213 force_components: bool,
214 ) -> UiElement {
215 let _current_context = context.contexts().enter_current(component_id);
216 let (children, deferred_children) = if self.defer_children {
217 (Vec::new(), Some(self.children))
218 } else {
219 (
220 compile_children(
221 scope,
222 context,
223 component_id,
224 force_components,
225 self.children,
226 ),
227 None,
228 )
229 };
230 let mut element = (self.render)(ElementRenderCx {
231 id: scope.node_id(),
232 scope,
233 context,
234 children,
235 component_id,
236 force_components,
237 deferred_children,
238 id_counter: Cell::new(0),
239 });
240 if let Some(interaction) = self.interaction {
241 element = element.interaction(interaction);
242 }
243 if let Some(semantics) = self.semantics {
244 element = element.semantics(semantics);
245 }
246 if let Some(handler) = self.click_capture_handler {
247 element = element.on_click_capture_handler(handler);
248 }
249 if let Some(handler) = self.click_handler {
250 element = element.on_click_handler(handler);
251 }
252 for binding in self.input_event_handlers {
253 element = element.on_event_handler(binding.kind, binding.capture, binding.handler);
254 }
255 if let Some(policy) = self.event_policy {
256 element = element.event_policy(policy);
257 }
258 if let Some(phase) = self.phase {
259 element = element.render_phase(phase);
260 }
261 for animation in self.animations {
262 element = element.animation(animation);
263 }
264 for (property, active) in self.animation_targets {
265 element = element.animation_target(property, active);
266 }
267 if let Some(bounds) = self.paint_bounds {
268 element = element.paint_bounds(bounds);
269 }
270 if self.focus_scope {
271 element = element.focus_scope();
272 }
273 if let Some(shadow) = self.shadow {
274 element = element.shadow(shadow);
275 }
276 element
277 }
278}
279
280impl ElementRenderCx<'_, '_, '_> {
281 pub fn animation_value(&self, property: AnimProperty) -> f32 {
282 self.context.animation_value(&self.id, property)
283 }
284
285 pub fn compile(&self, element: Element) -> UiElement {
286 element.compile_internal(
287 self.scope,
288 self.context,
289 self.component_id,
290 self.force_components,
291 )
292 }
293
294 pub fn compile_deferred_children(&mut self) -> Vec<UiElement> {
295 self.deferred_children
296 .take()
297 .map(|children| {
298 compile_children(
299 self.scope,
300 self.context,
301 self.component_id,
302 self.force_components,
303 children,
304 )
305 })
306 .unwrap_or_default()
307 }
308}
309
310impl DeclarativeView for Element {
311 fn compile(
312 self,
313 scope: &UiScope,
314 context: &UiRenderContext,
315 component_id: ComponentId,
316 force_components: bool,
317 ) -> UiElement {
318 self.compile_internal(scope, context, component_id, force_components)
319 }
320}
321
322impl ElementKey {
323 #[track_caller]
324 pub fn caller() -> Self {
325 let location = Location::caller();
326 Self {
327 file: location.file(),
328 line: location.line(),
329 column: location.column(),
330 explicit: None,
331 }
332 }
333
334 pub(super) fn segment(self, index: usize) -> String {
335 match self.explicit {
336 Some(key) => format!("e.{:016x}.k.{key:016x}", self.hash()),
337 None => format!("e.{:016x}.{index}", self.hash()),
338 }
339 }
340
341 fn hash(self) -> u64 {
342 let mut hash = FNV_OFFSET;
343 hash = hash_bytes(hash, self.file.as_bytes());
344 hash = hash_u32(hash, self.line);
345 hash_u32(hash, self.column)
346 }
347}
348
349impl Element {
350 pub(super) fn with_layout(mut self, layout: LayoutSpec) -> Self {
351 let render = self.render;
352 self.render = Box::new(move |cx| render(cx).layout(layout));
353 self
354 }
355}
356
357fn compile_children(
358 scope: &UiScope,
359 context: &UiRenderContext,
360 component_id: ComponentId,
361 force_components: bool,
362 children: Vec<Element>,
363) -> Vec<UiElement> {
364 children
365 .into_iter()
366 .enumerate()
367 .map(|(index, child)| {
368 let child_scope = UiScope::from_path(scope.path().child(child.key.segment(index)));
369 child.compile_internal(&child_scope, context, component_id, force_components)
370 })
371 .collect()
372}
373
374fn hash_u32(hash: u64, value: u32) -> u64 {
375 hash_bytes(hash, &value.to_le_bytes())
376}
377
378fn hash_bytes(mut hash: u64, bytes: &[u8]) -> u64 {
379 for byte in bytes {
380 hash ^= u64::from(*byte);
381 hash = hash.wrapping_mul(FNV_PRIME);
382 }
383 hash
384}
385
386pub(super) fn stable_hash(value: &str) -> u64 {
387 hash_bytes(FNV_OFFSET, value.as_bytes())
388}
389
390pub(super) fn location_hash(location: &'static Location<'static>) -> u64 {
391 let mut hash = FNV_OFFSET;
392 hash = hash_bytes(hash, location.file().as_bytes());
393 hash = hash_u32(hash, location.line());
394 hash_u32(hash, location.column())
395}
396
397const FNV_OFFSET: u64 = 0xcbf29ce484222325;
398const FNV_PRIME: u64 = 0x100000001b3;